From 4bfbf62794a037533a6d856184a93d499306508c Mon Sep 17 00:00:00 2001 From: Caio Marcelo de Oliveira Filho Date: Tue, 2 Jun 2020 16:58:51 -0700 Subject: [PATCH] Add support for GL_EXT_shared_memory_block Uses SPV_KHR_workgroup_memory_explicit_layout. Note that if GL_EXT_scalar_block_layout is enabled, Workgroup blocks can also use scalar layout. --- SPIRV/GLSL.ext.KHR.h | 1 + SPIRV/GlslangToSpv.cpp | 17 ++++ SPIRV/SpvPostProcess.cpp | 25 ++++++ SPIRV/SpvTools.cpp | 1 + SPIRV/doc.cpp | 4 + Test/baseResults/310.comp.out | 2 +- Test/baseResults/400.frag.out | 2 +- Test/baseResults/430.comp.out | 2 +- ...pMemoryExplicitLayout.16BitAccess.comp.out | 54 ++++++++++++ ...upMemoryExplicitLayout.8BitAccess.comp.out | 45 ++++++++++ ...citLayout.MixBlockNonBlock_Errors.comp.out | 4 + ...upMemoryExplicitLayout.MultiBlock.comp.out | 54 ++++++++++++ ...roupMemoryExplicitLayout.NonBlock.comp.out | 35 ++++++++ ...pMemoryExplicitLayout.SingleBlock.comp.out | 41 +++++++++ ...kgroupMemoryExplicitLayout.scalar.comp.out | 84 +++++++++++++++++++ ...kgroupMemoryExplicitLayout.std140.comp.out | 83 ++++++++++++++++++ ...kgroupMemoryExplicitLayout.std430.comp.out | 83 ++++++++++++++++++ ...groupMemoryExplicitLayout.16BitAccess.comp | 18 ++++ ...kgroupMemoryExplicitLayout.8BitAccess.comp | 16 ++++ ...xplicitLayout.MixBlockNonBlock_Errors.comp | 20 +++++ ...kgroupMemoryExplicitLayout.MultiBlock.comp | 21 +++++ ...orkgroupMemoryExplicitLayout.NonBlock.comp | 14 ++++ ...groupMemoryExplicitLayout.SingleBlock.comp | 15 ++++ ....WorkgroupMemoryExplicitLayout.scalar.comp | 39 +++++++++ ....WorkgroupMemoryExplicitLayout.std140.comp | 35 ++++++++ ....WorkgroupMemoryExplicitLayout.std430.comp | 35 ++++++++ glslang/MachineIndependent/ParseHelper.cpp | 43 ++++++++-- glslang/MachineIndependent/ParseHelper.h | 1 + glslang/MachineIndependent/Versions.cpp | 2 + glslang/MachineIndependent/Versions.h | 1 + glslang/MachineIndependent/linkValidate.cpp | 21 +++++ .../MachineIndependent/localintermediate.h | 1 + gtests/Spv.FromFile.cpp | 11 +++ 33 files changed, 822 insertions(+), 8 deletions(-) create mode 100644 Test/baseResults/spv.WorkgroupMemoryExplicitLayout.16BitAccess.comp.out create mode 100644 Test/baseResults/spv.WorkgroupMemoryExplicitLayout.8BitAccess.comp.out create mode 100644 Test/baseResults/spv.WorkgroupMemoryExplicitLayout.MixBlockNonBlock_Errors.comp.out create mode 100644 Test/baseResults/spv.WorkgroupMemoryExplicitLayout.MultiBlock.comp.out create mode 100644 Test/baseResults/spv.WorkgroupMemoryExplicitLayout.NonBlock.comp.out create mode 100644 Test/baseResults/spv.WorkgroupMemoryExplicitLayout.SingleBlock.comp.out create mode 100644 Test/baseResults/spv.WorkgroupMemoryExplicitLayout.scalar.comp.out create mode 100644 Test/baseResults/spv.WorkgroupMemoryExplicitLayout.std140.comp.out create mode 100644 Test/baseResults/spv.WorkgroupMemoryExplicitLayout.std430.comp.out create mode 100644 Test/spv.WorkgroupMemoryExplicitLayout.16BitAccess.comp create mode 100644 Test/spv.WorkgroupMemoryExplicitLayout.8BitAccess.comp create mode 100644 Test/spv.WorkgroupMemoryExplicitLayout.MixBlockNonBlock_Errors.comp create mode 100644 Test/spv.WorkgroupMemoryExplicitLayout.MultiBlock.comp create mode 100644 Test/spv.WorkgroupMemoryExplicitLayout.NonBlock.comp create mode 100644 Test/spv.WorkgroupMemoryExplicitLayout.SingleBlock.comp create mode 100644 Test/spv.WorkgroupMemoryExplicitLayout.scalar.comp create mode 100644 Test/spv.WorkgroupMemoryExplicitLayout.std140.comp create mode 100644 Test/spv.WorkgroupMemoryExplicitLayout.std430.comp diff --git a/SPIRV/GLSL.ext.KHR.h b/SPIRV/GLSL.ext.KHR.h index 9610c6ee..175fa8d5 100644 --- a/SPIRV/GLSL.ext.KHR.h +++ b/SPIRV/GLSL.ext.KHR.h @@ -50,5 +50,6 @@ static const char* const E_SPV_KHR_ray_tracing = "SPV_KHR_ray_t static const char* const E_SPV_KHR_ray_query = "SPV_KHR_ray_query"; static const char* const E_SPV_KHR_fragment_shading_rate = "SPV_KHR_fragment_shading_rate"; static const char* const E_SPV_KHR_terminate_invocation = "SPV_KHR_terminate_invocation"; +static const char* const E_SPV_KHR_workgroup_memory_explicit_layout = "SPV_KHR_workgroup_memory_explicit_layout"; #endif // #ifndef GLSLextKHR_H diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp index 49baf978..5ad2d333 100644 --- a/SPIRV/GlslangToSpv.cpp +++ b/SPIRV/GlslangToSpv.cpp @@ -380,6 +380,7 @@ spv::Decoration TranslateBlockDecoration(const glslang::TType& type, bool useSto case glslang::EvqBuffer: return useStorageBuffer ? spv::DecorationBlock : spv::DecorationBufferBlock; case glslang::EvqVaryingIn: return spv::DecorationBlock; case glslang::EvqVaryingOut: return spv::DecorationBlock; + case glslang::EvqShared: return spv::DecorationBlock; #ifndef GLSLANG_WEB case glslang::EvqPayload: return spv::DecorationBlock; case glslang::EvqPayloadIn: return spv::DecorationBlock; @@ -436,6 +437,7 @@ spv::Decoration TranslateLayoutDecoration(const glslang::TType& type, glslang::T break; case glslang::EbtBlock: switch (type.getQualifier().storage) { + case glslang::EvqShared: case glslang::EvqUniform: case glslang::EvqBuffer: switch (type.getQualifier().layoutPacking) { @@ -1278,6 +1280,12 @@ spv::StorageClass TGlslangToSpvTraverser::TranslateStorageClass(const glslang::T return spv::StorageClassUniformConstant; } + if (type.getQualifier().storage == glslang::EvqShared && type.getBasicType() == glslang::EbtBlock) { + builder.addExtension(spv::E_SPV_KHR_workgroup_memory_explicit_layout); + builder.addCapability(spv::CapabilityWorkgroupMemoryExplicitLayoutKHR); + return spv::StorageClassWorkgroup; + } + switch (type.getQualifier().storage) { case glslang::EvqGlobal: return spv::StorageClassPrivate; case glslang::EvqConstReadOnly: return spv::StorageClassFunction; @@ -3623,6 +3631,11 @@ spv::Id TGlslangToSpvTraverser::createSpvVariable(const glslang::TIntermSymbol* break; #endif default: + if (storageClass == spv::StorageClassWorkgroup && + node->getType().getBasicType() == glslang::EbtBlock) { + builder.addCapability(spv::CapabilityWorkgroupMemoryExplicitLayout16BitAccessKHR); + break; + } if (node->getType().contains16BitFloat()) builder.addCapability(spv::CapabilityFloat16); if (node->getType().contains16BitInt()) @@ -3641,6 +3654,9 @@ spv::Id TGlslangToSpvTraverser::createSpvVariable(const glslang::TIntermSymbol* } else if (storageClass == spv::StorageClassStorageBuffer) { builder.addIncorporatedExtension(spv::E_SPV_KHR_8bit_storage, spv::Spv_1_5); builder.addCapability(spv::CapabilityStorageBuffer8BitAccess); + } else if (storageClass == spv::StorageClassWorkgroup && + node->getType().getBasicType() == glslang::EbtBlock) { + builder.addCapability(spv::CapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR); } else { builder.addCapability(spv::CapabilityInt8); } @@ -4407,6 +4423,7 @@ glslang::TLayoutPacking TGlslangToSpvTraverser::getExplicitLayout(const glslang: // has to be a uniform or buffer block or task in/out blocks if (type.getQualifier().storage != glslang::EvqUniform && type.getQualifier().storage != glslang::EvqBuffer && + type.getQualifier().storage != glslang::EvqShared && !type.getQualifier().isTaskMemory()) return glslang::ElpNone; diff --git a/SPIRV/SpvPostProcess.cpp b/SPIRV/SpvPostProcess.cpp index 36d568f0..23d7b5a4 100644 --- a/SPIRV/SpvPostProcess.cpp +++ b/SPIRV/SpvPostProcess.cpp @@ -443,6 +443,31 @@ void Builder::postProcessFeatures() { memoryModel = spv::MemoryModelVulkanKHR; addIncorporatedExtension(spv::E_SPV_KHR_vulkan_memory_model, spv::Spv_1_5); } + + // Add Aliased decoration if there's more than one Workgroup Block variable. + if (capabilities.find(spv::CapabilityWorkgroupMemoryExplicitLayoutKHR) != capabilities.end()) { + assert(entryPoints.size() == 1); + auto &ep = entryPoints[0]; + + std::vector workgroup_variables; + for (int i = 0; i < (int)ep->getNumOperands(); i++) { + if (!ep->isIdOperand(i)) + continue; + + const Id id = ep->getIdOperand(i); + const Instruction *instr = module.getInstruction(id); + if (instr->getOpCode() != spv::OpVariable) + continue; + + if (instr->getImmediateOperand(0) == spv::StorageClassWorkgroup) + workgroup_variables.push_back(id); + } + + if (workgroup_variables.size() > 1) { + for (size_t i = 0; i < workgroup_variables.size(); i++) + addDecoration(workgroup_variables[i], spv::DecorationAliased); + } + } } #endif diff --git a/SPIRV/SpvTools.cpp b/SPIRV/SpvTools.cpp index 56eb2484..5cfc4262 100644 --- a/SPIRV/SpvTools.cpp +++ b/SPIRV/SpvTools.cpp @@ -154,6 +154,7 @@ void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector< spvValidatorOptionsSetRelaxBlockLayout(options, intermediate.usingHlslOffsets()); spvValidatorOptionsSetBeforeHlslLegalization(options, prelegalization); spvValidatorOptionsSetScalarBlockLayout(options, intermediate.usingScalarBlockLayout()); + spvValidatorOptionsSetWorkgroupScalarBlockLayout(options, intermediate.usingScalarBlockLayout()); spvValidateWithOptions(context, options, &binary, &diagnostic); // report diff --git a/SPIRV/doc.cpp b/SPIRV/doc.cpp index 5327f221..6805c3a6 100644 --- a/SPIRV/doc.cpp +++ b/SPIRV/doc.cpp @@ -967,6 +967,10 @@ const char* CapabilityString(int info) case CapabilityAtomicFloat32AddEXT: return "AtomicFloat32AddEXT"; case CapabilityAtomicFloat64AddEXT: return "AtomicFloat64AddEXT"; + case CapabilityWorkgroupMemoryExplicitLayoutKHR: return "CapabilityWorkgroupMemoryExplicitLayoutKHR"; + case CapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR: return "CapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR"; + case CapabilityWorkgroupMemoryExplicitLayout16BitAccessKHR: return "CapabilityWorkgroupMemoryExplicitLayout16BitAccessKHR"; + default: return "Bad"; } } diff --git a/Test/baseResults/310.comp.out b/Test/baseResults/310.comp.out index 8874e20b..85b01161 100644 --- a/Test/baseResults/310.comp.out +++ b/Test/baseResults/310.comp.out @@ -7,7 +7,7 @@ ERROR: 0:39: 'in' : global storage input qualifier cannot be used in a compute s ERROR: 0:39: 'location qualifier on input' : not supported in this stage: compute ERROR: 0:40: 'in' : global storage input qualifier cannot be used in a compute shader ERROR: 0:41: 'out' : global storage output qualifier cannot be used in a compute shader -ERROR: 0:44: 'shared' : cannot apply layout qualifiers to a shared variable +ERROR: 0:44: 'shared block' : not supported for this version or the enabled extensions ERROR: 0:44: 'location' : can only apply to uniform, buffer, in, or out storage qualifiers ERROR: 0:45: 'shared' : initializer can only be a null initializer ('{}') ERROR: 0:47: 'local_size' : can only apply to 'in' diff --git a/Test/baseResults/400.frag.out b/Test/baseResults/400.frag.out index 90f73dc7..b7e88df9 100644 --- a/Test/baseResults/400.frag.out +++ b/Test/baseResults/400.frag.out @@ -34,7 +34,7 @@ ERROR: 0:183: 'assign' : cannot convert from ' const float' to ' temp 2-compone ERROR: 0:184: 'textureQueryLod' : no matching overloaded function found ERROR: 0:184: 'assign' : cannot convert from ' const float' to ' temp 2-component vector of float' ERROR: 0:197: 'subroutine' : feature not yet implemented -ERROR: 0:197: '' : default qualifier requires 'uniform', 'buffer', 'in', or 'out' storage qualification +ERROR: 0:197: '' : default qualifier requires 'uniform', 'buffer', 'in', 'out' or 'shared' storage qualification ERROR: 0:198: 'subroutine' : feature not yet implemented ERROR: 0:199: 'subroutine' : feature not yet implemented ERROR: 0:201: '' : syntax error, unexpected PRECISE, expecting IDENTIFIER diff --git a/Test/baseResults/430.comp.out b/Test/baseResults/430.comp.out index ee126a0f..4d8495bc 100644 --- a/Test/baseResults/430.comp.out +++ b/Test/baseResults/430.comp.out @@ -5,7 +5,7 @@ ERROR: 0:43: 'in' : global storage input qualifier cannot be used in a compute s ERROR: 0:43: 'location qualifier on input' : not supported in this stage: compute ERROR: 0:44: 'in' : global storage input qualifier cannot be used in a compute shader ERROR: 0:45: 'out' : global storage output qualifier cannot be used in a compute shader -ERROR: 0:48: 'shared' : cannot apply layout qualifiers to a shared variable +ERROR: 0:48: 'shared block' : not supported for this version or the enabled extensions ERROR: 0:48: 'location' : can only apply to uniform, buffer, in, or out storage qualifiers ERROR: 0:49: 'shared' : initializer can only be a null initializer ('{}') ERROR: 0:52: 'local_size' : cannot change previously set size diff --git a/Test/baseResults/spv.WorkgroupMemoryExplicitLayout.16BitAccess.comp.out b/Test/baseResults/spv.WorkgroupMemoryExplicitLayout.16BitAccess.comp.out new file mode 100644 index 00000000..31dd2dd1 --- /dev/null +++ b/Test/baseResults/spv.WorkgroupMemoryExplicitLayout.16BitAccess.comp.out @@ -0,0 +1,54 @@ +spv.WorkgroupMemoryExplicitLayout.16BitAccess.comp +// Module Version 10400 +// Generated by (magic number): 8000a +// Id's are bound by 25 + + Capability Shader + Capability Float16 + Capability Int16 + Capability CapabilityWorkgroupMemoryExplicitLayoutKHR + Capability CapabilityWorkgroupMemoryExplicitLayout16BitAccessKHR + Extension "SPV_KHR_workgroup_memory_explicit_layout" + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint GLCompute 4 "main" 10 + ExecutionMode 4 LocalSize 2 1 1 + Source GLSL 430 + SourceExtension "GL_EXT_shader_explicit_arithmetic_types" + SourceExtension "GL_EXT_shared_memory_block" + Name 4 "main" + Name 8 "first" + MemberName 8(first) 0 "a" + MemberName 8(first) 1 "f" + Name 10 "" + MemberDecorate 8(first) 0 Offset 0 + MemberDecorate 8(first) 1 Offset 2 + Decorate 8(first) Block + Decorate 24 BuiltIn WorkgroupSize + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeInt 16 1 + 7: TypeFloat 16 + 8(first): TypeStruct 6(int16_t) 7(float16_t) + 9: TypePointer Workgroup 8(first) + 10: 9(ptr) Variable Workgroup + 11: TypeInt 32 1 + 12: 11(int) Constant 0 + 13: 6(int16_t) Constant 3 + 14: TypePointer Workgroup 6(int16_t) + 16: 11(int) Constant 1 + 17:7(float16_t) Constant 18982 + 18: TypePointer Workgroup 7(float16_t) + 20: TypeInt 32 0 + 21: TypeVector 20(int) 3 + 22: 20(int) Constant 2 + 23: 20(int) Constant 1 + 24: 21(ivec3) ConstantComposite 22 23 23 + 4(main): 2 Function None 3 + 5: Label + 15: 14(ptr) AccessChain 10 12 + Store 15 13 + 19: 18(ptr) AccessChain 10 16 + Store 19 17 + Return + FunctionEnd diff --git a/Test/baseResults/spv.WorkgroupMemoryExplicitLayout.8BitAccess.comp.out b/Test/baseResults/spv.WorkgroupMemoryExplicitLayout.8BitAccess.comp.out new file mode 100644 index 00000000..3447791f --- /dev/null +++ b/Test/baseResults/spv.WorkgroupMemoryExplicitLayout.8BitAccess.comp.out @@ -0,0 +1,45 @@ +spv.WorkgroupMemoryExplicitLayout.8BitAccess.comp +// Module Version 10400 +// Generated by (magic number): 8000a +// Id's are bound by 20 + + Capability Shader + Capability Int8 + Capability CapabilityWorkgroupMemoryExplicitLayoutKHR + Capability CapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR + Extension "SPV_KHR_workgroup_memory_explicit_layout" + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint GLCompute 4 "main" 9 + ExecutionMode 4 LocalSize 2 1 1 + Source GLSL 430 + SourceExtension "GL_EXT_shader_explicit_arithmetic_types" + SourceExtension "GL_EXT_shared_memory_block" + Name 4 "main" + Name 7 "first" + MemberName 7(first) 0 "a" + Name 9 "" + MemberDecorate 7(first) 0 Offset 0 + Decorate 7(first) Block + Decorate 19 BuiltIn WorkgroupSize + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeInt 8 1 + 7(first): TypeStruct 6(int8_t) + 8: TypePointer Workgroup 7(first) + 9: 8(ptr) Variable Workgroup + 10: TypeInt 32 1 + 11: 10(int) Constant 0 + 12: 6(int8_t) Constant 2 + 13: TypePointer Workgroup 6(int8_t) + 15: TypeInt 32 0 + 16: TypeVector 15(int) 3 + 17: 15(int) Constant 2 + 18: 15(int) Constant 1 + 19: 16(ivec3) ConstantComposite 17 18 18 + 4(main): 2 Function None 3 + 5: Label + 14: 13(ptr) AccessChain 9 11 + Store 14 12 + Return + FunctionEnd diff --git a/Test/baseResults/spv.WorkgroupMemoryExplicitLayout.MixBlockNonBlock_Errors.comp.out b/Test/baseResults/spv.WorkgroupMemoryExplicitLayout.MixBlockNonBlock_Errors.comp.out new file mode 100644 index 00000000..82495d11 --- /dev/null +++ b/Test/baseResults/spv.WorkgroupMemoryExplicitLayout.MixBlockNonBlock_Errors.comp.out @@ -0,0 +1,4 @@ +spv.WorkgroupMemoryExplicitLayout.MixBlockNonBlock_Errors.comp +ERROR: Linking compute stage: cannot mix use of shared variables inside and outside blocks + +SPIR-V is not generated for failed compile or link diff --git a/Test/baseResults/spv.WorkgroupMemoryExplicitLayout.MultiBlock.comp.out b/Test/baseResults/spv.WorkgroupMemoryExplicitLayout.MultiBlock.comp.out new file mode 100644 index 00000000..b578bd3a --- /dev/null +++ b/Test/baseResults/spv.WorkgroupMemoryExplicitLayout.MultiBlock.comp.out @@ -0,0 +1,54 @@ +spv.WorkgroupMemoryExplicitLayout.MultiBlock.comp +// Module Version 10400 +// Generated by (magic number): 8000a +// Id's are bound by 24 + + Capability Shader + Capability CapabilityWorkgroupMemoryExplicitLayoutKHR + Extension "SPV_KHR_workgroup_memory_explicit_layout" + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint GLCompute 4 "main" 9 16 + ExecutionMode 4 LocalSize 8 1 1 + Source GLSL 430 + SourceExtension "GL_EXT_shared_memory_block" + Name 4 "main" + Name 7 "first" + MemberName 7(first) 0 "a" + Name 9 "" + Name 14 "second" + MemberName 14(second) 0 "b" + Name 16 "" + MemberDecorate 7(first) 0 Offset 0 + Decorate 7(first) Block + MemberDecorate 14(second) 0 Offset 0 + Decorate 14(second) Block + Decorate 23 BuiltIn WorkgroupSize + Decorate 9 Aliased + Decorate 16 Aliased + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeInt 32 1 + 7(first): TypeStruct 6(int) + 8: TypePointer Workgroup 7(first) + 9: 8(ptr) Variable Workgroup + 10: 6(int) Constant 0 + 11: 6(int) Constant 2 + 12: TypePointer Workgroup 6(int) + 14(second): TypeStruct 6(int) + 15: TypePointer Workgroup 14(second) + 16: 15(ptr) Variable Workgroup + 17: 6(int) Constant 3 + 19: TypeInt 32 0 + 20: TypeVector 19(int) 3 + 21: 19(int) Constant 8 + 22: 19(int) Constant 1 + 23: 20(ivec3) ConstantComposite 21 22 22 + 4(main): 2 Function None 3 + 5: Label + 13: 12(ptr) AccessChain 9 10 + Store 13 11 + 18: 12(ptr) AccessChain 16 10 + Store 18 17 + Return + FunctionEnd diff --git a/Test/baseResults/spv.WorkgroupMemoryExplicitLayout.NonBlock.comp.out b/Test/baseResults/spv.WorkgroupMemoryExplicitLayout.NonBlock.comp.out new file mode 100644 index 00000000..19bcff6b --- /dev/null +++ b/Test/baseResults/spv.WorkgroupMemoryExplicitLayout.NonBlock.comp.out @@ -0,0 +1,35 @@ +spv.WorkgroupMemoryExplicitLayout.NonBlock.comp +// Module Version 10400 +// Generated by (magic number): 8000a +// Id's are bound by 17 + + Capability Shader + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint GLCompute 4 "main" 8 10 + ExecutionMode 4 LocalSize 8 1 1 + Source GLSL 430 + SourceExtension "GL_EXT_shared_memory_block" + Name 4 "main" + Name 8 "a" + Name 10 "b" + Decorate 16 BuiltIn WorkgroupSize + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeInt 32 1 + 7: TypePointer Workgroup 6(int) + 8(a): 7(ptr) Variable Workgroup + 9: 6(int) Constant 2 + 10(b): 7(ptr) Variable Workgroup + 11: 6(int) Constant 3 + 12: TypeInt 32 0 + 13: TypeVector 12(int) 3 + 14: 12(int) Constant 8 + 15: 12(int) Constant 1 + 16: 13(ivec3) ConstantComposite 14 15 15 + 4(main): 2 Function None 3 + 5: Label + Store 8(a) 9 + Store 10(b) 11 + Return + FunctionEnd diff --git a/Test/baseResults/spv.WorkgroupMemoryExplicitLayout.SingleBlock.comp.out b/Test/baseResults/spv.WorkgroupMemoryExplicitLayout.SingleBlock.comp.out new file mode 100644 index 00000000..413fd2e8 --- /dev/null +++ b/Test/baseResults/spv.WorkgroupMemoryExplicitLayout.SingleBlock.comp.out @@ -0,0 +1,41 @@ +spv.WorkgroupMemoryExplicitLayout.SingleBlock.comp +// Module Version 10400 +// Generated by (magic number): 8000a +// Id's are bound by 19 + + Capability Shader + Capability CapabilityWorkgroupMemoryExplicitLayoutKHR + Extension "SPV_KHR_workgroup_memory_explicit_layout" + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint GLCompute 4 "main" 9 + ExecutionMode 4 LocalSize 8 1 1 + Source GLSL 430 + SourceExtension "GL_EXT_shared_memory_block" + Name 4 "main" + Name 7 "first" + MemberName 7(first) 0 "a" + Name 9 "" + MemberDecorate 7(first) 0 Offset 0 + Decorate 7(first) Block + Decorate 18 BuiltIn WorkgroupSize + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeInt 32 1 + 7(first): TypeStruct 6(int) + 8: TypePointer Workgroup 7(first) + 9: 8(ptr) Variable Workgroup + 10: 6(int) Constant 0 + 11: 6(int) Constant 2 + 12: TypePointer Workgroup 6(int) + 14: TypeInt 32 0 + 15: TypeVector 14(int) 3 + 16: 14(int) Constant 8 + 17: 14(int) Constant 1 + 18: 15(ivec3) ConstantComposite 16 17 17 + 4(main): 2 Function None 3 + 5: Label + 13: 12(ptr) AccessChain 9 10 + Store 13 11 + Return + FunctionEnd diff --git a/Test/baseResults/spv.WorkgroupMemoryExplicitLayout.scalar.comp.out b/Test/baseResults/spv.WorkgroupMemoryExplicitLayout.scalar.comp.out new file mode 100644 index 00000000..6a43e236 --- /dev/null +++ b/Test/baseResults/spv.WorkgroupMemoryExplicitLayout.scalar.comp.out @@ -0,0 +1,84 @@ +spv.WorkgroupMemoryExplicitLayout.scalar.comp +// Module Version 10400 +// Generated by (magic number): 8000a +// Id's are bound by 29 + + Capability Shader + Capability CapabilityWorkgroupMemoryExplicitLayoutKHR + Extension "SPV_KHR_workgroup_memory_explicit_layout" + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint GLCompute 4 "main" 28 + ExecutionMode 4 LocalSize 8 1 1 + Source GLSL 430 + SourceExtension "GL_EXT_scalar_block_layout" + SourceExtension "GL_EXT_shared_memory_block" + Name 4 "main" + Name 17 "T" + MemberName 17(T) 0 "t" + Name 24 "S" + MemberName 24(S) 0 "f" + MemberName 24(S) 1 "v2" + MemberName 24(S) 2 "v3" + MemberName 24(S) 3 "v4" + MemberName 24(S) 4 "t" + MemberName 24(S) 5 "f_array" + MemberName 24(S) 6 "v2_array" + MemberName 24(S) 7 "v3_array" + MemberName 24(S) 8 "v4_array" + MemberName 24(S) 9 "t_array" + Name 26 "Block" + MemberName 26(Block) 0 "s" + MemberName 26(Block) 1 "s_array" + Name 28 "" + Decorate 10 BuiltIn WorkgroupSize + Decorate 16 ArrayStride 4 + MemberDecorate 17(T) 0 Offset 0 + Decorate 19 ArrayStride 4 + Decorate 20 ArrayStride 8 + Decorate 21 ArrayStride 12 + Decorate 22 ArrayStride 16 + Decorate 23 ArrayStride 12 + MemberDecorate 24(S) 0 Offset 0 + MemberDecorate 24(S) 1 Offset 4 + MemberDecorate 24(S) 2 Offset 12 + MemberDecorate 24(S) 3 Offset 24 + MemberDecorate 24(S) 4 Offset 40 + MemberDecorate 24(S) 5 Offset 52 + MemberDecorate 24(S) 6 Offset 76 + MemberDecorate 24(S) 7 Offset 124 + MemberDecorate 24(S) 8 Offset 196 + MemberDecorate 24(S) 9 Offset 292 + Decorate 25 ArrayStride 364 + MemberDecorate 26(Block) 0 Offset 0 + MemberDecorate 26(Block) 1 Offset 364 + Decorate 26(Block) Block + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeInt 32 0 + 7: TypeVector 6(int) 3 + 8: 6(int) Constant 8 + 9: 6(int) Constant 1 + 10: 7(ivec3) ConstantComposite 8 9 9 + 11: TypeFloat 32 + 12: TypeVector 11(float) 2 + 13: TypeVector 11(float) 3 + 14: TypeVector 11(float) 4 + 15: 6(int) Constant 3 + 16: TypeArray 11(float) 15 + 17(T): TypeStruct 16 + 18: 6(int) Constant 6 + 19: TypeArray 11(float) 18 + 20: TypeArray 12(fvec2) 18 + 21: TypeArray 13(fvec3) 18 + 22: TypeArray 14(fvec4) 18 + 23: TypeArray 17(T) 18 + 24(S): TypeStruct 11(float) 12(fvec2) 13(fvec3) 14(fvec4) 17(T) 19 20 21 22 23 + 25: TypeArray 24(S) 18 + 26(Block): TypeStruct 24(S) 25 + 27: TypePointer Workgroup 26(Block) + 28: 27(ptr) Variable Workgroup + 4(main): 2 Function None 3 + 5: Label + Return + FunctionEnd diff --git a/Test/baseResults/spv.WorkgroupMemoryExplicitLayout.std140.comp.out b/Test/baseResults/spv.WorkgroupMemoryExplicitLayout.std140.comp.out new file mode 100644 index 00000000..df4b8aed --- /dev/null +++ b/Test/baseResults/spv.WorkgroupMemoryExplicitLayout.std140.comp.out @@ -0,0 +1,83 @@ +spv.WorkgroupMemoryExplicitLayout.std140.comp +// Module Version 10400 +// Generated by (magic number): 8000a +// Id's are bound by 29 + + Capability Shader + Capability CapabilityWorkgroupMemoryExplicitLayoutKHR + Extension "SPV_KHR_workgroup_memory_explicit_layout" + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint GLCompute 4 "main" 28 + ExecutionMode 4 LocalSize 8 1 1 + Source GLSL 430 + SourceExtension "GL_EXT_shared_memory_block" + Name 4 "main" + Name 17 "T" + MemberName 17(T) 0 "t" + Name 24 "S" + MemberName 24(S) 0 "f" + MemberName 24(S) 1 "v2" + MemberName 24(S) 2 "v3" + MemberName 24(S) 3 "v4" + MemberName 24(S) 4 "t" + MemberName 24(S) 5 "f_array" + MemberName 24(S) 6 "v2_array" + MemberName 24(S) 7 "v3_array" + MemberName 24(S) 8 "v4_array" + MemberName 24(S) 9 "t_array" + Name 26 "Block" + MemberName 26(Block) 0 "s" + MemberName 26(Block) 1 "s_array" + Name 28 "" + Decorate 10 BuiltIn WorkgroupSize + Decorate 16 ArrayStride 16 + MemberDecorate 17(T) 0 Offset 0 + Decorate 19 ArrayStride 16 + Decorate 20 ArrayStride 16 + Decorate 21 ArrayStride 16 + Decorate 22 ArrayStride 16 + Decorate 23 ArrayStride 48 + MemberDecorate 24(S) 0 Offset 0 + MemberDecorate 24(S) 1 Offset 8 + MemberDecorate 24(S) 2 Offset 16 + MemberDecorate 24(S) 3 Offset 32 + MemberDecorate 24(S) 4 Offset 48 + MemberDecorate 24(S) 5 Offset 96 + MemberDecorate 24(S) 6 Offset 192 + MemberDecorate 24(S) 7 Offset 288 + MemberDecorate 24(S) 8 Offset 384 + MemberDecorate 24(S) 9 Offset 480 + Decorate 25 ArrayStride 768 + MemberDecorate 26(Block) 0 Offset 0 + MemberDecorate 26(Block) 1 Offset 768 + Decorate 26(Block) Block + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeInt 32 0 + 7: TypeVector 6(int) 3 + 8: 6(int) Constant 8 + 9: 6(int) Constant 1 + 10: 7(ivec3) ConstantComposite 8 9 9 + 11: TypeFloat 32 + 12: TypeVector 11(float) 2 + 13: TypeVector 11(float) 3 + 14: TypeVector 11(float) 4 + 15: 6(int) Constant 3 + 16: TypeArray 11(float) 15 + 17(T): TypeStruct 16 + 18: 6(int) Constant 6 + 19: TypeArray 11(float) 18 + 20: TypeArray 12(fvec2) 18 + 21: TypeArray 13(fvec3) 18 + 22: TypeArray 14(fvec4) 18 + 23: TypeArray 17(T) 18 + 24(S): TypeStruct 11(float) 12(fvec2) 13(fvec3) 14(fvec4) 17(T) 19 20 21 22 23 + 25: TypeArray 24(S) 18 + 26(Block): TypeStruct 24(S) 25 + 27: TypePointer Workgroup 26(Block) + 28: 27(ptr) Variable Workgroup + 4(main): 2 Function None 3 + 5: Label + Return + FunctionEnd diff --git a/Test/baseResults/spv.WorkgroupMemoryExplicitLayout.std430.comp.out b/Test/baseResults/spv.WorkgroupMemoryExplicitLayout.std430.comp.out new file mode 100644 index 00000000..e782784b --- /dev/null +++ b/Test/baseResults/spv.WorkgroupMemoryExplicitLayout.std430.comp.out @@ -0,0 +1,83 @@ +spv.WorkgroupMemoryExplicitLayout.std430.comp +// Module Version 10400 +// Generated by (magic number): 8000a +// Id's are bound by 29 + + Capability Shader + Capability CapabilityWorkgroupMemoryExplicitLayoutKHR + Extension "SPV_KHR_workgroup_memory_explicit_layout" + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint GLCompute 4 "main" 28 + ExecutionMode 4 LocalSize 8 1 1 + Source GLSL 430 + SourceExtension "GL_EXT_shared_memory_block" + Name 4 "main" + Name 17 "T" + MemberName 17(T) 0 "t" + Name 24 "S" + MemberName 24(S) 0 "f" + MemberName 24(S) 1 "v2" + MemberName 24(S) 2 "v3" + MemberName 24(S) 3 "v4" + MemberName 24(S) 4 "t" + MemberName 24(S) 5 "f_array" + MemberName 24(S) 6 "v2_array" + MemberName 24(S) 7 "v3_array" + MemberName 24(S) 8 "v4_array" + MemberName 24(S) 9 "t_array" + Name 26 "Block" + MemberName 26(Block) 0 "s" + MemberName 26(Block) 1 "s_array" + Name 28 "" + Decorate 10 BuiltIn WorkgroupSize + Decorate 16 ArrayStride 4 + MemberDecorate 17(T) 0 Offset 0 + Decorate 19 ArrayStride 4 + Decorate 20 ArrayStride 8 + Decorate 21 ArrayStride 16 + Decorate 22 ArrayStride 16 + Decorate 23 ArrayStride 12 + MemberDecorate 24(S) 0 Offset 0 + MemberDecorate 24(S) 1 Offset 8 + MemberDecorate 24(S) 2 Offset 16 + MemberDecorate 24(S) 3 Offset 32 + MemberDecorate 24(S) 4 Offset 48 + MemberDecorate 24(S) 5 Offset 60 + MemberDecorate 24(S) 6 Offset 88 + MemberDecorate 24(S) 7 Offset 144 + MemberDecorate 24(S) 8 Offset 240 + MemberDecorate 24(S) 9 Offset 336 + Decorate 25 ArrayStride 416 + MemberDecorate 26(Block) 0 Offset 0 + MemberDecorate 26(Block) 1 Offset 416 + Decorate 26(Block) Block + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeInt 32 0 + 7: TypeVector 6(int) 3 + 8: 6(int) Constant 8 + 9: 6(int) Constant 1 + 10: 7(ivec3) ConstantComposite 8 9 9 + 11: TypeFloat 32 + 12: TypeVector 11(float) 2 + 13: TypeVector 11(float) 3 + 14: TypeVector 11(float) 4 + 15: 6(int) Constant 3 + 16: TypeArray 11(float) 15 + 17(T): TypeStruct 16 + 18: 6(int) Constant 6 + 19: TypeArray 11(float) 18 + 20: TypeArray 12(fvec2) 18 + 21: TypeArray 13(fvec3) 18 + 22: TypeArray 14(fvec4) 18 + 23: TypeArray 17(T) 18 + 24(S): TypeStruct 11(float) 12(fvec2) 13(fvec3) 14(fvec4) 17(T) 19 20 21 22 23 + 25: TypeArray 24(S) 18 + 26(Block): TypeStruct 24(S) 25 + 27: TypePointer Workgroup 26(Block) + 28: 27(ptr) Variable Workgroup + 4(main): 2 Function None 3 + 5: Label + Return + FunctionEnd diff --git a/Test/spv.WorkgroupMemoryExplicitLayout.16BitAccess.comp b/Test/spv.WorkgroupMemoryExplicitLayout.16BitAccess.comp new file mode 100644 index 00000000..e06555e4 --- /dev/null +++ b/Test/spv.WorkgroupMemoryExplicitLayout.16BitAccess.comp @@ -0,0 +1,18 @@ +#version 430 core + +#extension GL_EXT_shared_memory_block : enable +#extension GL_EXT_shader_explicit_arithmetic_types: enable + +layout(local_size_x = 2) in; + +shared first +{ + int16_t a; + float16_t f; +}; + +void main() +{ + a = int16_t(3); + f = float16_t(12.3); +} diff --git a/Test/spv.WorkgroupMemoryExplicitLayout.8BitAccess.comp b/Test/spv.WorkgroupMemoryExplicitLayout.8BitAccess.comp new file mode 100644 index 00000000..aaa512c2 --- /dev/null +++ b/Test/spv.WorkgroupMemoryExplicitLayout.8BitAccess.comp @@ -0,0 +1,16 @@ +#version 430 core + +#extension GL_EXT_shared_memory_block : enable +#extension GL_EXT_shader_explicit_arithmetic_types: enable + +layout(local_size_x = 2) in; + +shared first +{ + int8_t a; +}; + +void main() +{ + a = int8_t(2); +} diff --git a/Test/spv.WorkgroupMemoryExplicitLayout.MixBlockNonBlock_Errors.comp b/Test/spv.WorkgroupMemoryExplicitLayout.MixBlockNonBlock_Errors.comp new file mode 100644 index 00000000..573d0922 --- /dev/null +++ b/Test/spv.WorkgroupMemoryExplicitLayout.MixBlockNonBlock_Errors.comp @@ -0,0 +1,20 @@ +#version 430 core + +#extension GL_EXT_shared_memory_block : enable + +layout(local_size_x = 8) in; + +shared first +{ + int a; +}; + +shared int b; + +// Cannot mix shared block and shared non-block, will fail at linking. + +void main() +{ + a = 2; + b = 3; +} diff --git a/Test/spv.WorkgroupMemoryExplicitLayout.MultiBlock.comp b/Test/spv.WorkgroupMemoryExplicitLayout.MultiBlock.comp new file mode 100644 index 00000000..675a4433 --- /dev/null +++ b/Test/spv.WorkgroupMemoryExplicitLayout.MultiBlock.comp @@ -0,0 +1,21 @@ +#version 430 core + +#extension GL_EXT_shared_memory_block : enable + +layout(local_size_x = 8) in; + +shared first +{ + int a; +}; + +shared second +{ + int b; +}; + +void main() +{ + a = 2; + b = 3; +} diff --git a/Test/spv.WorkgroupMemoryExplicitLayout.NonBlock.comp b/Test/spv.WorkgroupMemoryExplicitLayout.NonBlock.comp new file mode 100644 index 00000000..38316a50 --- /dev/null +++ b/Test/spv.WorkgroupMemoryExplicitLayout.NonBlock.comp @@ -0,0 +1,14 @@ +#version 430 core + +#extension GL_EXT_shared_memory_block : enable + +layout(local_size_x = 8) in; + +shared int a; +shared int b; + +void main() +{ + a = 2; + b = 3; +} diff --git a/Test/spv.WorkgroupMemoryExplicitLayout.SingleBlock.comp b/Test/spv.WorkgroupMemoryExplicitLayout.SingleBlock.comp new file mode 100644 index 00000000..2a17c61c --- /dev/null +++ b/Test/spv.WorkgroupMemoryExplicitLayout.SingleBlock.comp @@ -0,0 +1,15 @@ +#version 430 core + +#extension GL_EXT_shared_memory_block : enable + +layout(local_size_x = 8) in; + +shared first +{ + int a; +}; + +void main() +{ + a = 2; +} diff --git a/Test/spv.WorkgroupMemoryExplicitLayout.scalar.comp b/Test/spv.WorkgroupMemoryExplicitLayout.scalar.comp new file mode 100644 index 00000000..38085b4d --- /dev/null +++ b/Test/spv.WorkgroupMemoryExplicitLayout.scalar.comp @@ -0,0 +1,39 @@ +#version 430 core + +#extension GL_EXT_scalar_block_layout : enable +#extension GL_EXT_shared_memory_block : enable + +layout(local_size_x = 8) in; + +struct T +{ + float t[3]; +}; + +struct S +{ + float f; + vec2 v2; + vec3 v3; + vec4 v4; + T t; + + float f_array[6]; + vec2 v2_array[6]; + vec3 v3_array[6]; + vec4 v4_array[6]; + T t_array[6]; +}; + +// Use a default qualifier. +layout(scalar) shared; + +shared Block +{ + S s; + S s_array[6]; +}; + +void main() +{ +} diff --git a/Test/spv.WorkgroupMemoryExplicitLayout.std140.comp b/Test/spv.WorkgroupMemoryExplicitLayout.std140.comp new file mode 100644 index 00000000..f4f2475a --- /dev/null +++ b/Test/spv.WorkgroupMemoryExplicitLayout.std140.comp @@ -0,0 +1,35 @@ +#version 430 core + +#extension GL_EXT_shared_memory_block : enable + +layout(local_size_x = 8) in; + +struct T +{ + float t[3]; +}; + +struct S +{ + float f; + vec2 v2; + vec3 v3; + vec4 v4; + T t; + + float f_array[6]; + vec2 v2_array[6]; + vec3 v3_array[6]; + vec4 v4_array[6]; + T t_array[6]; +}; + +layout(std140) shared Block +{ + S s; + S s_array[6]; +}; + +void main() +{ +} diff --git a/Test/spv.WorkgroupMemoryExplicitLayout.std430.comp b/Test/spv.WorkgroupMemoryExplicitLayout.std430.comp new file mode 100644 index 00000000..717593b6 --- /dev/null +++ b/Test/spv.WorkgroupMemoryExplicitLayout.std430.comp @@ -0,0 +1,35 @@ +#version 430 core + +#extension GL_EXT_shared_memory_block : enable + +layout(local_size_x = 8) in; + +struct T +{ + float t[3]; +}; + +struct S +{ + float f; + vec2 v2; + vec3 v3; + vec4 v4; + T t; + + float f_array[6]; + vec2 v2_array[6]; + vec3 v3_array[6]; + vec4 v4_array[6]; + T t_array[6]; +}; + +layout(std430) shared Block +{ + S s; + S s_array[6]; +}; + +void main() +{ +} diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index d4b360ce..8927b823 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -87,6 +87,10 @@ TParseContext::TParseContext(TSymbolTable& symbolTable, TIntermediate& interm, b globalInputDefaults.clear(); globalOutputDefaults.clear(); + globalSharedDefaults.clear(); + globalSharedDefaults.layoutMatrix = ElmColumnMajor; + globalSharedDefaults.layoutPacking = ElpStd430; + #ifndef GLSLANG_WEB // "Shaders in the transform // feedback capturing mode have an initial global default of @@ -6033,12 +6037,28 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type) } } +static bool storageCanHaveLayoutInBlock(const enum TStorageQualifier storage) +{ + switch (storage) { + case EvqUniform: + case EvqBuffer: + case EvqShared: + return true; + default: + return false; + } +} + // Do layout error checking that can be done within a layout qualifier proper, not needing to know // if there are blocks, atomic counters, variables, etc. void TParseContext::layoutQualifierCheck(const TSourceLoc& loc, const TQualifier& qualifier) { - if (qualifier.storage == EvqShared && qualifier.hasLayout()) - error(loc, "cannot apply layout qualifiers to a shared variable", "shared", ""); + if (qualifier.storage == EvqShared && qualifier.hasLayout()) { + if (spvVersion.spv > 0 && spvVersion.spv < EShTargetSpv_1_4) { + error(loc, "shared block requires at least SPIR-V 1.4", "shared block", ""); + } + profileRequires(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, 0, E_GL_EXT_shared_memory_block, "shared block"); + } // "It is a compile-time error to use *component* without also specifying the location qualifier (order does not matter)." if (qualifier.hasComponent() && ! qualifier.hasLocation()) @@ -6121,7 +6141,7 @@ void TParseContext::layoutQualifierCheck(const TSourceLoc& loc, const TQualifier error(loc, "can only be used on an output", "xfb layout qualifier", ""); } if (qualifier.hasUniformLayout()) { - if (! qualifier.isUniformOrBuffer() && !qualifier.isTaskMemory()) { + if (!storageCanHaveLayoutInBlock(qualifier.storage) && !qualifier.isTaskMemory()) { if (qualifier.hasMatrix() || qualifier.hasPacking()) error(loc, "matrix or packing qualifiers can only be used on a uniform or buffer", "layout", ""); if (qualifier.hasOffset() || qualifier.hasAlign()) @@ -7667,6 +7687,7 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con case EvqBuffer: defaultQualification = globalBufferDefaults; break; case EvqVaryingIn: defaultQualification = globalInputDefaults; break; case EvqVaryingOut: defaultQualification = globalOutputDefaults; break; + case EvqShared: defaultQualification = globalSharedDefaults; break; default: defaultQualification.clear(); break; } @@ -7930,6 +7951,12 @@ void TParseContext::blockStageIoCheck(const TSourceLoc& loc, const TQualifier& q error(loc, "output blocks cannot be used in a task shader", "out", ""); } break; + case EvqShared: + if (spvVersion.spv > 0 && spvVersion.spv < EShTargetSpv_1_4) { + error(loc, "shared block requires at least SPIR-V 1.4", "shared block", ""); + } + profileRequires(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, 0, E_GL_EXT_shared_memory_block, "shared block"); + break; #ifndef GLSLANG_WEB case EvqPayload: profileRequires(loc, ~EEsProfile, 460, 2, extsrt, "rayPayloadNV block"); @@ -8088,7 +8115,7 @@ void TParseContext::fixXfbOffsets(TQualifier& qualifier, TTypeList& typeList) // void TParseContext::fixBlockUniformOffsets(TQualifier& qualifier, TTypeList& typeList) { - if (!qualifier.isUniformOrBuffer() && !qualifier.isTaskMemory()) + if (!storageCanHaveLayoutInBlock(qualifier.storage) && !qualifier.isTaskMemory()) return; if (qualifier.layoutPacking != ElpStd140 && qualifier.layoutPacking != ElpStd430 && qualifier.layoutPacking != ElpScalar) return; @@ -8602,8 +8629,14 @@ void TParseContext::updateStandaloneQualifierDefaults(const TSourceLoc& loc, con } #endif break; + case EvqShared: + if (qualifier.hasMatrix()) + globalSharedDefaults.layoutMatrix = qualifier.layoutMatrix; + if (qualifier.hasPacking()) + globalSharedDefaults.layoutPacking = qualifier.layoutPacking; + break; default: - error(loc, "default qualifier requires 'uniform', 'buffer', 'in', or 'out' storage qualification", "", ""); + error(loc, "default qualifier requires 'uniform', 'buffer', 'in', 'out' or 'shared' storage qualification", "", ""); return; } diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h index fe2b6fbb..4093fbfe 100644 --- a/glslang/MachineIndependent/ParseHelper.h +++ b/glslang/MachineIndependent/ParseHelper.h @@ -485,6 +485,7 @@ protected: TQualifier globalUniformDefaults; TQualifier globalInputDefaults; TQualifier globalOutputDefaults; + TQualifier globalSharedDefaults; TString currentCaller; // name of last function body entered (not valid when at global scope) #ifndef GLSLANG_WEB int* atomicUintOffsets; // to become an array of the right size to hold an offset per binding point diff --git a/glslang/MachineIndependent/Versions.cpp b/glslang/MachineIndependent/Versions.cpp index 517ff9f8..488c98c5 100644 --- a/glslang/MachineIndependent/Versions.cpp +++ b/glslang/MachineIndependent/Versions.cpp @@ -331,6 +331,7 @@ void TParseVersions::initializeExtensionBehavior() extensionBehavior[E_GL_EXT_fragment_shading_rate] = EBhDisable; extensionBehavior[E_GL_EXT_shader_image_int64] = EBhDisable; extensionBehavior[E_GL_EXT_terminate_invocation] = EBhDisable; + extensionBehavior[E_GL_EXT_shared_memory_block] = EBhDisable; // OVR extensions extensionBehavior[E_GL_OVR_multiview] = EBhDisable; @@ -472,6 +473,7 @@ void TParseVersions::getPreamble(std::string& preamble) "#define GL_EXT_demote_to_helper_invocation 1\n" "#define GL_EXT_debug_printf 1\n" "#define GL_EXT_fragment_shading_rate 1\n" + "#define GL_EXT_shared_memory_block 1\n" // GL_KHR_shader_subgroup "#define GL_KHR_shader_subgroup_basic 1\n" diff --git a/glslang/MachineIndependent/Versions.h b/glslang/MachineIndependent/Versions.h index 6b5efbce..f377973a 100644 --- a/glslang/MachineIndependent/Versions.h +++ b/glslang/MachineIndependent/Versions.h @@ -202,6 +202,7 @@ const char* const E_GL_EXT_shader_implicit_conversions = "GL_EXT_shader_imp const char* const E_GL_EXT_fragment_shading_rate = "GL_EXT_fragment_shading_rate"; const char* const E_GL_EXT_shader_image_int64 = "GL_EXT_shader_image_int64"; const char* const E_GL_EXT_null_initializer = "GL_EXT_null_initializer"; +const char* const E_GL_EXT_shared_memory_block = "GL_EXT_shared_memory_block"; // Arrays of extensions for the above viewportEXTs duplications diff --git a/glslang/MachineIndependent/linkValidate.cpp b/glslang/MachineIndependent/linkValidate.cpp index 4e84adbf..2d14031c 100644 --- a/glslang/MachineIndependent/linkValidate.cpp +++ b/glslang/MachineIndependent/linkValidate.cpp @@ -653,6 +653,25 @@ void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& sy #endif } +void TIntermediate::sharedBlockCheck(TInfoSink& infoSink) +{ + bool has_shared_block = false; + bool has_shared_non_block = false; + TIntermSequence& linkObjects = findLinkerObjects()->getSequence(); + for (size_t i = 0; i < linkObjects.size(); ++i) { + const TType& type = linkObjects[i]->getAsTyped()->getType(); + const TQualifier& qualifier = type.getQualifier(); + if (qualifier.storage == glslang::EvqShared) { + if (type.getBasicType() == glslang::EbtBlock) + has_shared_block = true; + else + has_shared_non_block = true; + } + } + if (has_shared_block && has_shared_non_block) + error(infoSink, "cannot mix use of shared variables inside and outside blocks"); +} + // // Do final link-time error checking of a complete (merged) intermediate representation. // (Much error checking was done during merging). @@ -778,6 +797,7 @@ void TIntermediate::finalCheck(TInfoSink& infoSink, bool keepUncalled) error(infoSink, "post_depth_coverage requires early_fragment_tests"); break; case EShLangCompute: + sharedBlockCheck(infoSink); break; case EShLangRayGen: case EShLangIntersect: @@ -810,6 +830,7 @@ void TIntermediate::finalCheck(TInfoSink& infoSink, bool keepUncalled) case EShLangTaskNV: if (numTaskNVBlocks > 1) error(infoSink, "Only one taskNV interface block is allowed per shader"); + sharedBlockCheck(infoSink); break; default: error(infoSink, "Unknown Stage."); diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h index d581959d..84d19d45 100644 --- a/glslang/MachineIndependent/localintermediate.h +++ b/glslang/MachineIndependent/localintermediate.h @@ -954,6 +954,7 @@ protected: void checkCallGraphCycles(TInfoSink&); void checkCallGraphBodies(TInfoSink&, bool keepUncalled); void inOutLocationCheck(TInfoSink&); + void sharedBlockCheck(TInfoSink&); bool userOutputUsed() const; bool isSpecializationOperation(const TIntermOperator&) const; bool isNonuniformPropagating(TOperator) const; diff --git a/gtests/Spv.FromFile.cpp b/gtests/Spv.FromFile.cpp index 83aac827..2ee292e4 100644 --- a/gtests/Spv.FromFile.cpp +++ b/gtests/Spv.FromFile.cpp @@ -582,6 +582,17 @@ INSTANTIATE_TEST_SUITE_P( "spv.ext.World3x4.rahit", "spv.ext.AccelDecl.frag", "spv.ext.RayQueryDecl.frag", + + // SPV_KHR_workgroup_memory_explicit_layout depends on SPIR-V 1.4. + "spv.WorkgroupMemoryExplicitLayout.SingleBlock.comp", + "spv.WorkgroupMemoryExplicitLayout.MultiBlock.comp", + "spv.WorkgroupMemoryExplicitLayout.8BitAccess.comp", + "spv.WorkgroupMemoryExplicitLayout.16BitAccess.comp", + "spv.WorkgroupMemoryExplicitLayout.NonBlock.comp", + "spv.WorkgroupMemoryExplicitLayout.MixBlockNonBlock_Errors.comp", + "spv.WorkgroupMemoryExplicitLayout.std140.comp", + "spv.WorkgroupMemoryExplicitLayout.std430.comp", + "spv.WorkgroupMemoryExplicitLayout.scalar.comp", })), FileNameAsCustomTestSuffix );