Handle SPIR-V type mismatch when constructing a composite
diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp
index 16d90b8..4a5dc0b 100644
--- a/SPIRV/GlslangToSpv.cpp
+++ b/SPIRV/GlslangToSpv.cpp
@@ -210,6 +210,7 @@
}
std::pair<spv::Id, spv::Id> getForcedType(spv::BuiltIn, const glslang::TType&);
spv::Id translateForcedType(spv::Id object);
+ spv::Id createCompositeConstruct(spv::Id typeId, std::vector<spv::Id> constituents);
glslang::SpvOptions& options;
spv::Function* shaderEntry;
@@ -2172,6 +2173,39 @@
}
}
+// Construct a composite object, recursively copying members if their types don't match
+spv::Id TGlslangToSpvTraverser::createCompositeConstruct(spv::Id resultTypeId, std::vector<spv::Id> 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<spv::Id> 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<spv::Id> 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 @@
std::vector<spv::Id> 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 0000000..5c0f5cf
--- /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 0000000..6a23ecb
--- /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 0000000..7f1c370
--- /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 0000000..7f1c370
--- /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 3addb66..0d82039 100644
--- a/gtests/Spv.FromFile.cpp
+++ b/gtests/Spv.FromFile.cpp
@@ -295,6 +295,7 @@
"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 @@
"spv.1.4.image.frag",
"spv.1.4.sparseTexture.frag",
"spv.1.4.texture.frag",
+ "spv.1.4.constructComposite.comp",
})),
FileNameAsCustomTestSuffix
);