From 4da479aa6afa43e5a2ce4c4148c572a03123faf3 Mon Sep 17 00:00:00 2001 From: Jeff Bolz Date: Fri, 31 May 2024 12:00:03 -0500 Subject: [PATCH] Generate SPV_EXT_replicated_composites when requested by pragma. Implement GL_EXT_spec_constant_composites. --- SPIRV/GLSL.ext.KHR.h | 1 + SPIRV/GlslangToSpv.cpp | 2 + SPIRV/SpvBuilder.cpp | 63 ++++++++- SPIRV/SpvBuilder.h | 3 + SPIRV/doc.cpp | 10 ++ SPIRV/spirv.hpp | 13 +- Test/baseResults/spv.replicate.comp.out | 117 ++++++++++++++++ Test/baseResults/spv.replicatespec.comp.out | 132 ++++++++++++++++++ .../spv.specConstantComposite2.vert.out | 89 ++++++++++++ Test/spv.replicate.comp | 43 ++++++ Test/spv.replicatespec.comp | 43 ++++++ Test/spv.specConstantComposite2.vert | 98 +++++++++++++ Test/vulkan.ast.vert | 2 +- glslang/MachineIndependent/ParseHelper.cpp | 39 +++++- glslang/MachineIndependent/Versions.cpp | 2 + glslang/MachineIndependent/Versions.h | 1 + .../MachineIndependent/localintermediate.h | 6 + gtests/Spv.FromFile.cpp | 2 + known_good.json | 4 +- 19 files changed, 656 insertions(+), 14 deletions(-) create mode 100644 Test/baseResults/spv.replicate.comp.out create mode 100644 Test/baseResults/spv.replicatespec.comp.out create mode 100644 Test/baseResults/spv.specConstantComposite2.vert.out create mode 100644 Test/spv.replicate.comp create mode 100644 Test/spv.replicatespec.comp create mode 100644 Test/spv.specConstantComposite2.vert diff --git a/SPIRV/GLSL.ext.KHR.h b/SPIRV/GLSL.ext.KHR.h index 1d3af1403..ba26708de 100644 --- a/SPIRV/GLSL.ext.KHR.h +++ b/SPIRV/GLSL.ext.KHR.h @@ -61,5 +61,6 @@ static const char* const E_SPV_KHR_cooperative_matrix = "SPV_KHR_coope static const char* const E_SPV_KHR_maximal_reconvergence = "SPV_KHR_maximal_reconvergence"; static const char* const E_SPV_KHR_subgroup_rotate = "SPV_KHR_subgroup_rotate"; static const char* const E_SPV_KHR_expect_assume = "SPV_KHR_expect_assume"; +static const char* const E_SPV_EXT_replicated_composites = "SPV_EXT_replicated_composites"; #endif // #ifndef GLSLextKHR_H diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp index 36e6c01c9..16e224663 100755 --- a/SPIRV/GlslangToSpv.cpp +++ b/SPIRV/GlslangToSpv.cpp @@ -1583,6 +1583,8 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, builder.addInclude(iItr->first, iItr->second); } + builder.setUseReplicatedComposites(glslangIntermediate->usingReplicatedComposites()); + stdBuiltins = builder.import("GLSL.std.450"); spv::AddressingModel addressingModel = spv::AddressingModelLogical; diff --git a/SPIRV/SpvBuilder.cpp b/SPIRV/SpvBuilder.cpp index 6613655a8..f07460d2b 100644 --- a/SPIRV/SpvBuilder.cpp +++ b/SPIRV/SpvBuilder.cpp @@ -1484,12 +1484,14 @@ bool Builder::isConstantOpCode(Op opcode) const case OpConstantFalse: case OpConstant: case OpConstantComposite: + case OpConstantCompositeReplicateEXT: case OpConstantSampler: case OpConstantNull: case OpSpecConstantTrue: case OpSpecConstantFalse: case OpSpecConstant: case OpSpecConstantComposite: + case OpSpecConstantCompositeReplicateEXT: case OpSpecConstantOp: return true; default: @@ -1506,6 +1508,7 @@ bool Builder::isSpecConstantOpCode(Op opcode) const case OpSpecConstant: case OpSpecConstantComposite: case OpSpecConstantOp: + case OpSpecConstantCompositeReplicateEXT: return true; default: return false; @@ -1782,10 +1785,27 @@ Id Builder::findStructConstant(Id typeId, const std::vector& comps) // Comments in header Id Builder::makeCompositeConstant(Id typeId, const std::vector& members, bool specConstant) { - Op opcode = specConstant ? OpSpecConstantComposite : OpConstantComposite; assert(typeId); Op typeClass = getTypeClass(typeId); + bool replicate = false; + size_t numMembers = members.size(); + if (useReplicatedComposites) { + // use replicate if all members are the same + replicate = numMembers > 0 && + std::equal(members.begin() + 1, members.end(), members.begin()); + + if (replicate) { + numMembers = 1; + addCapability(spv::CapabilityReplicatedCompositesEXT); + addExtension(spv::E_SPV_EXT_replicated_composites); + } + } + + Op opcode = replicate ? + (specConstant ? OpSpecConstantCompositeReplicateEXT : OpConstantCompositeReplicateEXT) : + (specConstant ? OpSpecConstantComposite : OpConstantComposite); + switch (typeClass) { case OpTypeVector: case OpTypeArray: @@ -1812,7 +1832,7 @@ Id Builder::makeCompositeConstant(Id typeId, const std::vector& members, boo Instruction* c = new Instruction(getUniqueId(), typeId, opcode); c->reserveOperands(members.size()); - for (int op = 0; op < (int)members.size(); ++op) + for (size_t op = 0; op < numMembers; ++op) c->addIdOperand(members[op]); constantsTypesGlobals.push_back(std::unique_ptr(c)); if (typeClass == OpTypeStruct) @@ -2928,7 +2948,17 @@ Id Builder::smearScalar(Decoration precision, Id scalar, Id vectorType) auto result_id = makeCompositeConstant(vectorType, members, isSpecConstant(scalar)); smear = module.getInstruction(result_id); } else { - smear = new Instruction(getUniqueId(), vectorType, OpCompositeConstruct); + bool replicate = useReplicatedComposites && (numComponents > 0); + + if (replicate) { + numComponents = 1; + addCapability(spv::CapabilityReplicatedCompositesEXT); + addExtension(spv::E_SPV_EXT_replicated_composites); + } + + Op opcode = replicate ? OpCompositeConstructReplicateEXT : OpCompositeConstruct; + + smear = new Instruction(getUniqueId(), vectorType, opcode); smear->reserveOperands(numComponents); for (int c = 0; c < numComponents; ++c) smear->addIdOperand(scalar); @@ -3321,9 +3351,25 @@ Id Builder::createCompositeConstruct(Id typeId, const std::vector& constitue [&](spv::Id id) { return isSpecConstant(id); })); } - Instruction* op = new Instruction(getUniqueId(), typeId, OpCompositeConstruct); + bool replicate = false; + size_t numConstituents = constituents.size(); + + if (useReplicatedComposites) { + replicate = numConstituents > 0 && + std::equal(constituents.begin() + 1, constituents.end(), constituents.begin()); + } + + if (replicate) { + numConstituents = 1; + addCapability(spv::CapabilityReplicatedCompositesEXT); + addExtension(spv::E_SPV_EXT_replicated_composites); + } + + Op opcode = replicate ? OpCompositeConstructReplicateEXT : OpCompositeConstruct; + + Instruction* op = new Instruction(getUniqueId(), typeId, opcode); op->reserveOperands(constituents.size()); - for (int c = 0; c < (int)constituents.size(); ++c) + for (size_t c = 0; c < numConstituents; ++c) op->addIdOperand(constituents[c]); addInstruction(std::unique_ptr(op)); @@ -3458,6 +3504,13 @@ Id Builder::createMatrixConstructor(Decoration precision, const std::vector& return setPrecision(createCompositeConstruct(resultTypeId, matrixColumns), precision); } + // Detect a matrix being constructed from a repeated vector of the correct size. + // Create the composite directly from it. + if ((int)sources.size() == numCols && isVector(sources[0]) && getNumComponents(sources[0]) == numRows && + std::equal(sources.begin() + 1, sources.end(), sources.begin())) { + return setPrecision(createCompositeConstruct(resultTypeId, sources), precision); + } + // Otherwise, will use a two step process // 1. make a compile-time 2D array of values // 2. construct a matrix from that array diff --git a/SPIRV/SpvBuilder.h b/SPIRV/SpvBuilder.h index b5509a8ba..fd04f630d 100644 --- a/SPIRV/SpvBuilder.h +++ b/SPIRV/SpvBuilder.h @@ -872,6 +872,8 @@ public: // Check if the builder is generating code for spec constants. bool isInSpecConstCodeGenMode() { return generatingOpCodeForSpecConst; } + void setUseReplicatedComposites(bool use) { useReplicatedComposites = use; } + protected: Id makeIntConstant(Id typeId, unsigned value, bool specConstant); Id makeInt64Constant(Id typeId, unsigned long long value, bool specConstant); @@ -938,6 +940,7 @@ public: Id uniqueId; Function* entryPointFunction; bool generatingOpCodeForSpecConst; + bool useReplicatedComposites { false }; AccessChain accessChain; // special blocks of instructions for output diff --git a/SPIRV/doc.cpp b/SPIRV/doc.cpp index ea4915fe7..f60a89491 100755 --- a/SPIRV/doc.cpp +++ b/SPIRV/doc.cpp @@ -1066,6 +1066,8 @@ const char* CapabilityString(int info) case CapabilityTextureBlockMatchQCOM: return "TextureBlockMatchQCOM"; case CapabilityTextureBlockMatch2QCOM: return "TextureBlockMatch2QCOM"; + case CapabilityReplicatedCompositesEXT: return "CapabilityReplicatedCompositesEXT"; + default: return "Bad"; } } @@ -1584,6 +1586,10 @@ const char* OpcodeString(int op) case OpImageBlockMatchGatherSSDQCOM: return "OpImageBlockMatchGatherSSDQCOM"; case OpImageBlockMatchGatherSADQCOM: return "OpImageBlockMatchGatherSADQCOM"; + case OpConstantCompositeReplicateEXT: return "OpConstantCompositeReplicateEXT"; + case OpSpecConstantCompositeReplicateEXT: return "OpSpecConstantCompositeReplicateEXT"; + case OpCompositeConstructReplicateEXT: return "OpCompositeConstructReplicateEXT"; + default: return "Bad"; } @@ -3471,6 +3477,10 @@ void Parameterize() InstructionDesc[OpImageBlockMatchGatherSADQCOM].operands.push(OperandId, "'block size'"); InstructionDesc[OpImageBlockMatchGatherSADQCOM].operands.push(OperandImageOperands, "", true); InstructionDesc[OpImageBlockMatchGatherSADQCOM].setResultAndType(true, true); + + InstructionDesc[OpConstantCompositeReplicateEXT].operands.push(OperandId, "'Value'"); + InstructionDesc[OpSpecConstantCompositeReplicateEXT].operands.push(OperandId, "'Value'"); + InstructionDesc[OpCompositeConstructReplicateEXT].operands.push(OperandId, "'Value'"); }); } diff --git a/SPIRV/spirv.hpp b/SPIRV/spirv.hpp index 6eceabe67..5821eced2 100644 --- a/SPIRV/spirv.hpp +++ b/SPIRV/spirv.hpp @@ -1162,7 +1162,8 @@ enum Capability { CapabilityDotProduct = 6019, CapabilityDotProductKHR = 6019, CapabilityRayCullMaskKHR = 6020, - CapabilityCooperativeMatrixKHR = 6022, + CapabilityCooperativeMatrixKHR = 6022, + CapabilityReplicatedCompositesEXT = 6024, CapabilityBitInstructions = 6025, CapabilityGroupNonUniformRotateKHR = 6026, CapabilityAtomicFloat32AddEXT = 6033, @@ -1688,7 +1689,10 @@ enum Op { OpCooperativeMatrixLoadKHR = 4457, OpCooperativeMatrixStoreKHR = 4458, OpCooperativeMatrixMulAddKHR = 4459, - OpCooperativeMatrixLengthKHR = 4460, + OpCooperativeMatrixLengthKHR = 4460, + OpConstantCompositeReplicateEXT = 4461, + OpSpecConstantCompositeReplicateEXT = 4462, + OpCompositeConstructReplicateEXT = 4463, OpTypeRayQueryKHR = 4472, OpRayQueryInitializeKHR = 4473, OpRayQueryTerminateKHR = 4474, @@ -2417,7 +2421,10 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) { case OpCooperativeMatrixLoadKHR: *hasResult = true; *hasResultType = true; break; case OpCooperativeMatrixStoreKHR: *hasResult = false; *hasResultType = false; break; case OpCooperativeMatrixMulAddKHR: *hasResult = true; *hasResultType = true; break; - case OpCooperativeMatrixLengthKHR: *hasResult = true; *hasResultType = true; break; + case OpCooperativeMatrixLengthKHR: *hasResult = true; *hasResultType = true; break; + case OpConstantCompositeReplicateEXT: *hasResult = true; *hasResultType = true; break; + case OpSpecConstantCompositeReplicateEXT: *hasResult = true; *hasResultType = true; break; + case OpCompositeConstructReplicateEXT: *hasResult = true; *hasResultType = true; break; case OpTypeRayQueryKHR: *hasResult = true; *hasResultType = false; break; case OpRayQueryInitializeKHR: *hasResult = false; *hasResultType = false; break; case OpRayQueryTerminateKHR: *hasResult = false; *hasResultType = false; break; diff --git a/Test/baseResults/spv.replicate.comp.out b/Test/baseResults/spv.replicate.comp.out new file mode 100644 index 000000000..965b37b5b --- /dev/null +++ b/Test/baseResults/spv.replicate.comp.out @@ -0,0 +1,117 @@ +spv.replicate.comp +// Module Version 10000 +// Generated by (magic number): 8000b +// Id's are bound by 66 + + Capability Shader + Capability VulkanMemoryModelKHR + Capability CooperativeMatrixKHR + Capability CapabilityReplicatedCompositesEXT + Extension "SPV_EXT_replicated_composites" + Extension "SPV_KHR_cooperative_matrix" + Extension "SPV_KHR_vulkan_memory_model" + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical VulkanKHR + EntryPoint GLCompute 4 "main" + ExecutionMode 4 LocalSize 1 1 1 + Source GLSL 450 + SourceExtension "GL_EXT_spec_constant_composites" + SourceExtension "GL_KHR_cooperative_matrix" + SourceExtension "GL_KHR_memory_scope_semantics" + Name 4 "main" + Name 13 "coop" + Name 17 "a" + Name 21 "v" + Name 28 "m" + Name 33 "five" + Name 35 "six" + Name 39 "arr" + Name 44 "arr2" + Name 49 "S" + MemberName 49(S) 0 "a" + MemberName 49(S) 1 "b" + MemberName 49(S) 2 "c" + Name 51 "s2" + Name 54 "SS" + MemberName 54(SS) 0 "s1" + MemberName 54(SS) 1 "s2" + Name 56 "ss" + Decorate 61 BuiltIn WorkgroupSize + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeFloat 32 + 7: TypeInt 32 0 + 8: 7(int) Constant 3 + 9: 7(int) Constant 16 + 10: 7(int) Constant 0 + 11: TypeCooperativeMatrixKHR 6(float) 8 9 9 10 + 12: TypePointer Function 11 + 14: 6(float) Constant 1065353216 + 15: 11 ConstantCompositeReplicateEXT 14 + 16: TypePointer Function 6(float) + 18: 6(float) Constant 1073741824 + 19: TypeVector 6(float) 4 + 20: TypePointer Function 19(fvec4) + 24: 6(float) Constant 1077936128 + 25: 19(fvec4) ConstantCompositeReplicateEXT 24 + 26: TypeMatrix 19(fvec4) 4 + 27: TypePointer Function 26 + 31: TypeInt 32 1 + 32: TypePointer Function 31(int) + 34: 31(int) Constant 5 + 36: 31(int) Constant 6 + 37: TypeArray 31(int) 8 + 38: TypePointer Function 37 + 42: TypeArray 37 8 + 43: TypePointer Function 42 + 47: 37 ConstantCompositeReplicateEXT 34 + 48: 42 ConstantCompositeReplicateEXT 47 + 49(S): TypeStruct 31(int) 31(int) 31(int) + 50: TypePointer Function 49(S) + 54(SS): TypeStruct 49(S) 49(S) + 55: TypePointer Function 54(SS) + 59: TypeVector 7(int) 3 + 60: 7(int) Constant 1 + 61: 59(ivec3) ConstantCompositeReplicateEXT 60 + 62: 49(S) ConstantCompositeReplicateEXT 36 + 63: 54(SS) ConstantCompositeReplicateEXT 62 + 64: 26 ConstantCompositeReplicateEXT 25 + 65: 11 ConstantCompositeReplicateEXT 24 + 4(main): 2 Function None 3 + 5: Label + 13(coop): 12(ptr) Variable Function + 17(a): 16(ptr) Variable Function + 21(v): 20(ptr) Variable Function + 28(m): 27(ptr) Variable Function + 33(five): 32(ptr) Variable Function + 35(six): 32(ptr) Variable Function + 39(arr): 38(ptr) Variable Function + 44(arr2): 43(ptr) Variable Function + 51(s2): 50(ptr) Variable Function + 56(ss): 55(ptr) Variable Function + Store 13(coop) 15 + Store 17(a) 18 + 22: 6(float) Load 17(a) + 23: 19(fvec4) CompositeConstructReplicateEXT 22 + Store 21(v) 23 + Store 21(v) 25 + 29: 19(fvec4) Load 21(v) + 30: 26 CompositeConstructReplicateEXT 29 + Store 28(m) 30 + Store 33(five) 34 + Store 35(six) 36 + 40: 31(int) Load 33(five) + 41: 37 CompositeConstructReplicateEXT 40 + Store 39(arr) 41 + 45: 37 Load 39(arr) + 46: 42 CompositeConstructReplicateEXT 45 + Store 44(arr2) 46 + Store 44(arr2) 48 + 52: 31(int) Load 35(six) + 53: 49(S) CompositeConstructReplicateEXT 52 + Store 51(s2) 53 + 57: 49(S) Load 51(s2) + 58: 54(SS) CompositeConstructReplicateEXT 57 + Store 56(ss) 58 + Return + FunctionEnd diff --git a/Test/baseResults/spv.replicatespec.comp.out b/Test/baseResults/spv.replicatespec.comp.out new file mode 100644 index 000000000..dd7157fed --- /dev/null +++ b/Test/baseResults/spv.replicatespec.comp.out @@ -0,0 +1,132 @@ +spv.replicatespec.comp +// Module Version 10000 +// Generated by (magic number): 8000b +// Id's are bound by 68 + + Capability Shader + Capability VulkanMemoryModelKHR + Capability CooperativeMatrixKHR + Capability CapabilityReplicatedCompositesEXT + Extension "SPV_EXT_replicated_composites" + Extension "SPV_KHR_cooperative_matrix" + Extension "SPV_KHR_vulkan_memory_model" + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical VulkanKHR + EntryPoint GLCompute 4 "main" + ExecutionMode 4 LocalSize 1 1 1 + Source GLSL 450 + SourceExtension "GL_EXT_spec_constant_composites" + SourceExtension "GL_KHR_cooperative_matrix" + SourceExtension "GL_KHR_memory_scope_semantics" + Name 4 "main" + Name 13 "coop" + Name 17 "a" + Name 21 "v" + Name 24 "spec_float" + Name 25 "cv" + Name 28 "m" + Name 33 "five" + Name 35 "six" + Name 39 "arr" + Name 44 "arr2" + Name 47 "cfive" + Name 48 "carr" + Name 49 "carr2" + Name 50 "S" + MemberName 50(S) 0 "a" + MemberName 50(S) 1 "b" + MemberName 50(S) 2 "c" + Name 52 "s2" + Name 55 "SS" + MemberName 55(SS) 0 "s1" + MemberName 55(SS) 1 "s2" + Name 57 "ss" + Name 63 "csix" + Name 64 "cs" + Name 65 "css" + Name 66 "cm" + Name 67 "ccoop" + Decorate 24(spec_float) SpecId 2 + Decorate 47(cfive) SpecId 0 + Decorate 62 BuiltIn WorkgroupSize + Decorate 63(csix) SpecId 1 + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeFloat 32 + 7: TypeInt 32 0 + 8: 7(int) Constant 3 + 9: 7(int) Constant 16 + 10: 7(int) Constant 0 + 11: TypeCooperativeMatrixKHR 6(float) 8 9 9 10 + 12: TypePointer Function 11 + 14: 6(float) Constant 1065353216 + 15: 11 ConstantCompositeReplicateEXT 14 + 16: TypePointer Function 6(float) + 18: 6(float) Constant 1073741824 + 19: TypeVector 6(float) 4 + 20: TypePointer Function 19(fvec4) + 24(spec_float): 6(float) SpecConstant 1077936128 + 25(cv): 19(fvec4) SpecConstantCompositeReplicateEXT 24(spec_float) + 26: TypeMatrix 19(fvec4) 4 + 27: TypePointer Function 26 + 31: TypeInt 32 1 + 32: TypePointer Function 31(int) + 34: 31(int) Constant 5 + 36: 31(int) Constant 6 + 37: TypeArray 31(int) 8 + 38: TypePointer Function 37 + 42: TypeArray 37 8 + 43: TypePointer Function 42 + 47(cfive): 31(int) SpecConstant 5 + 48(carr): 37 SpecConstantCompositeReplicateEXT 47(cfive) + 49(carr2): 42 SpecConstantCompositeReplicateEXT 48(carr) + 50(S): TypeStruct 31(int) 31(int) 31(int) + 51: TypePointer Function 50(S) + 55(SS): TypeStruct 50(S) 50(S) + 56: TypePointer Function 55(SS) + 60: TypeVector 7(int) 3 + 61: 7(int) Constant 1 + 62: 60(ivec3) ConstantCompositeReplicateEXT 61 + 63(csix): 31(int) SpecConstant 6 + 64(cs): 50(S) SpecConstantCompositeReplicateEXT 63(csix) + 65(css): 55(SS) SpecConstantCompositeReplicateEXT 64(cs) + 66(cm): 26 SpecConstantCompositeReplicateEXT 25(cv) + 67(ccoop): 11 SpecConstantCompositeReplicateEXT 24(spec_float) + 4(main): 2 Function None 3 + 5: Label + 13(coop): 12(ptr) Variable Function + 17(a): 16(ptr) Variable Function + 21(v): 20(ptr) Variable Function + 28(m): 27(ptr) Variable Function + 33(five): 32(ptr) Variable Function + 35(six): 32(ptr) Variable Function + 39(arr): 38(ptr) Variable Function + 44(arr2): 43(ptr) Variable Function + 52(s2): 51(ptr) Variable Function + 57(ss): 56(ptr) Variable Function + Store 13(coop) 15 + Store 17(a) 18 + 22: 6(float) Load 17(a) + 23: 19(fvec4) CompositeConstructReplicateEXT 22 + Store 21(v) 23 + Store 21(v) 25(cv) + 29: 19(fvec4) Load 21(v) + 30: 26 CompositeConstructReplicateEXT 29 + Store 28(m) 30 + Store 33(five) 34 + Store 35(six) 36 + 40: 31(int) Load 33(five) + 41: 37 CompositeConstructReplicateEXT 40 + Store 39(arr) 41 + 45: 37 Load 39(arr) + 46: 42 CompositeConstructReplicateEXT 45 + Store 44(arr2) 46 + Store 44(arr2) 49(carr2) + 53: 31(int) Load 35(six) + 54: 50(S) CompositeConstructReplicateEXT 53 + Store 52(s2) 54 + 58: 50(S) Load 52(s2) + 59: 55(SS) CompositeConstructReplicateEXT 58 + Store 57(ss) 59 + Return + FunctionEnd diff --git a/Test/baseResults/spv.specConstantComposite2.vert.out b/Test/baseResults/spv.specConstantComposite2.vert.out new file mode 100644 index 000000000..191f35062 --- /dev/null +++ b/Test/baseResults/spv.specConstantComposite2.vert.out @@ -0,0 +1,89 @@ +spv.specConstantComposite2.vert +// Module Version 10000 +// Generated by (magic number): 8000b +// Id's are bound by 43 + + Capability Shader + Capability Float64 + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint Vertex 4 "main" 27 42 + Source GLSL 450 + Name 4 "main" + Name 6 "refer_primary_spec_const(" + Name 8 "refer_composite_spec_const(" + Name 10 "refer_copmosite_dot_dereference(" + Name 12 "refer_composite_bracket_dereference(" + Name 16 "refer_spec_const_array_length(" + Name 18 "declare_spec_const_in_func(" + Name 21 "spec_bool" + Name 27 "color" + Name 28 "spec_int" + Name 33 "len" + Name 37 "spec_float" + Name 39 "spec_double" + Name 42 "global_vec4_array_with_spec_length" + Decorate 21(spec_bool) SpecId 203 + Decorate 27(color) Location 0 + Decorate 28(spec_int) SpecId 200 + Decorate 37(spec_float) SpecId 201 + Decorate 39(spec_double) SpecId 202 + Decorate 42(global_vec4_array_with_spec_length) Location 0 + 2: TypeVoid + 3: TypeFunction 2 + 14: TypeInt 32 1 + 15: TypeFunction 14(int) + 20: TypeBool + 21(spec_bool): 20(bool) SpecConstantTrue + 24: TypeFloat 32 + 25: TypeVector 24(float) 4 + 26: TypePointer Output 25(fvec4) + 27(color): 26(ptr) Variable Output + 28(spec_int): 14(int) SpecConstant 3 + 32: TypePointer Function 14(int) + 37(spec_float): 24(float) SpecConstant 1078523331 + 38: TypeFloat 64 + 39(spec_double):38(float64_t) SpecConstant 1413754136 1074340347 + 40: TypeArray 25(fvec4) 28(spec_int) + 41: TypePointer Input 40 +42(global_vec4_array_with_spec_length): 41(ptr) Variable Input + 4(main): 2 Function None 3 + 5: Label + Return + FunctionEnd +6(refer_primary_spec_const(): 2 Function None 3 + 7: Label + SelectionMerge 23 None + BranchConditional 21(spec_bool) 22 23 + 22: Label + 29: 24(float) ConvertSToF 28(spec_int) + 30: 25(fvec4) Load 27(color) + 31: 25(fvec4) VectorTimesScalar 30 29 + Store 27(color) 31 + Branch 23 + 23: Label + Return + FunctionEnd +8(refer_composite_spec_const(): 2 Function None 3 + 9: Label + Return + FunctionEnd +10(refer_copmosite_dot_dereference(): 2 Function None 3 + 11: Label + Return + FunctionEnd +12(refer_composite_bracket_dereference(): 2 Function None 3 + 13: Label + Return + FunctionEnd +16(refer_spec_const_array_length(): 14(int) Function None 15 + 17: Label + 33(len): 32(ptr) Variable Function + Store 33(len) 28(spec_int) + 34: 14(int) Load 33(len) + ReturnValue 34 + FunctionEnd +18(declare_spec_const_in_func(): 2 Function None 3 + 19: Label + Return + FunctionEnd diff --git a/Test/spv.replicate.comp b/Test/spv.replicate.comp new file mode 100644 index 000000000..ac2018f5c --- /dev/null +++ b/Test/spv.replicate.comp @@ -0,0 +1,43 @@ +#version 450 core +#extension GL_KHR_memory_scope_semantics : enable +#extension GL_KHR_cooperative_matrix : enable +#extension GL_EXT_spec_constant_composites : enable + +#pragma use_replicated_composites + +layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in; + +const int csix = 6; +struct S { int a; int b; int c; }; +struct SS { S s1; S s2; }; +const S cs = S(csix, csix, csix); +const SS css = SS(cs, cs); + +const float spec_float = 3; +const vec4 cv = vec4(spec_float); +const mat4 cm = mat4(cv,cv,cv,cv); + +const int cfive = 5; +const int carr[3] = {cfive, cfive, cfive}; +const int carr2[3][3] = {carr, carr, carr}; + +const coopmat ccoop = coopmat(spec_float); + +void main() +{ + coopmat coop = coopmat(1.0); + + float a = 2.0; + vec4 v = vec4(a); + v = cv; + mat4 m = mat4(v,v,v,v); + + int five = 5; + int six = 6; + int arr[3] = {five, five, five}; + int arr2[3][3] = {arr, arr, arr}; + arr2 = carr2; + + S s2 = S(six, six, six); + SS ss = SS(s2, s2); +} diff --git a/Test/spv.replicatespec.comp b/Test/spv.replicatespec.comp new file mode 100644 index 000000000..e4bc8c059 --- /dev/null +++ b/Test/spv.replicatespec.comp @@ -0,0 +1,43 @@ +#version 450 core +#extension GL_KHR_memory_scope_semantics : enable +#extension GL_KHR_cooperative_matrix : enable +#extension GL_EXT_spec_constant_composites : enable + +#pragma use_replicated_composites + +layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in; + +layout(constant_id = 1) const int csix = 6; +struct S { int a; int b; int c; }; +struct SS { S s1; S s2; }; +const S cs = S(csix, csix, csix); +const SS css = SS(cs, cs); + +layout(constant_id = 2) const float spec_float = 3; +const vec4 cv = vec4(spec_float); +const mat4 cm = mat4(cv,cv,cv,cv); + +layout(constant_id = 0) const int cfive = 5; +const int carr[3] = {cfive, cfive, cfive}; +const int carr2[3][3] = {carr, carr, carr}; + +const coopmat ccoop = coopmat(spec_float); + +void main() +{ + coopmat coop = coopmat(1.0); + + float a = 2.0; + vec4 v = vec4(a); + v = cv; + mat4 m = mat4(v,v,v,v); + + int five = 5; + int six = 6; + int arr[3] = {five, five, five}; + int arr2[3][3] = {arr, arr, arr}; + arr2 = carr2; + + S s2 = S(six, six, six); + SS ss = SS(s2, s2); +} diff --git a/Test/spv.specConstantComposite2.vert b/Test/spv.specConstantComposite2.vert new file mode 100644 index 000000000..d9d07a3ed --- /dev/null +++ b/Test/spv.specConstantComposite2.vert @@ -0,0 +1,98 @@ +#version 450 + +// constant_id specified scalar spec constants +layout(constant_id = 200) const int spec_int = 3; +layout(constant_id = 201) const float spec_float = 3.14; +layout(constant_id = 202) const + double spec_double = 3.1415926535897932384626433832795; +layout(constant_id = 203) const bool spec_bool = true; + +// const float cast_spec_float = float(spec_float); + +// Flat struct +struct flat_struct { + int i; + float f; + double d; + bool b; +}; + +// Nesting struct +struct nesting_struct { + flat_struct nested; + vec4 v; + int i; +}; + +// Expect OpSpecConstantComposite +// Flat struct initializer +//const flat_struct spec_flat_struct_all_spec = {spec_int, spec_float, +// spec_double, spec_bool}; +//const flat_struct spec_flat_struct_partial_spec = {30, 30.14, spec_double, +// spec_bool}; + +// Nesting struct initializer +//const nesting_struct nesting_struct_ctor = { +// {spec_int, spec_float, spec_double, false}, +// vec4(0.1, 0.1, 0.1, 0.1), +// spec_int}; + +// Vector constructor +//const vec4 spec_vec4_all_spec = +// vec4(spec_float, spec_float, spec_float, spec_float); +//const vec4 spec_vec4_partial_spec = +// vec4(spec_float, spec_float, 300.14, 300.14); +//const vec4 spec_vec4_from_one_scalar = vec4(spec_float); + +// Matrix constructor +//const mat2x3 spec_mat2x3 = mat2x3(spec_float, spec_float, spec_float, 1.1, 2.2, 3.3); +//const mat2x3 spec_mat2x3_from_one_scalar = mat2x3(spec_float); + +// Struct nesting constructor +//const nesting_struct spec_nesting_struct_all_spec = { +// spec_flat_struct_all_spec, spec_vec4_all_spec, spec_int}; +//const nesting_struct spec_nesting_struct_partial_spec = { +// spec_flat_struct_partial_spec, spec_vec4_partial_spec, 3000}; + +//const float spec_float_array[5] = {spec_float, spec_float, 1.0, 2.0, 3.0}; +//const int spec_int_array[5] = {spec_int, spec_int, 1, 2, 30}; + +// global_vec4_array_with_spec_length is not a spec constant, but its array +// size is. When calling global_vec4_array_with_spec_length.length(), A +// TIntermSymbol Node should be returned, instead of a TIntermConstantUnion +// node which represents a known constant value. +in vec4 global_vec4_array_with_spec_length[spec_int]; + +out vec4 color; + +void refer_primary_spec_const() { + if (spec_bool) color *= spec_int; +} + +void refer_composite_spec_const() { + //color += spec_vec4_all_spec; + //color -= spec_vec4_partial_spec; +} + +void refer_copmosite_dot_dereference() { + //color *= spec_nesting_struct_all_spec.i; + //color += spec_vec4_all_spec.x; +} + +void refer_composite_bracket_dereference() { + //color -= spec_float_array[1]; + //color /= spec_int_array[spec_int_array[spec_int]]; +} + +int refer_spec_const_array_length() { + int len = global_vec4_array_with_spec_length.length(); + return len; +} + +void declare_spec_const_in_func() { + //const nesting_struct spec_const_declared_in_func = { + // spec_flat_struct_partial_spec, spec_vec4_partial_spec, 10}; + //color /= spec_const_declared_in_func.i; +} + +void main() {} diff --git a/Test/vulkan.ast.vert b/Test/vulkan.ast.vert index b9e3e28b8..5817a2368 100644 --- a/Test/vulkan.ast.vert +++ b/Test/vulkan.ast.vert @@ -38,5 +38,5 @@ void main() ivec2[2](ivec2(sci2, sci2), ivec2(sci2, sci2)); // not a spec-const vec2(scf1, scf1); // spec-const - vec2[2](vec2(scf1, scf1), vec2(scf1, scf1)); // not a spec-const + vec2[2](vec2(scf1, scf1), vec2(scf1, scf1)); // spec-const } diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index 2880cce18..98a7d2688 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -399,6 +399,10 @@ void TParseContext::handlePragma(const TSourceLoc& loc, const TVector& if (spvVersion.spv < glslang::EShTargetSpv_1_3) error(loc, "requires SPIR-V 1.3", "#pragma use_variable_pointers", ""); intermediate.setUseVariablePointers(); + } else if (spvVersion.spv > 0 && tokens[0].compare("use_replicated_composites") == 0) { + if (tokens.size() != 1) + error(loc, "extra tokens", "#pragma", ""); + intermediate.setReplicatedComposites(); } else if (tokens[0].compare("once") == 0) { warn(loc, "not implemented", "#pragma once", ""); } else if (tokens[0].compare("glslang_binary_double_output") == 0) { @@ -3613,6 +3617,19 @@ bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, T makeSpecConst = ! intArgument && !type.isArray(); break; + case EOpConstructCooperativeMatrixNV: + case EOpConstructCooperativeMatrixKHR: + case EOpConstructStruct: + { + const char *specConstantCompositeExt[] = { E_GL_EXT_spec_constant_composites }; + if (checkExtensionsRequested(loc, 1, specConstantCompositeExt, "spec constant aggregate constructor")) { + makeSpecConst = true; + } else { + makeSpecConst = false; + } + } + break; + default: // anything else wasn't white-listed in the spec as a conversion makeSpecConst = false; @@ -8355,6 +8372,11 @@ TIntermTyped* TParseContext::addConstructor(const TSourceLoc& loc, TIntermNode* int paramCount = 0; // keeps track of the constructor parameter number being checked + // We don't know "top down" whether type is a specialization constant, + // but a const becomes a specialization constant if any of its children are. + bool hasSpecConst = false; + bool isConstConstructor = true; + // for each parameter to the constructor call, check to see if the right type is passed or convert them // to the right type if possible (and allowed). // for structure constructors, just check if the right type is passed, no conversion is allowed. @@ -8367,13 +8389,24 @@ TIntermTyped* TParseContext::addConstructor(const TSourceLoc& loc, TIntermNode* else newNode = constructBuiltIn(type, op, (*p)->getAsTyped(), node->getLoc(), true); - if (newNode) + if (newNode) { *p = newNode; - else + if (!newNode->getType().getQualifier().isConstant()) + isConstConstructor = false; + if (newNode->getType().getQualifier().isSpecConstant()) + hasSpecConst = true; + } else return nullptr; } - TIntermTyped *ret_node = intermediate.setAggregateOperator(aggrNode, op, type, loc); + TIntermTyped* ret_node = intermediate.setAggregateOperator(aggrNode, op, type, loc); + + const char *specConstantCompositeExt[] = { E_GL_EXT_spec_constant_composites }; + if (checkExtensionsRequested(loc, 1, specConstantCompositeExt, "spec constant aggregate constructor")) { + if (isConstConstructor && hasSpecConst) { + ret_node->getWritableType().getQualifier().makeSpecConstant(); + } + } TIntermAggregate *agg_node = ret_node->getAsAggregate(); if (agg_node && (agg_node->isVector() || agg_node->isArray() || agg_node->isMatrix())) diff --git a/glslang/MachineIndependent/Versions.cpp b/glslang/MachineIndependent/Versions.cpp index 44ba9e061..e016ef6b9 100644 --- a/glslang/MachineIndependent/Versions.cpp +++ b/glslang/MachineIndependent/Versions.cpp @@ -265,6 +265,7 @@ void TParseVersions::initializeExtensionBehavior() extensionBehavior[E_GL_EXT_expect_assume] = EBhDisable; extensionBehavior[E_GL_EXT_control_flow_attributes2] = EBhDisable; + extensionBehavior[E_GL_EXT_spec_constant_composites] = EBhDisable; extensionBehavior[E_GL_KHR_cooperative_matrix] = EBhDisable; @@ -519,6 +520,7 @@ void TParseVersions::getPreamble(std::string& preamble) "#define GL_EXT_fragment_shading_rate 1\n" "#define GL_EXT_shared_memory_block 1\n" "#define GL_EXT_shader_integer_mix 1\n" + "#define GL_EXT_spec_constant_composites 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 cfaeb1ff1..75a823774 100755 --- a/glslang/MachineIndependent/Versions.h +++ b/glslang/MachineIndependent/Versions.h @@ -222,6 +222,7 @@ const char* const E_GL_EXT_texture_array = "GL_EXT_texture_ar const char* const E_GL_EXT_maximal_reconvergence = "GL_EXT_maximal_reconvergence"; const char* const E_GL_EXT_expect_assume = "GL_EXT_expect_assume"; const char* const E_GL_EXT_control_flow_attributes2 = "GL_EXT_control_flow_attributes2"; +const char* const E_GL_EXT_spec_constant_composites = "GL_EXT_spec_constant_composites"; // Arrays of extensions for the above viewportEXTs duplications diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h index 5e9714780..2a24cdaf7 100644 --- a/glslang/MachineIndependent/localintermediate.h +++ b/glslang/MachineIndependent/localintermediate.h @@ -729,6 +729,11 @@ public: usePhysicalStorageBuffer = true; } bool usingPhysicalStorageBuffer() const { return usePhysicalStorageBuffer; } + void setReplicatedComposites() + { + useReplicatedComposites = true; + } + bool usingReplicatedComposites() const { return useReplicatedComposites; } void setUseVariablePointers() { useVariablePointers = true; @@ -1242,6 +1247,7 @@ protected: bool subgroupUniformControlFlow; bool maximallyReconverges; bool usePhysicalStorageBuffer; + bool useReplicatedComposites { false }; TSpirvRequirement* spirvRequirement; TSpirvExecutionMode* spirvExecutionMode; diff --git a/gtests/Spv.FromFile.cpp b/gtests/Spv.FromFile.cpp index 5ebd5b315..b12799320 100644 --- a/gtests/Spv.FromFile.cpp +++ b/gtests/Spv.FromFile.cpp @@ -468,6 +468,8 @@ INSTANTIATE_TEST_SUITE_P( "spv.prepost.frag", "spv.privateVariableTypes.frag", "spv.qualifiers.vert", + "spv.replicate.comp", + "spv.replicatespec.comp", "spv.sample.frag", "spv.sampleId.frag", "spv.samplePosition.frag", diff --git a/known_good.json b/known_good.json index d01b29366..8dbe973df 100644 --- a/known_good.json +++ b/known_good.json @@ -5,14 +5,14 @@ "site" : "github", "subrepo" : "KhronosGroup/SPIRV-Tools", "subdir" : "External/spirv-tools", - "commit": "dd4b663e13c07fea4fbb3f70c1c91c86731099f7" + "commit": "148c97f6876e427efd76d2328122c3075eab4b8f" }, { "name" : "spirv-tools/external/spirv-headers", "site" : "github", "subrepo" : "KhronosGroup/SPIRV-Headers", "subdir" : "External/spirv-tools/external/spirv-headers", - "commit" : "4f7b471f1a66b6d06462cd4ba57628cc0cd087d7" + "commit" : "ea77f2a826bc820cb8f57f9b2a7c7eccb681c731" }, { "name": "googletest",