SPV: Fix array strides by explicitly computing them in the getBaseAlignment() algorithm.
diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp
index 654fe87..c17a73e 100755
--- a/SPIRV/GlslangToSpv.cpp
+++ b/SPIRV/GlslangToSpv.cpp
@@ -1707,25 +1707,25 @@
 int TGlslangToSpvTraverser::getArrayStride(const glslang::TType& arrayType, glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout)
 {
     int size;
-    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 (matrixLayout == glslang::ElmRowMajor)
-            stride *= arrayType.getMatrixRows();
-        else
-            stride *= arrayType.getMatrixCols();
-    }
+    int stride;
+    glslangIntermediate->getBaseAlignment(arrayType, size, stride, explicitLayout == glslang::ElpStd140, matrixLayout == glslang::ElmRowMajor);
 
     return stride;
 }
 
-// Given a matrix type, returns the integer stride required for that matrix
+// Given a matrix type, or array (of array) of matrixes 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, glslang::TLayoutMatrix matrixLayout)
 {
+    glslang::TType elementType;
+    elementType.shallowCopy(matrixType);
+    elementType.clearArraySizes();
+
     int size;
-    return glslangIntermediate->getBaseAlignment(matrixType, size, explicitLayout == glslang::ElpStd140, matrixLayout == glslang::ElmRowMajor);
+    int stride;
+    glslangIntermediate->getBaseAlignment(elementType, size, stride, explicitLayout == glslang::ElpStd140, matrixLayout == glslang::ElmRowMajor);
+
+    return stride;
 }
 
 // Given a member type of a struct, realign the current offset for it, and compute
@@ -1764,7 +1764,8 @@
     // but possibly not yet correctly aligned.
 
     int memberSize;
