SPV: Handle stride decorations for arrays of arrays, and using multiple type instances when strides are used.
diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp
index c17a73e..e468705 100755
--- a/SPIRV/GlslangToSpv.cpp
+++ b/SPIRV/GlslangToSpv.cpp
@@ -1651,10 +1651,37 @@
     }
 
     if (type.isArray()) {
+        int stride = 0;  // keep this 0 unless doing an explicit layout; 0 will mean no decoration, no stride
+
         // Do all but the outer dimension
-        for (int dim = type.getArraySizes()->getNumDims() - 1; dim > 0; --dim) {
-            assert(type.getArraySizes()->getDimSize(dim) > 0);
-            spvType = builder.makeArrayType(spvType, type.getArraySizes()->getDimSize(dim));
+        if (type.getArraySizes()->getNumDims() > 1) {
+            if (explicitLayout != glslang::ElpNone) {
+                // Use a dummy glslang type for querying internal strides of
+                // arrays of arrays, but using just a one-dimensional array.
+                glslang::TType simpleArrayType(type, 0); // deference type of the array
+                while (simpleArrayType.getArraySizes().getNumDims() > 1)
+                    simpleArrayType.getArraySizes().dereference();
+
+                // Will compute the higher-order strides here, rather than making a whole
+                // pile of types and doing repetitive recursion on their contents.
+                stride = getArrayStride(simpleArrayType, explicitLayout, qualifier.layoutMatrix);
+            }
+            for (int dim = type.getArraySizes()->getNumDims() - 1; dim > 0; --dim) {
+                int size = type.getArraySizes()->getDimSize(dim);
+                assert(size > 0);
+                spvType = builder.makeArrayType(spvType, size, stride);
+                if (stride > 0)
+                    builder.addDecoration(spvType, spv::DecorationArrayStride, stride);
+                stride *= size;
+            }
+        } else {
+            // single-dimensional array, and don't yet have stride
+
+            // We need to decorate array strides for types needing explicit layout,
+            // 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 != glslang::ElpNone && type.getBasicType() != glslang::EbtBlock)
+                stride = getArrayStride(type, explicitLayout, qualifier.layoutMatrix);
         }
 
         // Do the outer dimension, which might not be known for a runtime-sized array
@@ -1662,18 +1689,10 @@
             spvType = builder.makeRuntimeArray(spvType);
         } else {
             assert(type.getOuterArraySize() > 0);
-            spvType = builder.makeArrayType(spvType, type.getOuterArraySize());
+            spvType = builder.makeArrayType(spvType, type.getOuterArraySize(), stride);
         }
-
-        // TODO: explicit layout still needs to be done hierarchically for arrays of arrays, which 
-        // may still require additional "link time" support from the front-end 
-        // for arrays of arrays
-
-        // We need to decorate array strides for types needing explicit layout,
-        // 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, qualifier.layoutMatrix));
+        if (stride > 0)
+            builder.addDecoration(spvType, spv::DecorationArrayStride, stride);
     }
 
     return spvType;