Reduce runtime of array layout checks (#2534)

Fixes #2533

* Stop checking layouts once the offset gets back to a 16 byte alignment
diff --git a/source/val/validate_decorations.cpp b/source/val/validate_decorations.cpp
index 193b170..1eef64d 100644
--- a/source/val/validate_decorations.cpp
+++ b/source/val/validate_decorations.cpp
@@ -548,6 +548,9 @@
                                 typeId, storage_class_str, decoration_str,
                                 blockRules, next_offset, constraints, vstate)))
           return recursive_status;
+        // If offsets accumulate up to a 16-byte multiple stop checking since
+        // it will just repeat.
+        if (i > 0 && (next_offset % 16 == 0)) break;
       }
 
       // Proceed to the element in case it is an array.
diff --git a/test/val/val_decoration_test.cpp b/test/val/val_decoration_test.cpp
index 635afad..764ee08 100644
--- a/test/val/val_decoration_test.cpp
+++ b/test/val/val_decoration_test.cpp
@@ -5719,6 +5719,41 @@
                         "improperly straddling vector at offset 28"));
 }
 
+TEST_F(ValidateDecorations, LargeArray) {
+  const std::string spirv = R"(
+OpCapability Shader
+OpMemoryModel Logical GLSL450
+OpEntryPoint GLCompute %main "main"
+OpExecutionMode %main LocalSize 1 1 1
+OpDecorate %struct Block
+OpMemberDecorate %struct 0 Offset 0
+OpDecorate %array ArrayStride 24
+OpMemberDecorate %inner 0 Offset 0
+OpMemberDecorate %inner 1 Offset 8
+OpMemberDecorate %inner 2 Offset 16
+OpMemberDecorate %inner 3 Offset 20
+OpDecorate %var DescriptorSet 0
+OpDecorate %var Binding 0
+%void = OpTypeVoid
+%int = OpTypeInt 32 0
+%int_2000000 = OpConstant %int 2000000
+%int2 = OpTypeVector %int 2
+%inner = OpTypeStruct %int %int2 %int %int
+%array = OpTypeArray %inner %int_2000000
+%struct = OpTypeStruct %array
+%ptr_struct = OpTypePointer StorageBuffer %struct
+%var = OpVariable %ptr_struct StorageBuffer
+%void_fn = OpTypeFunction %void
+%main = OpFunction %void None %void_fn
+%entry = OpLabel
+OpReturn
+OpFunctionEnd
+)";
+
+  CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
+  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
+}
+
 // NonWritable
 
 // Returns a SPIR-V shader module with variables in various storage classes,