Xenova HF Staff commited on
Commit
e9fc83c
·
verified ·
1 Parent(s): 0877677

sync 2e7068faf55e

Browse files
README.md CHANGED
@@ -1,3 +1,74 @@
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.GridSample
10
+
11
+ `ai.onnx` · standard ONNX operator · ONNX opset ≥ 20
12
+
13
+ ## Description
14
+
15
+ Samples values from input tensor `X` at positions defined by a flow-field `grid`, producing output `Y` with spatial dimensions taken from `grid`. Grid coordinates are normalized to `[-1, 1]` over the input spatial extent; positions outside this range are handled according to `padding_mode`. Supports spatial `(rank-4, NCHW)` and volumetric `(rank-5, NCDHW)` inputs with `linear`, `nearest`, or `cubic` interpolation.
16
+
17
+ See the [ONNX `GridSample` spec](https://onnx.ai/onnx/operators/onnx__GridSample.html) for the reference semantics.
18
+
19
+ ## Inputs
20
+
21
+ | Name | Bind key | Logical dtype | Rank | Shape | Description | Presence |
22
+ | --- | --- | --- | --- | --- | --- | --- |
23
+ | `X` | `x` | `T` | — | — | Input tensor of shape `(N, C, D1, ..., Dr)` whose values are sampled. | required |
24
+ | `grid` | `grid` | `T` | — | — | Flow-field of shape `(N, D1_out, ..., Dr_out, r)` with normalized sampling coordinates in `[-1, 1]`. | required |
25
+
26
+ ## Outputs
27
+
28
+ | Name | Bind key | Logical dtype | Rank | Shape | Description | Presence |
29
+ | --- | --- | --- | --- | --- | --- | --- |
30
+ | `Y` | `y` | `T` | same as `grid` | derived; see description | Output tensor of shape `(N, C, D1_out, ..., Dr_out)` containing the interpolated samples. | required |
31
+
32
+ ## Attributes
33
+
34
+ Default values (overridable per request):
35
+
36
+ | Attribute | Default | Description |
37
+ | --- | --- | --- |
38
+ | `mode` | `"linear"` | Interpolation method: `linear` (bilinear or trilinear, depending on rank), `nearest`, or `cubic`. Cubic interpolation is supported for rank-4 (2-D spatial) inputs. |
39
+ | `padding_mode` | `"zeros"` | How out-of-bound grid positions are handled: `zeros` pads with 0, `border` clamps to the border value, or `reflection` reflects coordinates back into the valid range. |
40
+ | `align_corners` | `0` | When 1, extrema values `-1` and `1` map to the center of the corner pixels; when 0 (default) they map to the outer edge of corner pixels, making sampling resolution-agnostic. |
41
+
42
+ ## Type constraints
43
+
44
+ | Variable | Allowed dtypes |
45
+ | --- | --- |
46
+ | `T` | `float32`, `float16` |
47
+
48
+ ## Files
49
+
50
+ - [`metadata.json`](build/webgpu/metadata.json) — kernel metadata (id, digests, provenance)
51
+ - [`manifest.json`](build/webgpu/manifest.json) — the op contract (source of truth)
52
+ - [`test.json`](build/webgpu/test.json) — correctness cases
53
+ - [`bench.json`](build/webgpu/bench.json) — benchmark + tuning cases
54
+ - [`grid-sample.wgsl.jinja`](build/webgpu/grid-sample.wgsl.jinja)
55
+ - [`grid-sample3d.wgsl.jinja`](build/webgpu/grid-sample3d.wgsl.jinja)
56
+
57
+ ## Use with `@huggingface/kernels`
58
+
59
+ The loader derives every required output's shape and logical dtype from the manifest contract and this call.
60
+ It then allocates the result tensors automatically.
61
+
62
+ The `version: 1` option selects the published kernel contract; it is independent of any operator opset, contrib `since_version`, or model version.
63
+
64
+ Replace each `*Data` placeholder with a typed array containing the corresponding input data.
65
+
66
+ ```js
67
+ import { getKernel } from "@huggingface/kernels";
68
+
69
+ const kernel = await getKernel("webgpu-kernels/ai.onnx.GridSample", { version: 1 });
70
+ const { y } = await kernel({
71
+ x: { data: xData, shape: [1, 1, 2, 2] },
72
+ grid: { data: gridData, shape: [1, 1, 3, 2] },
73
+ });
74
+ ```
build/webgpu/bench.json ADDED
@@ -0,0 +1,132 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "op": "ai.onnx.GridSample",
3
+ "cases": [
4
+ {
5
+ "name": "1x3x256x256_to_256_linear",
6
+ "attrs": { "mode": "linear", "padding_mode": "zeros", "align_corners": 0 },
7
+ "inputs": {
8
+ "x": { "dtype": "float32", "shape": [1, 3, 256, 256] },
9
+ "grid": { "dtype": "float32", "shape": [1, 256, 256, 2] }
10
+ },
11
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 3, 256, 256] } }
12
+ },
13
+ {
14
+ "name": "nchw_1x32x256x256_linear_zeros_f32_healthy",
15
+ "preset": "smoke",
16
+ "attrs": { "mode": "linear", "padding_mode": "zeros", "align_corners": 0 },
17
+ "inputs": {
18
+ "x": { "dtype": "float32", "shape": [1, 32, 256, 256], "dist": "normal", "seed": 811, "scale": 1 },
19
+ "grid": { "dtype": "float32", "shape": [1, 256, 256, 2], "dist": "normal", "seed": 812, "scale": 1 }
20
+ },
21
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 32, 256, 256] } },
22
+ "bench": {
23
+ "primary": true,
24
+ "metrics": [{ "type": "bandwidth", "value": "(numel(shapes.x) + numel(shapes.grid) + numel(shapes.y)) * 4" }]
25
+ }
26
+ },
27
+ {
28
+ "name": "nchw_1x32x256x256_cubic_zeros_f32_16reads_pathology",
29
+ "preset": "smoke",
30
+ "attrs": { "mode": "cubic", "padding_mode": "zeros", "align_corners": 0 },
31
+ "inputs": {
32
+ "x": { "dtype": "float32", "shape": [1, 32, 256, 256], "dist": "normal", "seed": 821, "scale": 1 },
33
+ "grid": { "dtype": "float32", "shape": [1, 256, 256, 2], "dist": "normal", "seed": 822, "scale": 1 }
34
+ },
35
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 32, 256, 256] } },
36
+ "bench": {
37
+ "metrics": [{ "type": "bandwidth", "value": "(numel(shapes.x) + numel(shapes.grid) + numel(shapes.y)) * 4" }]
38
+ }
39
+ },
40
+ {
41
+ "name": "nchw_1x32x256x256_linear_reflection_f32_reflectcoord_pathology",
42
+ "preset": "smoke",
43
+ "attrs": { "mode": "linear", "padding_mode": "reflection", "align_corners": 1 },
44
+ "inputs": {
45
+ "x": { "dtype": "float32", "shape": [1, 32, 256, 256], "dist": "normal", "seed": 831, "scale": 1 },
46
+ "grid": { "dtype": "float32", "shape": [1, 256, 256, 2], "dist": "normal", "seed": 832, "scale": 1.5 }
47
+ },
48
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 32, 256, 256] } },
49
+ "bench": {
50
+ "metrics": [{ "type": "bandwidth", "value": "(numel(shapes.x) + numel(shapes.grid) + numel(shapes.y)) * 4" }]
51
+ }
52
+ },
53
+ {
54
+ "name": "nchw_1x32x256x256_linear_zeros_f16_halfbandwidth_pathology",
55
+ "preset": "smoke",
56
+ "attrs": { "mode": "linear", "padding_mode": "zeros", "align_corners": 0 },
57
+ "inputs": {
58
+ "x": { "dtype": "float16", "shape": [1, 32, 256, 256], "dist": "normal", "seed": 841, "scale": 1 },
59
+ "grid": { "dtype": "float16", "shape": [1, 256, 256, 2], "dist": "normal", "seed": 842, "scale": 1 }
60
+ },
61
+ "outputs": { "y": { "dtype": "float16", "shape": [1, 32, 256, 256] } },
62
+ "bench": {
63
+ "metrics": [{ "type": "bandwidth", "value": "(numel(shapes.x) + numel(shapes.grid) + numel(shapes.y)) * 2" }]
64
+ }
65
+ },
66
+ {
67
+ "name": "ncdhw_1x4x16x32x32_linear_zeros_f32_volumetric_unbenched_variant",
68
+ "preset": "smoke",
69
+ "attrs": { "mode": "linear", "padding_mode": "zeros", "align_corners": 0 },
70
+ "inputs": {
71
+ "x": { "dtype": "float32", "shape": [1, 4, 16, 32, 32], "dist": "normal", "seed": 851, "scale": 1 },
72
+ "grid": { "dtype": "float32", "shape": [1, 16, 32, 32, 3], "dist": "normal", "seed": 852, "scale": 1 }
73
+ },
74
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 4, 16, 32, 32] } },
75
+ "bench": {
76
+ "metrics": [{ "type": "bandwidth", "value": "(numel(shapes.x) + numel(shapes.grid) + numel(shapes.y)) * 4" }]
77
+ }
78
+ },
79
+ {
80
+ "name": "nchw_1x8x1024x1024_linear_zeros_f32_dispatch_cliff_over16m",
81
+ "preset": "smoke",
82
+ "attrs": { "mode": "linear", "padding_mode": "zeros", "align_corners": 0 },
83
+ "inputs": {
84
+ "x": { "dtype": "float32", "shape": [1, 8, 256, 256], "dist": "normal", "seed": 861, "scale": 1 },
85
+ "grid": { "dtype": "float32", "shape": [1, 1024, 1024, 2], "dist": "normal", "seed": 862, "scale": 1 }
86
+ },
87
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 8, 1024, 1024] } },
88
+ "bench": {
89
+ "metrics": [{ "type": "bandwidth", "value": "(numel(shapes.x) + numel(shapes.grid) + numel(shapes.y)) * 4" }]
90
+ }
91
+ },
92
+ {
93
+ "name": "nchw_1x3x2049x2731_linear_zeros_f32_partial_channel_dispatch_cliff",
94
+ "preset": "stress",
95
+ "attrs": { "mode": "linear", "padding_mode": "zeros", "align_corners": 0 },
96
+ "inputs": {
97
+ "x": { "dtype": "float32", "shape": [1, 3, 16, 16], "dist": "normal", "seed": 863, "scale": 1 },
98
+ "grid": { "dtype": "float32", "shape": [1, 2049, 2731, 2], "dist": "normal", "seed": 864, "scale": 0.9 }
99
+ },
100
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 3, 2049, 2731] } },
101
+ "bench": {
102
+ "metrics": [{ "type": "bandwidth", "value": "(numel(shapes.x) + numel(shapes.grid) + numel(shapes.y)) * 4" }]
103
+ }
104
+ },
105
+ {
106
+ "name": "nchw_cubic_reflection_highC_f32_perchannel_recompute_amp",
107
+ "preset": "stress",
108
+ "attrs": { "mode": "cubic", "padding_mode": "reflection", "align_corners": 0 },
109
+ "inputs": {
110
+ "x": { "dtype": "float32", "shape": [1, 48, 192, 192], "dist": "normal", "seed": 9101, "scale": 1 },
111
+ "grid": { "dtype": "float32", "shape": [1, 320, 320, 2], "dist": "normal", "seed": 9102, "scale": 1.5 }
112
+ },
113
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 48, 320, 320] } },
114
+ "bench": {
115
+ "metrics": [{ "type": "bandwidth", "value": "(numel(shapes.x) + numel(shapes.grid) + numel(shapes.y)) * 4" }]
116
+ }
117
+ },
118
+ {
119
+ "name": "ncdhw_linear_reflection_f32_trilinear_reflect_amp",
120
+ "preset": "stress",
121
+ "attrs": { "mode": "linear", "padding_mode": "reflection", "align_corners": 0 },
122
+ "inputs": {
123
+ "x": { "dtype": "float32", "shape": [1, 8, 24, 32, 32], "dist": "normal", "seed": 9201, "scale": 1 },
124
+ "grid": { "dtype": "float32", "shape": [1, 48, 48, 48, 3], "dist": "normal", "seed": 9202, "scale": 1.5 }
125
+ },
126
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 8, 48, 48, 48] } },
127
+ "bench": {
128
+ "metrics": [{ "type": "bandwidth", "value": "(numel(shapes.x) + numel(shapes.grid) + numel(shapes.y)) * 4" }]
129
+ }
130
+ }
131
+ ]
132
+ }
build/webgpu/grid-sample.wgsl.jinja ADDED
@@ -0,0 +1,342 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ fn denormalize(n: f32, length: u32) -> f32 {
40
+ {% if source.alignCorners %}
41
+ return (n + 1.0) * 0.5 * f32(length - 1u);
42
+ {% else %}
43
+ return ((n + 1.0) * f32(length) - 1.0) * 0.5;
44
+ {% endif %}
45
+ }
46
+
47
+ fn sanitize_coord(v: f32) -> f32 {
48
+ if (!(v >= -2147483000.0 && v <= 2147483000.0)) {
49
+ {% if source.alignCorners %}
50
+ return 0.0;
51
+ {% else %}
52
+ return -0.5;
53
+ {% endif %}
54
+ }
55
+ return v;
56
+ }
57
+ {% if source.paddingMode == "reflection" %}
58
+
59
+ fn reflect_coord(v: f32, lo: f32, hi: f32) -> f32 {
60
+ let range = hi - lo;
61
+ if (range == 0.0) { return lo; }
62
+ var x0 = v;
63
+ if (x0 < lo) {
64
+ let d = lo - x0;
65
+ if (d / range > 2147483000.0) { return lo; }
66
+ let n = i32(floor(d / range));
67
+ let r = d - f32(n) * range;
68
+ x0 = select(hi - r, lo + r, n % 2 == 0);
69
+ } else if (x0 > hi) {
70
+ let d = x0 - hi;
71
+ if (d / range > 2147483000.0) { return hi; }
72
+ let n = i32(floor(d / range));
73
+ let r = d - f32(n) * range;
74
+ x0 = select(lo + r, hi - r, n % 2 == 0);
75
+ }
76
+ return x0;
77
+ }
78
+
79
+ {% endif %}
80
+ {% if source.mode != "nearest" %}
81
+ fn sample_floor(v: f32) -> i32 {
82
+ if (v > 2147483000.0) {
83
+ {% if source.paddingMode == "reflection" %}
84
+ return 0;
85
+ {% else %}
86
+ return 2147483000;
87
+ {% endif %}
88
+ }
89
+ if (v < -2147483000.0) {
90
+ {% if source.paddingMode == "reflection" %}
91
+ return 0;
92
+ {% else %}
93
+ return -2147483000;
94
+ {% endif %}
95
+ }
96
+ return i32(floor(v));
97
+ }
98
+ {%- else %}
99
+ fn sample_round(v: f32) -> i32 {
100
+ if (v > 2147483000.0) {
101
+ {% if source.paddingMode == "reflection" %}
102
+ return 0;
103
+ {% else %}
104
+ return 2147483000;
105
+ {% endif %}
106
+ }
107
+ if (v < -2147483000.0) {
108
+ {% if source.paddingMode == "reflection" %}
109
+ return 0;
110
+ {% else %}
111
+ return -2147483000;
112
+ {% endif %}
113
+ }
114
+ return i32(round(v));
115
+ }
116
+ {%- endif %}
117
+
118
+
119
+ {% if source.mode == "cubic" %}
120
+ fn cubic_coeffs(t: f32) -> vec4<f32> {
121
+ let a = -0.75;
122
+ let x0 = abs(t + 1.0);
123
+ let x1 = abs(t);
124
+ let x2 = abs(1.0 - t);
125
+ let x3 = abs(2.0 - t);
126
+ return vec4<f32>(cubic_one(x0, a), cubic_one(x1, a), cubic_one(x2, a), cubic_one(x3, a));
127
+ }
128
+
129
+ fn cubic_one(x0: f32, a: f32) -> f32 {
130
+ if (x0 <= 1.0) { return (a + 2.0) * x0 * x0 * x0 - (a + 3.0) * x0 * x0 + 1.0; }
131
+ if (x0 < 2.0) { return a * x0 * x0 * x0 - 5.0 * a * x0 * x0 + 8.0 * a * x0 - 4.0 * a; }
132
+ return 0.0;
133
+ }
134
+
135
+ {% endif -%}
136
+ {% if source.channelWidth is not defined %}
137
+ fn pixel(base: u32, h: i32, w: i32) -> f32 {
138
+ {% if source.paddingMode == "zeros" %}
139
+ if (h < 0 || h >= i32(params.inH) || w < 0 || w >= i32(params.inW)) { return 0.0; }
140
+ let hh = u32(h);
141
+ let ww = u32(w);
142
+ {% elif source.paddingMode == "border" %}
143
+ let hh = u32(clamp(h, 0, i32(params.inH) - 1));
144
+ let ww = u32(clamp(w, 0, i32(params.inW) - 1));
145
+ {% else %}
146
+ {% if source.alignCorners %}
147
+ let rh = i32(reflect_coord(f32(h), 0.0, f32(params.inH) - 1.0));
148
+ let rw = i32(reflect_coord(f32(w), 0.0, f32(params.inW) - 1.0));
149
+ {% else %}
150
+ let rh = i32(reflect_coord(f32(h), -0.5, f32(params.inH) - 0.5));
151
+ let rw = i32(reflect_coord(f32(w), -0.5, f32(params.inW) - 0.5));
152
+ {% endif %}
153
+ let hh = u32(clamp(rh, 0, i32(params.inH) - 1));
154
+ let ww = u32(clamp(rw, 0, i32(params.inW) - 1));
155
+ {% endif %}
156
+ return f32(x[base + hh * params.inW + ww]);
157
+ }
158
+
159
+
160
+ {% endif %}
161
+ {% if source.channelWidth is defined %}
162
+ {% set channelVec = "vec" ~ source.channelWidth ~ "<f32>" %}
163
+ {% set components = ["x", "y", "z", "w"] %}
164
+ // A block of NCHW channels shares one grid coordinate. Tail lanes alias the
165
+ // final channel safely because main suppresses their stores.
166
+ {% if source.paddingMode != "reflection" or source.mode == "nearest" %}
167
+ fn pixel_channels(n: u32, c0: u32, h: i32, w: i32) -> {{ channelVec }} {
168
+ {% if source.paddingMode == "zeros" %}
169
+ if (h < 0 || h >= i32(params.inH) || w < 0 || w >= i32(params.inW)) { return {{ channelVec }}(0.0); }
170
+ let hh = u32(h);
171
+ let ww = u32(w);
172
+ {% elif source.paddingMode == "border" %}
173
+ let hh = u32(clamp(h, 0, i32(params.inH) - 1));
174
+ let ww = u32(clamp(w, 0, i32(params.inW) - 1));
175
+ {% else %}
176
+ {% if source.alignCorners %}
177
+ let rh = i32(reflect_coord(f32(h), 0.0, f32(params.inH) - 1.0));
178
+ let rw = i32(reflect_coord(f32(w), 0.0, f32(params.inW) - 1.0));
179
+ {% else %}
180
+ let rh = i32(reflect_coord(f32(h), -0.5, f32(params.inH) - 0.5));
181
+ let rw = i32(reflect_coord(f32(w), -0.5, f32(params.inW) - 0.5));
182
+ {% endif %}
183
+ let hh = u32(clamp(rh, 0, i32(params.inH) - 1));
184
+ let ww = u32(clamp(rw, 0, i32(params.inW) - 1));
185
+ {% endif %}
186
+ let plane = params.inH * params.inW;
187
+ let offset = hh * params.inW + ww;
188
+ let nb = n * params.C;
189
+ return {{ channelVec }}(
190
+ {% for lane in range(source.channelWidth) %}
191
+ f32(x[(nb + {% if source.channelTail %}min(c0 + {{ lane }}u, params.C - 1u){% else %}c0 + {{ lane }}u{% endif %}) * plane + offset]){% if not loop.last %},{% else %});{% endif %}
192
+ {% endfor %}
193
+ }
194
+
195
+ {% endif %}
196
+ {% if source.paddingMode == "reflection" %}
197
+ // Reflection gives every tap in one row or column the same resolved coordinate.
198
+ // Resolve each row and column once in main and reuse it for all channel loads.
199
+ {% if source.mode != "nearest" %}
200
+ fn pixel_channels_resolved(n: u32, c0: u32, h: u32, w: u32) -> {{ channelVec }} {
201
+ let plane = params.inH * params.inW;
202
+ let offset = h * params.inW + w;
203
+ let nb = n * params.C;
204
+ return {{ channelVec }}(
205
+ {% for lane in range(source.channelWidth) %}
206
+ f32(x[(nb + {% if source.channelTail %}min(c0 + {{ lane }}u, params.C - 1u){% else %}c0 + {{ lane }}u{% endif %}) * plane + offset]){% if not loop.last %},{% else %});{% endif %}
207
+ {% endfor %}
208
+ }
209
+
210
+ {% endif %}
211
+ {% else %}
212
+
213
+ {% endif %}
214
+ {% endif -%}
215
+ @compute @workgroup_size({{ tunables.WORKGROUP_SIZE }})
216
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>, @builtin(num_workgroups) nwg: vec3<u32>) {
217
+ {{ flat_index_2d("i", "") }}
218
+ {% if source.channelWidth is defined %}
219
+ let out_plane = params.outH * params.outW;
220
+ let channel_blocks = (params.C + {{ source.channelWidth - 1 }}u) / {{ source.channelWidth }}u;
221
+ let block_count = (params.count / params.C) * channel_blocks;
222
+ if (i >= block_count) { return; }
223
+ let spatial = i % out_plane;
224
+ let cb = (i / out_plane) % channel_blocks;
225
+ let n = i / (out_plane * channel_blocks);
226
+ let c = cb * {{ source.channelWidth }}u;
227
+ let grid_base = (n * out_plane + spatial) * 2u;
228
+ let sx = sanitize_coord(denormalize(f32(grid[grid_base]), params.inW));
229
+ let sy = sanitize_coord(denormalize(f32(grid[grid_base + 1u]), params.inH));
230
+ {% if source.mode == "nearest" %}
231
+ let result = pixel_channels(n, c, sample_round(sy), sample_round(sx));
232
+ {% elif source.mode == "cubic" %}
233
+ let x0 = sample_floor(sx) - 1;
234
+ let y0 = sample_floor(sy) - 1;
235
+ let dx = sx - f32(x0 + 1);
236
+ let dy = sy - f32(y0 + 1);
237
+ let cx = cubic_coeffs(dx);
238
+ let cy = cubic_coeffs(dy);
239
+ {% if source.paddingMode == "reflection" %}
240
+ var reflected_y: array<u32, 4>;
241
+ var reflected_x: array<u32, 4>;
242
+ for (var k = 0u; k < 4u; k = k + 1u) {
243
+ {% if source.alignCorners %}
244
+ reflected_y[k] = u32(clamp(i32(reflect_coord(f32(y0 + i32(k)), 0.0, f32(params.inH) - 1.0)), 0, i32(params.inH) - 1));
245
+ reflected_x[k] = u32(clamp(i32(reflect_coord(f32(x0 + i32(k)), 0.0, f32(params.inW) - 1.0)), 0, i32(params.inW) - 1));
246
+ {% else %}
247
+ reflected_y[k] = u32(clamp(i32(reflect_coord(f32(y0 + i32(k)), -0.5, f32(params.inH) - 0.5)), 0, i32(params.inH) - 1));
248
+ reflected_x[k] = u32(clamp(i32(reflect_coord(f32(x0 + i32(k)), -0.5, f32(params.inW) - 0.5)), 0, i32(params.inW) - 1));
249
+ {% endif %}
250
+ }
251
+ {% endif %}
252
+ var result = {{ channelVec }}(0.0);
253
+ for (var r = 0i; r < 4i; r = r + 1i) {
254
+ {% if source.paddingMode == "reflection" %}
255
+ let row = cx.x * pixel_channels_resolved(n, c, reflected_y[u32(r)], reflected_x[0])
256
+ + cx.y * pixel_channels_resolved(n, c, reflected_y[u32(r)], reflected_x[1])
257
+ + cx.z * pixel_channels_resolved(n, c, reflected_y[u32(r)], reflected_x[2])
258
+ + cx.w * pixel_channels_resolved(n, c, reflected_y[u32(r)], reflected_x[3]);
259
+ {% else %}
260
+ let row = cx.x * pixel_channels(n, c, y0 + r, x0)
261
+ + cx.y * pixel_channels(n, c, y0 + r, x0 + 1)
262
+ + cx.z * pixel_channels(n, c, y0 + r, x0 + 2)
263
+ + cx.w * pixel_channels(n, c, y0 + r, x0 + 3);
264
+ {% endif %}
265
+ result = result + cy[u32(r)] * row;
266
+ }
267
+ {% else %}
268
+ let x0 = sample_floor(sx);
269
+ let y0 = sample_floor(sy);
270
+ let wx = sx - f32(x0);
271
+ let wy = sy - f32(y0);
272
+ {% if source.paddingMode == "reflection" %}
273
+ {% if source.alignCorners %}
274
+ let reflected_y0 = u32(clamp(i32(reflect_coord(f32(y0), 0.0, f32(params.inH) - 1.0)), 0, i32(params.inH) - 1));
275
+ let reflected_y1 = u32(clamp(i32(reflect_coord(f32(y0 + 1), 0.0, f32(params.inH) - 1.0)), 0, i32(params.inH) - 1));
276
+ let reflected_x0 = u32(clamp(i32(reflect_coord(f32(x0), 0.0, f32(params.inW) - 1.0)), 0, i32(params.inW) - 1));
277
+ let reflected_x1 = u32(clamp(i32(reflect_coord(f32(x0 + 1), 0.0, f32(params.inW) - 1.0)), 0, i32(params.inW) - 1));
278
+ {% else %}
279
+ let reflected_y0 = u32(clamp(i32(reflect_coord(f32(y0), -0.5, f32(params.inH) - 0.5)), 0, i32(params.inH) - 1));
280
+ let reflected_y1 = u32(clamp(i32(reflect_coord(f32(y0 + 1), -0.5, f32(params.inH) - 0.5)), 0, i32(params.inH) - 1));
281
+ let reflected_x0 = u32(clamp(i32(reflect_coord(f32(x0), -0.5, f32(params.inW) - 0.5)), 0, i32(params.inW) - 1));
282
+ let reflected_x1 = u32(clamp(i32(reflect_coord(f32(x0 + 1), -0.5, f32(params.inW) - 0.5)), 0, i32(params.inW) - 1));
283
+ {% endif %}
284
+ let v00 = pixel_channels_resolved(n, c, reflected_y0, reflected_x0);
285
+ let v01 = pixel_channels_resolved(n, c, reflected_y0, reflected_x1);
286
+ let v10 = pixel_channels_resolved(n, c, reflected_y1, reflected_x0);
287
+ let v11 = pixel_channels_resolved(n, c, reflected_y1, reflected_x1);
288
+ {% else %}
289
+ let v00 = pixel_channels(n, c, y0, x0);
290
+ let v01 = pixel_channels(n, c, y0, x0 + 1);
291
+ let v10 = pixel_channels(n, c, y0 + 1, x0);
292
+ let v11 = pixel_channels(n, c, y0 + 1, x0 + 1);
293
+ {% endif %}
294
+ let result = (1.0 - wy) * ((1.0 - wx) * v00 + wx * v01)
295
+ + wy * ((1.0 - wx) * v10 + wx * v11);
296
+ {% endif %}
297
+ let out_base = (n * params.C + c) * out_plane + spatial;
298
+ {% for lane in range(source.channelWidth) %}
299
+ {% if source.channelTail and lane > 0 %}
300
+ if (c + {{ lane }}u < params.C) { y[out_base + {{ lane }}u * out_plane] = {{ scalar }}(result.{{ components[lane] }}); }
301
+ {% else %}
302
+ y[out_base + {{ lane }}u * out_plane] = {{ scalar }}(result.{{ components[lane] }});
303
+ {% endif %}
304
+ {% endfor %}
305
+ {% else %}
306
+ if (i >= params.count) { return; }
307
+ let ow = i % params.outW;
308
+ let oh = (i / params.outW) % params.outH;
309
+ let c = (i / (params.outW * params.outH)) % params.C;
310
+ let n = i / (params.outW * params.outH * params.C);
311
+ let grid_base = ((n * params.outH + oh) * params.outW + ow) * 2u;
312
+ let sx = sanitize_coord(denormalize(f32(grid[grid_base]), params.inW));
313
+ let sy = sanitize_coord(denormalize(f32(grid[grid_base + 1u]), params.inH));
314
+ let img_base = (n * params.C + c) * params.inH * params.inW;
315
+ {% if source.mode == "nearest" %}
316
+ let result = pixel(img_base, sample_round(sy), sample_round(sx));
317
+ {% elif source.mode == "cubic" %}
318
+ let x0 = sample_floor(sx) - 1;
319
+ let y0 = sample_floor(sy) - 1;
320
+ let dx = sx - f32(x0 + 1);
321
+ let dy = sy - f32(y0 + 1);
322
+ let cx = cubic_coeffs(dx);
323
+ let cy = cubic_coeffs(dy);
324
+ var rows: vec4<f32>;
325
+ for (var r = 0i; r < 4i; r = r + 1i) {
326
+ rows[u32(r)] = cx.x * pixel(img_base, y0 + r, x0) + cx.y * pixel(img_base, y0 + r, x0 + 1) + cx.z * pixel(img_base, y0 + r, x0 + 2) + cx.w * pixel(img_base, y0 + r, x0 + 3);
327
+ }
328
+ let result = dot(cy, rows);
329
+ {% else %}
330
+ let x0 = sample_floor(sx);
331
+ let y0 = sample_floor(sy);
332
+ let wx = sx - f32(x0);
333
+ let wy = sy - f32(y0);
334
+ let v00 = pixel(img_base, y0, x0);
335
+ let v01 = pixel(img_base, y0, x0 + 1);
336
+ let v10 = pixel(img_base, y0 + 1, x0);
337
+ let v11 = pixel(img_base, y0 + 1, x0 + 1);
338
+ let result = (1.0 - wy) * ((1.0 - wx) * v00 + wx * v01) + wy * ((1.0 - wx) * v10 + wx * v11);
339
+ {% endif %}
340
+ y[i] = {{ scalar }}(result);
341
+ {% endif %}
342
+ }
build/webgpu/grid-sample3d.wgsl.jinja ADDED
@@ -0,0 +1,228 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ fn denormalize(n: f32, length: u32) -> f32 {
40
+ {% if source.alignCorners %}
41
+ return (n + 1.0) * 0.5 * f32(length - 1u);
42
+ {% else %}
43
+ return ((n + 1.0) * f32(length) - 1.0) * 0.5;
44
+ {% endif %}
45
+ }
46
+
47
+ fn sanitize_coord(v: f32) -> f32 {
48
+ if (!(v >= -2147483000.0 && v <= 2147483000.0)) {
49
+ {% if source.alignCorners %}
50
+ return 0.0;
51
+ {% else %}
52
+ return -0.5;
53
+ {% endif %}
54
+ }
55
+ return v;
56
+ }
57
+ {% if source.paddingMode == "reflection" %}
58
+
59
+ fn reflect_coord(v: f32, lo: f32, hi: f32) -> f32 {
60
+ let range = hi - lo;
61
+ if (range == 0.0) { return lo; }
62
+ var x0 = v;
63
+ if (x0 < lo) {
64
+ let d = lo - x0;
65
+ if (d / range > 2147483000.0) { return lo; }
66
+ let n = i32(floor(d / range));
67
+ let r = d - f32(n) * range;
68
+ x0 = select(hi - r, lo + r, n % 2 == 0);
69
+ } else if (x0 > hi) {
70
+ let d = x0 - hi;
71
+ if (d / range > 2147483000.0) { return hi; }
72
+ let n = i32(floor(d / range));
73
+ let r = d - f32(n) * range;
74
+ x0 = select(lo + r, hi - r, n % 2 == 0);
75
+ }
76
+ return x0;
77
+ }
78
+
79
+ {% endif %}
80
+ {% if source.mode != "nearest" %}
81
+ fn sample_floor(v: f32) -> i32 {
82
+ if (v > 2147483000.0) {
83
+ {% if source.paddingMode == "reflection" %}
84
+ return 0;
85
+ {% else %}
86
+ return 2147483000;
87
+ {% endif %}
88
+ }
89
+ if (v < -2147483000.0) {
90
+ {% if source.paddingMode == "reflection" %}
91
+ return 0;
92
+ {% else %}
93
+ return -2147483000;
94
+ {% endif %}
95
+ }
96
+ return i32(floor(v));
97
+ }
98
+ {%- else %}
99
+ fn sample_round(v: f32) -> i32 {
100
+ if (v > 2147483000.0) {
101
+ {% if source.paddingMode == "reflection" %}
102
+ return 0;
103
+ {% else %}
104
+ return 2147483000;
105
+ {% endif %}
106
+ }
107
+ if (v < -2147483000.0) {
108
+ {% if source.paddingMode == "reflection" %}
109
+ return 0;
110
+ {% else %}
111
+ return -2147483000;
112
+ {% endif %}
113
+ }
114
+ return i32(round(v));
115
+ }
116
+ {%- endif %}
117
+
118
+
119
+ {% if source.mode == "cubic" %}
120
+ fn cubic_coeffs(t: f32) -> vec4<f32> {
121
+ let a = -0.75;
122
+ let x0 = abs(t + 1.0);
123
+ let x1 = abs(t);
124
+ let x2 = abs(1.0 - t);
125
+ let x3 = abs(2.0 - t);
126
+ return vec4<f32>(cubic_one(x0, a), cubic_one(x1, a), cubic_one(x2, a), cubic_one(x3, a));
127
+ }
128
+
129
+ fn cubic_one(x0: f32, a: f32) -> f32 {
130
+ if (x0 <= 1.0) { return (a + 2.0) * x0 * x0 * x0 - (a + 3.0) * x0 * x0 + 1.0; }
131
+ if (x0 < 2.0) { return a * x0 * x0 * x0 - 5.0 * a * x0 * x0 + 8.0 * a * x0 - 4.0 * a; }
132
+ return 0.0;
133
+ }
134
+
135
+ {% endif -%}
136
+ fn voxel(base: u32, d: i32, h: i32, w: i32) -> f32 {
137
+ {% if source.paddingMode == "zeros" %}
138
+ if (d < 0 || d >= i32(params.inD) || h < 0 || h >= i32(params.inH) || w < 0 || w >= i32(params.inW)) {
139
+ return 0.0;
140
+ }
141
+ let dd = u32(d);
142
+ let hh = u32(h);
143
+ let ww = u32(w);
144
+ {% elif source.paddingMode == "border" %}
145
+ let dd = u32(clamp(d, 0, i32(params.inD) - 1));
146
+ let hh = u32(clamp(h, 0, i32(params.inH) - 1));
147
+ let ww = u32(clamp(w, 0, i32(params.inW) - 1));
148
+ {% else %}
149
+ {% if source.alignCorners %}
150
+ let rd = i32(reflect_coord(f32(d), 0.0, f32(params.inD) - 1.0));
151
+ let rh = i32(reflect_coord(f32(h), 0.0, f32(params.inH) - 1.0));
152
+ let rw = i32(reflect_coord(f32(w), 0.0, f32(params.inW) - 1.0));
153
+ {% else %}
154
+ let rd = i32(reflect_coord(f32(d), -0.5, f32(params.inD) - 0.5));
155
+ let rh = i32(reflect_coord(f32(h), -0.5, f32(params.inH) - 0.5));
156
+ let rw = i32(reflect_coord(f32(w), -0.5, f32(params.inW) - 0.5));
157
+ {% endif %}
158
+ let dd = u32(clamp(rd, 0, i32(params.inD) - 1));
159
+ let hh = u32(clamp(rh, 0, i32(params.inH) - 1));
160
+ let ww = u32(clamp(rw, 0, i32(params.inW) - 1));
161
+ {% endif %}
162
+ return f32(x[((base + dd) * params.inH + hh) * params.inW + ww]);
163
+ }
164
+
165
+ @compute @workgroup_size({{ tunables.WORKGROUP_SIZE }})
166
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>, @builtin(num_workgroups) nwg: vec3<u32>) {
167
+ {{ flat_index_2d(guardInline=true) }}
168
+
169
+ let ow = i % params.outW;
170
+ var t = i / params.outW;
171
+ let oh = t % params.outH;
172
+ t = t / params.outH;
173
+ let od = t % params.outD;
174
+ t = t / params.outD;
175
+ let c = t % params.C;
176
+ let n = t / params.C;
177
+
178
+ let grid_base = (((n * params.outD + od) * params.outH + oh) * params.outW + ow) * 3u;
179
+ let sx = sanitize_coord(denormalize(f32(grid[grid_base]), params.inW));
180
+ let sy = sanitize_coord(denormalize(f32(grid[grid_base + 1u]), params.inH));
181
+ let sz = sanitize_coord(denormalize(f32(grid[grid_base + 2u]), params.inD));
182
+ let img_base = (n * params.C + c) * params.inD;
183
+
184
+ {% if source.mode == "nearest" %}
185
+ let result = voxel(img_base, sample_round(sz), sample_round(sy), sample_round(sx));
186
+ {% elif source.mode == "cubic" %}
187
+ // Tricubic is the separable product of the same 4-tap Keys kernel the 2D path
188
+ // uses, one axis at a time; voxel() already resolves every padding mode, so
189
+ // the 64-tap window needs no boundary handling of its own.
190
+ let x0 = sample_floor(sx) - 1;
191
+ let y0 = sample_floor(sy) - 1;
192
+ let z0 = sample_floor(sz) - 1;
193
+ let cx = cubic_coeffs(sx - f32(x0 + 1));
194
+ let cy = cubic_coeffs(sy - f32(y0 + 1));
195
+ let cz = cubic_coeffs(sz - f32(z0 + 1));
196
+ var result = 0.0;
197
+ for (var kz = 0i; kz < 4i; kz = kz + 1i) {
198
+ var plane = 0.0;
199
+ for (var ky = 0i; ky < 4i; ky = ky + 1i) {
200
+ let row = cx.x * voxel(img_base, z0 + kz, y0 + ky, x0)
201
+ + cx.y * voxel(img_base, z0 + kz, y0 + ky, x0 + 1)
202
+ + cx.z * voxel(img_base, z0 + kz, y0 + ky, x0 + 2)
203
+ + cx.w * voxel(img_base, z0 + kz, y0 + ky, x0 + 3);
204
+ plane = plane + cy[u32(ky)] * row;
205
+ }
206
+ result = result + cz[u32(kz)] * plane;
207
+ }
208
+ {% else %}
209
+ let x0 = sample_floor(sx);
210
+ let y0 = sample_floor(sy);
211
+ let z0 = sample_floor(sz);
212
+ let wx = sx - f32(x0);
213
+ let wy = sy - f32(y0);
214
+ let wz = sz - f32(z0);
215
+ let v000 = voxel(img_base, z0, y0, x0);
216
+ let v001 = voxel(img_base, z0, y0, x0 + 1);
217
+ let v010 = voxel(img_base, z0, y0 + 1, x0);
218
+ let v011 = voxel(img_base, z0, y0 + 1, x0 + 1);
219
+ let v100 = voxel(img_base, z0 + 1, y0, x0);
220
+ let v101 = voxel(img_base, z0 + 1, y0, x0 + 1);
221
+ let v110 = voxel(img_base, z0 + 1, y0 + 1, x0);
222
+ let v111 = voxel(img_base, z0 + 1, y0 + 1, x0 + 1);
223
+ let front = (1.0 - wy) * ((1.0 - wx) * v000 + wx * v001) + wy * ((1.0 - wx) * v010 + wx * v011);
224
+ let back = (1.0 - wy) * ((1.0 - wx) * v100 + wx * v101) + wy * ((1.0 - wx) * v110 + wx * v111);
225
+ let result = (1.0 - wz) * front + wz * back;
226
+ {% endif %}
227
+ y[i] = {{ scalar }}(result);
228
+ }
build/webgpu/manifest.json ADDED
@@ -0,0 +1,184 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "domain": "ai.onnx",
3
+ "name": "GridSample",
4
+ "sinceVersion": 20,
5
+ "description": "Samples values from input tensor `X` at positions defined by a flow-field `grid`, producing output `Y` with spatial dimensions taken from `grid`. Grid coordinates are normalized to `[-1, 1]` over the input spatial extent; positions outside this range are handled according to `padding_mode`. Supports spatial `(rank-4, NCHW)` and volumetric `(rank-5, NCDHW)` inputs with `linear`, `nearest`, or `cubic` interpolation.",
6
+ "inputs": [
7
+ {
8
+ "role": "X",
9
+ "dtype": "T",
10
+ "description": "Input tensor of shape `(N, C, D1, ..., Dr)` whose values are sampled."
11
+ },
12
+ {
13
+ "role": "grid",
14
+ "dtype": "T",
15
+ "description": "Flow-field of shape `(N, D1_out, ..., Dr_out, r)` with normalized sampling coordinates in `[-1, 1]`."
16
+ }
17
+ ],
18
+ "outputs": [
19
+ {
20
+ "role": "Y",
21
+ "dtype": "T",
22
+ "rank": "ranks.grid",
23
+ "description": "Output tensor of shape `(N, C, D1_out, ..., Dr_out)` containing the interpolated samples.",
24
+ "shape": "prefix(shapes.X, 2) + prefix(suffix(shapes.grid, 1), ranks.grid - 2)"
25
+ }
26
+ ],
27
+ "attributes": { "mode": "linear", "padding_mode": "zeros", "align_corners": 0 },
28
+ "attributeDescriptions": {
29
+ "mode": "Interpolation method: `linear` (bilinear or trilinear, depending on rank), `nearest`, or `cubic`. Cubic interpolation is supported for rank-4 (2-D spatial) inputs.",
30
+ "padding_mode": "How out-of-bound grid positions are handled: `zeros` pads with 0, `border` clamps to the border value, or `reflection` reflects coordinates back into the valid range.",
31
+ "align_corners": "When 1, extrema values `-1` and `1` map to the center of the corner pixels; when 0 (default) they map to the outer edge of corner pixels, making sampling resolution-agnostic."
32
+ },
33
+ "attributeConstraints": {
34
+ "mode": { "values": ["linear", "nearest", "cubic"] },
35
+ "padding_mode": { "values": ["zeros", "border", "reflection"] },
36
+ "align_corners": { "values": [0, 1] }
37
+ },
38
+ "typeConstraints": { "T": ["float32", "float16"] },
39
+ "args": {
40
+ "x": { "kind": "tensor", "semantic": "X", "role": "input" },
41
+ "grid": { "kind": "tensor", "semantic": "grid", "role": "input" },
42
+ "y": { "kind": "tensor", "semantic": "Y", "role": "output" }
43
+ },
44
+ "tunables": { "WORKGROUP_SIZE": 256 },
45
+ "derive": {
46
+ "wave32Adapter": "has(device.adapterInfo, \"subgroupMinSize\") and has(device.adapterInfo, \"subgroupMaxSize\") and device.adapterInfo.subgroupMinSize == 32 and device.adapterInfo.subgroupMaxSize == 32",
47
+ "reportedNonWave32Adapter": "not wave32Adapter and (has(device.adapterInfo, \"subgroupMinSize\") or has(device.adapterInfo, \"subgroupMaxSize\"))",
48
+ "rank4Ok": "ranks.X == 4 and ranks.grid == 4 and ranks.Y == 4 and dim(shapes.grid, 0) == dim(shapes.X, 0) and dim(shapes.grid, 3) == 2 and dim(shapes.Y, 0) == dim(shapes.X, 0) and dim(shapes.Y, 1) == dim(shapes.X, 1) and dim(shapes.Y, 2) == dim(shapes.grid, 1) and dim(shapes.Y, 3) == dim(shapes.grid, 2) and f16Ok(dtypes.T)",
49
+ "channelWidth": 4
50
+ },
51
+ "constants": { "scalar": "dtypes.T", "usesF16": "dtypes.T == \"f16\"" },
52
+ "bindingSets": {
53
+ "rank4": [
54
+ { "name": "x", "arg": "x", "semantic": "X", "buffer": { "type": "read-only-storage" }, "elementType": "$scalar" },
55
+ {
56
+ "name": "grid",
57
+ "arg": "grid",
58
+ "semantic": "grid",
59
+ "buffer": { "type": "read-only-storage" },
60
+ "elementType": "$scalar"
61
+ },
62
+ { "name": "y", "arg": "y", "semantic": "Y", "buffer": { "type": "storage" }, "elementType": "$scalar" },
63
+ {
64
+ "name": "params",
65
+ "semantic": "kernel.params",
66
+ "buffer": { "type": "uniform" },
67
+ "struct": {
68
+ "name": "Params",
69
+ "fields": [
70
+ { "name": "count", "type": "u32", "value": "numel(shapes.Y)" },
71
+ { "name": "C", "type": "u32", "value": "dim(shapes.X, 1)" },
72
+ { "name": "inH", "type": "u32", "value": "dim(shapes.X, 2)" },
73
+ { "name": "inW", "type": "u32", "value": "dim(shapes.X, 3)" },
74
+ { "name": "outH", "type": "u32", "value": "dim(shapes.Y, 2)" },
75
+ { "name": "outW", "type": "u32", "value": "dim(shapes.Y, 3)" }
76
+ ]
77
+ }
78
+ }
79
+ ]
80
+ },
81
+ "variants": [
82
+ {
83
+ "id": "nchw_rank4_channel_vector",
84
+ "priority": 5,
85
+ "when": ["rank4Ok", "not reportedNonWave32Adapter", "dim(shapes.X, 1) >= 2"],
86
+ "passes": [
87
+ {
88
+ "id": "main",
89
+ "name": "GridSample.ChannelX4",
90
+ "source": {
91
+ "shader": "grid-sample.wgsl.jinja",
92
+ "inputs": {
93
+ "mode": "attrs.mode",
94
+ "paddingMode": "attrs.padding_mode",
95
+ "alignCorners": "attrs.align_corners != 0",
96
+ "channelWidth": "channelWidth",
97
+ "channelTail": "dim(shapes.X, 1) % channelWidth != 0"
98
+ }
99
+ },
100
+ "bindings": "rank4",
101
+ "dispatch": {
102
+ "threads": "dim(shapes.Y, 0) * ceilDiv(dim(shapes.Y, 1), channelWidth) * dim(shapes.Y, 2) * dim(shapes.Y, 3)",
103
+ "workgroupSize": "tunables.WORKGROUP_SIZE"
104
+ }
105
+ }
106
+ ]
107
+ },
108
+ {
109
+ "id": "nchw_rank4",
110
+ "when": ["rank4Ok"],
111
+ "passes": [
112
+ {
113
+ "id": "main",
114
+ "name": "GridSample",
115
+ "source": {
116
+ "shader": "grid-sample.wgsl.jinja",
117
+ "inputs": {
118
+ "mode": "attrs.mode",
119
+ "paddingMode": "attrs.padding_mode",
120
+ "alignCorners": "attrs.align_corners != 0"
121
+ }
122
+ },
123
+ "bindings": "rank4",
124
+ "dispatch": { "threads": "numel(shapes.Y)", "workgroupSize": "tunables.WORKGROUP_SIZE" }
125
+ }
126
+ ]
127
+ },
128
+ {
129
+ "id": "ncdhw_rank5",
130
+ "priority": 10,
131
+ "when": ["ranks.X == 5", "ranks.grid == 5", "ranks.Y == 5", "dim(shapes.grid, 0) == dim(shapes.X, 0)", "dim(shapes.grid, 4) == 3", "dim(shapes.Y, 0) == dim(shapes.X, 0)", "dim(shapes.Y, 1) == dim(shapes.X, 1)", "dim(shapes.Y, 2) == dim(shapes.grid, 1)", "dim(shapes.Y, 3) == dim(shapes.grid, 2)", "dim(shapes.Y, 4) == dim(shapes.grid, 3)", "(attrs.mode == \"linear\" or attrs.mode == \"nearest\" or attrs.mode == \"cubic\")", "(attrs.padding_mode == \"zeros\" or attrs.padding_mode == \"border\" or attrs.padding_mode == \"reflection\")", "f16Ok(dtypes.T)"],
132
+ "passes": [
133
+ {
134
+ "id": "main",
135
+ "name": "GridSample.Volumetric",
136
+ "source": {
137
+ "shader": "grid-sample3d.wgsl.jinja",
138
+ "inputs": {
139
+ "mode": "attrs.mode",
140
+ "paddingMode": "attrs.padding_mode",
141
+ "alignCorners": "attrs.align_corners != 0"
142
+ }
143
+ },
144
+ "bindings": [
145
+ {
146
+ "name": "x",
147
+ "arg": "x",
148
+ "semantic": "X",
149
+ "buffer": { "type": "read-only-storage" },
150
+ "elementType": "$scalar"
151
+ },
152
+ {
153
+ "name": "grid",
154
+ "arg": "grid",
155
+ "semantic": "grid",
156
+ "buffer": { "type": "read-only-storage" },
157
+ "elementType": "$scalar"
158
+ },
159
+ { "name": "y", "arg": "y", "semantic": "Y", "buffer": { "type": "storage" }, "elementType": "$scalar" },
160
+ {
161
+ "name": "params",
162
+ "semantic": "kernel.params",
163
+ "buffer": { "type": "uniform" },
164
+ "struct": {
165
+ "name": "Params",
166
+ "fields": [
167
+ { "name": "count", "type": "u32", "value": "numel(shapes.Y)" },
168
+ { "name": "C", "type": "u32", "value": "dim(shapes.X, 1)" },
169
+ { "name": "inD", "type": "u32", "value": "dim(shapes.X, 2)" },
170
+ { "name": "inH", "type": "u32", "value": "dim(shapes.X, 3)" },
171
+ { "name": "inW", "type": "u32", "value": "dim(shapes.X, 4)" },
172
+ { "name": "outD", "type": "u32", "value": "dim(shapes.Y, 2)" },
173
+ { "name": "outH", "type": "u32", "value": "dim(shapes.Y, 3)" },
174
+ { "name": "outW", "type": "u32", "value": "dim(shapes.Y, 4)" }
175
+ ]
176
+ }
177
+ }
178
+ ],
179
+ "dispatch": { "threads": "numel(shapes.Y)", "workgroupSize": "tunables.WORKGROUP_SIZE" }
180
+ }
181
+ ]
182
+ }
183
+ ]
184
+ }
build/webgpu/metadata.json ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "ai.onnx.GridSample",
3
+ "id": "_ai_onnx_gridsample_webgpu_3892192",
4
+ "version": 1,
5
+ "license": "Apache-2.0",
6
+ "backend": { "type": "webgpu" },
7
+ "digest": {
8
+ "algorithm": "sha256",
9
+ "files": {
10
+ "bench.json": "G6tTb9EsyvpKUZLsd4qAik9iHOhPJGsUBR3ah5o7L+w=",
11
+ "grid-sample.wgsl.jinja": "vGFCLAzhkxtkeC071yc3MrcZa3C5mqPT4+ZbjxJn5Zo=",
12
+ "grid-sample3d.wgsl.jinja": "cSEW1lJIrYaiamCfxoP1KBWbzqcRfe+00AtqpeXRUNA=",
13
+ "manifest.json": "iZOT6Iz9u/5yFWpFbpO+1EgSPRoW9YPluK9w2unD2wk=",
14
+ "test.json": "iD0xQONckmqQHJylOBRTC7z57/IvRn28fEdFgYX1TNI="
15
+ }
16
+ },
17
+ "provenance": { "kernel": { "sha": "2e7068faf55e7f43df740015f6d1ee49391a41c5", "dirty": false } },
18
+ "webgpu": { "manifestSpec": "1.0", "specialized": true, "opPath": "ops/ai.onnx.GridSample" }
19
+ }
build/webgpu/test.json ADDED
@@ -0,0 +1,1965 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "op": "ai.onnx.GridSample",
3
+ "fixtureArrays": {
4
+ "onnx_backend_gridsample_volumetric_input_grid": [-1, -1, -1, -1, -0.5, 0.30000001192092896, -0.5, -0.5, -0.5, 1, -0.6000000238418579, -1, -0.20000000298023224, -0.20000000298023224, -0.20000000298023224, 0.4000000059604645, 0.20000000298023224, 0.6000000238418579, 0, 0, 0, -1, 0, 0, 0, 0, 0, -1, 1, 0, -0.20000000298023224, -0.20000000298023224, -0.20000000298023224, 1, 0.4000000059604645, -0.20000000298023224, 0.5, 0.5, 0.5, -1, -0.800000011920929, 0.800000011920929, 1, 1, 1, 0.4000000059604645, 0.6000000238418579, -0.30000001192092896],
5
+ "grid_sample_grid_16": [-1, -0.800000011920929, -0.6000000238418579, -0.5, -0.10000000149011612, -0.20000000298023224, 0.699999988079071, 0, 0, 0.4000000059604645, 0.20000000298023224, -0.20000000298023224, -0.30000001192092896, 0.5, -1, 1],
6
+ "onnx_backend_far_coords_zeros_padding_input_grid": [-10, -10, -5, -5, -0.2, -0.2, 10, 10, 10, 10, -0.2, -0.2, 5, 5, 10, 10],
7
+ "onnx_backend_gridsample_input_x": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
8
+ "onnx_backend_gridsample_aligncorners_true_input_grid": [-1, -1, -0.5, -0.5, -0.20000000298023224, -0.20000000298023224, 0, 0, 0, 0, -0.20000000298023224, -0.20000000298023224, 0.5, 0.5, 1, 1],
9
+ "onnx_backend_gridsample_border_padding_input_grid": [-10, -10, -5, -5, -0.20000000298023224, -0.20000000298023224, 10, 10, 10, 10, -0.20000000298023224, -0.20000000298023224, 5, 5, 10, 10]
10
+ },
11
+ "cases": [
12
+ {
13
+ "name": "channel_x4_cubic_reflection_c16_f32",
14
+ "attrs": { "mode": "cubic", "padding_mode": "reflection", "align_corners": 0 },
15
+ "inputs": {
16
+ "x": {
17
+ "dtype": "float32",
18
+ "shape": [1, 16, 4, 4],
19
+ "data": { "kind": "fillFloat32", "scale": 0.5, "sinStep": 0.17, "cosStep": 0.09 }
20
+ },
21
+ "grid": { "dtype": "float32", "shape": [1, 3, 3, 2], "data": { "kind": "linspace", "start": -1.4, "end": 1.4 } }
22
+ },
23
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 16, 3, 3], "tolerance": 0.0001, "relTolerance": 0.0001 } }
24
+ },
25
+ {
26
+ "name": "channel_x4_cubic_reflection_align_corners_c4",
27
+ "provenance": {
28
+ "notes": "Cubic reflection padding with align_corners on over four channels checks the aligned reflection bounds 0 .. dim-1 on the channel-cooperative path."
29
+ },
30
+ "attrs": { "mode": "cubic", "padding_mode": "reflection", "align_corners": 1 },
31
+ "inputs": {
32
+ "x": {
33
+ "dtype": "float32",
34
+ "shape": [1, 4, 4, 4],
35
+ "data": { "kind": "fillFloat32", "scale": 0.5, "sinStep": 0.17, "cosStep": 0.09 }
36
+ },
37
+ "grid": { "dtype": "float32", "shape": [1, 3, 3, 2], "data": { "kind": "linspace", "start": -1.4, "end": 1.4 } }
38
+ },
39
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 4, 3, 3], "tolerance": 0.0001, "relTolerance": 0.0001 } }
40
+ },
41
+ {
42
+ "name": "channel_x4_linear_reflection_c4",
43
+ "provenance": {
44
+ "notes": "Bilinear reflection padding with align_corners off over four channels checks the half-pixel reflection bounds on the channel-cooperative path."
45
+ },
46
+ "attrs": { "mode": "linear", "padding_mode": "reflection", "align_corners": 0 },
47
+ "inputs": {
48
+ "x": {
49
+ "dtype": "float32",
50
+ "shape": [1, 4, 4, 5],
51
+ "data": { "kind": "fillFloat32", "scale": 0.5, "sinStep": 0.23, "cosStep": 0.11 }
52
+ },
53
+ "grid": { "dtype": "float32", "shape": [1, 3, 4, 2], "data": { "kind": "linspace", "start": -1.6, "end": 1.4 } }
54
+ },
55
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 4, 3, 4], "tolerance": 0.0001, "relTolerance": 0.0001 } }
56
+ },
57
+ {
58
+ "name": "channel_x4_linear_border_c8_f32",
59
+ "attrs": { "mode": "linear", "padding_mode": "border", "align_corners": 1 },
60
+ "inputs": {
61
+ "x": {
62
+ "dtype": "float32",
63
+ "shape": [1, 8, 5, 5],
64
+ "data": { "kind": "fillFloat32", "scale": 0.4, "sinStep": 0.13, "cosStep": 0.07 }
65
+ },
66
+ "grid": { "dtype": "float32", "shape": [1, 4, 4, 2], "data": { "kind": "linspace", "start": -1.2, "end": 1.2 } }
67
+ },
68
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 8, 4, 4], "tolerance": 0.00001, "relTolerance": 0.00001 } }
69
+ },
70
+ {
71
+ "name": "linear_zeros_exact_subnormal_pixel_gpu_gap",
72
+ "skipGpu": {
73
+ "category": "permanent",
74
+ "reason": "Portable WGSL floating-point semantics do not guarantee preservation of the subnormal values required by this fixture. Backend evidence: Metal flushes denormals to zero in the ALU; bilinear/trilinear interpolation arithmetic flushes the subnormal pixel/voxel on GPU. Permanent FTZ limitation."
75
+ },
76
+ "provenance": {
77
+ "notes": "Exact corner sampling with align_corners=1 should copy the positive subnormal source pixel through the bilinear path."
78
+ },
79
+ "attrs": { "mode": "linear", "padding_mode": "zeros", "align_corners": 1 },
80
+ "inputs": {
81
+ "x": {
82
+ "dtype": "float32",
83
+ "shape": [1, 1, 2, 2],
84
+ "data": { "kind": "values", "values": [1e-40, 0.0, 0.0, 0.0] }
85
+ },
86
+ "grid": { "dtype": "float32", "shape": [1, 1, 1, 2], "data": { "kind": "values", "values": [-1.0, -1.0] } }
87
+ },
88
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 1, 1], "tolerance": 0 } }
89
+ },
90
+ {
91
+ "name": "linear_zeros_exact_subnormal_voxel_gpu_gap",
92
+ "skipGpu": {
93
+ "category": "permanent",
94
+ "reason": "Portable WGSL floating-point semantics do not guarantee preservation of the subnormal values required by this fixture. Backend evidence: Metal flushes denormals to zero in the ALU; bilinear/trilinear interpolation arithmetic flushes the subnormal pixel/voxel on GPU. Permanent FTZ limitation."
95
+ },
96
+ "provenance": {
97
+ "notes": "Rank-5 companion: exact corner sampling should copy the positive subnormal source voxel through the trilinear path."
98
+ },
99
+ "attrs": { "mode": "linear", "padding_mode": "zeros", "align_corners": 1 },
100
+ "inputs": {
101
+ "x": {
102
+ "dtype": "float32",
103
+ "shape": [1, 1, 2, 2, 2],
104
+ "data": { "kind": "values", "values": [1e-40, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] }
105
+ },
106
+ "grid": {
107
+ "dtype": "float32",
108
+ "shape": [1, 1, 1, 1, 3],
109
+ "data": { "kind": "values", "values": [-1.0, -1.0, -1.0] }
110
+ }
111
+ },
112
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 1, 1, 1], "tolerance": 0 } }
113
+ },
114
+ {
115
+ "name": "dispatch_cliff_nchw_over_16m_elements",
116
+ "attrs": { "mode": "linear", "padding_mode": "zeros", "align_corners": 0 },
117
+ "inputs": {
118
+ "x": { "dtype": "float32", "shape": [1, 256, 8, 8] },
119
+ "grid": {
120
+ "dtype": "float32",
121
+ "shape": [1, 256, 256, 2],
122
+ "data": { "kind": "linspace", "start": -1.0, "end": 1.0 }
123
+ }
124
+ },
125
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 256, 256, 256], "tolerance": 0.0001 } }
126
+ },
127
+ {
128
+ "name": "dispatch_cliff_ncdhw_over_16m_elements",
129
+ "attrs": { "mode": "linear", "padding_mode": "zeros", "align_corners": 0 },
130
+ "inputs": {
131
+ "x": { "dtype": "float32", "shape": [1, 64, 8, 8, 8] },
132
+ "grid": {
133
+ "dtype": "float32",
134
+ "shape": [1, 64, 64, 64, 3],
135
+ "data": { "kind": "linspace", "start": -1.0, "end": 1.0 }
136
+ }
137
+ },
138
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 64, 64, 64, 64], "tolerance": 0.0001 } }
139
+ },
140
+ {
141
+ "name": "linear_zeros_align_corners",
142
+ "attrs": { "mode": "linear", "padding_mode": "zeros", "align_corners": 1 },
143
+ "inputs": {
144
+ "x": { "dtype": "float32", "shape": [1, 1, 2, 2], "data": { "kind": "values", "values": [1.0, 2.0, 3.0, 4.0] } },
145
+ "grid": {
146
+ "dtype": "float32",
147
+ "shape": [1, 2, 2, 2],
148
+ "data": { "kind": "values", "values": [-1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0] }
149
+ }
150
+ },
151
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 2, 2] } },
152
+ "tolerance": 0.000001
153
+ },
154
+ {
155
+ "name": "ort_linear_zeros_align_corners_rank4",
156
+ "provenance": {
157
+ "source": "onnxruntime/test/providers/cpu/tensor/grid_sample_test_gen.py",
158
+ "test": "GridSampleTest.test_grid_sample_16_4D_bilinear_zeros_align_corners",
159
+ "notes": "Generated ORT fixture materialized in grid_sample_test.cc; opset-20 spelling uses mode=linear for the 4D bilinear case."
160
+ },
161
+ "attrs": { "mode": "linear", "padding_mode": "zeros", "align_corners": 1 },
162
+ "inputs": {
163
+ "x": {
164
+ "dtype": "float32",
165
+ "shape": [2, 2, 3, 2],
166
+ "data": {
167
+ "kind": "values",
168
+ "values": [0.294201, 0.797322, 1.264215, 0.935492, 0.545464, -1.537389, 0.312439, 0.74006, -0.575326, -1.432532, -0.666175, 1.017438, -2.241368, 0.437349, -0.555362, -0.057943, 0.658583, 0.992938, -0.206548, -0.244841, -0.380599, 1.131112, -0.090205, -0.8979]
169
+ }
170
+ },
171
+ "grid": {
172
+ "dtype": "float32",
173
+ "shape": [2, 3, 2, 2],
174
+ "data": {
175
+ "kind": "values",
176
+ "values": [0.595248, -1.096726, -0.214731, -0.891773, -0.512023, 0.432352, -0.852156, 0.446072, 1.018534, 0.078706, -0.799785, -0.429942, 0.262037, -0.914782, 0.596172, -1.089444, -1.153552, -1.165993, -0.243436, 0.80692, -1.135775, 0.997425, -0.480027, 0.351461]
177
+ }
178
+ }
179
+ },
180
+ "outputs": { "y": { "dtype": "float32", "shape": [2, 2, 3, 2], "tolerance": 0.00001 } }
181
+ },
182
+ {
183
+ "name": "nearest_border",
184
+ "attrs": { "mode": "nearest", "padding_mode": "border", "align_corners": 1 },
185
+ "inputs": {
186
+ "x": { "dtype": "float32", "shape": [1, 1, 2, 2], "data": { "kind": "values", "values": [1.0, 2.0, 3.0, 4.0] } },
187
+ "grid": {
188
+ "dtype": "float32",
189
+ "shape": [1, 1, 3, 2],
190
+ "data": { "kind": "values", "values": [-2.0, -2.0, 0.0, 0.0, 2.0, 2.0] }
191
+ }
192
+ },
193
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 1, 3] } }
194
+ },
195
+ {
196
+ "name": "linear_f16",
197
+ "attrs": { "mode": "linear", "padding_mode": "zeros", "align_corners": 0 },
198
+ "inputs": {
199
+ "x": { "dtype": "float16", "shape": [1, 1, 2, 2], "data": { "kind": "values", "values": [1.0, 2.0, 3.0, 4.0] } },
200
+ "grid": {
201
+ "dtype": "float16",
202
+ "shape": [1, 1, 2, 2],
203
+ "data": { "kind": "values", "values": [0.0, 0.0, 1.0, 0.0] }
204
+ }
205
+ },
206
+ "outputs": { "y": { "dtype": "float16", "shape": [1, 1, 1, 2] } },
207
+ "tolerance": 0.002
208
+ },
209
+ {
210
+ "name": "nearest_reflection_extreme_coords_ort",
211
+ "provenance": {
212
+ "source": "onnxruntime/test/providers/cpu/tensor/grid_sample_test_custom.cc",
213
+ "test": "GridSampleCustomTest.test_grid_sample_20_4D_nearest_reflection_extreme_coords"
214
+ },
215
+ "attrs": { "mode": "nearest", "padding_mode": "reflection", "align_corners": 0 },
216
+ "inputs": {
217
+ "x": { "dtype": "float32", "shape": [1, 1, 2, 2], "data": { "kind": "constant", "value": 1.0 } },
218
+ "grid": {
219
+ "dtype": "float32",
220
+ "shape": [1, 1, 2, 2],
221
+ "data": { "kind": "values", "values": [10000000000.0, 10000000000.0, -10000000000.0, -10000000000.0] }
222
+ }
223
+ },
224
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 1, 2], "tolerance": 0.000001 } }
225
+ },
226
+ {
227
+ "name": "linear_reflection_far_coords_ort",
228
+ "provenance": {
229
+ "source": "onnxruntime/test/providers/cpu/tensor/grid_sample_test_custom.cc",
230
+ "test": "GridSampleCustomTest.test_grid_sample_20_4D_bilinear_reflection_extreme_coords",
231
+ "notes": "Uses smaller finite coordinates than ORT's extreme-coordinate regression while preserving the reflection boundary path."
232
+ },
233
+ "attrs": { "mode": "linear", "padding_mode": "reflection", "align_corners": 0 },
234
+ "inputs": {
235
+ "x": { "dtype": "float32", "shape": [1, 1, 2, 2], "data": { "kind": "constant", "value": 1.0 } },
236
+ "grid": {
237
+ "dtype": "float32",
238
+ "shape": [1, 1, 2, 2],
239
+ "data": { "kind": "values", "values": [5.0, 5.0, -5.0, -5.0] }
240
+ }
241
+ },
242
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 1, 2], "tolerance": 0.000001 } }
243
+ },
244
+ {
245
+ "name": "cubic_reflection_extreme_coords_ort",
246
+ "provenance": {
247
+ "source": "onnxruntime/test/providers/cpu/tensor/grid_sample_test_custom.cc",
248
+ "test": "GridSampleCustomTestFloatOnly.test_grid_sample_20_4D_cubic_reflection_extreme_coords"
249
+ },
250
+ "attrs": { "mode": "cubic", "padding_mode": "reflection", "align_corners": 0 },
251
+ "inputs": {
252
+ "x": { "dtype": "float32", "shape": [1, 1, 4, 4], "data": { "kind": "constant", "value": 1.0 } },
253
+ "grid": {
254
+ "dtype": "float32",
255
+ "shape": [1, 1, 1, 2],
256
+ "data": { "kind": "values", "values": [10000000000.0, -10000000000.0] }
257
+ }
258
+ },
259
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 1, 1], "tolerance": 0.0001 } }
260
+ },
261
+ {
262
+ "name": "nearest_reflection_extreme_coords_rank5",
263
+ "provenance": {
264
+ "source": "onnxruntime/test/providers/cpu/tensor/grid_sample_test_custom.cc",
265
+ "test": "GridSampleCustomTest.test_grid_sample_20_5D_nearest_reflection_extreme_coords",
266
+ "notes": "Covers ONNX 5D/volumetric nearest sampling with reflection padding."
267
+ },
268
+ "attrs": { "mode": "nearest", "padding_mode": "reflection", "align_corners": 0 },
269
+ "inputs": {
270
+ "x": { "dtype": "float32", "shape": [1, 1, 2, 2, 2], "data": { "kind": "constant", "value": 1.0 } },
271
+ "grid": {
272
+ "dtype": "float32",
273
+ "shape": [1, 1, 1, 2, 3],
274
+ "data": {
275
+ "kind": "values",
276
+ "values": [10000000000.0, 10000000000.0, 10000000000.0, -10000000000.0, -10000000000.0, -10000000000.0]
277
+ }
278
+ }
279
+ },
280
+ "outputs": {
281
+ "y": {
282
+ "dtype": "float32",
283
+ "shape": [1, 1, 1, 1, 2],
284
+ "tolerance": 0.000001,
285
+ "data": { "kind": "values", "values": [1.0, 1.0] }
286
+ }
287
+ }
288
+ },
289
+ {
290
+ "name": "linear_zeros_mixed_bounds_right_bottom_ort",
291
+ "provenance": {
292
+ "source": "onnxruntime/test/providers/cpu/tensor/grid_sample_test_custom.cc",
293
+ "test": "GridSampleCustomTest.test_grid_sample_20_4D_linear_zeros_mixed_bounds_right_bottom",
294
+ "notes": "Projection onto a 3x3 source image; it preserves ORT's right/bottom zero-padding boundary behavior."
295
+ },
296
+ "attrs": { "mode": "linear", "padding_mode": "zeros", "align_corners": 0 },
297
+ "inputs": {
298
+ "x": {
299
+ "dtype": "float32",
300
+ "shape": [1, 1, 3, 3],
301
+ "data": { "kind": "values", "values": [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0] }
302
+ },
303
+ "grid": {
304
+ "dtype": "float32",
305
+ "shape": [1, 1, 4, 2],
306
+ "data": { "kind": "values", "values": [1.0, 1.0, 0.8, 1.0, 1.0, 0.8, 1.2, 1.2] }
307
+ }
308
+ },
309
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 1, 4], "tolerance": 0.000001 } }
310
+ },
311
+ {
312
+ "name": "linear_border_batch2_channels2_ort",
313
+ "provenance": {
314
+ "source": "onnxruntime/test/providers/cpu/tensor/grid_sample_test.cc",
315
+ "test": "GridSampleTest.test_grid_sample_20_4D_bilinear_border_no_align_corners",
316
+ "notes": "Projection using deterministic generated data to cover batch and channel indexing in the same border/no-align mode."
317
+ },
318
+ "attrs": { "mode": "linear", "padding_mode": "border", "align_corners": 0 },
319
+ "inputs": {
320
+ "x": {
321
+ "dtype": "float32",
322
+ "shape": [2, 2, 3, 2],
323
+ "data": { "kind": "fillFloat32", "scale": 0.7, "sinStep": 0.13, "cosStep": 0.29 }
324
+ },
325
+ "grid": {
326
+ "dtype": "float32",
327
+ "shape": [2, 2, 2, 2],
328
+ "data": {
329
+ "kind": "values",
330
+ "values": [-1.1, -0.9, 0.25, -0.25, 0.8, 0.6, 1.2, 1.1, -0.4, 0.7, 0.0, 0.0, 0.9, -1.2, -1.3, 1.3]
331
+ }
332
+ }
333
+ },
334
+ "outputs": { "y": { "dtype": "float32", "shape": [2, 2, 2, 2], "tolerance": 0.000001 } }
335
+ },
336
+ {
337
+ "name": "cubic_zeros_fractional_multichannel",
338
+ "attrs": { "mode": "cubic", "padding_mode": "zeros", "align_corners": 1 },
339
+ "inputs": {
340
+ "x": {
341
+ "dtype": "float32",
342
+ "shape": [1, 2, 4, 4],
343
+ "data": { "kind": "fillFloat32", "scale": 0.5, "sinStep": 0.17, "cosStep": 0.11 }
344
+ },
345
+ "grid": {
346
+ "dtype": "float32",
347
+ "shape": [1, 2, 2, 2],
348
+ "data": { "kind": "values", "values": [-0.5, -0.5, 0.25, -0.25, 0.75, 0.5, 1.2, -1.2] }
349
+ }
350
+ },
351
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 2, 2, 2], "tolerance": 0.0001 } }
352
+ },
353
+ {
354
+ "name": "ort_linear_border_align_corners_compact",
355
+ "provenance": {
356
+ "source": "onnxruntime/test/providers/cpu/tensor/grid_sample_test.cc",
357
+ "test": "GridSampleTest.test_grid_sample_16_4D_bilinear_border_align_corners",
358
+ "notes": "Compact opset-20 projection using mode=linear for ORT's generated 4D bilinear border align-corners case."
359
+ },
360
+ "attrs": { "mode": "linear", "padding_mode": "border", "align_corners": 1 },
361
+ "inputs": {
362
+ "x": {
363
+ "dtype": "float32",
364
+ "shape": [1, 1, 2, 3],
365
+ "data": { "kind": "values", "values": [1.0, 2.0, 3.0, 4.0, 5.0, 6.0] }
366
+ },
367
+ "grid": {
368
+ "dtype": "float32",
369
+ "shape": [1, 2, 3, 2],
370
+ "data": { "kind": "values", "values": [-1.5, -1.0, 0.0, 0.0, 1.5, 1.0, -1.0, 1.2, 0.5, -1.2, 1.0, 0.0] }
371
+ }
372
+ },
373
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 2, 3], "tolerance": 0.00001 } }
374
+ },
375
+ {
376
+ "name": "ort_linear_reflection_align_corners_compact",
377
+ "provenance": {
378
+ "source": "onnxruntime/test/providers/cpu/tensor/grid_sample_test.cc",
379
+ "test": "GridSampleTest.test_grid_sample_20_4D_bilinear_reflection_align_corners",
380
+ "notes": "Compact opset-20 projection using mode=linear for ORT's generated 4D bilinear reflection align-corners case."
381
+ },
382
+ "attrs": { "mode": "linear", "padding_mode": "reflection", "align_corners": 1 },
383
+ "inputs": {
384
+ "x": {
385
+ "dtype": "float32",
386
+ "shape": [1, 1, 3, 3],
387
+ "data": { "kind": "values", "values": [1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0] }
388
+ },
389
+ "grid": {
390
+ "dtype": "float32",
391
+ "shape": [1, 2, 2, 2],
392
+ "data": { "kind": "values", "values": [-1.4, -1.4, 1.4, 1.4, 0.25, -0.5, -2.2, 0.6] }
393
+ }
394
+ },
395
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 2, 2], "tolerance": 0.00001 } }
396
+ },
397
+ {
398
+ "name": "ort_cubic_border_no_align_corners_compact",
399
+ "provenance": {
400
+ "source": "onnxruntime/test/providers/cpu/tensor/grid_sample_test.cc",
401
+ "test": "GridSampleTest.test_grid_sample_20_4D_bicubic_border_no_align_corners",
402
+ "notes": "Compact projection of ORT's generated 4D bicubic border no-align case; opset-20 spelling uses mode=cubic."
403
+ },
404
+ "attrs": { "mode": "cubic", "padding_mode": "border", "align_corners": 0 },
405
+ "inputs": {
406
+ "x": {
407
+ "dtype": "float32",
408
+ "shape": [1, 1, 3, 3],
409
+ "data": { "kind": "values", "values": [-2.0, -1.0, 0.0, 1.0, 3.0, 5.0, 8.0, 13.0, 21.0] }
410
+ },
411
+ "grid": {
412
+ "dtype": "float32",
413
+ "shape": [1, 2, 2, 2],
414
+ "data": { "kind": "values", "values": [0.2, -0.6, 1.2, 1.2, -1.1, 0.0, 0.0, 0.8] }
415
+ }
416
+ },
417
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 2, 2], "tolerance": 0.00001 } }
418
+ },
419
+ {
420
+ "name": "ort_cubic_reflection_align_corners_compact",
421
+ "provenance": {
422
+ "source": "onnxruntime/test/providers/cpu/tensor/grid_sample_test.cc",
423
+ "test": "GridSampleTest.test_grid_sample_20_4D_bicubic_reflection_align_corners",
424
+ "notes": "Compact projection of ORT's generated 4D bicubic reflection align-corners case; opset-20 spelling uses mode=cubic."
425
+ },
426
+ "attrs": { "mode": "cubic", "padding_mode": "reflection", "align_corners": 1 },
427
+ "inputs": {
428
+ "x": {
429
+ "dtype": "float32",
430
+ "shape": [1, 1, 3, 3],
431
+ "data": { "kind": "values", "values": [0.0, 1.0, 0.0, 2.0, 4.0, 2.0, 0.0, 1.0, 0.0] }
432
+ },
433
+ "grid": {
434
+ "dtype": "float32",
435
+ "shape": [1, 2, 2, 2],
436
+ "data": { "kind": "values", "values": [-1.25, -1.25, 1.25, -0.25, -0.6, 1.3, 0.3, 0.4] }
437
+ }
438
+ },
439
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 2, 2], "tolerance": 0.00001 } }
440
+ },
441
+ {
442
+ "name": "nearest_reflection_dim1_align_corners_ort",
443
+ "provenance": {
444
+ "source": "onnxruntime/test/providers/cpu/tensor/grid_sample_test_custom.cc",
445
+ "test": "GridSampleCustomTest.test_grid_sample_20_4D_nearest_reflection_dim1_align_corners",
446
+ "notes": "Extends ORT's dim-1 reflection case to a width-3 input so the same row-degenerate path also checks horizontal sampling."
447
+ },
448
+ "attrs": { "mode": "nearest", "padding_mode": "reflection", "align_corners": 1 },
449
+ "inputs": {
450
+ "x": { "dtype": "float32", "shape": [1, 1, 1, 3], "data": { "kind": "values", "values": [10.0, 20.0, 30.0] } },
451
+ "grid": {
452
+ "dtype": "float32",
453
+ "shape": [1, 1, 5, 2],
454
+ "data": { "kind": "values", "values": [-2.0, -2.0, -1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 2.0, 2.0] }
455
+ }
456
+ },
457
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 1, 5], "tolerance": 0.000001 } }
458
+ },
459
+ {
460
+ "name": "onnx_backend_far_coords_zeros_padding",
461
+ "provenance": {
462
+ "source": "cmake/external/onnx/onnx/backend/test/case/node/gridsample.py",
463
+ "test": "test_gridsample_zeros_padding"
464
+ },
465
+ "attrs": { "mode": "linear", "padding_mode": "zeros", "align_corners": 0 },
466
+ "inputs": {
467
+ "x": {
468
+ "dtype": "float32",
469
+ "shape": [1, 1, 3, 2],
470
+ "data": { "kind": "values", "values": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0] }
471
+ },
472
+ "grid": {
473
+ "dtype": "float32",
474
+ "shape": [1, 2, 4, 2],
475
+ "data": {
476
+ "kind": "values",
477
+ "values": { "$ref": "#/fixtureArrays/onnx_backend_far_coords_zeros_padding_input_grid" }
478
+ }
479
+ }
480
+ },
481
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 2, 4], "tolerance": 0.0001 } }
482
+ },
483
+ {
484
+ "name": "onnx_backend_far_coords_border_padding",
485
+ "provenance": {
486
+ "source": "cmake/external/onnx/onnx/backend/test/case/node/gridsample.py",
487
+ "test": "test_gridsample_border_padding"
488
+ },
489
+ "attrs": { "mode": "linear", "padding_mode": "border", "align_corners": 0 },
490
+ "inputs": {
491
+ "x": {
492
+ "dtype": "float32",
493
+ "shape": [1, 1, 3, 2],
494
+ "data": { "kind": "values", "values": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0] }
495
+ },
496
+ "grid": {
497
+ "dtype": "float32",
498
+ "shape": [1, 2, 4, 2],
499
+ "data": {
500
+ "kind": "values",
501
+ "values": { "$ref": "#/fixtureArrays/onnx_backend_far_coords_zeros_padding_input_grid" }
502
+ }
503
+ }
504
+ },
505
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 2, 4], "tolerance": 0.0001 } }
506
+ },
507
+ {
508
+ "name": "onnx_backend_far_coords_reflection_padding",
509
+ "provenance": {
510
+ "source": "cmake/external/onnx/onnx/backend/test/case/node/gridsample.py",
511
+ "test": "test_gridsample_reflection_padding"
512
+ },
513
+ "attrs": { "mode": "linear", "padding_mode": "reflection", "align_corners": 0 },
514
+ "inputs": {
515
+ "x": {
516
+ "dtype": "float32",
517
+ "shape": [1, 1, 3, 2],
518
+ "data": { "kind": "values", "values": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0] }
519
+ },
520
+ "grid": {
521
+ "dtype": "float32",
522
+ "shape": [1, 2, 4, 2],
523
+ "data": {
524
+ "kind": "values",
525
+ "values": { "$ref": "#/fixtureArrays/onnx_backend_far_coords_zeros_padding_input_grid" }
526
+ }
527
+ }
528
+ },
529
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 2, 4], "tolerance": 0.0001 } }
530
+ },
531
+ {
532
+ "name": "onnx_backend_cubic_mode",
533
+ "provenance": {
534
+ "source": "cmake/external/onnx/onnx/backend/test/case/node/gridsample.py",
535
+ "test": "test_gridsample_bicubic"
536
+ },
537
+ "attrs": { "mode": "cubic", "padding_mode": "zeros", "align_corners": 0 },
538
+ "inputs": {
539
+ "x": {
540
+ "dtype": "float32",
541
+ "shape": [1, 1, 3, 2],
542
+ "data": { "kind": "values", "values": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0] }
543
+ },
544
+ "grid": {
545
+ "dtype": "float32",
546
+ "shape": [1, 2, 4, 2],
547
+ "data": {
548
+ "kind": "values",
549
+ "values": [-1.0, -1.0, -0.5, -0.5, -0.2, -0.2, 0.0, 0.0, 0.0, 0.0, -0.2, -0.2, 0.5, 0.5, 1.0, 1.0]
550
+ }
551
+ }
552
+ },
553
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 2, 4], "tolerance": 0.0002 } }
554
+ },
555
+ {
556
+ "name": "ort_nearest_zeros_align",
557
+ "provenance": {
558
+ "source": "onnxruntime/test/providers/cpu/tensor/grid_sample_test.cc",
559
+ "test": "GridSampleTest.test_grid_sample_16_4D_nearest_zeros_align_corners"
560
+ },
561
+ "attrs": { "mode": "nearest", "padding_mode": "zeros", "align_corners": 1 },
562
+ "inputs": {
563
+ "x": {
564
+ "dtype": "float32",
565
+ "shape": [2, 2, 3, 2],
566
+ "data": {
567
+ "kind": "values",
568
+ "values": [-1.12584, -1.15236, -0.250579, -0.433879, 0.84871, 0.692009, -0.316013, -2.115219, 0.468096, -0.157712, 1.44366, 0.266049, 0.166455, 0.874382, -0.143474, -0.111609, 0.931827, 1.259009, 2.004981, 0.053737, 0.618057, -0.412802, -0.841065, -2.316042]
569
+ }
570
+ },
571
+ "grid": {
572
+ "dtype": "float32",
573
+ "shape": [2, 3, 2, 2],
574
+ "data": {
575
+ "kind": "values",
576
+ "values": [0.06311, -0.61522, 0.203022, -1.120434, -0.867079, -0.618636, 0.757125, 0.703586, -0.532194, -0.043299, 0.767473, 1.19296, 0.476259, 0.162111, 0.804584, -0.706563, 0.223613, -0.930367, -0.831703, -0.6199, 0.542968, 0.482592, -0.710823, 0.362529]
577
+ }
578
+ }
579
+ },
580
+ "outputs": { "y": { "dtype": "float32", "shape": [2, 2, 3, 2], "tolerance": 0 } }
581
+ },
582
+ {
583
+ "name": "ort_nearest_zeros_no_align",
584
+ "provenance": {
585
+ "source": "onnxruntime/test/providers/cpu/tensor/grid_sample_test.cc",
586
+ "test": "GridSampleTest.test_grid_sample_16_4D_nearest_zeros_no_align_corners"
587
+ },
588
+ "attrs": { "mode": "nearest", "padding_mode": "zeros", "align_corners": 0 },
589
+ "inputs": {
590
+ "x": {
591
+ "dtype": "float32",
592
+ "shape": [2, 2, 3, 2],
593
+ "data": {
594
+ "kind": "values",
595
+ "values": [-0.569248, 0.919971, 1.110816, 1.289874, -1.478174, 2.567233, -0.47312, 0.335551, -0.003304, -0.534441, 1.168688, 0.394503, 1.941462, 0.791498, -0.020252, -0.43717, -1.535287, -0.412679, 0.966303, 1.624783, -0.365619, -1.30244, 0.099403, 0.441822]
596
+ }
597
+ },
598
+ "grid": {
599
+ "dtype": "float32",
600
+ "shape": [2, 3, 2, 2],
601
+ "data": {
602
+ "kind": "values",
603
+ "values": [-1.143118, -0.021569, -0.903671, -0.925628, -0.06612, 0.180174, -0.491436, 0.712053, -0.730247, 1.088844, 0.82236, -1.01194, -0.298661, 0.054147, 0.175081, 0.284609, 0.470914, 0.07188, -0.585515, 0.567827, -1.151099, -0.711248, -0.300396, -0.584536]
604
+ }
605
+ }
606
+ },
607
+ "outputs": { "y": { "dtype": "float32", "shape": [2, 2, 3, 2], "tolerance": 0 } }
608
+ },
609
+ {
610
+ "name": "ort_nearest_border_align",
611
+ "provenance": {
612
+ "source": "onnxruntime/test/providers/cpu/tensor/grid_sample_test.cc",
613
+ "test": "GridSampleTest.test_grid_sample_16_4D_nearest_border_align_corners"
614
+ },
615
+ "attrs": { "mode": "nearest", "padding_mode": "border", "align_corners": 1 },
616
+ "inputs": {
617
+ "x": {
618
+ "dtype": "float32",
619
+ "shape": [2, 2, 3, 2],
620
+ "data": {
621
+ "kind": "values",
622
+ "values": [-0.883376, -0.418913, -0.804826, 0.56561, 0.610365, 0.466884, 1.950657, -1.063099, -0.829367, -1.407257, 1.626847, 0.172273, -1.611502, -0.479448, -0.143351, -0.317295, 0.573655, 0.997931, 0.543609, 0.078804, 0.86286, -0.01949, 0.991047, -0.777735]
623
+ }
624
+ },
625
+ "grid": {
626
+ "dtype": "float32",
627
+ "shape": [2, 3, 2, 2],
628
+ "data": {
629
+ "kind": "values",
630
+ "values": [-1.08007, -0.080985, 1.055303, -0.48947, 1.083604, 0.434584, -1.082953, 0.759237, -0.138473, -0.535688, 0.959584, -0.969714, 0.128766, -0.251242, 0.856935, 0.334973, 0.576606, 0.423791, -0.28857, -0.252367, -0.988898, 0.650213, 0.952774, 0.82107]
631
+ }
632
+ }
633
+ },
634
+ "outputs": { "y": { "dtype": "float32", "shape": [2, 2, 3, 2], "tolerance": 0 } }
635
+ },
636
+ {
637
+ "name": "ort_nearest_border_no_align",
638
+ "provenance": {
639
+ "source": "onnxruntime/test/providers/cpu/tensor/grid_sample_test.cc",
640
+ "test": "GridSampleTest.test_grid_sample_16_4D_nearest_border_no_align_corners"
641
+ },
642
+ "attrs": { "mode": "nearest", "padding_mode": "border", "align_corners": 0 },
643
+ "inputs": {
644
+ "x": {
645
+ "dtype": "float32",
646
+ "shape": [2, 2, 3, 2],
647
+ "data": {
648
+ "kind": "values",
649
+ "values": [-0.55963, 0.533472, 0.406887, 0.394587, 0.171511, 0.876045, -0.287087, 1.02164, 0.438649, -0.010704, 1.338354, -0.279405, -0.551834, -2.889061, -1.509981, 1.024115, 0.195393, -0.737109, 1.700101, 0.346216, 0.971125, 1.45025, -0.051909, -0.628431]
650
+ }
651
+ },
652
+ "grid": {
653
+ "dtype": "float32",
654
+ "shape": [2, 3, 2, 2],
655
+ "data": {
656
+ "kind": "values",
657
+ "values": [0.149807, 1.074831, 0.734055, -0.758657, 0.538205, -0.848275, -0.50859, 0.352947, 0.396231, 0.900274, -0.386299, 0.001921, 0.617788, -1.160511, 0.867577, -0.992307, 0.016539, -0.20402, -0.632008, 0.158605, 0.992302, -0.350783, -0.712433, -0.443807]
658
+ }
659
+ }
660
+ },
661
+ "outputs": { "y": { "dtype": "float32", "shape": [2, 2, 3, 2], "tolerance": 0 } }
662
+ },
663
+ {
664
+ "name": "ort_nearest_reflection_align",
665
+ "provenance": {
666
+ "source": "onnxruntime/test/providers/cpu/tensor/grid_sample_test.cc",
667
+ "test": "GridSampleTest.test_grid_sample_16_4D_nearest_reflection_align_corners"
668
+ },
669
+ "attrs": { "mode": "nearest", "padding_mode": "reflection", "align_corners": 1 },
670
+ "inputs": {
671
+ "x": {
672
+ "dtype": "float32",
673
+ "shape": [2, 2, 3, 2],
674
+ "data": {
675
+ "kind": "values",
676
+ "values": [-0.039373, -0.801472, -0.495544, -0.361514, 0.585113, -1.156007, -0.143365, -0.194741, -0.906885, -0.591838, 0.150785, -1.041149, -0.720534, -2.214754, -0.68373, 0.516358, 0.792848, 0.083228, 0.4228, -1.868747, -1.105713, 0.143731, 0.583597, 1.348155]
677
+ }
678
+ },
679
+ "grid": {
680
+ "dtype": "float32",
681
+ "shape": [2, 3, 2, 2],
682
+ "data": {
683
+ "kind": "values",
684
+ "values": [0.829854, -0.893309, 0.491599, -0.403504, -0.578962, 0.215574, -0.623348, 0.276486, 0.235657, -0.890987, 0.199798, 0.511115, 0.474997, -0.151054, -0.983745, -0.184985, 0.416769, -0.437853, 0.455497, 0.799155, -0.626582, 0.011834, 0.496199, 0.094053]
685
+ }
686
+ }
687
+ },
688
+ "outputs": { "y": { "dtype": "float32", "shape": [2, 2, 3, 2], "tolerance": 0 } }
689
+ },
690
+ {
691
+ "name": "ort_nearest_reflection_no_align",
692
+ "provenance": {
693
+ "source": "onnxruntime/test/providers/cpu/tensor/grid_sample_test.cc",
694
+ "test": "GridSampleTest.test_grid_sample_16_4D_nearest_reflection_no_align_corners"
695
+ },
696
+ "attrs": { "mode": "nearest", "padding_mode": "reflection", "align_corners": 0 },
697
+ "inputs": {
698
+ "x": {
699
+ "dtype": "float32",
700
+ "shape": [2, 2, 3, 2],
701
+ "data": {
702
+ "kind": "values",
703
+ "values": [-0.12923, -0.054595, 0.408347, 1.126366, 1.935057, 1.007685, 1.004642, -0.43352, -0.562711, -0.832754, -1.395545, -0.399295, -0.30994, -0.056062, 0.517413, -1.596237, 0.35696, -2.297482, -0.871083, -1.674028, 0.563055, -1.435067, 0.7194, -1.370747]
704
+ }
705
+ },
706
+ "grid": {
707
+ "dtype": "float32",
708
+ "shape": [2, 3, 2, 2],
709
+ "data": {
710
+ "kind": "values",
711
+ "values": [-0.81191, -1.183845, -0.963667, 0.947364, 0.649243, 1.125859, 0.961345, -1.071655, -0.818917, -0.193899, -0.779319, 0.833276, -0.907209, -0.585482, -1.15931, -0.681295, 0.986973, 0.982512, 0.859005, 0.926553, 1.067024, -0.307276, 0.528003, 1.069117]
712
+ }
713
+ }
714
+ },
715
+ "outputs": { "y": { "dtype": "float32", "shape": [2, 2, 3, 2], "tolerance": 0 } }
716
+ },
717
+ {
718
+ "name": "ort_custom_linear_zeros_mixed_bounds_right_bottom",
719
+ "provenance": {
720
+ "source": "onnxruntime/test/providers/cpu/tensor/grid_sample_test_custom.cc",
721
+ "test": "GridSampleCustomTest.test_grid_sample_20_4D_linear_zeros_mixed_bounds_right_bottom"
722
+ },
723
+ "attrs": { "mode": "linear", "padding_mode": "zeros", "align_corners": 0 },
724
+ "inputs": {
725
+ "x": { "dtype": "float32", "shape": [1, 1, 2, 2], "data": { "kind": "values", "values": [1.0, 2.0, 3.0, 4.0] } },
726
+ "grid": {
727
+ "dtype": "float32",
728
+ "shape": [1, 2, 2, 2],
729
+ "data": { "kind": "values", "values": [0.0, 0.0, 0.9, 0.0, 0.0, 0.9, 0.9, 0.9] }
730
+ }
731
+ },
732
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 2, 2], "tolerance": 0.000001 } }
733
+ },
734
+ {
735
+ "name": "ort_custom_linear_zeros_mixed_bounds_left_top",
736
+ "provenance": {
737
+ "source": "onnxruntime/test/providers/cpu/tensor/grid_sample_test_custom.cc",
738
+ "test": "GridSampleCustomTest.test_grid_sample_20_4D_linear_zeros_mixed_bounds_left_top"
739
+ },
740
+ "attrs": { "mode": "linear", "padding_mode": "zeros", "align_corners": 0 },
741
+ "inputs": {
742
+ "x": { "dtype": "float32", "shape": [1, 1, 2, 2], "data": { "kind": "values", "values": [1.0, 2.0, 3.0, 4.0] } },
743
+ "grid": {
744
+ "dtype": "float32",
745
+ "shape": [1, 2, 2, 2],
746
+ "data": { "kind": "values", "values": [0.0, 0.0, -0.9, 0.0, 0.0, -0.9, -0.9, -0.9] }
747
+ }
748
+ },
749
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 2, 2], "tolerance": 0.000001 } }
750
+ },
751
+ {
752
+ "name": "ort_custom_nearest_reflection_nan_coords",
753
+ "provenance": {
754
+ "source": "onnxruntime/test/providers/cpu/tensor/grid_sample_test_custom.cc",
755
+ "test": "GridSampleCustomTest.test_grid_sample_20_4D_nearest_reflection_nan_coords"
756
+ },
757
+ "attrs": { "mode": "nearest", "padding_mode": "reflection", "align_corners": 0 },
758
+ "inputs": {
759
+ "x": { "dtype": "float32", "shape": [1, 1, 2, 2], "data": { "kind": "constant", "value": 1.0 } },
760
+ "grid": {
761
+ "dtype": "float32",
762
+ "shape": [1, 1, 2, 2],
763
+ "data": { "kind": "values", "values": ["NaN", "NaN", 0.0, "NaN"] }
764
+ }
765
+ },
766
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 1, 2], "tolerance": 0.000001 } }
767
+ },
768
+ {
769
+ "name": "ort_custom_linear_reflection_infinity_coords",
770
+ "provenance": {
771
+ "source": "onnxruntime/test/providers/cpu/tensor/grid_sample_test_custom.cc",
772
+ "test": "GridSampleCustomTest.test_grid_sample_20_4D_bilinear_reflection_infinity_coords"
773
+ },
774
+ "attrs": { "mode": "linear", "padding_mode": "reflection", "align_corners": 0 },
775
+ "inputs": {
776
+ "x": { "dtype": "float32", "shape": [1, 1, 2, 2], "data": { "kind": "constant", "value": 1.0 } },
777
+ "grid": {
778
+ "dtype": "float32",
779
+ "shape": [1, 1, 2, 2],
780
+ "data": { "kind": "values", "values": ["Infinity", "-Infinity", "-Infinity", "Infinity"] }
781
+ }
782
+ },
783
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 1, 2], "tolerance": 0.000001 } }
784
+ },
785
+ {
786
+ "name": "ort_custom_linear_reflection_extreme_coords",
787
+ "provenance": {
788
+ "source": "onnxruntime/test/providers/cpu/tensor/grid_sample_test_custom.cc",
789
+ "test": "GridSampleCustomTest.test_grid_sample_20_4D_bilinear_reflection_extreme_coords"
790
+ },
791
+ "attrs": { "mode": "linear", "padding_mode": "reflection", "align_corners": 0 },
792
+ "inputs": {
793
+ "x": { "dtype": "float32", "shape": [1, 1, 2, 2], "data": { "kind": "constant", "value": 1.0 } },
794
+ "grid": {
795
+ "dtype": "float32",
796
+ "shape": [1, 1, 2, 2],
797
+ "data": {
798
+ "kind": "values",
799
+ "values": [100000000000000000000.0, 100000000000000000000.0, -100000000000000000000.0, -100000000000000000000.0]
800
+ }
801
+ }
802
+ },
803
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 1, 2], "tolerance": 0.000001 } }
804
+ },
805
+ {
806
+ "name": "ort_custom_linear_border_extreme_coords",
807
+ "provenance": {
808
+ "source": "onnxruntime/test/providers/cpu/tensor/grid_sample_test_custom.cc",
809
+ "test": "GridSampleCustomTest.test_grid_sample_20_4D_bilinear_border_extreme_coords"
810
+ },
811
+ "attrs": { "mode": "linear", "padding_mode": "border", "align_corners": 0 },
812
+ "inputs": {
813
+ "x": { "dtype": "float32", "shape": [1, 1, 2, 2], "data": { "kind": "constant", "value": 1.0 } },
814
+ "grid": {
815
+ "dtype": "float32",
816
+ "shape": [1, 1, 2, 2],
817
+ "data": {
818
+ "kind": "values",
819
+ "values": [100000000000000000000.0, 100000000000000000000.0, -100000000000000000000.0, -100000000000000000000.0]
820
+ }
821
+ }
822
+ },
823
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 1, 2], "tolerance": 0.000001 } }
824
+ },
825
+ {
826
+ "name": "ort_custom_linear_zeros_extreme_nan_inf_coords",
827
+ "provenance": {
828
+ "source": "onnxruntime/test/providers/cpu/tensor/grid_sample_test_custom.cc",
829
+ "test": "GridSampleCustomTest.test_grid_sample_20_4D_linear_zeros_extreme_nan_inf_coords"
830
+ },
831
+ "attrs": { "mode": "linear", "padding_mode": "zeros", "align_corners": 0 },
832
+ "inputs": {
833
+ "x": { "dtype": "float32", "shape": [1, 1, 2, 2], "data": { "kind": "constant", "value": 1.0 } },
834
+ "grid": {
835
+ "dtype": "float32",
836
+ "shape": [1, 1, 3, 2],
837
+ "data": {
838
+ "kind": "values",
839
+ "values": ["NaN", "NaN", "Infinity", "-Infinity", 100000000000000000000.0, -100000000000000000000.0]
840
+ }
841
+ }
842
+ },
843
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 1, 3], "tolerance": 0.000001 } }
844
+ },
845
+ {
846
+ "name": "ort_custom_cubic_reflection_nan_inf_coords",
847
+ "provenance": {
848
+ "source": "onnxruntime/test/providers/cpu/tensor/grid_sample_test_custom.cc",
849
+ "test": "GridSampleCustomTestFloatOnly.test_grid_sample_20_4D_cubic_reflection_nan_inf_coords"
850
+ },
851
+ "attrs": { "mode": "cubic", "padding_mode": "reflection", "align_corners": 0 },
852
+ "inputs": {
853
+ "x": { "dtype": "float32", "shape": [1, 1, 4, 4], "data": { "kind": "constant", "value": 1.0 } },
854
+ "grid": {
855
+ "dtype": "float32",
856
+ "shape": [1, 1, 3, 2],
857
+ "data": { "kind": "values", "values": ["NaN", "NaN", "Infinity", "-Infinity", "-Infinity", "Infinity"] }
858
+ }
859
+ },
860
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 1, 3], "tolerance": 0.0001 } }
861
+ },
862
+ {
863
+ "name": "ort_custom_nearest_reflection_align_corners_extreme",
864
+ "provenance": {
865
+ "source": "onnxruntime/test/providers/cpu/tensor/grid_sample_test_custom.cc",
866
+ "test": "GridSampleCustomTest.test_grid_sample_20_4D_nearest_reflection_align_corners_extreme"
867
+ },
868
+ "attrs": { "mode": "nearest", "padding_mode": "reflection", "align_corners": 1 },
869
+ "inputs": {
870
+ "x": {
871
+ "dtype": "float32",
872
+ "shape": [1, 1, 3, 3],
873
+ "data": { "kind": "values", "values": [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0] }
874
+ },
875
+ "grid": {
876
+ "dtype": "float32",
877
+ "shape": [1, 1, 2, 2],
878
+ "data": { "kind": "values", "values": [100000000000000000000.0, 100000000000000000000.0, "NaN", "-Infinity"] }
879
+ }
880
+ },
881
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 1, 2], "tolerance": 0.000001 } }
882
+ },
883
+ {
884
+ "name": "ort_custom_nearest_reflection_negative_only_extreme",
885
+ "provenance": {
886
+ "source": "onnxruntime/test/providers/cpu/tensor/grid_sample_test_custom.cc",
887
+ "test": "GridSampleCustomTest.test_grid_sample_20_4D_nearest_reflection_negative_only_extreme"
888
+ },
889
+ "attrs": { "mode": "nearest", "padding_mode": "reflection", "align_corners": 0 },
890
+ "inputs": {
891
+ "x": {
892
+ "dtype": "float32",
893
+ "shape": [1, 1, 3, 3],
894
+ "data": { "kind": "values", "values": [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0] }
895
+ },
896
+ "grid": {
897
+ "dtype": "float32",
898
+ "shape": [1, 1, 2, 2],
899
+ "data": {
900
+ "kind": "values",
901
+ "values": [-100000000000000000000.0, -100000000000000000000.0, "-Infinity", "-Infinity"]
902
+ }
903
+ }
904
+ },
905
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 1, 2], "tolerance": 0.000001 } }
906
+ },
907
+ {
908
+ "name": "ort_custom_nearest_reflection_mixed_normal_pathological",
909
+ "provenance": {
910
+ "source": "onnxruntime/test/providers/cpu/tensor/grid_sample_test_custom.cc",
911
+ "test": "GridSampleCustomTest.test_grid_sample_20_4D_nearest_reflection_mixed_normal_pathological"
912
+ },
913
+ "attrs": { "mode": "nearest", "padding_mode": "reflection", "align_corners": 1 },
914
+ "inputs": {
915
+ "x": {
916
+ "dtype": "float32",
917
+ "shape": [1, 1, 3, 3],
918
+ "data": { "kind": "values", "values": [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0] }
919
+ },
920
+ "grid": {
921
+ "dtype": "float32",
922
+ "shape": [1, 1, 4, 2],
923
+ "data": {
924
+ "kind": "values",
925
+ "values": [0.0, 0.0, -1.0, -1.0, "NaN", "NaN", 100000000000000000000.0, -100000000000000000000.0]
926
+ }
927
+ }
928
+ },
929
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 1, 4], "tolerance": 0.000001 } }
930
+ },
931
+ {
932
+ "name": "onnx_backend_gridsample",
933
+ "provenance": { "source": "cmake/external/onnx/onnx/backend/test/data/node/test_gridsample" },
934
+ "inputs": {
935
+ "x": {
936
+ "dtype": "float32",
937
+ "shape": [1, 1, 4, 4],
938
+ "data": { "kind": "values", "values": { "$ref": "#/fixtureArrays/onnx_backend_gridsample_input_x" } }
939
+ },
940
+ "grid": {
941
+ "dtype": "float32",
942
+ "shape": [1, 6, 6, 2],
943
+ "data": {
944
+ "kind": "values",
945
+ "values": [-1.0, -1.0, -0.6000000238418579, -1.0, -0.20000000298023224, -1.0, 0.20000000298023224, -1.0, 0.6000000238418579, -1.0, 1.0, -1.0, -1.0, -0.6000000238418579, -0.6000000238418579, -0.6000000238418579, -0.20000000298023224, -0.6000000238418579, 0.20000000298023224, -0.6000000238418579, 0.6000000238418579, -0.6000000238418579, 1.0, -0.6000000238418579, -1.0, -0.20000000298023224, -0.6000000238418579, -0.20000000298023224, -0.20000000298023224, -0.20000000298023224, 0.20000000298023224, -0.20000000298023224, 0.6000000238418579, -0.20000000298023224, 1.0, -0.20000000298023224, -1.0, 0.20000000298023224, -0.6000000238418579, 0.20000000298023224, -0.20000000298023224, 0.20000000298023224, 0.20000000298023224, 0.20000000298023224, 0.6000000238418579, 0.20000000298023224, 1.0, 0.20000000298023224, -1.0, 0.6000000238418579, -0.6000000238418579, 0.6000000238418579, -0.20000000298023224, 0.6000000238418579, 0.20000000298023224, 0.6000000238418579, 0.6000000238418579, 0.6000000238418579, 1.0, 0.6000000238418579, -1.0, 1.0, -0.6000000238418579, 1.0, -0.20000000298023224, 1.0, 0.20000000298023224, 1.0, 0.6000000238418579, 1.0, 1.0, 1.0]
946
+ }
947
+ }
948
+ },
949
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 6, 6], "tolerance": 0.0001 } },
950
+ "attrs": { "align_corners": 0, "mode": "linear", "padding_mode": "zeros" }
951
+ },
952
+ {
953
+ "name": "onnx_backend_gridsample_aligncorners_true",
954
+ "provenance": { "source": "cmake/external/onnx/onnx/backend/test/data/node/test_gridsample_aligncorners_true" },
955
+ "inputs": {
956
+ "x": {
957
+ "dtype": "float32",
958
+ "shape": [1, 1, 3, 2],
959
+ "data": { "kind": "values", "values": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0] }
960
+ },
961
+ "grid": {
962
+ "dtype": "float32",
963
+ "shape": [1, 2, 4, 2],
964
+ "data": {
965
+ "kind": "values",
966
+ "values": { "$ref": "#/fixtureArrays/onnx_backend_gridsample_aligncorners_true_input_grid" }
967
+ }
968
+ }
969
+ },
970
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 2, 4], "tolerance": 0.0001 } },
971
+ "attrs": { "align_corners": 1, "mode": "linear" }
972
+ },
973
+ {
974
+ "name": "onnx_backend_gridsample_bicubic",
975
+ "provenance": { "source": "cmake/external/onnx/onnx/backend/test/data/node/test_gridsample_bicubic" },
976
+ "inputs": {
977
+ "x": {
978
+ "dtype": "float32",
979
+ "shape": [1, 1, 3, 2],
980
+ "data": { "kind": "values", "values": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0] }
981
+ },
982
+ "grid": {
983
+ "dtype": "float32",
984
+ "shape": [1, 2, 4, 2],
985
+ "data": {
986
+ "kind": "values",
987
+ "values": { "$ref": "#/fixtureArrays/onnx_backend_gridsample_aligncorners_true_input_grid" }
988
+ }
989
+ }
990
+ },
991
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 2, 4], "tolerance": 0.0001 } },
992
+ "attrs": { "mode": "cubic" }
993
+ },
994
+ {
995
+ "name": "onnx_backend_gridsample_bicubic_align_corners_0_additional_1",
996
+ "provenance": {
997
+ "source": "cmake/external/onnx/onnx/backend/test/data/node/test_gridsample_bicubic_align_corners_0_additional_1"
998
+ },
999
+ "inputs": {
1000
+ "x": {
1001
+ "dtype": "float32",
1002
+ "shape": [1, 1, 3, 2],
1003
+ "data": { "kind": "values", "values": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0] }
1004
+ },
1005
+ "grid": {
1006
+ "dtype": "float32",
1007
+ "shape": [1, 2, 4, 2],
1008
+ "data": { "kind": "values", "values": { "$ref": "#/fixtureArrays/grid_sample_grid_16" } }
1009
+ }
1010
+ },
1011
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 2, 4], "tolerance": 0.0001 } },
1012
+ "attrs": { "align_corners": 0, "mode": "cubic" }
1013
+ },
1014
+ {
1015
+ "name": "onnx_backend_gridsample_bicubic_align_corners_1_additional_1",
1016
+ "provenance": {
1017
+ "source": "cmake/external/onnx/onnx/backend/test/data/node/test_gridsample_bicubic_align_corners_1_additional_1"
1018
+ },
1019
+ "inputs": {
1020
+ "x": {
1021
+ "dtype": "float32",
1022
+ "shape": [1, 1, 3, 2],
1023
+ "data": { "kind": "values", "values": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0] }
1024
+ },
1025
+ "grid": {
1026
+ "dtype": "float32",
1027
+ "shape": [1, 2, 4, 2],
1028
+ "data": { "kind": "values", "values": { "$ref": "#/fixtureArrays/grid_sample_grid_16" } }
1029
+ }
1030
+ },
1031
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 2, 4], "tolerance": 0.0001 } },
1032
+ "attrs": { "align_corners": 1, "mode": "cubic" }
1033
+ },
1034
+ {
1035
+ "name": "onnx_backend_gridsample_bilinear",
1036
+ "provenance": { "source": "cmake/external/onnx/onnx/backend/test/data/node/test_gridsample_bilinear" },
1037
+ "inputs": {
1038
+ "x": {
1039
+ "dtype": "float32",
1040
+ "shape": [1, 1, 3, 2],
1041
+ "data": { "kind": "values", "values": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0] }
1042
+ },
1043
+ "grid": {
1044
+ "dtype": "float32",
1045
+ "shape": [1, 2, 4, 2],
1046
+ "data": {
1047
+ "kind": "values",
1048
+ "values": { "$ref": "#/fixtureArrays/onnx_backend_gridsample_aligncorners_true_input_grid" }
1049
+ }
1050
+ }
1051
+ },
1052
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 2, 4], "tolerance": 0.0001 } },
1053
+ "attrs": { "mode": "linear" }
1054
+ },
1055
+ {
1056
+ "name": "onnx_backend_gridsample_bilinear_align_corners_0_additional_1",
1057
+ "provenance": {
1058
+ "source": "cmake/external/onnx/onnx/backend/test/data/node/test_gridsample_bilinear_align_corners_0_additional_1"
1059
+ },
1060
+ "inputs": {
1061
+ "x": {
1062
+ "dtype": "float32",
1063
+ "shape": [1, 1, 3, 2],
1064
+ "data": { "kind": "values", "values": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0] }
1065
+ },
1066
+ "grid": {
1067
+ "dtype": "float32",
1068
+ "shape": [1, 2, 4, 2],
1069
+ "data": { "kind": "values", "values": { "$ref": "#/fixtureArrays/grid_sample_grid_16" } }
1070
+ }
1071
+ },
1072
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 2, 4], "tolerance": 0.0001 } },
1073
+ "attrs": { "align_corners": 0, "mode": "linear" }
1074
+ },
1075
+ {
1076
+ "name": "onnx_backend_gridsample_bilinear_align_corners_1_additional_1",
1077
+ "provenance": {
1078
+ "source": "cmake/external/onnx/onnx/backend/test/data/node/test_gridsample_bilinear_align_corners_1_additional_1"
1079
+ },
1080
+ "inputs": {
1081
+ "x": {
1082
+ "dtype": "float32",
1083
+ "shape": [1, 1, 3, 2],
1084
+ "data": { "kind": "values", "values": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0] }
1085
+ },
1086
+ "grid": {
1087
+ "dtype": "float32",
1088
+ "shape": [1, 2, 4, 2],
1089
+ "data": { "kind": "values", "values": { "$ref": "#/fixtureArrays/grid_sample_grid_16" } }
1090
+ }
1091
+ },
1092
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 2, 4], "tolerance": 0.0001 } },
1093
+ "attrs": { "align_corners": 1, "mode": "linear" }
1094
+ },
1095
+ {
1096
+ "name": "onnx_backend_gridsample_border_padding",
1097
+ "provenance": { "source": "cmake/external/onnx/onnx/backend/test/data/node/test_gridsample_border_padding" },
1098
+ "inputs": {
1099
+ "x": {
1100
+ "dtype": "float32",
1101
+ "shape": [1, 1, 3, 2],
1102
+ "data": { "kind": "values", "values": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0] }
1103
+ },
1104
+ "grid": {
1105
+ "dtype": "float32",
1106
+ "shape": [1, 2, 4, 2],
1107
+ "data": {
1108
+ "kind": "values",
1109
+ "values": { "$ref": "#/fixtureArrays/onnx_backend_gridsample_border_padding_input_grid" }
1110
+ }
1111
+ }
1112
+ },
1113
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 2, 4], "tolerance": 0.0001 } },
1114
+ "attrs": { "padding_mode": "border" }
1115
+ },
1116
+ {
1117
+ "name": "onnx_backend_gridsample_nearest",
1118
+ "provenance": { "source": "cmake/external/onnx/onnx/backend/test/data/node/test_gridsample_nearest" },
1119
+ "inputs": {
1120
+ "x": {
1121
+ "dtype": "float32",
1122
+ "shape": [1, 1, 3, 2],
1123
+ "data": { "kind": "values", "values": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0] }
1124
+ },
1125
+ "grid": {
1126
+ "dtype": "float32",
1127
+ "shape": [1, 2, 4, 2],
1128
+ "data": {
1129
+ "kind": "values",
1130
+ "values": { "$ref": "#/fixtureArrays/onnx_backend_gridsample_aligncorners_true_input_grid" }
1131
+ }
1132
+ }
1133
+ },
1134
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 2, 4], "tolerance": 0.0001 } },
1135
+ "attrs": { "mode": "nearest" }
1136
+ },
1137
+ {
1138
+ "name": "onnx_backend_gridsample_nearest_align_corners_0_additional_1",
1139
+ "provenance": {
1140
+ "source": "cmake/external/onnx/onnx/backend/test/data/node/test_gridsample_nearest_align_corners_0_additional_1"
1141
+ },
1142
+ "inputs": {
1143
+ "x": {
1144
+ "dtype": "float32",
1145
+ "shape": [1, 1, 3, 2],
1146
+ "data": { "kind": "values", "values": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0] }
1147
+ },
1148
+ "grid": {
1149
+ "dtype": "float32",
1150
+ "shape": [1, 2, 4, 2],
1151
+ "data": { "kind": "values", "values": { "$ref": "#/fixtureArrays/grid_sample_grid_16" } }
1152
+ }
1153
+ },
1154
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 2, 4], "tolerance": 0.0001 } },
1155
+ "attrs": { "align_corners": 0, "mode": "nearest" }
1156
+ },
1157
+ {
1158
+ "name": "onnx_backend_gridsample_nearest_align_corners_1_additional_1",
1159
+ "provenance": {
1160
+ "source": "cmake/external/onnx/onnx/backend/test/data/node/test_gridsample_nearest_align_corners_1_additional_1"
1161
+ },
1162
+ "inputs": {
1163
+ "x": {
1164
+ "dtype": "float32",
1165
+ "shape": [1, 1, 3, 2],
1166
+ "data": { "kind": "values", "values": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0] }
1167
+ },
1168
+ "grid": {
1169
+ "dtype": "float32",
1170
+ "shape": [1, 2, 4, 2],
1171
+ "data": { "kind": "values", "values": { "$ref": "#/fixtureArrays/grid_sample_grid_16" } }
1172
+ }
1173
+ },
1174
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 2, 4], "tolerance": 0.0001 } },
1175
+ "attrs": { "align_corners": 1, "mode": "nearest" }
1176
+ },
1177
+ {
1178
+ "name": "onnx_backend_gridsample_reflection_padding",
1179
+ "provenance": { "source": "cmake/external/onnx/onnx/backend/test/data/node/test_gridsample_reflection_padding" },
1180
+ "inputs": {
1181
+ "x": {
1182
+ "dtype": "float32",
1183
+ "shape": [1, 1, 3, 2],
1184
+ "data": { "kind": "values", "values": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0] }
1185
+ },
1186
+ "grid": {
1187
+ "dtype": "float32",
1188
+ "shape": [1, 2, 4, 2],
1189
+ "data": {
1190
+ "kind": "values",
1191
+ "values": { "$ref": "#/fixtureArrays/onnx_backend_gridsample_border_padding_input_grid" }
1192
+ }
1193
+ }
1194
+ },
1195
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 2, 4], "tolerance": 0.0001 } },
1196
+ "attrs": { "padding_mode": "reflection" }
1197
+ },
1198
+ {
1199
+ "name": "onnx_backend_gridsample_zeros_padding",
1200
+ "provenance": { "source": "cmake/external/onnx/onnx/backend/test/data/node/test_gridsample_zeros_padding" },
1201
+ "inputs": {
1202
+ "x": {
1203
+ "dtype": "float32",
1204
+ "shape": [1, 1, 3, 2],
1205
+ "data": { "kind": "values", "values": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0] }
1206
+ },
1207
+ "grid": {
1208
+ "dtype": "float32",
1209
+ "shape": [1, 2, 4, 2],
1210
+ "data": {
1211
+ "kind": "values",
1212
+ "values": { "$ref": "#/fixtureArrays/onnx_backend_gridsample_border_padding_input_grid" }
1213
+ }
1214
+ }
1215
+ },
1216
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 2, 4], "tolerance": 0.0001 } },
1217
+ "attrs": { "padding_mode": "zeros" }
1218
+ },
1219
+ {
1220
+ "name": "onnx_backend_gridsample_volumetric_bilinear_align_corners_0",
1221
+ "provenance": {
1222
+ "source": "cmake/external/onnx/onnx/backend/test/data/node/test_gridsample_volumetric_bilinear_align_corners_0"
1223
+ },
1224
+ "attrs": { "mode": "linear", "padding_mode": "zeros", "align_corners": 0 },
1225
+ "inputs": {
1226
+ "x": {
1227
+ "dtype": "float32",
1228
+ "shape": [1, 1, 3, 2, 2],
1229
+ "data": { "kind": "values", "values": [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0] }
1230
+ },
1231
+ "grid": {
1232
+ "dtype": "float32",
1233
+ "shape": [1, 2, 4, 2, 3],
1234
+ "data": {
1235
+ "kind": "values",
1236
+ "values": { "$ref": "#/fixtureArrays/onnx_backend_gridsample_volumetric_input_grid" }
1237
+ }
1238
+ }
1239
+ },
1240
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 2, 4, 2], "tolerance": 0.00001 } }
1241
+ },
1242
+ {
1243
+ "name": "onnx_backend_gridsample_volumetric_bilinear_align_corners_1",
1244
+ "provenance": {
1245
+ "source": "cmake/external/onnx/onnx/backend/test/data/node/test_gridsample_volumetric_bilinear_align_corners_1"
1246
+ },
1247
+ "attrs": { "mode": "linear", "padding_mode": "zeros", "align_corners": 1 },
1248
+ "inputs": {
1249
+ "x": {
1250
+ "dtype": "float32",
1251
+ "shape": [1, 1, 3, 2, 2],
1252
+ "data": { "kind": "values", "values": [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0] }
1253
+ },
1254
+ "grid": {
1255
+ "dtype": "float32",
1256
+ "shape": [1, 2, 4, 2, 3],
1257
+ "data": {
1258
+ "kind": "values",
1259
+ "values": { "$ref": "#/fixtureArrays/onnx_backend_gridsample_volumetric_input_grid" }
1260
+ }
1261
+ }
1262
+ },
1263
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 2, 4, 2], "tolerance": 0.00001 } }
1264
+ },
1265
+ {
1266
+ "name": "onnx_backend_gridsample_volumetric_nearest_align_corners_0",
1267
+ "provenance": {
1268
+ "source": "cmake/external/onnx/onnx/backend/test/data/node/test_gridsample_volumetric_nearest_align_corners_0"
1269
+ },
1270
+ "attrs": { "mode": "nearest", "padding_mode": "zeros", "align_corners": 0 },
1271
+ "inputs": {
1272
+ "x": {
1273
+ "dtype": "float32",
1274
+ "shape": [1, 1, 3, 2, 2],
1275
+ "data": { "kind": "values", "values": [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0] }
1276
+ },
1277
+ "grid": {
1278
+ "dtype": "float32",
1279
+ "shape": [1, 2, 4, 2, 3],
1280
+ "data": {
1281
+ "kind": "values",
1282
+ "values": { "$ref": "#/fixtureArrays/onnx_backend_gridsample_volumetric_input_grid" }
1283
+ }
1284
+ }
1285
+ },
1286
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 2, 4, 2], "tolerance": 0 } }
1287
+ },
1288
+ {
1289
+ "name": "onnx_backend_gridsample_volumetric_nearest_align_corners_1",
1290
+ "provenance": {
1291
+ "source": "cmake/external/onnx/onnx/backend/test/data/node/test_gridsample_volumetric_nearest_align_corners_1"
1292
+ },
1293
+ "attrs": { "mode": "nearest", "padding_mode": "zeros", "align_corners": 1 },
1294
+ "inputs": {
1295
+ "x": {
1296
+ "dtype": "float32",
1297
+ "shape": [1, 1, 3, 2, 2],
1298
+ "data": { "kind": "values", "values": [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0] }
1299
+ },
1300
+ "grid": {
1301
+ "dtype": "float32",
1302
+ "shape": [1, 2, 4, 2, 3],
1303
+ "data": {
1304
+ "kind": "values",
1305
+ "values": { "$ref": "#/fixtureArrays/onnx_backend_gridsample_volumetric_input_grid" }
1306
+ }
1307
+ }
1308
+ },
1309
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 2, 4, 2], "tolerance": 0 } }
1310
+ },
1311
+ {
1312
+ "name": "ort_5d_nearest_zeros_align_corners_simple",
1313
+ "provenance": {
1314
+ "source": "onnxruntime/test/providers/cpu/tensor/grid_sample_test.cc",
1315
+ "test": "GridSampleTest.test_grid_sample_20_5D_nearest_zeros_align_corners",
1316
+ "notes": "Compact node-level projection of ORT's generated 5D nearest zeros case."
1317
+ },
1318
+ "attrs": { "mode": "nearest", "padding_mode": "zeros", "align_corners": 1 },
1319
+ "inputs": {
1320
+ "x": {
1321
+ "dtype": "float32",
1322
+ "shape": [1, 1, 2, 2, 2],
1323
+ "data": { "kind": "values", "values": [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0] }
1324
+ },
1325
+ "grid": {
1326
+ "dtype": "float32",
1327
+ "shape": [1, 1, 1, 3, 3],
1328
+ "data": { "kind": "values", "values": [-1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 3.0, 0.0, 0.0] }
1329
+ }
1330
+ },
1331
+ "outputs": {
1332
+ "y": {
1333
+ "dtype": "float32",
1334
+ "shape": [1, 1, 1, 1, 3],
1335
+ "tolerance": 0,
1336
+ "data": { "kind": "values", "values": [1.0, 8.0, 0.0] }
1337
+ }
1338
+ }
1339
+ },
1340
+ {
1341
+ "name": "ort_5d_nearest_zeros_no_align_corners_simple",
1342
+ "provenance": {
1343
+ "source": "onnxruntime/test/providers/cpu/tensor/grid_sample_test.cc",
1344
+ "test": "GridSampleTest.test_grid_sample_20_5D_nearest_zeros_no_align_corners",
1345
+ "notes": "Uses normalized coordinates that map exactly to both volume corners when align_corners=0."
1346
+ },
1347
+ "attrs": { "mode": "nearest", "padding_mode": "zeros", "align_corners": 0 },
1348
+ "inputs": {
1349
+ "x": {
1350
+ "dtype": "float32",
1351
+ "shape": [1, 1, 2, 2, 2],
1352
+ "data": { "kind": "values", "values": [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0] }
1353
+ },
1354
+ "grid": {
1355
+ "dtype": "float32",
1356
+ "shape": [1, 1, 1, 3, 3],
1357
+ "data": { "kind": "values", "values": [-0.5, -0.5, -0.5, 0.5, 0.5, 0.5, 1.5, 0.0, 0.0] }
1358
+ }
1359
+ },
1360
+ "outputs": {
1361
+ "y": {
1362
+ "dtype": "float32",
1363
+ "shape": [1, 1, 1, 1, 3],
1364
+ "tolerance": 0,
1365
+ "data": { "kind": "values", "values": [1.0, 8.0, 0.0] }
1366
+ }
1367
+ }
1368
+ },
1369
+ {
1370
+ "name": "ort_5d_linear_zeros_align_corners_simple",
1371
+ "provenance": {
1372
+ "source": "onnxruntime/test/providers/cpu/tensor/grid_sample_test.cc",
1373
+ "test": "GridSampleTest.test_grid_sample_20_5D_bilinear_zeros_align_corners",
1374
+ "notes": "Opset-20 5D bilinear is represented as mode=linear."
1375
+ },
1376
+ "attrs": { "mode": "linear", "padding_mode": "zeros", "align_corners": 1 },
1377
+ "inputs": {
1378
+ "x": {
1379
+ "dtype": "float32",
1380
+ "shape": [1, 1, 2, 2, 2],
1381
+ "data": { "kind": "values", "values": [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0] }
1382
+ },
1383
+ "grid": {
1384
+ "dtype": "float32",
1385
+ "shape": [1, 1, 1, 3, 3],
1386
+ "data": { "kind": "values", "values": [-1.0, -1.0, -1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0] }
1387
+ }
1388
+ },
1389
+ "outputs": {
1390
+ "y": {
1391
+ "dtype": "float32",
1392
+ "shape": [1, 1, 1, 1, 3],
1393
+ "tolerance": 0.000001,
1394
+ "data": { "kind": "values", "values": [1.0, 4.5, 8.0] }
1395
+ }
1396
+ }
1397
+ },
1398
+ {
1399
+ "name": "ort_5d_linear_zeros_no_align_corners_simple",
1400
+ "provenance": {
1401
+ "source": "onnxruntime/test/providers/cpu/tensor/grid_sample_test.cc",
1402
+ "test": "GridSampleTest.test_grid_sample_22_5D_bilinear_zeros_no_align_corners",
1403
+ "notes": "Uses exact corner/center coordinates for align_corners=0."
1404
+ },
1405
+ "attrs": { "mode": "linear", "padding_mode": "zeros", "align_corners": 0 },
1406
+ "inputs": {
1407
+ "x": {
1408
+ "dtype": "float32",
1409
+ "shape": [1, 1, 2, 2, 2],
1410
+ "data": { "kind": "values", "values": [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0] }
1411
+ },
1412
+ "grid": {
1413
+ "dtype": "float32",
1414
+ "shape": [1, 1, 1, 3, 3],
1415
+ "data": { "kind": "values", "values": [-0.5, -0.5, -0.5, 0.0, 0.0, 0.0, 0.5, 0.5, 0.5] }
1416
+ }
1417
+ },
1418
+ "outputs": {
1419
+ "y": {
1420
+ "dtype": "float32",
1421
+ "shape": [1, 1, 1, 1, 3],
1422
+ "tolerance": 0.000001,
1423
+ "data": { "kind": "values", "values": [1.0, 4.5, 8.0] }
1424
+ }
1425
+ }
1426
+ },
1427
+ {
1428
+ "name": "ort_custom_5d_nearest_reflection_extreme_coords",
1429
+ "provenance": {
1430
+ "source": "onnxruntime/test/providers/cpu/tensor/grid_sample_test_custom.cc",
1431
+ "test": "GridSampleCustomTest.test_grid_sample_20_5D_nearest_reflection_extreme_coords"
1432
+ },
1433
+ "attrs": { "mode": "nearest", "padding_mode": "reflection", "align_corners": 0 },
1434
+ "inputs": {
1435
+ "x": { "dtype": "float32", "shape": [1, 1, 2, 2, 2], "data": { "kind": "constant", "value": 1.0 } },
1436
+ "grid": {
1437
+ "dtype": "float32",
1438
+ "shape": [1, 1, 1, 2, 3],
1439
+ "data": {
1440
+ "kind": "values",
1441
+ "values": [10000000000.0, 10000000000.0, 10000000000.0, -10000000000.0, -10000000000.0, -10000000000.0]
1442
+ }
1443
+ }
1444
+ },
1445
+ "outputs": {
1446
+ "y": {
1447
+ "dtype": "float32",
1448
+ "shape": [1, 1, 1, 1, 2],
1449
+ "tolerance": 0,
1450
+ "data": { "kind": "values", "values": [1.0, 1.0] }
1451
+ }
1452
+ }
1453
+ },
1454
+ {
1455
+ "name": "ort_5d_nearest_border_no_align_corners",
1456
+ "provenance": {
1457
+ "source": "onnxruntime/test/providers/cpu/tensor/grid_sample_test.cc",
1458
+ "test": "GridSampleTest.test_grid_sample_20_5D_nearest_border_no_align_corners",
1459
+ "notes": "Compact projection of ORT's generated 5D nearest border/no-align case."
1460
+ },
1461
+ "attrs": { "mode": "nearest", "padding_mode": "border", "align_corners": 0 },
1462
+ "inputs": {
1463
+ "x": {
1464
+ "dtype": "float32",
1465
+ "shape": [1, 1, 2, 2, 2],
1466
+ "data": { "kind": "values", "values": [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0] }
1467
+ },
1468
+ "grid": {
1469
+ "dtype": "float32",
1470
+ "shape": [1, 1, 1, 3, 3],
1471
+ "data": { "kind": "values", "values": [-2.0, -2.0, -2.0, 0.5, 0.5, 0.5, 2.0, 2.0, 2.0] }
1472
+ }
1473
+ },
1474
+ "outputs": {
1475
+ "y": {
1476
+ "dtype": "float32",
1477
+ "shape": [1, 1, 1, 1, 3],
1478
+ "tolerance": 0,
1479
+ "data": { "kind": "values", "values": [1.0, 8.0, 8.0] }
1480
+ }
1481
+ }
1482
+ },
1483
+ {
1484
+ "name": "ort_5d_nearest_reflection_align_corners",
1485
+ "provenance": {
1486
+ "source": "onnxruntime/test/providers/cpu/tensor/grid_sample_test.cc",
1487
+ "test": "GridSampleTest.test_grid_sample_20_5D_nearest_reflection_align_corners",
1488
+ "notes": "Compact projection of ORT's generated 5D nearest reflection/align-corners case."
1489
+ },
1490
+ "attrs": { "mode": "nearest", "padding_mode": "reflection", "align_corners": 1 },
1491
+ "inputs": {
1492
+ "x": {
1493
+ "dtype": "float32",
1494
+ "shape": [1, 1, 2, 2, 2],
1495
+ "data": { "kind": "values", "values": [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0] }
1496
+ },
1497
+ "grid": {
1498
+ "dtype": "float32",
1499
+ "shape": [1, 1, 1, 3, 3],
1500
+ "data": { "kind": "values", "values": [-2.0, -2.0, -2.0, 0.0, 0.0, 0.0, 2.0, 2.0, 2.0] }
1501
+ }
1502
+ },
1503
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 1, 1, 3], "tolerance": 0 } }
1504
+ },
1505
+ {
1506
+ "name": "ort_5d_linear_border_align_corners",
1507
+ "provenance": {
1508
+ "source": "onnxruntime/test/providers/cpu/tensor/grid_sample_test.cc",
1509
+ "test": "GridSampleTest.test_grid_sample_22_5D_bilinear_border_align_corners",
1510
+ "notes": "Compact opset-20 projection using mode=linear for ORT's generated 5D bilinear border/align-corners case."
1511
+ },
1512
+ "attrs": { "mode": "linear", "padding_mode": "border", "align_corners": 1 },
1513
+ "inputs": {
1514
+ "x": {
1515
+ "dtype": "float32",
1516
+ "shape": [1, 1, 2, 2, 2],
1517
+ "data": { "kind": "values", "values": [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0] }
1518
+ },
1519
+ "grid": {
1520
+ "dtype": "float32",
1521
+ "shape": [1, 1, 1, 3, 3],
1522
+ "data": { "kind": "values", "values": [-2.0, -2.0, -2.0, 0.0, 0.0, 0.0, 2.0, 2.0, 2.0] }
1523
+ }
1524
+ },
1525
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 1, 1, 3], "tolerance": 0.000001 } }
1526
+ },
1527
+ {
1528
+ "name": "ort_5d_linear_reflection_no_align_corners",
1529
+ "provenance": {
1530
+ "source": "onnxruntime/test/providers/cpu/tensor/grid_sample_test.cc",
1531
+ "test": "GridSampleTest.test_grid_sample_22_5D_bilinear_reflection_no_align_corners",
1532
+ "notes": "Compact opset-20 projection using mode=linear for ORT's generated 5D bilinear reflection/no-align case."
1533
+ },
1534
+ "attrs": { "mode": "linear", "padding_mode": "reflection", "align_corners": 0 },
1535
+ "inputs": {
1536
+ "x": {
1537
+ "dtype": "float32",
1538
+ "shape": [1, 1, 2, 2, 2],
1539
+ "data": { "kind": "values", "values": [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0] }
1540
+ },
1541
+ "grid": {
1542
+ "dtype": "float32",
1543
+ "shape": [1, 1, 1, 3, 3],
1544
+ "data": { "kind": "values", "values": [-2.0, -2.0, -2.0, 0.0, 0.0, 0.0, 2.0, 2.0, 2.0] }
1545
+ }
1546
+ },
1547
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 1, 1, 3], "tolerance": 0.000001 } }
1548
+ },
1549
+ {
1550
+ "name": "ort_5d_nearest_border_align_corners",
1551
+ "provenance": {
1552
+ "source": "onnxruntime/test/providers/cpu/tensor/grid_sample_test.cc",
1553
+ "test": "GridSampleTest.test_grid_sample_20_5D_nearest_border_align_corners",
1554
+ "notes": "Compact 5D border-padding projection of ORT's generated align-corners case."
1555
+ },
1556
+ "attrs": { "mode": "nearest", "padding_mode": "border", "align_corners": 1 },
1557
+ "inputs": {
1558
+ "x": {
1559
+ "dtype": "float32",
1560
+ "shape": [1, 1, 2, 2, 2],
1561
+ "data": { "kind": "values", "values": [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0] }
1562
+ },
1563
+ "grid": {
1564
+ "dtype": "float32",
1565
+ "shape": [1, 1, 1, 4, 3],
1566
+ "data": { "kind": "values", "values": [-2.0, -2.0, -2.0, 2.0, 2.0, 2.0, 0.2, -0.2, 0.6, -0.6, 0.6, -0.2] }
1567
+ }
1568
+ },
1569
+ "outputs": {
1570
+ "y": {
1571
+ "dtype": "float32",
1572
+ "shape": [1, 1, 1, 1, 4],
1573
+ "tolerance": 0,
1574
+ "data": { "kind": "values", "values": [1.0, 8.0, 6.0, 3.0] }
1575
+ }
1576
+ }
1577
+ },
1578
+ {
1579
+ "name": "ort_custom_5d_nearest_reflection_nan_inf_coords",
1580
+ "provenance": {
1581
+ "source": "onnxruntime/test/providers/cpu/tensor/grid_sample_test_custom.cc",
1582
+ "test": "GridSampleCustomTest.test_grid_sample_20_5D_nearest_reflection_nan_inf_coords"
1583
+ },
1584
+ "attrs": { "mode": "nearest", "padding_mode": "reflection", "align_corners": 0 },
1585
+ "inputs": {
1586
+ "x": { "dtype": "float32", "shape": [1, 1, 2, 2, 2], "data": { "kind": "constant", "value": 1.0 } },
1587
+ "grid": {
1588
+ "dtype": "float32",
1589
+ "shape": [1, 1, 1, 2, 3],
1590
+ "data": { "kind": "values", "values": ["NaN", "Infinity", "-Infinity", "Infinity", "NaN", "-Infinity"] }
1591
+ }
1592
+ },
1593
+ "outputs": {
1594
+ "y": {
1595
+ "dtype": "float32",
1596
+ "shape": [1, 1, 1, 1, 2],
1597
+ "tolerance": 0,
1598
+ "data": { "kind": "values", "values": [1.0, 1.0] }
1599
+ }
1600
+ }
1601
+ },
1602
+ {
1603
+ "name": "ort_linear_zeros_no_align_corners_compact",
1604
+ "provenance": {
1605
+ "source": "onnxruntime/test/providers/cpu/tensor/grid_sample_test.cc",
1606
+ "test": "GridSampleTest.test_grid_sample_16_4D_bilinear_zeros_no_align_corners",
1607
+ "notes": "Opset-20 spelling uses mode=linear for ORT's generated 4D bilinear no-align case."
1608
+ },
1609
+ "attrs": { "mode": "linear", "padding_mode": "zeros", "align_corners": 0 },
1610
+ "inputs": {
1611
+ "x": {
1612
+ "dtype": "float32",
1613
+ "shape": [1, 1, 3, 3],
1614
+ "data": { "kind": "values", "values": [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0] }
1615
+ },
1616
+ "grid": {
1617
+ "dtype": "float32",
1618
+ "shape": [1, 2, 3, 2],
1619
+ "data": { "kind": "values", "values": [-1.0, -1.0, 0.0, 0.0, 1.0, 1.0, -1.2, 0.4, 0.4, -1.2, 1.2, 1.2] }
1620
+ }
1621
+ },
1622
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 2, 3], "tolerance": 0.000001 } }
1623
+ },
1624
+ {
1625
+ "name": "ort_linear_reflection_no_align_corners_compact",
1626
+ "provenance": {
1627
+ "source": "onnxruntime/test/providers/cpu/tensor/grid_sample_test.cc",
1628
+ "test": "GridSampleTest.test_grid_sample_16_4D_bilinear_reflection_no_align_corners",
1629
+ "notes": "Compact projection of ORT's 4D bilinear reflection no-align coverage."
1630
+ },
1631
+ "attrs": { "mode": "linear", "padding_mode": "reflection", "align_corners": 0 },
1632
+ "inputs": {
1633
+ "x": {
1634
+ "dtype": "float32",
1635
+ "shape": [1, 1, 3, 3],
1636
+ "data": { "kind": "values", "values": [1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0] }
1637
+ },
1638
+ "grid": {
1639
+ "dtype": "float32",
1640
+ "shape": [1, 2, 2, 2],
1641
+ "data": { "kind": "values", "values": [-1.4, -1.4, 1.4, 1.4, -0.2, 0.6, 2.2, -0.6] }
1642
+ }
1643
+ },
1644
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 2, 2], "tolerance": 0.00001 } }
1645
+ },
1646
+ {
1647
+ "name": "ort_cubic_zeros_no_align_corners_compact",
1648
+ "provenance": {
1649
+ "source": "onnxruntime/test/providers/cpu/tensor/grid_sample_test.cc",
1650
+ "test": "GridSampleTest.test_grid_sample_20_4D_bicubic_zeros_no_align_corners",
1651
+ "notes": "Opset-20 spelling uses mode=cubic for ORT's generated 4D bicubic zeros no-align case."
1652
+ },
1653
+ "attrs": { "mode": "cubic", "padding_mode": "zeros", "align_corners": 0 },
1654
+ "inputs": {
1655
+ "x": {
1656
+ "dtype": "float32",
1657
+ "shape": [1, 1, 4, 4],
1658
+ "data": { "kind": "values", "values": { "$ref": "#/fixtureArrays/onnx_backend_gridsample_input_x" } }
1659
+ },
1660
+ "grid": {
1661
+ "dtype": "float32",
1662
+ "shape": [1, 2, 2, 2],
1663
+ "data": { "kind": "values", "values": [-0.6, -0.6, 0.4, -0.2, 1.2, 1.2, -1.1, 0.3] }
1664
+ }
1665
+ },
1666
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 2, 2], "tolerance": 0.0001 } }
1667
+ },
1668
+ {
1669
+ "name": "ort_linear_border_rank5_no_align_corners",
1670
+ "provenance": {
1671
+ "source": "onnxruntime/test/providers/cpu/tensor/grid_sample_test.cc",
1672
+ "test": "GridSampleTest.test_grid_sample_22_5D_bilinear_border_no_align_corners",
1673
+ "notes": "Valid 5D trilinear border-padding case."
1674
+ },
1675
+ "attrs": { "mode": "linear", "padding_mode": "border", "align_corners": 0 },
1676
+ "inputs": {
1677
+ "x": {
1678
+ "dtype": "float32",
1679
+ "shape": [1, 1, 2, 2, 2],
1680
+ "data": { "kind": "values", "values": [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0] }
1681
+ },
1682
+ "grid": {
1683
+ "dtype": "float32",
1684
+ "shape": [1, 1, 1, 3, 3],
1685
+ "data": { "kind": "values", "values": [-1.2, -1.2, -1.2, 0.0, 0.0, 0.0, 1.2, 1.2, 1.2] }
1686
+ }
1687
+ },
1688
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 1, 1, 1, 3], "tolerance": 0.000001 } }
1689
+ },
1690
+ {
1691
+ "name": "ort_linear_reflection_rank5_extreme",
1692
+ "provenance": {
1693
+ "source": "onnxruntime/test/providers/cpu/tensor/grid_sample_test_custom.cc",
1694
+ "test": "GridSampleCustomTest.test_grid_sample_20_5D_linear_reflection_extreme_coords",
1695
+ "notes": "Valid 5D trilinear reflection-padding case with extreme coordinates."
1696
+ },
1697
+ "attrs": { "mode": "linear", "padding_mode": "reflection", "align_corners": 0 },
1698
+ "inputs": {
1699
+ "x": { "dtype": "float32", "shape": [1, 1, 2, 2, 2], "data": { "kind": "constant", "value": 1.0 } },
1700
+ "grid": {
1701
+ "dtype": "float32",
1702
+ "shape": [1, 1, 1, 2, 3],
1703
+ "data": {
1704
+ "kind": "values",
1705
+ "values": [100000000000000000000.0, 100000000000000000000.0, 100000000000000000000.0, -100000000000000000000.0, -100000000000000000000.0, -100000000000000000000.0]
1706
+ }
1707
+ }
1708
+ },
1709
+ "outputs": {
1710
+ "y": {
1711
+ "dtype": "float32",
1712
+ "shape": [1, 1, 1, 1, 2],
1713
+ "data": { "kind": "values", "values": [1.0, 1.0] },
1714
+ "tolerance": 0.000001
1715
+ }
1716
+ }
1717
+ },
1718
+ {
1719
+ "name": "empty_input_zero_dim",
1720
+ "attrs": { "mode": "linear", "padding_mode": "zeros", "align_corners": 1 },
1721
+ "inputs": {
1722
+ "x": { "dtype": "float32", "shape": [0, 1, 2, 2], "data": { "kind": "values", "values": [] } },
1723
+ "grid": { "dtype": "float32", "shape": [0, 2, 2, 2], "data": { "kind": "values", "values": [] } }
1724
+ },
1725
+ "outputs": { "y": { "dtype": "float32", "shape": [0, 1, 2, 2], "tolerance": 0 } }
1726
+ },
1727
+ {
1728
+ "name": "ort_caseB_empty",
1729
+ "attrs": { "mode": "linear", "padding_mode": "zeros", "align_corners": 1 },
1730
+ "inputs": {
1731
+ "x": { "dtype": "float32", "shape": [1, 1, 0, 2], "data": { "kind": "values", "values": [] } },
1732
+ "grid": {
1733
+ "dtype": "float32",
1734
+ "shape": [1, 2, 2, 2],
1735
+ "data": { "kind": "values", "values": [-1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0] }
1736
+ }
1737
+ },
1738
+ "outputs": {
1739
+ "y": {
1740
+ "dtype": "float32",
1741
+ "shape": [1, 1, 2, 2],
1742
+ "data": { "kind": "values", "values": [0.0, 0.0, 0.0, 0.0] },
1743
+ "tolerance": 0.001
1744
+ }
1745
+ }
1746
+ },
1747
+ {
1748
+ "name": "f16_linear_zeros_feature_warp",
1749
+ "attrs": { "mode": "linear", "padding_mode": "zeros", "align_corners": 0 },
1750
+ "inputs": {
1751
+ "x": {
1752
+ "dtype": "float16",
1753
+ "shape": [1, 32, 32, 32],
1754
+ "data": { "kind": "fillFloat32", "scale": 0.5, "sinStep": 0.07, "cosStep": 0.13 }
1755
+ },
1756
+ "grid": {
1757
+ "dtype": "float16",
1758
+ "shape": [1, 32, 32, 2],
1759
+ "data": { "kind": "linspace", "start": -1.0, "end": 1.0 }
1760
+ }
1761
+ },
1762
+ "outputs": { "y": { "dtype": "float16", "shape": [1, 32, 32, 32], "tolerance": 0.02, "relTolerance": 0.02 } }
1763
+ },
1764
+ {
1765
+ "name": "f16_linear_border_align_corners_stn",
1766
+ "attrs": { "mode": "linear", "padding_mode": "border", "align_corners": 1 },
1767
+ "inputs": {
1768
+ "x": {
1769
+ "dtype": "float16",
1770
+ "shape": [1, 16, 24, 24],
1771
+ "data": { "kind": "fillFloat32", "scale": 0.4, "sinStep": 0.11, "cosStep": 0.19 }
1772
+ },
1773
+ "grid": {
1774
+ "dtype": "float16",
1775
+ "shape": [1, 24, 24, 2],
1776
+ "data": { "kind": "linspace", "start": -1.2, "end": 1.2 }
1777
+ }
1778
+ },
1779
+ "outputs": { "y": { "dtype": "float16", "shape": [1, 16, 24, 24], "tolerance": 0.02, "relTolerance": 0.02 } }
1780
+ },
1781
+ {
1782
+ "name": "f16_volumetric_linear_zeros_3d_warp",
1783
+ "attrs": { "mode": "linear", "padding_mode": "zeros", "align_corners": 0 },
1784
+ "inputs": {
1785
+ "x": {
1786
+ "dtype": "float16",
1787
+ "shape": [1, 4, 8, 16, 16],
1788
+ "data": { "kind": "fillFloat32", "scale": 0.5, "sinStep": 0.05, "cosStep": 0.09 }
1789
+ },
1790
+ "grid": {
1791
+ "dtype": "float16",
1792
+ "shape": [1, 8, 16, 16, 3],
1793
+ "data": { "kind": "linspace", "start": -1.0, "end": 1.0 }
1794
+ }
1795
+ },
1796
+ "outputs": { "y": { "dtype": "float16", "shape": [1, 4, 8, 16, 16], "tolerance": 0.03, "relTolerance": 0.03 } }
1797
+ },
1798
+ {
1799
+ "name": "f16_nearest_reflection_warp",
1800
+ "attrs": { "mode": "nearest", "padding_mode": "reflection", "align_corners": 0 },
1801
+ "inputs": {
1802
+ "x": {
1803
+ "dtype": "float16",
1804
+ "shape": [1, 8, 28, 28],
1805
+ "data": { "kind": "fillFloat32", "scale": 0.6, "sinStep": 0.13, "cosStep": 0.23 }
1806
+ },
1807
+ "grid": {
1808
+ "dtype": "float16",
1809
+ "shape": [1, 28, 28, 2],
1810
+ "data": { "kind": "linspace", "start": -1.5, "end": 1.5 }
1811
+ }
1812
+ },
1813
+ "outputs": { "y": { "dtype": "float16", "shape": [1, 8, 28, 28], "tolerance": 0.02, "relTolerance": 0.02 } }
1814
+ },
1815
+ {
1816
+ "name": "empty_output_zero_grid_spatial_nonempty_inputs",
1817
+ "attrs": { "mode": "linear", "padding_mode": "zeros", "align_corners": 0 },
1818
+ "inputs": {
1819
+ "x": {
1820
+ "dtype": "float32",
1821
+ "shape": [1, 2, 3, 4],
1822
+ "data": { "kind": "fillFloat32", "sinStep": 0.7, "scale": 1.0, "offset": 0.0 }
1823
+ },
1824
+ "grid": {
1825
+ "dtype": "float32",
1826
+ "shape": [1, 0, 4, 2],
1827
+ "data": { "kind": "fillFloat32", "sinStep": 0.3, "scale": 1.0, "offset": 0.0 }
1828
+ }
1829
+ },
1830
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 2, 0, 4] } }
1831
+ },
1832
+ {
1833
+ "name": "linear_zeros_fold_boundary_partial_last_row_over16m",
1834
+ "attrs": { "mode": "linear", "padding_mode": "zeros", "align_corners": 0 },
1835
+ "inputs": {
1836
+ "x": {
1837
+ "dtype": "float32",
1838
+ "shape": [1, 3, 16, 16],
1839
+ "data": { "kind": "fillFloat32", "sinStep": 0.13, "scale": 1.0, "offset": 0.0 }
1840
+ },
1841
+ "grid": {
1842
+ "dtype": "float32",
1843
+ "shape": [1, 2049, 2731, 2],
1844
+ "data": { "kind": "fillFloat32", "sinStep": 0.017, "scale": 0.9, "offset": 0.0 }
1845
+ }
1846
+ },
1847
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 3, 2049, 2731] } }
1848
+ },
1849
+ {
1850
+ "name": "cubic_reflection_channel_quad_tail_compact",
1851
+ "provenance": {
1852
+ "source": "ONNX GridSample-20 cubic reflection semantics",
1853
+ "notes": "Exercises channel-cooperative sampling with a non-multiple-of-four channel tail and out-of-range coordinates."
1854
+ },
1855
+ "attrs": { "mode": "cubic", "padding_mode": "reflection", "align_corners": 0 },
1856
+ "inputs": {
1857
+ "x": {
1858
+ "dtype": "float32",
1859
+ "shape": [1, 5, 4, 5],
1860
+ "data": { "kind": "fillFloat32", "sinStep": 0.17, "cosStep": 0.29, "scale": 1.0 }
1861
+ },
1862
+ "grid": { "dtype": "float32", "shape": [1, 3, 4, 2], "data": { "kind": "linspace", "start": -1.6, "end": 1.4 } }
1863
+ },
1864
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 5, 3, 4], "tolerance": 0.0001, "relTolerance": 0.0001 } }
1865
+ },
1866
+ {
1867
+ "name": "rank5_cubic_border_partition_of_unity",
1868
+ "provenance": {
1869
+ "notes": "A constant field: every interpolation returns the constant, so this sees only that the tricubic weights sum to one on each axis. It cannot tell cubic from linear or catch a wrong tap offset — rank5_cubic_border_pinned_taps is the case that does."
1870
+ },
1871
+ "attrs": { "mode": "cubic", "padding_mode": "border", "align_corners": 0 },
1872
+ "inputs": {
1873
+ "x": { "dtype": "float32", "shape": [1, 1, 2, 2, 2], "data": { "kind": "constant", "value": 2.0 } },
1874
+ "grid": {
1875
+ "dtype": "float32",
1876
+ "shape": [1, 1, 1, 1, 3],
1877
+ "data": { "kind": "values", "values": [0.0, 0.0, 0.0] }
1878
+ }
1879
+ },
1880
+ "outputs": {
1881
+ "y": {
1882
+ "dtype": "float32",
1883
+ "shape": [1, 1, 1, 1, 1],
1884
+ "tolerance": 0.000001,
1885
+ "data": { "kind": "values", "values": [2.0] }
1886
+ }
1887
+ }
1888
+ },
1889
+ {
1890
+ "name": "rank5_cubic_border_pinned_taps",
1891
+ "provenance": {
1892
+ "source": "ONNX GridSample cubic definition (Keys kernel, cubic_coeff_a = -0.75), evaluated independently",
1893
+ "notes": "Ground truth computed independently from the separable 4-tap definition, so neither the kernel nor the reference is its own oracle. Sample points are dyadic and the field is in quarters, so the values are exact in binary; two of the four points push taps past the volume, which border clamps. Trilinear on the same points gives different answers, so a cubic path that silently ran as linear would fail here."
1894
+ },
1895
+ "attrs": { "mode": "cubic", "padding_mode": "border", "align_corners": 0 },
1896
+ "inputs": {
1897
+ "x": {
1898
+ "dtype": "float32",
1899
+ "shape": [1, 2, 4, 4, 4],
1900
+ "data": {
1901
+ "kind": "values",
1902
+ "values": [-2.75, -2.5, -2.25, -2.0, -1.75, -1.5, -1.25, -1.0, -0.75, -0.5, -0.25, 0.0, 0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0, 2.25, 2.5, 2.75, -2.75, -2.5, -2.25, -2.0, -1.75, -1.5, -1.25, -1.0, -0.75, -0.5, -0.25, 0.0, 0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0, 2.25, 2.5, 2.75, -2.75, -2.5, -2.25, -2.0, -1.75, -1.5, -1.25, -1.0, -0.75, -0.5, -0.25, 0.0, 0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0, 2.25, 2.5, 2.75, -2.75, -2.5, -2.25, -2.0, -1.75, -1.5, -1.25, -1.0, -0.75, -0.5, -0.25, 0.0, 0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0, 2.25, 2.5, 2.75, -2.75, -2.5, -2.25, -2.0, -1.75, -1.5, -1.25, -1.0, -0.75, -0.5, -0.25, 0.0, 0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0, 2.25, 2.5, 2.75, -2.75, -2.5, -2.25, -2.0, -1.75, -1.5, -1.25, -1.0, -0.75, -0.5, -0.25, 0.0, 0.25]
1903
+ }
1904
+ },
1905
+ "grid": {
1906
+ "dtype": "float32",
1907
+ "shape": [1, 1, 2, 2, 3],
1908
+ "data": { "kind": "values", "values": [-0.5, 0.5, 0.0, 1.0, -1.0, 0.25, 0.25, 0.75, -0.75, -0.25, 0.0, 0.5] }
1909
+ }
1910
+ },
1911
+ "outputs": {
1912
+ "y": {
1913
+ "dtype": "float32",
1914
+ "shape": [1, 2, 1, 2, 2],
1915
+ "tolerance": 0.00001,
1916
+ "relTolerance": 0.00001,
1917
+ "data": {
1918
+ "kind": "values",
1919
+ "values": [0.0352783203125, 0.1796875, 0.75, 0.48046875, 0.6776123046875, -1.0703125, -0.5, -1.359130859375]
1920
+ }
1921
+ }
1922
+ }
1923
+ },
1924
+ {
1925
+ "name": "rank5_cubic_zeros_align_corners",
1926
+ "provenance": {
1927
+ "notes": "Cubic with zeros padding and align_corners, so the 4-tap window reads outside the volume and must contribute nothing there. The grid scale puts roughly half the sample points out of range."
1928
+ },
1929
+ "attrs": { "mode": "cubic", "padding_mode": "zeros", "align_corners": 1 },
1930
+ "inputs": {
1931
+ "x": {
1932
+ "dtype": "float32",
1933
+ "shape": [1, 2, 5, 5, 5],
1934
+ "data": { "kind": "fillFloat32", "sinStep": 0.23, "cosStep": 0.41, "scale": 1.5 }
1935
+ },
1936
+ "grid": {
1937
+ "dtype": "float32",
1938
+ "shape": [1, 2, 2, 2, 3],
1939
+ "data": { "kind": "fillFloat32", "sinStep": 0.37, "cosStep": 0.19, "scale": 1.3 }
1940
+ }
1941
+ },
1942
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 2, 2, 2, 2], "tolerance": 0.0001, "relTolerance": 0.0001 } }
1943
+ },
1944
+ {
1945
+ "name": "rank5_cubic_reflection",
1946
+ "provenance": {
1947
+ "notes": "Cubic with reflection padding: the out-of-range taps fold back inside, which is the one padding mode whose resolved index depends on align_corners as well as the bound."
1948
+ },
1949
+ "attrs": { "mode": "cubic", "padding_mode": "reflection", "align_corners": 0 },
1950
+ "inputs": {
1951
+ "x": {
1952
+ "dtype": "float32",
1953
+ "shape": [1, 2, 5, 5, 5],
1954
+ "data": { "kind": "fillFloat32", "sinStep": 0.23, "cosStep": 0.41, "scale": 1.5 }
1955
+ },
1956
+ "grid": {
1957
+ "dtype": "float32",
1958
+ "shape": [1, 2, 2, 2, 3],
1959
+ "data": { "kind": "fillFloat32", "sinStep": 0.37, "cosStep": 0.19, "scale": 1.3 }
1960
+ }
1961
+ },
1962
+ "outputs": { "y": { "dtype": "float32", "shape": [1, 2, 2, 2, 2], "tolerance": 0.0001, "relTolerance": 0.0001 } }
1963
+ }
1964
+ ]
1965
+ }