Handle SPIR-V type mismatch when constructing a composite
authorJeff Bolz <jbolz@nvidia.com>
Tue, 25 Jun 2019 18:31:10 +0000 (13:31 -0500)
committerJeff Bolz <jbolz@nvidia.com>
Tue, 25 Jun 2019 18:32:35 +0000 (13:32 -0500)
SPIRV/GlslangToSpv.cpp
Test/baseResults/spv.1.4.constructComposite.comp.out [new file with mode: 0644]
Test/baseResults/spv.constructComposite.comp.out [new file with mode: 0644]
Test/spv.1.4.constructComposite.comp [new file with mode: 0644]
Test/spv.constructComposite.comp [new file with mode: 0644]
gtests/Spv.FromFile.cpp

index 16d90b8..4a5dc0b 100644 (file)
@@ -210,6 +210,7 @@ protected:
     }
     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 @@ 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<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 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
             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 (file)
index 0000000..5c0f5cf
--- /dev/null
@@ -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 (file)
index 0000000..6a23ecb
--- /dev/null
@@ -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 (file)
index 0000000..7f1c370
--- /dev/null
@@ -0,0 +1,25 @@
+#version 460 core\r
+\r
+layout(local_size_x=64) in;\r
+\r
+struct sA {\r
+  int x, y;\r
+};\r
+\r
+struct sB {\r
+  sA a;\r
+};\r
+\r
+layout(binding=0,set=0) uniform ubo {\r
+  sB  b;\r
+};\r
+\r
+struct sC {\r
+  sA state;\r
+} c = {\r
+  b.a,\r
+};\r
+\r
+void main()\r
+{\r
+}\r
diff --git a/Test/spv.constructComposite.comp b/Test/spv.constructComposite.comp
new file mode 100644 (file)
index 0000000..7f1c370
--- /dev/null
@@ -0,0 +1,25 @@
+#version 460 core\r
+\r
+layout(local_size_x=64) in;\r
+\r
+struct sA {\r
+  int x, y;\r
+};\r
+\r
+struct sB {\r
+  sA a;\r
+};\r
+\r
+layout(binding=0,set=0) uniform ubo {\r
+  sB  b;\r
+};\r
+\r
+struct sC {\r
+  sA state;\r
+} c = {\r
+  b.a,\r
+};\r
+\r
+void main()\r
+{\r
+}\r
index 3addb66..0d82039 100644 (file)
@@ -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
 );