SPV: recursively propagate row/col majorness through nested structures.

This includes doing structure uniqueness modulo majorness, for shared nested structures.
diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp
index ca6a577..fb4e115 100755
--- a/SPIRV/GlslangToSpv.cpp
+++ b/SPIRV/GlslangToSpv.cpp
@@ -91,11 +91,11 @@
     spv::Id createSpvVariable(const glslang::TIntermSymbol*);
     spv::Id getSampledType(const glslang::TSampler&);
     spv::Id convertGlslangToSpvType(const glslang::TType& type);
-    spv::Id convertGlslangToSpvType(const glslang::TType& type, glslang::TLayoutPacking);
+    spv::Id convertGlslangToSpvType(const glslang::TType& type, glslang::TLayoutPacking, glslang::TLayoutMatrix);
     glslang::TLayoutPacking getExplicitLayout(const glslang::TType& type) const;
-    int getArrayStride(const glslang::TType& arrayType, glslang::TLayoutPacking);
-    int getMatrixStride(const glslang::TType& matrixType, glslang::TLayoutPacking);
-    void updateMemberOffset(const glslang::TType& structType, const glslang::TType& memberType, int& currentOffset, int& nextOffset, glslang::TLayoutPacking);
+    int getArrayStride(const glslang::TType& arrayType, glslang::TLayoutPacking, glslang::TLayoutMatrix);
+    int getMatrixStride(const glslang::TType& matrixType, glslang::TLayoutPacking, glslang::TLayoutMatrix);
+    void updateMemberOffset(const glslang::TType& structType, const glslang::TType& memberType, int& currentOffset, int& nextOffset, glslang::TLayoutPacking, glslang::TLayoutMatrix);
 
     bool isShaderEntrypoint(const glslang::TIntermAggregate* node);
     void makeFunctions(const glslang::TIntermSequence&);
@@ -140,7 +140,7 @@
     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_map<std::string, spv::Function*> functionMap;
-    std::unordered_map<const glslang::TTypeList*, spv::Id> structMap[glslang::ElpStd430 + 1];
+    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)
     std::stack<bool> breakForLoop;  // false means break for switch
     std::stack<glslang::TIntermTyped*> loopTerminal;  // code from the last part of a for loop: for(...; ...; terminal), needed for e.g., continue };
@@ -256,14 +256,17 @@
 }
 
 // Translate glslang type to SPIR-V layout decorations.
-spv::Decoration TranslateLayoutDecoration(const glslang::TType& type)
+spv::Decoration TranslateLayoutDecoration(const glslang::TType& type, glslang::TLayoutMatrix matrixLayout)
 {
     if (type.isMatrix()) {
-        switch (type.getQualifier().layoutMatrix) {
+        switch (matrixLayout) {
         case glslang::ElmRowMajor:
             return spv::DecorationRowMajor;
-        default:
+        case glslang::ElmColumnMajor:
             return spv::DecorationColMajor;
+        default:
+            // opaque layouts don't need a majorness
+            return (spv::Decoration)spv::BadValue;
         }
     } else {
         switch (type.getBasicType()) {
@@ -1451,16 +1454,17 @@
     }
 }
 
-// Convert from a glslang type to an SPV type, by calling into
-// recursive version of this function.
+// Convert from a glslang type to an SPV type, by calling into a
+// recursive version of this function. This establishes the inherited
+// layout state rooted from the top-level type.
 spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& type)
 {
-    return convertGlslangToSpvType(type, getExplicitLayout(type));
+    return convertGlslangToSpvType(type, getExplicitLayout(type), type.getQualifier().layoutMatrix);
 }
 
 // Do full recursive conversion of an arbitrary glslang type to a SPIR-V Id.
 // explicitLayout can be kept the same throughout the heirarchical recursive walk.
-spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& type, glslang::TLayoutPacking explicitLayout)
+spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& type, glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout)
 {
     spv::Id spvType = 0;
 
@@ -1505,7 +1509,7 @@
             // If we've seen this struct type, return it
             const glslang::TTypeList* glslangStruct = type.getStruct();
             std::vector<spv::Id> structFields;
-            spvType = structMap[explicitLayout][glslangStruct];
+            spvType = structMap[explicitLayout][matrixLayout][glslangStruct];
             if (spvType)
                 break;
 
@@ -1524,13 +1528,16 @@
                 } else {
                     if (type.getBasicType() == glslang::EbtBlock)
                         memberRemapper[glslangStruct][i] = i - memberDelta;
-                    structFields.push_back(convertGlslangToSpvType(glslangType, explicitLayout));
+                    // modify just the children's view of matrix layout, if there is one for this member
+                    glslang::TLayoutMatrix subMatrixLayout = glslangType.getQualifier().layoutMatrix;
+                    structFields.push_back(convertGlslangToSpvType(glslangType, explicitLayout,
+                                           subMatrixLayout != glslang::ElmNone ? subMatrixLayout : matrixLayout));
                 }
             }
 
             // Make the SPIR-V type
             spvType = builder.makeStructType(structFields, type.getTypeName().c_str());
