|
1 | | -//! Symbols to query SPIR-V read-only global built-ins |
| 1 | +//! Query SPIR-V read-only global built-in values |
| 2 | +//! |
| 3 | +//! Reference links: |
| 4 | +//! * [WGSL specification describing these builtins](https://www.w3.org/TR/WGSL/#builtin-inputs-outputs) |
| 5 | +//! * [SPIR-V specification for builtins](https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#_builtin) |
| 6 | +//! * [GLSL 4.x reference](https://registry.khronos.org/OpenGL-Refpages/gl4/) |
2 | 7 |
|
3 | | -/// compute shader built-ins |
| 8 | +#[cfg(target_arch = "spirv")] |
| 9 | +macro_rules! load_builtin { |
| 10 | + ($ty:ty, $name:ident) => { |
| 11 | + unsafe { |
| 12 | + let mut result = <$ty>::default(); |
| 13 | + asm! { |
| 14 | + "%builtin = OpVariable typeof{result_ref} Input", |
| 15 | + concat!("OpDecorate %builtin BuiltIn ", stringify!($name)), |
| 16 | + "%result = OpLoad typeof*{result_ref} %builtin", |
| 17 | + "OpStore {result_ref} %result", |
| 18 | + result_ref = in(reg) &mut result, |
| 19 | + } |
| 20 | + result |
| 21 | + } |
| 22 | + }; |
| 23 | +} |
| 24 | + |
| 25 | +/// Compute shader built-ins |
4 | 26 | pub mod compute { |
5 | 27 | #[cfg(target_arch = "spirv")] |
6 | 28 | use core::arch::asm; |
7 | 29 | use glam::UVec3; |
8 | 30 |
|
9 | | - /// GLSL: `gl_LocalInvocationID()` |
| 31 | + // Local builtins (for this invocation's position in the workgroup). |
| 32 | + |
| 33 | + /// The current invocation’s local invocation ID, |
| 34 | + /// i.e. its position in the workgroup grid. |
| 35 | + /// |
| 36 | + /// GLSL: `gl_LocalInvocationID` |
10 | 37 | /// WGSL: `local_invocation_id` |
11 | 38 | #[doc(alias = "gl_LocalInvocationID")] |
12 | 39 | #[inline] |
13 | 40 | #[gpu_only] |
14 | 41 | pub fn local_invocation_id() -> UVec3 { |
15 | | - unsafe { |
16 | | - let result = UVec3::default(); |
17 | | - asm! { |
18 | | - "%builtin = OpVariable typeof{result} Input", |
19 | | - "OpDecorate %builtin BuiltIn LocalInvocationId", |
20 | | - "%result = OpLoad typeof*{result} %builtin", |
21 | | - "OpStore {result} %result", |
22 | | - result = in(reg) &result, |
23 | | - } |
24 | | - result |
25 | | - } |
| 42 | + load_builtin!(UVec3, LocalInvocationId) |
| 43 | + } |
| 44 | + |
| 45 | + /// The current invocation’s local invocation index, |
| 46 | + /// a linearized index of the invocation’s position within the workgroup grid. |
| 47 | + /// |
| 48 | + /// GLSL: `gl_LocalInvocationIndex` |
| 49 | + /// WGSL: `local_invocation_index` |
| 50 | + #[doc(alias = "gl_LocalInvocationIndex")] |
| 51 | + #[inline] |
| 52 | + #[gpu_only] |
| 53 | + pub fn local_invocation_index() -> u32 { |
| 54 | + load_builtin!(u32, LocalInvocationIndex) |
| 55 | + } |
| 56 | + |
| 57 | + // Global builtins, for this invocation's position in the compute grid. |
| 58 | + |
| 59 | + /// The current invocation’s global invocation ID, |
| 60 | + /// i.e. its position in the compute shader grid. |
| 61 | + /// |
| 62 | + /// GLSL: `gl_GlobalInvocationID` |
| 63 | + /// WGSL: `global_invocation_id` |
| 64 | + #[doc(alias = "gl_GlobalInvocationID")] |
| 65 | + #[inline] |
| 66 | + #[gpu_only] |
| 67 | + pub fn global_invocation_id() -> UVec3 { |
| 68 | + load_builtin!(UVec3, GlobalInvocationId) |
| 69 | + } |
| 70 | + |
| 71 | + // Subgroup builtins |
| 72 | + |
| 73 | + /// The number of subgroups in the current invocation’s workgroup. |
| 74 | + /// |
| 75 | + /// WGSL: `num_subgroups` |
| 76 | + /// No equivalent in GLSL. |
| 77 | + #[inline] |
| 78 | + #[gpu_only] |
| 79 | + pub fn num_subgroups() -> u32 { |
| 80 | + load_builtin!(u32, NumSubgroups) |
| 81 | + } |
| 82 | + |
| 83 | + /// The subgroup ID of current invocation’s subgroup within the workgroup. |
| 84 | + /// |
| 85 | + /// WGSL: `subgroup_id` |
| 86 | + /// No equivalent in GLSL. |
| 87 | + #[inline] |
| 88 | + #[gpu_only] |
| 89 | + pub fn subgroup_id() -> u32 { |
| 90 | + load_builtin!(u32, SubgroupId) |
| 91 | + } |
| 92 | + |
| 93 | + /// This invocation's ID within its subgroup. |
| 94 | + /// |
| 95 | + /// WGSL: `subgroup_invocation_id` |
| 96 | + /// No equivalent in GLSL. |
| 97 | + #[doc(alias = "subgroup_invocation_id")] |
| 98 | + #[inline] |
| 99 | + #[gpu_only] |
| 100 | + pub fn subgroup_local_invocation_id() -> u32 { |
| 101 | + load_builtin!(u32, SubgroupLocalInvocationId) |
| 102 | + } |
| 103 | + |
| 104 | + /// The subgroup size of current invocation’s subgroup. |
| 105 | + /// |
| 106 | + /// WGSL: `subgroup_size` |
| 107 | + /// No equivalent in GLSL. |
| 108 | + #[inline] |
| 109 | + #[gpu_only] |
| 110 | + pub fn subgroup_size() -> u32 { |
| 111 | + load_builtin!(u32, SubgroupSize) |
| 112 | + } |
| 113 | + |
| 114 | + // Workgroup builtins |
| 115 | + |
| 116 | + /// The number of workgroups that have been dispatched in the compute shader grid. |
| 117 | + /// |
| 118 | + /// GLSL: `gl_NumWorkGroups` |
| 119 | + /// WGSL: `num_workgroups` |
| 120 | + #[doc(alias = "gl_WorkGroupID")] |
| 121 | + #[inline] |
| 122 | + #[gpu_only] |
| 123 | + pub fn num_workgroups() -> UVec3 { |
| 124 | + load_builtin!(UVec3, NumWorkgroups) |
| 125 | + } |
| 126 | + |
| 127 | + /// The current invocation’s workgroup ID, |
| 128 | + /// i.e. the position of the workgroup in the overall compute shader grid. |
| 129 | + /// |
| 130 | + /// GLSL: `gl_WorkGroupID` |
| 131 | + /// WGSL: `workgroup_id` |
| 132 | + #[doc(alias = "gl_WorkGroupID")] |
| 133 | + #[inline] |
| 134 | + #[gpu_only] |
| 135 | + pub fn workgroup_id() -> UVec3 { |
| 136 | + load_builtin!(UVec3, WorkgroupId) |
26 | 137 | } |
27 | 138 | } |
0 commit comments