| { |
| "domain": "ai.onnx", |
| "name": "BitShift", |
| "sinceVersion": 11, |
| "description": "Performs an elementwise bitwise shift on unsigned integer tensors. `X` is shifted left or right by the amounts in `Y`, with the direction controlled by the `direction` attribute. Supports multidirectional (NumPy-style) broadcasting between `X` and `Y`.", |
| "inputs": [ |
| { "role": "X", "dtype": "T", "description": "Input tensor to be shifted." }, |
| { |
| "role": "Y", |
| "dtype": "T", |
| "description": "Tensor specifying the number of bit positions to shift each element of X." |
| } |
| ], |
| "outputs": [ |
| { |
| "role": "Z", |
| "dtype": "T", |
| "rank": "max(ranks.X, ranks.Y)", |
| "description": "Output tensor with the same shape as the broadcast result of X and Y.", |
| "shape": "broadcastShape(shapes.X, shapes.Y)" |
| } |
| ], |
| "attributes": {}, |
| "attributeDescriptions": { |
| "direction": "Direction of the bit shift: `LEFT` shifts bits toward higher significance (increasing value), while `RIGHT` shifts toward lower significance (decreasing value)." |
| }, |
| "attributeConstraints": { "direction": { "required": true, "values": ["LEFT", "RIGHT"] } }, |
| "typeConstraints": { "T": ["uint32", "uint8"] }, |
| "args": { |
| "x": { "kind": "tensor", "semantic": "X", "role": "input" }, |
| "y": { "kind": "tensor", "semantic": "Y", "role": "input" }, |
| "z": { "kind": "tensor", "semantic": "Z", "role": "output" } |
| }, |
| "tunables": { "WORKGROUP_SIZE": 256 }, |
| "derive": {}, |
| "constants": { |
| "leftShift": "attrs.direction == \"LEFT\"", |
| "logicalDtype": "tensorDtypes.Z", |
| "bitWidth": "8 if tensorDtypes.Z == \"uint8\" else 32" |
| }, |
| "variants": [ |
| { |
| "id": "same_shape_vec4", |
| "priority": 20, |
| "when": ["sameShape(shapes.X, shapes.Z)", "sameShape(shapes.Y, shapes.Z)", "numel(shapes.Z) > 0", "numel(shapes.Z) % 4 == 0"], |
| "constants": { "vectorScalar": "\"vec4<\" ~ dtypes.T ~ \">\"" }, |
| "passes": [ |
| { |
| "id": "main", |
| "name": "BitShift.vec4", |
| "source": { "shader": "bitshift-vec4.wgsl.jinja", "inputs": {} }, |
| "bindings": [ |
| { |
| "name": "x", |
| "arg": "x", |
| "semantic": "X", |
| "buffer": { "type": "read-only-storage" }, |
| "elementType": "$vectorScalar" |
| }, |
| { |
| "name": "shift", |
| "arg": "y", |
| "semantic": "Y", |
| "buffer": { "type": "read-only-storage" }, |
| "elementType": "$vectorScalar" |
| }, |
| { |
| "name": "z", |
| "arg": "z", |
| "semantic": "Z", |
| "buffer": { "type": "storage" }, |
| "elementType": "$vectorScalar" |
| }, |
| { |
| "name": "params", |
| "semantic": "kernel.params", |
| "buffer": { "type": "uniform" }, |
| "struct": { |
| "name": "Params", |
| "fields": [{ "name": "count", "type": "u32", "value": "numel(shapes.Z) / 4" }] |
| } |
| } |
| ], |
| "dispatch": { "threads": "numel(shapes.Z) / 4", "workgroupSize": "tunables.WORKGROUP_SIZE" } |
| } |
| ] |
| }, |
| { |
| "id": "broadcast", |
| "when": ["ranks.X >= 0", "ranks.Y >= 0", "ranks.Z >= 0", "ranks.X <= ranks.Z", "ranks.Y <= ranks.Z"], |
| "passes": [ |
| { |
| "id": "main", |
| "name": "BitShift", |
| "source": { |
| "shader": "bitshift.wgsl.jinja", |
| "inputs": { |
| "xShape": "shapes.X", |
| "yShape": "shapes.Y", |
| "zShape": "shapes.Z", |
| "xRank": "ranks.X", |
| "yRank": "ranks.Y", |
| "zRank": "ranks.Z" |
| } |
| }, |
| "bindings": [ |
| { "name": "x", "arg": "x", "semantic": "X", "buffer": { "type": "read-only-storage" }, "elementType": "$T" }, |
| { |
| "name": "shift", |
| "arg": "y", |
| "semantic": "Y", |
| "buffer": { "type": "read-only-storage" }, |
| "elementType": "$T" |
| }, |
| { "name": "z", "arg": "z", "semantic": "Z", "buffer": { "type": "storage" }, "elementType": "$T" }, |
| { |
| "name": "params", |
| "semantic": "kernel.params", |
| "buffer": { "type": "uniform" }, |
| "struct": { "name": "Params", "fields": [{ "name": "count", "type": "u32", "value": "numel(shapes.Z)" }] } |
| } |
| ], |
| "dispatch": { "threads": "numel(shapes.Z)", "workgroupSize": "tunables.WORKGROUP_SIZE" } |
| } |
| ] |
| } |
| ] |
| } |
|
|