Xenova HF Staff commited on
Commit
239770a
·
verified ·
1 Parent(s): a7a5557

sync 2e7068faf55e

Browse files
README.md CHANGED
@@ -1,3 +1,85 @@
1
  ---
 
2
  license: apache-2.0
 
 
 
 
3
  ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ library_name: kernels
3
  license: apache-2.0
4
+ tags:
5
+ - kernel
6
+ - webgpu
7
+ - wgsl
8
  ---
9
+ # ai.onnx.OneHot
10
+
11
+ `ai.onnx` · standard ONNX operator · ONNX opset ≥ 11
12
+
13
+ ## Description
14
+
15
+ Produces a one-hot tensor from an `indices` input: positions matching each index are filled with `on_value` and all other positions with `off_value`, where both are taken from the two-element `values` tensor `[off_value, on_value]`. The output rank is one greater than `indices`, with the new dimension of size `depth` inserted at the position given by `axis`; indices outside `[-depth, depth-1]` yield all-`off_value` rows.
16
+
17
+ See the [ONNX `OneHot` spec](https://onnx.ai/onnx/operators/onnx__OneHot.html) for the reference semantics.
18
+
19
+ ## Inputs
20
+
21
+ | Name | Bind key | Logical dtype | Rank | Shape | Description | Presence |
22
+ | --- | --- | --- | --- | --- | --- | --- |
23
+ | `indices` | `indices` | `I` | — | — | Integer or float index tensor; values outside `[-depth, depth-1]` produce all-`off_value` output rows. | required |
24
+ | `depth` | `depth` | `D` | — | — | Scalar (or length-1 rank-1) tensor specifying the number of classes and the size of the one-hot dimension. | required |
25
+ | `values` | `values` | `T` | `1` | — | Rank-1 tensor of exactly two elements `[off_value, on_value]` giving the values written to inactive and active positions respectively. | required |
26
+
27
+ ## Outputs
28
+
29
+ | Name | Bind key | Logical dtype | Rank | Shape | Description | Presence |
30
+ | --- | --- | --- | --- | --- | --- | --- |
31
+ | `output` | `output` | `T` | derived | — | One-hot tensor with rank equal to `rank(indices) + 1`, same element type as `values`. | required |
32
+
33
+ ## Attributes
34
+
35
+ Default values (overridable per request):
36
+
37
+ | Attribute | Default | Description |
38
+ | --- | --- | --- |
39
+ | `axis` | `-1` | Axis along which the one-hot dimension is inserted; default `-1` appends it as the last dimension. Negative values count from the back; accepted range is `[-r-1, r]` where `r = rank(indices)`. |
40
+
41
+ ## Type constraints
42
+
43
+ | Variable | Allowed dtypes |
44
+ | --- | --- |
45
+ | `I` | `float32`, `float16`, `int32`, `int16`, `int8`, `uint32`, `uint8` |
46
+ | `D` | `float32`, `float16`, `int32`, `int16`, `int8`, `uint32`, `uint8` |
47
+ | `T` | `float32`, `float16`, `int32`, `int16`, `int8`, `uint32`, `uint8`, `bool` |
48
+
49
+ ## Files
50
+
51
+ - [`metadata.json`](build/webgpu/metadata.json) — kernel metadata (id, digests, provenance)
52
+ - [`manifest.json`](build/webgpu/manifest.json) — the op contract (source of truth)
53
+ - [`test.json`](build/webgpu/test.json) — correctness cases
54
+ - [`bench.json`](build/webgpu/bench.json) — benchmark + tuning cases
55
+ - [`one-hot-fill.wgsl.jinja`](build/webgpu/one-hot-fill.wgsl.jinja)
56
+ - [`one-hot-last-axis-vec4.wgsl.jinja`](build/webgpu/one-hot-last-axis-vec4.wgsl.jinja)
57
+ - [`one-hot-scatter.wgsl.jinja`](build/webgpu/one-hot-scatter.wgsl.jinja)
58
+
59
+ ## Use with `@huggingface/kernels`
60
+
61
+ The loader automatically allocates outputs whose metadata it can derive from the manifest contract and this call.
62
+
63
+ The explicit `outputs` entries provide shape and logical dtype metadata for the results listed below:
64
+
65
+ - `output`
66
+
67
+ Each entry either requests an optional result or supplies metadata that cannot be inferred from the inputs.
68
+
69
+ The `version: 1` option selects the published kernel contract; it is independent of any operator opset, contrib `since_version`, or model version.
70
+
71
+ Replace each `*Data` placeholder with a typed array containing the corresponding input data.
72
+
73
+ ```js
74
+ import { getKernel } from "@huggingface/kernels";
75
+
76
+ const kernel = await getKernel("webgpu-kernels/ai.onnx.OneHot", { version: 1 });
77
+ // Explicit destinations request optional results or supply metadata that cannot be inferred.
78
+ const { output } = await kernel({
79
+ indices: { data: indicesData, shape: [1] },
80
+ depth: { data: depthData, shape: [] },
81
+ values: { data: valuesData, shape: [2] },
82
+ }, {
83
+ outputs: { output: { shape: [1, 2], dtype: "float32" } },
84
+ });
85
+ ```
build/webgpu/bench.json ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "op": "ai.onnx.OneHot",
3
+ "cases": [
4
+ {
5
+ "name": "tokens_vocab",
6
+ "inputs": {
7
+ "indices": { "dtype": "uint32", "shape": [128] },
8
+ "depth": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [4096] } },
9
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [0.0, 1.0] } }
10
+ },
11
+ "outputs": { "output": { "dtype": "float32", "shape": [128, 4096] } }
12
+ },
13
+ {
14
+ "name": "tokens_vocab_2047x8192",
15
+ "preset": "smoke",
16
+ "inputs": {
17
+ "indices": { "dtype": "uint32", "shape": [2047], "dist": "uniform", "seed": 901, "scale": 8000, "offset": 0 },
18
+ "depth": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [8192] } },
19
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [0.0, 1.0] } }
20
+ },
21
+ "outputs": { "output": { "dtype": "float32", "shape": [2047, 8192] } },
22
+ "bench": { "primary": true, "metrics": [{ "type": "bandwidth", "value": "numel(shapes.output) * 4" }] }
23
+ },
24
+ {
25
+ "name": "unaligned_depth_8191_generic_scalar",
26
+ "preset": "smoke",
27
+ "inputs": {
28
+ "indices": { "dtype": "uint32", "shape": [2047], "dist": "uniform", "seed": 902, "scale": 8000, "offset": 0 },
29
+ "depth": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [8191] } },
30
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [0.0, 1.0] } }
31
+ },
32
+ "outputs": { "output": { "dtype": "float32", "shape": [2047, 8191] } },
33
+ "bench": { "metrics": [{ "type": "bandwidth", "value": "numel(shapes.output) * 4" }] }
34
+ },
35
+ {
36
+ "name": "axis0_generic_8192x2047",
37
+ "preset": "smoke",
38
+ "attrs": { "axis": 0 },
39
+ "inputs": {
40
+ "indices": { "dtype": "uint32", "shape": [2047], "dist": "uniform", "seed": 903, "scale": 8000, "offset": 0 },
41
+ "depth": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [8192] } },
42
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [0.0, 1.0] } }
43
+ },
44
+ "outputs": { "output": { "dtype": "float32", "shape": [8192, 2047] } },
45
+ "bench": { "metrics": [{ "type": "bandwidth", "value": "numel(shapes.output) * 4" }] }
46
+ },
47
+ {
48
+ "name": "axis1_middle_generic_2047x1024x8",
49
+ "preset": "smoke",
50
+ "attrs": { "axis": 1 },
51
+ "inputs": {
52
+ "indices": { "dtype": "uint32", "shape": [2047, 8], "dist": "uniform", "seed": 904, "scale": 1000, "offset": 0 },
53
+ "depth": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [1024] } },
54
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [0.0, 1.0] } }
55
+ },
56
+ "outputs": { "output": { "dtype": "float32", "shape": [2047, 1024, 8] } },
57
+ "bench": { "metrics": [{ "type": "bandwidth", "value": "numel(shapes.output) * 4" }] }
58
+ },
59
+ {
60
+ "name": "tokens_vocab_f16_2047x8192_vec4",
61
+ "preset": "smoke",
62
+ "inputs": {
63
+ "indices": { "dtype": "uint32", "shape": [2047], "dist": "uniform", "seed": 905, "scale": 8000, "offset": 0 },
64
+ "depth": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [8192] } },
65
+ "values": { "dtype": "float16", "shape": [2], "data": { "kind": "values", "values": [0.0, 1.0] } }
66
+ },
67
+ "outputs": { "output": { "dtype": "float16", "shape": [2047, 8192] } },
68
+ "bench": { "metrics": [{ "type": "bandwidth", "value": "numel(shapes.output) * 2" }] }
69
+ },
70
+ {
71
+ "name": "generic_middle_axis_rank5_3p9m",
72
+ "preset": "stress",
73
+ "attrs": { "axis": 1 },
74
+ "inputs": {
75
+ "indices": {
76
+ "dtype": "uint32",
77
+ "shape": [256, 8, 8, 8],
78
+ "dist": "uniform",
79
+ "seed": 911,
80
+ "scale": 29,
81
+ "offset": 0
82
+ },
83
+ "depth": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [30] } },
84
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [0.0, 1.0] } }
85
+ },
86
+ "outputs": { "output": { "dtype": "float32", "shape": [256, 30, 8, 8, 8], "dist": "empty" } },
87
+ "bench": { "metrics": [{ "type": "bandwidth", "value": "numel(shapes.output) * 4" }] }
88
+ }
89
+ ]
90
+ }
build/webgpu/manifest.json ADDED
@@ -0,0 +1,278 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "domain": "ai.onnx",
3
+ "name": "OneHot",
4
+ "sinceVersion": 11,
5
+ "description": "Produces a one-hot tensor from an `indices` input: positions matching each index are filled with `on_value` and all other positions with `off_value`, where both are taken from the two-element `values` tensor `[off_value, on_value]`. The output rank is one greater than `indices`, with the new dimension of size `depth` inserted at the position given by `axis`; indices outside `[-depth, depth-1]` yield all-`off_value` rows.",
6
+ "inputs": [
7
+ {
8
+ "role": "indices",
9
+ "dtype": "I",
10
+ "description": "Integer or float index tensor; values outside `[-depth, depth-1]` produce all-`off_value` output rows."
11
+ },
12
+ {
13
+ "role": "depth",
14
+ "dtype": "D",
15
+ "description": "Scalar (or length-1 rank-1) tensor specifying the number of classes and the size of the one-hot dimension."
16
+ },
17
+ {
18
+ "role": "values",
19
+ "dtype": "T",
20
+ "description": "Rank-1 tensor of exactly two elements `[off_value, on_value]` giving the values written to inactive and active positions respectively.",
21
+ "rank": 1
22
+ }
23
+ ],
24
+ "outputs": [
25
+ {
26
+ "role": "output",
27
+ "dtype": "T",
28
+ "description": "One-hot tensor with rank equal to `rank(indices) + 1`, same element type as `values`.",
29
+ "rank": "ranks.indices + 1"
30
+ }
31
+ ],
32
+ "attributes": { "axis": -1 },
33
+ "attributeDescriptions": {
34
+ "axis": "Axis along which the one-hot dimension is inserted; default `-1` appends it as the last dimension. Negative values count from the back; accepted range is `[-r-1, r]` where `r = rank(indices)`."
35
+ },
36
+ "typeConstraints": {
37
+ "I": ["float32", "float16", "int32", "int16", "int8", "uint32", "uint8"],
38
+ "D": ["float32", "float16", "int32", "int16", "int8", "uint32", "uint8"],
39
+ "T": ["float32", "float16", "int32", "int16", "int8", "uint32", "uint8", "bool"]
40
+ },
41
+ "args": {
42
+ "indices": { "kind": "tensor", "semantic": "indices", "role": "indices" },
43
+ "depth": { "kind": "tensor", "semantic": "depth", "role": "depth" },
44
+ "values": { "kind": "tensor", "semantic": "values", "role": "values" },
45
+ "output": { "kind": "tensor", "semantic": "output", "role": "output" }
46
+ },
47
+ "tunables": { "WORKGROUP_SIZE": 256 },
48
+ "derive": {
49
+ "oneHotContractOk": "(dtypes.I == \"u32\" or dtypes.I == \"i32\" or dtypes.I == \"f32\" or dtypes.I == \"f16\") and ranks.indices >= 1 and ranks.output == ranks.indices + 1 and (ranks.depth == 0 or (ranks.depth == 1 and dim(shapes.depth, 0) == 1)) and ranks.values == 1 and dim(shapes.values, 0) == 2 and numel(shapes.output) >= numel(shapes.indices) and f16Ok(dtypes.T) and f16Ok(dtypes.I)",
50
+ "oneHotLastAxisCovered": "oneHotContractOk and (attrs.axis == ranks.output - 1 or attrs.axis == -1) and dim(shapes.output, -1) % 4 == 0",
51
+ "oneHotLastAxisVecCount": "dim(shapes.output, -1) / 4",
52
+ "oneHotRowWorkgroup": "min(tunables.WORKGROUP_SIZE, device.limits.maxComputeInvocationsPerWorkgroup, device.limits.maxComputeWorkgroupSizeX, max(1, pow2ceil(oneHotLastAxisVecCount)))",
53
+ "oneHotCooperativeMinVecs": "device.adapterInfo.subgroupMinSize if has(device.adapterInfo, \"subgroupMinSize\") else 32",
54
+ "oneHotRowCooperative": "oneHotLastAxisCovered and oneHotLastAxisVecCount >= oneHotCooperativeMinVecs"
55
+ },
56
+ "constants": {
57
+ "scalar": "dtypes.T",
58
+ "indexScalar": "dtypes.I",
59
+ "usesI32": "dtypes.I == \"i32\"",
60
+ "floatIndices": "dtypes.I == \"f32\" or dtypes.I == \"f16\"",
61
+ "usesF16": "dtypes.T == \"f16\" or dtypes.I == \"f16\"",
62
+ "vectorScalar": "\"vec4<\" ~ dtypes.T ~ \">\""
63
+ },
64
+ "variants": [
65
+ {
66
+ "id": "last_axis_row_vec4",
67
+ "priority": 20,
68
+ "when": ["oneHotRowCooperative"],
69
+ "passes": [
70
+ {
71
+ "id": "main",
72
+ "name": "OneHot.last_axis_row_vec4",
73
+ "source": {
74
+ "shader": "one-hot-last-axis-vec4.wgsl.jinja",
75
+ "inputs": {
76
+ "depth": "dim(shapes.output, -1)",
77
+ "rows": "numel(shapes.indices)",
78
+ "wg": "oneHotRowWorkgroup",
79
+ "cooperative": true
80
+ }
81
+ },
82
+ "bindings": [
83
+ {
84
+ "name": "indices",
85
+ "arg": "indices",
86
+ "semantic": "indices",
87
+ "buffer": { "type": "read-only-storage" },
88
+ "elementType": "$indexScalar"
89
+ },
90
+ {
91
+ "name": "values",
92
+ "arg": "values",
93
+ "semantic": "values",
94
+ "buffer": { "type": "read-only-storage" },
95
+ "elementType": "$scalar",
96
+ "length": 2
97
+ },
98
+ {
99
+ "name": "output",
100
+ "arg": "output",
101
+ "semantic": "output",
102
+ "buffer": { "type": "storage" },
103
+ "elementType": "$vectorScalar"
104
+ }
105
+ ],
106
+ "dispatch": { "workgroups": "numel(shapes.indices)" }
107
+ }
108
+ ]
109
+ },
110
+ {
111
+ "id": "last_axis_vec4",
112
+ "priority": 10,
113
+ "when": ["oneHotLastAxisCovered"],
114
+ "passes": [
115
+ {
116
+ "id": "main",
117
+ "name": "OneHot.last_axis_vec4",
118
+ "source": {
119
+ "shader": "one-hot-last-axis-vec4.wgsl.jinja",
120
+ "inputs": { "depth": "dim(shapes.output, -1)", "cooperative": false }
121
+ },
122
+ "bindings": [
123
+ {
124
+ "name": "indices",
125
+ "arg": "indices",
126
+ "semantic": "indices",
127
+ "buffer": { "type": "read-only-storage" },
128
+ "elementType": "$indexScalar"
129
+ },
130
+ {
131
+ "name": "values",
132
+ "arg": "values",
133
+ "semantic": "values",
134
+ "buffer": { "type": "read-only-storage" },
135
+ "elementType": "$scalar",
136
+ "length": 2
137
+ },
138
+ {
139
+ "name": "output",
140
+ "arg": "output",
141
+ "semantic": "output",
142
+ "buffer": { "type": "storage" },
143
+ "elementType": "$vectorScalar"
144
+ },
145
+ {
146
+ "name": "params",
147
+ "semantic": "kernel.params",
148
+ "buffer": { "type": "uniform" },
149
+ "struct": {
150
+ "name": "Params",
151
+ "fields": [{ "name": "count", "type": "u32", "value": "numel(shapes.output) / 4" }]
152
+ }
153
+ }
154
+ ],
155
+ "dispatch": { "threads": "numel(shapes.output) / 4", "workgroupSize": "tunables.WORKGROUP_SIZE" }
156
+ }
157
+ ]
158
+ },
159
+ {
160
+ "id": "generic_axis",
161
+ "when": ["oneHotContractOk", "attrs.axis + ranks.output >= 0", "attrs.axis < ranks.output"],
162
+ "derive": {
163
+ "depthAxis": "attrs.axis if attrs.axis >= 0 else attrs.axis + ranks.output",
164
+ "depthInner": "max(1, inner(shapes.output, depthAxis))",
165
+ "outputVecCount": "floor(numel(shapes.output) / 4)",
166
+ "outputTailCount": "numel(shapes.output) % 4"
167
+ },
168
+ "passes": [
169
+ {
170
+ "id": "fill_vec4",
171
+ "name": "OneHot.FillVec4",
172
+ "source": { "shader": "one-hot-fill.wgsl.jinja", "inputs": { "vectorized": true } },
173
+ "bindings": [
174
+ {
175
+ "name": "values",
176
+ "arg": "values",
177
+ "semantic": "values",
178
+ "buffer": { "type": "read-only-storage" },
179
+ "elementType": "$scalar",
180
+ "length": 2
181
+ },
182
+ {
183
+ "name": "output",
184
+ "arg": "output",
185
+ "semantic": "output",
186
+ "buffer": { "type": "storage" },
187
+ "elementType": "$vectorScalar"
188
+ },
189
+ {
190
+ "name": "params",
191
+ "semantic": "kernel.params",
192
+ "buffer": { "type": "uniform" },
193
+ "struct": { "name": "Params", "fields": [{ "name": "count", "type": "u32", "value": "outputVecCount" }] }
194
+ }
195
+ ],
196
+ "dispatch": { "threads": "outputVecCount", "workgroupSize": "tunables.WORKGROUP_SIZE" }
197
+ },
198
+ {
199
+ "id": "fill_tail",
200
+ "name": "OneHot.FillTail",
201
+ "source": { "shader": "one-hot-fill.wgsl.jinja", "inputs": { "vectorized": false } },
202
+ "bindings": [
203
+ {
204
+ "name": "values",
205
+ "arg": "values",
206
+ "semantic": "values",
207
+ "buffer": { "type": "read-only-storage" },
208
+ "elementType": "$scalar",
209
+ "length": 2
210
+ },
211
+ {
212
+ "name": "output",
213
+ "arg": "output",
214
+ "semantic": "output",
215
+ "buffer": { "type": "storage" },
216
+ "elementType": "$scalar"
217
+ },
218
+ {
219
+ "name": "params",
220
+ "semantic": "kernel.params",
221
+ "buffer": { "type": "uniform" },
222
+ "struct": {
223
+ "name": "Params",
224
+ "fields": [
225
+ { "name": "count", "type": "u32", "value": "outputTailCount" },
226
+ { "name": "offset", "type": "u32", "value": "outputVecCount * 4" }
227
+ ]
228
+ }
229
+ }
230
+ ],
231
+ "dispatch": { "threads": "outputTailCount", "workgroupSize": "tunables.WORKGROUP_SIZE" }
232
+ },
233
+ {
234
+ "id": "scatter",
235
+ "name": "OneHot.Scatter",
236
+ "source": {
237
+ "shader": "one-hot-scatter.wgsl.jinja",
238
+ "inputs": { "depth": "dim(shapes.output, depthAxis)", "inner": "depthInner" }
239
+ },
240
+ "bindings": [
241
+ {
242
+ "name": "indices",
243
+ "arg": "indices",
244
+ "semantic": "indices",
245
+ "buffer": { "type": "read-only-storage" },
246
+ "elementType": "$indexScalar"
247
+ },
248
+ {
249
+ "name": "values",
250
+ "arg": "values",
251
+ "semantic": "values",
252
+ "buffer": { "type": "read-only-storage" },
253
+ "elementType": "$scalar",
254
+ "length": 2
255
+ },
256
+ {
257
+ "name": "output",
258
+ "arg": "output",
259
+ "semantic": "output",
260
+ "buffer": { "type": "storage" },
261
+ "elementType": "$scalar"
262
+ },
263
+ {
264
+ "name": "params",
265
+ "semantic": "kernel.params",
266
+ "buffer": { "type": "uniform" },
267
+ "struct": {
268
+ "name": "Params",
269
+ "fields": [{ "name": "count", "type": "u32", "value": "numel(shapes.indices)" }]
270
+ }
271
+ }
272
+ ],
273
+ "dispatch": { "threads": "numel(shapes.indices)", "workgroupSize": "tunables.WORKGROUP_SIZE" }
274
+ }
275
+ ]
276
+ }
277
+ ]
278
+ }
build/webgpu/metadata.json ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "ai.onnx.OneHot",
3
+ "id": "_ai_onnx_onehot_webgpu_21894c9",
4
+ "version": 1,
5
+ "license": "Apache-2.0",
6
+ "backend": { "type": "webgpu" },
7
+ "digest": {
8
+ "algorithm": "sha256",
9
+ "files": {
10
+ "bench.json": "8JSemsHPcNMzWPXe0x90can66FWOW5qWvz0P7W7I7Pg=",
11
+ "manifest.json": "BfEMlX6Fvw/2pFVCJ1L9FoZ2lBpbHjLoAr2PbX2GBZc=",
12
+ "one-hot-fill.wgsl.jinja": "+1+3T4yVF91Ta11a5kEZHAC8D3C/uGzVKZm/CSK4Htc=",
13
+ "one-hot-last-axis-vec4.wgsl.jinja": "nQ+vRZPx/rWi3Q+vuIhccDJzW6BATwWLFiaDf+HNwXo=",
14
+ "one-hot-scatter.wgsl.jinja": "xXJjRoPmpglSeIQvxCv+9mmygMaGMw1LTKy82ViMVJ8=",
15
+ "test.json": "UrZtlg9pSruj4lfpgeNOargkGctAr+ZUIM0fkeBJNsg="
16
+ }
17
+ },
18
+ "provenance": { "kernel": { "sha": "2e7068faf55e7f43df740015f6d1ee49391a41c5", "dirty": false } },
19
+ "webgpu": { "manifestSpec": "1.0", "specialized": true, "opPath": "ops/ai.onnx.OneHot" }
20
+ }
build/webgpu/one-hot-fill.wgsl.jinja ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% macro flat_index_2d(name="i", bound="params.count", guardInline=false, note="dispatch-limit") %}
2
+ {% if note == "dispatch-limit" %}
3
+ // 2D-folded flat index: gid.y carries the high bits past the
4
+ // maxComputeWorkgroupsPerDimension dispatch limit (outputs > 16.7M elements).
5
+ {% elif note == "limit" %}
6
+ // 2D-folded flat index: gid.y carries the high bits past the
7
+ // maxComputeWorkgroupsPerDimension limit.
8
+ {% elif note == "device-axis" %}
9
+ // The flat dispatch is folded across x/y at the device's per-axis workgroup
10
+ // limit; gid.y carries the high portion of the output index.
11
+ {% elif note == "vec4-limit" %}
12
+ // 2D-folded flat vec4 index: gid.y carries the high bits past the
13
+ // maxComputeWorkgroupsPerDimension limit (the dispatch caps x and spills into y).
14
+ {% elif note == "element-limit" %}
15
+ // 2D-folded flat element index: gid.y carries the high bits past the
16
+ // maxComputeWorkgroupsPerDimension limit.
17
+ {% elif note == "dispatch" %}
18
+ // 2D-folded flat index: gid.y carries the high bits past the
19
+ // maxComputeWorkgroupsPerDimension dispatch limit.
20
+ {% endif %}
21
+ {% if bound == "" %}
22
+ let {{ name }} = gid.x + gid.y * nwg.x * {{ tunables.WORKGROUP_SIZE }}u;
23
+ {%- elif guardInline %}
24
+ let {{ name }} = gid.x + gid.y * nwg.x * {{ tunables.WORKGROUP_SIZE }}u;
25
+ if ({{ name }} >= {{ bound }}) { return; }
26
+ {%- else %}
27
+ let {{ name }} = gid.x + gid.y * nwg.x * {{ tunables.WORKGROUP_SIZE }}u;
28
+ if ({{ name }} >= {{ bound }}) {
29
+ return;
30
+ }
31
+ {%- endif %}
32
+ {% endmacro %}
33
+
34
+ {% if usesF16 %}
35
+ enable f16;
36
+ {% endif %}
37
+ {{ env.wgsl.resourceDeclarations }}
38
+
39
+ // Dense off-value fill for arbitrary-axis OneHot. The vector form writes four
40
+ // elements per invocation and the scalar form handles the tail. A sparse pass
41
+ // writes the on-values afterward.
42
+ @compute @workgroup_size({{ tunables.WORKGROUP_SIZE }})
43
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>, @builtin(num_workgroups) nwg: vec3<u32>) {
44
+ {{ flat_index_2d(note="") }}
45
+ {% if source.vectorized %}
46
+ output[i] = {{ vectorScalar }}(values[0]);
47
+ {% else %}
48
+ output[params.offset + i] = values[0];
49
+ {% endif %}
50
+ }
build/webgpu/one-hot-last-axis-vec4.wgsl.jinja ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% macro flat_index_2d(name="i", bound="params.count", guardInline=false, note="dispatch-limit") %}
2
+ {% if note == "dispatch-limit" %}
3
+ // 2D-folded flat index: gid.y carries the high bits past the
4
+ // maxComputeWorkgroupsPerDimension dispatch limit (outputs > 16.7M elements).
5
+ {% elif note == "limit" %}
6
+ // 2D-folded flat index: gid.y carries the high bits past the
7
+ // maxComputeWorkgroupsPerDimension limit.
8
+ {% elif note == "device-axis" %}
9
+ // The flat dispatch is folded across x/y at the device's per-axis workgroup
10
+ // limit; gid.y carries the high portion of the output index.
11
+ {% elif note == "vec4-limit" %}
12
+ // 2D-folded flat vec4 index: gid.y carries the high bits past the
13
+ // maxComputeWorkgroupsPerDimension limit (the dispatch caps x and spills into y).
14
+ {% elif note == "element-limit" %}
15
+ // 2D-folded flat element index: gid.y carries the high bits past the
16
+ // maxComputeWorkgroupsPerDimension limit.
17
+ {% elif note == "dispatch" %}
18
+ // 2D-folded flat index: gid.y carries the high bits past the
19
+ // maxComputeWorkgroupsPerDimension dispatch limit.
20
+ {% endif %}
21
+ {% if bound == "" %}
22
+ let {{ name }} = gid.x + gid.y * nwg.x * {{ tunables.WORKGROUP_SIZE }}u;
23
+ {%- elif guardInline %}
24
+ let {{ name }} = gid.x + gid.y * nwg.x * {{ tunables.WORKGROUP_SIZE }}u;
25
+ if ({{ name }} >= {{ bound }}) { return; }
26
+ {%- else %}
27
+ let {{ name }} = gid.x + gid.y * nwg.x * {{ tunables.WORKGROUP_SIZE }}u;
28
+ if ({{ name }} >= {{ bound }}) {
29
+ return;
30
+ }
31
+ {%- endif %}
32
+ {% endmacro %}
33
+
34
+ {% if usesF16 %}
35
+ enable f16;
36
+ {% endif %}
37
+ {{ env.wgsl.resourceDeclarations }}
38
+
39
+ // Vec4 OneHot for a contiguous depth-last output. Wide rows are assigned one
40
+ // cooperative workgroup so they share the index load and avoid flat division;
41
+ // short rows use the dense flat launch to avoid underfilled workgroups.
42
+ const DEPTH: u32 = {{ source.depth }}u;
43
+ const VEC_DEPTH: u32 = DEPTH / 4u;
44
+
45
+ struct NormalizedIndex {
46
+ valid: bool,
47
+ depth: u32,
48
+ };
49
+
50
+ fn normalize_index(raw: {{ indexScalar }}) -> NormalizedIndex {
51
+ {% if floatIndices %}
52
+ let depth_i = i32(DEPTH);
53
+ let truncated = i32(trunc(raw));
54
+ let adjusted = select(truncated, truncated + depth_i, truncated < 0);
55
+ return NormalizedIndex(adjusted >= 0 && adjusted < depth_i, u32(adjusted));
56
+ {% elif usesI32 %}
57
+ let depth_i = i32(DEPTH);
58
+ let adjusted = select(raw, raw + depth_i, raw < 0);
59
+ return NormalizedIndex(adjusted >= 0 && adjusted < depth_i, u32(adjusted));
60
+ {% else %}
61
+ return NormalizedIndex(raw < DEPTH, raw);
62
+ {% endif %}
63
+ }
64
+
65
+ {% if source.cooperative %}
66
+ const ROWS: u32 = {{ source.rows }}u;
67
+ const WG: u32 = {{ source.wg }}u;
68
+
69
+ var<workgroup> row_index: {{ indexScalar }};
70
+
71
+ @compute @workgroup_size({{ source.wg }})
72
+ fn main(
73
+ @builtin(local_invocation_id) lid3: vec3<u32>,
74
+ @builtin(workgroup_id) wid: vec3<u32>,
75
+ @builtin(num_workgroups) nwg: vec3<u32>
76
+ ) {
77
+ let lane = lid3.x;
78
+ let row = wid.x + wid.y * nwg.x;
79
+ if (row >= ROWS) {
80
+ return;
81
+ }
82
+ if (lane == 0u) {
83
+ row_index = indices[row];
84
+ }
85
+ workgroupBarrier();
86
+ let index = normalize_index(row_index);
87
+ let off_v = values[0];
88
+ let on_v = values[1];
89
+ let row_base = row * VEC_DEPTH;
90
+ for (var d4 = lane; d4 < VEC_DEPTH; d4 += WG) {
91
+ let d0 = d4 * 4u;
92
+ output[row_base + d4] = {{ vectorScalar }}(
93
+ select(off_v, on_v, index.valid && index.depth == d0),
94
+ select(off_v, on_v, index.valid && index.depth == d0 + 1u),
95
+ select(off_v, on_v, index.valid && index.depth == d0 + 2u),
96
+ select(off_v, on_v, index.valid && index.depth == d0 + 3u)
97
+ );
98
+ }
99
+ }
100
+ {% else %}
101
+ @compute @workgroup_size({{ tunables.WORKGROUP_SIZE }})
102
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>, @builtin(num_workgroups) nwg: vec3<u32>) {
103
+ {{ flat_index_2d("i4", note="") }}
104
+ let d4 = i4 % VEC_DEPTH;
105
+ let d0 = d4 * 4u;
106
+ let row = i4 / VEC_DEPTH;
107
+ let index = normalize_index(indices[row]);
108
+ let off_v = values[0];
109
+ let on_v = values[1];
110
+ output[i4] = {{ vectorScalar }}(
111
+ select(off_v, on_v, index.valid && index.depth == d0),
112
+ select(off_v, on_v, index.valid && index.depth == d0 + 1u),
113
+ select(off_v, on_v, index.valid && index.depth == d0 + 2u),
114
+ select(off_v, on_v, index.valid && index.depth == d0 + 3u)
115
+ );
116
+ }
117
+ {% endif %}
build/webgpu/one-hot-scatter.wgsl.jinja ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% macro flat_index_2d(name="i", bound="params.count", guardInline=false, note="dispatch-limit") %}
2
+ {% if note == "dispatch-limit" %}
3
+ // 2D-folded flat index: gid.y carries the high bits past the
4
+ // maxComputeWorkgroupsPerDimension dispatch limit (outputs > 16.7M elements).
5
+ {% elif note == "limit" %}
6
+ // 2D-folded flat index: gid.y carries the high bits past the
7
+ // maxComputeWorkgroupsPerDimension limit.
8
+ {% elif note == "device-axis" %}
9
+ // The flat dispatch is folded across x/y at the device's per-axis workgroup
10
+ // limit; gid.y carries the high portion of the output index.
11
+ {% elif note == "vec4-limit" %}
12
+ // 2D-folded flat vec4 index: gid.y carries the high bits past the
13
+ // maxComputeWorkgroupsPerDimension limit (the dispatch caps x and spills into y).
14
+ {% elif note == "element-limit" %}
15
+ // 2D-folded flat element index: gid.y carries the high bits past the
16
+ // maxComputeWorkgroupsPerDimension limit.
17
+ {% elif note == "dispatch" %}
18
+ // 2D-folded flat index: gid.y carries the high bits past the
19
+ // maxComputeWorkgroupsPerDimension dispatch limit.
20
+ {% endif %}
21
+ {% if bound == "" %}
22
+ let {{ name }} = gid.x + gid.y * nwg.x * {{ tunables.WORKGROUP_SIZE }}u;
23
+ {%- elif guardInline %}
24
+ let {{ name }} = gid.x + gid.y * nwg.x * {{ tunables.WORKGROUP_SIZE }}u;
25
+ if ({{ name }} >= {{ bound }}) { return; }
26
+ {%- else %}
27
+ let {{ name }} = gid.x + gid.y * nwg.x * {{ tunables.WORKGROUP_SIZE }}u;
28
+ if ({{ name }} >= {{ bound }}) {
29
+ return;
30
+ }
31
+ {%- endif %}
32
+ {% endmacro %}
33
+
34
+ {% if usesF16 %}
35
+ enable f16;
36
+ {% endif %}
37
+ {{ env.wgsl.resourceDeclarations }}
38
+
39
+ // Sparse on-value scatter for an output laid out as [outer, depth, inner].
40
+ // One thread owns one input index, so output locations are unique even when
41
+ // several input elements select the same depth value.
42
+ const DEPTH: u32 = {{ source.depth }}u;
43
+ const INNER: u32 = {{ source.inner }}u;
44
+
45
+ @compute @workgroup_size({{ tunables.WORKGROUP_SIZE }})
46
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>, @builtin(num_workgroups) nwg: vec3<u32>) {
47
+ {{ flat_index_2d(note="") }}
48
+ let raw = indices[i];
49
+ {% if floatIndices %}
50
+ let depth_i = i32(DEPTH);
51
+ let truncated = i32(trunc(raw));
52
+ let adjusted = select(truncated, truncated + depth_i, truncated < 0);
53
+ let valid = adjusted >= 0 && adjusted < depth_i;
54
+ let on_depth = u32(adjusted);
55
+ {% elif usesI32 %}
56
+ let depth_i = i32(DEPTH);
57
+ let adjusted = select(raw, raw + depth_i, raw < 0);
58
+ let valid = adjusted >= 0 && adjusted < depth_i;
59
+ let on_depth = u32(adjusted);
60
+ {% else %}
61
+ let valid = raw < DEPTH;
62
+ let on_depth = raw;
63
+ {% endif %}
64
+ if (valid) {
65
+ let inner_coord = i % INNER;
66
+ let outer = i / INNER;
67
+ output[(outer * DEPTH + on_depth) * INNER + inner_coord] = values[1];
68
+ }
69
+ }
build/webgpu/test.json ADDED
@@ -0,0 +1,790 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "op": "ai.onnx.OneHot",
3
+ "cases": [
4
+ {
5
+ "name": "float16_indices_depth_and_values",
6
+ "provenance": {
7
+ "notes": "Pins the exact ONNX float16 routes for independent indices, depth, and value type variables."
8
+ },
9
+ "attrs": { "axis": -1 },
10
+ "inputs": {
11
+ "indices": { "dtype": "float16", "shape": [4], "data": { "kind": "values", "values": [-1.0, 0.0, 2.0, 4.0] } },
12
+ "depth": { "dtype": "float16", "shape": [1], "data": { "kind": "values", "values": [4.0] } },
13
+ "values": { "dtype": "float16", "shape": [2], "data": { "kind": "values", "values": [-0.5, 2.0] } }
14
+ },
15
+ "outputs": { "output": { "dtype": "float16", "shape": [4, 4], "tolerance": 0 } }
16
+ },
17
+ {
18
+ "name": "int16_indices_depth_and_values",
19
+ "provenance": {
20
+ "notes": "Pins widened-storage int16 support across all three independent OneHot type variables."
21
+ },
22
+ "attrs": { "axis": 0 },
23
+ "inputs": {
24
+ "indices": { "dtype": "int16", "shape": [4], "data": { "kind": "values", "values": [-1, 0, 2, 3] } },
25
+ "depth": { "dtype": "int16", "shape": [], "data": { "kind": "values", "values": [3] } },
26
+ "values": { "dtype": "int16", "shape": [2], "data": { "kind": "values", "values": [-1234, 2345] } }
27
+ },
28
+ "outputs": { "output": { "dtype": "int16", "shape": [3, 4], "tolerance": 0 } }
29
+ },
30
+ {
31
+ "name": "int8_indices_depth_and_values",
32
+ "provenance": { "notes": "Pins signed 8-bit logical tensors through widened i32 shader storage." },
33
+ "attrs": { "axis": -1 },
34
+ "inputs": {
35
+ "indices": { "dtype": "int8", "shape": [4], "data": { "kind": "values", "values": [-2, -1, 1, 4] } },
36
+ "depth": { "dtype": "int8", "shape": [1], "data": { "kind": "values", "values": [4] } },
37
+ "values": { "dtype": "int8", "shape": [2], "data": { "kind": "values", "values": [-7, 101] } }
38
+ },
39
+ "outputs": { "output": { "dtype": "int8", "shape": [4, 4], "tolerance": 0 } }
40
+ },
41
+ {
42
+ "name": "uint8_indices_depth_and_values",
43
+ "provenance": { "notes": "Pins unsigned 8-bit logical tensors through widened u32 shader storage." },
44
+ "attrs": { "axis": 1 },
45
+ "inputs": {
46
+ "indices": { "dtype": "uint8", "shape": [2, 2], "data": { "kind": "values", "values": [0, 3, 4, 1] } },
47
+ "depth": { "dtype": "uint8", "shape": [1], "data": { "kind": "values", "values": [4] } },
48
+ "values": { "dtype": "uint8", "shape": [2], "data": { "kind": "values", "values": [2, 251] } }
49
+ },
50
+ "outputs": { "output": { "dtype": "uint8", "shape": [2, 4, 2], "tolerance": 0 } }
51
+ },
52
+ {
53
+ "name": "bool_values_and_output",
54
+ "provenance": { "notes": "Pins ONNX boolean off/on payloads without exposing bool as an index or depth type." },
55
+ "attrs": { "axis": -1 },
56
+ "inputs": {
57
+ "indices": { "dtype": "int32", "shape": [4], "data": { "kind": "values", "values": [-1, 0, 2, 3] } },
58
+ "depth": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [3] } },
59
+ "values": { "dtype": "bool", "shape": [2], "data": { "kind": "values", "values": [0, 1] } }
60
+ },
61
+ "outputs": { "output": { "dtype": "bool", "shape": [4, 3], "tolerance": 0 } }
62
+ },
63
+ {
64
+ "name": "float32_indices_int16_depth_float32_values",
65
+ "provenance": {
66
+ "notes": "An integral float32 index route with independently typed int16 depth connects both standard type variables while the all-int16 sibling retains widened-storage coverage."
67
+ },
68
+ "attrs": { "axis": -1 },
69
+ "inputs": {
70
+ "indices": { "dtype": "float32", "shape": [4], "data": { "kind": "values", "values": [-1.0, 0.0, 2.0, 3.0] } },
71
+ "depth": { "dtype": "int16", "shape": [1], "data": { "kind": "values", "values": [3] } },
72
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [-0.25, 1.5] } }
73
+ },
74
+ "outputs": { "output": { "dtype": "float32", "shape": [4, 3], "tolerance": 0 } }
75
+ },
76
+ {
77
+ "name": "float32_indices_int8_depth_float32_values",
78
+ "provenance": {
79
+ "notes": "An integral float32 index route with independently typed int8 depth connects both standard type variables while the all-int8 sibling retains widened-storage coverage."
80
+ },
81
+ "attrs": { "axis": 0 },
82
+ "inputs": {
83
+ "indices": { "dtype": "float32", "shape": [4], "data": { "kind": "values", "values": [-2.0, -1.0, 1.0, 4.0] } },
84
+ "depth": { "dtype": "int8", "shape": [], "data": { "kind": "values", "values": [4] } },
85
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [0.125, 2.5] } }
86
+ },
87
+ "outputs": { "output": { "dtype": "float32", "shape": [4, 4], "tolerance": 0 } }
88
+ },
89
+ {
90
+ "name": "float32_indices_uint8_depth_float32_values",
91
+ "provenance": {
92
+ "notes": "An integral float32 index route with independently typed uint8 depth connects both standard type variables while the all-uint8 sibling retains widened-storage coverage."
93
+ },
94
+ "attrs": { "axis": 1 },
95
+ "inputs": {
96
+ "indices": { "dtype": "float32", "shape": [2, 2], "data": { "kind": "values", "values": [0.0, 3.0, 4.0, 1.0] } },
97
+ "depth": { "dtype": "uint8", "shape": [1], "data": { "kind": "values", "values": [4] } },
98
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [-1.0, 3.0] } }
99
+ },
100
+ "outputs": { "output": { "dtype": "float32", "shape": [2, 4, 2], "tolerance": 0 } }
101
+ },
102
+ {
103
+ "name": "int16_indices_depth_float32_values",
104
+ "provenance": { "notes": "Pairs int16 indices/depth with the independent float32 value/output route." },
105
+ "inputs": {
106
+ "indices": { "dtype": "int16", "shape": [1], "data": { "kind": "values", "values": [-1] } },
107
+ "depth": { "dtype": "int16", "shape": [], "data": { "kind": "values", "values": [2] } },
108
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [-0.25, 1.5] } }
109
+ },
110
+ "outputs": { "output": { "dtype": "float32", "shape": [1, 2], "tolerance": 0 } }
111
+ },
112
+ {
113
+ "name": "int8_indices_depth_float32_values",
114
+ "provenance": { "notes": "Pairs int8 indices/depth with the independent float32 value/output route." },
115
+ "inputs": {
116
+ "indices": { "dtype": "int8", "shape": [1], "data": { "kind": "values", "values": [1] } },
117
+ "depth": { "dtype": "int8", "shape": [], "data": { "kind": "values", "values": [2] } },
118
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [0.125, 2.5] } }
119
+ },
120
+ "outputs": { "output": { "dtype": "float32", "shape": [1, 2], "tolerance": 0 } }
121
+ },
122
+ {
123
+ "name": "uint8_indices_depth_float32_values",
124
+ "provenance": { "notes": "Pairs uint8 indices/depth with the independent float32 value/output route." },
125
+ "inputs": {
126
+ "indices": { "dtype": "uint8", "shape": [1], "data": { "kind": "values", "values": [0] } },
127
+ "depth": { "dtype": "uint8", "shape": [], "data": { "kind": "values", "values": [2] } },
128
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [-1.0, 3.0] } }
129
+ },
130
+ "outputs": { "output": { "dtype": "float32", "shape": [1, 2], "tolerance": 0 } }
131
+ },
132
+ {
133
+ "name": "dispatch_cliff_axis0",
134
+ "attrs": { "axis": 0 },
135
+ "inputs": {
136
+ "indices": { "dtype": "uint32", "shape": [4], "data": { "kind": "cycle", "values": [0, 1000000, 4194240, 7] } },
137
+ "depth": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [4194241] } },
138
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [0.0, 1.0] } }
139
+ },
140
+ "outputs": { "output": { "dtype": "float32", "shape": [4194241, 4], "tolerance": 0 } }
141
+ },
142
+ {
143
+ "name": "rank1_last_axis",
144
+ "inputs": {
145
+ "indices": { "dtype": "uint32", "shape": [3], "data": { "kind": "values", "values": [0, 2, 1] } },
146
+ "depth": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [4] } },
147
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [0.0, 1.0] } }
148
+ },
149
+ "outputs": { "output": { "dtype": "float32", "shape": [3, 4] } }
150
+ },
151
+ {
152
+ "name": "f32_subnormal_values_last_axis_vec4",
153
+ "provenance": {
154
+ "source": "onnxruntime/test/providers/cpu/tensor/onehot_op_test.cc",
155
+ "test": "OneHotOpTest.DefaultAxis_float_float_float",
156
+ "notes": "OneHot payload values may be valid positive subnormal floats; the last-axis vec4 path must not flush on-values to zero."
157
+ },
158
+ "inputs": {
159
+ "indices": { "dtype": "uint32", "shape": [3], "data": { "kind": "values", "values": [0, 2, 1] } },
160
+ "depth": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [4] } },
161
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [0.0, 1e-40] } }
162
+ },
163
+ "outputs": {
164
+ "output": {
165
+ "dtype": "float32",
166
+ "shape": [3, 4],
167
+ "tolerance": 2e-45,
168
+ "data": {
169
+ "kind": "values",
170
+ "values": [9.99994610111476e-41, 0.0, 0.0, 0.0, 0.0, 0.0, 9.99994610111476e-41, 0.0, 0.0, 9.99994610111476e-41, 0.0, 0.0]
171
+ }
172
+ }
173
+ }
174
+ },
175
+ {
176
+ "name": "rank2_f16",
177
+ "inputs": {
178
+ "indices": { "dtype": "uint32", "shape": [2, 2], "data": { "kind": "values", "values": [0, 1, 2, 1] } },
179
+ "depth": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [3] } },
180
+ "values": { "dtype": "float16", "shape": [2], "data": { "kind": "values", "values": [-1.0, 2.0] } }
181
+ },
182
+ "outputs": { "output": { "dtype": "float16", "shape": [2, 2, 3] } },
183
+ "tolerance": 0.001
184
+ },
185
+ {
186
+ "name": "rank2_axis0",
187
+ "attrs": { "axis": 0 },
188
+ "inputs": {
189
+ "indices": { "dtype": "uint32", "shape": [2, 2], "data": { "kind": "values", "values": [0, 1, 2, 1] } },
190
+ "depth": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [3] } },
191
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [-1.0, 2.0] } }
192
+ },
193
+ "outputs": { "output": { "dtype": "float32", "shape": [3, 2, 2], "tolerance": 0.000001 } }
194
+ },
195
+ {
196
+ "name": "f32_subnormal_values_axis0_negative_and_oob",
197
+ "provenance": {
198
+ "source": "onnxruntime/test/providers/cpu/tensor/onehot_op_test.cc",
199
+ "test": "OneHotOpTest.Axis_Negative_NegIndex_NonDefault_NonZeroOffValue",
200
+ "notes": "Generic-axis payload edge with subnormal off/on values, negative index normalization, and an out-of-range index that must remain off."
201
+ },
202
+ "attrs": { "axis": 0 },
203
+ "inputs": {
204
+ "indices": { "dtype": "int32", "shape": [4], "data": { "kind": "values", "values": [0, -1, 5, 1] } },
205
+ "depth": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [3] } },
206
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [1e-40, 2e-40] } }
207
+ },
208
+ "outputs": {
209
+ "output": {
210
+ "dtype": "float32",
211
+ "shape": [3, 4],
212
+ "tolerance": 2e-45,
213
+ "data": {
214
+ "kind": "values",
215
+ "values": [1.999989220222952e-40, 9.99994610111476e-41, 9.99994610111476e-41, 9.99994610111476e-41, 9.99994610111476e-41, 9.99994610111476e-41, 9.99994610111476e-41, 1.999989220222952e-40, 9.99994610111476e-41, 1.999989220222952e-40, 9.99994610111476e-41, 9.99994610111476e-41]
216
+ }
217
+ }
218
+ }
219
+ },
220
+ {
221
+ "name": "rank4_indices_last_axis",
222
+ "attrs": { "axis": -1 },
223
+ "inputs": {
224
+ "indices": { "dtype": "uint32", "shape": [1, 2, 1, 2], "data": { "kind": "values", "values": [0, 2, 1, 3] } },
225
+ "depth": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [4] } },
226
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [-1.0, 5.0] } }
227
+ },
228
+ "outputs": { "output": { "dtype": "float32", "shape": [1, 2, 1, 2, 4], "tolerance": 0.000001 } }
229
+ },
230
+ {
231
+ "name": "rank5_indices_last_axis",
232
+ "attrs": { "axis": -1 },
233
+ "inputs": {
234
+ "indices": { "dtype": "uint32", "shape": [1, 2, 1, 2, 1], "data": { "kind": "values", "values": [0, 2, 1, 3] } },
235
+ "depth": { "dtype": "uint32", "shape": [], "data": { "kind": "values", "values": [4] } },
236
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [-1.0, 5.0] } }
237
+ },
238
+ "outputs": { "output": { "dtype": "float32", "shape": [1, 2, 1, 2, 1, 4], "tolerance": 0.000001 } }
239
+ },
240
+ {
241
+ "name": "rank6_indices_axis0_output_rank7",
242
+ "attrs": { "axis": 0 },
243
+ "inputs": {
244
+ "indices": {
245
+ "dtype": "uint32",
246
+ "shape": [1, 2, 1, 2, 1, 2],
247
+ "data": { "kind": "values", "values": [0, 2, 1, 3, 2, 0, 3, 1] }
248
+ },
249
+ "depth": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [4] } },
250
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [-2.0, 6.0] } }
251
+ },
252
+ "outputs": { "output": { "dtype": "float32", "shape": [4, 1, 2, 1, 2, 1, 2], "tolerance": 0.000001 } }
253
+ },
254
+ {
255
+ "name": "scalar_depth",
256
+ "attrs": { "axis": -1 },
257
+ "inputs": {
258
+ "indices": { "dtype": "uint32", "shape": [3], "data": { "kind": "values", "values": [0, 2, 3] } },
259
+ "depth": { "dtype": "uint32", "shape": [], "data": { "kind": "values", "values": [4] } },
260
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [-3.0, 7.0] } }
261
+ },
262
+ "outputs": { "output": { "dtype": "float32", "shape": [3, 4], "tolerance": 0.000001 } }
263
+ },
264
+ {
265
+ "name": "ort_default_axis_rank2_depth10",
266
+ "provenance": {
267
+ "source": "onnxruntime/test/providers/cpu/tensor/onehot_op_test.cc",
268
+ "test": "OneHotOpTest.DefaultAxis"
269
+ },
270
+ "attrs": { "axis": -1 },
271
+ "inputs": {
272
+ "indices": { "dtype": "uint32", "shape": [2, 3], "data": { "kind": "values", "values": [1, 9, 8, 2, 4, 6] } },
273
+ "depth": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [10] } },
274
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [0.0, 1.0] } }
275
+ },
276
+ "outputs": { "output": { "dtype": "float32", "shape": [2, 3, 10], "tolerance": 0 } }
277
+ },
278
+ {
279
+ "name": "ort_float_indices_float_depth_default_axis",
280
+ "provenance": {
281
+ "source": "onnxruntime/test/providers/cpu/tensor/onehot_op_test.cc",
282
+ "test": "OneHotOpTest.DefaultAxis_float_float_float",
283
+ "notes": "Covers integral index and depth values carried by ONNX-permitted float32 tensors."
284
+ },
285
+ "attrs": { "axis": -1 },
286
+ "inputs": {
287
+ "indices": {
288
+ "dtype": "float32",
289
+ "shape": [2, 3],
290
+ "data": { "kind": "values", "values": [1.0, 9.0, 8.0, 2.0, 4.0, 6.0] }
291
+ },
292
+ "depth": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [10.0] } },
293
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [0.0, 1.0] } }
294
+ },
295
+ "outputs": { "output": { "dtype": "float32", "shape": [2, 3, 10], "tolerance": 0 } }
296
+ },
297
+ {
298
+ "name": "float32_indices_float16_depth_nonzero_off",
299
+ "provenance": {
300
+ "source": "onnxruntime/test/providers/cpu/tensor/onehot_op_test.cc",
301
+ "test": "OneHotOpTest.DefaultAxis_float_float_float_NonZeroOffValue",
302
+ "notes": "The ORT-derived integral float-index case uses float16 depth to cover the independent I/D type variables; arbitrary off/on values catch accidental zero-fill assumptions."
303
+ },
304
+ "attrs": { "axis": -1 },
305
+ "inputs": {
306
+ "indices": {
307
+ "dtype": "float32",
308
+ "shape": [2, 3],
309
+ "data": { "kind": "values", "values": [1.0, 9.0, 8.0, 2.0, 4.0, 6.0] }
310
+ },
311
+ "depth": { "dtype": "float16", "shape": [1], "data": { "kind": "values", "values": [10.0] } },
312
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [2.0, 3.0] } }
313
+ },
314
+ "outputs": { "output": { "dtype": "float32", "shape": [2, 3, 10], "tolerance": 0 } }
315
+ },
316
+ {
317
+ "name": "ort_int32_indices_depth_float_values_default_axis",
318
+ "provenance": {
319
+ "source": "onnxruntime/test/providers/cpu/tensor/onehot_op_test.cc",
320
+ "test": "OneHotOpTest.DefaultAxis_int32_float_int32"
321
+ },
322
+ "inputs": {
323
+ "indices": { "dtype": "int32", "shape": [2, 3], "data": { "kind": "values", "values": [1, 9, 8, 2, 4, 6] } },
324
+ "depth": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [10] } },
325
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [0.0, 1.0] } }
326
+ },
327
+ "outputs": { "output": { "dtype": "float32", "shape": [2, 3, 10], "tolerance": 0 } }
328
+ },
329
+ {
330
+ "name": "ort_axis1_rank2_depth10",
331
+ "provenance": {
332
+ "source": "onnxruntime/test/providers/cpu/tensor/onehot_op_test.cc",
333
+ "test": "OneHotOpTest.Axis_1"
334
+ },
335
+ "attrs": { "axis": 1 },
336
+ "inputs": {
337
+ "indices": { "dtype": "uint32", "shape": [2, 3], "data": { "kind": "values", "values": [1, 9, 8, 2, 4, 6] } },
338
+ "depth": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [10] } },
339
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [0.0, 1.0] } }
340
+ },
341
+ "outputs": { "output": { "dtype": "float32", "shape": [2, 10, 3], "tolerance": 0 } }
342
+ },
343
+ {
344
+ "name": "ort_negative_axis_nondefault_rank2_depth10",
345
+ "provenance": {
346
+ "source": "onnxruntime/test/providers/cpu/tensor/onehot_op_test.cc",
347
+ "test": "OneHotOpTest.Axis_Negative_NonDefault"
348
+ },
349
+ "attrs": { "axis": -3 },
350
+ "inputs": {
351
+ "indices": { "dtype": "uint32", "shape": [2, 3], "data": { "kind": "values", "values": [1, 9, 8, 2, 4, 6] } },
352
+ "depth": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [10] } },
353
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [0.0, 1.0] } }
354
+ },
355
+ "outputs": { "output": { "dtype": "float32", "shape": [10, 2, 3], "tolerance": 0 } }
356
+ },
357
+ {
358
+ "name": "ort_int32_indices_float32_depth_values_nonzero_off_default_axis",
359
+ "provenance": {
360
+ "source": "onnxruntime/test/providers/cpu/tensor/onehot_op_test.cc",
361
+ "test": "OneHotOpTest.DefaultAxis_int32_float_int32_NonZeroOffValue",
362
+ "notes": "The ORT case's depth is adapted from int32 to float32 to cover the independent I/D type variables while preserving its integral value and exact output."
363
+ },
364
+ "inputs": {
365
+ "indices": { "dtype": "int32", "shape": [2, 3], "data": { "kind": "values", "values": [1, 9, 8, 2, 4, 6] } },
366
+ "depth": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [10.0] } },
367
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [2.0, 3.0] } }
368
+ },
369
+ "outputs": { "output": { "dtype": "float32", "shape": [2, 3, 10], "tolerance": 0 } }
370
+ },
371
+ {
372
+ "name": "ort_default_axis_nonzero_off_value",
373
+ "provenance": {
374
+ "source": "onnxruntime/test/providers/cpu/tensor/onehot_op_test.cc",
375
+ "test": "OneHotOpTest.DefaultAxis_NonZeroOffValue"
376
+ },
377
+ "attrs": { "axis": -1 },
378
+ "inputs": {
379
+ "indices": { "dtype": "uint32", "shape": [2, 3], "data": { "kind": "values", "values": [1, 9, 8, 2, 4, 6] } },
380
+ "depth": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [10] } },
381
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [2.0, 3.0] } }
382
+ },
383
+ "outputs": { "output": { "dtype": "float32", "shape": [2, 3, 10], "tolerance": 0 } }
384
+ },
385
+ {
386
+ "name": "ort_dim_with_zero_axis0",
387
+ "provenance": {
388
+ "source": "onnxruntime/test/providers/cpu/tensor/onehot_op_test.cc",
389
+ "test": "OneHotOpTest.DimWithZero"
390
+ },
391
+ "attrs": { "axis": 0 },
392
+ "inputs": {
393
+ "indices": { "dtype": "uint32", "shape": [2, 0], "data": { "kind": "values", "values": [] } },
394
+ "depth": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [10] } },
395
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [0.0, 1.0] } }
396
+ },
397
+ "outputs": { "output": { "dtype": "float32", "shape": [10, 2, 0], "tolerance": 0 } }
398
+ },
399
+ {
400
+ "name": "ort_negative_index_axis_negative_nondefault",
401
+ "provenance": {
402
+ "source": "onnxruntime/test/providers/cpu/tensor/onehot_op_test.cc",
403
+ "test": "OneHotOpTest.Axis_Negative_NegIndex_NonDefault"
404
+ },
405
+ "attrs": { "axis": -3 },
406
+ "inputs": {
407
+ "indices": { "dtype": "int32", "shape": [2, 3], "data": { "kind": "values", "values": [1, -1, 8, 2, 4, 6] } },
408
+ "depth": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [10] } },
409
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [0.0, 1.0] } }
410
+ },
411
+ "outputs": { "output": { "dtype": "float32", "shape": [10, 2, 3], "tolerance": 0 } }
412
+ },
413
+ {
414
+ "name": "ort_indices_out_of_range_default_axis_nonzero_off",
415
+ "provenance": {
416
+ "source": "onnxruntime/test/providers/cpu/tensor/onehot_op_test.cc",
417
+ "test": "OneHotOpTest.DefaultAxis_IndicesOutOfRange_NonZeroOffValue"
418
+ },
419
+ "attrs": { "axis": -1 },
420
+ "inputs": {
421
+ "indices": { "dtype": "int32", "shape": [2, 3], "data": { "kind": "values", "values": [1, -1, 8, 13, 4, -12] } },
422
+ "depth": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [10] } },
423
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [2.0, 3.0] } }
424
+ },
425
+ "outputs": { "output": { "dtype": "float32", "shape": [2, 3, 10], "tolerance": 0 } }
426
+ },
427
+ {
428
+ "name": "onnx_backend_onehot_negative_indices",
429
+ "attrs": { "axis": 1 },
430
+ "inputs": {
431
+ "indices": { "dtype": "int32", "shape": [3], "data": { "kind": "values", "values": [0, -7, -8] } },
432
+ "depth": { "dtype": "uint32", "shape": [], "data": { "kind": "values", "values": [10] } },
433
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [1.0, 3.0] } }
434
+ },
435
+ "outputs": { "output": { "dtype": "float32", "shape": [3, 10] } },
436
+ "provenance": {
437
+ "source": "cmake/external/onnx/onnx/backend/test/data/node/test_onehot_negative_indices",
438
+ "notes": "ONNX int64 metadata/index tensors use framework int32/uint32 slots where representable. Official backend depth is represented with framework uint32 metadata."
439
+ }
440
+ },
441
+ {
442
+ "name": "onnx_backend_onehot_with_axis",
443
+ "attrs": { "axis": 1 },
444
+ "inputs": {
445
+ "indices": { "dtype": "int32", "shape": [2, 2], "data": { "kind": "values", "values": [1, 9, 2, 4] } },
446
+ "depth": { "dtype": "uint32", "shape": [], "data": { "kind": "values", "values": [10] } },
447
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [1.0, 3.0] } }
448
+ },
449
+ "outputs": { "output": { "dtype": "float32", "shape": [2, 10, 2] } },
450
+ "provenance": {
451
+ "source": "cmake/external/onnx/onnx/backend/test/data/node/test_onehot_with_axis",
452
+ "notes": "Official backend fixture stores integer-looking indices/depth as floats; represented with framework integer metadata tensors. Official backend depth is represented with framework uint32 metadata."
453
+ }
454
+ },
455
+ {
456
+ "name": "onnx_backend_onehot_with_negative_axis",
457
+ "attrs": { "axis": -2 },
458
+ "inputs": {
459
+ "indices": { "dtype": "int32", "shape": [2, 2], "data": { "kind": "values", "values": [1, 9, 2, 4] } },
460
+ "depth": { "dtype": "uint32", "shape": [], "data": { "kind": "values", "values": [10] } },
461
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [1.0, 3.0] } }
462
+ },
463
+ "outputs": { "output": { "dtype": "float32", "shape": [2, 10, 2] } },
464
+ "provenance": {
465
+ "source": "cmake/external/onnx/onnx/backend/test/data/node/test_onehot_with_negative_axis",
466
+ "notes": "Official backend fixture stores integer-looking indices/depth as floats; represented with framework integer metadata tensors. Official backend depth is represented with framework uint32 metadata."
467
+ }
468
+ },
469
+ {
470
+ "name": "onnx_backend_onehot_without_axis",
471
+ "inputs": {
472
+ "indices": { "dtype": "uint32", "shape": [3], "data": { "kind": "values", "values": [0, 7, 8] } },
473
+ "depth": { "dtype": "uint32", "shape": [], "data": { "kind": "values", "values": [12] } },
474
+ "values": { "dtype": "int32", "shape": [2], "data": { "kind": "values", "values": [2, 5] } }
475
+ },
476
+ "outputs": { "output": { "dtype": "int32", "shape": [3, 12] } },
477
+ "provenance": {
478
+ "source": "cmake/external/onnx/onnx/backend/test/data/node/test_onehot_without_axis",
479
+ "notes": "ONNX int64 metadata/index tensors use framework int32/uint32 slots where representable. Official backend depth is represented with framework uint32 metadata."
480
+ }
481
+ },
482
+ {
483
+ "name": "ort_int32_values_exact_above_float24_default_axis",
484
+ "provenance": {
485
+ "source": "onnxruntime/test/providers/cpu/tensor/onehot_op_test.cc",
486
+ "test": "OneHotOpTest.DefaultAxis_int64_int32_float_NonZeroOffValue",
487
+ "notes": "Uses framework int32 depth instead of ORT's float depth so WebGPU can treat depth as shape metadata."
488
+ },
489
+ "inputs": {
490
+ "indices": { "dtype": "int32", "shape": [4], "data": { "kind": "values", "values": [0, 2, -1, 5] } },
491
+ "depth": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [4] } },
492
+ "values": { "dtype": "int32", "shape": [2], "data": { "kind": "values", "values": [16777217, -16777219] } }
493
+ },
494
+ "outputs": { "output": { "dtype": "int32", "shape": [4, 4], "tolerance": 0 } }
495
+ },
496
+ {
497
+ "name": "ort_int32_values_oob_indices_exact_above_float24",
498
+ "provenance": {
499
+ "source": "onnxruntime/test/providers/cpu/tensor/onehot_op_test.cc",
500
+ "test": "OneHotOpTest.DefaultAxis_IndicesOutOfRange_NonZeroOffValue"
501
+ },
502
+ "inputs": {
503
+ "indices": { "dtype": "int32", "shape": [4], "data": { "kind": "values", "values": [1, -1, 4, -7] } },
504
+ "depth": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [4] } },
505
+ "values": { "dtype": "int32", "shape": [2], "data": { "kind": "values", "values": [20000001, -20000003] } }
506
+ },
507
+ "outputs": { "output": { "dtype": "int32", "shape": [4, 4], "tolerance": 0 } }
508
+ },
509
+ {
510
+ "name": "ort_axis0_nonzero_off_value_float",
511
+ "provenance": {
512
+ "source": "onnxruntime/test/providers/cpu/tensor/onehot_op_test.cc",
513
+ "test": "OneHotOpTest.Axis_0_NonZeroOffValue",
514
+ "notes": "Pins axis-0 insertion with distinct nonzero off/on values 2 and 3, producing output shape [10,2,3]."
515
+ },
516
+ "attrs": { "axis": 0 },
517
+ "inputs": {
518
+ "indices": { "dtype": "uint32", "shape": [2, 3], "data": { "kind": "values", "values": [1, 9, 8, 2, 4, 6] } },
519
+ "depth": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [10] } },
520
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [2.0, 3.0] } }
521
+ },
522
+ "outputs": { "output": { "dtype": "float32", "shape": [10, 2, 3], "tolerance": 0 } }
523
+ },
524
+ {
525
+ "name": "ort_axis2_nonzero_off_value_float",
526
+ "provenance": {
527
+ "source": "onnxruntime/test/providers/cpu/tensor/onehot_op_test.cc",
528
+ "test": "OneHotOpTest.Axis_2_NonZeroOffValue",
529
+ "notes": "Pins axis-2 insertion with distinct nonzero off/on values 2 and 3, producing output shape [2,3,10]."
530
+ },
531
+ "attrs": { "axis": 2 },
532
+ "inputs": {
533
+ "indices": { "dtype": "uint32", "shape": [2, 3], "data": { "kind": "values", "values": [1, 9, 8, 2, 4, 6] } },
534
+ "depth": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [10] } },
535
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [2.0, 3.0] } }
536
+ },
537
+ "outputs": { "output": { "dtype": "float32", "shape": [2, 3, 10], "tolerance": 0 } }
538
+ },
539
+ {
540
+ "name": "ort_depth_one_all_indices_on",
541
+ "provenance": {
542
+ "source": "onnxruntime/test/providers/cpu/tensor/onehot_op_test.cc",
543
+ "test": "OneHotOpTest.DepthOne"
544
+ },
545
+ "inputs": {
546
+ "indices": { "dtype": "uint32", "shape": [3], "data": { "kind": "values", "values": [0, 0, 0] } },
547
+ "depth": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [1] } },
548
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [-4.0, 9.0] } }
549
+ },
550
+ "outputs": { "output": { "dtype": "float32", "shape": [3, 1], "tolerance": 0 } }
551
+ },
552
+ {
553
+ "name": "ort_axis0_rank2_depth10",
554
+ "provenance": {
555
+ "source": "onnxruntime/test/providers/cpu/tensor/onehot_op_test.cc",
556
+ "test": "OneHotOpTest.Axis_0",
557
+ "notes": "Uses uint32 indices/depth and float32 values in place of ORT's int64 tensors."
558
+ },
559
+ "attrs": { "axis": 0 },
560
+ "inputs": {
561
+ "indices": { "dtype": "uint32", "shape": [2, 3], "data": { "kind": "values", "values": [1, 9, 8, 2, 4, 6] } },
562
+ "depth": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [10] } },
563
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [0.0, 1.0] } }
564
+ },
565
+ "outputs": { "output": { "dtype": "float32", "shape": [10, 2, 3], "tolerance": 0 } }
566
+ },
567
+ {
568
+ "name": "ort_axis2_rank2_depth10",
569
+ "provenance": {
570
+ "source": "onnxruntime/test/providers/cpu/tensor/onehot_op_test.cc",
571
+ "test": "OneHotOpTest.Axis_2",
572
+ "notes": "Uses uint32 indices/depth and float32 values in place of ORT's int64 tensors."
573
+ },
574
+ "attrs": { "axis": 2 },
575
+ "inputs": {
576
+ "indices": { "dtype": "uint32", "shape": [2, 3], "data": { "kind": "values", "values": [1, 9, 8, 2, 4, 6] } },
577
+ "depth": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [10] } },
578
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [0.0, 1.0] } }
579
+ },
580
+ "outputs": { "output": { "dtype": "float32", "shape": [2, 3, 10], "tolerance": 0 } }
581
+ },
582
+ {
583
+ "name": "ort_axis1_nonzero_off_value_float",
584
+ "provenance": {
585
+ "source": "onnxruntime/test/providers/cpu/tensor/onehot_op_test.cc",
586
+ "test": "OneHotOpTest.Axis_1_NonZeroOffValue",
587
+ "notes": "Uses uint32 indices/depth and float32 values in place of ORT's int64 tensors."
588
+ },
589
+ "attrs": { "axis": 1 },
590
+ "inputs": {
591
+ "indices": { "dtype": "uint32", "shape": [2, 3], "data": { "kind": "values", "values": [1, 9, 8, 2, 4, 6] } },
592
+ "depth": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [10] } },
593
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [2.0, 3.0] } }
594
+ },
595
+ "outputs": { "output": { "dtype": "float32", "shape": [2, 10, 3], "tolerance": 0 } }
596
+ },
597
+ {
598
+ "name": "ort_negative_axis_nondefault_nonzero_off_value_float",
599
+ "provenance": {
600
+ "source": "onnxruntime/test/providers/cpu/tensor/onehot_op_test.cc",
601
+ "test": "OneHotOpTest.Axis_Negative_NonDefault_NonZeroOffValue",
602
+ "notes": "Uses uint32 indices/depth and float32 values in place of ORT's int64 tensors."
603
+ },
604
+ "attrs": { "axis": -3 },
605
+ "inputs": {
606
+ "indices": { "dtype": "uint32", "shape": [2, 3], "data": { "kind": "values", "values": [1, 9, 8, 2, 4, 6] } },
607
+ "depth": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [10] } },
608
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [2.0, 3.0] } }
609
+ },
610
+ "outputs": { "output": { "dtype": "float32", "shape": [10, 2, 3], "tolerance": 0 } }
611
+ },
612
+ {
613
+ "name": "ort_negative_axis_negative_index_nonzero_off_value",
614
+ "provenance": {
615
+ "source": "onnxruntime/test/providers/cpu/tensor/onehot_op_test.cc",
616
+ "test": "OneHotOpTest.Axis_Negative_NegIndex_NonDefault_NonZeroOffValue",
617
+ "notes": "Uses int32 indices/depth and float32 values in place of ORT's int64 tensors."
618
+ },
619
+ "attrs": { "axis": -3 },
620
+ "inputs": {
621
+ "indices": { "dtype": "int32", "shape": [2, 3], "data": { "kind": "values", "values": [1, -1, 8, 2, 4, 6] } },
622
+ "depth": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [10] } },
623
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [2.0, 3.0] } }
624
+ },
625
+ "outputs": { "output": { "dtype": "float32", "shape": [10, 2, 3], "tolerance": 0 } }
626
+ },
627
+ {
628
+ "name": "ort_default_axis_indices_out_of_range_zero_off",
629
+ "provenance": {
630
+ "source": "onnxruntime/test/providers/cpu/tensor/onehot_op_test.cc",
631
+ "test": "OneHotOpTest.DefaultAxis_IndicesOutOfRange",
632
+ "notes": "Uses int32 indices/depth and float32 values in place of ORT's int64 tensors."
633
+ },
634
+ "attrs": { "axis": -1 },
635
+ "inputs": {
636
+ "indices": { "dtype": "int32", "shape": [2, 3], "data": { "kind": "values", "values": [1, -1, 8, 13, 4, -12] } },
637
+ "depth": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [10] } },
638
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [0.0, 1.0] } }
639
+ },
640
+ "outputs": { "output": { "dtype": "float32", "shape": [2, 3, 10], "tolerance": 0 } }
641
+ },
642
+ {
643
+ "name": "ort_default_axis_int32_f16_nonzero_off_value",
644
+ "provenance": {
645
+ "source": "onnxruntime/test/providers/cpu/tensor/onehot_op_test.cc",
646
+ "test": "OneHotOpTest.DefaultAxis_int32_MLFloat16_int32_NonZeroOffValue"
647
+ },
648
+ "attrs": { "axis": -1 },
649
+ "inputs": {
650
+ "indices": { "dtype": "int32", "shape": [2, 3], "data": { "kind": "values", "values": [1, 9, 8, 2, 4, 6] } },
651
+ "depth": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [10] } },
652
+ "values": { "dtype": "float16", "shape": [2], "data": { "kind": "values", "values": [2.0, 3.0] } }
653
+ },
654
+ "outputs": {
655
+ "output": {
656
+ "dtype": "float16",
657
+ "shape": [2, 3, 10],
658
+ "tolerance": 0,
659
+ "data": {
660
+ "kind": "values",
661
+ "values": [2.0, 3.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 3.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 3.0, 2.0, 2.0, 2.0, 3.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 3.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 3.0, 2.0, 2.0, 2.0]
662
+ }
663
+ }
664
+ }
665
+ },
666
+ {
667
+ "name": "f16_last_axis_vec4_depth8",
668
+ "provenance": {
669
+ "notes": "f16 OneHot with a depth divisible by 4 selects last_axis_vec4 with usesF16=true (a vec4<f16> 64-bit store). Every existing f16 case has depth 3 or 10 (not %4) and routes to the scalar generic_axis kernel, so the vec4<f16> store branch is entirely untested. A real f16 embedding/classification one-hot over a %4 vocab hits this path."
670
+ },
671
+ "attrs": { "axis": -1 },
672
+ "inputs": {
673
+ "indices": { "dtype": "uint32", "shape": [3], "data": { "kind": "values", "values": [0, 5, 7] } },
674
+ "depth": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [8] } },
675
+ "values": { "dtype": "float16", "shape": [2], "data": { "kind": "values", "values": [-1.0, 2.0] } }
676
+ },
677
+ "outputs": { "output": { "dtype": "float16", "shape": [3, 8], "tolerance": 0.001 } }
678
+ },
679
+ {
680
+ "name": "uint32_values_last_axis_vec4_extremes",
681
+ "provenance": {
682
+ "notes": "Standard ONNX uint32 payload coverage. Values above float32's exact-integer range ensure the values/output path remains integer-native while the depth-last vec4 route fills and scatters."
683
+ },
684
+ "attrs": { "axis": -1 },
685
+ "inputs": {
686
+ "indices": { "dtype": "uint32", "shape": [3], "data": { "kind": "values", "values": [0, 3, 7] } },
687
+ "depth": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [4] } },
688
+ "values": { "dtype": "uint32", "shape": [2], "data": { "kind": "values", "values": [4294967295, 2147483649] } }
689
+ },
690
+ "outputs": {
691
+ "output": {
692
+ "dtype": "uint32",
693
+ "shape": [3, 4],
694
+ "tolerance": 0,
695
+ "data": {
696
+ "kind": "values",
697
+ "values": [2147483649, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 2147483649, 4294967295, 4294967295, 4294967295, 4294967295]
698
+ }
699
+ }
700
+ }
701
+ },
702
+ {
703
+ "name": "float_indices_last_axis_vec4_depth8",
704
+ "provenance": {
705
+ "notes": "Float32 indices with a depth divisible by 4 select last_axis_vec4 with floatIndices=true (i32(trunc(raw)) + negative-wrap, then a vec4 store). Every existing float-index case has depth 10 (not %4) and routes to generic_axis, so the floatIndices branch of the vec4 kernel is untested. ONNX permits numeric indices (cast to int); a negative float index exercises the truncation+wrap."
706
+ },
707
+ "attrs": { "axis": -1 },
708
+ "inputs": {
709
+ "indices": { "dtype": "float32", "shape": [4], "data": { "kind": "values", "values": [0.0, 6.9, -1.0, 11.0] } },
710
+ "depth": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [8.0] } },
711
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [0.0, 1.0] } }
712
+ },
713
+ "outputs": { "output": { "dtype": "float32", "shape": [4, 8], "tolerance": 0 } }
714
+ },
715
+ {
716
+ "name": "f16_vocab256_default_axis",
717
+ "provenance": {
718
+ "notes": "Realistic f16 one-hot over a 256-wide vocab (depth %4) routed through last_axis_vec4 usesF16. Larger %4 depth than the depth8 case so several vec4 lanes are all-off before the on-lane, exercising the vec4 fill + single-lane scatter at a model-realistic width."
719
+ },
720
+ "attrs": { "axis": -1 },
721
+ "inputs": {
722
+ "indices": { "dtype": "uint32", "shape": [5], "data": { "kind": "values", "values": [0, 1, 200, 255, 137] } },
723
+ "depth": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [256] } },
724
+ "values": { "dtype": "float16", "shape": [2], "data": { "kind": "values", "values": [0.0, 1.0] } }
725
+ },
726
+ "outputs": { "output": { "dtype": "float16", "shape": [5, 256], "tolerance": 0.001 } }
727
+ },
728
+ {
729
+ "name": "int32_indices_last_axis_vec4_depth8_negwrap",
730
+ "provenance": {
731
+ "notes": "int32 indices with depth %4 select last_axis_vec4 usesI32 (negative-wrap + bounds). Covers the vec4 i32 branch with a model-realistic %4 depth and a negative index that must wrap to a valid slot plus an out-of-range index that must stay all-off."
732
+ },
733
+ "attrs": { "axis": -1 },
734
+ "inputs": {
735
+ "indices": { "dtype": "int32", "shape": [4], "data": { "kind": "values", "values": [0, -1, 3, 99] } },
736
+ "depth": { "dtype": "int32", "shape": [1], "data": { "kind": "values", "values": [8] } },
737
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [0.0, 1.0] } }
738
+ },
739
+ "outputs": { "output": { "dtype": "float32", "shape": [4, 8], "tolerance": 0 } }
740
+ },
741
+ {
742
+ "name": "empty_output_last_axis_vec4_depth8",
743
+ "attrs": { "axis": -1 },
744
+ "inputs": {
745
+ "indices": { "dtype": "uint32", "shape": [0], "data": { "kind": "values", "values": [] } },
746
+ "depth": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [8] } },
747
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [0.0, 1.0] } }
748
+ },
749
+ "outputs": { "output": { "dtype": "float32", "shape": [0, 8], "tolerance": 0 } }
750
+ },
751
+ {
752
+ "name": "vec4_uint32_on_slot_last_lane_and_oob_depth8",
753
+ "attrs": { "axis": -1 },
754
+ "inputs": {
755
+ "indices": { "dtype": "uint32", "shape": [4], "data": { "kind": "values", "values": [7, 8, 100, 4] } },
756
+ "depth": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [8] } },
757
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [-5.0, 9.0] } }
758
+ },
759
+ "outputs": { "output": { "dtype": "float32", "shape": [4, 8], "tolerance": 0 } }
760
+ },
761
+ {
762
+ "name": "generic_float_indices_middle_axis_negwrap",
763
+ "attrs": { "axis": 1 },
764
+ "inputs": {
765
+ "indices": {
766
+ "dtype": "float32",
767
+ "shape": [2, 3],
768
+ "data": { "kind": "values", "values": [0.0, 6.9, -1.0, 3.0, 10.0, 2.5] }
769
+ },
770
+ "depth": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [7.0] } },
771
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [2.0, 3.0] } }
772
+ },
773
+ "outputs": { "output": { "dtype": "float32", "shape": [2, 7, 3], "tolerance": 0 } }
774
+ },
775
+ {
776
+ "name": "rank7_indices_axis0_output_rank8",
777
+ "attrs": { "axis": 0 },
778
+ "inputs": {
779
+ "indices": {
780
+ "dtype": "uint32",
781
+ "shape": [1, 2, 1, 2, 1, 2, 2],
782
+ "data": { "kind": "cycle", "values": [0, 3, 1, 2] }
783
+ },
784
+ "depth": { "dtype": "uint32", "shape": [1], "data": { "kind": "values", "values": [4] } },
785
+ "values": { "dtype": "float32", "shape": [2], "data": { "kind": "values", "values": [0.0, 1.0] } }
786
+ },
787
+ "outputs": { "output": { "dtype": "float32", "shape": [4, 1, 2, 1, 2, 1, 2, 2], "tolerance": 0.000001 } }
788
+ }
789
+ ]
790
+ }