sync 91d990483a17
Browse files- README.md +17 -13
- build/webgpu/bench.json +1 -2
- build/webgpu/deform-conv2d-aligned-groups.wgsl.jinja +38 -38
- build/webgpu/deform-conv2d-nchw.wgsl.jinja +15 -15
- build/webgpu/manifest.json +149 -400
- build/webgpu/metadata.json +18 -8
- build/webgpu/test.json +4 -5
README.md
CHANGED
|
@@ -18,19 +18,19 @@ See the [ONNX `DeformConv` spec](https://onnx.ai/onnx/operators/onnx__DeformConv
|
|
| 18 |
|
| 19 |
## Inputs
|
| 20 |
|
| 21 |
-
| Name |
|
| 22 |
| --- | --- | --- | --- | --- | --- | --- |
|
| 23 |
-
| `
|
| 24 |
-
| `
|
| 25 |
-
| `offset` |
|
| 26 |
-
| `
|
| 27 |
-
| `mask` |
|
| 28 |
|
| 29 |
## Outputs
|
| 30 |
|
| 31 |
-
| Name |
|
| 32 |
| --- | --- | --- | --- | --- | --- | --- |
|
| 33 |
-
| `
|
| 34 |
|
| 35 |
## Attributes
|
| 36 |
|
|
@@ -38,10 +38,10 @@ Attributes and default values (overridable per request):
|
|
| 38 |
|
| 39 |
| Attribute | Default | Description |
|
| 40 |
| --- | --- | --- |
|
| 41 |
-
| `group` | `1` | Number of groups the input channels C and output channels oC are divided into; both must be divisible by group. |
|
| 42 |
-
| `offset_group` | `1` | Number of offset groups; input channels `C` must be divisible by `offset_group`. |
|
| 43 |
| `dilations` | — | Dilation factors for the spatial axes in height-width order; defaults to `[1, 1]`. |
|
|
|
|
| 44 |
| `kernel_shape` | — | Kernel dimensions in height-width order. When omitted, they are inferred from the spatial dimensions of `W`. |
|
|
|
|
| 45 |
| `pads` | — | Padding at the beginning and end of each spatial axis in `[top, left, bottom, right]` order; defaults to zeros. |
|
| 46 |
| `strides` | — | Stride factors for the spatial axes in height-width order; defaults to `[1, 1]`. |
|
| 47 |
|
|
@@ -53,7 +53,7 @@ Attributes and default values (overridable per request):
|
|
| 53 |
|
| 54 |
## Files
|
| 55 |
|
| 56 |
-
- [`metadata.json`](build/webgpu/metadata.json) — kernel metadata (id, digests, provenance)
|
| 57 |
- [`manifest.json`](build/webgpu/manifest.json) — the op contract (source of truth)
|
| 58 |
- [`test.json`](build/webgpu/test.json) — correctness cases
|
| 59 |
- [`bench.json`](build/webgpu/bench.json) — benchmark + tuning cases
|
|
@@ -62,10 +62,14 @@ Attributes and default values (overridable per request):
|
|
| 62 |
|
| 63 |
## Use with `@huggingface/kernels`
|
| 64 |
|
| 65 |
-
|
| 66 |
-
|
|
|
|
|
|
|
|
|
|
| 67 |
|
| 68 |
The `version: 1` option selects the published kernel contract; it is independent of any operator opset, contrib `since_version`, or model version.
|
|
|
|
| 69 |
|
| 70 |
Replace each `*Data` placeholder with a typed array containing the corresponding input data.
|
| 71 |
|
|
|
|
| 18 |
|
| 19 |
## Inputs
|
| 20 |
|
| 21 |
+
| Name | Upstream name | Logical dtype | Rank | Shape | Description | Presence |
|
| 22 |
| --- | --- | --- | --- | --- | --- | --- |
|
| 23 |
+
| `x` | `X` | `T` | `4` | — | Input data tensor of shape `(N, C, H, W)` for 2D or `(N, C, D1, ..., Dn)` in general. | required |
|
| 24 |
+
| `w` | `W` | `T` | `4` | — | Convolution weight tensor of shape `(oC, C/group, kH, kW)`. | required |
|
| 25 |
+
| `offset` | — | `T` | `4` | — | Per-output-position sampling offsets of shape `(N, offset_group * kH * kW * 2, oH, oW)` for 2D data. | required |
|
| 26 |
+
| `bias` | `B` | `T` | `1` | — | Optional 1D bias of length oC added to the convolution output. | optional |
|
| 27 |
+
| `mask` | — | `T` | `4` | — | Optional modulation mask of shape `(N, offset_group * kH * kW, oH, oW)` scaling each sampled kernel point; defaults to ones. | optional |
|
| 28 |
|
| 29 |
## Outputs
|
| 30 |
|
| 31 |
+
| Name | Upstream name | Logical dtype | Rank | Shape | Description | Presence |
|
| 32 |
| --- | --- | --- | --- | --- | --- | --- |
|
| 33 |
+
| `y` | `Y` | `T` | `4` | derived | Output tensor of shape `(N, oC, oH, oW)` containing the deformable convolution result. | required |
|
| 34 |
|
| 35 |
## Attributes
|
| 36 |
|
|
|
|
| 38 |
|
| 39 |
| Attribute | Default | Description |
|
| 40 |
| --- | --- | --- |
|
|
|
|
|
|
|
| 41 |
| `dilations` | — | Dilation factors for the spatial axes in height-width order; defaults to `[1, 1]`. |
|
| 42 |
+
| `group` | `1` | Number of groups the input channels C and output channels oC are divided into; both must be divisible by group. |
|
| 43 |
| `kernel_shape` | — | Kernel dimensions in height-width order. When omitted, they are inferred from the spatial dimensions of `W`. |
|
| 44 |
+
| `offset_group` | `1` | Number of offset groups; input channels `C` must be divisible by `offset_group`. |
|
| 45 |
| `pads` | — | Padding at the beginning and end of each spatial axis in `[top, left, bottom, right]` order; defaults to zeros. |
|
| 46 |
| `strides` | — | Stride factors for the spatial axes in height-width order; defaults to `[1, 1]`. |
|
| 47 |
|
|
|
|
| 53 |
|
| 54 |
## Files
|
| 55 |
|
| 56 |
+
- [`metadata.json`](build/webgpu/metadata.json) — kernel metadata (id, digests, per-variant templates, provenance)
|
| 57 |
- [`manifest.json`](build/webgpu/manifest.json) — the op contract (source of truth)
|
| 58 |
- [`test.json`](build/webgpu/test.json) — correctness cases
|
| 59 |
- [`bench.json`](build/webgpu/bench.json) — benchmark + tuning cases
|
|
|
|
| 62 |
|
| 63 |
## Use with `@huggingface/kernels`
|
| 64 |
|
| 65 |
+
```sh
|
| 66 |
+
npm install --save-exact @huggingface/kernels@0.0.1-preview.2
|
| 67 |
+
```
|
| 68 |
+
|
| 69 |
+
Required output shapes and logical data types are inferred from the supplied inputs and attributes; result tensors are allocated automatically.
|
| 70 |
|
| 71 |
The `version: 1` option selects the published kernel contract; it is independent of any operator opset, contrib `since_version`, or model version.
|
| 72 |
+
It follows the `v1` branch as fixes land. To pin exact artifact bytes, pass a 40-character commit `revision` instead of `version`.
|
| 73 |
|
| 74 |
Replace each `*Data` placeholder with a typed array containing the corresponding input data.
|
| 75 |
|
build/webgpu/bench.json
CHANGED
|
@@ -1,5 +1,4 @@
|
|
| 1 |
{
|
| 2 |
-
"op": "ai.onnx.DeformConv",
|
| 3 |
"cases": [
|
| 4 |
{
|
| 5 |
"name": "nchw_1x8x32x32_k3",
|
|
@@ -75,7 +74,7 @@
|
|
| 75 |
"name": "deform-conv-f32-unmodulated-b1c64m64-128x128-k3-g4-pathology",
|
| 76 |
"preset": "stress",
|
| 77 |
"provenance": {
|
| 78 |
-
"source": "
|
| 79 |
"notes": "Unmodulated grouped DeformConv exercises the nchw2d route; the paired bias-and-mask case selects the blocked kernel and isolates the optional-input route boundary."
|
| 80 |
},
|
| 81 |
"attrs": { "group": 4, "offset_group": 4, "pads": [1, 1, 1, 1] },
|
|
|
|
| 1 |
{
|
|
|
|
| 2 |
"cases": [
|
| 3 |
{
|
| 4 |
"name": "nchw_1x8x32x32_k3",
|
|
|
|
| 74 |
"name": "deform-conv-f32-unmodulated-b1c64m64-128x128-k3-g4-pathology",
|
| 75 |
"preset": "stress",
|
| 76 |
"provenance": {
|
| 77 |
+
"source": "synthetic benchmark",
|
| 78 |
"notes": "Unmodulated grouped DeformConv exercises the nchw2d route; the paired bias-and-mask case selects the blocked kernel and isolates the optional-input route boundary."
|
| 79 |
},
|
| 80 |
"attrs": { "group": 4, "offset_group": 4, "pads": [1, 1, 1, 1] },
|
build/webgpu/deform-conv2d-aligned-groups.wgsl.jinja
CHANGED
|
@@ -4,26 +4,26 @@
|
|
| 4 |
// output group shares the same tap coordinates and modulation mask. Hoist the
|
| 5 |
// offset fetch, floor, bounds and interpolation coefficients out of the channel
|
| 6 |
// loop instead of repeating them C/group times for every output channel.
|
| 7 |
-
const COUNT: u32 = {{
|
| 8 |
-
const IN_C: u32 = {{
|
| 9 |
-
const IN_CPG: u32 = {{
|
| 10 |
-
const IN_H: i32 = {{
|
| 11 |
-
const IN_W: i32 = {{
|
| 12 |
-
const IN_H_U: u32 = {{
|
| 13 |
-
const IN_W_U: u32 = {{
|
| 14 |
-
const OUT_C: u32 = {{
|
| 15 |
-
const OUT_CPG: u32 = {{
|
| 16 |
-
{% if
|
| 17 |
{% endif %}
|
| 18 |
-
const OUT_H: u32 = {{
|
| 19 |
-
const OUT_W: u32 = {{
|
| 20 |
-
const KAREA: u32 = {{
|
| 21 |
-
{% if
|
| 22 |
{% endif %}
|
| 23 |
-
const STRIDE_H: u32 = {{
|
| 24 |
-
const STRIDE_W: u32 = {{
|
| 25 |
-
const PAD_H: i32 = {{
|
| 26 |
-
const PAD_W: i32 = {{
|
| 27 |
const WG: u32 = {{ tunables.WORKGROUP_SIZE }}u;
|
| 28 |
|
| 29 |
fn pixel(n: u32, c: u32, h: i32, wc: i32) -> f32 {
|
|
@@ -32,10 +32,10 @@ fn pixel(n: u32, c: u32, h: i32, wc: i32) -> f32 {
|
|
| 32 |
}
|
| 33 |
|
| 34 |
@compute @workgroup_size({{ tunables.WORKGROUP_SIZE }})
|
| 35 |
-
fn main(@builtin(global_invocation_id) gid: vec3<u32>
|
| 36 |
-
let index = gid.x + gid.y *
|
| 37 |
if (index >= COUNT) { return; }
|
| 38 |
-
{% if
|
| 39 |
// Output channels in the same convolution group use identical deformable
|
| 40 |
// coordinates, masks, and sampled input values. Accumulate a compile-time
|
| 41 |
// output-channel block together so those values are shared across the block.
|
|
@@ -45,11 +45,11 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>, @builtin(num_workgroups)
|
|
| 45 |
t /= OUT_H;
|
| 46 |
let ocBlock = t % (OUT_CPG / OC_BLOCK);
|
| 47 |
t /= OUT_CPG / OC_BLOCK;
|
| 48 |
-
let group = t % {{
|
| 49 |
-
let n = t / {{
|
| 50 |
let oc = group * OUT_CPG + ocBlock * OC_BLOCK;
|
| 51 |
-
{% for v in range(
|
| 52 |
-
{% if
|
| 53 |
var acc{{ v }} = vec4<f32>(
|
| 54 |
bias[oc + {{ v * 4 }}u], bias[oc + {{ v * 4 + 1 }}u],
|
| 55 |
bias[oc + {{ v * 4 + 2 }}u], bias[oc + {{ v * 4 + 3 }}u]);
|
|
@@ -65,7 +65,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>, @builtin(num_workgroups)
|
|
| 65 |
let oc = t % OUT_C;
|
| 66 |
let n = t / OUT_C;
|
| 67 |
let group = oc / OUT_CPG;
|
| 68 |
-
{% if
|
| 69 |
var acc = bias[oc];
|
| 70 |
{% else %}
|
| 71 |
var acc = 0.0;
|
|
@@ -75,24 +75,24 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>, @builtin(num_workgroups)
|
|
| 75 |
let spatial = oh * OUT_W + ow;
|
| 76 |
let offsetPlane = OUT_H * OUT_W;
|
| 77 |
|
| 78 |
-
{% for kh in range(
|
| 79 |
-
{% for kw in range(
|
| 80 |
{
|
| 81 |
-
const TAP: u32 = {{ kh *
|
| 82 |
let offsetChannel = group * KAREA * 2u + TAP * 2u;
|
| 83 |
-
let offsetBase = n * ({{
|
| 84 |
let dy = offset[offsetBase + offsetChannel * offsetPlane + spatial];
|
| 85 |
let dx = offset[offsetBase + (offsetChannel + 1u) * offsetPlane + spatial];
|
| 86 |
-
let sy = f32(i32(oh * STRIDE_H) + {{ kh *
|
| 87 |
-
let sx = f32(i32(ow * STRIDE_W) + {{ kw *
|
| 88 |
if (sy > -1.0 && sy < f32(IN_H) && sx > -1.0 && sx < f32(IN_W)) {
|
| 89 |
let h0 = i32(floor(sy)); let h1 = h0 + 1;
|
| 90 |
let w0 = i32(floor(sx)); let w1 = w0 + 1;
|
| 91 |
let lh = sy - f32(h0); let lw = sx - f32(w0);
|
| 92 |
let hh = 1.0 - lh; let hw = 1.0 - lw;
|
| 93 |
-
{% if
|
| 94 |
let maskChannel = group * KAREA + TAP;
|
| 95 |
-
let maskBase = n * ({{
|
| 96 |
let mv = mask[maskBase + maskChannel * offsetPlane + spatial];
|
| 97 |
{% else %}
|
| 98 |
let mv = 1.0;
|
|
@@ -104,8 +104,8 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>, @builtin(num_workgroups)
|
|
| 104 |
+ lh * hw * pixel(n, ic, h1, w0)
|
| 105 |
+ lh * lw * pixel(n, ic, h1, w1);
|
| 106 |
let wi = ((oc * IN_CPG + localIc) * KAREA) + TAP;
|
| 107 |
-
{% if
|
| 108 |
-
{% for v in range(
|
| 109 |
let weights{{ v }} = vec4<f32>(
|
| 110 |
w[wi + {{ v * 4 }}u * W_OC_STRIDE], w[wi + {{ v * 4 + 1 }}u * W_OC_STRIDE],
|
| 111 |
w[wi + {{ v * 4 + 2 }}u * W_OC_STRIDE], w[wi + {{ v * 4 + 3 }}u * W_OC_STRIDE]);
|
|
@@ -119,10 +119,10 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>, @builtin(num_workgroups)
|
|
| 119 |
}
|
| 120 |
{% endfor %}
|
| 121 |
{% endfor %}
|
| 122 |
-
{% if
|
| 123 |
let y0 = ((n * OUT_C + oc) * OUT_H + oh) * OUT_W + ow;
|
| 124 |
let yPlane = OUT_H * OUT_W;
|
| 125 |
-
{% for v in range(
|
| 126 |
y[y0 + {{ v * 4 }}u * yPlane] = acc{{ v }}.x;
|
| 127 |
y[y0 + {{ v * 4 + 1 }}u * yPlane] = acc{{ v }}.y;
|
| 128 |
y[y0 + {{ v * 4 + 2 }}u * yPlane] = acc{{ v }}.z;
|
|
|
|
| 4 |
// output group shares the same tap coordinates and modulation mask. Hoist the
|
| 5 |
// offset fetch, floor, bounds and interpolation coefficients out of the channel
|
| 6 |
// loop instead of repeating them C/group times for every output channel.
|
| 7 |
+
const COUNT: u32 = {{ count }}u;
|
| 8 |
+
const IN_C: u32 = {{ inC }}u;
|
| 9 |
+
const IN_CPG: u32 = {{ inCPerGroup }}u;
|
| 10 |
+
const IN_H: i32 = {{ inH }};
|
| 11 |
+
const IN_W: i32 = {{ inW }};
|
| 12 |
+
const IN_H_U: u32 = {{ inH }}u;
|
| 13 |
+
const IN_W_U: u32 = {{ inW }}u;
|
| 14 |
+
const OUT_C: u32 = {{ outC }}u;
|
| 15 |
+
const OUT_CPG: u32 = {{ outCPerGroup }}u;
|
| 16 |
+
{% if outChannelBlock != 1 %}const OC_BLOCK: u32 = {{ outChannelBlock }}u;
|
| 17 |
{% endif %}
|
| 18 |
+
const OUT_H: u32 = {{ outH }}u;
|
| 19 |
+
const OUT_W: u32 = {{ outW }}u;
|
| 20 |
+
const KAREA: u32 = {{ kernelHSpec * kernelWSpec }}u;
|
| 21 |
+
{% if outChannelBlock != 1 %}const W_OC_STRIDE: u32 = IN_CPG * KAREA;
|
| 22 |
{% endif %}
|
| 23 |
+
const STRIDE_H: u32 = {{ strideHSpec }}u;
|
| 24 |
+
const STRIDE_W: u32 = {{ strideWSpec }}u;
|
| 25 |
+
const PAD_H: i32 = {{ padH }};
|
| 26 |
+
const PAD_W: i32 = {{ padW }};
|
| 27 |
const WG: u32 = {{ tunables.WORKGROUP_SIZE }}u;
|
| 28 |
|
| 29 |
fn pixel(n: u32, c: u32, h: i32, wc: i32) -> f32 {
|
|
|
|
| 32 |
}
|
| 33 |
|
| 34 |
@compute @workgroup_size({{ tunables.WORKGROUP_SIZE }})
|
| 35 |
+
fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
|
| 36 |
+
let index = gid.x + gid.y * {{ DISPATCH_FOLD_WIDTH }}u * WG;
|
| 37 |
if (index >= COUNT) { return; }
|
| 38 |
+
{% if outChannelBlock != 1 %}
|
| 39 |
// Output channels in the same convolution group use identical deformable
|
| 40 |
// coordinates, masks, and sampled input values. Accumulate a compile-time
|
| 41 |
// output-channel block together so those values are shared across the block.
|
|
|
|
| 45 |
t /= OUT_H;
|
| 46 |
let ocBlock = t % (OUT_CPG / OC_BLOCK);
|
| 47 |
t /= OUT_CPG / OC_BLOCK;
|
| 48 |
+
let group = t % {{ groups }}u;
|
| 49 |
+
let n = t / {{ groups }}u;
|
| 50 |
let oc = group * OUT_CPG + ocBlock * OC_BLOCK;
|
| 51 |
+
{% for v in range(outChannelVecs) %}
|
| 52 |
+
{% if hasBias %}
|
| 53 |
var acc{{ v }} = vec4<f32>(
|
| 54 |
bias[oc + {{ v * 4 }}u], bias[oc + {{ v * 4 + 1 }}u],
|
| 55 |
bias[oc + {{ v * 4 + 2 }}u], bias[oc + {{ v * 4 + 3 }}u]);
|
|
|
|
| 65 |
let oc = t % OUT_C;
|
| 66 |
let n = t / OUT_C;
|
| 67 |
let group = oc / OUT_CPG;
|
| 68 |
+
{% if hasBias %}
|
| 69 |
var acc = bias[oc];
|
| 70 |
{% else %}
|
| 71 |
var acc = 0.0;
|
|
|
|
| 75 |
let spatial = oh * OUT_W + ow;
|
| 76 |
let offsetPlane = OUT_H * OUT_W;
|
| 77 |
|
| 78 |
+
{% for kh in range(kernelHSpec) %}
|
| 79 |
+
{% for kw in range(kernelWSpec) %}
|
| 80 |
{
|
| 81 |
+
const TAP: u32 = {{ kh * kernelWSpec + kw }}u;
|
| 82 |
let offsetChannel = group * KAREA * 2u + TAP * 2u;
|
| 83 |
+
let offsetBase = n * ({{ groups }}u * KAREA * 2u) * offsetPlane;
|
| 84 |
let dy = offset[offsetBase + offsetChannel * offsetPlane + spatial];
|
| 85 |
let dx = offset[offsetBase + (offsetChannel + 1u) * offsetPlane + spatial];
|
| 86 |
+
let sy = f32(i32(oh * STRIDE_H) + {{ kh * dilationHSpec }} - PAD_H) + dy;
|
| 87 |
+
let sx = f32(i32(ow * STRIDE_W) + {{ kw * dilationWSpec }} - PAD_W) + dx;
|
| 88 |
if (sy > -1.0 && sy < f32(IN_H) && sx > -1.0 && sx < f32(IN_W)) {
|
| 89 |
let h0 = i32(floor(sy)); let h1 = h0 + 1;
|
| 90 |
let w0 = i32(floor(sx)); let w1 = w0 + 1;
|
| 91 |
let lh = sy - f32(h0); let lw = sx - f32(w0);
|
| 92 |
let hh = 1.0 - lh; let hw = 1.0 - lw;
|
| 93 |
+
{% if hasMask %}
|
| 94 |
let maskChannel = group * KAREA + TAP;
|
| 95 |
+
let maskBase = n * ({{ groups }}u * KAREA) * offsetPlane;
|
| 96 |
let mv = mask[maskBase + maskChannel * offsetPlane + spatial];
|
| 97 |
{% else %}
|
| 98 |
let mv = 1.0;
|
|
|
|
| 104 |
+ lh * hw * pixel(n, ic, h1, w0)
|
| 105 |
+ lh * lw * pixel(n, ic, h1, w1);
|
| 106 |
let wi = ((oc * IN_CPG + localIc) * KAREA) + TAP;
|
| 107 |
+
{% if outChannelBlock != 1 %}
|
| 108 |
+
{% for v in range(outChannelVecs) %}
|
| 109 |
let weights{{ v }} = vec4<f32>(
|
| 110 |
w[wi + {{ v * 4 }}u * W_OC_STRIDE], w[wi + {{ v * 4 + 1 }}u * W_OC_STRIDE],
|
| 111 |
w[wi + {{ v * 4 + 2 }}u * W_OC_STRIDE], w[wi + {{ v * 4 + 3 }}u * W_OC_STRIDE]);
|
|
|
|
| 119 |
}
|
| 120 |
{% endfor %}
|
| 121 |
{% endfor %}
|
| 122 |
+
{% if outChannelBlock != 1 %}
|
| 123 |
let y0 = ((n * OUT_C + oc) * OUT_H + oh) * OUT_W + ow;
|
| 124 |
let yPlane = OUT_H * OUT_W;
|
| 125 |
+
{% for v in range(outChannelVecs) %}
|
| 126 |
y[y0 + {{ v * 4 }}u * yPlane] = acc{{ v }}.x;
|
| 127 |
y[y0 + {{ v * 4 + 1 }}u * yPlane] = acc{{ v }}.y;
|
| 128 |
y[y0 + {{ v * 4 + 2 }}u * yPlane] = acc{{ v }}.z;
|
build/webgpu/deform-conv2d-nchw.wgsl.jinja
CHANGED
|
@@ -1,30 +1,30 @@
|
|
| 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 |
-
//
|
| 5 |
{% elif note == "limit" %}
|
| 6 |
-
// 2D-folded flat index: gid.y carries the high bits past the
|
| 7 |
-
//
|
| 8 |
{% elif note == "device-axis" %}
|
| 9 |
-
// The flat dispatch is folded across x/y at
|
| 10 |
-
//
|
| 11 |
{% elif note == "vec4-limit" %}
|
| 12 |
-
// 2D-folded flat vec4 index: gid.y carries the high bits past the
|
| 13 |
-
//
|
| 14 |
{% elif note == "element-limit" %}
|
| 15 |
// 2D-folded flat element index: gid.y carries the high bits past the
|
| 16 |
-
//
|
| 17 |
{% elif note == "dispatch" %}
|
| 18 |
-
// 2D-folded flat index: gid.y carries the high bits past the
|
| 19 |
-
//
|
| 20 |
{% endif %}
|
| 21 |
{% if bound == "" %}
|
| 22 |
-
let {{ name }} = gid.x + gid.y *
|
| 23 |
{%- elif guardInline %}
|
| 24 |
-
let {{ name }} = gid.x + gid.y *
|
| 25 |
if ({{ name }} >= {{ bound }}) { return; }
|
| 26 |
{%- else %}
|
| 27 |
-
let {{ name }} = gid.x + gid.y *
|
| 28 |
if ({{ name }} >= {{ bound }}) {
|
| 29 |
return;
|
| 30 |
}
|
|
@@ -69,7 +69,7 @@ fn mask_at(n: u32, channel: u32, oh: u32, ow: u32) -> f32 {
|
|
| 69 |
|
| 70 |
{% endif %}
|
| 71 |
@compute @workgroup_size({{ tunables.WORKGROUP_SIZE }})
|
| 72 |
-
fn main(@builtin(global_invocation_id) gid: vec3<u32>
|
| 73 |
{{ flat_index_2d("index", guardInline=true) }}
|
| 74 |
|
| 75 |
let ow = index % params.outW;
|
|
|
|
| 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 dispatch's
|
| 4 |
+
// per-axis workgroup fold width (outputs > 16.7M elements).
|
| 5 |
{% elif note == "limit" %}
|
| 6 |
+
// 2D-folded flat index: gid.y carries the high bits past the dispatch's
|
| 7 |
+
// per-axis workgroup fold width.
|
| 8 |
{% elif note == "device-axis" %}
|
| 9 |
+
// The flat dispatch is folded across x/y at a fixed per-axis workgroup
|
| 10 |
+
// width; 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 dispatch's
|
| 13 |
+
// per-axis workgroup fold width (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 |
+
// dispatch's per-axis workgroup fold width.
|
| 17 |
{% elif note == "dispatch" %}
|
| 18 |
+
// 2D-folded flat index: gid.y carries the high bits past the dispatch's
|
| 19 |
+
// per-axis workgroup fold width.
|
| 20 |
{% endif %}
|
| 21 |
{% if bound == "" %}
|
| 22 |
+
let {{ name }} = gid.x + gid.y * {{ DISPATCH_FOLD_WIDTH }}u * {{ tunables.WORKGROUP_SIZE }}u;
|
| 23 |
{%- elif guardInline %}
|
| 24 |
+
let {{ name }} = gid.x + gid.y * {{ DISPATCH_FOLD_WIDTH }}u * {{ tunables.WORKGROUP_SIZE }}u;
|
| 25 |
if ({{ name }} >= {{ bound }}) { return; }
|
| 26 |
{%- else %}
|
| 27 |
+
let {{ name }} = gid.x + gid.y * {{ DISPATCH_FOLD_WIDTH }}u * {{ tunables.WORKGROUP_SIZE }}u;
|
| 28 |
if ({{ name }} >= {{ bound }}) {
|
| 29 |
return;
|
| 30 |
}
|
|
|
|
| 69 |
|
| 70 |
{% endif %}
|
| 71 |
@compute @workgroup_size({{ tunables.WORKGROUP_SIZE }})
|
| 72 |
+
fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
|
| 73 |
{{ flat_index_2d("index", guardInline=true) }}
|
| 74 |
|
| 75 |
let ow = index % params.outW;
|
build/webgpu/manifest.json
CHANGED
|
@@ -2,69 +2,31 @@
|
|
| 2 |
"domain": "ai.onnx",
|
| 3 |
"name": "DeformConv",
|
| 4 |
"sinceVersion": 22,
|
| 5 |
-
"
|
| 6 |
-
|
| 7 |
-
{
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
{
|
| 14 |
-
"
|
| 15 |
-
"dtype": "T",
|
| 16 |
-
"description": "Convolution weight tensor of shape `(oC, C/group, kH, kW)`.",
|
| 17 |
-
"rank": 4
|
| 18 |
-
},
|
| 19 |
-
{
|
| 20 |
-
"role": "offset",
|
| 21 |
-
"dtype": "T",
|
| 22 |
-
"description": "Per-output-position sampling offsets of shape `(N, offset_group * kH * kW * 2, oH, oW)` for 2D data.",
|
| 23 |
-
"rank": 4
|
| 24 |
-
},
|
| 25 |
-
{
|
| 26 |
-
"role": "B",
|
| 27 |
-
"dtype": "T",
|
| 28 |
-
"optional": true,
|
| 29 |
-
"description": "Optional 1D bias of length oC added to the convolution output.",
|
| 30 |
-
"rank": 1
|
| 31 |
-
},
|
| 32 |
-
{
|
| 33 |
-
"role": "mask",
|
| 34 |
-
"dtype": "T",
|
| 35 |
-
"optional": true,
|
| 36 |
-
"description": "Optional modulation mask of shape `(N, offset_group * kH * kW, oH, oW)` scaling each sampled kernel point; defaults to ones.",
|
| 37 |
-
"rank": 4
|
| 38 |
-
}
|
| 39 |
-
],
|
| 40 |
-
"outputs": [
|
| 41 |
-
{
|
| 42 |
-
"role": "Y",
|
| 43 |
"dtype": "T",
|
| 44 |
-
"description": "Output tensor of shape `(N, oC, oH, oW)` containing the deformable convolution result.",
|
| 45 |
"rank": 4,
|
| 46 |
-
"shape": ["dim(shapes.
|
| 47 |
}
|
| 48 |
-
],
|
| 49 |
-
"attributes": { "group": 1, "offset_group": 1 },
|
| 50 |
-
"attributeDescriptions": {
|
| 51 |
-
"dilations": "Dilation factors for the spatial axes in height-width order; defaults to `[1, 1]`.",
|
| 52 |
-
"group": "Number of groups the input channels C and output channels oC are divided into; both must be divisible by group.",
|
| 53 |
-
"kernel_shape": "Kernel dimensions in height-width order. When omitted, they are inferred from the spatial dimensions of `W`.",
|
| 54 |
-
"offset_group": "Number of offset groups; input channels `C` must be divisible by `offset_group`.",
|
| 55 |
-
"pads": "Padding at the beginning and end of each spatial axis in `[top, left, bottom, right]` order; defaults to zeros.",
|
| 56 |
-
"strides": "Stride factors for the spatial axes in height-width order; defaults to `[1, 1]`."
|
| 57 |
},
|
| 58 |
-
"
|
| 59 |
-
|
| 60 |
-
"
|
| 61 |
-
"
|
| 62 |
-
"
|
| 63 |
-
"
|
| 64 |
-
"
|
| 65 |
-
"y": { "kind": "tensor", "semantic": "Y", "role": "output" }
|
| 66 |
},
|
| 67 |
-
"
|
|
|
|
| 68 |
"derive": {
|
| 69 |
"spatialRank": 2,
|
| 70 |
"kernelShapeLengthOk": "not has(attrs, \"kernel_shape\") or (attrs.kernel_shape | length) == spatialRank",
|
|
@@ -81,157 +43,52 @@
|
|
| 81 |
"padLeft": "attrs.pads[spatialRank - 1] if padsLengthOk and has(attrs, \"pads\") and spatialRank >= 1 else 0",
|
| 82 |
"padBottom": "attrs.pads[2 * spatialRank - 2] if padsLengthOk and has(attrs, \"pads\") and spatialRank >= 2 else 0",
|
| 83 |
"padRight": "attrs.pads[2 * spatialRank - 1] if padsLengthOk and has(attrs, \"pads\") and spatialRank >= 1 else 0",
|
| 84 |
-
"spatialAttributesOk": "kernelShapeLengthOk and stridesLengthOk and dilationsLengthOk and padsLengthOk and strideH >= 1 and strideW >= 1 and dilationH >= 1 and dilationW >= 1 and padTop >= 0 and padLeft >= 0 and padBottom >= 0 and padRight >= 0 and (not has(attrs, \"kernel_shape\") or (kernelH == dim(shapes.
|
| 85 |
-
"alignedGroupsCoreOk": "spatialAttributesOk and ranks.
|
| 86 |
-
"alignedBiasMaskOk": "alignedGroupsCoreOk and present.bias and present.mask and ranks.
|
| 87 |
"alignedPlainOk": "alignedGroupsCoreOk and not present.bias and not present.mask",
|
| 88 |
-
"genericCoreOk": "spatialAttributesOk and ranks.
|
| 89 |
-
"genericBiasShapeOk": "present.bias and ranks.
|
| 90 |
-
"genericMaskShapeOk": "present.mask and ranks.mask == 4 and dim(shapes.mask, 0) == dim(shapes.
|
| 91 |
"genericPlainOk": "genericCoreOk and not present.bias and not present.mask",
|
| 92 |
"genericBiasOk": "genericCoreOk and genericBiasShapeOk and not present.mask",
|
| 93 |
"genericMaskOk": "genericCoreOk and not present.bias and genericMaskShapeOk",
|
| 94 |
"genericBiasMaskOk": "genericCoreOk and genericBiasShapeOk and genericMaskShapeOk",
|
| 95 |
-
"alignedOcBlock": "16 if (dim(shapes.
|
| 96 |
"alignedOcVecs": "4 if alignedOcBlock == 16 else (2 if alignedOcBlock == 8 else (1 if alignedOcBlock == 4 else 0))"
|
| 97 |
},
|
| 98 |
-
"
|
| 99 |
-
"
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
"name": "
|
| 111 |
-
"
|
| 112 |
-
"
|
| 113 |
-
"
|
| 114 |
-
"
|
| 115 |
-
|
| 116 |
-
|
| 117 |
-
"name": "
|
| 118 |
-
"
|
| 119 |
-
"
|
| 120 |
-
"
|
| 121 |
-
"
|
| 122 |
-
|
| 123 |
-
|
| 124 |
-
|
| 125 |
-
|
| 126 |
-
|
| 127 |
-
|
| 128 |
-
|
| 129 |
-
|
| 130 |
-
"arg": "offset",
|
| 131 |
-
"semantic": "offset",
|
| 132 |
-
"buffer": { "type": "read-only-storage" },
|
| 133 |
-
"elementType": "f32"
|
| 134 |
-
},
|
| 135 |
-
{ "name": "y", "arg": "y", "semantic": "Y", "buffer": { "type": "storage" }, "elementType": "f32" }
|
| 136 |
-
],
|
| 137 |
-
"nchw2dPlain": [
|
| 138 |
-
{ "name": "x", "arg": "x", "semantic": "X", "buffer": { "type": "read-only-storage" }, "elementType": "f32" },
|
| 139 |
-
{ "name": "w", "arg": "w", "semantic": "W", "buffer": { "type": "read-only-storage" }, "elementType": "f32" },
|
| 140 |
-
{
|
| 141 |
-
"name": "offset",
|
| 142 |
-
"arg": "offset",
|
| 143 |
-
"semantic": "offset",
|
| 144 |
-
"buffer": { "type": "read-only-storage" },
|
| 145 |
-
"elementType": "f32"
|
| 146 |
-
},
|
| 147 |
-
{ "name": "y", "arg": "y", "semantic": "Y", "buffer": { "type": "storage" }, "elementType": "f32" },
|
| 148 |
-
{
|
| 149 |
-
"name": "params",
|
| 150 |
-
"semantic": "kernel.params",
|
| 151 |
-
"buffer": { "type": "uniform" },
|
| 152 |
-
"struct": {
|
| 153 |
-
"name": "Params",
|
| 154 |
-
"fields": [
|
| 155 |
-
{ "name": "count", "type": "u32", "value": "numel(shapes.Y)" },
|
| 156 |
-
{ "name": "inChannels", "type": "u32", "value": "dim(shapes.X, 1)" },
|
| 157 |
-
{ "name": "inH", "type": "u32", "value": "dim(shapes.X, 2)" },
|
| 158 |
-
{ "name": "inW", "type": "u32", "value": "dim(shapes.X, 3)" },
|
| 159 |
-
{ "name": "outChannels", "type": "u32", "value": "dim(shapes.W, 0)" },
|
| 160 |
-
{ "name": "weightInChannels", "type": "u32", "value": "dim(shapes.W, 1)" },
|
| 161 |
-
{ "name": "inChannelsPerGroup", "type": "u32", "value": "dim(shapes.X, 1) / attrs.group" },
|
| 162 |
-
{ "name": "outChannelsPerGroup", "type": "u32", "value": "dim(shapes.W, 0) / attrs.group" },
|
| 163 |
-
{ "name": "inChannelsPerOffsetGroup", "type": "u32", "value": "dim(shapes.X, 1) / attrs.offset_group" },
|
| 164 |
-
{ "name": "kernelH", "type": "u32", "value": "dim(shapes.W, 2)" },
|
| 165 |
-
{ "name": "kernelW", "type": "u32", "value": "dim(shapes.W, 3)" },
|
| 166 |
-
{ "name": "outH", "type": "u32", "value": "dim(shapes.Y, 2)" },
|
| 167 |
-
{ "name": "outW", "type": "u32", "value": "dim(shapes.Y, 3)" },
|
| 168 |
-
{ "name": "strideH", "type": "u32", "value": "strideH" },
|
| 169 |
-
{ "name": "strideW", "type": "u32", "value": "strideW" },
|
| 170 |
-
{ "name": "dilationH", "type": "u32", "value": "dilationH" },
|
| 171 |
-
{ "name": "dilationW", "type": "u32", "value": "dilationW" },
|
| 172 |
-
{ "name": "padH", "type": "i32", "value": "padTop" },
|
| 173 |
-
{ "name": "padW", "type": "i32", "value": "padLeft" },
|
| 174 |
-
{ "name": "offsetGroup", "type": "u32", "value": "attrs.offset_group" }
|
| 175 |
-
]
|
| 176 |
-
}
|
| 177 |
-
}
|
| 178 |
-
],
|
| 179 |
-
"nchw2dBiasMask": [
|
| 180 |
-
{ "name": "x", "arg": "x", "semantic": "X", "buffer": { "type": "read-only-storage" }, "elementType": "f32" },
|
| 181 |
-
{ "name": "w", "arg": "w", "semantic": "W", "buffer": { "type": "read-only-storage" }, "elementType": "f32" },
|
| 182 |
-
{
|
| 183 |
-
"name": "offset",
|
| 184 |
-
"arg": "offset",
|
| 185 |
-
"semantic": "offset",
|
| 186 |
-
"buffer": { "type": "read-only-storage" },
|
| 187 |
-
"elementType": "f32"
|
| 188 |
-
},
|
| 189 |
-
{
|
| 190 |
-
"name": "bias",
|
| 191 |
-
"arg": "bias",
|
| 192 |
-
"semantic": "B",
|
| 193 |
-
"buffer": { "type": "read-only-storage" },
|
| 194 |
-
"elementType": "f32"
|
| 195 |
-
},
|
| 196 |
-
{
|
| 197 |
-
"name": "mask",
|
| 198 |
-
"arg": "mask",
|
| 199 |
-
"semantic": "mask",
|
| 200 |
-
"buffer": { "type": "read-only-storage" },
|
| 201 |
-
"elementType": "f32"
|
| 202 |
-
},
|
| 203 |
-
{ "name": "y", "arg": "y", "semantic": "Y", "buffer": { "type": "storage" }, "elementType": "f32" },
|
| 204 |
-
{
|
| 205 |
-
"name": "params",
|
| 206 |
-
"semantic": "kernel.params",
|
| 207 |
-
"buffer": { "type": "uniform" },
|
| 208 |
-
"struct": {
|
| 209 |
-
"name": "Params",
|
| 210 |
-
"fields": [
|
| 211 |
-
{ "name": "count", "type": "u32", "value": "numel(shapes.Y)" },
|
| 212 |
-
{ "name": "inChannels", "type": "u32", "value": "dim(shapes.X, 1)" },
|
| 213 |
-
{ "name": "inH", "type": "u32", "value": "dim(shapes.X, 2)" },
|
| 214 |
-
{ "name": "inW", "type": "u32", "value": "dim(shapes.X, 3)" },
|
| 215 |
-
{ "name": "outChannels", "type": "u32", "value": "dim(shapes.W, 0)" },
|
| 216 |
-
{ "name": "weightInChannels", "type": "u32", "value": "dim(shapes.W, 1)" },
|
| 217 |
-
{ "name": "inChannelsPerGroup", "type": "u32", "value": "dim(shapes.X, 1) / attrs.group" },
|
| 218 |
-
{ "name": "outChannelsPerGroup", "type": "u32", "value": "dim(shapes.W, 0) / attrs.group" },
|
| 219 |
-
{ "name": "inChannelsPerOffsetGroup", "type": "u32", "value": "dim(shapes.X, 1) / attrs.offset_group" },
|
| 220 |
-
{ "name": "kernelH", "type": "u32", "value": "dim(shapes.W, 2)" },
|
| 221 |
-
{ "name": "kernelW", "type": "u32", "value": "dim(shapes.W, 3)" },
|
| 222 |
-
{ "name": "outH", "type": "u32", "value": "dim(shapes.Y, 2)" },
|
| 223 |
-
{ "name": "outW", "type": "u32", "value": "dim(shapes.Y, 3)" },
|
| 224 |
-
{ "name": "strideH", "type": "u32", "value": "strideH" },
|
| 225 |
-
{ "name": "strideW", "type": "u32", "value": "strideW" },
|
| 226 |
-
{ "name": "dilationH", "type": "u32", "value": "dilationH" },
|
| 227 |
-
{ "name": "dilationW", "type": "u32", "value": "dilationW" },
|
| 228 |
-
{ "name": "padH", "type": "i32", "value": "padTop" },
|
| 229 |
-
{ "name": "padW", "type": "i32", "value": "padLeft" },
|
| 230 |
-
{ "name": "offsetGroup", "type": "u32", "value": "attrs.offset_group" }
|
| 231 |
-
]
|
| 232 |
-
}
|
| 233 |
-
}
|
| 234 |
-
]
|
| 235 |
},
|
| 236 |
"variants": [
|
| 237 |
{
|
|
@@ -242,35 +99,37 @@
|
|
| 242 |
{
|
| 243 |
"id": "main",
|
| 244 |
"name": "DeformConv.AlignedGroupsBlocked",
|
| 245 |
-
"
|
| 246 |
-
|
| 247 |
-
"
|
| 248 |
-
|
| 249 |
-
|
| 250 |
-
|
| 251 |
-
|
| 252 |
-
|
| 253 |
-
|
| 254 |
-
|
| 255 |
-
|
| 256 |
-
|
| 257 |
-
|
| 258 |
-
|
| 259 |
-
|
| 260 |
-
|
| 261 |
-
|
| 262 |
-
|
| 263 |
-
|
| 264 |
-
|
| 265 |
-
|
| 266 |
-
|
| 267 |
-
|
| 268 |
-
|
| 269 |
-
"hasMask": true
|
| 270 |
-
}
|
| 271 |
},
|
| 272 |
-
"bindings": "
|
| 273 |
-
"dispatch": {
|
|
|
|
|
|
|
|
|
|
|
|
|
| 274 |
}
|
| 275 |
]
|
| 276 |
},
|
|
@@ -282,143 +141,93 @@
|
|
| 282 |
{
|
| 283 |
"id": "main",
|
| 284 |
"name": "DeformConv.AlignedGroupsBlocked",
|
| 285 |
-
"
|
| 286 |
-
|
| 287 |
-
"
|
| 288 |
-
|
| 289 |
-
|
| 290 |
-
|
| 291 |
-
|
| 292 |
-
|
| 293 |
-
|
| 294 |
-
|
| 295 |
-
|
| 296 |
-
|
| 297 |
-
|
| 298 |
-
|
| 299 |
-
|
| 300 |
-
|
| 301 |
-
|
| 302 |
-
|
| 303 |
-
|
| 304 |
-
|
| 305 |
-
|
| 306 |
-
|
| 307 |
-
|
| 308 |
-
|
| 309 |
-
"hasMask": false
|
| 310 |
-
}
|
| 311 |
},
|
| 312 |
-
"bindings": "
|
| 313 |
-
"dispatch": {
|
|
|
|
|
|
|
|
|
|
|
|
|
| 314 |
}
|
| 315 |
]
|
| 316 |
},
|
| 317 |
{
|
| 318 |
"id": "nchw2d",
|
| 319 |
"when": ["genericPlainOk"],
|
| 320 |
-
"
|
| 321 |
"passes": [
|
| 322 |
{
|
| 323 |
"id": "main",
|
| 324 |
"name": "DeformConv",
|
| 325 |
"shader": "deform-conv2d-nchw.wgsl.jinja",
|
| 326 |
-
"bindings": "
|
| 327 |
-
"dispatch": {
|
|
|
|
|
|
|
|
|
|
|
|
|
| 328 |
}
|
| 329 |
]
|
| 330 |
},
|
| 331 |
{
|
| 332 |
"id": "nchw2d_bias_mask",
|
|
|
|
| 333 |
"when": ["genericBiasMaskOk"],
|
| 334 |
-
"
|
| 335 |
"passes": [
|
| 336 |
{
|
| 337 |
"id": "main",
|
| 338 |
"name": "DeformConv",
|
| 339 |
"shader": "deform-conv2d-nchw.wgsl.jinja",
|
| 340 |
-
"bindings": "
|
| 341 |
-
"dispatch": {
|
|
|
|
|
|
|
|
|
|
|
|
|
| 342 |
}
|
| 343 |
-
]
|
| 344 |
-
"priority": 10
|
| 345 |
},
|
| 346 |
{
|
| 347 |
"id": "nchw2d_bias",
|
| 348 |
"priority": 5,
|
| 349 |
"when": ["genericBiasOk"],
|
| 350 |
-
"
|
| 351 |
"passes": [
|
| 352 |
{
|
| 353 |
"id": "main",
|
| 354 |
"name": "DeformConv",
|
| 355 |
"shader": "deform-conv2d-nchw.wgsl.jinja",
|
| 356 |
-
"bindings": [
|
| 357 |
-
|
| 358 |
-
|
| 359 |
-
|
| 360 |
-
|
| 361 |
-
|
| 362 |
-
"elementType": "f32"
|
| 363 |
-
},
|
| 364 |
-
{
|
| 365 |
-
"name": "w",
|
| 366 |
-
"arg": "w",
|
| 367 |
-
"semantic": "W",
|
| 368 |
-
"buffer": { "type": "read-only-storage" },
|
| 369 |
-
"elementType": "f32"
|
| 370 |
-
},
|
| 371 |
-
{
|
| 372 |
-
"name": "offset",
|
| 373 |
-
"arg": "offset",
|
| 374 |
-
"semantic": "offset",
|
| 375 |
-
"buffer": { "type": "read-only-storage" },
|
| 376 |
-
"elementType": "f32"
|
| 377 |
-
},
|
| 378 |
-
{
|
| 379 |
-
"name": "bias",
|
| 380 |
-
"arg": "bias",
|
| 381 |
-
"semantic": "B",
|
| 382 |
-
"buffer": { "type": "read-only-storage" },
|
| 383 |
-
"elementType": "f32"
|
| 384 |
-
},
|
| 385 |
-
{ "name": "y", "arg": "y", "semantic": "Y", "buffer": { "type": "storage" }, "elementType": "f32" },
|
| 386 |
-
{
|
| 387 |
-
"name": "params",
|
| 388 |
-
"semantic": "kernel.params",
|
| 389 |
-
"buffer": { "type": "uniform" },
|
| 390 |
-
"struct": {
|
| 391 |
-
"name": "Params",
|
| 392 |
-
"fields": [
|
| 393 |
-
{ "name": "count", "type": "u32", "value": "numel(shapes.Y)" },
|
| 394 |
-
{ "name": "inChannels", "type": "u32", "value": "dim(shapes.X, 1)" },
|
| 395 |
-
{ "name": "inH", "type": "u32", "value": "dim(shapes.X, 2)" },
|
| 396 |
-
{ "name": "inW", "type": "u32", "value": "dim(shapes.X, 3)" },
|
| 397 |
-
{ "name": "outChannels", "type": "u32", "value": "dim(shapes.W, 0)" },
|
| 398 |
-
{ "name": "weightInChannels", "type": "u32", "value": "dim(shapes.W, 1)" },
|
| 399 |
-
{ "name": "inChannelsPerGroup", "type": "u32", "value": "dim(shapes.X, 1) / attrs.group" },
|
| 400 |
-
{ "name": "outChannelsPerGroup", "type": "u32", "value": "dim(shapes.W, 0) / attrs.group" },
|
| 401 |
-
{
|
| 402 |
-
"name": "inChannelsPerOffsetGroup",
|
| 403 |
-
"type": "u32",
|
| 404 |
-
"value": "dim(shapes.X, 1) / attrs.offset_group"
|
| 405 |
-
},
|
| 406 |
-
{ "name": "kernelH", "type": "u32", "value": "dim(shapes.W, 2)" },
|
| 407 |
-
{ "name": "kernelW", "type": "u32", "value": "dim(shapes.W, 3)" },
|
| 408 |
-
{ "name": "outH", "type": "u32", "value": "dim(shapes.Y, 2)" },
|
| 409 |
-
{ "name": "outW", "type": "u32", "value": "dim(shapes.Y, 3)" },
|
| 410 |
-
{ "name": "strideH", "type": "u32", "value": "strideH" },
|
| 411 |
-
{ "name": "strideW", "type": "u32", "value": "strideW" },
|
| 412 |
-
{ "name": "dilationH", "type": "u32", "value": "dilationH" },
|
| 413 |
-
{ "name": "dilationW", "type": "u32", "value": "dilationW" },
|
| 414 |
-
{ "name": "padH", "type": "i32", "value": "padTop" },
|
| 415 |
-
{ "name": "padW", "type": "i32", "value": "padLeft" },
|
| 416 |
-
{ "name": "offsetGroup", "type": "u32", "value": "attrs.offset_group" }
|
| 417 |
-
]
|
| 418 |
-
}
|
| 419 |
-
}
|
| 420 |
-
],
|
| 421 |
-
"dispatch": { "threads": "numel(shapes.Y)", "workgroupSize": "tunables.WORKGROUP_SIZE" }
|
| 422 |
}
|
| 423 |
]
|
| 424 |
},
|
|
@@ -426,78 +235,18 @@
|
|
| 426 |
"id": "nchw2d_mask",
|
| 427 |
"priority": 5,
|
| 428 |
"when": ["genericMaskOk"],
|
| 429 |
-
"
|
| 430 |
"passes": [
|
| 431 |
{
|
| 432 |
"id": "main",
|
| 433 |
"name": "DeformConv",
|
| 434 |
"shader": "deform-conv2d-nchw.wgsl.jinja",
|
| 435 |
-
"bindings": [
|
| 436 |
-
|
| 437 |
-
|
| 438 |
-
|
| 439 |
-
|
| 440 |
-
|
| 441 |
-
"elementType": "f32"
|
| 442 |
-
},
|
| 443 |
-
{
|
| 444 |
-
"name": "w",
|
| 445 |
-
"arg": "w",
|
| 446 |
-
"semantic": "W",
|
| 447 |
-
"buffer": { "type": "read-only-storage" },
|
| 448 |
-
"elementType": "f32"
|
| 449 |
-
},
|
| 450 |
-
{
|
| 451 |
-
"name": "offset",
|
| 452 |
-
"arg": "offset",
|
| 453 |
-
"semantic": "offset",
|
| 454 |
-
"buffer": { "type": "read-only-storage" },
|
| 455 |
-
"elementType": "f32"
|
| 456 |
-
},
|
| 457 |
-
{
|
| 458 |
-
"name": "mask",
|
| 459 |
-
"arg": "mask",
|
| 460 |
-
"semantic": "mask",
|
| 461 |
-
"buffer": { "type": "read-only-storage" },
|
| 462 |
-
"elementType": "f32"
|
| 463 |
-
},
|
| 464 |
-
{ "name": "y", "arg": "y", "semantic": "Y", "buffer": { "type": "storage" }, "elementType": "f32" },
|
| 465 |
-
{
|
| 466 |
-
"name": "params",
|
| 467 |
-
"semantic": "kernel.params",
|
| 468 |
-
"buffer": { "type": "uniform" },
|
| 469 |
-
"struct": {
|
| 470 |
-
"name": "Params",
|
| 471 |
-
"fields": [
|
| 472 |
-
{ "name": "count", "type": "u32", "value": "numel(shapes.Y)" },
|
| 473 |
-
{ "name": "inChannels", "type": "u32", "value": "dim(shapes.X, 1)" },
|
| 474 |
-
{ "name": "inH", "type": "u32", "value": "dim(shapes.X, 2)" },
|
| 475 |
-
{ "name": "inW", "type": "u32", "value": "dim(shapes.X, 3)" },
|
| 476 |
-
{ "name": "outChannels", "type": "u32", "value": "dim(shapes.W, 0)" },
|
| 477 |
-
{ "name": "weightInChannels", "type": "u32", "value": "dim(shapes.W, 1)" },
|
| 478 |
-
{ "name": "inChannelsPerGroup", "type": "u32", "value": "dim(shapes.X, 1) / attrs.group" },
|
| 479 |
-
{ "name": "outChannelsPerGroup", "type": "u32", "value": "dim(shapes.W, 0) / attrs.group" },
|
| 480 |
-
{
|
| 481 |
-
"name": "inChannelsPerOffsetGroup",
|
| 482 |
-
"type": "u32",
|
| 483 |
-
"value": "dim(shapes.X, 1) / attrs.offset_group"
|
| 484 |
-
},
|
| 485 |
-
{ "name": "kernelH", "type": "u32", "value": "dim(shapes.W, 2)" },
|
| 486 |
-
{ "name": "kernelW", "type": "u32", "value": "dim(shapes.W, 3)" },
|
| 487 |
-
{ "name": "outH", "type": "u32", "value": "dim(shapes.Y, 2)" },
|
| 488 |
-
{ "name": "outW", "type": "u32", "value": "dim(shapes.Y, 3)" },
|
| 489 |
-
{ "name": "strideH", "type": "u32", "value": "strideH" },
|
| 490 |
-
{ "name": "strideW", "type": "u32", "value": "strideW" },
|
| 491 |
-
{ "name": "dilationH", "type": "u32", "value": "dilationH" },
|
| 492 |
-
{ "name": "dilationW", "type": "u32", "value": "dilationW" },
|
| 493 |
-
{ "name": "padH", "type": "i32", "value": "padTop" },
|
| 494 |
-
{ "name": "padW", "type": "i32", "value": "padLeft" },
|
| 495 |
-
{ "name": "offsetGroup", "type": "u32", "value": "attrs.offset_group" }
|
| 496 |
-
]
|
| 497 |
-
}
|
| 498 |
-
}
|
| 499 |
-
],
|
| 500 |
-
"dispatch": { "threads": "numel(shapes.Y)", "workgroupSize": "tunables.WORKGROUP_SIZE" }
|
| 501 |
}
|
| 502 |
]
|
| 503 |
}
|
|
|
|
| 2 |
"domain": "ai.onnx",
|
| 3 |
"name": "DeformConv",
|
| 4 |
"sinceVersion": 22,
|
| 5 |
+
"inputs": {
|
| 6 |
+
"x": { "onnx": "X", "dtype": "T", "rank": 4 },
|
| 7 |
+
"w": { "onnx": "W", "dtype": "T", "rank": 4 },
|
| 8 |
+
"offset": { "dtype": "T", "rank": 4 },
|
| 9 |
+
"bias": { "onnx": "B", "dtype": "T", "rank": 1, "optional": true },
|
| 10 |
+
"mask": { "dtype": "T", "rank": 4, "optional": true }
|
| 11 |
+
},
|
| 12 |
+
"outputs": {
|
| 13 |
+
"y": {
|
| 14 |
+
"onnx": "Y",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
"dtype": "T",
|
|
|
|
| 16 |
"rank": 4,
|
| 17 |
+
"shape": ["dim(shapes.x, 0)", "dim(shapes.w, 0)", "floor((dim(shapes.x, 2) + padTop + padBottom - ((dim(shapes.w, 2) - 1) * dilationH + 1)) / strideH) + 1", "floor((dim(shapes.x, 3) + padLeft + padRight - ((dim(shapes.w, 3) - 1) * dilationW + 1)) / strideW) + 1"]
|
| 18 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
},
|
| 20 |
+
"attributes": {
|
| 21 |
+
"group": { "default": 1 },
|
| 22 |
+
"offset_group": { "default": 1 },
|
| 23 |
+
"dilations": {},
|
| 24 |
+
"kernel_shape": {},
|
| 25 |
+
"pads": {},
|
| 26 |
+
"strides": {}
|
|
|
|
| 27 |
},
|
| 28 |
+
"typeConstraints": { "T": ["float32"] },
|
| 29 |
+
"tunables": { "WORKGROUP_SIZE": { "default": 128 } },
|
| 30 |
"derive": {
|
| 31 |
"spatialRank": 2,
|
| 32 |
"kernelShapeLengthOk": "not has(attrs, \"kernel_shape\") or (attrs.kernel_shape | length) == spatialRank",
|
|
|
|
| 43 |
"padLeft": "attrs.pads[spatialRank - 1] if padsLengthOk and has(attrs, \"pads\") and spatialRank >= 1 else 0",
|
| 44 |
"padBottom": "attrs.pads[2 * spatialRank - 2] if padsLengthOk and has(attrs, \"pads\") and spatialRank >= 2 else 0",
|
| 45 |
"padRight": "attrs.pads[2 * spatialRank - 1] if padsLengthOk and has(attrs, \"pads\") and spatialRank >= 1 else 0",
|
| 46 |
+
"spatialAttributesOk": "kernelShapeLengthOk and stridesLengthOk and dilationsLengthOk and padsLengthOk and strideH >= 1 and strideW >= 1 and dilationH >= 1 and dilationW >= 1 and padTop >= 0 and padLeft >= 0 and padBottom >= 0 and padRight >= 0 and (not has(attrs, \"kernel_shape\") or (kernelH == dim(shapes.w, 2) and kernelW == dim(shapes.w, 3)))",
|
| 47 |
+
"alignedGroupsCoreOk": "spatialAttributesOk and ranks.x == 4 and ranks.w == 4 and ranks.offset == 4 and ranks.y == 4 and attrs.group >= 1 and attrs.offset_group == attrs.group and dim(shapes.w, 2) >= 1 and dim(shapes.w, 2) <= 7 and dim(shapes.w, 3) >= 1 and dim(shapes.w, 3) <= 7 and dim(shapes.w, 1) * attrs.group == dim(shapes.x, 1) and dim(shapes.w, 0) % attrs.group == 0 and dim(shapes.y, 0) == dim(shapes.x, 0) and dim(shapes.y, 1) == dim(shapes.w, 0) and dim(shapes.y, 2) == floor((dim(shapes.x, 2) + padTop + padBottom - ((dim(shapes.w, 2) - 1) * dilationH + 1)) / strideH) + 1 and dim(shapes.y, 3) == floor((dim(shapes.x, 3) + padLeft + padRight - ((dim(shapes.w, 3) - 1) * dilationW + 1)) / strideW) + 1 and dim(shapes.offset, 0) == dim(shapes.x, 0) and dim(shapes.offset, 1) == attrs.offset_group * dim(shapes.w, 2) * dim(shapes.w, 3) * 2 and dim(shapes.offset, 2) == dim(shapes.y, 2) and dim(shapes.offset, 3) == dim(shapes.y, 3)",
|
| 48 |
+
"alignedBiasMaskOk": "alignedGroupsCoreOk and present.bias and present.mask and ranks.bias == 1 and ranks.mask == 4 and dim(shapes.bias, 0) == dim(shapes.w, 0) and dim(shapes.mask, 0) == dim(shapes.x, 0) and dim(shapes.mask, 1) == attrs.offset_group * dim(shapes.w, 2) * dim(shapes.w, 3) and dim(shapes.mask, 2) == dim(shapes.y, 2) and dim(shapes.mask, 3) == dim(shapes.y, 3)",
|
| 49 |
"alignedPlainOk": "alignedGroupsCoreOk and not present.bias and not present.mask",
|
| 50 |
+
"genericCoreOk": "spatialAttributesOk and ranks.x == 4 and ranks.w == 4 and ranks.offset == 4 and ranks.y == 4 and attrs.group >= 1 and attrs.offset_group >= 1 and dim(shapes.w, 1) * attrs.group == dim(shapes.x, 1) and dim(shapes.x, 1) % attrs.offset_group == 0 and dim(shapes.w, 0) % attrs.group == 0 and dim(shapes.y, 0) == dim(shapes.x, 0) and dim(shapes.y, 1) == dim(shapes.w, 0) and dim(shapes.y, 2) == floor((dim(shapes.x, 2) + padTop + padBottom - ((dim(shapes.w, 2) - 1) * dilationH + 1)) / strideH) + 1 and dim(shapes.y, 3) == floor((dim(shapes.x, 3) + padLeft + padRight - ((dim(shapes.w, 3) - 1) * dilationW + 1)) / strideW) + 1 and dim(shapes.offset, 0) == dim(shapes.x, 0) and dim(shapes.offset, 1) == attrs.offset_group * dim(shapes.w, 2) * dim(shapes.w, 3) * 2 and dim(shapes.offset, 2) == dim(shapes.y, 2) and dim(shapes.offset, 3) == dim(shapes.y, 3)",
|
| 51 |
+
"genericBiasShapeOk": "present.bias and ranks.bias == 1 and dim(shapes.bias, 0) == dim(shapes.w, 0)",
|
| 52 |
+
"genericMaskShapeOk": "present.mask and ranks.mask == 4 and dim(shapes.mask, 0) == dim(shapes.x, 0) and dim(shapes.mask, 1) == attrs.offset_group * dim(shapes.w, 2) * dim(shapes.w, 3) and dim(shapes.mask, 2) == dim(shapes.y, 2) and dim(shapes.mask, 3) == dim(shapes.y, 3)",
|
| 53 |
"genericPlainOk": "genericCoreOk and not present.bias and not present.mask",
|
| 54 |
"genericBiasOk": "genericCoreOk and genericBiasShapeOk and not present.mask",
|
| 55 |
"genericMaskOk": "genericCoreOk and not present.bias and genericMaskShapeOk",
|
| 56 |
"genericBiasMaskOk": "genericCoreOk and genericBiasShapeOk and genericMaskShapeOk",
|
| 57 |
+
"alignedOcBlock": "16 if (dim(shapes.w, 0) / attrs.group) % 16 == 0 else (8 if (dim(shapes.w, 0) / attrs.group) % 8 == 0 else (4 if (dim(shapes.w, 0) / attrs.group) % 4 == 0 else 1))",
|
| 58 |
"alignedOcVecs": "4 if alignedOcBlock == 16 else (2 if alignedOcBlock == 8 else (1 if alignedOcBlock == 4 else 0))"
|
| 59 |
},
|
| 60 |
+
"bindings": {
|
| 61 |
+
"x": { "buffer": "read-only-storage", "elementType": "f32" },
|
| 62 |
+
"w": { "buffer": "read-only-storage", "elementType": "f32" },
|
| 63 |
+
"offset": { "buffer": "read-only-storage", "elementType": "f32" },
|
| 64 |
+
"bias": { "buffer": "read-only-storage", "elementType": "f32" },
|
| 65 |
+
"mask": { "buffer": "read-only-storage", "elementType": "f32" },
|
| 66 |
+
"y": { "buffer": "storage", "elementType": "f32" },
|
| 67 |
+
"params": {
|
| 68 |
+
"buffer": "uniform",
|
| 69 |
+
"struct": [
|
| 70 |
+
{ "name": "count", "type": "u32", "value": "numel(shapes.y)" },
|
| 71 |
+
{ "name": "inChannels", "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": "outChannels", "type": "u32", "value": "dim(shapes.w, 0)" },
|
| 75 |
+
{ "name": "weightInChannels", "type": "u32", "value": "dim(shapes.w, 1)" },
|
| 76 |
+
{ "name": "inChannelsPerGroup", "type": "u32", "value": "dim(shapes.x, 1) / attrs.group" },
|
| 77 |
+
{ "name": "outChannelsPerGroup", "type": "u32", "value": "dim(shapes.w, 0) / attrs.group" },
|
| 78 |
+
{ "name": "inChannelsPerOffsetGroup", "type": "u32", "value": "dim(shapes.x, 1) / attrs.offset_group" },
|
| 79 |
+
{ "name": "kernelH", "type": "u32", "value": "dim(shapes.w, 2)" },
|
| 80 |
+
{ "name": "kernelW", "type": "u32", "value": "dim(shapes.w, 3)" },
|
| 81 |
+
{ "name": "outH", "type": "u32", "value": "dim(shapes.y, 2)" },
|
| 82 |
+
{ "name": "outW", "type": "u32", "value": "dim(shapes.y, 3)" },
|
| 83 |
+
{ "name": "strideH", "type": "u32", "value": "strideH" },
|
| 84 |
+
{ "name": "strideW", "type": "u32", "value": "strideW" },
|
| 85 |
+
{ "name": "dilationH", "type": "u32", "value": "dilationH" },
|
| 86 |
+
{ "name": "dilationW", "type": "u32", "value": "dilationW" },
|
| 87 |
+
{ "name": "padH", "type": "i32", "value": "padTop" },
|
| 88 |
+
{ "name": "padW", "type": "i32", "value": "padLeft" },
|
| 89 |
+
{ "name": "offsetGroup", "type": "u32", "value": "attrs.offset_group" }
|
| 90 |
+
]
|
| 91 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 92 |
},
|
| 93 |
"variants": [
|
| 94 |
{
|
|
|
|
| 99 |
{
|
| 100 |
"id": "main",
|
| 101 |
"name": "DeformConv.AlignedGroupsBlocked",
|
| 102 |
+
"shader": "deform-conv2d-aligned-groups.wgsl.jinja",
|
| 103 |
+
"derive": {
|
| 104 |
+
"count": "numel(shapes.y) / alignedOcBlock",
|
| 105 |
+
"inC": "dim(shapes.x, 1)",
|
| 106 |
+
"inCPerGroup": "dim(shapes.x, 1) / attrs.group",
|
| 107 |
+
"inH": "dim(shapes.x, 2)",
|
| 108 |
+
"inW": "dim(shapes.x, 3)",
|
| 109 |
+
"outC": "dim(shapes.y, 1)",
|
| 110 |
+
"outCPerGroup": "dim(shapes.y, 1) / attrs.group",
|
| 111 |
+
"outChannelBlock": "alignedOcBlock",
|
| 112 |
+
"outChannelVecs": "alignedOcVecs",
|
| 113 |
+
"groups": "attrs.group",
|
| 114 |
+
"outH": "dim(shapes.y, 2)",
|
| 115 |
+
"outW": "dim(shapes.y, 3)",
|
| 116 |
+
"kernelHSpec": "dim(shapes.w, 2)",
|
| 117 |
+
"kernelWSpec": "dim(shapes.w, 3)",
|
| 118 |
+
"strideHSpec": "strideH",
|
| 119 |
+
"strideWSpec": "strideW",
|
| 120 |
+
"dilationHSpec": "dilationH",
|
| 121 |
+
"dilationWSpec": "dilationW",
|
| 122 |
+
"padH": "padTop",
|
| 123 |
+
"padW": "padLeft",
|
| 124 |
+
"hasBias": true,
|
| 125 |
+
"hasMask": true
|
|
|
|
|
|
|
| 126 |
},
|
| 127 |
+
"bindings": ["x", "w", "offset", "bias", "mask", "y"],
|
| 128 |
+
"dispatch": {
|
| 129 |
+
"x": "min(ceilDiv((numel(shapes.y) / alignedOcBlock), (tunables.WORKGROUP_SIZE)), 65535)",
|
| 130 |
+
"y": "ceilDiv(ceilDiv((numel(shapes.y) / alignedOcBlock), (tunables.WORKGROUP_SIZE)), 65535)",
|
| 131 |
+
"z": 1
|
| 132 |
+
}
|
| 133 |
}
|
| 134 |
]
|
| 135 |
},
|
|
|
|
| 141 |
{
|
| 142 |
"id": "main",
|
| 143 |
"name": "DeformConv.AlignedGroupsBlocked",
|
| 144 |
+
"shader": "deform-conv2d-aligned-groups.wgsl.jinja",
|
| 145 |
+
"derive": {
|
| 146 |
+
"count": "numel(shapes.y) / alignedOcBlock",
|
| 147 |
+
"inC": "dim(shapes.x, 1)",
|
| 148 |
+
"inCPerGroup": "dim(shapes.x, 1) / attrs.group",
|
| 149 |
+
"inH": "dim(shapes.x, 2)",
|
| 150 |
+
"inW": "dim(shapes.x, 3)",
|
| 151 |
+
"outC": "dim(shapes.y, 1)",
|
| 152 |
+
"outCPerGroup": "dim(shapes.y, 1) / attrs.group",
|
| 153 |
+
"outChannelBlock": "alignedOcBlock",
|
| 154 |
+
"outChannelVecs": "alignedOcVecs",
|
| 155 |
+
"groups": "attrs.group",
|
| 156 |
+
"outH": "dim(shapes.y, 2)",
|
| 157 |
+
"outW": "dim(shapes.y, 3)",
|
| 158 |
+
"kernelHSpec": "dim(shapes.w, 2)",
|
| 159 |
+
"kernelWSpec": "dim(shapes.w, 3)",
|
| 160 |
+
"strideHSpec": "strideH",
|
| 161 |
+
"strideWSpec": "strideW",
|
| 162 |
+
"dilationHSpec": "dilationH",
|
| 163 |
+
"dilationWSpec": "dilationW",
|
| 164 |
+
"padH": "padTop",
|
| 165 |
+
"padW": "padLeft",
|
| 166 |
+
"hasBias": false,
|
| 167 |
+
"hasMask": false
|
|
|
|
|
|
|
| 168 |
},
|
| 169 |
+
"bindings": ["x", "w", "offset", "y"],
|
| 170 |
+
"dispatch": {
|
| 171 |
+
"x": "min(ceilDiv((numel(shapes.y) / alignedOcBlock), (tunables.WORKGROUP_SIZE)), 65535)",
|
| 172 |
+
"y": "ceilDiv(ceilDiv((numel(shapes.y) / alignedOcBlock), (tunables.WORKGROUP_SIZE)), 65535)",
|
| 173 |
+
"z": 1
|
| 174 |
+
}
|
| 175 |
}
|
| 176 |
]
|
| 177 |
},
|
| 178 |
{
|
| 179 |
"id": "nchw2d",
|
| 180 |
"when": ["genericPlainOk"],
|
| 181 |
+
"derive": { "hasBias": false, "hasMask": false },
|
| 182 |
"passes": [
|
| 183 |
{
|
| 184 |
"id": "main",
|
| 185 |
"name": "DeformConv",
|
| 186 |
"shader": "deform-conv2d-nchw.wgsl.jinja",
|
| 187 |
+
"bindings": ["x", "w", "offset", "y", "params"],
|
| 188 |
+
"dispatch": {
|
| 189 |
+
"x": "min(ceilDiv((numel(shapes.y)), (tunables.WORKGROUP_SIZE)), 65535)",
|
| 190 |
+
"y": "ceilDiv(ceilDiv((numel(shapes.y)), (tunables.WORKGROUP_SIZE)), 65535)",
|
| 191 |
+
"z": 1
|
| 192 |
+
}
|
| 193 |
}
|
| 194 |
]
|
| 195 |
},
|
| 196 |
{
|
| 197 |
"id": "nchw2d_bias_mask",
|
| 198 |
+
"priority": 10,
|
| 199 |
"when": ["genericBiasMaskOk"],
|
| 200 |
+
"derive": { "hasBias": true, "hasMask": true },
|
| 201 |
"passes": [
|
| 202 |
{
|
| 203 |
"id": "main",
|
| 204 |
"name": "DeformConv",
|
| 205 |
"shader": "deform-conv2d-nchw.wgsl.jinja",
|
| 206 |
+
"bindings": ["x", "w", "offset", "bias", "mask", "y", "params"],
|
| 207 |
+
"dispatch": {
|
| 208 |
+
"x": "min(ceilDiv((numel(shapes.y)), (tunables.WORKGROUP_SIZE)), 65535)",
|
| 209 |
+
"y": "ceilDiv(ceilDiv((numel(shapes.y)), (tunables.WORKGROUP_SIZE)), 65535)",
|
| 210 |
+
"z": 1
|
| 211 |
+
}
|
| 212 |
}
|
| 213 |
+
]
|
|
|
|
| 214 |
},
|
| 215 |
{
|
| 216 |
"id": "nchw2d_bias",
|
| 217 |
"priority": 5,
|
| 218 |
"when": ["genericBiasOk"],
|
| 219 |
+
"derive": { "hasBias": true, "hasMask": false },
|
| 220 |
"passes": [
|
| 221 |
{
|
| 222 |
"id": "main",
|
| 223 |
"name": "DeformConv",
|
| 224 |
"shader": "deform-conv2d-nchw.wgsl.jinja",
|
| 225 |
+
"bindings": ["x", "w", "offset", "bias", "y", "params"],
|
| 226 |
+
"dispatch": {
|
| 227 |
+
"x": "min(ceilDiv((numel(shapes.y)), (tunables.WORKGROUP_SIZE)), 65535)",
|
| 228 |
+
"y": "ceilDiv(ceilDiv((numel(shapes.y)), (tunables.WORKGROUP_SIZE)), 65535)",
|
| 229 |
+
"z": 1
|
| 230 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 231 |
}
|
| 232 |
]
|
| 233 |
},
|
|
|
|
| 235 |
"id": "nchw2d_mask",
|
| 236 |
"priority": 5,
|
| 237 |
"when": ["genericMaskOk"],
|
| 238 |
+
"derive": { "hasBias": false, "hasMask": true },
|
| 239 |
"passes": [
|
| 240 |
{
|
| 241 |
"id": "main",
|
| 242 |
"name": "DeformConv",
|
| 243 |
"shader": "deform-conv2d-nchw.wgsl.jinja",
|
| 244 |
+
"bindings": ["x", "w", "offset", "mask", "y", "params"],
|
| 245 |
+
"dispatch": {
|
| 246 |
+
"x": "min(ceilDiv((numel(shapes.y)), (tunables.WORKGROUP_SIZE)), 65535)",
|
| 247 |
+
"y": "ceilDiv(ceilDiv((numel(shapes.y)), (tunables.WORKGROUP_SIZE)), 65535)",
|
| 248 |
+
"z": 1
|
| 249 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 250 |
}
|
| 251 |
]
|
| 252 |
}
|
build/webgpu/metadata.json
CHANGED
|
@@ -1,19 +1,29 @@
|
|
| 1 |
{
|
| 2 |
"name": "ai.onnx.DeformConv",
|
| 3 |
-
"id": "
|
| 4 |
"version": 1,
|
| 5 |
"license": "Apache-2.0",
|
| 6 |
"backend": { "type": "webgpu" },
|
| 7 |
"digest": {
|
| 8 |
"algorithm": "sha256",
|
| 9 |
"files": {
|
| 10 |
-
"bench.json": "
|
| 11 |
-
"deform-conv2d-aligned-groups.wgsl.jinja": "
|
| 12 |
-
"deform-conv2d-nchw.wgsl.jinja": "
|
| 13 |
-
"manifest.json": "
|
| 14 |
-
"test.json": "
|
| 15 |
}
|
| 16 |
},
|
| 17 |
-
"provenance": { "kernel": { "sha": "
|
| 18 |
-
"webgpu": {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
}
|
|
|
|
| 1 |
{
|
| 2 |
"name": "ai.onnx.DeformConv",
|
| 3 |
+
"id": "_ai_onnx_deformconv_webgpu_bd95a88",
|
| 4 |
"version": 1,
|
| 5 |
"license": "Apache-2.0",
|
| 6 |
"backend": { "type": "webgpu" },
|
| 7 |
"digest": {
|
| 8 |
"algorithm": "sha256",
|
| 9 |
"files": {
|
| 10 |
+
"bench.json": "QuUDCU5THdFkh2/r2/k4/Uo61MTtbMbE8R5uE3XZagU=",
|
| 11 |
+
"deform-conv2d-aligned-groups.wgsl.jinja": "dtmKq+oPJLAziEgWffUCuNR05TCDSWuFTpIeKrkfhXA=",
|
| 12 |
+
"deform-conv2d-nchw.wgsl.jinja": "hjYa940wbG47JZU6xEB1f+ocmLfCTdKYd2bZWwZ+8VU=",
|
| 13 |
+
"manifest.json": "p+fNwbHM9W6A5oca8kgfytxZOvic1x+qOPu44gH6Kts=",
|
| 14 |
+
"test.json": "868t0+sfE0Szo3ySh3cdEN+OTQ+77X7pAUXkgxxZqrc="
|
| 15 |
}
|
| 16 |
},
|
| 17 |
+
"provenance": { "kernel": { "sha": "91d990483a174128daf7673f3f37a7c890493ae1", "dirty": false } },
|
| 18 |
+
"webgpu": {
|
| 19 |
+
"manifestSpec": "2.0",
|
| 20 |
+
"variants": {
|
| 21 |
+
"nchw2d_bias_mask_aligned_groups_blocked": ["deform-conv2d-aligned-groups.wgsl.jinja"],
|
| 22 |
+
"nchw2d_aligned_groups_blocked": ["deform-conv2d-aligned-groups.wgsl.jinja"],
|
| 23 |
+
"nchw2d": ["deform-conv2d-nchw.wgsl.jinja"],
|
| 24 |
+
"nchw2d_bias_mask": ["deform-conv2d-nchw.wgsl.jinja"],
|
| 25 |
+
"nchw2d_bias": ["deform-conv2d-nchw.wgsl.jinja"],
|
| 26 |
+
"nchw2d_mask": ["deform-conv2d-nchw.wgsl.jinja"]
|
| 27 |
+
}
|
| 28 |
+
}
|
| 29 |
}
|
build/webgpu/test.json
CHANGED
|
@@ -1,5 +1,4 @@
|
|
| 1 |
{
|
| 2 |
-
"op": "ai.onnx.DeformConv",
|
| 3 |
"fixtureArrays": {
|
| 4 |
"onnx_backend_basic_deform_conv_without_padding_input_offset": [0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.10000000149011612, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
| 5 |
},
|
|
@@ -128,7 +127,7 @@
|
|
| 128 |
"w": {
|
| 129 |
"dtype": "float32",
|
| 130 |
"shape": [1, 1, 2, 2],
|
| 131 |
-
"data": { "kind": "values", "values": [1.0, 0.0, 0.0, -
|
| 132 |
},
|
| 133 |
"offset": { "dtype": "float32", "shape": [1, 8, 2, 2], "data": { "kind": "constant", "value": 0.0 } }
|
| 134 |
},
|
|
@@ -211,7 +210,7 @@
|
|
| 211 |
{
|
| 212 |
"name": "mask_zeros_preserve_bias",
|
| 213 |
"inputs": {
|
| 214 |
-
"x": { "dtype": "float32", "shape": [1, 1, 2, 2], "data": { "kind": "
|
| 215 |
"w": { "dtype": "float32", "shape": [1, 1, 1, 1], "data": { "kind": "values", "values": [7.0] } },
|
| 216 |
"offset": { "dtype": "float32", "shape": [1, 2, 2, 2], "data": { "kind": "constant", "value": 0.0 } },
|
| 217 |
"bias": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [0.5] } },
|
|
@@ -788,7 +787,7 @@
|
|
| 788 |
"offset": {
|
| 789 |
"dtype": "float32",
|
| 790 |
"shape": [1, 2, 2, 2],
|
| 791 |
-
"data": { "kind": "values", "values": [2.0, 2.0,
|
| 792 |
}
|
| 793 |
},
|
| 794 |
"outputs": {
|
|
@@ -796,7 +795,7 @@
|
|
| 796 |
"dtype": "float32",
|
| 797 |
"shape": [1, 1, 2, 2],
|
| 798 |
"tolerance": 0,
|
| 799 |
-
"data": { "kind": "values", "values": [0.0, 0.0,
|
| 800 |
}
|
| 801 |
}
|
| 802 |
},
|
|
|
|
| 1 |
{
|
|
|
|
| 2 |
"fixtureArrays": {
|
| 3 |
"onnx_backend_basic_deform_conv_without_padding_input_offset": [0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.10000000149011612, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
| 4 |
},
|
|
|
|
| 127 |
"w": {
|
| 128 |
"dtype": "float32",
|
| 129 |
"shape": [1, 1, 2, 2],
|
| 130 |
+
"data": { "kind": "values", "values": [1.0, 0.0, 0.0, -2.0] }
|
| 131 |
},
|
| 132 |
"offset": { "dtype": "float32", "shape": [1, 8, 2, 2], "data": { "kind": "constant", "value": 0.0 } }
|
| 133 |
},
|
|
|
|
| 210 |
{
|
| 211 |
"name": "mask_zeros_preserve_bias",
|
| 212 |
"inputs": {
|
| 213 |
+
"x": { "dtype": "float32", "shape": [1, 1, 2, 2], "data": { "kind": "constant", "value": 2.0 } },
|
| 214 |
"w": { "dtype": "float32", "shape": [1, 1, 1, 1], "data": { "kind": "values", "values": [7.0] } },
|
| 215 |
"offset": { "dtype": "float32", "shape": [1, 2, 2, 2], "data": { "kind": "constant", "value": 0.0 } },
|
| 216 |
"bias": { "dtype": "float32", "shape": [1], "data": { "kind": "values", "values": [0.5] } },
|
|
|
|
| 787 |
"offset": {
|
| 788 |
"dtype": "float32",
|
| 789 |
"shape": [1, 2, 2, 2],
|
| 790 |
+
"data": { "kind": "values", "values": [2.0, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] }
|
| 791 |
}
|
| 792 |
},
|
| 793 |
"outputs": {
|
|
|
|
| 795 |
"dtype": "float32",
|
| 796 |
"shape": [1, 1, 2, 2],
|
| 797 |
"tolerance": 0,
|
| 798 |
+
"data": { "kind": "values", "values": [0.0, 0.0, 3.0, 4.0] }
|
| 799 |
}
|
| 800 |
}
|
| 801 |
},
|