|
| 1 | +/* |
| 2 | + * Copyright (c) Meta Platforms, Inc. and affiliates. |
| 3 | + * All rights reserved. |
| 4 | + * |
| 5 | + * This source code is licensed under the BSD-style license found in the |
| 6 | + * LICENSE file in the root directory of this source tree. |
| 7 | + */ |
| 8 | + |
| 9 | +#pragma once |
| 10 | + |
| 11 | +#include <cstdint> |
| 12 | + |
| 13 | +namespace executorch::backends::webgpu { |
| 14 | + |
| 15 | +// @generated from binary_op.wgsl - DO NOT EDIT. |
| 16 | +// wgsl-sha256: 496b343cef6838c8316686916a1c8fd971afc7a9abfc9abca4eb28db60611371 |
| 17 | +inline constexpr const char* kBinarySubWGSL = R"( |
| 18 | +@group(0) @binding(0) var<storage, read> input1: array<f32>; |
| 19 | +@group(0) @binding(1) var<storage, read> input2: array<f32>; |
| 20 | +@group(0) @binding(2) var<storage, read_write> output: array<f32>; |
| 21 | +
|
| 22 | +struct TensorMeta { |
| 23 | + ndim: u32, |
| 24 | + numel: u32, |
| 25 | + sizes: vec4<u32>, |
| 26 | + strides: vec4<u32>, |
| 27 | +} |
| 28 | +@group(0) @binding(3) var<uniform> out_meta: TensorMeta; |
| 29 | +@group(0) @binding(4) var<uniform> in1_meta: TensorMeta; |
| 30 | +@group(0) @binding(5) var<uniform> in2_meta: TensorMeta; |
| 31 | +
|
| 32 | +override wg_size: u32 = 64u; |
| 33 | +override alpha: f32 = 1.0; |
| 34 | +
|
| 35 | +fn op(a: f32, b: f32) -> f32 { |
| 36 | + return a - alpha * b; |
| 37 | +} |
| 38 | +
|
| 39 | +@compute @workgroup_size(wg_size, 1, 1) |
| 40 | +fn main( |
| 41 | + @builtin(global_invocation_id) gid: vec3<u32>, |
| 42 | + @builtin(num_workgroups) num_workgroups: vec3<u32>) { |
| 43 | + // 2D-folded flat index (lifts the 65535 1D-dispatch cap for large numel). |
| 44 | + let idx = gid.x + gid.y * (num_workgroups.x * wg_size); |
| 45 | + if (idx >= out_meta.numel) { |
| 46 | + return; |
| 47 | + } |
| 48 | +
|
| 49 | + var same = true; |
| 50 | + for (var d: u32 = 0u; d < out_meta.ndim; d = d + 1u) { |
| 51 | + if (in1_meta.sizes[d] != out_meta.sizes[d] || |
| 52 | + in2_meta.sizes[d] != out_meta.sizes[d]) { |
| 53 | + same = false; |
| 54 | + } |
| 55 | + } |
| 56 | + if (same) { |
| 57 | + output[idx] = op(input1[idx], input2[idx]); |
| 58 | + return; |
| 59 | + } |
| 60 | +
|
| 61 | + var rem = idx; |
| 62 | + var l1: u32 = 0u; |
| 63 | + var l2: u32 = 0u; |
| 64 | + for (var d: u32 = 0u; d < out_meta.ndim; d = d + 1u) { |
| 65 | + let coord = rem / out_meta.strides[d]; |
| 66 | + rem = rem % out_meta.strides[d]; |
| 67 | + l1 = l1 + min(coord, in1_meta.sizes[d] - 1u) * in1_meta.strides[d]; |
| 68 | + l2 = l2 + min(coord, in2_meta.sizes[d] - 1u) * in2_meta.strides[d]; |
| 69 | + } |
| 70 | + output[idx] = op(input1[l1], input2[l2]); |
| 71 | +} |
| 72 | +)"; |
| 73 | + |
| 74 | +inline constexpr uint32_t kBinarySubWorkgroupSizeX = 64; |
| 75 | +inline constexpr uint32_t kBinarySubWorkgroupSizeY = 1; |
| 76 | +inline constexpr uint32_t kBinarySubWorkgroupSizeZ = 1; |
| 77 | + |
| 78 | +} // namespace executorch::backends::webgpu |
0 commit comments