commit b8ab0b6ce9c9d312b57414c281df16cd57d9af99
parent cf36a61d3e94ed60b29356da045a71da000ecd42
Author: Ningxin Hu <ningxin.hu@intel.com>
Date: Wed, 15 Oct 2025 08:22:06 +0000
Bug 1993493 [wpt PR 55147] - WebNN: Align tensor limits implementation with spec, a=testonly
Automatic update from web-platform-tests
WebNN: Align tensor limits implementation with spec
This CL aligns the tensor limits setting in
`WebNNContextImpl::IntersectWithBaseProperties` with spec, especially
for scalar operand limits that was fixed by spec PR [1].
The change includes:
1. argMin/Max doesn't accept scalar input and output data types except
int32 and int64 [2]
2. batchNormalization doesn't accept scalar input [3]
3. concat doesn't accept scalar input [4]
4. conv2d/convTranspose2d only accept floating-point input data types
[5]
5. softmax doesn't accept scalar input [6]
6. split doesn't accept scalar input [7]
Pad [8] and slice [9] support scalar input as a no-op. This CL
replaces pad or slice having scalar input with an identity operator at
MLGraphBuilder to unify the behaviors across backends.
[1]: https://github.com/webmachinelearning/webnn/pull/882
[2]: https://www.w3.org/TR/webnn/#tensor-limits-argMin-argMax
[3]: https://www.w3.org/TR/webnn/#tensor-limits-batchNormalization
[4]: https://www.w3.org/TR/webnn/#tensor-limits-concat
[5]: https://www.w3.org/TR/webnn/#tensor-limits-conv2d
[6]: https://www.w3.org/TR/webnn/#tensor-limits-softmax
[7]: https://www.w3.org/TR/webnn/#tensor-limits-split
[8]: https://www.w3.org/TR/webnn/#tensor-limits-pad
[9]: https://www.w3.org/TR/webnn/#tensor-limits-slice
Change-Id: I8480cf9ef1e9e18a175677a16a553c1562a747c5
Bug: 446481989
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6972256
Commit-Queue: ningxin hu <ningxin.hu@intel.com>
Reviewed-by: Reilly Grant <reillyg@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1527306}
--
wpt-commits: a460ea73b9d67a705401622c6a7f8c0088b6a036
wpt-pr: 55147
Diffstat:
9 files changed, 98 insertions(+), 33 deletions(-)
diff --git a/testing/web-platform/tests/webnn/conformance_tests/pad.https.any.js b/testing/web-platform/tests/webnn/conformance_tests/pad.https.any.js
@@ -29,6 +29,32 @@
const padTests = [
{
+ 'name':
+ 'padding float32 0D constant tensor with empty paddings should be no-op',
+ 'graph': {
+ 'inputs': {
+ 'padInput': {
+ 'data': [22.76361846923828],
+ 'descriptor': {shape: [], dataType: 'float32'},
+ 'constant': true
+ }
+ },
+ 'operators': [{
+ 'name': 'pad',
+ 'arguments': [
+ {'input': 'padInput'}, {'beginningPadding': []}, {'endingPadding': []}
+ ],
+ 'outputs': 'padOutput'
+ }],
+ 'expectedOutputs': {
+ 'padOutput': {
+ 'data': [22.76361846923828],
+ 'descriptor': {shape: [], dataType: 'float32'}
+ }
+ }
+ }
+ },
+ {
'name': 'pad float32 1D constant tensor default options',
'graph': {
'inputs': {
@@ -690,11 +716,7 @@ const padTests = [
'graph': {
'inputs': {
'padInput': {
- 'data': [
- 22, -21, -91,
- 16, 60, -70,
- -60, -47, 68
- ],
+ 'data': [22, -21, -91, 16, 60, -70, -60, -47, 68],
'descriptor': {shape: [3, 3], dataType: 'int64'}
}
},
@@ -764,30 +786,14 @@ const padTests = [
'expectedOutputs': {
'padOutput': {
'data': [
- -Infinity,
- -Infinity,
- -Infinity,
- -Infinity,
- -Infinity,
- -Infinity,
- 22.76361846923828,
- -21.168529510498047,
- -91.66168975830078,
- -Infinity,
- -Infinity,
- 16.863798141479492,
- 60.51472091674805,
- -70.56755065917969,
- -Infinity,
- -Infinity,
- -60.643272399902344,
- -47.8821907043457,
- 68.72557830810547,
- -Infinity,
- -Infinity,
- -Infinity,
- -Infinity,
- -Infinity,
+ -Infinity, -Infinity, -Infinity,
+ -Infinity, -Infinity, -Infinity,
+ 22.76361846923828, -21.168529510498047, -91.66168975830078,
+ -Infinity, -Infinity, 16.863798141479492,
+ 60.51472091674805, -70.56755065917969, -Infinity,
+ -Infinity, -60.643272399902344, -47.8821907043457,
+ 68.72557830810547, -Infinity, -Infinity,
+ -Infinity, -Infinity, -Infinity,
-Infinity
],
'descriptor': {shape: [5, 5], dataType: 'float32'}
diff --git a/testing/web-platform/tests/webnn/conformance_tests/slice.https.any.js b/testing/web-platform/tests/webnn/conformance_tests/slice.https.any.js
@@ -17,6 +17,30 @@
const sliceTests = [
{
+ 'name':
+ 'slicing float32 0D constant tensor with empty starts and sizes should be a no-op',
+ 'graph': {
+ 'inputs': {
+ 'sliceInput': {
+ 'data': [28.846250534057617],
+ 'descriptor': {shape: [], dataType: 'float32'},
+ 'constant': true
+ }
+ },
+ 'operators': [{
+ 'name': 'slice',
+ 'arguments': [{'input': 'sliceInput'}, {'starts': []}, {'sizes': []}],
+ 'outputs': 'sliceOutput'
+ }],
+ 'expectedOutputs': {
+ 'sliceOutput': {
+ 'data': [28.846250534057617],
+ 'descriptor': {shape: [], dataType: 'float32'}
+ }
+ }
+ }
+ },
+ {
'name': 'slice float32 1D constant tensor',
'graph': {
'inputs': {
diff --git a/testing/web-platform/tests/webnn/validation_tests/argMinMax.https.any.js b/testing/web-platform/tests/webnn/validation_tests/argMinMax.https.any.js
@@ -62,6 +62,12 @@ const tests = [
label: label,
},
},
+ {
+ name: '[argMin/Max] Throw if outputDataType=float32',
+ input: {dataType: 'float32', shape: [1, 2, 3, 4]},
+ axis: 1,
+ options: {outputDataType: 'float32', label: label}
+ }
];
function runTests(operatorName, tests) {
diff --git a/testing/web-platform/tests/webnn/validation_tests/batchNormalization.https.any.js b/testing/web-platform/tests/webnn/validation_tests/batchNormalization.https.any.js
@@ -248,6 +248,16 @@ const tests = [
label: label,
},
},
+ {
+ name: '[batchNormalization] Throw if the input is a scalar.',
+ input: {dataType: 'float32', shape: []},
+ mean: {dataType: 'float32', shape: [1]},
+ variance: {dataType: 'float32', shape: [1]},
+ options: {
+ axis: 0,
+ label: label,
+ }
+ }
];
tests.forEach(
diff --git a/testing/web-platform/tests/webnn/validation_tests/cumulativeSum.https.any.js b/testing/web-platform/tests/webnn/validation_tests/cumulativeSum.https.any.js
@@ -15,6 +15,12 @@ const tests = [
output: {dataType: 'float32', shape: [3, 2, 5]}
},
{
+ name: '[cumulativeSum] Test with integer input',
+ input: {dataType: 'int32', shape: [3, 2, 5]},
+ axis: 0,
+ output: {dataType: 'int32', shape: [3, 2, 5]}
+ },
+ {
name: '[cumulativeSum] Test with axis=1',
input: {dataType: 'float32', shape: [3, 2, 5]},
axis: 1,
diff --git a/testing/web-platform/tests/webnn/validation_tests/pad.https.any.js b/testing/web-platform/tests/webnn/validation_tests/pad.https.any.js
@@ -53,11 +53,12 @@ const tests = [
output: {dataType: 'float32', shape: [4, 7]}
},
{
- name: '[pad] Throw if building pad for scalar input.',
+ name:
+ '[pad] Test pad for scalar input with empty beginningPadding and endingPadding.',
input: {dataType: 'float32', shape: []},
beginningPadding: [],
endingPadding: [],
- options: {label}
+ output: {dataType: 'float32', shape: []}
},
{
name:
diff --git a/testing/web-platform/tests/webnn/validation_tests/slice.https.any.js b/testing/web-platform/tests/webnn/validation_tests/slice.https.any.js
@@ -26,7 +26,14 @@ const tests = [
output: {dataType: 'float32', shape: [1, 2, 3]}
},
{
- name: '[slice] Throw if input is a scalar.',
+ name: '[slice] Test slicing a scalar with empty starts and sizes.',
+ input: {dataType: 'float32', shape: []},
+ starts: [],
+ sizes: [],
+ output: {dataType: 'float32', shape: []}
+ },
+ {
+ name: '[slice] Throw if input is a scalar and starts/sizes are not empty.',
input: {dataType: 'float32', shape: []},
starts: [0],
sizes: [1]
diff --git a/testing/web-platform/tests/webnn/validation_tests/softmax.https.any.js b/testing/web-platform/tests/webnn/validation_tests/softmax.https.any.js
@@ -80,6 +80,11 @@ const tests = [
name: '[softmax] Throw if the axis is greater than input rank - 1.',
input: {dataType: 'float16', shape: [3, 1, 5, 2]},
axis: 4
+ },
+ {
+ name: '[softmax] Throw if the input is a scalar.',
+ input: {dataType: 'float32', shape: []},
+ axis: 0
}
];
diff --git a/testing/web-platform/tests/webnn/validation_tests/split.https.any.js b/testing/web-platform/tests/webnn/validation_tests/split.https.any.js
@@ -41,7 +41,7 @@ const tests = [
{
name: '[split] Throw if splitting a scalar.',
input: {dataType: 'float32', shape: []},
- splits: [2],
+ splits: [1],
options: {label}
},
{