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

Submitted by apinheiro on Sept. 15, 2018, 4:22 p.m.

Details

Message ID 20180915162255.21591-8-apinheiro@igalia.com
State New
Headers show
Series "ARB_gl_spirv: ubo/ssbo tests" ( rev: 2 1 ) in Piglit

Not browsing as part of any series.

Commit Message

apinheiro Sept. 15, 2018, 4:22 p.m.
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.
---
 .../execution/ubo/array-indirect.shader_test       | 108 ++++++++++++
 .../execution/ubo/array-inside-ubo.shader_test     |  94 ++++++++++
 .../ubo/array-of-arrays-inside-ubo.shader_test     | 184 ++++++++++++++++++++
 .../arb_gl_spirv/execution/ubo/array.shader_test   |  96 +++++++++++
 .../execution/ubo/location-0-crash.shader_test     |  93 ++++++++++
 .../arb_gl_spirv/execution/ubo/simple.shader_test  |  92 ++++++++++
 .../execution/ubo/two-stages.shader_test           | 191 +++++++++++++++++++++
 .../execution/ubo/two-ubos.shader_test             |  98 +++++++++++
 .../linker/ubo/two-stages-wrong1.shader_test       | 190 ++++++++++++++++++++
 .../linker/ubo/two-stages-wrong2.shader_test       | 185 ++++++++++++++++++++
 10 files changed, 1331 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

