[04/63] arb_gl_spirv: add some simple ubo/ssbo tests

Submitted by apinheiro on Feb. 23, 2019, 11:44 p.m.

Details

Message ID 20190223234551.21111-5-apinheiro@igalia.com
State New
Headers show
Series "ARB_gl_spirv full series" ( rev: 1 ) in Piglit

Not browsing as part of any series.

Commit Message

apinheiro Feb. 23, 2019, 11:44 p.m.
Those include:
   * Simple test with just one ubo
   * Two different ubo on the same stage
   * Same ubo used on two different stages
   * Array and array using indirect index of ubos

Finally this also includes a test for a shader that was crashing on a
early version of the SPIR-V support. Included here just in case the
codebase regresses.

v2: don't check if the block content is correct with additions and
    substractions of the ubo content (Timothy)
---
 .../execution/ssbo/array-indirect.shader_test | 121 ++++++++
 .../ssbo/array-inside-ssbo.shader_test        | 190 ++++++++++++
 .../array-of-arrays-inside-ssbo.shader_test   | 204 +++++++++++++
 .../execution/ssbo/array.shader_test          | 173 +++++++++++
 .../execution/ssbo/simple.shader_test         | 138 +++++++++
 .../execution/ssbo/two-ssbo.shader_test       | 151 ++++++++++
 .../execution/ssbo/two-stages.shader_test     | 279 ++++++++++++++++++
 .../execution/ubo/array-indirect.shader_test  | 108 +++++++
 .../ubo/array-inside-ubo.shader_test          | 155 ++++++++++
 .../array-of-arrays-inside-ubo.shader_test    | 185 ++++++++++++
 .../execution/ubo/array.shader_test           | 140 +++++++++
 .../ubo/location-0-crash.shader_test          |  94 ++++++
 .../execution/ubo/simple.shader_test          | 131 ++++++++
 .../execution/ubo/two-stages.shader_test      | 276 +++++++++++++++++
 .../execution/ubo/two-ubos.shader_test        | 141 +++++++++
 15 files changed, 2486 insertions(+)
 create mode 100644 tests/spec/arb_gl_spirv/execution/ssbo/array-indirect.shader_test
 create mode 100644 tests/spec/arb_gl_spirv/execution/ssbo/array-inside-ssbo.shader_test
 create mode 100644 tests/spec/arb_gl_spirv/execution/ssbo/array-of-arrays-inside-ssbo.shader_test
 create mode 100644 tests/spec/arb_gl_spirv/execution/ssbo/array.shader_test
 create mode 100644 tests/spec/arb_gl_spirv/execution/ssbo/simple.shader_test
 create mode 100644 tests/spec/arb_gl_spirv/execution/ssbo/two-ssbo.shader_test
 create mode 100644 tests/spec/arb_gl_spirv/execution/ssbo/two-stages.shader_test
 create mode 100644 tests/spec/arb_gl_spirv/execution/ubo/array-indirect.shader_test
 create mode 100644 tests/spec/arb_gl_spirv/execution/ubo/array-inside-ubo.shader_test
 create mode 100644 tests/spec/arb_gl_spirv/execution/ubo/array-of-arrays-inside-ubo.shader_test
 create mode 100644 tests/spec/arb_gl_spirv/execution/ubo/array.shader_test
 create mode 100644 tests/spec/arb_gl_spirv/execution/ubo/location-0-crash.shader_test
 create mode 100644 tests/spec/arb_gl_spirv/execution/ubo/simple.shader_test
 create mode 100644 tests/spec/arb_gl_spirv/execution/ubo/two-stages.shader_test
 create mode 100644 tests/spec/arb_gl_spirv/execution/ubo/two-ubos.shader_test

Patch hide | download patch | download mbox

