diff --git a/js/web/docs/webnn-operators.md b/js/web/docs/webnn-operators.md index 5ad2311ef8..a6a2ecdf6f 100644 --- a/js/web/docs/webnn-operators.md +++ b/js/web/docs/webnn-operators.md @@ -6,108 +6,110 @@ operators and the supported opset domain/versions in **WebNN EP** by ONNX Runtim (**Note**: ONNX Runtime only *guarantees* support for models stamped with opset version 7 or above for opset domain 'ai.onnx'.) -[WebNN API](https://webmachinelearning.github.io/webnn) provides two device types `cpu` and `gpu` to leverage different on-device accelerators. WebNN API implementation in Chromium uses TFLite XNNPack delegate backend for `cpu` device type and DirectML backend for `gpu` device type. [The op support status](https://webmachinelearning.github.io/webnn-status/) behind these two backends is inconsistent. +The [WebNN API](https://webmachinelearning.github.io/webnn) is available in the latest versions of Chrome and Edge on Windows, +Linux, macOS, Android, and ChromeOS behind an "Enables WebNN API" flag. The operator support status may vary across these +platforms. Check the [WebNN status](https://webmachinelearning.github.io/webnn-status/) for the latest implementation details. -| Operator | Opset | WebNN API | WebNN CPU | WebNN GPU | Comments | -|:------:|:------:|:------:|:-:|:-:|:------| -| Abs | ai.onnx(7-12, 13+) | abs | ✓ | ✓ | | -| Add | ai.onnx(7-12, 13, 14+) | add | ✓ | ✓ | | -| And | ai.onnx(7+) | logicalAnd | ✗ | ✓ | | -| ArgMax | ai.onnx(7-10, 11, 12, 13+) | argMax | ✓ | ✓ | | -| ArgMin | ai.onnx(7-10, 11, 12, 13+) | argMin | ✓ | ✓ | | -| AveragePool | ai.onnx(7-9, 10, 11, 12-18, 19+) | averagePool2d | ✓ | ✓ | Only supports 4-D input, 2-D 'kernel_shape', 'count_include_pad' value is 0 | -| BatchNormalization | ai.onnx(7-8, 9-13, 14, 15+) | batchNormalization | ✓ | ✓ | Only supports 'training_mode' value is 0, one output | -| Cast | ai.onnx(7-8, 9-12, 13-18, 19-20, 21+) | cast | ✓ | ✓ | WebNN CPU backend doesn't support casting to uint64 data type | -| Ceil | ai.onnx(7-12, 13+) | ceil | ✓ | ✓ | | -| Clip | ai.onnx(7-10, 11, 12, 13+) | clamp | ✓ | ✓ | WebNN CPU backend only supports 3 specific ranges: [0.0, infinity], [-1.0, 1.0], [0.0, 6.0] (Chromium issue: https://issues.chromium.org/issues/326156496) | -| Concat | ai.onnx(7-10, 11-12, 13+) | concat | ✓ | ✓ | | -| Conv | ai.onnx(7-10, 11+) | conv2d | ✓ | ✓ | Only supports 3-D or 4-D input and 'W' (weight) | -| ConvTranspose | ai.onnx(7-10, 11+) | convTranspose2d | ✓ | ✓ | Only supports 3-D or 4-D input and 'W' (weight). WebNN CPU backend only supports default dilations and group | -| Cos | ai.onnx(7+) | cos | ✓ | ✓ | | -| CumSum | ai.onnx(11-13, 14+) | cumulativeSum | ✓ | ✓ | 'axis' input should be a constant | -| Div | ai.onnx(7-12, 13, 14+) | div | ✓ | ✓ | | -| DequantizeLinear | ai.onnx(10-12, 13-18, 19-20, 21-22, 23+) | dequantizeLinear | ✓ | ✓ | The shape of x_scale should be a subsample of the shape of input | -| Dropout | ai.onnx(7-9, 10-11, 12, 13-21, 22+) | identity | ✓ | ✓ | Only supports test mode | -| Einsum | ai.onnx(12+) | reshape, transpose, matmul, reduceSum, mul, triangular | ✓ | ✓ | | -| Elu | ai.onnx(7+) | elu | ✓ | ✓ | WebNN CPU backend only supports 'alpha' value is 1.0 | -| Equal | ai.onnx(7-10, 11-12, 13-18, 19+) | equal | ✓ | ✓ | | -| Erf | ai.onnx(7-9, 10-12, 13+) | erf | ✓ | ✓ | | -| Exp | ai.onnx(7-12, 13+) | exp | ✓ | ✓ | | -| Expand | ai.onnx(8-12, 13+) | expand | ✓ | ✓ | 'shape' input should be a constant | -| Flatten | ai.onnx(7-8, 9-10, 11-12, 13-20, 21+) | reshape | ✓ | ✓ | | -| Floor | ai.onnx(7-12, 13+) | floor | ✓ | ✓ | | -| Gather | ai.onnx(7-10, 11-12, 13+) | gather | ✓ | ✓ | | -| GatherElements | ai.onnx(11-12, 13+) | gatherElements | ✗ | ✓ | | -| GatherND | ai.onnx(11, 12, 13+) | gatherND | ✓ | ✓ | Only supports 'batch_dims' == 0 | -| Gelu | ai.onnx(20+) | gelu | ✓ | ✓ | | -| Gemm | ai.onnx(7-8, 9-10, 11-12, 13+) | gemm | ✓ | ✓ | Only supports 1-D 'C' input | -| GlobalAveragePool | ai.onnx(7+) | averagePool2d | ✓ | ✓ | Only supports 4-D input | -| GlobalMaxPool | ai.onnx(7+) | maxPool2d | ✓ | ✓ | Only supports 4-D input | -| GlobalLpPool| ai.onnx(7+) | l2Pool2d | ✗ | ✓ | Only supports 4-D input, 'p' value is 2 | -| Greater | ai.onnx(7-8, 9-12, 13+) | greater | ✓ | ✓ | | -| GreaterOrEqual | ai.onnx(12-15, 16+) | greaterOrEqual | ✓ | ✓ | | -| GRU | ai.onnx(7-13, 14-21, 22+) | gru | ✓ | ✓ | Only supports 'layout' == 0. 'clip' is not supported. The activation functions in 'activations' must be one of 'Relu', 'Tanh', 'Sigmoid'. Forward and backward activations must be the same if bidirectional. 'sequence_lens' if present should be constant with values equal to the first dimension length of input 'X' | -| HardSigmoid | ai.onnx(7+) | hardSigmoid | ✓ | ✓ | | -| HardSwish | ai.onnx(14+) | hardSwish | ✓ | ✓ | | -| Identity | ai.onnx(7-13, 14-15, 16-18, 19-20, 21+) | identity | ✓ | ✓ | | -| InstanceNormalization | ai.onnx(7+) | instanceNormalization | ✓ | ✓ | | -| LayerNormalization | ai.onnx(7-16, 17+) | layerNormalization | ✓ | ✓ | | -| LeakyRelu | ai.onnx(7-15, 16+) | leakyRelu | ✓ | ✓ | | -| Less | ai.onnx(7-8, 9-12, 13+) | lesser | ✓ | ✓ | | -| LessOrEqual | ai.onnx(12-15, 16+) | lesserOrEqual | ✓ | ✓ | | -| Log | ai.onnx(7-12, 13+) | log | ✓ | ✓ | | -| LpPool | ai.onnx(7-10, 11-17, 18+) | l2Pool2d | ✗ | ✓ | Only supports 4-D input, 2-D 'kernel_shape', 'p' value is 2 | -| LRN | ai.onnx(7-12, 13+) | pad, averagePool2d, transpose, add, mul, pow, div | ✓ | ✓ | | -| LSTM | ai.onnx(7-13, 14-21, 22+) | lstm | ✓ | ✓ | Only supports 'layout' == 0, 'input_forget' == 0. 'clip' is not supported. The activation functions in 'activations' must be one of 'Relu', 'Tanh', 'Sigmoid'. Forward and backward activations must be the same if bidirectional. 'sequence_lens' if present should be constant with values equal to the first dimension length of input 'X' | -| MatMul | ai.onnx(7-8, 9-12, 13+) | matmul | ✓ | ✓ | | -| Max | ai.onnx(7, 8-11, 12, 13+) | max | ✓ | ✓ | | -| MaxPool | ai.onnx(7, 8-9, 10, 11, 12+) | maxPool2d | ✓ | ✓ | Only supports 4-D input, 2-D 'kernel_shape', 'storage_order' != 1, one output | -| Min | ai.onnx(7, 8-11, 12, 13+) | min | ✓ | ✓ | | -| Mul | ai.onnx(7-12, 13, 14+) | mul | ✓ | ✓ | | -| Neg | ai.onnx(7-12, 13+) | neg | ✓ | ✓ | | -| Not | ai.onnx(7+) | logicalNot | ✓ | ✓ | | -| Or | ai.onnx(7+) | logicalOr | ✗ | ✓ | | -| Pad | ai.onnx(7-10, 11-12, 13-17, 18, 19-20, 21+) | pad | ✓ | ✓ | modes == 'wrap' is not supported | -| Pow | ai.onnx(7-11, 12, 13-14, 15+) | pow | ✓ | ✓ | | -| PRelu | ai.onnx(7-8, 9-15, 16+) | prelu | ✓ | ✓ | WebNN CPU backend restricts the last dimension of input and slope to be same (Chromium issue: https://issues.chromium.org/issues/335517470) | -| QuantizeLinear | ai.onnx(10-12, 13-18, 19-20, 21-22, 23+) | quantizeLinear | ✓ | ✓ | The shape of x_scale should be a subsample of the shape of input | -| Reciprocal | ai.onnx(7-12, 13+) | reciprocal | ✓ | ✓ | | -| ReduceL1 | ai.onnx(7-10, 11-12, 13-17, 18+) | reduceL1 | ✓ | ✓ | Input 'axes' if present should be a constant | -| ReduceL2 | ai.onnx(7-10, 11-12, 13-17, 18+) | reduceL2 | ✓ | ✓ | Input 'axes' if present should be a constant | -| ReduceLogSum| ai.onnx(7-10, 11-12, 13-17, 18+) | reduceLogSum| ✓ | ✓ | Input 'axes' if present should be a constant | -| ReduceLogSumExp | ai.onnx(7-10, 11-12, 13-17, 18+) | reduceLogSumExp | ✓ | ✓ | Input 'axes' if present should be a constant | -| ReduceMax | ai.onnx(7-10, 11, 12, 13-17, 18-19, 20+) | reduceMax | ✓ | ✓ | Input 'axes' if present should be a constant | -| ReduceMean | ai.onnx(7-10, 11-12, 13-17, 18+) | reduceMean | ✓ | ✓ | Input 'axes' if present should be a constant | -| ReduceMin | ai.onnx(7-10, 11, 12, 13-17, 18-19, 20+) | reduceMin | ✓ | ✓ | Input 'axes' if present should be a constant | -| ReduceProd | ai.onnx(7-10, 11-12, 13-17, 18+) | reduceProduct | ✓ | ✓ | Input 'axes' if present should be a constant | -| ReduceSum | ai.onnx(7-10, 11-12, 13+) | reduceSum | ✓ | ✓ | Input 'axes' if present should be a constant | -| ReduceSumSquare | ai.onnx(7-10, 11-12, 13-17, 18+) | reduceSumSquare | ✓ | ✓ | Input 'axes' if present should be a constant | -| Relu | ai.onnx(7-12, 13, 14+) | relu | ✓ | ✓ | | -| Reshape | ai.onnx(7-12, 13, 14-18, 19-20, 21+) | reshape | ✓ | ✓ | Input 'shape' should be a constant, 0 dimension value in 'shape' is not supported | -| Resize | ai.onnx(11-12, 13-17, 18, 19+) | resample2d | ✓ | ✓ | Only supports 4-D input, antialias == 0, exclude_outside == 0, keep_aspect_ratio_policy == 'stretch', 'linear' and 'nearest' modes, input 'scales' and 'sizes' if present must be a constant | -| RotaryEmbedding | com.microsoft(1+) | add, concat, gather, mul, reshape, split | ✓ | ✓ | | -| ScatterElements | ai.onnx(11-12, 13-15, 16-17, 18+) | scatterElements | ✗ | ✓ | Only supports 'reduction' == 'none' | -| ScatterND | ai.onnx(11-12, 13-15, 16-17, 18+) | scatterND | ✗ | ✓ | Only supports 'reduction' == 'none' | -| Shape | ai.onnx(7-12, 13-14, 15-18, 19-20, 21+) | slice | ✓ | ✓ | | -| SimplifiedLayerNormalization | ai.onnx(1+) | pow, reduceMean, add, sqrt, div, mul | ✓ | ✓ | | -| Sigmoid | ai.onnx(7-12, 13+) | sigmoid | ✓ | ✓ | | -| Sign | ai.onnx(9-12, 13+) | sign | ✓ | ✓ | | -| SkipSimplifiedLayerNormalization | com.microsoft(1+) | pow, reduceMean, add, sqrt, div, mul | ✓ | ✓ | | -| Softplus | ai.onnx(7+) | softplus | ✓ | ✓ | | -| Softsign | ai.onnx(7+) | softsign | ✓ | ✓ | | -| Sin | ai.onnx(7+) | sin | ✓ | ✓ | | -| Slice | ai.onnx(7-9, 10, 11-12, 13+) | slice, reverse | ✓ | ✓ | Input 'starts', 'ends', 'axes', and 'steps' if present must be a constant | -| Softmax | ai.onnx(7-10, 11-12, 13+) | softmax | ✓ | ✓ | | -| Split | ai.onnx(7-10, 11-12, 13-17, 18+) | split | ✓ | ✓ | Input 'split' if present should be a constant | -| Sqrt | ai.onnx(7-12, 13+) | sqrt | ✓ | ✓ | | -| Squeeze | ai.onnx(7-10, 11-12, 13-20, 21+) | reshape | ✓ | ✓ | Input 'axes' if present should be a constant | -| Sub | ai.onnx(7-12, 13, 14+) | sub | ✓ | ✓ | | -| Tan | ai.onnx(7+) | tan | ✓ | ✓ | | -| Tanh | ai.onnx(7-12, 13+) | tanh | ✓ | ✓ | | -| Tile | ai.onnx(7-12, 13+) | tile | ✗ | ✓ | Input 'repeats' should be a constant | -| Transpose | ai.onnx(7-12, 13-20, 21+) | transpose | ✓ | ✓ | | -| Trilu | ai.onnx(14+) | triangular | ✓ | ✓ | Input 'k' (option 'diagonal' for WebNN) if present should be a constant | -| Unsqueeze | ai.onnx(7-10, 11-12, 13-20, 21+) | reshape | ✓ | ✓ | | -| Where | ai.onnx(7-8, 9-15, 16+) | where | ✓ | ✓ | | -| Xor | ai.onnx(7+) | logicalXor | ✗ | ✓ | | +| Operator | Opset | WebNN API | Comments | +|:------:|:------:|:------:|:------| +| Abs | ai.onnx(7-12, 13+) | abs | | +| Add | ai.onnx(7-12, 13, 14+) | add | | +| And | ai.onnx(7+) | logicalAnd | | +| ArgMax | ai.onnx(7-10, 11, 12, 13+) | argMax | | +| ArgMin | ai.onnx(7-10, 11, 12, 13+) | argMin | | +| AveragePool | ai.onnx(7-9, 10, 11, 12-18, 19+) | averagePool2d | Only supports 4-D input, 2-D 'kernel_shape', 'count_include_pad' value is 0 | +| BatchNormalization | ai.onnx(7-8, 9-13, 14, 15+) | batchNormalization | Only supports 'training_mode' value is 0, one output | +| Cast | ai.onnx(7-8, 9-12, 13-18, 19-20, 21+) | cast | | +| Ceil | ai.onnx(7-12, 13+) | ceil | | +| Clip | ai.onnx(7-10, 11, 12, 13+) | clamp | | +| Concat | ai.onnx(7-10, 11-12, 13+) | concat | | +| Conv | ai.onnx(7-10, 11+) | conv2d | Only supports 3-D or 4-D input and 'W' (weight) | +| ConvTranspose | ai.onnx(7-10, 11+) | convTranspose2d | Only supports 3-D or 4-D input and 'W' (weight) | +| Cos | ai.onnx(7+) | cos | | +| CumSum | ai.onnx(11-13, 14+) | cumulativeSum | 'axis' input should be a constant | +| Div | ai.onnx(7-12, 13, 14+) | div | | +| DequantizeLinear | ai.onnx(10-12, 13-18, 19-20, 21-22, 23+) | dequantizeLinear | The shape of x_scale should be a subsample of the shape of input | +| Dropout | ai.onnx(7-9, 10-11, 12, 13-21, 22+) | identity | Only supports test mode | +| Einsum | ai.onnx(12+) | reshape, transpose, matmul, reduceSum, mul, triangular | | +| Elu | ai.onnx(7+) | elu | | +| Equal | ai.onnx(7-10, 11-12, 13-18, 19+) | equal | | +| Erf | ai.onnx(7-9, 10-12, 13+) | erf | | +| Exp | ai.onnx(7-12, 13+) | exp | | +| Expand | ai.onnx(8-12, 13+) | expand | 'shape' input should be a constant | +| Flatten | ai.onnx(7-8, 9-10, 11-12, 13-20, 21+) | reshape | | +| Floor | ai.onnx(7-12, 13+) | floor | | +| Gather | ai.onnx(7-10, 11-12, 13+) | gather | | +| GatherElements | ai.onnx(11-12, 13+) | gatherElements | | +| GatherND | ai.onnx(11, 12, 13+) | gatherND | Only supports 'batch_dims' == 0 | +| Gelu | ai.onnx(20+) | gelu | | +| Gemm | ai.onnx(7-8, 9-10, 11-12, 13+) | gemm | Only supports 1-D 'C' input | +| GlobalAveragePool | ai.onnx(7+) | averagePool2d | Only supports 4-D input | +| GlobalMaxPool | ai.onnx(7+) | maxPool2d | Only supports 4-D input | +| GlobalLpPool| ai.onnx(7+) | l2Pool2d | Only supports 4-D input, 'p' value is 2 | +| Greater | ai.onnx(7-8, 9-12, 13+) | greater | | +| GreaterOrEqual | ai.onnx(12-15, 16+) | greaterOrEqual | | +| GRU | ai.onnx(7-13, 14-21, 22+) | gru | Only supports 'layout' == 0. 'clip' is not supported. The activation functions in 'activations' must be one of 'Relu', 'Tanh', 'Sigmoid'. Forward and backward activations must be the same if bidirectional. 'sequence_lens' if present should be constant with values equal to the first dimension length of input 'X' | +| HardSigmoid | ai.onnx(7+) | hardSigmoid | | +| HardSwish | ai.onnx(14+) | hardSwish | | +| Identity | ai.onnx(7-13, 14-15, 16-18, 19-20, 21+) | identity | | +| InstanceNormalization | ai.onnx(7+) | instanceNormalization | | +| LayerNormalization | ai.onnx(7-16, 17+) | layerNormalization | | +| LeakyRelu | ai.onnx(7-15, 16+) | leakyRelu | | +| Less | ai.onnx(7-8, 9-12, 13+) | lesser | | +| LessOrEqual | ai.onnx(12-15, 16+) | lesserOrEqual | | +| Log | ai.onnx(7-12, 13+) | log | | +| LpPool | ai.onnx(7-10, 11-17, 18+) | l2Pool2d | Only supports 4-D input, 2-D 'kernel_shape', 'p' value is 2 | +| LRN | ai.onnx(7-12, 13+) | pad, averagePool2d, transpose, add, mul, pow, div | | +| LSTM | ai.onnx(7-13, 14-21, 22+) | lstm | Only supports 'layout' == 0, 'input_forget' == 0. 'clip' is not supported. The activation functions in 'activations' must be one of 'Relu', 'Tanh', 'Sigmoid'. Forward and backward activations must be the same if bidirectional. 'sequence_lens' if present should be constant with values equal to the first dimension length of input 'X' | +| MatMul | ai.onnx(7-8, 9-12, 13+) | matmul | | +| Max | ai.onnx(7, 8-11, 12, 13+) | max | | +| MaxPool | ai.onnx(7, 8-9, 10, 11, 12+) | maxPool2d | Only supports 4-D input, 2-D 'kernel_shape', 'storage_order' != 1, one output | +| Min | ai.onnx(7, 8-11, 12, 13+) | min | | +| Mul | ai.onnx(7-12, 13, 14+) | mul | | +| Neg | ai.onnx(7-12, 13+) | neg | | +| Not | ai.onnx(7+) | logicalNot | | +| Or | ai.onnx(7+) | logicalOr | | +| Pad | ai.onnx(7-10, 11-12, 13-17, 18, 19-20, 21+) | pad | modes == 'wrap' is not supported | +| Pow | ai.onnx(7-11, 12, 13-14, 15+) | pow | | +| PRelu | ai.onnx(7-8, 9-15, 16+) | prelu | | +| QuantizeLinear | ai.onnx(10-12, 13-18, 19-20, 21-22, 23+) | quantizeLinear | The shape of x_scale should be a subsample of the shape of input | +| Reciprocal | ai.onnx(7-12, 13+) | reciprocal | | +| ReduceL1 | ai.onnx(7-10, 11-12, 13-17, 18+) | reduceL1 | Input 'axes' if present should be a constant | +| ReduceL2 | ai.onnx(7-10, 11-12, 13-17, 18+) | reduceL2 | Input 'axes' if present should be a constant | +| ReduceLogSum| ai.onnx(7-10, 11-12, 13-17, 18+) | reduceLogSum | Input 'axes' if present should be a constant | +| ReduceLogSumExp | ai.onnx(7-10, 11-12, 13-17, 18+) | reduceLogSumExp | Input 'axes' if present should be a constant | +| ReduceMax | ai.onnx(7-10, 11, 12, 13-17, 18-19, 20+) | reduceMax | Input 'axes' if present should be a constant | +| ReduceMean | ai.onnx(7-10, 11-12, 13-17, 18+) | reduceMean | Input 'axes' if present should be a constant | +| ReduceMin | ai.onnx(7-10, 11, 12, 13-17, 18-19, 20+) | reduceMin | Input 'axes' if present should be a constant | +| ReduceProd | ai.onnx(7-10, 11-12, 13-17, 18+) | reduceProduct | Input 'axes' if present should be a constant | +| ReduceSum | ai.onnx(7-10, 11-12, 13+) | reduceSum | Input 'axes' if present should be a constant | +| ReduceSumSquare | ai.onnx(7-10, 11-12, 13-17, 18+) | reduceSumSquare | Input 'axes' if present should be a constant | +| Relu | ai.onnx(7-12, 13, 14+) | relu | | +| Reshape | ai.onnx(7-12, 13, 14-18, 19-20, 21+) | reshape | Input 'shape' should be a constant, 0 dimension value in 'shape' is not supported | +| Resize | ai.onnx(11-12, 13-17, 18, 19+) | resample2d | Only supports 4-D input, antialias == 0, exclude_outside == 0, keep_aspect_ratio_policy == 'stretch', 'linear' and 'nearest' modes, input 'scales' and 'sizes' if present must be a constant | +| RotaryEmbedding | com.microsoft(1+) | add, concat, gather, mul, reshape, split | | +| ScatterElements | ai.onnx(11-12, 13-15, 16-17, 18+) | scatterElements | Only supports 'reduction' == 'none' | +| ScatterND | ai.onnx(11-12, 13-15, 16-17, 18+) | scatterND | Only supports 'reduction' == 'none' | +| Shape | ai.onnx(7-12, 13-14, 15-18, 19-20, 21+) | slice | | +| SimplifiedLayerNormalization | ai.onnx(1+) | pow, reduceMean, add, sqrt, div, mul | | +| Sigmoid | ai.onnx(7-12, 13+) | sigmoid | | +| Sign | ai.onnx(9-12, 13+) | sign | | +| SkipSimplifiedLayerNormalization | com.microsoft(1+) | pow, reduceMean, add, sqrt, div, mul | | +| Softplus | ai.onnx(7+) | softplus | | +| Softsign | ai.onnx(7+) | softsign | | +| Sin | ai.onnx(7+) | sin | | +| Slice | ai.onnx(7-9, 10, 11-12, 13+) | slice, reverse | Input 'starts', 'ends', 'axes', and 'steps' if present must be a constant | +| Softmax | ai.onnx(7-10, 11-12, 13+) | softmax | | +| Split | ai.onnx(7-10, 11-12, 13-17, 18+) | split | Input 'split' if present should be a constant | +| Sqrt | ai.onnx(7-12, 13+) | sqrt | | +| Squeeze | ai.onnx(7-10, 11-12, 13-20, 21+) | reshape | Input 'axes' if present should be a constant | +| Sub | ai.onnx(7-12, 13, 14+) | sub | | +| Tan | ai.onnx(7+) | tan | | +| Tanh | ai.onnx(7-12, 13+) | tanh | | +| Tile | ai.onnx(7-12, 13+) | tile | Input 'repeats' should be a constant | +| Transpose | ai.onnx(7-12, 13-20, 21+) | transpose | | +| Trilu | ai.onnx(14+) | triangular | Input 'k' (option 'diagonal' for WebNN) if present should be a constant | +| Unsqueeze | ai.onnx(7-10, 11-12, 13-20, 21+) | reshape | | +| Where | ai.onnx(7-8, 9-15, 16+) | where | | +| Xor | ai.onnx(7+) | logicalXor | | diff --git a/onnxruntime/core/providers/webnn/builders/impl/activation_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/activation_op_builder.cc index 781ddcb896..585fddfd1f 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/activation_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/activation_op_builder.cc @@ -17,10 +17,6 @@ class ActivationOpBuilder : public BaseOpBuilder { private: Status AddToModelBuilderImpl(ModelBuilder& model_builder, const Node& node, const logging::Logger& logger) const override ORT_MUST_USE_RESULT; - - // Operator support related. - bool IsOpSupportedImpl(const InitializedTensorSet& initializers, const Node& node, - WebnnDeviceType device_type, const logging::Logger& logger) const override; }; // Add operator related. @@ -68,30 +64,6 @@ Status ActivationOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, return Status::OK(); } -// Operator support related. -bool ActivationOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& /* initializers */, - const Node& node, - WebnnDeviceType device_type, - const logging::Logger& logger) const { - const auto& input_defs = node.InputDefs(); - const auto& op_type = node.OpType(); - - std::vector input_shape; - if (!GetShape(*input_defs[0], input_shape, logger)) - return false; - - if (op_type == "Elu" && device_type == WebnnDeviceType::CPU) { - NodeAttrHelper helper(node); - float alpha = helper.Get("alpha", 1.0f); - if (alpha != 1.0f) { - LOGS(logger, VERBOSE) << "WebNN CPU backend only supports Elu's alpha == 1.0"; - return false; - } - } - - return true; -} - void CreateActivationOpBuilder(const std::string& op_type, OpBuilderRegistrations& op_registrations) { if (op_registrations.op_builder_map.count(op_type) > 0) return; diff --git a/onnxruntime/core/providers/webnn/builders/impl/binary_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/binary_op_builder.cc index e14507e8f5..c5493f97fd 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/binary_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/binary_op_builder.cc @@ -20,8 +20,6 @@ class BinaryOpBuilder : public BaseOpBuilder { const logging::Logger& logger) const override ORT_MUST_USE_RESULT; // Operator support related. - bool IsOpSupportedImpl(const InitializedTensorSet& initializers, const Node& node, - const WebnnDeviceType device_type, const logging::Logger& logger) const override; bool HasSupportedInputsImpl(const InitializedTensorSet& /* initializers */, const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const override; }; @@ -59,33 +57,6 @@ Status BinaryOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, const return Status::OK(); } -bool BinaryOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initializers, - const Node& node, - const WebnnDeviceType device_type, - const logging::Logger& logger) const { - const auto& input_defs = node.InputDefs(); - const auto& op_type = node.OpType(); - - std::vector input0_shape; - std::vector input1_shape; - if (!GetShape(*input_defs[0], input0_shape, logger) || - !GetShape(*input_defs[1], input1_shape, logger)) { - return false; - } - - // 'prelu' op in WebNN CPU backend restricts the last dimension of input and slope to be same. - // TODO: Remove this workaround once the associated issue is resolved in Chromium: - // https://issues.chromium.org/issues/335517470. - if (op_type == "PRelu" && device_type == WebnnDeviceType::CPU) { - if (input0_shape.back() != input1_shape.back()) { - LOGS(logger, VERBOSE) << "The last dimension of input and slope for PRelu must be same for WebNN CPU backend."; - return false; - } - } - - return true; -} - bool BinaryOpBuilder::HasSupportedInputsImpl(const InitializedTensorSet& /* initializers */, const Node& node, const emscripten::val& wnn_limits, const logging::Logger& logger) const { const auto& input_defs = node.InputDefs(); diff --git a/onnxruntime/core/providers/webnn/builders/impl/clip_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/clip_op_builder.cc index 374143c886..a244efdd9b 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/clip_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/clip_op_builder.cc @@ -69,27 +69,7 @@ bool ClipOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initializers, // can ensure initializers are constant. See #19401 for details of how this update was made to the NNAPI EP. // GetClipMinMax(graph_viewer, node, minValue, maxValue, logger) float min, max; - if (GetClipMinMax(initializers, node, min, max, logger)) { - // WebNN CPU backend only supports 3 specific ranges: [0.0, infinity], [-1.0, 1.0], [0.0, 6.0]. - // TODO: Remove this workaround once the associated issue is resolved in Chromium: - // https://issues.chromium.org/issues/326156496. - if (device_type == WebnnDeviceType::CPU) { - if ((min == 0.0f && max == std::numeric_limits::infinity()) || - (min == -1.0f && max == 1.0f) || - (min == 0.0f && max == 6.0f)) { - return true; - } else { - LOGS(logger, VERBOSE) << "Clip min and max values (" - << min << ", " - << max << ") are not supported for WebNN CPU backend"; - return false; - } - } - - return true; - } else { - return false; - }; + return GetClipMinMax(initializers, node, min, max, logger); } void CreateClipOpBuilder(const std::string& op_type, OpBuilderRegistrations& op_registrations) { diff --git a/onnxruntime/core/providers/webnn/builders/impl/conv_op_builder.cc b/onnxruntime/core/providers/webnn/builders/impl/conv_op_builder.cc index 548e718b87..e623590e3b 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/conv_op_builder.cc +++ b/onnxruntime/core/providers/webnn/builders/impl/conv_op_builder.cc @@ -378,22 +378,6 @@ bool ConvOpBuilder::IsOpSupportedImpl(const InitializedTensorSet& initializers, return false; } - // WebNN CPU backend (TFLite) only supports default dilations and group. - // https://source.chromium.org/chromium/chromium/src/+/main:services/webnn/tflite/graph_builder_tflite.cc;l=1040 - if (device_type == WebnnDeviceType::CPU && op_type == "ConvTranspose") { - NodeAttrHelper helper(node); - const auto dilations = helper.Get("dilations", std::vector{1, 1}); - const auto group = helper.Get("group", 1); - if (dilations[0] != 1 || (dilations.size() > 1 && dilations[1] != 1)) { - LOGS(logger, VERBOSE) << op_type << " for WebNN CPU backend only supports default dilation 1."; - return false; - } - if (group != 1) { - LOGS(logger, VERBOSE) << op_type << " for WebNN CPU backend only supports default group 1."; - return false; - } - } - return true; }