SPV: Flatten structs for copy when they are GLSL type aliases.
authorJohn Kessenich <cepheus@frii.com>
Fri, 2 Sep 2016 17:20:21 +0000 (11:20 -0600)
committerJohn Kessenich <cepheus@frii.com>
Fri, 2 Sep 2016 22:35:01 +0000 (16:35 -0600)
Addresses issue #304 and issue #307 by replacing unmatched type OpStores with
per-member copies. Covers assignment statements and most argument passing, but
does not yet cover r-value-based argument passing.

SPIRV/GlslangToSpv.cpp
Test/baseResults/spv.multiStruct.comp.out [new file with mode: 0755]
Test/baseResults/spv.multiStructFuncall.frag.out [new file with mode: 0755]
Test/spv.multiStruct.comp [new file with mode: 0644]
Test/spv.multiStructFuncall.frag [new file with mode: 0755]
glslang/Include/revision.h
gtests/Spv.FromFile.cpp

index ddad636..84c9e73 100755 (executable)
@@ -130,6 +130,7 @@ protected:
     spv::Id makeArraySizeId(const glslang::TArraySizes&, int dim);
     spv::Id accessChainLoad(const glslang::TType& type);
     void    accessChainStore(const glslang::TType& type, spv::Id rvalue);
+    void multiTypeStore(const glslang::TType&, spv::Id rValue);
     glslang::TLayoutPacking getExplicitLayout(const glslang::TType& type) const;
     int getArrayStride(const glslang::TType& arrayType, glslang::TLayoutPacking, glslang::TLayoutMatrix);
     int getMatrixStride(const glslang::TType& matrixType, glslang::TLayoutPacking, glslang::TLayoutMatrix);
@@ -188,7 +189,7 @@ protected:
     std::unordered_map<const char*, spv::Id> extBuiltinMap;
 
     std::unordered_map<int, spv::Id> symbolValues;
-    std::unordered_set<int> constReadOnlyParameters;  // set of formal function parameters that have glslang qualifier constReadOnly, so we know they are not local function "const" that are write-once
+    std::unordered_set<int> rValueParameters;  // set of formal function parameters passed as rValues, rather than a pointer
     std::unordered_map<std::string, spv::Function*> functionMap;
     std::unordered_map<const glslang::TTypeList*, spv::Id> structMap[glslang::ElpCount][glslang::ElmCount];
     std::unordered_map<const glslang::TTypeList*, std::vector<int> > memberRemapper;  // for mapping glslang block indices to spv indices (e.g., due to hidden members)
@@ -897,13 +898,12 @@ void TGlslangToSpvTraverser::visitSymbol(glslang::TIntermSymbol* symbol)
 
         // For now, we consider all user variables as being in memory, so they are pointers,
         // except for
-        // A) "const in" arguments to a function, which are an intermediate object.
+        // A) R-Value arguments to a function, which are an intermediate object.
         //    See comments in handleUserFunctionCall().
-        // B) Specialization constants (normal constant don't even come in as a variable),
+        // B) Specialization constants (normal constants don't even come in as a variable),
         //    These are also pure R-values.
         glslang::TQualifier qualifier = symbol->getQualifier();
-        if ((qualifier.storage == glslang::EvqConstReadOnly && constReadOnlyParameters.find(symbol->getId()) != constReadOnlyParameters.end()) ||
-             qualifier.isSpecConstant())
+        if (qualifier.isSpecConstant() || rValueParameters.find(symbol->getId()) != rValueParameters.end())
             builder.setAccessChainRValue(id);
         else
             builder.setAccessChainLValue(id);
@@ -965,16 +965,7 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T
 
             // store the result
             builder.setAccessChain(lValue);
-            if (builder.isStructType(builder.getTypeId(rValue))) {
-                //spv::Id lType = builder.getContainedTypeId(builder.getTypeId(builder.accessChainGetLValue()));
-                //spv::Id rType = builder.getTypeId(rValue);
-                //if (lType != rType) {
-                    // TODO: do member-wise copy instead, this is current issue
-                    // https://github.com/KhronosGroup/glslang/issues/304
-                //} else
-                    accessChainStore(node->getType(), rValue);
-            } else
-                accessChainStore(node->getType(), rValue);
+            multiTypeStore(node->getType(), rValue);
 
             // assignments are expressions having an rValue after they are evaluated...
             builder.clearAccessChain();