-            structMap[explicitLayout][glslangStruct] = spvType;
+            structMap[explicitLayout][matrixLayout][glslangStruct] = spvType;
 
             // Name and decorate the non-hidden members
             int offset = -1;
@@ -1539,10 +1546,16 @@
                 int member = i;
                 if (type.getBasicType() == glslang::EbtBlock)
                     member = memberRemapper[glslangStruct][i];
+
+                // modify just the children's view of matrix layout, if there is one for this member
+                glslang::TLayoutMatrix subMatrixLayout = glslangType.getQualifier().layoutMatrix;
+                if (subMatrixLayout == glslang::ElmNone)
+                    subMatrixLayout = matrixLayout;
+
                 // using -1 above to indicate a hidden member
                 if (member >= 0) {
                     builder.addMemberName(spvType, member, glslangType.getFieldName().c_str());
-                    addMemberDecoration(spvType, member, TranslateLayoutDecoration(glslangType));
+                    addMemberDecoration(spvType, member, TranslateLayoutDecoration(glslangType, subMatrixLayout));
                     addMemberDecoration(spvType, member, TranslatePrecisionDecoration(glslangType));
                     addMemberDecoration(spvType, member, TranslateInterpolationDecoration(glslangType));
                     addMemberDecoration(spvType, member, TranslateInvariantDecoration(glslangType));
@@ -1555,14 +1568,14 @@
                     else if (explicitLayout != glslang::ElpNone) {
                         // figure out what to do with offset, which is accumulating
                         int nextOffset;
-                        updateMemberOffset(type, glslangType, offset, nextOffset, explicitLayout);
+                        updateMemberOffset(type, glslangType, offset, nextOffset, explicitLayout, subMatrixLayout);
                         if (offset >= 0)
                             builder.addMemberDecoration(spvType, member, spv::DecorationOffset, offset);
                         offset = nextOffset;
                     }
 
                     if (glslangType.isMatrix() && explicitLayout != glslang::ElpNone)
-                        builder.addMemberDecoration(spvType, member, spv::DecorationMatrixStride, getMatrixStride(glslangType, explicitLayout));
+                        builder.addMemberDecoration(spvType, member, spv::DecorationMatrixStride, getMatrixStride(glslangType, explicitLayout, subMatrixLayout));
 
                     // built-in variable decorations
                     spv::BuiltIn builtIn = TranslateBuiltInDecoration(glslangType.getQualifier().builtIn);
@@ -1572,7 +1585,7 @@
             }
 
             // Decorate the structure
-            addDecoration(spvType, TranslateLayoutDecoration(type));
+            addDecoration(spvType, TranslateLayoutDecoration(type, matrixLayout));
             addDecoration(spvType, TranslateBlockDecoration(type));
             if (type.getQualifier().hasStream())
                 builder.addDecoration(spvType, spv::DecorationStream, type.getQualifier().layoutStream);
@@ -1620,7 +1633,7 @@
         // except for the very top if it is an array of blocks; that array is
         // not laid out in memory in a way needing a stride.
         if (explicitLayout && type.getBasicType() != glslang::EbtBlock)
-            builder.addDecoration(spvType, spv::DecorationArrayStride, getArrayStride(type, explicitLayout));
+            builder.addDecoration(spvType, spv::DecorationArrayStride, getArrayStride(type, explicitLayout, matrixLayout));
     }
 
     return spvType;
@@ -1651,14 +1664,14 @@
 }
 
 // Given an array type, returns the integer stride required for that array
