From 531344905f3ee4fd260a094aff02ac6ee12e68f8 Mon Sep 17 00:00:00 2001 From: Jeff Bolz Date: Tue, 25 Jun 2019 13:31:10 -0500 Subject: [PATCH] Handle SPIR-V type mismatch when constructing a composite --- SPIRV/GlslangToSpv.cpp | 36 ++++++++++- .../spv.1.4.constructComposite.comp.out | 62 ++++++++++++++++++ .../spv.constructComposite.comp.out | 64 +++++++++++++++++++ Test/spv.1.4.constructComposite.comp | 25 ++++++++ Test/spv.constructComposite.comp | 25 ++++++++ gtests/Spv.FromFile.cpp | 2 + 6 files changed, 213 insertions(+), 1 deletion(-) create mode 100644 Test/baseResults/spv.1.4.constructComposite.comp.out create mode 100644 Test/baseResults/spv.constructComposite.comp.out create mode 100644 Test/spv.1.4.constructComposite.comp create mode 100644 Test/spv.constructComposite.comp diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp index 16d90b893..4a5dc0b86 100644 --- a/SPIRV/GlslangToSpv.cpp +++ b/SPIRV/GlslangToSpv.cpp @@ -210,6 +210,7 @@ protected: } std::pair getForcedType(spv::BuiltIn, const glslang::TType&); spv::Id translateForcedType(spv::Id object); + spv::Id createCompositeConstruct(spv::Id typeId, std::vector constituents); glslang::SpvOptions& options; spv::Function* shaderEntry; @@ -2172,6 +2173,39 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI } } +// Construct a composite object, recursively copying members if their types don't match +spv::Id TGlslangToSpvTraverser::createCompositeConstruct(spv::Id resultTypeId, std::vector constituents) +{ + for (int c = 0; c < (int)constituents.size(); ++c) { + spv::Id& constituent = constituents[c]; + spv::Id lType = builder.getContainedTypeId(resultTypeId, c); + spv::Id rType = builder.getTypeId(constituent); + if (lType != rType) { + if (glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_4) { + constituent = builder.createUnaryOp(spv::OpCopyLogical, lType, constituent); + } else if (builder.isStructType(rType)) { + std::vector rTypeConstituents; + int numrTypeConstituents = builder.getNumTypeConstituents(rType); + for (int i = 0; i < numrTypeConstituents; ++i) { + rTypeConstituents.push_back(builder.createCompositeExtract(constituent, builder.getContainedTypeId(rType, i), i)); + } + constituents[c] = createCompositeConstruct(lType, rTypeConstituents); + } else { + assert(builder.isArrayType(rType)); + std::vector rTypeConstituents; + int numrTypeConstituents = builder.getNumTypeConstituents(rType); + + spv::Id elementRType = builder.getContainedTypeId(rType); + for (int i = 0; i < numrTypeConstituents; ++i) { + rTypeConstituents.push_back(builder.createCompositeExtract(constituent, elementRType, i)); + } + constituents[c] = createCompositeConstruct(lType, rTypeConstituents); + } + } + } + return builder.createCompositeConstruct(resultTypeId, constituents); +} + bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TIntermAggregate* node) { SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder); @@ -2413,7 +2447,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt std::vector constituents; for (int c = 0; c < (int)arguments.size(); ++c) constituents.push_back(arguments[c]); - constructed = builder.createCompositeConstruct(resultType(), constituents); + constructed = createCompositeConstruct(resultType(), constituents); } else if (isMatrix) constructed = builder.createMatrixConstructor(precision, arguments, resultType()); else diff --git a/Test/baseResults/spv.1.4.constructComposite.comp.out b/Test/baseResults/spv.1.4.constructComposite.comp.out new file mode 100644 index 000000000..5c0f5cfa9 --- /dev/null +++ b/Test/baseResults/spv.1.4.constructComposite.comp.out @@ -0,0 +1,62 @@ +spv.1.4.constructComposite.comp +// Module Version 10400 +// Generated by (magic number): 80007 +// Id's are bound by 27 + + Capability Shader + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint GLCompute 4 "main" 10 15 + ExecutionMode 4 LocalSize 64 1 1 + Source GLSL 460 + Name 4 "main" + Name 7 "sA" + MemberName 7(sA) 0 "x" + MemberName 7(sA) 1 "y" + Name 8 "sC" + MemberName 8(sC) 0 "state" + Name 10 "c" + Name 11 "sA" + MemberName 11(sA) 0 "x" + MemberName 11(sA) 1 "y" + Name 12 "sB" + MemberName 12(sB) 0 "a" + Name 13 "ubo" + MemberName 13(ubo) 0 "b" + Name 15 "" + MemberDecorate 11(sA) 0 Offset 0 + MemberDecorate 11(sA) 1 Offset 4 + MemberDecorate 12(sB) 0 Offset 0 + MemberDecorate 13(ubo) 0 Offset 0 + Decorate 13(ubo) Block + Decorate 15 DescriptorSet 0 + Decorate 15 Binding 0 + Decorate 26 BuiltIn WorkgroupSize + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeInt 32 1 + 7(sA): TypeStruct 6(int) 6(int) + 8(sC): TypeStruct 7(sA) + 9: TypePointer Private 8(sC) + 10(c): 9(ptr) Variable Private + 11(sA): TypeStruct 6(int) 6(int) + 12(sB): TypeStruct 11(sA) + 13(ubo): TypeStruct 12(sB) + 14: TypePointer Uniform 13(ubo) + 15: 14(ptr) Variable Uniform + 16: 6(int) Constant 0 + 17: TypePointer Uniform 11(sA) + 22: TypeInt 32 0 + 23: TypeVector 22(int) 3 + 24: 22(int) Constant 64 + 25: 22(int) Constant 1 + 26: 23(ivec3) ConstantComposite 24 25 25 + 4(main): 2 Function None 3 + 5: Label + 18: 17(ptr) AccessChain 15 16 16 + 19: 11(sA) Load 18 + 20: 7(sA) CopyLogical 19 + 21: 8(sC) CompositeConstruct 20 + Store 10(c) 21 + Return + FunctionEnd diff --git a/Test/baseResults/spv.constructComposite.comp.out b/Test/baseResults/spv.constructComposite.comp.out new file mode 100644 index 000000000..6a23ecb2b --- /dev/null +++ b/Test/baseResults/spv.constructComposite.comp.out @@ -0,0 +1,64 @@ +spv.constructComposite.comp +// Module Version 10000 +// Generated by (magic number): 80007 +// Id's are bound by 29 + + Capability Shader + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint GLCompute 4 "main" + ExecutionMode 4 LocalSize 64 1 1 + Source GLSL 460 + Name 4 "main" + Name 7 "sA" + MemberName 7(sA) 0 "x" + MemberName 7(sA) 1 "y" + Name 8 "sC" + MemberName 8(sC) 0 "state" + Name 10 "c" + Name 11 "sA" + MemberName 11(sA) 0 "x" + MemberName 11(sA) 1 "y" + Name 12 "sB" + MemberName 12(sB) 0 "a" + Name 13 "ubo" + MemberName 13(ubo) 0 "b" + Name 15 "" + MemberDecorate 11(sA) 0 Offset 0 + MemberDecorate 11(sA) 1 Offset 4 + MemberDecorate 12(sB) 0 Offset 0 + MemberDecorate 13(ubo) 0 Offset 0 + Decorate 13(ubo) Block + Decorate 15 DescriptorSet 0 + Decorate 15 Binding 0 + Decorate 28 BuiltIn WorkgroupSize + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeInt 32 1 + 7(sA): TypeStruct 6(int) 6(int) + 8(sC): TypeStruct 7(sA) + 9: TypePointer Private 8(sC) + 10(c): 9(ptr) Variable Private + 11(sA): TypeStruct 6(int) 6(int) + 12(sB): TypeStruct 11(sA) + 13(ubo): TypeStruct 12(sB) + 14: TypePointer Uniform 13(ubo) + 15: 14(ptr) Variable Uniform + 16: 6(int) Constant 0 + 17: TypePointer Uniform 11(sA) + 24: TypeInt 32 0 + 25: TypeVector 24(int) 3 + 26: 24(int) Constant 64 + 27: 24(int) Constant 1 + 28: 25(ivec3) ConstantComposite 26 27 27 + 4(main): 2 Function None 3 + 5: Label + 18: 17(ptr) AccessChain 15 16 16 + 19: 11(sA) Load 18 + 20: 6(int) CompositeExtract 19 0 + 21: 6(int) CompositeExtract 19 1 + 22: 7(sA) CompositeConstruct 20 21 + 23: 8(sC) CompositeConstruct 22 + Store 10(c) 23 + Return + FunctionEnd diff --git a/Test/spv.1.4.constructComposite.comp b/Test/spv.1.4.constructComposite.comp new file mode 100644 index 000000000..7f1c37076 --- /dev/null +++ b/Test/spv.1.4.constructComposite.comp @@ -0,0 +1,25 @@ +#version 460 core + +layout(local_size_x=64) in; + +struct sA { + int x, y; +}; + +struct sB { + sA a; +}; + +layout(binding=0,set=0) uniform ubo { + sB b; +}; + +struct sC { + sA state; +} c = { + b.a, +}; + +void main() +{ +} diff --git a/Test/spv.constructComposite.comp b/Test/spv.constructComposite.comp new file mode 100644 index 000000000..7f1c37076 --- /dev/null +++ b/Test/spv.constructComposite.comp @@ -0,0 +1,25 @@ +#version 460 core + +layout(local_size_x=64) in; + +struct sA { + int x, y; +}; + +struct sB { + sA a; +}; + +layout(binding=0,set=0) uniform ubo { + sB b; +}; + +struct sC { + sA state; +} c = { + b.a, +}; + +void main() +{ +} diff --git a/gtests/Spv.FromFile.cpp b/gtests/Spv.FromFile.cpp index 3addb6622..0d820398f 100644 --- a/gtests/Spv.FromFile.cpp +++ b/gtests/Spv.FromFile.cpp @@ -295,6 +295,7 @@ INSTANTIATE_TEST_CASE_P( "spv.bufferhandle_Error.frag", "spv.builtInXFB.vert", "spv.conditionalDiscard.frag", + "spv.constructComposite.comp", "spv.constStruct.vert", "spv.constConstruct.vert", "spv.controlFlowAttributes.frag", @@ -482,6 +483,7 @@ INSTANTIATE_TEST_CASE_P( "spv.1.4.image.frag", "spv.1.4.sparseTexture.frag", "spv.1.4.texture.frag", + "spv.1.4.constructComposite.comp", })), FileNameAsCustomTestSuffix );