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.
This commit is contained in:
Caio Marcelo de Oliveira Filho 2020-06-02 16:58:51 -07:00
parent 3785ddd59a
commit 4bfbf62794
33 changed files with 822 additions and 8 deletions

View File

@ -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_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_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_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 #endif // #ifndef GLSLextKHR_H

View File

@ -380,6 +380,7 @@ spv::Decoration TranslateBlockDecoration(const glslang::TType& type, bool useSto
case glslang::EvqBuffer: return useStorageBuffer ? spv::DecorationBlock : spv::DecorationBufferBlock; case glslang::EvqBuffer: return useStorageBuffer ? spv::DecorationBlock : spv::DecorationBufferBlock;
case glslang::EvqVaryingIn: return spv::DecorationBlock; case glslang::EvqVaryingIn: return spv::DecorationBlock;
case glslang::EvqVaryingOut: return spv::DecorationBlock; case glslang::EvqVaryingOut: return spv::DecorationBlock;
case glslang::EvqShared: return spv::DecorationBlock;
#ifndef GLSLANG_WEB #ifndef GLSLANG_WEB
case glslang::EvqPayload: return spv::DecorationBlock; case glslang::EvqPayload: return spv::DecorationBlock;
case glslang::EvqPayloadIn: return spv::DecorationBlock; case glslang::EvqPayloadIn: return spv::DecorationBlock;
@ -436,6 +437,7 @@ spv::Decoration TranslateLayoutDecoration(const glslang::TType& type, glslang::T
break; break;
case glslang::EbtBlock: case glslang::EbtBlock:
switch (type.getQualifier().storage) { switch (type.getQualifier().storage) {
case glslang::EvqShared:
case glslang::EvqUniform: case glslang::EvqUniform:
case glslang::EvqBuffer: case glslang::EvqBuffer:
switch (type.getQualifier().layoutPacking) { switch (type.getQualifier().layoutPacking) {
@ -1278,6 +1280,12 @@ spv::StorageClass TGlslangToSpvTraverser::TranslateStorageClass(const glslang::T
return spv::StorageClassUniformConstant; 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) { switch (type.getQualifier().storage) {
case glslang::EvqGlobal: return spv::StorageClassPrivate; case glslang::EvqGlobal: return spv::StorageClassPrivate;
case glslang::EvqConstReadOnly: return spv::StorageClassFunction; case glslang::EvqConstReadOnly: return spv::StorageClassFunction;
@ -3623,6 +3631,11 @@ spv::Id TGlslangToSpvTraverser::createSpvVariable(const glslang::TIntermSymbol*
break; break;
#endif #endif
default: default:
if (storageClass == spv::StorageClassWorkgroup &&
node->getType().getBasicType() == glslang::EbtBlock) {
builder.addCapability(spv::CapabilityWorkgroupMemoryExplicitLayout16BitAccessKHR);
break;
}
if (node->getType().contains16BitFloat()) if (node->getType().contains16BitFloat())
builder.addCapability(spv::CapabilityFloat16); builder.addCapability(spv::CapabilityFloat16);
if (node->getType().contains16BitInt()) if (node->getType().contains16BitInt())
@ -3641,6 +3654,9 @@ spv::Id TGlslangToSpvTraverser::createSpvVariable(const glslang::TIntermSymbol*
} else if (storageClass == spv::StorageClassStorageBuffer) { } else if (storageClass == spv::StorageClassStorageBuffer) {
builder.addIncorporatedExtension(spv::E_SPV_KHR_8bit_storage, spv::Spv_1_5); builder.addIncorporatedExtension(spv::E_SPV_KHR_8bit_storage, spv::Spv_1_5);
builder.addCapability(spv::CapabilityStorageBuffer8BitAccess); builder.addCapability(spv::CapabilityStorageBuffer8BitAccess);
} else if (storageClass == spv::StorageClassWorkgroup &&
node->getType().getBasicType() == glslang::EbtBlock) {
builder.addCapability(spv::CapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR);
} else { } else {
builder.addCapability(spv::CapabilityInt8); 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 // has to be a uniform or buffer block or task in/out blocks
if (type.getQualifier().storage != glslang::EvqUniform && if (type.getQualifier().storage != glslang::EvqUniform &&
type.getQualifier().storage != glslang::EvqBuffer && type.getQualifier().storage != glslang::EvqBuffer &&
type.getQualifier().storage != glslang::EvqShared &&
!type.getQualifier().isTaskMemory()) !type.getQualifier().isTaskMemory())
return glslang::ElpNone; return glslang::ElpNone;

View File

@ -443,6 +443,31 @@ void Builder::postProcessFeatures() {
memoryModel = spv::MemoryModelVulkanKHR; memoryModel = spv::MemoryModelVulkanKHR;
addIncorporatedExtension(spv::E_SPV_KHR_vulkan_memory_model, spv::Spv_1_5); 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<Id> 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 #endif

View File

@ -154,6 +154,7 @@ void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector<
spvValidatorOptionsSetRelaxBlockLayout(options, intermediate.usingHlslOffsets()); spvValidatorOptionsSetRelaxBlockLayout(options, intermediate.usingHlslOffsets());
spvValidatorOptionsSetBeforeHlslLegalization(options, prelegalization); spvValidatorOptionsSetBeforeHlslLegalization(options, prelegalization);
spvValidatorOptionsSetScalarBlockLayout(options, intermediate.usingScalarBlockLayout()); spvValidatorOptionsSetScalarBlockLayout(options, intermediate.usingScalarBlockLayout());
spvValidatorOptionsSetWorkgroupScalarBlockLayout(options, intermediate.usingScalarBlockLayout());
spvValidateWithOptions(context, options, &binary, &diagnostic); spvValidateWithOptions(context, options, &binary, &diagnostic);
// report // report

View File

@ -967,6 +967,10 @@ const char* CapabilityString(int info)
case CapabilityAtomicFloat32AddEXT: return "AtomicFloat32AddEXT"; case CapabilityAtomicFloat32AddEXT: return "AtomicFloat32AddEXT";
case CapabilityAtomicFloat64AddEXT: return "AtomicFloat64AddEXT"; case CapabilityAtomicFloat64AddEXT: return "AtomicFloat64AddEXT";
case CapabilityWorkgroupMemoryExplicitLayoutKHR: return "CapabilityWorkgroupMemoryExplicitLayoutKHR";
case CapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR: return "CapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR";
case CapabilityWorkgroupMemoryExplicitLayout16BitAccessKHR: return "CapabilityWorkgroupMemoryExplicitLayout16BitAccessKHR";
default: return "Bad"; default: return "Bad";
} }
} }

View File

@ -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: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: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: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: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:45: 'shared' : initializer can only be a null initializer ('{}')
ERROR: 0:47: 'local_size' : can only apply to 'in' ERROR: 0:47: 'local_size' : can only apply to 'in'

View File

@ -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: 'textureQueryLod' : no matching overloaded function found
ERROR: 0:184: 'assign' : cannot convert from ' const float' to ' temp 2-component vector of float' 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: '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:198: 'subroutine' : feature not yet implemented
ERROR: 0:199: 'subroutine' : feature not yet implemented ERROR: 0:199: 'subroutine' : feature not yet implemented
ERROR: 0:201: '' : syntax error, unexpected PRECISE, expecting IDENTIFIER ERROR: 0:201: '' : syntax error, unexpected PRECISE, expecting IDENTIFIER

View File

@ -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: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: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: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: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:49: 'shared' : initializer can only be a null initializer ('{}')
ERROR: 0:52: 'local_size' : cannot change previously set size ERROR: 0:52: 'local_size' : cannot change previously set size

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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()
{
}

View File

@ -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()
{
}

View File

@ -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()
{
}

View File

@ -87,6 +87,10 @@ TParseContext::TParseContext(TSymbolTable& symbolTable, TIntermediate& interm, b
globalInputDefaults.clear(); globalInputDefaults.clear();
globalOutputDefaults.clear(); globalOutputDefaults.clear();
globalSharedDefaults.clear();
globalSharedDefaults.layoutMatrix = ElmColumnMajor;
globalSharedDefaults.layoutPacking = ElpStd430;
#ifndef GLSLANG_WEB #ifndef GLSLANG_WEB
// "Shaders in the transform // "Shaders in the transform
// feedback capturing mode have an initial global default of // 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 // 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. // if there are blocks, atomic counters, variables, etc.
void TParseContext::layoutQualifierCheck(const TSourceLoc& loc, const TQualifier& qualifier) void TParseContext::layoutQualifierCheck(const TSourceLoc& loc, const TQualifier& qualifier)
{ {
if (qualifier.storage == EvqShared && qualifier.hasLayout()) if (qualifier.storage == EvqShared && qualifier.hasLayout()) {
error(loc, "cannot apply layout qualifiers to a shared variable", "shared", ""); 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)." // "It is a compile-time error to use *component* without also specifying the location qualifier (order does not matter)."
if (qualifier.hasComponent() && ! qualifier.hasLocation()) 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", ""); error(loc, "can only be used on an output", "xfb layout qualifier", "");
} }
if (qualifier.hasUniformLayout()) { if (qualifier.hasUniformLayout()) {
if (! qualifier.isUniformOrBuffer() && !qualifier.isTaskMemory()) { if (!storageCanHaveLayoutInBlock(qualifier.storage) && !qualifier.isTaskMemory()) {
if (qualifier.hasMatrix() || qualifier.hasPacking()) if (qualifier.hasMatrix() || qualifier.hasPacking())
error(loc, "matrix or packing qualifiers can only be used on a uniform or buffer", "layout", ""); error(loc, "matrix or packing qualifiers can only be used on a uniform or buffer", "layout", "");
if (qualifier.hasOffset() || qualifier.hasAlign()) if (qualifier.hasOffset() || qualifier.hasAlign())
@ -7667,6 +7687,7 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con
case EvqBuffer: defaultQualification = globalBufferDefaults; break; case EvqBuffer: defaultQualification = globalBufferDefaults; break;
case EvqVaryingIn: defaultQualification = globalInputDefaults; break; case EvqVaryingIn: defaultQualification = globalInputDefaults; break;
case EvqVaryingOut: defaultQualification = globalOutputDefaults; break; case EvqVaryingOut: defaultQualification = globalOutputDefaults; break;
case EvqShared: defaultQualification = globalSharedDefaults; break;
default: defaultQualification.clear(); 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", ""); error(loc, "output blocks cannot be used in a task shader", "out", "");
} }
break; 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 #ifndef GLSLANG_WEB
case EvqPayload: case EvqPayload:
profileRequires(loc, ~EEsProfile, 460, 2, extsrt, "rayPayloadNV block"); 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) void TParseContext::fixBlockUniformOffsets(TQualifier& qualifier, TTypeList& typeList)
{ {
if (!qualifier.isUniformOrBuffer() && !qualifier.isTaskMemory()) if (!storageCanHaveLayoutInBlock(qualifier.storage) && !qualifier.isTaskMemory())
return; return;
if (qualifier.layoutPacking != ElpStd140 && qualifier.layoutPacking != ElpStd430 && qualifier.layoutPacking != ElpScalar) if (qualifier.layoutPacking != ElpStd140 && qualifier.layoutPacking != ElpStd430 && qualifier.layoutPacking != ElpScalar)
return; return;
@ -8602,8 +8629,14 @@ void TParseContext::updateStandaloneQualifierDefaults(const TSourceLoc& loc, con
} }
#endif #endif
break; break;
case EvqShared:
if (qualifier.hasMatrix())
globalSharedDefaults.layoutMatrix = qualifier.layoutMatrix;
if (qualifier.hasPacking())
globalSharedDefaults.layoutPacking = qualifier.layoutPacking;
break;
default: 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; return;
} }

View File

@ -485,6 +485,7 @@ protected:
TQualifier globalUniformDefaults; TQualifier globalUniformDefaults;
TQualifier globalInputDefaults; TQualifier globalInputDefaults;
TQualifier globalOutputDefaults; TQualifier globalOutputDefaults;
TQualifier globalSharedDefaults;
TString currentCaller; // name of last function body entered (not valid when at global scope) TString currentCaller; // name of last function body entered (not valid when at global scope)
#ifndef GLSLANG_WEB #ifndef GLSLANG_WEB
int* atomicUintOffsets; // to become an array of the right size to hold an offset per binding point int* atomicUintOffsets; // to become an array of the right size to hold an offset per binding point

View File

@ -331,6 +331,7 @@ void TParseVersions::initializeExtensionBehavior()
extensionBehavior[E_GL_EXT_fragment_shading_rate] = EBhDisable; extensionBehavior[E_GL_EXT_fragment_shading_rate] = EBhDisable;
extensionBehavior[E_GL_EXT_shader_image_int64] = EBhDisable; extensionBehavior[E_GL_EXT_shader_image_int64] = EBhDisable;
extensionBehavior[E_GL_EXT_terminate_invocation] = EBhDisable; extensionBehavior[E_GL_EXT_terminate_invocation] = EBhDisable;
extensionBehavior[E_GL_EXT_shared_memory_block] = EBhDisable;
// OVR extensions // OVR extensions
extensionBehavior[E_GL_OVR_multiview] = EBhDisable; 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_demote_to_helper_invocation 1\n"
"#define GL_EXT_debug_printf 1\n" "#define GL_EXT_debug_printf 1\n"
"#define GL_EXT_fragment_shading_rate 1\n" "#define GL_EXT_fragment_shading_rate 1\n"
"#define GL_EXT_shared_memory_block 1\n"
// GL_KHR_shader_subgroup // GL_KHR_shader_subgroup
"#define GL_KHR_shader_subgroup_basic 1\n" "#define GL_KHR_shader_subgroup_basic 1\n"

View File

@ -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_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_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_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 // Arrays of extensions for the above viewportEXTs duplications

View File

@ -653,6 +653,25 @@ void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& sy
#endif #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. // Do final link-time error checking of a complete (merged) intermediate representation.
// (Much error checking was done during merging). // (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"); error(infoSink, "post_depth_coverage requires early_fragment_tests");
break; break;
case EShLangCompute: case EShLangCompute:
sharedBlockCheck(infoSink);
break; break;
case EShLangRayGen: case EShLangRayGen:
case EShLangIntersect: case EShLangIntersect:
@ -810,6 +830,7 @@ void TIntermediate::finalCheck(TInfoSink& infoSink, bool keepUncalled)
case EShLangTaskNV: case EShLangTaskNV:
if (numTaskNVBlocks > 1) if (numTaskNVBlocks > 1)
error(infoSink, "Only one taskNV interface block is allowed per shader"); error(infoSink, "Only one taskNV interface block is allowed per shader");
sharedBlockCheck(infoSink);
break; break;
default: default:
error(infoSink, "Unknown Stage."); error(infoSink, "Unknown Stage.");

View File

@ -954,6 +954,7 @@ protected:
void checkCallGraphCycles(TInfoSink&); void checkCallGraphCycles(TInfoSink&);
void checkCallGraphBodies(TInfoSink&, bool keepUncalled); void checkCallGraphBodies(TInfoSink&, bool keepUncalled);
void inOutLocationCheck(TInfoSink&); void inOutLocationCheck(TInfoSink&);
void sharedBlockCheck(TInfoSink&);
bool userOutputUsed() const; bool userOutputUsed() const;
bool isSpecializationOperation(const TIntermOperator&) const; bool isSpecializationOperation(const TIntermOperator&) const;
bool isNonuniformPropagating(TOperator) const; bool isNonuniformPropagating(TOperator) const;

View File

@ -582,6 +582,17 @@ INSTANTIATE_TEST_SUITE_P(
"spv.ext.World3x4.rahit", "spv.ext.World3x4.rahit",
"spv.ext.AccelDecl.frag", "spv.ext.AccelDecl.frag",
"spv.ext.RayQueryDecl.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 FileNameAsCustomTestSuffix
); );