-int TGlslangToSpvTraverser::getArrayStride(const glslang::TType& arrayType, glslang::TLayoutPacking explicitLayout)
+int TGlslangToSpvTraverser::getArrayStride(const glslang::TType& arrayType, glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout)
 {
     int size;
-    int stride = glslangIntermediate->getBaseAlignment(arrayType, size, explicitLayout == glslang::ElpStd140);
+    int stride = glslangIntermediate->getBaseAlignment(arrayType, size, explicitLayout == glslang::ElpStd140, matrixLayout == glslang::ElmRowMajor);
     if (arrayType.isMatrix()) {
         // GLSL strides are set to alignments of the matrix flattened to individual rows/cols,
         // but SPV needs an array stride for the whole matrix, not the rows/cols
-        if (arrayType.getQualifier().layoutMatrix == glslang::ElmRowMajor)
+        if (matrixLayout == glslang::ElmRowMajor)
             stride *= arrayType.getMatrixRows();
         else
             stride *= arrayType.getMatrixCols();
@@ -1669,10 +1682,10 @@
 
 // Given a matrix type, returns the integer stride required for that matrix
 // when used as a member of an interface block
-int TGlslangToSpvTraverser::getMatrixStride(const glslang::TType& matrixType, glslang::TLayoutPacking explicitLayout)
+int TGlslangToSpvTraverser::getMatrixStride(const glslang::TType& matrixType, glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout)
 {
     int size;
-    return glslangIntermediate->getBaseAlignment(matrixType, size, explicitLayout == glslang::ElpStd140);
+    return glslangIntermediate->getBaseAlignment(matrixType, size, explicitLayout == glslang::ElpStd140, matrixLayout == glslang::ElmRowMajor);
 }
 
 // Given a member type of a struct, realign the current offset for it, and compute
@@ -1682,7 +1695,7 @@
 // the migration of data from nextOffset -> currentOffset.  It should be -1 on the first call.
 // -1 means a non-forced member offset (no decoration needed).
 void TGlslangToSpvTraverser::updateMemberOffset(const glslang::TType& structType, const glslang::TType& memberType, int& currentOffset, int& nextOffset,
-                                                glslang::TLayoutPacking explicitLayout)
+                                                glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout)
 {
     // this will get a positive value when deemed necessary
     nextOffset = -1;
@@ -1711,7 +1724,7 @@
     // but possibly not yet correctly aligned.
 
     int memberSize;
-    int memberAlignment = glslangIntermediate->getBaseAlignment(memberType, memberSize, explicitLayout == glslang::ElpStd140);
+    int memberAlignment = glslangIntermediate->getBaseAlignment(memberType, memberSize, explicitLayout == glslang::ElpStd140, matrixLayout == glslang::ElmRowMajor);
     glslang::RoundToPow2(currentOffset, memberAlignment);
     nextOffset = currentOffset + memberSize;
 }
diff --git a/Test/baseResults/spv.layoutNested.vert.out b/Test/baseResults/spv.layoutNested.vert.out
index 007c029..98e4ae6 100644
--- a/Test/baseResults/spv.layoutNested.vert.out
+++ b/Test/baseResults/spv.layoutNested.vert.out
@@ -7,132 +7,217 @@
 
 // Module Version 10000
 // Generated by (magic number): 80001
-// Id's are bound by 54
+// Id's are bound by 63
 
                               Capability Shader
                1:             ExtInstImport  "GLSL.std.450"
                               MemoryModel Logical GLSL450
-                              EntryPoint Vertex 4  "main" 38 52 53
+                              EntryPoint Vertex 4  "main" 61 62
                               Source GLSL 450
                               Name 4  "main"
-                              Name 13  "S"
-                              MemberName 13(S) 0  "a"
-                              MemberName 13(S) 1  "b"
-                              MemberName 13(S) 2  "c"
-                              Name 15  "s"
-                              Name 18  "S"
-                              MemberName 18(S) 0  "a"
-                              MemberName 18(S) 1  "b"
-                              MemberName 18(S) 2  "c"
-                              Name 23  "Block140"
-                              MemberName 23(Block140) 0  "u"
-                              MemberName 23(Block140) 1  "s"
-                              MemberName 23(Block140) 2  "v"
-                              Name 25  "inst140"
-                              Name 36  "gl_PerVertex"
-                              MemberName 36(gl_PerVertex) 0  "gl_Position"
-                              MemberName 36(gl_PerVertex) 1  "gl_PointSize"
-                              MemberName 36(gl_PerVertex) 2  "gl_ClipDistance"
-                              MemberName 36(gl_PerVertex) 3  "gl_CullDistance"
-                              Name 38  ""
-                              Name 45  "S"
-                              MemberName 45(S) 0  "a"
-                              MemberName 45(S) 1  "b"
-                              MemberName 45(S) 2  "c"
-                              Name 48  "Block430"
-                              MemberName 48(Block430) 0  "u"
-                              MemberName 48(Block430) 1  "s"
-                              MemberName 48(Block430) 2  "v"
-                              Name 50  "inst430"
-                              Name 52  "gl_VertexID"
-                              Name 53  "gl_InstanceID"
-                              MemberDecorate 13(S) 1 ColMajor
-                              Decorate 12 ArrayStride 32
-                              MemberDecorate 18(S) 0 Offset 0
-                              MemberDecorate 18(S) 1 ColMajor
-                              MemberDecorate 18(S) 1 Offset 16
-                              MemberDecorate 18(S) 1 MatrixStride 16
-                              MemberDecorate 18(S) 2 Offset 144
-                              Decorate 22 ArrayStride 16
-                              MemberDecorate 23(Block140) 0 Offset 0
-                              MemberDecorate 23(Block140) 1 Offset 16
-                              MemberDecorate 23(Block140) 2 Offset 976
-                              Decorate 23(Block140) Block
-                              Decorate 25(inst140) DescriptorSet 0
-                              Decorate 25(inst140) Binding 0
-                              MemberDecorate 36(gl_PerVertex) 0 BuiltIn Position
-                              MemberDecorate 36(gl_PerVertex) 1 BuiltIn PointSize
-                              MemberDecorate 36(gl_PerVertex) 2 BuiltIn ClipDistance
-                              MemberDecorate 36(gl_PerVertex) 3 BuiltIn CullDistance
-                              Decorate 36(gl_PerVertex) Block
-                              Decorate 12 ArrayStride 16
-                              MemberDecorate 45(S) 0 Offset 0
-                              MemberDecorate 45(S) 1 ColMajor
-                              MemberDecorate 45(S) 1 Offset 16
-                              MemberDecorate 45(S) 1 MatrixStride 8
-                              MemberDecorate 45(S) 2 Offset 80
-                              Decorate 47 ArrayStride 16
-                              MemberDecorate 48(Block430) 0 Offset 0
-                              MemberDecorate 48(Block430) 1 Offset 16
-                              MemberDecorate 48(Block430) 2 Offset 592
-                              Decorate 48(Block430) BufferBlock
-                              Decorate 50(inst430) DescriptorSet 0
-                              Decorate 50(inst430) Binding 1
-                              Decorate 52(gl_VertexID) BuiltIn VertexId
-                              Decorate 53(gl_InstanceID) BuiltIn InstanceId
+                              Name 14  "S"
+                              MemberName 14(S) 0  "a"
+                              MemberName 14(S) 1  "b"
+                              MemberName 14(S) 2  "c"
+                              Name 19  "Block140"
+                              MemberName 19(Block140) 0  "u"
+                              MemberName 19(Block140) 1  "s"
+                              MemberName 19(Block140) 2  "v"
+                              Name 21  "inst140"
+                              Name 22  "S"
+                              MemberName 22(S) 0  "a"
+                              MemberName 22(S) 1  "b"
+                              MemberName 22(S) 2  "c"
+                              Name 25  "Block430"
+                              MemberName 25(Block430) 0  "u"
+                              MemberName 25(Block430) 1  "s"
+                              MemberName 25(Block430) 2  "v"
+                              Name 27  "inst430"
+                              Name 28  "S"
+                              MemberName 28(S) 0  "a"
+                              MemberName 28(S) 1  "b"
+                              MemberName 28(S) 2  "c"
+                              Name 30  "s"
+                              Name 31  "T"
+                              MemberName 31(T) 0  "m"
+                              MemberName 31(T) 1  "a"
+                              Name 33  "t"
+                              Name 34  "T"
+                              MemberName 34(T) 0  "m"
+                              MemberName 34(T) 1  "a"
+                              Name 35  "Nestor"
+                              MemberName 35(Nestor) 0  "nestorT"
+                              Name 36  "Bt1"
+                              MemberName 36(Bt1) 0  "nt"
+                              Name 38  "Btn1"
+                              Name 39  "T"
+                              MemberName 39(T) 0  "m"
+                              MemberName 39(T) 1  "a"
+                              Name 40  "Nestor"
+                              MemberName 40(Nestor) 0  "nestorT"
+                              Name 41  "Bt2"
+                              MemberName 41(Bt2) 0  "nt"
+                              Name 43  "Btn2"
+                              Name 44  "Bt3"
+                              MemberName 44(Bt3) 0  "ntcol"
+                              MemberName 44(Bt3) 1  "ntrow"
+                              Name 46  "Btn3"
+                              Name 47  "T"
+                              MemberName 47(T) 0  "m"
+                              MemberName 47(T) 1  "a"
+                              Name 48  "Nestor"
+                              MemberName 48(Nestor) 0  "nestorT"
+                              Name 49  "bBt1"
+                              MemberName 49(bBt1) 0  "nt"
+                              Name 51  "bBtn1"
+                              Name 52  "T"
+                              MemberName 52(T) 0  "m"
+                              MemberName 52(T) 1  "a"
+                              Name 53  "Nestor"
+                              MemberName 53(Nestor) 0  "nestorT"
+                              Name 54  "bBt2"
+                              MemberName 54(bBt2) 0  "nt"
+                              Name 56  "bBtn2"
+                              Name 57  "bBt3"
+                              MemberName 57(bBt3) 0  "ntcol"
+                              MemberName 57(bBt3) 1  "ntrow"
+                              Name 59  "bBtn3"
+                              Name 61  "gl_VertexID"
+                              Name 62  "gl_InstanceID"
+                              Decorate 13 ArrayStride 32
+                              MemberDecorate 14(S) 0 Offset 0
+                              MemberDecorate 14(S) 1 ColMajor
+                              MemberDecorate 14(S) 1 Offset 16
+                              MemberDecorate 14(S) 1 MatrixStride 16
+                              MemberDecorate 14(S) 2 Offset 144
+                              Decorate 18 ArrayStride 16
+                              MemberDecorate 19(Block140) 0 Offset 0
+                              MemberDecorate 19(Block140) 1 Offset 16
+                              MemberDecorate 19(Block140) 2 Offset 976
+                              Decorate 19(Block140) Block
+                              Decorate 21(inst140) DescriptorSet 0
+                              Decorate 21(inst140) Binding 0
+                              Decorate 13 ArrayStride 16
+                              MemberDecorate 22(S) 0 Offset 0
+                              MemberDecorate 22(S) 1 ColMajor
+                              MemberDecorate 22(S) 1 Offset 16
+                              MemberDecorate 22(S) 1 MatrixStride 8
+                              MemberDecorate 22(S) 2 Offset 80
+                              Decorate 24 ArrayStride 16
+                              MemberDecorate 25(Block430) 0 Offset 0
+                              MemberDecorate 25(Block430) 1 Offset 16
+                              MemberDecorate 25(Block430) 2 Offset 592
+                              Decorate 25(Block430) BufferBlock
+                              Decorate 27(inst430) DescriptorSet 0
+                              Decorate 27(inst430) Binding 1
+                              MemberDecorate 34(T) 0 RowMajor
+                              MemberDecorate 34(T) 0 Offset 0
+                              MemberDecorate 34(T) 0 MatrixStride 16
+                              MemberDecorate 34(T) 1 Offset 32
+                              MemberDecorate 35(Nestor) 0 Offset 0
+                              MemberDecorate 36(Bt1) 0 Offset 0
+                              Decorate 36(Bt1) Block
+                              Decorate 38(Btn1) DescriptorSet 1
+                              Decorate 38(Btn1) Binding 0
+                              MemberDecorate 39(T) 0 ColMajor
+                              MemberDecorate 39(T) 0 Offset 0
+                              MemberDecorate 39(T) 0 MatrixStride 16
+                              MemberDecorate 39(T) 1 Offset 32
+                              MemberDecorate 40(Nestor) 0 Offset 0
+                              MemberDecorate 41(Bt2) 0 Offset 0
+                              Decorate 41(Bt2) Block
+                              Decorate 43(Btn2) DescriptorSet 1
+                              Decorate 43(Btn2) Binding 0
+                              MemberDecorate 44(Bt3) 0 Offset 0
+                              MemberDecorate 44(Bt3) 1 Offset 48
+                              Decorate 44(Bt3) Block
+                              Decorate 46(Btn3) DescriptorSet 1
+                              Decorate 46(Btn3) Binding 0
+                              MemberDecorate 47(T) 0 RowMajor
+                              MemberDecorate 47(T) 0 Offset 0
+                              MemberDecorate 47(T) 0 MatrixStride 8
+                              MemberDecorate 47(T) 1 Offset 16
+                              MemberDecorate 48(Nestor) 0 Offset 0
+                              MemberDecorate 49(bBt1) 0 Offset 0
+                              Decorate 49(bBt1) BufferBlock
+                              Decorate 51(bBtn1) DescriptorSet 1
+                              Decorate 51(bBtn1) Binding 0
+                              MemberDecorate 52(T) 0 ColMajor
+                              MemberDecorate 52(T) 0 Offset 0
+                              MemberDecorate 52(T) 0 MatrixStride 8
+                              MemberDecorate 52(T) 1 Offset 16
+                              MemberDecorate 53(Nestor) 0 Offset 0
+                              MemberDecorate 54(bBt2) 0 Offset 0
+                              Decorate 54(bBt2) BufferBlock
+                              Decorate 56(bBtn2) DescriptorSet 1
+                              Decorate 56(bBtn2) Binding 0
+                              MemberDecorate 57(bBt3) 0 Offset 0
+                              MemberDecorate 57(bBt3) 1 Offset 24
+                              Decorate 57(bBt3) BufferBlock
+                              Decorate 59(bBtn3) DescriptorSet 1
+                              Decorate 59(bBtn3) Binding 0
+                              Decorate 61(gl_VertexID) BuiltIn VertexId
+                              Decorate 62(gl_InstanceID) BuiltIn InstanceId
                2:             TypeVoid
                3:             TypeFunction 2
-               6:             TypeInt 32 0
-               7:             TypeVector 6(int) 3
-               8:             TypeFloat 32
-               9:             TypeVector 8(float) 2
-              10:             TypeMatrix 9(fvec2) 2
-              11:      6(int) Constant 4
-              12:             TypeArray 10 11
-           13(S):             TypeStruct 7(ivec3) 12 6(int)
-              14:             TypePointer Private 13(S)
-           15(s):     14(ptr) Variable Private
-              16:             TypeInt 32 1
-              17:     16(int) Constant 2
-           18(S):             TypeStruct 7(ivec3) 12 6(int)
-              19:      6(int) Constant 3
-              20:             TypeArray 18(S) 19
-              21:      6(int) Constant 2
-              22:             TypeArray 20 21
-    23(Block140):             TypeStruct 16(int) 22 9(fvec2)
-              24:             TypePointer Uniform 23(Block140)
-     25(inst140):     24(ptr) Variable Uniform
-              26:     16(int) Constant 0
-              27:             TypePointer Uniform 16(int)
-              31:             TypePointer Private 6(int)
-              33:             TypeVector 8(float) 4
-              34:      6(int) Constant 1
-              35:             TypeArray 8(float) 34
-36(gl_PerVertex):             TypeStruct 33(fvec4) 8(float) 35 35
-              37:             TypePointer Output 36(gl_PerVertex)
-              38:     37(ptr) Variable Output
-              43:             TypePointer Output 33(fvec4)
-           45(S):             TypeStruct 7(ivec3) 12 6(int)
-              46:             TypeArray 45(S) 19
-              47:             TypeArray 46 21
-    48(Block430):             TypeStruct 16(int) 47 9(fvec2)
-              49:             TypePointer Uniform 48(Block430)
-     50(inst430):     49(ptr) Variable Uniform
-              51:             TypePointer Input 16(int)
- 52(gl_VertexID):     51(ptr) Variable Input
-53(gl_InstanceID):     51(ptr) Variable Input
+               6:             TypeInt 32 1
+               7:             TypeInt 32 0
+               8:             TypeVector 7(int) 3
+               9:             TypeFloat 32
+              10:             TypeVector 9(float) 2
+              11:             TypeMatrix 10(fvec2) 2
+              12:      7(int) Constant 4
+              13:             TypeArray 11 12
+           14(S):             TypeStruct 8(ivec3) 13 7(int)
+              15:      7(int) Constant 3
+              16:             TypeArray 14(S) 15
+              17:      7(int) Constant 2
+              18:             TypeArray 16 17
+    19(Block140):             TypeStruct 6(int) 18 10(fvec2)
+              20:             TypePointer Uniform 19(Block140)
+     21(inst140):     20(ptr) Variable Uniform
+           22(S):             TypeStruct 8(ivec3) 13 7(int)
+              23:             TypeArray 22(S) 15
+              24:             TypeArray 23 17
+    25(Block430):             TypeStruct 6(int) 24 10(fvec2)
+              26:             TypePointer Uniform 25(Block430)
+     27(inst430):     26(ptr) Variable Uniform
+           28(S):             TypeStruct 8(ivec3) 13 7(int)
+              29:             TypePointer Private 28(S)
+           30(s):     29(ptr) Variable Private
+           31(T):             TypeStruct 11 6(int)
+              32:             TypePointer Private 31(T)
+           33(t):     32(ptr) Variable Private
+           34(T):             TypeStruct 11 6(int)
+      35(Nestor):             TypeStruct 34(T)
+         36(Bt1):             TypeStruct 35(Nestor)
+              37:             TypePointer Uniform 36(Bt1)
+        38(Btn1):     37(ptr) Variable Uniform
+           39(T):             TypeStruct 11 6(int)
+      40(Nestor):             TypeStruct 39(T)
+         41(Bt2):             TypeStruct 40(Nestor)
+              42:             TypePointer Uniform 41(Bt2)
+        43(Btn2):     42(ptr) Variable Uniform
+         44(Bt3):             TypeStruct 40(Nestor) 35(Nestor)
+              45:             TypePointer Uniform 44(Bt3)
+        46(Btn3):     45(ptr) Variable Uniform
+           47(T):             TypeStruct 11 6(int)
+      48(Nestor):             TypeStruct 47(T)
+        49(bBt1):             TypeStruct 48(Nestor)
+              50:             TypePointer Uniform 49(bBt1)
+       51(bBtn1):     50(ptr) Variable Uniform
+           52(T):             TypeStruct 11 6(int)
+      53(Nestor):             TypeStruct 52(T)
+        54(bBt2):             TypeStruct 53(Nestor)
+              55:             TypePointer Uniform 54(bBt2)
+       56(bBtn2):     55(ptr) Variable Uniform
+        57(bBt3):             TypeStruct 48(Nestor) 53(Nestor)
+              58:             TypePointer Uniform 57(bBt3)
+       59(bBtn3):     58(ptr) Variable Uniform
+              60:             TypePointer Input 6(int)
+ 61(gl_VertexID):     60(ptr) Variable Input
+62(gl_InstanceID):     60(ptr) Variable Input
          4(main):           2 Function None 3
                5:             Label
-              28:     27(ptr) AccessChain 25(inst140) 26
-              29:     16(int) Load 28
-              30:      6(int) Bitcast 29
-              32:     31(ptr) AccessChain 15(s) 17
-                              Store 32 30
-              39:     31(ptr) AccessChain 15(s) 17
-              40:      6(int) Load 39
-              41:    8(float) ConvertUToF 40
-              42:   33(fvec4) CompositeConstruct 41 41 41 41
-              44:     43(ptr) AccessChain 38 26
-                              Store 44 42
                               Return
                               FunctionEnd
diff --git a/Test/spv.layoutNested.vert b/Test/spv.layoutNested.vert
index aa403fc..ac44cbe 100644
--- a/Test/spv.layoutNested.vert
+++ b/Test/spv.layoutNested.vert
@@ -1,6 +1,6 @@
 #version 450

 

-// should get 3 SPV types: no layout, 140, and 430

+// should get 3 SPV types for S: no layout, 140, and 430

 struct S

 {

 	highp uvec3 a;

@@ -24,8 +24,50 @@
 

 S s;

 

+// should get 5 SPV types for T: no layout, 140/row, 140/col, 430/row, and 430/col

+struct T {

+    mat2 m;

+    int a;

+};

+

+T t;

+

+struct Nestor {

+    T nestorT;

+};

+

+layout(set = 1, binding = 0, std140) uniform Bt1

+{

+    layout(row_major) Nestor nt;

+} Btn1;

+

+layout(set = 1, binding = 0, std140) uniform Bt2

+{

+    layout(column_major) Nestor nt;

+} Btn2;

+

+layout(row_major, set = 1, binding = 0, std140) uniform Bt3

+{

+    layout(column_major) Nestor ntcol;

+    Nestor ntrow;                         // should be row major decoration version of Nestor

+} Btn3;

+

+layout(set = 1, binding = 0, std430) buffer bBt1

+{

+    layout(row_major) Nestor nt;

+} bBtn1;

+

+layout(set = 1, binding = 0, std430) buffer bBt2

+{

+    layout(column_major) Nestor nt;

+} bBtn2;

+

+layout(set = 1, binding = 0, std430) buffer bBt3

+{

+    layout(row_major) Nestor ntcol;

+    Nestor ntrow;                         // should be col major decoration version of Nestor

+} bBtn3;

+

 void main()

 {

-    s.c = inst140.u;

-    gl_Position = vec4(s.c);

 }

diff --git a/glslang/Include/Types.h b/glslang/Include/Types.h
index 06e8449..df606ff 100644
--- a/glslang/Include/Types.h
+++ b/glslang/Include/Types.h
@@ -186,15 +186,15 @@
     ElpShared,      // default, but different than saying nothing
     ElpStd140,
     ElpStd430,
-    ElpPacked
-    // If expanding, see bitfield width below
+    ElpPacked,
+    ElpCount        // If expanding, see bitfield width below
 };
 
 enum TLayoutMatrix {
     ElmNone,
     ElmRowMajor,
-    ElmColumnMajor  // default, but different than saying nothing
-    // If expanding, see bitfield width below
+    ElmColumnMajor, // default, but different than saying nothing
+    ElmCount        // If expanding, see bitfield width below
 };
 
 // Union of geometry shader and tessellation shader geometry types.
diff --git a/glslang/Include/revision.h b/glslang/Include/revision.h
index 42a916c..2b4d425 100644
--- a/glslang/Include/revision.h
+++ b/glslang/Include/revision.h
@@ -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 "SPIRV99.860"
-#define GLSLANG_DATE "19-Dec-2015"
+#define GLSLANG_REVISION "SPIRV99.861"
+#define GLSLANG_DATE "20-Dec-2015"
diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp
index 72e6010..9ed4f86 100644
--- a/glslang/MachineIndependent/ParseHelper.cpp
+++ b/glslang/MachineIndependent/ParseHelper.cpp
@@ -5345,8 +5345,11 @@
         const TSourceLoc& memberLoc = typeList[member].loc;
 
         // "When align is applied to an array, it effects only the start of the array, not the array's internal stride."
-        
-        int memberAlignment = intermediate.getBaseAlignment(*typeList[member].type, memberSize, qualifier.layoutPacking == ElpStd140);
+
+        // modify just the children's view of matrix layout, if there is one for this member
+        TLayoutMatrix subMatrixLayout = typeList[member].type->getQualifier().layoutMatrix;
+        int memberAlignment = intermediate.getBaseAlignment(*typeList[member].type, memberSize, qualifier.layoutPacking == ElpStd140,
+                                                            subMatrixLayout != ElmNone ? subMatrixLayout == ElmRowMajor : qualifier.layoutMatrix == ElmRowMajor);
         if (memberQualifier.hasOffset()) {
             // "The specified offset must be a multiple 
             // of the base alignment of the type of the block member it qualifies, or a compile-time error results."
diff --git a/glslang/MachineIndependent/linkValidate.cpp b/glslang/MachineIndependent/linkValidate.cpp
index 5e4104c..1a543c1 100644
--- a/glslang/MachineIndependent/linkValidate.cpp
+++ b/glslang/MachineIndependent/linkValidate.cpp
@@ -859,7 +859,7 @@
 //
 // The size is returned in the 'size' parameter
 // Return value is the alignment of the type.
-int TIntermediate::getBaseAlignment(const TType& type, int& size, bool std140)
+int TIntermediate::getBaseAlignment(const TType& type, int& size, bool std140, bool rowMajor)
 {
     int alignment;
 
@@ -921,7 +921,7 @@
     if (type.isArray()) {
         // TODO: perf: this might be flattened by using getCumulativeArraySize(), and a deref that discards all arrayness
         TType derefType(type, 0);
-        alignment = getBaseAlignment(derefType, size, std140);
+        alignment = getBaseAlignment(derefType, size, std140, rowMajor);
         if (std140)
             alignment = std::max(baseAlignmentVec4Std140, alignment);
         RoundToPow2(size, alignment);
@@ -937,7 +937,10 @@
         int maxAlignment = std140 ? baseAlignmentVec4Std140 : 0;
         for (size_t m = 0; m < memberList.size(); ++m) {
             int memberSize;
-            int memberAlignment = getBaseAlignment(*memberList[m].type, memberSize, std140);
+            // modify just the children's view of matrix layout, if there is one for this member
+            TLayoutMatrix subMatrixLayout = memberList[m].type->getQualifier().layoutMatrix;
+            int memberAlignment = getBaseAlignment(*memberList[m].type, memberSize, std140,
+                                                   (subMatrixLayout != ElmNone) ? (subMatrixLayout == ElmRowMajor) : rowMajor);
             maxAlignment = std::max(maxAlignment, memberAlignment);
             RoundToPow2(size, memberAlignment);         
             size += memberSize;
@@ -968,11 +971,11 @@
         // rule 5: deref to row, not to column, meaning the size of vector is num columns instead of num rows
         TType derefType(type, 0, type.getQualifier().layoutMatrix == ElmRowMajor);
             
-        alignment = getBaseAlignment(derefType, size, std140);
+        alignment = getBaseAlignment(derefType, size, std140, rowMajor);
         if (std140)
             alignment = std::max(baseAlignmentVec4Std140, alignment);
         RoundToPow2(size, alignment);
-        if (type.getQualifier().layoutMatrix == ElmRowMajor)
+        if (rowMajor)
             size *= type.getMatrixRows();
         else
             size *= type.getMatrixCols();
diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h
index 27bac7b..9933594 100644
--- a/glslang/MachineIndependent/localintermediate.h
+++ b/glslang/MachineIndependent/localintermediate.h
@@ -305,7 +305,7 @@
     }
     int addXfbBufferOffset(const TType&);
     unsigned int computeTypeXfbSize(const TType&, bool& containsDouble) const;
-    static int getBaseAlignment(const TType&, int& size, bool std140);
+    static int getBaseAlignment(const TType&, int& size, bool std140, bool rowMajor);
 
 protected:
     void error(TInfoSink& infoSink, const char*);
diff --git a/glslang/MachineIndependent/reflection.cpp b/glslang/MachineIndependent/reflection.cpp
index 85caff7..5a1479a 100644
--- a/glslang/MachineIndependent/reflection.cpp
+++ b/glslang/MachineIndependent/reflection.cpp
@@ -123,7 +123,10 @@
         int memberSize;
         int offset = 0;
         for (int m = 0; m <= index; ++m) {
-            int memberAlignment = intermediate.getBaseAlignment(*memberList[m].type, memberSize, type.getQualifier().layoutPacking == ElpStd140);
+            // modify just the children's view of matrix layout, if there is one for this member
+            TLayoutMatrix subMatrixLayout = memberList[m].type->getQualifier().layoutMatrix;
+            int memberAlignment = intermediate.getBaseAlignment(*memberList[m].type, memberSize, type.getQualifier().layoutPacking == ElpStd140,
+                                                                subMatrixLayout != ElmNone ? subMatrixLayout == ElmRowMajor : type.getQualifier().layoutMatrix == ElmRowMajor);
             RoundToPow2(offset, memberAlignment);
             if (m < index)
                 offset += memberSize;
@@ -141,7 +144,8 @@
         int lastOffset = getOffset(blockType, lastIndex);
 
         int lastMemberSize;
-        intermediate.getBaseAlignment(*memberList[lastIndex].type, lastMemberSize, blockType.getQualifier().layoutPacking == ElpStd140);
+        intermediate.getBaseAlignment(*memberList[lastIndex].type, lastMemberSize, blockType.getQualifier().layoutPacking == ElpStd140,
+                                      blockType.getQualifier().layoutMatrix == ElmRowMajor);
 
         return lastOffset + lastMemberSize;
     }