[Piglit] [PATCH v2 06/17] arb_gl_spirv: add some simple ubo tests

Alejandro PiƱeiro apinheiro at igalia.com
Thu Sep 27 09:54:56 UTC 2018


Add two linker tests and several simple execution tests for
ubo. Linker tests just checks for some basic linker errors (like
mistmatched ubo on different stages).

The execution tests include:
     * Simple one 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/ubo/array-indirect.shader_test       | 108 ++++++++
 .../execution/ubo/array-inside-ubo.shader_test     | 154 ++++++++++++
 .../ubo/array-of-arrays-inside-ubo.shader_test     | 184 ++++++++++++++
 .../arb_gl_spirv/execution/ubo/array.shader_test   | 140 +++++++++++
 .../execution/ubo/location-0-crash.shader_test     |  93 +++++++
 .../arb_gl_spirv/execution/ubo/simple.shader_test  | 131 ++++++++++
 .../execution/ubo/two-stages.shader_test           | 276 +++++++++++++++++++++
 .../execution/ubo/two-ubos.shader_test             | 141 +++++++++++
 .../linker/ubo/two-stages-wrong1.shader_test       | 190 ++++++++++++++
 .../linker/ubo/two-stages-wrong2.shader_test       | 185 ++++++++++++++
 10 files changed, 1602 insertions(+)
 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
 create mode 100644 tests/spec/arb_gl_spirv/linker/ubo/two-stages-wrong1.shader_test
 create mode 100644 tests/spec/arb_gl_spirv/linker/ubo/two-stages-wrong2.shader_test

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..87e741159
--- /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 >= 3.30
+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..af9e0d5a3
--- /dev/null
+++ b/tests/spec/arb_gl_spirv/execution/ubo/array-inside-ubo.shader_test
@@ -0,0 +1,154 @@
+# Using a array inside a ubo, instead of an array of ubo.
+
+[require]
+SPIRV YES
+GL >= 3.3
+GLSL >= 3.30
+
+[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..0e1366a1a
--- /dev/null
+++ b/tests/spec/arb_gl_spirv/execution/ubo/array-of-arrays-inside-ubo.shader_test
@@ -0,0 +1,184 @@
+# Using a array of arrays inside a ubo, instead of a aoa of ubos.
+
+[require]
+SPIRV YES
+GL >= 3.3
+GLSL >= 3.30
+
+[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..0f8c98868
--- /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 >= 3.30
+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..f02a2ebbf
--- /dev/null
+++ b/tests/spec/arb_gl_spirv/execution/ubo/location-0-crash.shader_test
@@ -0,0 +1,93 @@
+# 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 >= 3.30
+
+[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..e62e3ccf3
--- /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 >= 3.30
+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..d0c983944
--- /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 >= 3.30
+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..a1d7edf38
--- /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 >= 3.30
+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
diff --git a/tests/spec/arb_gl_spirv/linker/ubo/two-stages-wrong1.shader_test b/tests/spec/arb_gl_spirv/linker/ubo/two-stages-wrong1.shader_test
new file mode 100644
index 000000000..012083fe6
--- /dev/null
+++ b/tests/spec/arb_gl_spirv/linker/ubo/two-stages-wrong1.shader_test
@@ -0,0 +1,190 @@
+# Using the same block on two different stages
+# Wrong: using a different type on one of the variables on one of the stages.
+
+[require]
+SPIRV YES
+GL >= 3.3
+GLSL >= 3.30
+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; 6
+; Bound: 45
+; Schema: 0
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Vertex %main "main" %_ %position %gl_VertexID %gl_InstanceID
+               OpSource GLSL 450
+               OpName %main "main"
+               OpName %gl_PerVertex "gl_PerVertex"
+               OpMemberName %gl_PerVertex 0 "gl_Position"
+               OpMemberName %gl_PerVertex 1 "gl_PointSize"
+               OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
+               OpMemberName %gl_PerVertex 3 "gl_CullDistance"
+               OpName %_ ""
+               OpName %position "position"
+               OpName %extPosition "extPosition"
+               OpName %ComponentsBlock "ComponentsBlock"
+               OpMemberName %ComponentsBlock 0 "c1"
+               OpMemberName %ComponentsBlock 1 "c2"
+               OpName %components "components"
+               OpName %gl_VertexID "gl_VertexID"
+               OpName %gl_InstanceID "gl_InstanceID"
+               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 %position Location 0
+               OpDecorate %extPosition Location 20
+               OpDecorate %extPosition DescriptorSet 0
+               OpMemberDecorate %ComponentsBlock 0 Offset 0
+               OpMemberDecorate %ComponentsBlock 1 Offset 16
+               OpDecorate %ComponentsBlock Block
+               OpDecorate %components DescriptorSet 0
+               OpDecorate %components Binding 5
+               OpDecorate %gl_VertexID BuiltIn VertexId
+               OpDecorate %gl_InstanceID BuiltIn InstanceId
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+       %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
+        %int = OpTypeInt 32 1
+      %int_0 = OpConstant %int 0
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+   %position = OpVariable %_ptr_Input_v4float Input
+%_ptr_UniformConstant_v4float = OpTypePointer UniformConstant %v4float
+%extPosition = OpVariable %_ptr_UniformConstant_v4float UniformConstant
+    %v2float = OpTypeVector %float 2
+%ComponentsBlock = OpTypeStruct %v4float %v2float
+%_ptr_Uniform_ComponentsBlock = OpTypePointer Uniform %ComponentsBlock
+ %components = OpVariable %_ptr_Uniform_ComponentsBlock Uniform
+%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
+      %int_1 = OpConstant %int 1
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+    %float_0 = OpConstant %float 0
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+%_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
+         %18 = OpLoad %v4float %position
+         %21 = OpLoad %v4float %extPosition
+         %22 = OpFAdd %v4float %18 %21
+         %28 = OpAccessChain %_ptr_Uniform_v4float %components %int_0
+         %29 = OpLoad %v4float %28
+         %30 = OpFAdd %v4float %22 %29
+         %33 = OpAccessChain %_ptr_Uniform_v2float %components %int_1
+         %34 = OpLoad %v2float %33
+         %36 = OpCompositeExtract %float %34 0
+         %37 = OpCompositeExtract %float %34 1
+         %38 = OpCompositeConstruct %v4float %36 %37 %float_0 %float_0
+         %39 = OpFAdd %v4float %30 %38
+         %41 = OpAccessChain %_ptr_Output_v4float %_ %int_0
+               OpStore %41 %39
+               OpReturn
+               OpFunctionEnd
+
+[vertex shader]
+
+#version 450
+
+layout (location = 0) in vec4 position;
+layout (location = 20) uniform vec4 extPosition;
+layout (binding = 5) uniform ComponentsBlock
+ {
+    vec4 c1;
+    vec2 c2;
+ } components;
+
+void main()
+{
+    gl_Position = position + extPosition + components.c1 + vec4(components.c2, 0.0, 0.0);
+}
+
+
+[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; 6
+; Bound: 29
+; Schema: 0
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %main "main" %outColor
+               OpExecutionMode %main OriginLowerLeft
+               OpSource GLSL 450
+               OpName %main "main"
+               OpName %outColor "outColor"
+               OpName %ComponentsBlock "ComponentsBlock"
+               OpMemberName %ComponentsBlock 0 "c1"
+               OpMemberName %ComponentsBlock 1 "c2"
+               OpName %components "components"
+               OpDecorate %outColor Location 3
+               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_Output_v4float = OpTypePointer Output %v4float
+   %outColor = OpVariable %_ptr_Output_v4float Output
+    %v3float = OpTypeVector %float 3
+%ComponentsBlock = OpTypeStruct %v4float %v3float
+%_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
+      %int_1 = OpConstant %int 1
+%_ptr_Uniform_v3float = OpTypePointer Uniform %v3float
+    %float_1 = OpConstant %float 1
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+         %17 = OpAccessChain %_ptr_Uniform_v4float %components %int_0
+         %18 = OpLoad %v4float %17
+         %21 = OpAccessChain %_ptr_Uniform_v3float %components %int_1
+         %22 = OpLoad %v3float %21
+         %24 = OpCompositeExtract %float %22 0
+         %25 = OpCompositeExtract %float %22 1
+         %26 = OpCompositeExtract %float %22 2
+         %27 = OpCompositeConstruct %v4float %24 %25 %26 %float_1
+         %28 = OpFAdd %v4float %18 %27
+               OpStore %outColor %28
+               OpReturn
+               OpFunctionEnd
+
+[fragment shader]
+
+#version 450
+
+layout (location = 3) out vec4 outColor;
+layout (binding = 5) uniform ComponentsBlock
+ {
+    vec4 c1;
+    vec3 c2;
+ } components;
+
+void main()
+{
+	outColor = components.c1 + vec4(components.c2, 1.0);
+}
+
+[test]
+link error
diff --git a/tests/spec/arb_gl_spirv/linker/ubo/two-stages-wrong2.shader_test b/tests/spec/arb_gl_spirv/linker/ubo/two-stages-wrong2.shader_test
new file mode 100644
index 000000000..f91cf37cc
--- /dev/null
+++ b/tests/spec/arb_gl_spirv/linker/ubo/two-stages-wrong2.shader_test
@@ -0,0 +1,185 @@
+# Using the same block on two different stages
+# Wrong: different amount of variables defined on each stage.
+
+[require]
+SPIRV YES
+GL >= 3.3
+GLSL >= 3.30
+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; 6
+; Bound: 45
+; Schema: 0
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Vertex %main "main" %_ %position %gl_VertexID %gl_InstanceID
+               OpSource GLSL 450
+               OpName %main "main"
+               OpName %gl_PerVertex "gl_PerVertex"
+               OpMemberName %gl_PerVertex 0 "gl_Position"
+               OpMemberName %gl_PerVertex 1 "gl_PointSize"
+               OpMemberName %gl_PerVertex 2 "gl_ClipDistance"
+               OpMemberName %gl_PerVertex 3 "gl_CullDistance"
+               OpName %_ ""
+               OpName %position "position"
+               OpName %extPosition "extPosition"
+               OpName %ComponentsBlock "ComponentsBlock"
+               OpMemberName %ComponentsBlock 0 "c1"
+               OpMemberName %ComponentsBlock 1 "c2"
+               OpName %components "components"
+               OpName %gl_VertexID "gl_VertexID"
+               OpName %gl_InstanceID "gl_InstanceID"
+               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 %position Location 0
+               OpDecorate %extPosition Location 20
+               OpDecorate %extPosition DescriptorSet 0
+               OpMemberDecorate %ComponentsBlock 0 Offset 0
+               OpMemberDecorate %ComponentsBlock 1 Offset 16
+               OpDecorate %ComponentsBlock Block
+               OpDecorate %components DescriptorSet 0
+               OpDecorate %components Binding 5
+               OpDecorate %gl_VertexID BuiltIn VertexId
+               OpDecorate %gl_InstanceID BuiltIn InstanceId
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+       %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
+        %int = OpTypeInt 32 1
+      %int_0 = OpConstant %int 0
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+   %position = OpVariable %_ptr_Input_v4float Input
+%_ptr_UniformConstant_v4float = OpTypePointer UniformConstant %v4float
+%extPosition = OpVariable %_ptr_UniformConstant_v4float UniformConstant
+    %v2float = OpTypeVector %float 2
+%ComponentsBlock = OpTypeStruct %v4float %v2float
+%_ptr_Uniform_ComponentsBlock = OpTypePointer Uniform %ComponentsBlock
+ %components = OpVariable %_ptr_Uniform_ComponentsBlock Uniform
+%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
+      %int_1 = OpConstant %int 1
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+    %float_0 = OpConstant %float 0
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+%_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
+         %18 = OpLoad %v4float %position
+         %21 = OpLoad %v4float %extPosition
+         %22 = OpFAdd %v4float %18 %21
+         %28 = OpAccessChain %_ptr_Uniform_v4float %components %int_0
+         %29 = OpLoad %v4float %28
+         %30 = OpFAdd %v4float %22 %29
+         %33 = OpAccessChain %_ptr_Uniform_v2float %components %int_1
+         %34 = OpLoad %v2float %33
+         %36 = OpCompositeExtract %float %34 0
+         %37 = OpCompositeExtract %float %34 1
+         %38 = OpCompositeConstruct %v4float %36 %37 %float_0 %float_0
+         %39 = OpFAdd %v4float %30 %38
+         %41 = OpAccessChain %_ptr_Output_v4float %_ %int_0
+               OpStore %41 %39
+               OpReturn
+               OpFunctionEnd
+
+[vertex shader]
+
+#version 450
+
+layout (location = 0) in vec4 position;
+layout (location = 20) uniform vec4 extPosition;
+layout (binding = 5) uniform ComponentsBlock
+ {
+    vec4 c1;
+    vec2 c2;
+ } components;
+
+void main()
+{
+    gl_Position = position + extPosition + components.c1 + vec4(components.c2, 0.0, 0.0);
+}
+
+
+[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; 6
+; Bound: 27
+; Schema: 0
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %main "main" %outColor
+               OpExecutionMode %main OriginLowerLeft
+               OpSource GLSL 450
+               OpName %main "main"
+               OpName %outColor "outColor"
+               OpName %ComponentsBlock "ComponentsBlock"
+               OpMemberName %ComponentsBlock 0 "c1"
+               OpName %components "components"
+               OpDecorate %outColor Location 3
+               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_Output_v4float = OpTypePointer Output %v4float
+   %outColor = OpVariable %_ptr_Output_v4float Output
+%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
+    %v2float = OpTypeVector %float 2
+    %float_0 = OpConstant %float 0
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+         %16 = OpAccessChain %_ptr_Uniform_v4float %components %int_0
+         %17 = OpLoad %v4float %16
+         %19 = OpAccessChain %_ptr_Uniform_v4float %components %int_0
+         %20 = OpLoad %v4float %19
+         %21 = OpVectorShuffle %v2float %20 %20 0 1
+         %23 = OpCompositeExtract %float %21 0
+         %24 = OpCompositeExtract %float %21 1
+         %25 = OpCompositeConstruct %v4float %23 %24 %float_0 %float_0
+         %26 = OpFAdd %v4float %17 %25
+               OpStore %outColor %26
+               OpReturn
+               OpFunctionEnd
+
+[fragment shader]
+
+#version 450
+
+layout (location = 3) out vec4 outColor;
+layout (binding = 5) uniform ComponentsBlock
+ {
+    vec4 c1;
+ } components;
+
+void main()
+{
+	outColor = components.c1 + vec4(components.c1.xy, 0.0, 0.0);
+}
+
+[test]
+link error
-- 
2.14.1



More information about the Piglit mailing list