diff --git a/tests/spec/arb_gl_spirv/execution/ssbo/array-indirect.shader_test b/tests/spec/arb_gl_spirv/execution/ssbo/array-indirect.shader_test
new file mode 100644
index 000000000..62bb39d59
--- /dev/null
+++ b/tests/spec/arb_gl_spirv/execution/ssbo/array-indirect.shader_test
@@ -0,0 +1,121 @@ 
+# SSBO test using an array of ssbo and indirect(dynamically uniform)
+# indexing. Just uses one stage.
+
+[require]
+SPIRV YES
+GL >= 3.3
+GLSL >= 4.50
+GL_ARB_gl_spirv
+
+[vertex shader passthrough]
+
+[fragment shader spirv]
+; Automatically generated from the GLSL by shader_test_spirv.py. DO NOT EDIT
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 24
+; Schema: 0
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %main "main" %color
+               OpExecutionMode %main OriginLowerLeft
+               OpSource GLSL 450
+               OpDecorate %color Location 0
+               OpMemberDecorate %ssbo 0 Offset 0
+               OpDecorate %ssbo BufferBlock
+               OpDecorate %components DescriptorSet 0
+               OpDecorate %components Binding 5
+               OpDecorate %u_idx Location 10
+               OpDecorate %u_idx DescriptorSet 0
+               OpDecorate %u_idx Binding 0
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+      %color = OpVariable %_ptr_Output_v4float Output
+       %ssbo = OpTypeStruct %v4float
+       %uint = OpTypeInt 32 0
+     %uint_3 = OpConstant %uint 3
+%_arr_ssbo_uint_3 = OpTypeArray %ssbo %uint_3
+%_ptr_Uniform__arr_ssbo_uint_3 = OpTypePointer Uniform %_arr_ssbo_uint_3
+ %components = OpVariable %_ptr_Uniform__arr_ssbo_uint_3 Uniform
+        %int = OpTypeInt 32 1
+%_ptr_UniformConstant_int = OpTypePointer UniformConstant %int
+      %u_idx = OpVariable %_ptr_UniformConstant_int UniformConstant
+      %int_0 = OpConstant %int 0
+%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+         %19 = OpLoad %int %u_idx
+         %22 = OpAccessChain %_ptr_Uniform_v4float %components %19 %int_0
+         %23 = OpLoad %v4float %22
+               OpStore %color %23
+               OpReturn
+               OpFunctionEnd
+
+[fragment shader]
+
+#version 450
+
+layout (location = 0) out vec4 color;
+layout (location = 10) uniform int u_idx;
+
+layout (std430, binding = 5) buffer ssbo
+ {
+    vec4 c1;
+ } components[3];
+
+void main()
+{
+	color = components[u_idx].c1;
+}
+
+[test]
+clear color 1.0 0.0 0.0 0.0
+clear
+
+ssbo 5 32 # size, aligned to 16
+#c1
+ssbo 5 subdata float 0  0.11
+ssbo 5 subdata float 4  0.12
+ssbo 5 subdata float 8  0.13
+ssbo 5 subdata float 12 0.14
+
+ssbo 6 32
+#c1
+ssbo 6 subdata float 0  0.21
+ssbo 6 subdata float 4  0.22
+ssbo 6 subdata float 8  0.23
+ssbo 6 subdata float 12 0.24
+
+ssbo 7 32
+#c1
+ssbo 7 subdata float 0  0.31
+ssbo 7 subdata float 4  0.32
+ssbo 7 subdata float 8  0.33
+ssbo 7 subdata float 12 0.34
+
+uniform int 10 0 # location 10, uniform u_idx
+draw rect -1 -1 2 2
+probe all rgba 0.11 0.12 0.13 0.14
+
+uniform int 10 1 # location 10, uniform u_idx
+draw rect -1 -1 2 2
+probe all rgba 0.21 0.22 0.23 0.24
+
+uniform int 10 2 # location 10, uniform u_idx
+draw rect -1 -1 2 2
+probe all rgba 0.31 0.32 0.33 0.34
+
+block binding 5
+verify program_interface_query GL_SHADER_STORAGE_BLOCK ssbo[0] GL_NUM_ACTIVE_VARIABLES 1
+verify program_interface_query GL_SHADER_STORAGE_BLOCK ssbo[0] GL_BUFFER_DATA_SIZE 16
+
+block binding 6
+verify program_interface_query GL_SHADER_STORAGE_BLOCK ssbo[1] GL_NUM_ACTIVE_VARIABLES 1
+verify program_interface_query GL_SHADER_STORAGE_BLOCK ssbo[1] GL_BUFFER_DATA_SIZE 16
+
+verify program_query GL_ACTIVE_UNIFORMS 1
\ No newline at end of file
diff --git a/tests/spec/arb_gl_spirv/execution/ssbo/array-inside-ssbo.shader_test b/tests/spec/arb_gl_spirv/execution/ssbo/array-inside-ssbo.shader_test
new file mode 100644
index 000000000..706ef9035
--- /dev/null
+++ b/tests/spec/arb_gl_spirv/execution/ssbo/array-inside-ssbo.shader_test
@@ -0,0 +1,190 @@ 
+# Using a array of arrays inside a ssbo, instead of a aoa of ssbo.
+
+[require]
+SPIRV YES
+GL >= 3.3
+GLSL >= 4.50
+GL_ARB_gl_spirv
+
+[vertex shader passthrough]
+
+[fragment shader spirv]
+; Automatically generated from the GLSL by shader_test_spirv.py. DO NOT EDIT
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 78
+; Schema: 0
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %main "main" %color
+               OpExecutionMode %main OriginLowerLeft
+               OpSource GLSL 450
+               OpDecorate %color Location 0
+               OpDecorate %_arr_v4float_uint_4 ArrayStride 16
+               OpMemberDecorate %ssbo 0 Offset 0
+               OpDecorate %ssbo BufferBlock
+               OpDecorate %arr DescriptorSet 0
+               OpDecorate %arr Binding 5
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+    %float_1 = OpConstant %float 1
+    %float_0 = OpConstant %float 0
+         %12 = OpConstantComposite %v4float %float_1 %float_0 %float_0 %float_1
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+      %color = OpVariable %_ptr_Output_v4float Output
+         %15 = OpConstantComposite %v4float %float_0 %float_1 %float_0 %float_1
+       %uint = OpTypeInt 32 0
+     %uint_4 = OpConstant %uint 4
+%_arr_v4float_uint_4 = OpTypeArray %v4float %uint_4
+       %ssbo = OpTypeStruct %_arr_v4float_uint_4
+%_ptr_Uniform_ssbo = OpTypePointer Uniform %ssbo
+        %arr = OpVariable %_ptr_Uniform_ssbo Uniform
+        %int = OpTypeInt 32 1
+      %int_0 = OpConstant %int 0
+%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
+%float_610_072205 = OpConstant %float 610.072205
+%float_24998_1719 = OpConstant %float 24998.1719
+%float_8190_74414 = OpConstant %float 8190.74414
+%float_26479_0312 = OpConstant %float 26479.0312
+         %31 = OpConstantComposite %v4float %float_610_072205 %float_24998_1719 %float_8190_74414 %float_26479_0312
+       %bool = OpTypeBool
+     %v4bool = OpTypeVector %bool 4
+      %int_1 = OpConstant %int 1
+%float_15538_2891 = OpConstant %float 15538.2891
+%float_5642_53711 = OpConstant %float 5642.53711
+%float_n23131_3867 = OpConstant %float -23131.3867
+%float_18541_5391 = OpConstant %float 18541.5391
+         %46 = OpConstantComposite %v4float %float_15538_2891 %float_5642_53711 %float_n23131_3867 %float_18541_5391
+      %int_2 = OpConstant %int 2
+%float_n32637_8945 = OpConstant %float -32637.8945
+%float_12265_4824 = OpConstant %float 12265.4824
+%float_n13669_0615 = OpConstant %float -13669.0615
+%float_27760_8262 = OpConstant %float 27760.8262
+         %59 = OpConstantComposite %v4float %float_n32637_8945 %float_12265_4824 %float_n13669_0615 %float_27760_8262
+      %int_3 = OpConstant %int 3
+%float_n1013_09918 = OpConstant %float -1013.09918
+%float_n23371_9824 = OpConstant %float -23371.9824
+%float_n3101_10449 = OpConstant %float -3101.10449
+%float_n19908_5312 = OpConstant %float -19908.5312
+         %72 = OpConstantComposite %v4float %float_n1013_09918 %float_n23371_9824 %float_n3101_10449 %float_n19908_5312
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+ %fail_color = OpVariable %_ptr_Function_v4float Function
+               OpStore %fail_color %12
+               OpStore %color %15
+         %25 = OpAccessChain %_ptr_Uniform_v4float %arr %int_0 %int_0
+         %26 = OpLoad %v4float %25
+         %34 = OpFOrdNotEqual %v4bool %26 %31
+         %35 = OpAny %bool %34
+               OpSelectionMerge %37 None
+               OpBranchConditional %35 %36 %37
+         %36 = OpLabel
+         %38 = OpLoad %v4float %fail_color
+               OpStore %color %38
+               OpBranch %37
+         %37 = OpLabel
+         %40 = OpAccessChain %_ptr_Uniform_v4float %arr %int_0 %int_1
+         %41 = OpLoad %v4float %40
+         %47 = OpFOrdNotEqual %v4bool %41 %46
+         %48 = OpAny %bool %47
+               OpSelectionMerge %50 None
+               OpBranchConditional %48 %49 %50
+         %49 = OpLabel
+         %51 = OpLoad %v4float %fail_color
+               OpStore %color %51
+               OpBranch %50
+         %50 = OpLabel
+         %53 = OpAccessChain %_ptr_Uniform_v4float %arr %int_0 %int_2
+         %54 = OpLoad %v4float %53
+         %60 = OpFOrdNotEqual %v4bool %54 %59
+         %61 = OpAny %bool %60
+               OpSelectionMerge %63 None
+               OpBranchConditional %61 %62 %63
+         %62 = OpLabel
+         %64 = OpLoad %v4float %fail_color
+               OpStore %color %64
+               OpBranch %63
+         %63 = OpLabel
+         %66 = OpAccessChain %_ptr_Uniform_v4float %arr %int_0 %int_3
+         %67 = OpLoad %v4float %66
+         %73 = OpFOrdNotEqual %v4bool %67 %72
+         %74 = OpAny %bool %73
+               OpSelectionMerge %76 None
+               OpBranchConditional %74 %75 %76
+         %75 = OpLabel
+         %77 = OpLoad %v4float %fail_color
+               OpStore %color %77
+               OpBranch %76
+         %76 = OpLabel
+               OpReturn
+               OpFunctionEnd
+
+[fragment shader]
+#version 450
+
+layout (location = 0) out vec4 color;
+
+layout (std430, binding = 5) buffer ssbo {
+	vec4 color[4];
+} arr;
+
+
+
+void main()
+{
+	vec4 fail_color = vec4(1.0, 0.0, 0.0, 1.0);
+	color = vec4(0.0, 1.0, 0.0, 1.0);
+
+	if (arr.color[0] != vec4(610.072190433, 24998.1713741, 8190.74402991, 26479.0313725)) {
+	   color = fail_color;
+	}
+	if (arr.color[1] != vec4(15538.2894026, 5642.53723964, -23131.3873198, 18541.5383078)) {
+	   color = fail_color;
+	}
+	if (arr.color[2] != vec4(-32637.8949874, 12265.4819562, -13669.0617838, 27760.8253605)) {
+	   color = fail_color;
+	}
+	if (arr.color[3] != vec4(-1013.0991989, -23371.9822385, -3101.104448, -19908.5317922)) {
+	   color = fail_color;
+	}
+
+}
+
+[test]
+clear color 0.2 0.2 0.2 0.2
+clear
+
+ssbo 5 64
+ssbo 5 subdata float 0  610.072190433
+ssbo 5 subdata float 4  24998.1713741
+ssbo 5 subdata float 8  8190.74402991
+ssbo 5 subdata float 12 26479.0313725
+
+ssbo 5 subdata float 16 15538.2894026
+ssbo 5 subdata float 20 5642.53723964
+ssbo 5 subdata float 24 -23131.3873198
+ssbo 5 subdata float 28 18541.5383078
+
+ssbo 5 subdata float 32 -32637.8949874
+ssbo 5 subdata float 36 12265.4819562
+ssbo 5 subdata float 40 -13669.0617838
+ssbo 5 subdata float 44 27760.8253605
+
+ssbo 5 subdata float 48 -1013.0991989
+ssbo 5 subdata float 52 -23371.9822385
+ssbo 5 subdata float 56 -3101.104448
+ssbo 5 subdata float 60 -19908.5317922
+
+block binding 5
+verify program_interface_query GL_SHADER_STORAGE_BLOCK ssbo GL_NUM_ACTIVE_VARIABLES 1
+verify program_interface_query GL_SHADER_STORAGE_BLOCK ssbo GL_BUFFER_DATA_SIZE 64
+
+verify program_query GL_ACTIVE_UNIFORMS 0
+
+draw rect -1 -1 2 2
+probe all rgba 0.00 1.0 0.0 1.0
diff --git a/tests/spec/arb_gl_spirv/execution/ssbo/array-of-arrays-inside-ssbo.shader_test b/tests/spec/arb_gl_spirv/execution/ssbo/array-of-arrays-inside-ssbo.shader_test
new file mode 100644
index 000000000..ba665e718
--- /dev/null
+++ b/tests/spec/arb_gl_spirv/execution/ssbo/array-of-arrays-inside-ssbo.shader_test
@@ -0,0 +1,204 @@ 
+# Using a array of arrays inside a ssbo, instead of a aoa of ssbo.
+
+[require]
+SPIRV YES
+GL >= 3.3
+GLSL >= 4.50
+GL_ARB_gl_spirv
+
+[vertex shader passthrough]
+
+[fragment shader spirv]
+; Automatically generated from the GLSL by shader_test_spirv.py. DO NOT EDIT
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 84
+; Schema: 0
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %main "main" %color
+               OpExecutionMode %main OriginLowerLeft
+               OpSource GLSL 450
+               OpDecorate %color Location 0
+               OpDecorate %_arr_v4float_uint_4 ArrayStride 16
+               OpDecorate %_arr__arr_v4float_uint_4_uint_3 ArrayStride 64
+               OpDecorate %_arr__arr__arr_v4float_uint_4_uint_3_uint_2 ArrayStride 192
+               OpDecorate %_arr_v4float_uint_2 ArrayStride 16
+               OpDecorate %_arr__arr_v4float_uint_2_uint_2 ArrayStride 32
+               OpMemberDecorate %ssbo 0 Offset 0
+               OpMemberDecorate %ssbo 1 Offset 384
+               OpDecorate %ssbo BufferBlock
+               OpDecorate %arr DescriptorSet 0
+               OpDecorate %arr Binding 5
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+    %float_1 = OpConstant %float 1
+    %float_0 = OpConstant %float 0
+         %12 = OpConstantComposite %v4float %float_1 %float_0 %float_0 %float_1
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+      %color = OpVariable %_ptr_Output_v4float Output
+         %15 = OpConstantComposite %v4float %float_0 %float_1 %float_0 %float_1
+       %uint = OpTypeInt 32 0
+     %uint_4 = OpConstant %uint 4
+%_arr_v4float_uint_4 = OpTypeArray %v4float %uint_4
+     %uint_3 = OpConstant %uint 3
+%_arr__arr_v4float_uint_4_uint_3 = OpTypeArray %_arr_v4float_uint_4 %uint_3
+     %uint_2 = OpConstant %uint 2
+%_arr__arr__arr_v4float_uint_4_uint_3_uint_2 = OpTypeArray %_arr__arr_v4float_uint_4_uint_3 %uint_2
+%_arr_v4float_uint_2 = OpTypeArray %v4float %uint_2
+%_arr__arr_v4float_uint_2_uint_2 = OpTypeArray %_arr_v4float_uint_2 %uint_2
+       %ssbo = OpTypeStruct %_arr__arr__arr_v4float_uint_4_uint_3_uint_2 %_arr__arr_v4float_uint_2_uint_2
+%_ptr_Uniform_ssbo = OpTypePointer Uniform %ssbo
+        %arr = OpVariable %_ptr_Uniform_ssbo Uniform
+        %int = OpTypeInt 32 1
+      %int_0 = OpConstant %int 0
+%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
+%float_0_109999999 = OpConstant %float 0.109999999
+%float_0_119999997 = OpConstant %float 0.119999997
+%float_0_129999995 = OpConstant %float 0.129999995
+%float_0_140000001 = OpConstant %float 0.140000001
+         %37 = OpConstantComposite %v4float %float_0_109999999 %float_0_119999997 %float_0_129999995 %float_0_140000001
+       %bool = OpTypeBool
+     %v4bool = OpTypeVector %bool 4
+      %int_1 = OpConstant %int 1
+%float_0_209999993 = OpConstant %float 0.209999993
+%float_0_219999999 = OpConstant %float 0.219999999
+%float_0_230000004 = OpConstant %float 0.230000004
+%float_0_239999995 = OpConstant %float 0.239999995
+         %52 = OpConstantComposite %v4float %float_0_209999993 %float_0_219999999 %float_0_230000004 %float_0_239999995
+      %int_2 = OpConstant %int 2
+      %int_3 = OpConstant %int 3
+%float_0_310000002 = OpConstant %float 0.310000002
+%float_0_319999993 = OpConstant %float 0.319999993
+%float_0_330000013 = OpConstant %float 0.330000013
+%float_0_340000004 = OpConstant %float 0.340000004
+         %66 = OpConstantComposite %v4float %float_0_310000002 %float_0_319999993 %float_0_330000013 %float_0_340000004
+%float_0_409999996 = OpConstant %float 0.409999996
+%float_0_419999987 = OpConstant %float 0.419999987
+%float_0_430000007 = OpConstant %float 0.430000007
+%float_0_439999998 = OpConstant %float 0.439999998
+         %78 = OpConstantComposite %v4float %float_0_409999996 %float_0_419999987 %float_0_430000007 %float_0_439999998
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+ %fail_color = OpVariable %_ptr_Function_v4float Function
+               OpStore %fail_color %12
+               OpStore %color %15
+         %31 = OpAccessChain %_ptr_Uniform_v4float %arr %int_0 %int_0 %int_0 %int_0
+         %32 = OpLoad %v4float %31
+         %40 = OpFOrdNotEqual %v4bool %32 %37
+         %41 = OpAny %bool %40
+               OpSelectionMerge %43 None
+               OpBranchConditional %41 %42 %43
+         %42 = OpLabel
+         %44 = OpLoad %v4float %fail_color
+               OpStore %color %44
+               OpBranch %43
+         %43 = OpLabel
+         %46 = OpAccessChain %_ptr_Uniform_v4float %arr %int_0 %int_1 %int_1 %int_1
+         %47 = OpLoad %v4float %46
+         %53 = OpFOrdNotEqual %v4bool %47 %52
+         %54 = OpAny %bool %53
+               OpSelectionMerge %56 None
+               OpBranchConditional %54 %55 %56
+         %55 = OpLabel
+         %57 = OpLoad %v4float %fail_color
+               OpStore %color %57
+               OpBranch %56
+         %56 = OpLabel
+         %60 = OpAccessChain %_ptr_Uniform_v4float %arr %int_0 %int_1 %int_2 %int_3
+         %61 = OpLoad %v4float %60
+         %67 = OpFOrdNotEqual %v4bool %61 %66
+         %68 = OpAny %bool %67
+               OpSelectionMerge %70 None
+               OpBranchConditional %68 %69 %70
+         %69 = OpLabel
+         %71 = OpLoad %v4float %fail_color
+               OpStore %color %71
+               OpBranch %70
+         %70 = OpLabel
+         %72 = OpAccessChain %_ptr_Uniform_v4float %arr %int_1 %int_1 %int_1
+         %73 = OpLoad %v4float %72
+         %79 = OpFOrdNotEqual %v4bool %73 %78
+         %80 = OpAny %bool %79
+               OpSelectionMerge %82 None
+               OpBranchConditional %80 %81 %82
+         %81 = OpLabel
+         %83 = OpLoad %v4float %fail_color
+               OpStore %color %83
+               OpBranch %82
+         %82 = OpLabel
+               OpReturn
+               OpFunctionEnd
+
+[fragment shader]
+#version 450
+
+layout (location = 0) out vec4 color;
+
+layout (std430, binding = 5) buffer ssbo {
+	vec4 color[2][3][4];
+	vec4 position[2][2];
+} arr;
+
+
+
+void main()
+{
+	vec4 fail_color = vec4(1.0, 0.0, 0.0, 1.0);
+	color = vec4(0.0, 1.0, 0.0, 1.0);
+
+	if (arr.color[0][0][0] != vec4(0.11, 0.12, 0.13, 0.14))
+	   color = fail_color;
+
+	if (arr.color[1][1][1] != vec4(0.21, 0.22, 0.23, 0.24))
+	   color = fail_color;
+
+	if (arr.color[1][2][3] != vec4(0.31, 0.32, 0.33, 0.34))
+	   color = fail_color;
+
+	if (arr.position[1][1] != vec4(0.41, 0.42, 0.43, 0.44))
+	   color = fail_color;
+}
+
+[test]
+clear color 0.2 0.2 0.2 0.2
+clear
+
+ssbo 5 448
+#arr.color[0][0][0]
+ssbo 5 subdata float 0  0.11
+ssbo 5 subdata float 4  0.12
+ssbo 5 subdata float 8  0.13
+ssbo 5 subdata float 12 0.14
+
+#arr.color[1][1][1]
+ssbo 5 subdata float 272 0.21
+ssbo 5 subdata float 276 0.22
+ssbo 5 subdata float 280 0.23
+ssbo 5 subdata float 284 0.24
+
+#arr.color[1][2][3]
+ssbo 5 subdata float 368 0.31
+ssbo 5 subdata float 372 0.32
+ssbo 5 subdata float 376 0.33
+ssbo 5 subdata float 380 0.34
+
+#arr.position[1][1]
+ssbo 5 subdata float 432 0.41
+ssbo 5 subdata float 436 0.42
+ssbo 5 subdata float 440 0.43
+ssbo 5 subdata float 444 0.44
+
+block binding 5
+
+verify program_interface_query GL_SHADER_STORAGE_BLOCK ssbo GL_BUFFER_DATA_SIZE 448
+verify program_query GL_ACTIVE_UNIFORMS 0
+
+draw rect -1 -1 2 2
+probe all rgba 0.0 1.0 0.0 1.0
+
diff --git a/tests/spec/arb_gl_spirv/execution/ssbo/array.shader_test b/tests/spec/arb_gl_spirv/execution/ssbo/array.shader_test
new file mode 100644
index 000000000..dee2f6773
--- /dev/null
+++ b/tests/spec/arb_gl_spirv/execution/ssbo/array.shader_test
@@ -0,0 +1,173 @@ 
+# SSBO test using an array of ssbo
+
+[require]
+SPIRV YES
+GL >= 3.3
+GLSL >= 4.50
+GL_ARB_gl_spirv
+
+[vertex shader passthrough]
+
+[fragment shader spirv]
+; Automatically generated from the GLSL by shader_test_spirv.py. DO NOT EDIT
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 65
+; Schema: 0
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %main "main" %color
+               OpExecutionMode %main OriginLowerLeft
+               OpSource GLSL 450
+               OpDecorate %color Location 0
+               OpMemberDecorate %ComponentsSSBO 0 Offset 0
+               OpDecorate %ComponentsSSBO BufferBlock
+               OpDecorate %components DescriptorSet 0
+               OpDecorate %components Binding 5
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+    %float_1 = OpConstant %float 1
+    %float_0 = OpConstant %float 0
+         %12 = OpConstantComposite %v4float %float_1 %float_0 %float_0 %float_1
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+      %color = OpVariable %_ptr_Output_v4float Output
+         %15 = OpConstantComposite %v4float %float_0 %float_1 %float_0 %float_1
+%ComponentsSSBO = OpTypeStruct %v4float
+       %uint = OpTypeInt 32 0
+     %uint_3 = OpConstant %uint 3
+%_arr_ComponentsSSBO_uint_3 = OpTypeArray %ComponentsSSBO %uint_3
+%_ptr_Uniform__arr_ComponentsSSBO_uint_3 = OpTypePointer Uniform %_arr_ComponentsSSBO_uint_3
+ %components = OpVariable %_ptr_Uniform__arr_ComponentsSSBO_uint_3 Uniform
+        %int = OpTypeInt 32 1
+      %int_0 = OpConstant %int 0
+%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
+%float_13210_8457 = OpConstant %float 13210.8457
+%float_27568_4121 = OpConstant %float 27568.4121
+%float_n19680_3008 = OpConstant %float -19680.3008
+%float_n23797_5215 = OpConstant %float -23797.5215
+         %31 = OpConstantComposite %v4float %float_13210_8457 %float_27568_4121 %float_n19680_3008 %float_n23797_5215
+       %bool = OpTypeBool
+     %v4bool = OpTypeVector %bool 4
+      %int_1 = OpConstant %int 1
+%float_n4727_75244 = OpConstant %float -4727.75244
+%float_9629_81445 = OpConstant %float 9629.81445
+%float_27918_1016 = OpConstant %float 27918.1016
+%float_5792_34473 = OpConstant %float 5792.34473
+         %46 = OpConstantComposite %v4float %float_n4727_75244 %float_9629_81445 %float_27918_1016 %float_5792_34473
+      %int_2 = OpConstant %int 2
+%float_24080_6328 = OpConstant %float 24080.6328
+%float_n1620_24451 = OpConstant %float -1620.24451
+%float_26109_8477 = OpConstant %float 26109.8477
+%float_n25069_5859 = OpConstant %float -25069.5859
+         %59 = OpConstantComposite %v4float %float_24080_6328 %float_n1620_24451 %float_26109_8477 %float_n25069_5859
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+ %fail_color = OpVariable %_ptr_Function_v4float Function
+               OpStore %fail_color %12
+               OpStore %color %15
+         %25 = OpAccessChain %_ptr_Uniform_v4float %components %int_0 %int_0
+         %26 = OpLoad %v4float %25
+         %34 = OpFOrdNotEqual %v4bool %26 %31
+         %35 = OpAny %bool %34
+               OpSelectionMerge %37 None
+               OpBranchConditional %35 %36 %37
+         %36 = OpLabel
+         %38 = OpLoad %v4float %fail_color
+               OpStore %color %38
+               OpBranch %37
+         %37 = OpLabel
+         %40 = OpAccessChain %_ptr_Uniform_v4float %components %int_1 %int_0
+         %41 = OpLoad %v4float %40
+         %47 = OpFOrdNotEqual %v4bool %41 %46
+         %48 = OpAny %bool %47
+               OpSelectionMerge %50 None
+               OpBranchConditional %48 %49 %50
+         %49 = OpLabel
+         %51 = OpLoad %v4float %fail_color
+               OpStore %color %51
+               OpBranch %50
+         %50 = OpLabel
+         %53 = OpAccessChain %_ptr_Uniform_v4float %components %int_2 %int_0
+         %54 = OpLoad %v4float %53
+         %60 = OpFOrdNotEqual %v4bool %54 %59
+         %61 = OpAny %bool %60
+               OpSelectionMerge %63 None
+               OpBranchConditional %61 %62 %63
+         %62 = OpLabel
+         %64 = OpLoad %v4float %fail_color
+               OpStore %color %64
+               OpBranch %63
+         %63 = OpLabel
+               OpReturn
+               OpFunctionEnd
+
+[fragment shader]
+
+#version 450
+
+layout (location = 0) out vec4 color;
+layout (std430, binding = 5) buffer ComponentsSSBO
+ {
+    vec4 c1;
+ } components[3];
+
+void main()
+{
+	vec4 fail_color = vec4(1.0, 0.0, 0.0, 1.0);
+	color = vec4(0.0, 1.0, 0.0, 1.0);
+
+	if (components[0].c1 != vec4(13210.8456245, 27568.4123445, -19680.3003281, -23797.5217212)) {
+	   color = fail_color;
+	}
+
+	if (components[1].c1 != vec4(-4727.75226978, 9629.81445029, 27918.1017929, 5792.34471656)) {
+	   color = fail_color;
+	}
+
+	if (components[2].c1 != vec4(24080.6320592, -1620.2444495, 26109.8476997, -25069.5855955)) {
+	   color = fail_color;
+	}
+}
+
+[test]
+clear color 1.0 0.0 0.0 0.0
+clear
+
+ssbo 5 32 # size, aligned to 16
+#c1
+ssbo 5 subdata float 0  13210.8456245
+ssbo 5 subdata float 4  27568.4123445
+ssbo 5 subdata float 8  -19680.3003281
+ssbo 5 subdata float 12 -23797.5217212
+
+ssbo 6 32
+#c1
+ssbo 6 subdata float 0  -4727.75226978
+ssbo 6 subdata float 4  9629.81445029
+ssbo 6 subdata float 8  27918.1017929
+ssbo 6 subdata float 12 5792.34471656
+
+ssbo 7 32
+#c1
+ssbo 7 subdata float 0  24080.6320592
+ssbo 7 subdata float 4  -1620.2444495
+ssbo 7 subdata float 8  26109.8476997
+ssbo 7 subdata float 12 -25069.5855955
+
+block binding 5
+verify program_interface_query GL_SHADER_STORAGE_BLOCK ComponentsSSBO[0] GL_NUM_ACTIVE_VARIABLES 1
+verify program_interface_query GL_SHADER_STORAGE_BLOCK ComponentsSSBO[0] GL_BUFFER_DATA_SIZE 16
+
+block binding 6
+verify program_interface_query GL_SHADER_STORAGE_BLOCK ComponentsSSBO[1] GL_NUM_ACTIVE_VARIABLES 1
+verify program_interface_query GL_SHADER_STORAGE_BLOCK ComponentsSSBO[1] GL_BUFFER_DATA_SIZE 16
+
+verify program_query GL_ACTIVE_UNIFORMS 0
+
+draw rect -1 -1 2 2
+probe all rgba 0.0 1.0 0.0 1.0
diff --git a/tests/spec/arb_gl_spirv/execution/ssbo/simple.shader_test b/tests/spec/arb_gl_spirv/execution/ssbo/simple.shader_test
new file mode 100644
index 000000000..2d1972f1a
--- /dev/null
+++ b/tests/spec/arb_gl_spirv/execution/ssbo/simple.shader_test
@@ -0,0 +1,138 @@ 
+# Simple SSBO test: just one stage. No arrays.
+
+[require]
+SPIRV YES
+GL >= 3.3
+GLSL >= 4.50
+GL_ARB_gl_spirv
+
+[vertex shader passthrough]
+
+[fragment shader spirv]
+; Automatically generated from the GLSL by shader_test_spirv.py. DO NOT EDIT
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 50
+; Schema: 0
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %main "main" %color
+               OpExecutionMode %main OriginLowerLeft
+               OpSource GLSL 450
+               OpDecorate %color Location 0
+               OpMemberDecorate %ssbo 0 Offset 0
+               OpMemberDecorate %ssbo 1 Offset 16
+               OpDecorate %ssbo BufferBlock
+               OpDecorate %components DescriptorSet 0
+               OpDecorate %components Binding 5
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+    %float_1 = OpConstant %float 1
+    %float_0 = OpConstant %float 0
+         %12 = OpConstantComposite %v4float %float_1 %float_0 %float_0 %float_1
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+      %color = OpVariable %_ptr_Output_v4float Output
+         %15 = OpConstantComposite %v4float %float_0 %float_1 %float_0 %float_1
+    %v2float = OpTypeVector %float 2
+       %ssbo = OpTypeStruct %v4float %v2float
+%_ptr_Uniform_ssbo = OpTypePointer Uniform %ssbo
+ %components = OpVariable %_ptr_Uniform_ssbo Uniform
+        %int = OpTypeInt 32 1
+      %int_0 = OpConstant %int 0
+%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
+%float_n6781_29834 = OpConstant %float -6781.29834
+%float_1301_10352 = OpConstant %float 1301.10352
+%float_19589_3906 = OpConstant %float 19589.3906
+%float_n31590_043 = OpConstant %float -31590.043
+         %29 = OpConstantComposite %v4float %float_n6781_29834 %float_1301_10352 %float_19589_3906 %float_n31590_043
+       %bool = OpTypeBool
+     %v4bool = OpTypeVector %bool 4
+      %int_1 = OpConstant %int 1
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+%float_4651_35693 = OpConstant %float 4651.35693
+%float_n24122_5684 = OpConstant %float -24122.5684
+         %43 = OpConstantComposite %v2float %float_4651_35693 %float_n24122_5684
+     %v2bool = OpTypeVector %bool 2
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+ %fail_color = OpVariable %_ptr_Function_v4float Function
+               OpStore %fail_color %12
+               OpStore %color %15
+         %23 = OpAccessChain %_ptr_Uniform_v4float %components %int_0
+         %24 = OpLoad %v4float %23
+         %32 = OpFOrdNotEqual %v4bool %24 %29
+         %33 = OpAny %bool %32
+               OpSelectionMerge %35 None
+               OpBranchConditional %33 %34 %35
+         %34 = OpLabel
+         %36 = OpLoad %v4float %fail_color
+               OpStore %color %36
+               OpBranch %35
+         %35 = OpLabel
+         %39 = OpAccessChain %_ptr_Uniform_v2float %components %int_1
+         %40 = OpLoad %v2float %39
+         %45 = OpFOrdNotEqual %v2bool %40 %43
+         %46 = OpAny %bool %45
+               OpSelectionMerge %48 None
+               OpBranchConditional %46 %47 %48
+         %47 = OpLabel
+         %49 = OpLoad %v4float %fail_color
+               OpStore %color %49
+               OpBranch %48
+         %48 = OpLabel
+               OpReturn
+               OpFunctionEnd
+
+[fragment shader]
+
+#version 450
+
+layout (location = 0) out vec4 color;
+layout (std430, binding = 5) buffer ssbo
+ {
+    vec4 c1;
+    vec2 c2;
+ } components;
+
+void main()
+{
+	vec4 fail_color = vec4(1.0, 0.0, 0.0, 1.0);
+	color = vec4(0.0, 1.0, 0.0, 1.0);
+
+	if (components.c1 != vec4(-6781.29825284, 1301.10353246, 19589.3908751, -31590.0424201)) {
+	   color = fail_color;
+	}
+
+	if (components.c2 != vec2(4651.35672541, -24122.567834)) {
+	   color = fail_color;
+	}
+}
+
+[test]
+ssbo 5 32 # size, aligned to 16
+#c1
+ssbo 5 subdata float 0  -6781.29825284
+ssbo 5 subdata float 4  1301.10353246
+ssbo 5 subdata float 8  19589.3908751
+ssbo 5 subdata float 12 -31590.0424201
+
+#c2
+ssbo 5 subdata float 16 4651.35672541
+ssbo 5 subdata float 20 -24122.567834
+
+clear color 1.0 0.0 0.0 0.0
+clear
+
+block binding 5
+verify program_interface_query GL_SHADER_STORAGE_BLOCK ssbo GL_NUM_ACTIVE_VARIABLES 2
+verify program_interface_query GL_SHADER_STORAGE_BLOCK ssbo GL_BUFFER_DATA_SIZE 32
+
+verify program_query GL_ACTIVE_UNIFORMS 0
+
+draw rect -1 -1 2 2
+probe all rgba 0.0 1.0 0.0 1.0
diff --git a/tests/spec/arb_gl_spirv/execution/ssbo/two-ssbo.shader_test b/tests/spec/arb_gl_spirv/execution/ssbo/two-ssbo.shader_test
new file mode 100644
index 000000000..6ff2b7d9c
--- /dev/null
+++ b/tests/spec/arb_gl_spirv/execution/ssbo/two-ssbo.shader_test
@@ -0,0 +1,151 @@ 
+# SSBO test with two ssbos. Just one stage.
+
+[require]
+SPIRV YES
+GL >= 3.3
+GLSL >= 4.50
+GL_ARB_gl_spirv
+
+[vertex shader passthrough]
+
+[fragment shader spirv]
+; Automatically generated from the GLSL by shader_test_spirv.py. DO NOT EDIT
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 51
+; Schema: 0
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %main "main" %color
+               OpExecutionMode %main OriginLowerLeft
+               OpSource GLSL 450
+               OpDecorate %color Location 0
+               OpMemberDecorate %ssbo1 0 Offset 0
+               OpDecorate %ssbo1 BufferBlock
+               OpDecorate %components DescriptorSet 0
+               OpDecorate %components Binding 5
+               OpMemberDecorate %ssbo2 0 Offset 0
+               OpDecorate %ssbo2 BufferBlock
+               OpDecorate %components2 DescriptorSet 0
+               OpDecorate %components2 Binding 8
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+    %float_1 = OpConstant %float 1
+    %float_0 = OpConstant %float 0
+         %12 = OpConstantComposite %v4float %float_1 %float_0 %float_0 %float_1
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+      %color = OpVariable %_ptr_Output_v4float Output
+         %15 = OpConstantComposite %v4float %float_0 %float_1 %float_0 %float_1
+      %ssbo1 = OpTypeStruct %v4float
+%_ptr_Uniform_ssbo1 = OpTypePointer Uniform %ssbo1
+ %components = OpVariable %_ptr_Uniform_ssbo1 Uniform
+        %int = OpTypeInt 32 1
+      %int_0 = OpConstant %int 0
+%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
+%float_n28239_7891 = OpConstant %float -28239.7891
+%float_n9951_50195 = OpConstant %float -9951.50195
+%float_n13287_2412 = OpConstant %float -13287.2412
+%float_23475_834 = OpConstant %float 23475.834
+         %28 = OpConstantComposite %v4float %float_n28239_7891 %float_n9951_50195 %float_n13287_2412 %float_23475_834
+       %bool = OpTypeBool
+     %v4bool = OpTypeVector %bool 4
+      %ssbo2 = OpTypeStruct %v4float
+%_ptr_Uniform_ssbo2 = OpTypePointer Uniform %ssbo2
+%components2 = OpVariable %_ptr_Uniform_ssbo2 Uniform
+%float_19358_6133 = OpConstant %float 19358.6133
+%float_n21241_9316 = OpConstant %float -21241.9316
+%float_15521_1436 = OpConstant %float 15521.1436
+%float_11403_9219 = OpConstant %float 11403.9219
+         %45 = OpConstantComposite %v4float %float_19358_6133 %float_n21241_9316 %float_15521_1436 %float_11403_9219
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+ %fail_color = OpVariable %_ptr_Function_v4float Function
+               OpStore %fail_color %12
+               OpStore %color %15
+         %22 = OpAccessChain %_ptr_Uniform_v4float %components %int_0
+         %23 = OpLoad %v4float %22
+         %31 = OpFOrdNotEqual %v4bool %23 %28
+         %32 = OpAny %bool %31
+               OpSelectionMerge %34 None
+               OpBranchConditional %32 %33 %34
+         %33 = OpLabel
+         %35 = OpLoad %v4float %fail_color
+               OpStore %color %35
+               OpBranch %34
+         %34 = OpLabel
+         %39 = OpAccessChain %_ptr_Uniform_v4float %components2 %int_0
+         %40 = OpLoad %v4float %39
+         %46 = OpFOrdNotEqual %v4bool %40 %45
+         %47 = OpAny %bool %46
+               OpSelectionMerge %49 None
+               OpBranchConditional %47 %48 %49
+         %48 = OpLabel
+         %50 = OpLoad %v4float %fail_color
+               OpStore %color %50
+               OpBranch %49
+         %49 = OpLabel
+               OpReturn
+               OpFunctionEnd
+
+[fragment shader]
+
+#version 450
+
+layout (location = 0) out vec4 color;
+layout (std430, binding = 5) buffer ssbo1
+ {
+    vec4 c1;
+ } components;
+
+layout (std430, binding = 8) buffer ssbo2
+ {
+    vec4 c2;
+ } components2;
+
+void main()
+{
+	vec4 fail_color = vec4(1.0, 0.0, 0.0, 1.0);
+	color = vec4(0.0, 1.0, 0.0, 1.0);
+
+	if (components.c1 != vec4(-28239.7892271, -9951.50188449, -13287.2411688, 23475.834287)) {
+	   color = fail_color;
+	}
+
+	if (components2.c2 != vec4(19358.6128939, -21241.9322957, 15521.1431601, 11403.921767)) {
+	   color = fail_color;
+	}
+}
+
+[test]
+clear color 1.0 0.0 0.0 0.0
+clear
+
+ssbo 5 32
+ssbo 5 subdata float 0  -28239.7892271
+ssbo 5 subdata float 4  -9951.50188449
+ssbo 5 subdata float 8  -13287.2411688
+ssbo 5 subdata float 12 23475.834287
+
+ssbo 8 32
+ssbo 8 subdata float 0  19358.6128939
+ssbo 8 subdata float 4  -21241.9322957
+ssbo 8 subdata float 8  15521.1431601
+ssbo 8 subdata float 12 11403.921767
+
+block binding 5
+verify program_interface_query GL_SHADER_STORAGE_BLOCK ssbo1 GL_NUM_ACTIVE_VARIABLES 1
+verify program_interface_query GL_SHADER_STORAGE_BLOCK ssbo1 GL_BUFFER_DATA_SIZE 16
+
+block binding 8
+verify program_interface_query GL_SHADER_STORAGE_BLOCK ssbo2 GL_NUM_ACTIVE_VARIABLES 1
+verify program_interface_query GL_SHADER_STORAGE_BLOCK ssbo2 GL_BUFFER_DATA_SIZE 16
+
+verify program_query GL_ACTIVE_UNIFORMS 0
+
+draw rect -1 -1 2 2
+probe all rgba 0.0 1.0 0.0 1.0
diff --git a/tests/spec/arb_gl_spirv/execution/ssbo/two-stages.shader_test b/tests/spec/arb_gl_spirv/execution/ssbo/two-stages.shader_test
new file mode 100644
index 000000000..21cdf9924
--- /dev/null
+++ b/tests/spec/arb_gl_spirv/execution/ssbo/two-stages.shader_test
@@ -0,0 +1,279 @@ 
+# Simple SSBO test with two stages using the same ssbo
+
+[require]
+SPIRV YES
+GL >= 3.3
+GLSL >= 4.50
+GL_ARB_gl_spirv
+
+[vertex shader spirv]
+; Automatically generated from the GLSL by shader_test_spirv.py. DO NOT EDIT
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 63
+; Schema: 0
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Vertex %main "main" %vertexColor %_ %piglit_vertex %gl_VertexID %gl_InstanceID
+               OpSource GLSL 450
+               OpName %_ ""
+               OpDecorate %vertexColor Location 1
+               OpMemberDecorate %ssbo 0 Offset 0
+               OpMemberDecorate %ssbo 1 Offset 16
+               OpDecorate %ssbo BufferBlock
+               OpDecorate %components DescriptorSet 0
+               OpDecorate %components Binding 5
+               OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
+               OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
+               OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
+               OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
+               OpDecorate %gl_PerVertex Block
+               OpDecorate %piglit_vertex Location 0
+               OpDecorate %gl_VertexID BuiltIn VertexId
+               OpDecorate %gl_InstanceID BuiltIn InstanceId
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+    %float_1 = OpConstant %float 1
+    %float_0 = OpConstant %float 0
+         %12 = OpConstantComposite %v4float %float_1 %float_0 %float_0 %float_1
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+%vertexColor = OpVariable %_ptr_Output_v4float Output
+         %15 = OpConstantComposite %v4float %float_0 %float_1 %float_0 %float_1
+    %v2float = OpTypeVector %float 2
+       %ssbo = OpTypeStruct %v4float %v2float
+%_ptr_Uniform_ssbo = OpTypePointer Uniform %ssbo
+ %components = OpVariable %_ptr_Uniform_ssbo Uniform
+        %int = OpTypeInt 32 1
+      %int_0 = OpConstant %int 0
+%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
+%float_17550_3594 = OpConstant %float 17550.3594
+%float_13929_9688 = OpConstant %float 13929.9688
+%float_32218_2559 = OpConstant %float 32218.2559
+%float_n2830_8335 = OpConstant %float -2830.8335
+         %29 = OpConstantComposite %v4float %float_17550_3594 %float_13929_9688 %float_32218_2559 %float_n2830_8335
+       %bool = OpTypeBool
+     %v4bool = OpTypeVector %bool 4
+      %int_1 = OpConstant %int 1
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+%float_n6948_05469 = OpConstant %float -6948.05469
+%float_11340_2324 = OpConstant %float 11340.2324
+         %43 = OpConstantComposite %v2float %float_n6948_05469 %float_11340_2324
+     %v2bool = OpTypeVector %bool 2
+       %uint = OpTypeInt 32 0
+     %uint_1 = OpConstant %uint 1
+%_arr_float_uint_1 = OpTypeArray %float %uint_1
+%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
+%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
+          %_ = OpVariable %_ptr_Output_gl_PerVertex Output
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+%piglit_vertex = OpVariable %_ptr_Input_v4float Input
+%_ptr_Input_int = OpTypePointer Input %int
+%gl_VertexID = OpVariable %_ptr_Input_int Input
+%gl_InstanceID = OpVariable %_ptr_Input_int Input
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+ %fail_color = OpVariable %_ptr_Function_v4float Function
+               OpStore %fail_color %12
+               OpStore %vertexColor %15
+         %23 = OpAccessChain %_ptr_Uniform_v4float %components %int_0
+         %24 = OpLoad %v4float %23
+         %32 = OpFOrdNotEqual %v4bool %24 %29
+         %33 = OpAny %bool %32
+               OpSelectionMerge %35 None
+               OpBranchConditional %33 %34 %35
+         %34 = OpLabel
+         %36 = OpLoad %v4float %fail_color
+               OpStore %vertexColor %36
+               OpBranch %35
+         %35 = OpLabel
+         %39 = OpAccessChain %_ptr_Uniform_v2float %components %int_1
+         %40 = OpLoad %v2float %39
+         %45 = OpFOrdNotEqual %v2bool %40 %43
+         %46 = OpAny %bool %45
+               OpSelectionMerge %48 None
+               OpBranchConditional %46 %47 %48
+         %47 = OpLabel
+         %49 = OpLoad %v4float %fail_color
+               OpStore %vertexColor %49
+               OpBranch %48
+         %48 = OpLabel
+         %58 = OpLoad %v4float %piglit_vertex
+         %59 = OpAccessChain %_ptr_Output_v4float %_ %int_0
+               OpStore %59 %58
+               OpReturn
+               OpFunctionEnd
+
+[vertex shader]
+
+#version 450
+
+layout (location = 0) in vec4 piglit_vertex;
+layout (location = 1) out vec4 vertexColor;
+layout (std430, binding = 5) buffer ssbo
+ {
+    vec4 c1;
+    vec2 c2;
+ } components;
+
+void main()
+{
+	vec4 fail_color = vec4(1.0, 0.0, 0.0, 1.0);
+	vertexColor = vec4(0.0, 1.0, 0.0, 1.0);
+
+	if (components.c1 != vec4(17550.3588006, 13929.9686885, 32218.2560311, -2830.83346304))
+	   vertexColor = fail_color;
+
+	if (components.c2 != vec2(-6948.05485618, 11340.2324865))
+	   vertexColor = fail_color;
+
+	gl_Position = piglit_vertex;
+}
+
+
+[fragment shader spirv]
+; Automatically generated from the GLSL by shader_test_spirv.py. DO NOT EDIT
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 58
+; Schema: 0
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %main "main" %color %vertexColor
+               OpExecutionMode %main OriginLowerLeft
+               OpSource GLSL 450
+               OpDecorate %color Location 0
+               OpMemberDecorate %ssbo 0 Offset 0
+               OpMemberDecorate %ssbo 1 Offset 16
+               OpDecorate %ssbo BufferBlock
+               OpDecorate %components DescriptorSet 0
+               OpDecorate %components Binding 5
+               OpDecorate %vertexColor Location 1
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+    %float_1 = OpConstant %float 1
+    %float_0 = OpConstant %float 0
+         %12 = OpConstantComposite %v4float %float_1 %float_0 %float_0 %float_1
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+      %color = OpVariable %_ptr_Output_v4float Output
+         %15 = OpConstantComposite %v4float %float_0 %float_1 %float_0 %float_1
+    %v2float = OpTypeVector %float 2
+       %ssbo = OpTypeStruct %v4float %v2float
+%_ptr_Uniform_ssbo = OpTypePointer Uniform %ssbo
+ %components = OpVariable %_ptr_Uniform_ssbo Uniform
+        %int = OpTypeInt 32 1
+      %int_0 = OpConstant %int 0
+%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
+%float_17550_3594 = OpConstant %float 17550.3594
+%float_13929_9688 = OpConstant %float 13929.9688
+%float_32218_2559 = OpConstant %float 32218.2559
+%float_n2830_8335 = OpConstant %float -2830.8335
+         %29 = OpConstantComposite %v4float %float_17550_3594 %float_13929_9688 %float_32218_2559 %float_n2830_8335
+       %bool = OpTypeBool
+     %v4bool = OpTypeVector %bool 4
+      %int_1 = OpConstant %int 1
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+%float_n6948_05469 = OpConstant %float -6948.05469
+%float_11340_2324 = OpConstant %float 11340.2324
+         %43 = OpConstantComposite %v2float %float_n6948_05469 %float_11340_2324
+     %v2bool = OpTypeVector %bool 2
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+%vertexColor = OpVariable %_ptr_Input_v4float Input
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+ %fail_color = OpVariable %_ptr_Function_v4float Function
+               OpStore %fail_color %12
+               OpStore %color %15
+         %23 = OpAccessChain %_ptr_Uniform_v4float %components %int_0
+         %24 = OpLoad %v4float %23
+         %32 = OpFOrdNotEqual %v4bool %24 %29
+         %33 = OpAny %bool %32
+               OpSelectionMerge %35 None
+               OpBranchConditional %33 %34 %35
+         %34 = OpLabel
+         %36 = OpLoad %v4float %fail_color
+               OpStore %color %36
+               OpBranch %35
+         %35 = OpLabel
+         %39 = OpAccessChain %_ptr_Uniform_v2float %components %int_1
+         %40 = OpLoad %v2float %39
+         %45 = OpFOrdNotEqual %v2bool %40 %43
+         %46 = OpAny %bool %45
+               OpSelectionMerge %48 None
+               OpBranchConditional %46 %47 %48
+         %47 = OpLabel
+         %49 = OpLoad %v4float %fail_color
+               OpStore %color %49
+               OpBranch %48
+         %48 = OpLabel
+         %52 = OpLoad %v4float %vertexColor
+         %53 = OpFOrdNotEqual %v4bool %52 %15
+         %54 = OpAny %bool %53
+               OpSelectionMerge %56 None
+               OpBranchConditional %54 %55 %56
+         %55 = OpLabel
+         %57 = OpLoad %v4float %fail_color
+               OpStore %color %57
+               OpBranch %56
+         %56 = OpLabel
+               OpReturn
+               OpFunctionEnd
+
+[fragment shader]
+
+#version 450
+
+layout (location = 0) out vec4 color;
+layout (location = 1) in vec4 vertexColor;
+layout (std430, binding = 5) buffer ssbo
+ {
+    vec4 c1;
+    vec2 c2;
+ } components;
+
+void main()
+{
+	vec4 fail_color = vec4(1.0, 0.0, 0.0, 1.0);
+	color = vec4(0.0, 1.0, 0.0, 1.0);
+
+	if (components.c1 != vec4(17550.3588006, 13929.9686885, 32218.2560311, -2830.83346304))
+	   color = fail_color;
+
+	if (components.c2 != vec2(-6948.05485618, 11340.2324865))
+	   color = fail_color;
+
+	if (vertexColor != vec4(0.0, 1.0, 0.0, 1.0))
+	   color = fail_color;
+}
+
+[test]
+clear color 1.0 0.0 0.0 0.0
+clear
+
+ssbo 5 32 # size, aligned to 16
+#c1
+ssbo 5 subdata float 0  17550.3588006
+ssbo 5 subdata float 4  13929.9686885
+ssbo 5 subdata float 8  32218.2560311
+ssbo 5 subdata float 12 -2830.83346304
+#c2
+ssbo 5 subdata float 16 -6948.05485618
+ssbo 5 subdata float 20 11340.2324865
+
+block binding 5
+verify program_interface_query GL_SHADER_STORAGE_BLOCK ssbo GL_NUM_ACTIVE_VARIABLES 2
+verify program_interface_query GL_SHADER_STORAGE_BLOCK ssbo GL_BUFFER_DATA_SIZE 32
+
+verify program_query GL_ACTIVE_UNIFORMS 0
+
+draw rect -1 -1 2 2
+probe all rgba 0.0 1.0 0.0 1.0
diff --git a/tests/spec/arb_gl_spirv/execution/ubo/array-indirect.shader_test b/tests/spec/arb_gl_spirv/execution/ubo/array-indirect.shader_test
new file mode 100644
index 000000000..6d6dd2f2d
--- /dev/null
+++ b/tests/spec/arb_gl_spirv/execution/ubo/array-indirect.shader_test
@@ -0,0 +1,108 @@ 
+# UBO test using an array of ubo and indirect(dynamically uniform)
+# indexing. Just uses one stage.
+
+[require]
+SPIRV YES
+GL >= 3.3
+GLSL >= 4.50
+GL_ARB_gl_spirv
+
+[vertex shader passthrough]
+
+[fragment shader spirv]
+; Automatically generated from the GLSL by shader_test_spirv.py. DO NOT EDIT
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 24
+; Schema: 0
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %main "main" %outColor
+               OpExecutionMode %main OriginLowerLeft
+               OpSource GLSL 450
+               OpDecorate %outColor Location 0
+               OpMemberDecorate %ComponentsBlock 0 Offset 0
+               OpDecorate %ComponentsBlock Block
+               OpDecorate %components DescriptorSet 0
+               OpDecorate %components Binding 5
+               OpDecorate %u_idx Location 10
+               OpDecorate %u_idx DescriptorSet 0
+               OpDecorate %u_idx Binding 0
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+   %outColor = OpVariable %_ptr_Output_v4float Output
+%ComponentsBlock = OpTypeStruct %v4float
+       %uint = OpTypeInt 32 0
+     %uint_2 = OpConstant %uint 2
+%_arr_ComponentsBlock_uint_2 = OpTypeArray %ComponentsBlock %uint_2
+%_ptr_Uniform__arr_ComponentsBlock_uint_2 = OpTypePointer Uniform %_arr_ComponentsBlock_uint_2
+ %components = OpVariable %_ptr_Uniform__arr_ComponentsBlock_uint_2 Uniform
+        %int = OpTypeInt 32 1
+%_ptr_UniformConstant_int = OpTypePointer UniformConstant %int
+      %u_idx = OpVariable %_ptr_UniformConstant_int UniformConstant
+      %int_0 = OpConstant %int 0
+%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+         %19 = OpLoad %int %u_idx
+         %22 = OpAccessChain %_ptr_Uniform_v4float %components %19 %int_0
+         %23 = OpLoad %v4float %22
+               OpStore %outColor %23
+               OpReturn
+               OpFunctionEnd
+
+[fragment shader]
+
+#version 450
+
+layout (location = 0) out vec4 outColor;
+layout (location = 10) uniform int u_idx;
+
+layout (std140, binding = 5) uniform ComponentsBlock
+ {
+    vec4 c1;
+ } components[2];
+
+void main()
+{
+	outColor = components[u_idx].c1;
+}
+
+[test]
+clear color 1.0 0.0 0.0 0.0
+clear
+
+block binding 5
+
+block array index 0
+block offset 0
+uniform vec4 ComponentsBlock.c1 0.1 0.2 0.3 0.4
+
+block array index 1
+block offset 0
+uniform vec4 ComponentsBlock.c1 0.4 0.3 0.2 0.1
+
+uniform int 10 0 # location 10, uniform u_idx
+
+draw rect -1 -1 2 2
+probe all rgba 0.1 0.2 0.3 0.4
+
+uniform int 10 1 # location 10, uniform u_idx
+
+block binding 5
+verify program_interface_query GL_UNIFORM_BLOCK ComponentsBlock[0] GL_NUM_ACTIVE_VARIABLES 1
+verify program_interface_query GL_UNIFORM_BLOCK ComponentsBlock[1] GL_BUFFER_DATA_SIZE 16
+
+block binding 6
+verify program_interface_query GL_UNIFORM_BLOCK ComponentsBlock[0] GL_NUM_ACTIVE_VARIABLES 1
+verify program_interface_query GL_UNIFORM_BLOCK ComponentsBlock[1] GL_BUFFER_DATA_SIZE 16
+
+verify program_query GL_ACTIVE_UNIFORMS 2
+
+draw rect -1 -1 2 2
+probe all rgba 0.4 0.3 0.2 0.1
diff --git a/tests/spec/arb_gl_spirv/execution/ubo/array-inside-ubo.shader_test b/tests/spec/arb_gl_spirv/execution/ubo/array-inside-ubo.shader_test
new file mode 100644
index 000000000..e8f6bedaa
--- /dev/null
+++ b/tests/spec/arb_gl_spirv/execution/ubo/array-inside-ubo.shader_test
@@ -0,0 +1,155 @@ 
+# Using a array inside a ubo, instead of an array of ubo.
+
+[require]
+SPIRV YES
+GL >= 3.3
+GLSL >= 4.50
+GL_ARB_gl_spirv
+
+[vertex shader passthrough]
+
+[fragment shader spirv]
+; Automatically generated from the GLSL by shader_test_spirv.py. DO NOT EDIT
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 65
+; Schema: 0
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %main "main" %color
+               OpExecutionMode %main OriginLowerLeft
+               OpSource GLSL 450
+               OpDecorate %color Location 0
+               OpDecorate %_arr_v4float_uint_3 ArrayStride 16
+               OpMemberDecorate %block 0 Offset 0
+               OpDecorate %block Block
+               OpDecorate %arr DescriptorSet 0
+               OpDecorate %arr Binding 5
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+    %float_1 = OpConstant %float 1
+    %float_0 = OpConstant %float 0
+         %12 = OpConstantComposite %v4float %float_1 %float_0 %float_0 %float_1
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+      %color = OpVariable %_ptr_Output_v4float Output
+         %15 = OpConstantComposite %v4float %float_0 %float_1 %float_0 %float_0
+       %uint = OpTypeInt 32 0
+     %uint_3 = OpConstant %uint 3
+%_arr_v4float_uint_3 = OpTypeArray %v4float %uint_3
+      %block = OpTypeStruct %_arr_v4float_uint_3
+%_ptr_Uniform_block = OpTypePointer Uniform %block
+        %arr = OpVariable %_ptr_Uniform_block Uniform
+        %int = OpTypeInt 32 1
+      %int_0 = OpConstant %int 0
+%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
+%float_n29816_0098 = OpConstant %float -29816.0098
+%float_4996_51611 = OpConstant %float 4996.51611
+%float_22829_4688 = OpConstant %float 22829.4688
+%float_n30383_2031 = OpConstant %float -30383.2031
+         %31 = OpConstantComposite %v4float %float_n29816_0098 %float_4996_51611 %float_22829_4688 %float_n30383_2031
+       %bool = OpTypeBool
+     %v4bool = OpTypeVector %bool 4
+      %int_1 = OpConstant %int 1
+%float_5720_54443 = OpConstant %float 5720.54443
+%float_n21857_1582 = OpConstant %float -21857.1582
+%float_n711_078674 = OpConstant %float -711.078674
+%float_8904_7334 = OpConstant %float 8904.7334
+         %46 = OpConstantComposite %v4float %float_5720_54443 %float_n21857_1582 %float_n711_078674 %float_8904_7334
+      %int_2 = OpConstant %int 2
+%float_31933_2734 = OpConstant %float 31933.2734
+%float_n11642_8975 = OpConstant %float -11642.8975
+%float_9012_23633 = OpConstant %float 9012.23633
+%float_n6150_84961 = OpConstant %float -6150.84961
+         %59 = OpConstantComposite %v4float %float_31933_2734 %float_n11642_8975 %float_9012_23633 %float_n6150_84961
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+ %fail_color = OpVariable %_ptr_Function_v4float Function
+               OpStore %fail_color %12
+               OpStore %color %15
+         %25 = OpAccessChain %_ptr_Uniform_v4float %arr %int_0 %int_0
+         %26 = OpLoad %v4float %25
+         %34 = OpFOrdNotEqual %v4bool %26 %31
+         %35 = OpAny %bool %34
+               OpSelectionMerge %37 None
+               OpBranchConditional %35 %36 %37
+         %36 = OpLabel
+         %38 = OpLoad %v4float %fail_color
+               OpStore %color %38
+               OpBranch %37
+         %37 = OpLabel
+         %40 = OpAccessChain %_ptr_Uniform_v4float %arr %int_0 %int_1
+         %41 = OpLoad %v4float %40
+         %47 = OpFOrdNotEqual %v4bool %41 %46
+         %48 = OpAny %bool %47
+               OpSelectionMerge %50 None
+               OpBranchConditional %48 %49 %50
+         %49 = OpLabel
+         %51 = OpLoad %v4float %fail_color
+               OpStore %color %51
+               OpBranch %50
+         %50 = OpLabel
+         %53 = OpAccessChain %_ptr_Uniform_v4float %arr %int_0 %int_2
+         %54 = OpLoad %v4float %53
+         %60 = OpFOrdNotEqual %v4bool %54 %59
+         %61 = OpAny %bool %60
+               OpSelectionMerge %63 None
+               OpBranchConditional %61 %62 %63
+         %62 = OpLabel
+         %64 = OpLoad %v4float %fail_color
+               OpStore %color %64
+               OpBranch %63
+         %63 = OpLabel
+               OpReturn
+               OpFunctionEnd
+
+[fragment shader]
+#version 450
+
+layout (location = 0) out vec4 color;
+
+layout (std140, binding = 5) uniform block {
+	vec4 color[3];
+} arr;
+
+
+
+void main()
+{
+	vec4 fail_color = vec4(1.0, 0.0, 0.0, 1.0);
+        color = vec4(0.0, 1.0, 0.0, 0.0);
+
+	if (arr.color[0] != vec4(-29816.0100557, 4996.51593805, 22829.4693217, -30383.203006))
+	   color = fail_color;
+
+	if (arr.color[1] != vec4(5720.54428931, -21857.1581292, -711.078644999, 8904.73374533))
+	   color = fail_color;
+
+	if (arr.color[2] != vec4(31933.27393, -11642.8972152, 9012.23624018, -6150.84975967))
+	   color = fail_color;
+}
+
+
+[test]
+clear color 0.2 0.2 0.2 0.2
+clear
+
+block binding 5
+block offset 0
+uniform vec4 block.color[0] -29816.0100557 4996.51593805 22829.4693217 -30383.203006
+block offset 16
+uniform vec4 block.color[1] 5720.54428931 -21857.1581292 -711.078644999 8904.73374533
+block offset 32
+uniform vec4 block.color[2] 31933.27393 -11642.8972152 9012.23624018 -6150.84975967
+
+verify program_interface_query GL_UNIFORM_BLOCK block GL_NUM_ACTIVE_VARIABLES 1
+verify program_interface_query GL_UNIFORM_BLOCK block GL_BUFFER_DATA_SIZE 48
+
+verify program_query GL_ACTIVE_UNIFORMS 1
+
+draw rect -1 -1 2 2
+probe all rgba 0.0 1.0 0.0 0.0
diff --git a/tests/spec/arb_gl_spirv/execution/ubo/array-of-arrays-inside-ubo.shader_test b/tests/spec/arb_gl_spirv/execution/ubo/array-of-arrays-inside-ubo.shader_test
new file mode 100644
index 000000000..9c8dbf819
--- /dev/null
+++ b/tests/spec/arb_gl_spirv/execution/ubo/array-of-arrays-inside-ubo.shader_test
@@ -0,0 +1,185 @@ 
+# Using a array of arrays inside a ubo, instead of a aoa of ubos.
+
+[require]
+SPIRV YES
+GL >= 3.3
+GLSL >= 4.50
+GL_ARB_gl_spirv
+
+[vertex shader passthrough]
+
+[fragment shader spirv]
+; Automatically generated from the GLSL by shader_test_spirv.py. DO NOT EDIT
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 77
+; Schema: 0
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %main "main" %color
+               OpExecutionMode %main OriginLowerLeft
+               OpSource GLSL 450
+               OpDecorate %color Location 0
+               OpDecorate %_arr_v4float_uint_4 ArrayStride 16
+               OpDecorate %_arr__arr_v4float_uint_4_uint_3 ArrayStride 64
+               OpDecorate %_arr__arr__arr_v4float_uint_4_uint_3_uint_2 ArrayStride 192
+               OpDecorate %_arr_v4float_uint_2 ArrayStride 16
+               OpDecorate %_arr__arr_v4float_uint_2_uint_2 ArrayStride 32
+               OpMemberDecorate %block 0 Offset 0
+               OpMemberDecorate %block 1 Offset 384
+               OpDecorate %block Block
+               OpDecorate %arr DescriptorSet 0
+               OpDecorate %arr Binding 5
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+    %float_1 = OpConstant %float 1
+    %float_0 = OpConstant %float 0
+         %12 = OpConstantComposite %v4float %float_1 %float_0 %float_0 %float_1
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+      %color = OpVariable %_ptr_Output_v4float Output
+         %15 = OpConstantComposite %v4float %float_0 %float_1 %float_0 %float_1
+       %uint = OpTypeInt 32 0
+     %uint_4 = OpConstant %uint 4
+%_arr_v4float_uint_4 = OpTypeArray %v4float %uint_4
+     %uint_3 = OpConstant %uint 3
+%_arr__arr_v4float_uint_4_uint_3 = OpTypeArray %_arr_v4float_uint_4 %uint_3
+     %uint_2 = OpConstant %uint 2
+%_arr__arr__arr_v4float_uint_4_uint_3_uint_2 = OpTypeArray %_arr__arr_v4float_uint_4_uint_3 %uint_2
+%_arr_v4float_uint_2 = OpTypeArray %v4float %uint_2
+%_arr__arr_v4float_uint_2_uint_2 = OpTypeArray %_arr_v4float_uint_2 %uint_2
+      %block = OpTypeStruct %_arr__arr__arr_v4float_uint_4_uint_3_uint_2 %_arr__arr_v4float_uint_2_uint_2
+%_ptr_Uniform_block = OpTypePointer Uniform %block
+        %arr = OpVariable %_ptr_Uniform_block Uniform
+        %int = OpTypeInt 32 1
+      %int_0 = OpConstant %int 0
+%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
+%float_0_100000001 = OpConstant %float 0.100000001
+%float_0_200000003 = OpConstant %float 0.200000003
+%float_0_300000012 = OpConstant %float 0.300000012
+         %36 = OpConstantComposite %v4float %float_0 %float_0_100000001 %float_0_200000003 %float_0_300000012
+       %bool = OpTypeBool
+     %v4bool = OpTypeVector %bool 4
+      %int_1 = OpConstant %int 1
+%float_0_400000006 = OpConstant %float 0.400000006
+  %float_0_5 = OpConstant %float 0.5
+%float_0_600000024 = OpConstant %float 0.600000024
+%float_0_699999988 = OpConstant %float 0.699999988
+         %51 = OpConstantComposite %v4float %float_0_400000006 %float_0_5 %float_0_600000024 %float_0_699999988
+      %int_2 = OpConstant %int 2
+      %int_3 = OpConstant %int 3
+%float_0_800000012 = OpConstant %float 0.800000012
+%float_0_899999976 = OpConstant %float 0.899999976
+         %63 = OpConstantComposite %v4float %float_0_800000012 %float_0_899999976 %float_1 %float_0_100000001
+         %71 = OpConstantComposite %v4float %float_0_300000012 %float_0_5 %float_0_699999988 %float_0_899999976
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+ %fail_color = OpVariable %_ptr_Function_v4float Function
+               OpStore %fail_color %12
+               OpStore %color %15
+         %31 = OpAccessChain %_ptr_Uniform_v4float %arr %int_0 %int_0 %int_0 %int_0
+         %32 = OpLoad %v4float %31
+         %39 = OpFOrdNotEqual %v4bool %32 %36
+         %40 = OpAny %bool %39
+               OpSelectionMerge %42 None
+               OpBranchConditional %40 %41 %42
+         %41 = OpLabel
+         %43 = OpLoad %v4float %fail_color
+               OpStore %color %43
+               OpBranch %42
+         %42 = OpLabel
+         %45 = OpAccessChain %_ptr_Uniform_v4float %arr %int_0 %int_1 %int_1 %int_1
+         %46 = OpLoad %v4float %45
+         %52 = OpFOrdNotEqual %v4bool %46 %51
+         %53 = OpAny %bool %52
+               OpSelectionMerge %55 None
+               OpBranchConditional %53 %54 %55
+         %54 = OpLabel
+         %56 = OpLoad %v4float %fail_color
+               OpStore %color %56
+               OpBranch %55
+         %55 = OpLabel
+         %59 = OpAccessChain %_ptr_Uniform_v4float %arr %int_0 %int_1 %int_2 %int_3
+         %60 = OpLoad %v4float %59
+         %64 = OpFOrdNotEqual %v4bool %60 %63
+         %65 = OpAny %bool %64
+               OpSelectionMerge %67 None
+               OpBranchConditional %65 %66 %67
+         %66 = OpLabel
+         %68 = OpLoad %v4float %fail_color
+               OpStore %color %68
+               OpBranch %67
+         %67 = OpLabel
+         %69 = OpAccessChain %_ptr_Uniform_v4float %arr %int_1 %int_1 %int_1
+         %70 = OpLoad %v4float %69
+         %72 = OpFOrdNotEqual %v4bool %70 %71
+         %73 = OpAny %bool %72
+               OpSelectionMerge %75 None
+               OpBranchConditional %73 %74 %75
+         %74 = OpLabel
+         %76 = OpLoad %v4float %fail_color
+               OpStore %color %76
+               OpBranch %75
+         %75 = OpLabel
+               OpReturn
+               OpFunctionEnd
+
+[fragment shader]
+#version 450
+
+layout (location = 0) out vec4 color;
+
+layout (std140, binding = 5, std140) uniform block {
+	vec4 color[2][3][4];
+	vec4 position[2][2];
+} arr;
+
+
+
+void main()
+{
+	vec4 fail_color = vec4(1.0, 0.0, 0.0, 1.0);
+	color = vec4(0.0, 1.0, 0.0, 1.0);
+
+	if (arr.color[0][0][0] != vec4(0.0, 0.1, 0.2, 0.3))
+	   color = fail_color;
+
+	if (arr.color[1][1][1] != vec4(0.4, 0.5, 0.6, 0.7))
+	   color = fail_color;
+
+	if (arr.color[1][2][3] != vec4(0.8, 0.9, 1.0, 0.1))
+	   color = fail_color;
+
+	if (arr.position[1][1] != vec4(0.3, 0.5, 0.7, 0.9))
+	   color = fail_color;
+}
+
+[test]
+clear color 0.2 0.2 0.2 0.2
+clear
+
+block binding 5
+block offset 0
+uniform vec4 block.color[0][0][0] 0.0 0.1 0.2 0.3
+
+block offset 272
+uniform vec4 block.color[1][1][1] 0.4 0.5 0.6 0.7
+
+block offset 368
+uniform vec4 block.color[1][2][3] 0.8 0.9 1.0 0.1
+
+block offset 432
+uniform vec4 block.position[1][1] 0.3 0.5 0.7 0.9
+
+
+verify program_interface_query GL_UNIFORM_BLOCK block GL_NUM_ACTIVE_VARIABLES 8
+verify program_interface_query GL_UNIFORM_BLOCK block GL_BUFFER_DATA_SIZE 448
+
+verify program_query GL_ACTIVE_UNIFORMS 8
+
+draw rect -1 -1 2 2
+probe all rgba 0.0 1.0 0.0 1.0
diff --git a/tests/spec/arb_gl_spirv/execution/ubo/array.shader_test b/tests/spec/arb_gl_spirv/execution/ubo/array.shader_test
new file mode 100644
index 000000000..b51c17db4
--- /dev/null
+++ b/tests/spec/arb_gl_spirv/execution/ubo/array.shader_test
@@ -0,0 +1,140 @@ 
+# UBO test using an array of ubos.
+
+[require]
+SPIRV YES
+GL >= 3.3
+GLSL >= 4.50
+GL_ARB_gl_spirv
+
+[vertex shader passthrough]
+
+[fragment shader spirv]
+; Automatically generated from the GLSL by shader_test_spirv.py. DO NOT EDIT
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 52
+; Schema: 0
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %main "main" %color
+               OpExecutionMode %main OriginLowerLeft
+               OpSource GLSL 450
+               OpDecorate %color Location 0
+               OpMemberDecorate %ComponentsBlock 0 Offset 0
+               OpDecorate %ComponentsBlock Block
+               OpDecorate %components DescriptorSet 0
+               OpDecorate %components Binding 5
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+    %float_1 = OpConstant %float 1
+    %float_0 = OpConstant %float 0
+         %12 = OpConstantComposite %v4float %float_1 %float_0 %float_0 %float_1
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+      %color = OpVariable %_ptr_Output_v4float Output
+         %15 = OpConstantComposite %v4float %float_0 %float_1 %float_0 %float_1
+%ComponentsBlock = OpTypeStruct %v4float
+       %uint = OpTypeInt 32 0
+     %uint_2 = OpConstant %uint 2
+%_arr_ComponentsBlock_uint_2 = OpTypeArray %ComponentsBlock %uint_2
+%_ptr_Uniform__arr_ComponentsBlock_uint_2 = OpTypePointer Uniform %_arr_ComponentsBlock_uint_2
+ %components = OpVariable %_ptr_Uniform__arr_ComponentsBlock_uint_2 Uniform
+        %int = OpTypeInt 32 1
+      %int_0 = OpConstant %int 0
+%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
+%float_20530_7109 = OpConstant %float 20530.7109
+%float_n10508_5107 = OpConstant %float -10508.5107
+%float_n23051_9961 = OpConstant %float -23051.9961
+%float_n23564_0664 = OpConstant %float -23564.0664
+         %31 = OpConstantComposite %v4float %float_20530_7109 %float_n10508_5107 %float_n23051_9961 %float_n23564_0664
+       %bool = OpTypeBool
+     %v4bool = OpTypeVector %bool 4
+      %int_1 = OpConstant %int 1
+%float_n3274_39771 = OpConstant %float -3274.39771
+%float_n7391_61914 = OpConstant %float -7391.61914
+%float_29371_457 = OpConstant %float 29371.457
+%float_7793_47266 = OpConstant %float 7793.47266
+         %46 = OpConstantComposite %v4float %float_n3274_39771 %float_n7391_61914 %float_29371_457 %float_7793_47266
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+ %fail_color = OpVariable %_ptr_Function_v4float Function
+               OpStore %fail_color %12
+               OpStore %color %15
+         %25 = OpAccessChain %_ptr_Uniform_v4float %components %int_0 %int_0
+         %26 = OpLoad %v4float %25
+         %34 = OpFOrdNotEqual %v4bool %26 %31
+         %35 = OpAny %bool %34
+               OpSelectionMerge %37 None
+               OpBranchConditional %35 %36 %37
+         %36 = OpLabel
+         %38 = OpLoad %v4float %fail_color
+               OpStore %color %38
+               OpBranch %37
+         %37 = OpLabel
+         %40 = OpAccessChain %_ptr_Uniform_v4float %components %int_1 %int_0
+         %41 = OpLoad %v4float %40
+         %47 = OpFOrdNotEqual %v4bool %41 %46
+         %48 = OpAny %bool %47
+               OpSelectionMerge %50 None
+               OpBranchConditional %48 %49 %50
+         %49 = OpLabel
+         %51 = OpLoad %v4float %fail_color
+               OpStore %color %51
+               OpBranch %50
+         %50 = OpLabel
+               OpReturn
+               OpFunctionEnd
+
+[fragment shader]
+
+#version 450
+
+layout (location = 0) out vec4 color;
+layout (std140, binding = 5, row_major) uniform ComponentsBlock
+ {
+    vec4 c1;
+ } components[2];
+
+void main()
+{
+	vec4 fail_color = vec4(1.0, 0.0, 0.0, 1.0);
+	color = vec4(0.0, 1.0, 0.0, 1.0);
+
+	if (components[0].c1 != vec4(20530.7108263, -10508.5105669, -23051.9953613, -23564.0673228))
+	   color = fail_color;
+
+	if (components[1].c1 != vec4(-3274.39775692, -7391.61915007, 29371.4563058, 7793.47278553))
+	   color = fail_color;
+}
+
+
+[test]
+clear color 1.0 0.0 0.0 0.0
+clear
+
+block binding 5
+
+block array index 0
+block offset 0
+uniform vec4 ComponentsBlock.c1 20530.7108263 -10508.5105669 -23051.9953613 -23564.0673228
+
+block array index 1
+block offset 0
+uniform vec4 ComponentsBlock.c1 -3274.39775692 -7391.61915007 29371.4563058 7793.47278553
+
+block binding 5
+verify program_interface_query GL_UNIFORM_BLOCK ComponentsBlock[0] GL_NUM_ACTIVE_VARIABLES 1
+verify program_interface_query GL_UNIFORM_BLOCK ComponentsBlock[0] GL_BUFFER_DATA_SIZE 16
+
+block binding 6
+verify program_interface_query GL_UNIFORM_BLOCK ComponentsBlock[1] GL_NUM_ACTIVE_VARIABLES 1
+verify program_interface_query GL_UNIFORM_BLOCK ComponentsBlock[1] GL_BUFFER_DATA_SIZE 16
+
+verify program_query GL_ACTIVE_UNIFORMS 1
+
+draw rect -1 -1 2 2
+probe all rgba 0.0 1.0 0.0 1.0
diff --git a/tests/spec/arb_gl_spirv/execution/ubo/location-0-crash.shader_test b/tests/spec/arb_gl_spirv/execution/ubo/location-0-crash.shader_test
new file mode 100644
index 000000000..eea4d1e42
--- /dev/null
+++ b/tests/spec/arb_gl_spirv/execution/ubo/location-0-crash.shader_test
@@ -0,0 +1,94 @@ 
+# This test has:
+#  * An ubo
+#  * An uniform with location 0
+#
+# At one point this test crashed. Keeping for regression catching.
+
+
+[require]
+SPIRV YES
+GL >= 3.3
+GLSL >= 4.50
+GL_ARB_gl_spirv
+
+[vertex shader passthrough]
+
+[fragment shader spirv]
+; Automatically generated from the GLSL by shader_test_spirv.py. DO NOT EDIT
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 24
+; Schema: 0
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %main "main" %color
+               OpExecutionMode %main OriginLowerLeft
+               OpSource GLSL 450
+               OpDecorate %color Location 0
+               OpMemberDecorate %block 0 Offset 0
+               OpDecorate %block Block
+               OpDecorate %arr DescriptorSet 0
+               OpDecorate %arr Binding 5
+               OpDecorate %n Location 0
+               OpDecorate %n DescriptorSet 0
+               OpDecorate %n Binding 0
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+      %color = OpVariable %_ptr_Output_v4float Output
+      %block = OpTypeStruct %v4float
+%_ptr_Uniform_block = OpTypePointer Uniform %block
+        %arr = OpVariable %_ptr_Uniform_block Uniform
+        %int = OpTypeInt 32 1
+      %int_0 = OpConstant %int 0
+%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
+%_ptr_UniformConstant_int = OpTypePointer UniformConstant %int
+          %n = OpVariable %_ptr_UniformConstant_int UniformConstant
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+         %16 = OpAccessChain %_ptr_Uniform_v4float %arr %int_0
+         %17 = OpLoad %v4float %16
+         %20 = OpLoad %int %n
+         %21 = OpConvertSToF %float %20
+         %22 = OpCompositeConstruct %v4float %21 %21 %21 %21
+         %23 = OpFAdd %v4float %17 %22
+               OpStore %color %23
+               OpReturn
+               OpFunctionEnd
+
+[fragment shader]
+#version 450
+
+layout (location = 0) out vec4 color;
+layout (std140, binding = 5) uniform block {
+	vec4 color;
+} arr;
+
+layout (location = 0) uniform int n;
+
+
+void main()
+{
+	color = arr.color + vec4(n);
+}
+
+[test]
+clear color 1.0 0.0 0.0 0.0
+clear
+
+block binding 5
+block offset 0
+block offset 0
+uniform vec4 block.color 0.0 0.1 0.2 0.3
+
+verify program_interface_query GL_UNIFORM_BLOCK block GL_NUM_ACTIVE_VARIABLES 1
+verify program_interface_query GL_UNIFORM_BLOCK block GL_BUFFER_DATA_SIZE 16
+
+verify program_query GL_ACTIVE_UNIFORMS 2
+
+draw rect -1 -1 2 2
+probe all rgba 0.0 0.1 0.2 0.3
diff --git a/tests/spec/arb_gl_spirv/execution/ubo/simple.shader_test b/tests/spec/arb_gl_spirv/execution/ubo/simple.shader_test
new file mode 100644
index 000000000..2fae49adc
--- /dev/null
+++ b/tests/spec/arb_gl_spirv/execution/ubo/simple.shader_test
@@ -0,0 +1,131 @@ 
+# Simple UBO test: just one stage. No arrays.
+
+[require]
+SPIRV YES
+GL >= 3.3
+GLSL >= 4.50
+GL_ARB_gl_spirv
+
+[vertex shader passthrough]
+
+[fragment shader spirv]
+; Automatically generated from the GLSL by shader_test_spirv.py. DO NOT EDIT
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 50
+; Schema: 0
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %main "main" %color
+               OpExecutionMode %main OriginLowerLeft
+               OpSource GLSL 450
+               OpDecorate %color Location 0
+               OpMemberDecorate %ComponentsBlock 0 Offset 0
+               OpMemberDecorate %ComponentsBlock 1 Offset 16
+               OpDecorate %ComponentsBlock Block
+               OpDecorate %components DescriptorSet 0
+               OpDecorate %components Binding 5
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+    %float_1 = OpConstant %float 1
+    %float_0 = OpConstant %float 0
+         %12 = OpConstantComposite %v4float %float_1 %float_0 %float_0 %float_1
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+      %color = OpVariable %_ptr_Output_v4float Output
+         %15 = OpConstantComposite %v4float %float_0 %float_1 %float_0 %float_1
+    %v2float = OpTypeVector %float 2
+%ComponentsBlock = OpTypeStruct %v4float %v2float
+%_ptr_Uniform_ComponentsBlock = OpTypePointer Uniform %ComponentsBlock
+ %components = OpVariable %_ptr_Uniform_ComponentsBlock Uniform
+        %int = OpTypeInt 32 1
+      %int_0 = OpConstant %int 0
+%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
+%float_4575_7998 = OpConstant %float 4575.7998
+%float_14191_6123 = OpConstant %float 14191.6123
+%float_n30199_3086 = OpConstant %float -30199.3086
+%float_n31303_4219 = OpConstant %float -31303.4219
+         %29 = OpConstantComposite %v4float %float_4575_7998 %float_14191_6123 %float_n30199_3086 %float_n31303_4219
+       %bool = OpTypeBool
+     %v4bool = OpTypeVector %bool 4
+      %int_1 = OpConstant %int 1
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+%float_n10231_1807 = OpConstant %float -10231.1807
+%float_11729_6475 = OpConstant %float 11729.6475
+         %43 = OpConstantComposite %v2float %float_n10231_1807 %float_11729_6475
+     %v2bool = OpTypeVector %bool 2
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+ %fail_color = OpVariable %_ptr_Function_v4float Function
+               OpStore %fail_color %12
+               OpStore %color %15
+         %23 = OpAccessChain %_ptr_Uniform_v4float %components %int_0
+         %24 = OpLoad %v4float %23
+         %32 = OpFOrdNotEqual %v4bool %24 %29
+         %33 = OpAny %bool %32
+               OpSelectionMerge %35 None
+               OpBranchConditional %33 %34 %35
+         %34 = OpLabel
+         %36 = OpLoad %v4float %fail_color
+               OpStore %color %36
+               OpBranch %35
+         %35 = OpLabel
+         %39 = OpAccessChain %_ptr_Uniform_v2float %components %int_1
+         %40 = OpLoad %v2float %39
+         %45 = OpFOrdNotEqual %v2bool %40 %43
+         %46 = OpAny %bool %45
+               OpSelectionMerge %48 None
+               OpBranchConditional %46 %47 %48
+         %47 = OpLabel
+         %49 = OpLoad %v4float %fail_color
+               OpStore %color %49
+               OpBranch %48
+         %48 = OpLabel
+               OpReturn
+               OpFunctionEnd
+
+[fragment shader]
+
+#version 450
+
+layout (location = 0) out vec4 color;
+layout (std140, binding = 5) uniform ComponentsBlock
+ {
+    vec4 c1;
+    vec2 c2;
+ } components;
+
+void main()
+{
+	vec4 fail_color = vec4(1.0, 0.0, 0.0, 1.0);
+	color = vec4(0.0, 1.0, 0.0, 1.0);
+
+	if (components.c1 != vec4(4575.7996643, 14191.6120546, -30199.3084764, -31303.4210269))
+	   color = fail_color;
+
+	if (components.c2 != vec2(-10231.1810483, 11729.6478218))
+	   color = fail_color;
+}
+
+[test]
+clear color 1.0 0.0 0.0 0.0
+clear
+
+
+block binding 5
+block offset 0
+uniform vec4 ComponentsBlock.c1 4575.7996643 14191.6120546 -30199.3084764 -31303.4210269
+block offset 16
+uniform vec2 ComponentsBlock.c2 -10231.1810483 11729.6478218
+
+verify program_interface_query GL_UNIFORM_BLOCK ComponentsBlock GL_NUM_ACTIVE_VARIABLES 2
+verify program_interface_query GL_UNIFORM_BLOCK ComponentsBlock GL_BUFFER_DATA_SIZE 32
+
+verify program_query GL_ACTIVE_UNIFORMS 2
+
+draw rect -1 -1 2 2
+probe all rgba 0.0 1.0 0.0 1.0
diff --git a/tests/spec/arb_gl_spirv/execution/ubo/two-stages.shader_test b/tests/spec/arb_gl_spirv/execution/ubo/two-stages.shader_test
new file mode 100644
index 000000000..3ebdeb451
--- /dev/null
+++ b/tests/spec/arb_gl_spirv/execution/ubo/two-stages.shader_test
@@ -0,0 +1,276 @@ 
+# Simple UBO test with two stages using the same UBO.
+
+[require]
+SPIRV YES
+GL >= 3.3
+GLSL >= 4.50
+GL_ARB_gl_spirv
+
+[vertex shader spirv]
+; Automatically generated from the GLSL by shader_test_spirv.py. DO NOT EDIT
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 63
+; Schema: 0
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Vertex %main "main" %vertexColor %_ %piglit_vertex %gl_VertexID %gl_InstanceID
+               OpSource GLSL 450
+               OpName %_ ""
+               OpDecorate %vertexColor Location 1
+               OpMemberDecorate %ComponentsBlock 0 Offset 0
+               OpMemberDecorate %ComponentsBlock 1 Offset 16
+               OpDecorate %ComponentsBlock Block
+               OpDecorate %components DescriptorSet 0
+               OpDecorate %components Binding 5
+               OpMemberDecorate %gl_PerVertex 0 BuiltIn Position
+               OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize
+               OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance
+               OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance
+               OpDecorate %gl_PerVertex Block
+               OpDecorate %piglit_vertex Location 0
+               OpDecorate %gl_VertexID BuiltIn VertexId
+               OpDecorate %gl_InstanceID BuiltIn InstanceId
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+    %float_1 = OpConstant %float 1
+    %float_0 = OpConstant %float 0
+         %12 = OpConstantComposite %v4float %float_1 %float_0 %float_0 %float_1
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+%vertexColor = OpVariable %_ptr_Output_v4float Output
+         %15 = OpConstantComposite %v4float %float_0 %float_1 %float_0 %float_1
+    %v2float = OpTypeVector %float 2
+%ComponentsBlock = OpTypeStruct %v4float %v2float
+%_ptr_Uniform_ComponentsBlock = OpTypePointer Uniform %ComponentsBlock
+ %components = OpVariable %_ptr_Uniform_ComponentsBlock Uniform
+        %int = OpTypeInt 32 1
+      %int_0 = OpConstant %int 0
+%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
+%float_4575_7998 = OpConstant %float 4575.7998
+%float_14191_6123 = OpConstant %float 14191.6123
+%float_n30199_3086 = OpConstant %float -30199.3086
+%float_n31303_4219 = OpConstant %float -31303.4219
+         %29 = OpConstantComposite %v4float %float_4575_7998 %float_14191_6123 %float_n30199_3086 %float_n31303_4219
+       %bool = OpTypeBool
+     %v4bool = OpTypeVector %bool 4
+      %int_1 = OpConstant %int 1
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+%float_n10231_1807 = OpConstant %float -10231.1807
+%float_11729_6475 = OpConstant %float 11729.6475
+         %43 = OpConstantComposite %v2float %float_n10231_1807 %float_11729_6475
+     %v2bool = OpTypeVector %bool 2
+       %uint = OpTypeInt 32 0
+     %uint_1 = OpConstant %uint 1
+%_arr_float_uint_1 = OpTypeArray %float %uint_1
+%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1
+%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex
+          %_ = OpVariable %_ptr_Output_gl_PerVertex Output
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+%piglit_vertex = OpVariable %_ptr_Input_v4float Input
+%_ptr_Input_int = OpTypePointer Input %int
+%gl_VertexID = OpVariable %_ptr_Input_int Input
+%gl_InstanceID = OpVariable %_ptr_Input_int Input
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+ %fail_color = OpVariable %_ptr_Function_v4float Function
+               OpStore %fail_color %12
+               OpStore %vertexColor %15
+         %23 = OpAccessChain %_ptr_Uniform_v4float %components %int_0
+         %24 = OpLoad %v4float %23
+         %32 = OpFOrdNotEqual %v4bool %24 %29
+         %33 = OpAny %bool %32
+               OpSelectionMerge %35 None
+               OpBranchConditional %33 %34 %35
+         %34 = OpLabel
+         %36 = OpLoad %v4float %fail_color
+               OpStore %vertexColor %36
+               OpBranch %35
+         %35 = OpLabel
+         %39 = OpAccessChain %_ptr_Uniform_v2float %components %int_1
+         %40 = OpLoad %v2float %39
+         %45 = OpFOrdNotEqual %v2bool %40 %43
+         %46 = OpAny %bool %45
+               OpSelectionMerge %48 None
+               OpBranchConditional %46 %47 %48
+         %47 = OpLabel
+         %49 = OpLoad %v4float %fail_color
+               OpStore %vertexColor %49
+               OpBranch %48
+         %48 = OpLabel
+         %58 = OpLoad %v4float %piglit_vertex
+         %59 = OpAccessChain %_ptr_Output_v4float %_ %int_0
+               OpStore %59 %58
+               OpReturn
+               OpFunctionEnd
+
+[vertex shader]
+
+#version 450
+
+layout (location = 0) in vec4 piglit_vertex;
+layout (location = 1) out vec4 vertexColor;
+
+
+layout (std140, binding = 5) uniform ComponentsBlock
+ {
+    vec4 c1;
+    vec2 c2;
+ } components;
+
+void main()
+{
+	vec4 fail_color = vec4(1.0, 0.0, 0.0, 1.0);
+	vertexColor = vec4(0.0, 1.0, 0.0, 1.0);
+
+	if (components.c1 != vec4(4575.7996643, 14191.6120546, -30199.3084764, -31303.4210269))
+	   vertexColor = fail_color;
+
+	if (components.c2 != vec2(-10231.1810483, 11729.6478218))
+	   vertexColor = fail_color;
+
+	gl_Position = piglit_vertex;
+}
+
+
+[fragment shader spirv]
+; Automatically generated from the GLSL by shader_test_spirv.py. DO NOT EDIT
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 58
+; Schema: 0
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %main "main" %color %vertexColor
+               OpExecutionMode %main OriginLowerLeft
+               OpSource GLSL 450
+               OpDecorate %color Location 0
+               OpMemberDecorate %ComponentsBlock 0 Offset 0
+               OpMemberDecorate %ComponentsBlock 1 Offset 16
+               OpDecorate %ComponentsBlock Block
+               OpDecorate %components DescriptorSet 0
+               OpDecorate %components Binding 5
+               OpDecorate %vertexColor Location 1
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+    %float_1 = OpConstant %float 1
+    %float_0 = OpConstant %float 0
+         %12 = OpConstantComposite %v4float %float_1 %float_0 %float_0 %float_1
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+      %color = OpVariable %_ptr_Output_v4float Output
+         %15 = OpConstantComposite %v4float %float_0 %float_1 %float_0 %float_1
+    %v2float = OpTypeVector %float 2
+%ComponentsBlock = OpTypeStruct %v4float %v2float
+%_ptr_Uniform_ComponentsBlock = OpTypePointer Uniform %ComponentsBlock
+ %components = OpVariable %_ptr_Uniform_ComponentsBlock Uniform
+        %int = OpTypeInt 32 1
+      %int_0 = OpConstant %int 0
+%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
+%float_4575_7998 = OpConstant %float 4575.7998
+%float_14191_6123 = OpConstant %float 14191.6123
+%float_n30199_3086 = OpConstant %float -30199.3086
+%float_n31303_4219 = OpConstant %float -31303.4219
+         %29 = OpConstantComposite %v4float %float_4575_7998 %float_14191_6123 %float_n30199_3086 %float_n31303_4219
+       %bool = OpTypeBool
+     %v4bool = OpTypeVector %bool 4
+      %int_1 = OpConstant %int 1
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+%float_n10231_1807 = OpConstant %float -10231.1807
+%float_11729_6475 = OpConstant %float 11729.6475
+         %43 = OpConstantComposite %v2float %float_n10231_1807 %float_11729_6475
+     %v2bool = OpTypeVector %bool 2
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+%vertexColor = OpVariable %_ptr_Input_v4float Input
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+ %fail_color = OpVariable %_ptr_Function_v4float Function
+               OpStore %fail_color %12
+               OpStore %color %15
+         %23 = OpAccessChain %_ptr_Uniform_v4float %components %int_0
+         %24 = OpLoad %v4float %23
+         %32 = OpFOrdNotEqual %v4bool %24 %29
+         %33 = OpAny %bool %32
+               OpSelectionMerge %35 None
+               OpBranchConditional %33 %34 %35
+         %34 = OpLabel
+         %36 = OpLoad %v4float %fail_color
+               OpStore %color %36
+               OpBranch %35
+         %35 = OpLabel
+         %39 = OpAccessChain %_ptr_Uniform_v2float %components %int_1
+         %40 = OpLoad %v2float %39
+         %45 = OpFOrdNotEqual %v2bool %40 %43
+         %46 = OpAny %bool %45
+               OpSelectionMerge %48 None
+               OpBranchConditional %46 %47 %48
+         %47 = OpLabel
+         %49 = OpLoad %v4float %fail_color
+               OpStore %color %49
+               OpBranch %48
+         %48 = OpLabel
+         %52 = OpLoad %v4float %vertexColor
+         %53 = OpFOrdNotEqual %v4bool %52 %15
+         %54 = OpAny %bool %53
+               OpSelectionMerge %56 None
+               OpBranchConditional %54 %55 %56
+         %55 = OpLabel
+         %57 = OpLoad %v4float %fail_color
+               OpStore %color %57
+               OpBranch %56
+         %56 = OpLabel
+               OpReturn
+               OpFunctionEnd
+
+[fragment shader]
+
+#version 450
+
+layout (location = 0) out vec4 color;
+layout (location = 1) in vec4 vertexColor;
+layout (std140, binding = 5) uniform ComponentsBlock
+ {
+    vec4 c1;
+    vec2 c2;
+ } components;
+
+void main()
+{
+	vec4 fail_color = vec4(1.0, 0.0, 0.0, 1.0);
+	color = vec4(0.0, 1.0, 0.0, 1.0);
+
+	if (components.c1 != vec4(4575.7996643, 14191.6120546, -30199.3084764, -31303.4210269))
+	   color = fail_color;
+
+	if (components.c2 != vec2(-10231.1810483, 11729.6478218))
+	   color = fail_color;
+
+	if (vertexColor != vec4(0.0, 1.0, 0.0, 1.0))
+	   color = fail_color;
+}
+
+[test]
+clear color 1.0 0.0 0.0 0.0
+clear
+
+block binding 5
+block offset 0
+uniform vec4 ComponentsBlock.c1 4575.7996643 14191.6120546 -30199.3084764 -31303.4210269
+block offset 16
+uniform vec2 ComponentsBlock.c2 -10231.1810483 11729.6478218
+
+verify program_interface_query GL_UNIFORM_BLOCK ComponentsBlock GL_NUM_ACTIVE_VARIABLES 2
+verify program_interface_query GL_UNIFORM_BLOCK ComponentsBlock GL_BUFFER_DATA_SIZE 32
+
+verify program_query GL_ACTIVE_UNIFORMS 2
+
+draw rect -1 -1 2 2
+probe all rgba 0.0 1.0 0.0 1.0
diff --git a/tests/spec/arb_gl_spirv/execution/ubo/two-ubos.shader_test b/tests/spec/arb_gl_spirv/execution/ubo/two-ubos.shader_test
new file mode 100644
index 000000000..33dc13319
--- /dev/null
+++ b/tests/spec/arb_gl_spirv/execution/ubo/two-ubos.shader_test
@@ -0,0 +1,141 @@ 
+# UBO test with two ubos. Just one stage.
+
+[require]
+SPIRV YES
+GL >= 3.3
+GLSL >= 4.50
+GL_ARB_gl_spirv
+
+[vertex shader passthrough]
+
+[fragment shader spirv]
+; Automatically generated from the GLSL by shader_test_spirv.py. DO NOT EDIT
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 7
+; Bound: 51
+; Schema: 0
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %main "main" %color
+               OpExecutionMode %main OriginLowerLeft
+               OpSource GLSL 450
+               OpDecorate %color Location 0
+               OpMemberDecorate %ComponentsBlock 0 Offset 0
+               OpDecorate %ComponentsBlock Block
+               OpDecorate %components DescriptorSet 0
+               OpDecorate %components Binding 5
+               OpMemberDecorate %ComponentsBlock2 0 Offset 0
+               OpDecorate %ComponentsBlock2 Block
+               OpDecorate %components2 DescriptorSet 0
+               OpDecorate %components2 Binding 8
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+    %float_1 = OpConstant %float 1
+    %float_0 = OpConstant %float 0
+         %12 = OpConstantComposite %v4float %float_1 %float_0 %float_0 %float_1
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+      %color = OpVariable %_ptr_Output_v4float Output
+         %15 = OpConstantComposite %v4float %float_0 %float_1 %float_0 %float_1
+%ComponentsBlock = OpTypeStruct %v4float
+%_ptr_Uniform_ComponentsBlock = OpTypePointer Uniform %ComponentsBlock
+ %components = OpVariable %_ptr_Uniform_ComponentsBlock Uniform
+        %int = OpTypeInt 32 1
+      %int_0 = OpConstant %int 0
+%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
+%float_n12496_1973 = OpConstant %float -12496.1973
+%float_n5854_81055 = OpConstant %float -5854.81055
+%float_5217_75732 = OpConstant %float 5217.75732
+%float_26363_8359 = OpConstant %float 26363.8359
+         %28 = OpConstantComposite %v4float %float_n12496_1973 %float_n5854_81055 %float_5217_75732 %float_26363_8359
+       %bool = OpTypeBool
+     %v4bool = OpTypeVector %bool 4
+%ComponentsBlock2 = OpTypeStruct %v4float
+%_ptr_Uniform_ComponentsBlock2 = OpTypePointer Uniform %ComponentsBlock2
+%components2 = OpVariable %_ptr_Uniform_ComponentsBlock2 Uniform
+%float_n7391_61914 = OpConstant %float -7391.61914
+%float_29371_457 = OpConstant %float 29371.457
+%float_7793_47266 = OpConstant %float 7793.47266
+%float_n20661_791 = OpConstant %float -20661.791
+         %45 = OpConstantComposite %v4float %float_n7391_61914 %float_29371_457 %float_7793_47266 %float_n20661_791
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+ %fail_color = OpVariable %_ptr_Function_v4float Function
+               OpStore %fail_color %12
+               OpStore %color %15
+         %22 = OpAccessChain %_ptr_Uniform_v4float %components %int_0
+         %23 = OpLoad %v4float %22
+         %31 = OpFOrdNotEqual %v4bool %23 %28
+         %32 = OpAny %bool %31
+               OpSelectionMerge %34 None
+               OpBranchConditional %32 %33 %34
+         %33 = OpLabel
+         %35 = OpLoad %v4float %fail_color
+               OpStore %color %35
+               OpBranch %34
+         %34 = OpLabel
+         %39 = OpAccessChain %_ptr_Uniform_v4float %components2 %int_0
+         %40 = OpLoad %v4float %39
+         %46 = OpFOrdNotEqual %v4bool %40 %45
+         %47 = OpAny %bool %46
+               OpSelectionMerge %49 None
+               OpBranchConditional %47 %48 %49
+         %48 = OpLabel
+         %50 = OpLoad %v4float %fail_color
+               OpStore %color %50
+               OpBranch %49
+         %49 = OpLabel
+               OpReturn
+               OpFunctionEnd
+
+[fragment shader]
+
+#version 450
+
+layout (location = 0) out vec4 color;
+layout (std140, binding = 5) uniform ComponentsBlock
+ {
+    vec4 c1;
+ } components;
+
+layout (std140, binding = 8) uniform ComponentsBlock2
+ {
+    vec4 c2;
+ } components2;
+
+void main()
+{
+	vec4 fail_color = vec4(1.0, 0.0, 0.0, 1.0);
+	color = vec4(0.0, 1.0, 0.0, 1.0);
+
+	if (components.c1 != vec4(-12496.1967803, -5854.8105745, 5217.75729, 26363.8367742))
+	   color = fail_color;
+
+	if (components2.c2 != vec4(-7391.61915007, 29371.4563058, 7793.47278553, -20661.7912871))
+	   color = fail_color;
+}
+
+[test]
+clear color 1.0 0.0 0.0 0.0
+clear
+
+block binding 5
+block offset 0
+uniform vec4 ComponentsBlock.c1 -12496.1967803 -5854.8105745 5217.75729 26363.8367742
+verify program_interface_query GL_UNIFORM_BLOCK ComponentsBlock GL_NUM_ACTIVE_VARIABLES 1
+verify program_interface_query GL_UNIFORM_BLOCK ComponentsBlock GL_BUFFER_DATA_SIZE 16
+
+block binding 8
+block offset 0
+uniform vec4 ComponentsBlock2.c2 -7391.61915007 29371.4563058 7793.47278553 -20661.7912871
+verify program_interface_query GL_UNIFORM_BLOCK ComponentsBlock2 GL_NUM_ACTIVE_VARIABLES 1
+verify program_interface_query GL_UNIFORM_BLOCK ComponentsBlock2 GL_BUFFER_DATA_SIZE 16
+
+verify program_query GL_ACTIVE_UNIFORMS 2
+
+draw rect -1 -1 2 2
+probe all rgba 0.0 1.0 0.0 1.0