@@ -2248,6 +2239,8 @@ spv::Id TGlslangToSpvTraverser::accessChainLoad(const glslang::TType& type)
 
 // Wrap the builder's accessChainStore to:
 //  - do conversion of concrete to abstract type
+//
+// Implicitly uses the existing builder.accessChain as the storage target.
 void TGlslangToSpvTraverser::accessChainStore(const glslang::TType& type, spv::Id rvalue)
 {
     // Need to convert to abstract types when necessary
@@ -2277,6 +2270,57 @@ void TGlslangToSpvTraverser::accessChainStore(const glslang::TType& type, spv::I
     builder.accessChainStore(rvalue);
 }
 
+// For storing when types match at the glslang level, but not might match at the
+// SPIR-V level.
+//
+// This especially happens when a single glslang type expands to multiple
+// SPIR-V types, like a struct that is used in an member-undecorated way as well
+// as in a member-decorated way.
+//
+// NOTE: This function can handle any store request; if it's not special it
+// simplifies to a simple OpStore.
+//
+// Implicitly uses the existing builder.accessChain as the storage target.
+void TGlslangToSpvTraverser::multiTypeStore(const glslang::TType& type, spv::Id rValue)
+{
+    // we only do the complex path here if it's a structure
+    if (! type.isStruct()) {
+        accessChainStore(type, rValue);
+        return;
+    }
+
+    // and, it has to be a case of structure type aliasing
+    spv::Id rType = builder.getTypeId(rValue);
+    spv::Id lValue = builder.accessChainGetLValue();
+    spv::Id lType = builder.getContainedTypeId(builder.getTypeId(lValue));
+    if (lType == rType) {
+        accessChainStore(type, rValue);
+        return;
+    }
+
+    // Recursively (as needed) copy a struct type to a different struct type,
+    // where the two types were the same type in GLSL. This requires member
+    // by member copy, recursively.
+
+    // loop over members
+    const glslang::TTypeList& members = *type.getStruct();
+    for (int m = 0; m < (int)members.size(); ++m) {
+        const glslang::TType& glslangMemberType = *members[m].type;
+
+        // get the source member
+        spv::Id memberRType = builder.getContainedTypeId(rType, m);
+        spv::Id memberRValue = builder.createCompositeExtract(rValue, memberRType, m);
+
+        // set up the target storage
+        builder.clearAccessChain();
+        builder.setAccessChainLValue(lValue);
+        builder.accessChainPush(builder.makeIntConstant(m));
+
+        // store the member
+        multiTypeStore(glslangMemberType, memberRValue);
+    }
+}
+
 // Decide whether or not this type should be
 // decorated with offsets and strides, and if so
 // whether std140 or std430 rules should be applied.
@@ -2403,19 +2447,18 @@ void TGlslangToSpvTraverser::makeFunctions(const glslang::TIntermSequence& glslF
             continue;
 
         // We're on a user function.  Set up the basic interface for the function now,
-        // so that it's available to call.
-        // Translating the body will happen later.
+        // so that it's available to call.  Translating the body will happen later.
         //
         // Typically (except for a "const in" parameter), an address will be passed to the
         // function.  What it is an address of varies:
         //
-        // - "in" parameters not marked as "const" can be written to without modifying the argument,
-        //  so that write needs to be to a copy, hence the address of a copy works.
+        // - "in" parameters not marked as "const" can be written to without modifying the calling
+        //   argument so that write needs to be to a copy, hence the address of a copy works.
         //
         // - "const in" parameters can just be the r-value, as no writes need occur.
         //
-        // - "out" and "inout" arguments can't be done as direct pointers, because GLSL has
-        // copy-in/copy-out semantics.  They can be handled though with a pointer to a copy.
+        // - "out" and "inout" arguments can't be done as pointers to the calling argument, because
+        //   GLSL has copy-in/copy-out semantics.  They can be handled though with a pointer to a copy.
 
         std::vector<spv::Id> paramTypes;
         std::vector<spv::Decoration> paramPrecisions;
@@ -2429,7 +2472,7 @@ void TGlslangToSpvTraverser::makeFunctions(const glslang::TIntermSequence& glslF
             else if (paramType.getQualifier().storage != glslang::EvqConstReadOnly)
                 typeId = builder.makePointer(spv::StorageClassFunction, typeId);
             else
-                constReadOnlyParameters.insert(parameters[p]->getAsSymbolNode()->getId());
+                rValueParameters.insert(parameters[p]->getAsSymbolNode()->getId());
             paramPrecisions.push_back(TranslatePrecisionDecoration(paramType));
             paramTypes.push_back(typeId);
         }
@@ -2914,7 +2957,9 @@ spv::Id TGlslangToSpvTraverser::handleUserFunctionCall(const glslang::TIntermAgg
                 // need to copy the input into output space
                 builder.setAccessChain(lValues[lValueCount]);
                 spv::Id copy = accessChainLoad(*argTypes[a]);
-                builder.createStore(copy, arg);
+                builder.clearAccessChain();
+                builder.setAccessChainLValue(arg);
+                multiTypeStore(paramType, copy);
             }
             ++lValueCount;
         } else {
@@ -2931,11 +2976,12 @@ spv::Id TGlslangToSpvTraverser::handleUserFunctionCall(const glslang::TIntermAgg
     // 4. Copy back out an "out" arguments.
     lValueCount = 0;
     for (int a = 0; a < (int)glslangArgs.size(); ++a) {
+        const glslang::TType& paramType = glslangArgs[a]->getAsTyped()->getType();
         if (qualifiers[a] != glslang::EvqConstReadOnly) {
             if (qualifiers[a] == glslang::EvqOut || qualifiers[a] == glslang::EvqInOut) {
                 spv::Id copy = builder.createLoad(spvArgs[a]);
                 builder.setAccessChain(lValues[lValueCount]);
-                accessChainStore(glslangArgs[a]->getAsTyped()->getType(), copy);
+                multiTypeStore(paramType, copy);
             }
             ++lValueCount;
         }
diff --git a/Test/baseResults/spv.multiStruct.comp.out b/Test/baseResults/spv.multiStruct.comp.out
new file mode 100755 (executable)
index 0000000..a2ab8f8
--- /dev/null
@@ -0,0 +1,192 @@
+spv.multiStruct.comp
+Warning, version 450 is not yet complete; most version-specific features are present, but some are missing.
+
+
+Linked compute stage:
+
+
+// Module Version 10000
+// Generated by (magic number): 80001
+// Id's are bound by 97
+
+                              Capability Shader
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint GLCompute 4  "main"
+                              ExecutionMode 4 LocalSize 1 1 1
+                              Source GLSL 450
+                              Name 4  "main"
+                              Name 9  "MyStruct"
+                              MemberName 9(MyStruct) 0  "foo"
+                              MemberName 9(MyStruct) 1  "sb"
+                              Name 11  "t"
+                              Name 13  "MyStruct"
+                              MemberName 13(MyStruct) 0  "foo"
+                              MemberName 13(MyStruct) 1  "sb"
+                              Name 14  "SSBO0"
+                              MemberName 14(SSBO0) 0  "a"
+                              Name 16  "inBuf"
+                              Name 29  "SSBO1"
+                              MemberName 29(SSBO1) 0  "b"
+                              Name 31  "outBuf"
+                              Name 43  "MyStruct"
+                              MemberName 43(MyStruct) 0  "foo"
+                              MemberName 43(MyStruct) 1  "sb"
+                              Name 44  "UBO"
+                              MemberName 44(UBO) 0  "c"
+                              Name 46  "uBuf"
+                              Name 61  "Nested"
+                              MemberName 61(Nested) 0  "f"
+                              MemberName 61(Nested) 1  "S"
+                              Name 63  "n"
+                              Name 64  "Nested"
+                              MemberName 64(Nested) 0  "f"
+                              MemberName 64(Nested) 1  "S"
+                              Name 65  "UBON"
+                              MemberName 65(UBON) 0  "N1"
+                              Name 67  "uBufN"
+                              Name 80  "Nested"
+                              MemberName 80(Nested) 0  "f"
+                              MemberName 80(Nested) 1  "S"
+                              Name 81  "SSBO1N"
+                              MemberName 81(SSBO1N) 0  "N2"
+                              Name 83  "outBufN"
+                              MemberDecorate 13(MyStruct) 0 Offset 0
+                              MemberDecorate 13(MyStruct) 1 Offset 16
+                              MemberDecorate 14(SSBO0) 0 Offset 0
+                              Decorate 14(SSBO0) BufferBlock
+                              Decorate 16(inBuf) DescriptorSet 0
+                              Decorate 16(inBuf) Binding 0
+                              MemberDecorate 29(SSBO1) 0 Offset 0
+                              Decorate 29(SSBO1) BufferBlock
+                              Decorate 31(outBuf) DescriptorSet 0
+                              Decorate 31(outBuf) Binding 1
+                              MemberDecorate 43(MyStruct) 0 Offset 0
+                              MemberDecorate 43(MyStruct) 1 Offset 16
+                              MemberDecorate 44(UBO) 0 Offset 0
+                              Decorate 44(UBO) Block
+                              Decorate 46(uBuf) DescriptorSet 0
+                              Decorate 46(uBuf) Binding 2
+                              MemberDecorate 64(Nested) 0 Offset 0
+                              MemberDecorate 64(Nested) 1 Offset 16
+                              MemberDecorate 65(UBON) 0 Offset 0
+                              Decorate 65(UBON) Block
+                              Decorate 67(uBufN) DescriptorSet 0
+                              Decorate 67(uBufN) Binding 2
+                              MemberDecorate 80(Nested) 0 Offset 0
+                              MemberDecorate 80(Nested) 1 Offset 16
+                              MemberDecorate 81(SSBO1N) 0 Offset 0
+                              Decorate 81(SSBO1N) BufferBlock
+                              Decorate 83(outBufN) DescriptorSet 0
+                              Decorate 83(outBufN) Binding 1
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeFloat 32
+               7:             TypeVector 6(float) 4
+               8:             TypeBool
+     9(MyStruct):             TypeStruct 7(fvec4) 8(bool)
+              10:             TypePointer Function 9(MyStruct)
+              12:             TypeInt 32 0
+    13(MyStruct):             TypeStruct 7(fvec4) 12(int)
+       14(SSBO0):             TypeStruct 13(MyStruct)
+              15:             TypePointer Uniform 14(SSBO0)
+       16(inBuf):     15(ptr) Variable Uniform
+              17:             TypeInt 32 1
+              18:     17(int) Constant 0
+              19:             TypePointer Uniform 13(MyStruct)
+              23:             TypePointer Function 7(fvec4)
+              26:     17(int) Constant 1
+              27:             TypePointer Function 8(bool)
+       29(SSBO1):             TypeStruct 13(MyStruct)
+              30:             TypePointer Uniform 29(SSBO1)
+      31(outBuf):     30(ptr) Variable Uniform
+              35:             TypePointer Uniform 7(fvec4)
+              38:     12(int) Constant 0
+              39:     12(int) Constant 1
+              41:             TypePointer Uniform 12(int)
+    43(MyStruct):             TypeStruct 7(fvec4) 12(int)
+         44(UBO):             TypeStruct 43(MyStruct)
+              45:             TypePointer Uniform 44(UBO)
+        46(uBuf):     45(ptr) Variable Uniform
+              47:             TypePointer Uniform 43(MyStruct)
+      61(Nested):             TypeStruct 6(float) 9(MyStruct)
+              62:             TypePointer Function 61(Nested)
+      64(Nested):             TypeStruct 6(float) 43(MyStruct)
+        65(UBON):             TypeStruct 64(Nested)
+              66:             TypePointer Uniform 65(UBON)
+       67(uBufN):     66(ptr) Variable Uniform
+              68:             TypePointer Uniform 64(Nested)
+              72:             TypePointer Function 6(float)
+      80(Nested):             TypeStruct 6(float) 13(MyStruct)
+      81(SSBO1N):             TypeStruct 80(Nested)
+              82:             TypePointer Uniform 81(SSBO1N)
+     83(outBufN):     82(ptr) Variable Uniform
+              85:             TypePointer Uniform 80(Nested)
+              88:             TypePointer Uniform 6(float)
+         4(main):           2 Function None 3
+               5:             Label
+           11(t):     10(ptr) Variable Function
+           63(n):     62(ptr) Variable Function
+              20:     19(ptr) AccessChain 16(inBuf) 18
+              21:13(MyStruct) Load 20
+              22:    7(fvec4) CompositeExtract 21 0
+              24:     23(ptr) AccessChain 11(t) 18
+                              Store 24 22
+              25:     12(int) CompositeExtract 21 1
+              28:     27(ptr) AccessChain 11(t) 26
+                              Store 28 25
+              32: 9(MyStruct) Load 11(t)
+              33:     19(ptr) AccessChain 31(outBuf) 18
+              34:    7(fvec4) CompositeExtract 32 0
+              36:     35(ptr) AccessChain 33 18
+                              Store 36 34
+              37:     8(bool) CompositeExtract 32 1
+              40:     12(int) Select 37 39 38
+              42:     41(ptr) AccessChain 33 26
+                              Store 42 40
+              48:     47(ptr) AccessChain 46(uBuf) 18
+              49:43(MyStruct) Load 48
+              50:    7(fvec4) CompositeExtract 49 0
+              51:     23(ptr) AccessChain 11(t) 18
+                              Store 51 50
+              52:     12(int) CompositeExtract 49 1
+              53:     27(ptr) AccessChain 11(t) 26
+                              Store 53 52
+              54: 9(MyStruct) Load 11(t)
+              55:     19(ptr) AccessChain 31(outBuf) 18
+              56:    7(fvec4) CompositeExtract 54 0
+              57:     35(ptr) AccessChain 55 18
+                              Store 57 56
+              58:     8(bool) CompositeExtract 54 1
+              59:     12(int) Select 58 39 38
+              60:     41(ptr) AccessChain 55 26
+                              Store 60 59
+              69:     68(ptr) AccessChain 67(uBufN) 18
+              70:  64(Nested) Load 69
+              71:    6(float) CompositeExtract 70 0
+              73:     72(ptr) AccessChain 63(n) 18
+                              Store 73 71
+              74:43(MyStruct) CompositeExtract 70 1
+              75:     10(ptr) AccessChain 63(n) 26
+              76:    7(fvec4) CompositeExtract 74 0
+              77:     23(ptr) AccessChain 75 18
+                              Store 77 76
+              78:     12(int) CompositeExtract 74 1
+              79:     27(ptr) AccessChain 75 26
+                              Store 79 78
+              84:  61(Nested) Load 63(n)
+              86:     85(ptr) AccessChain 83(outBufN) 18
+              87:    6(float) CompositeExtract 84 0
+              89:     88(ptr) AccessChain 86 18
+                              Store 89 87
+              90: 9(MyStruct) CompositeExtract 84 1
+              91:     19(ptr) AccessChain 86 26
+              92:    7(fvec4) CompositeExtract 90 0
+              93:     35(ptr) AccessChain 91 18
+                              Store 93 92
+              94:     8(bool) CompositeExtract 90 1
+              95:     12(int) Select 94 39 38
+              96:     41(ptr) AccessChain 91 26
+                              Store 96 95
+                              Return
+                              FunctionEnd
diff --git a/Test/baseResults/spv.multiStructFuncall.frag.out b/Test/baseResults/spv.multiStructFuncall.frag.out
new file mode 100755 (executable)
index 0000000..dcbcfa0
--- /dev/null
@@ -0,0 +1,120 @@
+spv.multiStructFuncall.frag
+Warning, version 450 is not yet complete; most version-specific features are present, but some are missing.
+
+
+Linked fragment stage:
+
+
+// Module Version 10000
+// Generated by (magic number): 80001
+// Id's are bound by 63
+
+                              Capability Shader
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Fragment 4  "main"
+                              ExecutionMode 4 OriginUpperLeft
+                              Source GLSL 450
+                              Name 4  "main"
+                              Name 9  "S"
+                              MemberName 9(S) 0  "m"
+                              Name 12  "fooConst(struct-S-mf441;"
+                              Name 11  "s"
+                              Name 17  "foo(struct-S-mf441;"
+                              Name 16  "s"
+                              Name 20  "fooOut(struct-S-mf441;"
+                              Name 19  "s"
+                              Name 22  "S"
+                              MemberName 22(S) 0  "m"
+                              Name 23  "blockName"
+                              MemberName 23(blockName) 0  "s1"
+                              Name 25  ""
+                              Name 33  "s2"
+                              Name 36  "S"
+                              MemberName 36(S) 0  "m"
+                              Name 38  "param"
+                              Name 45  "param"
+                              Name 48  "param"
+                              Name 59  "param"
+                              MemberDecorate 22(S) 0 ColMajor
+                              MemberDecorate 22(S) 0 Offset 0
+                              MemberDecorate 22(S) 0 MatrixStride 16
+                              MemberDecorate 23(blockName) 0 Offset 0
+                              Decorate 23(blockName) BufferBlock
+                              Decorate 25 DescriptorSet 0
+                              MemberDecorate 36(S) 0 ColMajor
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeFloat 32
+               7:             TypeVector 6(float) 4
+               8:             TypeMatrix 7(fvec4) 4
+            9(S):             TypeStruct 8
+              10:             TypeFunction 2 9(S)
+              14:             TypePointer Function 9(S)
+              15:             TypeFunction 2 14(ptr)
+           22(S):             TypeStruct 8
+   23(blockName):             TypeStruct 22(S)
+              24:             TypePointer Uniform 23(blockName)
+              25:     24(ptr) Variable Uniform
+              26:             TypeInt 32 1
+              27:     26(int) Constant 0
+              28:             TypePointer Uniform 22(S)
+              32:             TypePointer Private 9(S)
+          33(s2):     32(ptr) Variable Private
+           36(S):             TypeStruct 8
+              37:             TypePointer Function 36(S)
+              42:             TypePointer Function 8
+              57:             TypePointer Uniform 8
+         4(main):           2 Function None 3
+               5:             Label
+       38(param):     37(ptr) Variable Function
+       45(param):     14(ptr) Variable Function
+       48(param):     37(ptr) Variable Function
+       59(param):     14(ptr) Variable Function
+              29:     28(ptr) AccessChain 25 27
+              30:       22(S) Load 29
+              31:           2 FunctionCall 12(fooConst(struct-S-mf441;) 30
+              34:        9(S) Load 33(s2)
+              35:           2 FunctionCall 12(fooConst(struct-S-mf441;) 34
+              39:     28(ptr) AccessChain 25 27
+              40:       22(S) Load 39
+              41:           8 CompositeExtract 40 0
+              43:     42(ptr) AccessChain 38(param) 27
+                              Store 43 41
+              44:           2 FunctionCall 17(foo(struct-S-mf441;) 38(param)
+              46:        9(S) Load 33(s2)
+                              Store 45(param) 46
+              47:           2 FunctionCall 17(foo(struct-S-mf441;) 45(param)
+              49:     28(ptr) AccessChain 25 27
+              50:       22(S) Load 49
+              51:           8 CompositeExtract 50 0
+              52:     42(ptr) AccessChain 48(param) 27
+                              Store 52 51
+              53:           2 FunctionCall 20(fooOut(struct-S-mf441;) 48(param)
+              54:       36(S) Load 48(param)
+              55:     28(ptr) AccessChain 25 27
+              56:           8 CompositeExtract 54 0
+              58:     57(ptr) AccessChain 55 27
+                              Store 58 56
+              60:        9(S) Load 33(s2)
+                              Store 59(param) 60
+              61:           2 FunctionCall 20(fooOut(struct-S-mf441;) 59(param)
+              62:        9(S) Load 59(param)
+                              Store 33(s2) 62
+                              Return
+                              FunctionEnd
+12(fooConst(struct-S-mf441;):           2 Function None 10
+           11(s):        9(S) FunctionParameter
+              13:             Label
+                              Return
+                              FunctionEnd
+17(foo(struct-S-mf441;):           2 Function None 15
+           16(s):     14(ptr) FunctionParameter
+              18:             Label
+                              Return
+                              FunctionEnd
+20(fooOut(struct-S-mf441;):           2 Function None 15
+           19(s):     14(ptr) FunctionParameter
+              21:             Label
+                              Return
+                              FunctionEnd
diff --git a/Test/spv.multiStruct.comp b/Test/spv.multiStruct.comp
new file mode 100644 (file)
index 0000000..de27ccb
--- /dev/null
@@ -0,0 +1,48 @@
+#version 450 core\r
+\r
+struct MyStruct\r
+{\r
+    vec4 foo;\r
+    bool sb;\r
+};\r
+\r
+layout(binding = 0, std430) buffer SSBO0\r
+{\r
+    MyStruct a;\r
+} inBuf;\r
+\r
+layout(binding = 1, std430) buffer SSBO1\r
+{\r
+    MyStruct b;\r
+} outBuf;\r
+\r
+layout(binding = 2, std140) uniform UBO\r
+{\r
+    MyStruct c;\r
+} uBuf;\r
+\r
+struct Nested {\r
+    float f;\r
+    MyStruct S;\r
+};\r
+\r
+layout(binding = 2, std140) uniform UBON\r
+{\r
+    Nested N1;\r
+} uBufN;\r
+\r
+layout(binding = 1, std430) buffer SSBO1N\r
+{\r
+    Nested N2;\r
+} outBufN;\r
+\r
+void main()\r
+{\r
+    MyStruct t = inBuf.a;\r
+    outBuf.b = t;\r
+    t = uBuf.c;\r
+    outBuf.b = t;\r
+\r
+    Nested n = uBufN.N1;\r
+    outBufN.N2 = n;\r
+}\r
diff --git a/Test/spv.multiStructFuncall.frag b/Test/spv.multiStructFuncall.frag
new file mode 100755 (executable)
index 0000000..7f9968d
--- /dev/null
@@ -0,0 +1,21 @@
+#version 450\r
+\r
+struct S { mat4 m; };\r
+buffer blockName { S s1; };  // need an S with decoration\r
+S s2;                        // no decorations on S\r
+\r
+void fooConst(const in S s) { }\r
+void foo(in S s) { }\r
+void fooOut(inout S s) { }\r
+\r
+void main()\r
+{\r
+  fooConst(s1);\r
+  fooConst(s2);\r
+\r
+  foo(s1);\r
+  foo(s2);\r
+\r
+  fooOut(s1);\r
+  fooOut(s2);\r
+}
\ No newline at end of file
index 91b40ad..eac0393 100644 (file)
@@ -2,5 +2,5 @@
 // For the version, it uses the latest git tag followed by the number of commits.
 // For the date, it uses the current date (when then script is run).
 
-#define GLSLANG_REVISION "Overload400-PrecQual.1456"
-#define GLSLANG_DATE "01-Sep-2016"
+#define GLSLANG_REVISION "Overload400-PrecQual.1460"
+#define GLSLANG_DATE "02-Sep-2016"
index a8f3dd8..45fed04 100644 (file)
@@ -164,6 +164,8 @@ INSTANTIATE_TEST_CASE_P(
         "spv.matrix2.frag",
         "spv.memoryQualifier.frag",
         "spv.merge-unreachable.frag",
+        "spv.multiStruct.comp",
+        "spv.multiStructFuncall.frag",
         "spv.newTexture.frag",
         "spv.noDeadDecorations.vert",
         "spv.nonSquare.vert",