<!-- Thank you for filing a bug report! 🐛 --> ### Expected Behaviour I should be able to use workgroups in compute shaders. <!-- Please describe what you expected to happen. --> ### Example & Steps To Reproduce <!-- Describe what actually happened, including any relevant examples (smaller the better), error messages, or the relevant SPIR-V binary. --> This is the most simplified example I could make to reproduce. ```rust #[spirv(compute(threads(256)))] pub fn test( #[spirv(local_invocation_id)] lid: UVec3, #[spirv(workgroup_id)] gid: UVec3, #[spirv(workgroup)] shared: &mut [u32; 32], #[spirv(push_constant)] pc: &PushConstants, #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] all_bufs: &mut RuntimeArray< TypedBuffer<[u32]>, >, ) { shared[0] = 1; shared[1] = 2; let a = Vec2::new(shared[0] as f32, shared[1] as f32); } ``` produces this runtime Vulkan error: ``` vkCreateShaderModule(): pCreateInfo->pCode (spirv-val produced an error): Invalid explicit layout decorations on type for operand '17[%17]' %shared = OpVariable %_ptr_Workgroup__arr_uint_uint_32 Workgroup The Vulkan spec states: All variables must have valid explicit layout decorations as described in Shader Interfaces (https://vulkan.lunarg.com/doc/view/1.4.313.0/mac/antora/spec/latest/appendices/spirvenv.html#VUID-StandaloneSpirv-None-10684) ``` spir-v snippet: ``` OpCapability Shader OpCapability Int64 OpCapability StorageImageExtendedFormats OpCapability ImageQuery OpCapability StorageImageWriteWithoutFormat OpCapability RuntimeDescriptorArray OpExtension "SPV_EXT_descriptor_indexing" OpExtension "SPV_KHR_storage_buffer_storage_class" OpMemoryModel Logical GLSL450 OpEntryPoint GLCompute %1 "test" %lid %gid OpExecutionMode %1 LocalSize 256 1 1 OpName %lid "lid" OpName %gid "gid" OpName %shared "shared" OpDecorate %lid BuiltIn LocalInvocationId OpDecorate %gid BuiltIn WorkgroupId OpDecorate %_arr_uint_uint_32 ArrayStride 4 %void = OpTypeVoid %8 = OpTypeFunction %void %uint = OpTypeInt 32 0 %uint_0 = OpConstant %uint 0 %uint_1 = OpConstant %uint 1 %bool = OpTypeBool %v3uint = OpTypeVector %uint 3 %_ptr_Input_v3uint = OpTypePointer Input %v3uint %uint_32 = OpConstant %uint 32 %lid = OpVariable %_ptr_Input_v3uint Input %gid = OpVariable %_ptr_Input_v3uint Input %_ptr_Workgroup_uint = OpTypePointer Workgroup %uint %_arr_uint_uint_32 = OpTypeArray %uint %uint_32 %_ptr_Workgroup__arr_uint_uint_32 = OpTypePointer Workgroup %_arr_uint_uint_32 %shared = OpVariable %_ptr_Workgroup__arr_uint_uint_32 Workgroup %1 = OpFunction %void None %8 %18 = OpLabel OpLine %4 209 8 %19 = OpLoad %v3uint %lid OpLine %4 210 8 %20 = OpLoad %v3uint %gid OpLine %4 217 8 %21 = OpULessThan %bool %uint_0 %uint_32 OpNoLine OpSelectionMerge %22 None OpBranchConditional %21 %23 %24 %23 = OpLabel OpBranch %22 %24 = OpLabel OpReturn %22 = OpLabel OpLine %4 217 8 %25 = OpInBoundsAccessChain %_ptr_Workgroup_uint %shared %uint_0 OpStore %25 %uint_1 OpLine %4 218 26 %26 = OpULessThan %bool %uint_0 %uint_32 OpNoLine OpSelectionMerge %27 None OpBranchConditional %26 %28 %29 %28 = OpLabel OpBranch %27 %29 = OpLabel OpReturn %27 = OpLabel OpLine %4 218 26 %30 = OpInBoundsAccessChain %_ptr_Workgroup_uint %shared %uint_0 %31 = OpLoad %uint %30 OpLine %4 218 44 %32 = OpULessThan %bool %uint_1 %uint_32 OpNoLine OpSelectionMerge %33 None OpBranchConditional %32 %34 %35 %34 = OpLabel OpBranch %33 %35 = OpLabel OpReturn %33 = OpLabel OpLine %4 218 44 %36 = OpInBoundsAccessChain %_ptr_Workgroup_uint %shared %uint_1 %37 = OpLoad %uint %36 OpNoLine OpReturn OpFunctionEnd ``` ## System Info <!-- Helpful commands: - Rustc version: `rustc -V` - SPIR-V version: `spirv-val --version` --> - Rust: nightly-2024-11-22 - OS: MacOS 15.5 - GPU: Apple M1 (Integrated GPU) with Vulkan 1.2.296 - SPIR-V: SPIRV-Tools v2025.2 v2025.2.rc2-0-ga62abcb4 - Vulkan Loader version: 1.4.313 - rust-gpu: commit: 86fc48032c4cd4afb74f1d81ae859711d20386a1