-    int memberAlignment = glslangIntermediate->getBaseAlignment(memberType, memberSize, explicitLayout == glslang::ElpStd140, matrixLayout == glslang::ElmRowMajor);
+    int dummyStride;
+    int memberAlignment = glslangIntermediate->getBaseAlignment(memberType, memberSize, dummyStride, 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 54ed9b7..ac51aab 100644
--- a/Test/baseResults/spv.layoutNested.vert.out
+++ b/Test/baseResults/spv.layoutNested.vert.out
@@ -100,7 +100,7 @@
                               MemberDecorate 14(S) 1 Offset 16
                               MemberDecorate 14(S) 1 MatrixStride 16
                               MemberDecorate 14(S) 2 Offset 144
-                              Decorate 18 ArrayStride 16
+                              Decorate 18 ArrayStride 480
                               MemberDecorate 19(Block140) 0 Offset 0
                               MemberDecorate 19(Block140) 1 Offset 16
                               MemberDecorate 19(Block140) 2 Offset 976
@@ -113,7 +113,7 @@
                               MemberDecorate 22(S) 1 Offset 16
                               MemberDecorate 22(S) 1 MatrixStride 8
                               MemberDecorate 22(S) 2 Offset 80
-                              Decorate 24 ArrayStride 16
+                              Decorate 24 ArrayStride 288
                               MemberDecorate 25(Block430) 0 Offset 0
                               MemberDecorate 25(Block430) 1 Offset 16
                               MemberDecorate 25(Block430) 2 Offset 592
diff --git a/Test/sample.frag.out b/Test/sample.frag.out
index ebc450c..8885dba 100644
--- a/Test/sample.frag.out
+++ b/Test/sample.frag.out
@@ -1,15 +1,15 @@
-#### BEGIN COMPILER 0 INFO LOG ####

-0:? Sequence

-0:37  Function Definition: main( (void)

-0:37    Function Parameters: 

-0:39    Sequence

-0:39      move second child to first child (4-component vector of float)

-0:39        'gl_FragColor' (FragColor 4-component vector of float)

-0:39        Construct vec4 (4-component vector of float)

-0:39          'color' (varying in 3-component vector of float)

-0:39          1.000000 (const float)

-

-#### END COMPILER 0 INFO LOG ####

-#### BEGIN LINKER INFO LOG ####

-

-#### END LINKER INFO LOG ####

+#### BEGIN COMPILER 0 INFO LOG ####
+0:? Sequence
+0:37  Function Definition: main( (void)
+0:37    Function Parameters: 
+0:39    Sequence
+0:39      move second child to first child (4-component vector of float)
+0:39        'gl_FragColor' (FragColor 4-component vector of float)
+0:39        Construct vec4 (4-component vector of float)
+0:39          'color' (varying in 3-component vector of float)
+0:39          1.000000 (const float)
+
+#### END COMPILER 0 INFO LOG ####
+#### BEGIN LINKER INFO LOG ####
+
+#### END LINKER INFO LOG ####
diff --git a/Test/sample.vert.out b/Test/sample.vert.out
index ebb700d..aef6bb1 100644
--- a/Test/sample.vert.out
+++ b/Test/sample.vert.out
@@ -1,20 +1,20 @@
-#### BEGIN COMPILER 0 INFO LOG ####

-0:? Sequence

-0:37  Function Definition: main( (void)

-0:37    Function Parameters: 

-0:39    Sequence

-0:39      move second child to first child (3-component vector of float)

-0:39        'color' (varying out 3-component vector of float)

-0:39        1.000000 (const float)

-0:39        1.000000 (const float)

-0:39        1.000000 (const float)

-0:41      move second child to first child (4-component vector of float)

-0:41        'gl_Position' (Position 4-component vector of float)

-0:41        matrix-times-vector (4-component vector of float)

-0:41          'gl_ModelViewProjectionMatrix' (uniform 4X4 matrix of float)

-0:41          'gl_Vertex' (attribute 4-component vector of float)

-

-#### END COMPILER 0 INFO LOG ####

-#### BEGIN LINKER INFO LOG ####

-

-#### END LINKER INFO LOG ####

+#### BEGIN COMPILER 0 INFO LOG ####
+0:? Sequence
+0:37  Function Definition: main( (void)
+0:37    Function Parameters: 
+0:39    Sequence
+0:39      move second child to first child (3-component vector of float)
+0:39        'color' (varying out 3-component vector of float)
+0:39        1.000000 (const float)
+0:39        1.000000 (const float)
+0:39        1.000000 (const float)
+0:41      move second child to first child (4-component vector of float)
+0:41        'gl_Position' (Position 4-component vector of float)
+0:41        matrix-times-vector (4-component vector of float)
+0:41          'gl_ModelViewProjectionMatrix' (uniform 4X4 matrix of float)
+0:41          'gl_Vertex' (attribute 4-component vector of float)
+
+#### END COMPILER 0 INFO LOG ####
+#### BEGIN LINKER INFO LOG ####
+
+#### END LINKER INFO LOG ####
diff --git a/glslang/Include/Types.h b/glslang/Include/Types.h
index df606ff..f169583 100644
--- a/glslang/Include/Types.h
+++ b/glslang/Include/Types.h
@@ -1206,6 +1206,10 @@
         arraySizes = new TArraySizes;
         *arraySizes = s;
     }
+    void clearArraySizes()
+    {
+        arraySizes = 0;
+    }
     void addArrayOuterSizes(const TArraySizes& s)
     {
         if (arraySizes == nullptr)
diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp
index 5836926..7d952c6 100644
--- a/glslang/MachineIndependent/ParseHelper.cpp
+++ b/glslang/MachineIndependent/ParseHelper.cpp
@@ -5353,7 +5353,8 @@
 
         // 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,
+        int dummyStride;
+        int memberAlignment = intermediate.getBaseAlignment(*typeList[member].type, memberSize, dummyStride, qualifier.layoutPacking == ElpStd140,
                                                             subMatrixLayout != ElmNone ? subMatrixLayout == ElmRowMajor : qualifier.layoutMatrix == ElmRowMajor);
         if (memberQualifier.hasOffset()) {
             // "The specified offset must be a multiple 
diff --git a/glslang/MachineIndependent/linkValidate.cpp b/glslang/MachineIndependent/linkValidate.cpp
index 1a543c1..7c96d22 100644
--- a/glslang/MachineIndependent/linkValidate.cpp
+++ b/glslang/MachineIndependent/linkValidate.cpp
@@ -858,8 +858,14 @@
 // otherwise it does not, yielding std430 rules.
 //
 // The size is returned in the 'size' parameter
+//
+// The stride is only non-0 for arrays or matrices, and is the stride of the
+// top-level object nested within the type.  E.g., for an array of matrices,
+// it is the distances needed between matrices, despite the rules saying the
+// stride comes from the flattening down to vectors.
+//
 // Return value is the alignment of the type.
-int TIntermediate::getBaseAlignment(const TType& type, int& size, bool std140, bool rowMajor)
+int TIntermediate::getBaseAlignment(const TType& type, int& size, int& stride, bool std140, bool rowMajor)
 {
     int alignment;
 
@@ -916,16 +922,23 @@
     //
     //   10. If the member is an array of S structures, the S elements of the array are laid
     //       out in order, according to rule (9).
+    //
+    //   Assuming, for rule 10:  The stride is the same as the size of an element.
 
-    // rules 4, 6, and 8
+    stride = 0;
+    int dummyStride;
+
+    // rules 4, 6, 8, and 10
     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, rowMajor);
+        alignment = getBaseAlignment(derefType, size, dummyStride, std140, rowMajor);
         if (std140)
             alignment = std::max(baseAlignmentVec4Std140, alignment);
         RoundToPow2(size, alignment);
-        size *= type.getOuterArraySize();
+        stride = size;  // uses full matrix size for stride of an array of matrices (not quite what rule 6/8, but what's expected)
+                        // uses the assumption for rule 10 in the comment above
+        size = stride * type.getOuterArraySize();
         return alignment;
     }
 
@@ -939,7 +952,7 @@
             int memberSize;
             // 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,
+            int memberAlignment = getBaseAlignment(*memberList[m].type, memberSize, dummyStride, std140,
                                                    (subMatrixLayout != ElmNone) ? (subMatrixLayout == ElmRowMajor) : rowMajor);
             maxAlignment = std::max(maxAlignment, memberAlignment);
             RoundToPow2(size, memberAlignment);         
@@ -971,14 +984,15 @@
         // 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, rowMajor);
+        alignment = getBaseAlignment(derefType, size, dummyStride, std140, rowMajor);
         if (std140)
             alignment = std::max(baseAlignmentVec4Std140, alignment);
         RoundToPow2(size, alignment);
+        stride = size;  // use intra-matrix stride for stride of a just a matrix
         if (rowMajor)
-            size *= type.getMatrixRows();
+            size = stride * type.getMatrixRows();
         else
-            size *= type.getMatrixCols();
+            size = stride * type.getMatrixCols();
 
         return alignment;
     }
diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h
index 9933594..043d31f 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, bool rowMajor);
+    static int getBaseAlignment(const TType&, int& size, int& stride, bool std140, bool rowMajor);
 
 protected:
     void error(TInfoSink& infoSink, const char*);
diff --git a/glslang/MachineIndependent/reflection.cpp b/glslang/MachineIndependent/reflection.cpp
index 5a1479a..9ef6d02 100644
--- a/glslang/MachineIndependent/reflection.cpp
+++ b/glslang/MachineIndependent/reflection.cpp
@@ -121,11 +121,12 @@
             return memberList[index].type->getQualifier().layoutOffset;
 
         int memberSize;
+        int dummyStride;
         int offset = 0;
         for (int m = 0; m <= index; ++m) {
             // 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,
+            int memberAlignment = intermediate.getBaseAlignment(*memberList[m].type, memberSize, dummyStride, type.getQualifier().layoutPacking == ElpStd140,
                                                                 subMatrixLayout != ElmNone ? subMatrixLayout == ElmRowMajor : type.getQualifier().layoutMatrix == ElmRowMajor);
             RoundToPow2(offset, memberAlignment);
             if (m < index)
@@ -144,7 +145,8 @@
         int lastOffset = getOffset(blockType, lastIndex);
 
         int lastMemberSize;
-        intermediate.getBaseAlignment(*memberList[lastIndex].type, lastMemberSize, blockType.getQualifier().layoutPacking == ElpStd140,
+        int dummyStride;
+        intermediate.getBaseAlignment(*memberList[lastIndex].type, lastMemberSize, dummyStride, blockType.getQualifier().layoutPacking == ElpStd140,
                                       blockType.getQualifier().layoutMatrix == ElmRowMajor);
 
         return lastOffset + lastMemberSize;