Patch hide | download patch | download mbox

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..3e798f439
--- /dev/null
+++ b/tests/spec/arb_gl_spirv/execution/ubo/array-inside-ubo.shader_test
@@ -0,0 +1,94 @@ 
+# 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: 29
+; 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_Output_v4float = OpTypePointer Output %v4float
+      %color = OpVariable %_ptr_Output_v4float Output
+       %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
+      %int_1 = OpConstant %int 1
+      %int_2 = OpConstant %int 2
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+         %19 = OpAccessChain %_ptr_Uniform_v4float %arr %int_0 %int_0
+         %20 = OpLoad %v4float %19
+         %22 = OpAccessChain %_ptr_Uniform_v4float %arr %int_0 %int_1
+         %23 = OpLoad %v4float %22
+         %24 = OpFAdd %v4float %20 %23
+         %26 = OpAccessChain %_ptr_Uniform_v4float %arr %int_0 %int_2
+         %27 = OpLoad %v4float %26
+         %28 = OpFAdd %v4float %24 %27
+               OpStore %color %28
+               OpReturn
+               OpFunctionEnd
+
+[fragment shader]
+#version 450
+
+layout (location = 0) out vec4 color;
+
+layout (std140, binding = 5) uniform block {
+	vec4 color[3];
+} arr;
+
+
+
+void main()
+{
+	color = arr.color[0] + arr.color[1] + arr.color[2];
+}
+
+[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.1 0.2 0.3
+block offset 16
+uniform vec4 block.color[1] 0.4 0.5 0.6 0.2
+block offset 32
+uniform vec4 block.color[2] 0.1 0.3 0.1 0.2
+
+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.5 0.9 0.9 0.7
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..92ae0c347
--- /dev/null
+++ b/tests/spec/arb_gl_spirv/execution/ubo/array.shader_test
@@ -0,0 +1,96 @@ 
+# 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: 25
+; 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
+       %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
+      %int_0 = OpConstant %int 0
+%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
+      %int_1 = OpConstant %int 1
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+         %19 = OpAccessChain %_ptr_Uniform_v4float %components %int_0 %int_0
+         %20 = OpLoad %v4float %19
+         %22 = OpAccessChain %_ptr_Uniform_v4float %components %int_1 %int_0
+         %23 = OpLoad %v4float %22
+         %24 = OpFAdd %v4float %20 %23
+               OpStore %outColor %24
+               OpReturn
+               OpFunctionEnd
+
+[fragment shader]
+
+#version 450
+
+layout (location = 0) out vec4 outColor;
+layout (std140, binding = 5, row_major) uniform ComponentsBlock
+ {
+    vec4 c1;
+ } components[2];
+
+void main()
+{
+    outColor = components[0].c1 + components[1].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.3 0.1 0.6 0.2
+
+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.4 0.3 0.9 0.6
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..6f37d543f
--- /dev/null
+++ b/tests/spec/arb_gl_spirv/execution/ubo/simple.shader_test
@@ -0,0 +1,92 @@ 
+# 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: 28
+; 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
+               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
+    %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
+      %int_1 = OpConstant %int 1
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+    %float_0 = OpConstant %float 0
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+         %17 = OpAccessChain %_ptr_Uniform_v4float %components %int_0
+         %18 = OpLoad %v4float %17
+         %21 = OpAccessChain %_ptr_Uniform_v2float %components %int_1
+         %22 = OpLoad %v2float %21
+         %24 = OpCompositeExtract %float %22 0
+         %25 = OpCompositeExtract %float %22 1
+         %26 = OpCompositeConstruct %v4float %24 %25 %float_0 %float_0
+         %27 = OpFAdd %v4float %18 %26
+               OpStore %outColor %27
+               OpReturn
+               OpFunctionEnd
+
+[fragment shader]
+
+#version 450
+
+layout (location = 0) out vec4 outColor;
+layout (std140, binding = 5) uniform ComponentsBlock
+ {
+    vec4 c1;
+    vec2 c2;
+ } components;
+
+void main()
+{
+	outColor = components.c1 + vec4(components.c2, 0.0, 0.0);
+}
+
+[test]
+clear color 1.0 0.0 0.0 0.0
+clear
+
+block binding 5
+block offset 0
+uniform vec4 ComponentsBlock.c1 0.1 0.2 0.3 0.4
+block offset 16
+uniform vec2 ComponentsBlock.c2 0.1 0.2
+
+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.2 0.4 0.3 0.4
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..93d688892
--- /dev/null
+++ b/tests/spec/arb_gl_spirv/execution/ubo/two-stages.shader_test
@@ -0,0 +1,191 @@ 
+# 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: 41
+; 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_Output_v4float = OpTypePointer Output %v4float
+%vertexColor = OpVariable %_ptr_Output_v4float Output
+    %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
+      %int_1 = OpConstant %int 1
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+    %float_0 = OpConstant %float 0
+       %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
+         %17 = OpAccessChain %_ptr_Uniform_v4float %components %int_0
+         %18 = OpLoad %v4float %17
+         %21 = OpAccessChain %_ptr_Uniform_v2float %components %int_1
+         %22 = OpLoad %v2float %21
+         %24 = OpCompositeExtract %float %22 0
+         %25 = OpCompositeExtract %float %22 1
+         %26 = OpCompositeConstruct %v4float %24 %25 %float_0 %float_0
+         %27 = OpFAdd %v4float %18 %26
+               OpStore %vertexColor %27
+         %36 = OpLoad %v4float %piglit_vertex
+         %37 = OpAccessChain %_ptr_Output_v4float %_ %int_0
+               OpStore %37 %36
+               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()
+{
+    vertexColor = components.c1 + vec4(components.c2, 0.0, 0.0);
+    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: 35
+; Schema: 0
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %main "main" %outColor %vertexColor
+               OpExecutionMode %main OriginLowerLeft
+               OpSource GLSL 450
+               OpMemberDecorate %ComponentsBlock 0 Offset 0
+               OpMemberDecorate %ComponentsBlock 1 Offset 16
+               OpDecorate %ComponentsBlock Block
+               OpDecorate %components DescriptorSet 0
+               OpDecorate %components Binding 5
+               OpDecorate %outColor Location 0
+               OpDecorate %vertexColor Location 1
+       %void = OpTypeVoid
+          %3 = OpTypeFunction %void
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%_ptr_Function_v4float = OpTypePointer Function %v4float
+    %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
+      %int_1 = OpConstant %int 1
+%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
+    %float_0 = OpConstant %float 0
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+   %outColor = OpVariable %_ptr_Output_v4float Output
+%_ptr_Input_v4float = OpTypePointer Input %v4float
+%vertexColor = OpVariable %_ptr_Input_v4float Input
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+      %color = OpVariable %_ptr_Function_v4float Function
+         %17 = OpAccessChain %_ptr_Uniform_v4float %components %int_0
+         %18 = OpLoad %v4float %17
+         %21 = OpAccessChain %_ptr_Uniform_v2float %components %int_1
+         %22 = OpLoad %v2float %21
+         %24 = OpCompositeExtract %float %22 0
+         %25 = OpCompositeExtract %float %22 1
+         %26 = OpCompositeConstruct %v4float %24 %25 %float_0 %float_0
+         %27 = OpFAdd %v4float %18 %26
+               OpStore %color %27
+         %30 = OpLoad %v4float %color
+         %33 = OpLoad %v4float %vertexColor
+         %34 = OpFAdd %v4float %30 %33
+               OpStore %outColor %34
+               OpReturn
+               OpFunctionEnd
+
+[fragment shader]
+
+#version 450
+
+layout (location = 0) out vec4 outColor;
+layout (location = 1) in vec4 vertexColor;
+layout (std140, binding = 5) uniform ComponentsBlock
+ {
+    vec4 c1;
+    vec2 c2;
+ } components;
+
+void main()
+{
+	vec4 color = components.c1 + vec4(components.c2, 0.0, 0.0);
+	outColor = color + vertexColor;
+}
+
+[test]
+clear color 1.0 0.0 0.0 0.0
+clear
+
+block binding 5
+block offset 0
+uniform vec4 ComponentsBlock.c1 0.0 0.0 0.3 0.4
+block offset 16
+uniform vec2 ComponentsBlock.c2 0.1 0.2
+
+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.2 0.4 0.6 0.8
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..4505aadbe
--- /dev/null
+++ b/tests/spec/arb_gl_spirv/execution/ubo/two-ubos.shader_test
@@ -0,0 +1,98 @@ 
+# 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: 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
+               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_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
+%ComponentsBlock2 = OpTypeStruct %v4float
+%_ptr_Uniform_ComponentsBlock2 = OpTypePointer Uniform %ComponentsBlock2
+%components2 = OpVariable %_ptr_Uniform_ComponentsBlock2 Uniform
+       %main = OpFunction %void None %3
+          %5 = OpLabel
+         %16 = OpAccessChain %_ptr_Uniform_v4float %components %int_0
+         %17 = OpLoad %v4float %16
+         %21 = OpAccessChain %_ptr_Uniform_v4float %components2 %int_0
+         %22 = OpLoad %v4float %21
+         %23 = OpFAdd %v4float %17 %22
+               OpStore %outColor %23
+               OpReturn
+               OpFunctionEnd
+
+[fragment shader]
+
+#version 450
+
+layout (location = 0) out vec4 outColor;
+layout (std140, binding = 5) uniform ComponentsBlock
+ {
+    vec4 c1;
+ } components;
+
+layout (std140, binding = 8) uniform ComponentsBlock2
+ {
+    vec4 c2;
+ } components2;
+
+void main()
+{
+	outColor = components.c1 + components2.c2;
+}
+
+[test]
+clear color 1.0 0.0 0.0 0.0
+clear
+
+block binding 5
+block offset 0
+uniform vec4 ComponentsBlock.c1 0.1 0.2 0.3 0.4
+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 0.2 0.3 0.4 0.5
+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.3 0.5 0.7 0.9
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