[4/4] arb_enhanced_layouts: Test XFB layout qualifiers via SPIR-V

Submitted by apinheiro on July 20, 2018, 3:16 p.m.

Details

Message ID 20180720151612.27878-5-apinheiro@igalia.com
State New
Headers show
Series "ARB_gl_spirv: xfb tests" ( rev: 1 ) in Piglit

Not browsing as part of any series.

Commit Message

apinheiro July 20, 2018, 3:16 p.m.
From: Neil Roberts <nroberts@igalia.com>

v2: use shader_test file with the spirv assembly, instead of include
    two SPIRV binaries (Alejandro Piñeiro)

Signed-off-by: Neil Roberts <nroberts@igalia.com>
Signed-off-by: Alejandro Piñeiro <apinheiro@igalia.com>
---
 tests/opengl.py                                    |  22 +-
 .../shader_test/gs_text_two_sets_tmpl.shader_test  |  32 ++
 .../shader_test/vs_passthru.shader_test            |  50 ++++
 .../shader_test/vs_two_sets.shader_test            | 122 ++++++++
 .../shader_test/vs_two_sets_ifc.shader_test        | 125 ++++++++
 .../shader_test/vs_two_sets_named_ifc.shader_test  | 122 ++++++++
 .../shader_test/vs_two_sets_struct.shader_test     | 131 +++++++++
 .../transform-feedback-layout-qualifiers.c         | 322 +++++++++++----------
 8 files changed, 766 insertions(+), 160 deletions(-)
 create mode 100644 tests/spec/arb_enhanced_layouts/shader_test/gs_text_two_sets_tmpl.shader_test
 create mode 100644 tests/spec/arb_enhanced_layouts/shader_test/vs_passthru.shader_test
 create mode 100644 tests/spec/arb_enhanced_layouts/shader_test/vs_two_sets.shader_test
 create mode 100644 tests/spec/arb_enhanced_layouts/shader_test/vs_two_sets_ifc.shader_test
 create mode 100644 tests/spec/arb_enhanced_layouts/shader_test/vs_two_sets_named_ifc.shader_test
 create mode 100644 tests/spec/arb_enhanced_layouts/shader_test/vs_two_sets_struct.shader_test

Patch hide | download patch | download mbox

diff --git a/tests/opengl.py b/tests/opengl.py
index e4c49e72a..99d17037f 100644
--- a/tests/opengl.py
+++ b/tests/opengl.py
@@ -2288,18 +2288,16 @@  with profile.test_list.group_manager(
        'explicit-offset-bufferstorage')
     g(['arb_enhanced_layouts-gs-stream-location-aliasing'],
        'gs-stream-location-aliasing')
-    g(['arb_enhanced_layouts-transform-feedback-layout-qualifiers', 'vs'],
-      'arb_enhanced_layouts-transform-feedback-layout-qualifiers_vs',
-      run_concurrent=False)
-    g(['arb_enhanced_layouts-transform-feedback-layout-qualifiers', 'vs_ifc'],
-      'arb_enhanced_layouts-transform-feedback-layout-qualifiers_vs_interface',
-      run_concurrent=False)
-    g(['arb_enhanced_layouts-transform-feedback-layout-qualifiers', 'vs_named_ifc'],
-      'arb_enhanced_layouts-transform-feedback-layout-qualifiers_vs_named_interface',
-      run_concurrent=False)
-    g(['arb_enhanced_layouts-transform-feedback-layout-qualifiers', 'vs_struct'],
-      'arb_enhanced_layouts-transform-feedback-layout-qualifiers_vs_struct',
-      run_concurrent=False)
+    for test in ['vs', 'vs_ifc', 'vs_named_ifc', 'vs_struct']:
+        g(['arb_enhanced_layouts-transform-feedback-layout-qualifiers', test],
+          'arb_enhanced_layouts-transform-feedback-layout-qualifiers_' + test,
+          run_concurrent=False)
+        g(['arb_enhanced_layouts-transform-feedback-layout-qualifiers',
+           test,
+           'spirv'],
+          'arb_enhanced_layouts-transform-feedback-layout-qualifiers_' +
+          test + '_spirv',
+          run_concurrent=False)
     g(['arb_enhanced_layouts-transform-feedback-layout-qualifiers', 'gs'],
       'arb_enhanced_layouts-transform-feedback-layout-qualifiers_gs',
       run_concurrent=False)
diff --git a/tests/spec/arb_enhanced_layouts/shader_test/gs_text_two_sets_tmpl.shader_test b/tests/spec/arb_enhanced_layouts/shader_test/gs_text_two_sets_tmpl.shader_test
new file mode 100644
index 000000000..48e079efe
--- /dev/null
+++ b/tests/spec/arb_enhanced_layouts/shader_test/gs_text_two_sets_tmpl.shader_test
@@ -0,0 +1,32 @@ 
+[geometry shader]
+#version 150
+#extension GL_ARB_enhanced_layouts: require
+#extension GL_ARB_gpu_shader5 : enable
+#define INVOCATION_MAX_N %u
+
+layout(points, invocations = INVOCATION_MAX_N) in;
+layout(points, max_vertices = 1) out;
+
+layout(xfb_offset = 0) out float x1_out;
+layout(xfb_offset = 4) out vec2 x2_out;
+layout(xfb_offset = 12) out vec3 x3_out;
+out vec3 not_captured1;
+layout(xfb_buffer = 2) out;
+layout(xfb_offset = 0) out float y1_out;
+layout(xfb_offset = 4) out vec4 y2_out;
+layout(xfb_buffer = 2) out vec3 not_captured2;
+
+void main() {
+   gl_Position = gl_in[0].gl_Position;
+   x1_out = 1.0 + gl_InvocationID;
+   x2_out = vec2(2.0 + gl_InvocationID, 3.0 + gl_InvocationID);
+   x3_out = vec3(4.0 + gl_InvocationID, 5.0 + gl_InvocationID,
+                 6.0 + gl_InvocationID);
+   y1_out = 7.0 + gl_InvocationID;
+   y2_out = vec4(8.0 + gl_InvocationID, 9.0 + gl_InvocationID,
+                 10.0 + gl_InvocationID, 11.0 + gl_InvocationID);
+   not_captured1 = vec3(1.0);
+   not_captured2 = vec3(1.0);
+   EmitVertex();
+   EndPrimitive();
+}
diff --git a/tests/spec/arb_enhanced_layouts/shader_test/vs_passthru.shader_test b/tests/spec/arb_enhanced_layouts/shader_test/vs_passthru.shader_test
new file mode 100644
index 000000000..4b0487646
--- /dev/null
+++ b/tests/spec/arb_enhanced_layouts/shader_test/vs_passthru.shader_test
@@ -0,0 +1,50 @@ 
+[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: 23
+; Schema: 0
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Vertex %main "main" %_ %gl_VertexID %gl_InstanceID
+               OpSource GLSL 450
+               OpName %_ ""
+               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 %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
+    %float_0 = OpConstant %float 0
+         %17 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %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
+         %19 = OpAccessChain %_ptr_Output_v4float %_ %int_0
+               OpStore %19 %17
+               OpReturn
+               OpFunctionEnd
+
+[vertex shader]
+#version 150
+void main() {
+   gl_Position = vec4(0.0);
+}
diff --git a/tests/spec/arb_enhanced_layouts/shader_test/vs_two_sets.shader_test b/tests/spec/arb_enhanced_layouts/shader_test/vs_two_sets.shader_test
new file mode 100644
index 000000000..6675a2379
--- /dev/null
+++ b/tests/spec/arb_enhanced_layouts/shader_test/vs_two_sets.shader_test
@@ -0,0 +1,122 @@ 
+[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: 50
+; Schema: 0
+               OpCapability Shader
+               OpCapability TransformFeedback
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Vertex %main "main" %_ %x1_out %x2_out %x3_out %y1_out %y2_out %gl_VertexID %gl_InstanceID
+               OpExecutionMode %main Xfb
+               OpSource GLSL 450
+               OpSourceExtension "GL_ARB_enhanced_layouts"
+               OpName %_ ""
+               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 %_ XfbBuffer 0
+               OpDecorate %_ XfbStride 24
+               OpDecorate %x1_out Location 0
+               OpDecorate %x1_out XfbBuffer 0
+               OpDecorate %x1_out XfbStride 24
+               OpDecorate %x1_out Offset 0
+               OpDecorate %x2_out Location 1
+               OpDecorate %x2_out XfbBuffer 0
+               OpDecorate %x2_out XfbStride 24
+               OpDecorate %x2_out Offset 4
+               OpDecorate %x3_out Location 3
+               OpDecorate %x3_out XfbBuffer 0
+               OpDecorate %x3_out XfbStride 24
+               OpDecorate %x3_out Offset 12
+               OpDecorate %y1_out Location 4
+               OpDecorate %y1_out XfbBuffer 2
+               OpDecorate %y1_out XfbStride 20
+               OpDecorate %y1_out Offset 0
+               OpDecorate %y2_out Location 5
+               OpDecorate %y2_out XfbBuffer 2
+               OpDecorate %y2_out XfbStride 20
+               OpDecorate %y2_out Offset 4
+               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
+    %float_0 = OpConstant %float 0
+         %17 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+%_ptr_Output_float = OpTypePointer Output %float
+     %x1_out = OpVariable %_ptr_Output_float Output
+    %float_1 = OpConstant %float 1
+     %uint_2 = OpConstant %uint 2
+%_arr_float_uint_2 = OpTypeArray %float %uint_2
+%_ptr_Output__arr_float_uint_2 = OpTypePointer Output %_arr_float_uint_2
+     %x2_out = OpVariable %_ptr_Output__arr_float_uint_2 Output
+    %float_2 = OpConstant %float 2
+      %int_1 = OpConstant %int 1
+    %float_3 = OpConstant %float 3
+    %v3float = OpTypeVector %float 3
+%_ptr_Output_v3float = OpTypePointer Output %v3float
+     %x3_out = OpVariable %_ptr_Output_v3float Output
+    %float_4 = OpConstant %float 4
+    %float_5 = OpConstant %float 5
+    %float_6 = OpConstant %float 6
+         %38 = OpConstantComposite %v3float %float_4 %float_5 %float_6
+     %y1_out = OpVariable %_ptr_Output_float Output
+    %float_7 = OpConstant %float 7
+     %y2_out = OpVariable %_ptr_Output_v4float Output
+    %float_8 = OpConstant %float 8
+    %float_9 = OpConstant %float 9
+   %float_10 = OpConstant %float 10
+   %float_11 = OpConstant %float 11
+         %46 = OpConstantComposite %v4float %float_8 %float_9 %float_10 %float_11
+%_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
+         %19 = OpAccessChain %_ptr_Output_v4float %_ %int_0
+               OpStore %19 %17
+               OpStore %x1_out %float_1
+         %28 = OpAccessChain %_ptr_Output_float %x2_out %int_0
+               OpStore %28 %float_2
+         %31 = OpAccessChain %_ptr_Output_float %x2_out %int_1
+               OpStore %31 %float_3
+               OpStore %x3_out %38
+               OpStore %y1_out %float_7
+               OpStore %y2_out %46
+               OpReturn
+               OpFunctionEnd
+
+[vertex shader]
+#version 150
+#extension GL_ARB_enhanced_layouts: require
+
+layout(xfb_offset = 0) out float x1_out;
+layout(xfb_offset = 4) out float x2_out[2];
+layout(xfb_offset = 12) out vec3 x3_out;
+layout(xfb_buffer = 2) out;
+layout(xfb_offset = 0, xfb_buffer = 2) out float y1_out;
+layout(xfb_offset = 4) out vec4 y2_out;
+void main() {
+  gl_Position = vec4(0.0);
+  x1_out = 1.0;
+  x2_out[0] = 2.0;
+  x2_out[1] = 3.0;
+  x3_out = vec3(4.0, 5.0, 6.0);
+  y1_out = 7.0;
+  y2_out = vec4(8.0, 9.0, 10.0, 11.0);
+}
diff --git a/tests/spec/arb_enhanced_layouts/shader_test/vs_two_sets_ifc.shader_test b/tests/spec/arb_enhanced_layouts/shader_test/vs_two_sets_ifc.shader_test
new file mode 100644
index 000000000..4f5dbe62f
--- /dev/null
+++ b/tests/spec/arb_enhanced_layouts/shader_test/vs_two_sets_ifc.shader_test
@@ -0,0 +1,125 @@ 
+[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: 55
+; Schema: 0
+               OpCapability Shader
+               OpCapability TransformFeedback
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Vertex %main "main" %_ %__0 %__1 %gl_VertexID %gl_InstanceID
+               OpExecutionMode %main Xfb
+               OpSource GLSL 450
+               OpSourceExtension "GL_ARB_enhanced_layouts"
+               OpName %_ ""
+               OpName %__0 ""
+               OpName %__1 ""
+               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 %_ XfbBuffer 0
+               OpDecorate %_ XfbStride 24
+               OpMemberDecorate %block 0 Offset 12
+               OpMemberDecorate %block 1 Offset 16
+               OpMemberDecorate %block 3 Offset 0
+               OpDecorate %block Block
+               OpDecorate %__0 Location 0
+               OpDecorate %__0 XfbBuffer 0
+               OpDecorate %__0 XfbStride 24
+               OpDecorate %block2 Block
+               OpDecorate %__1 Location 4
+               OpDecorate %__1 XfbBuffer 2
+               OpDecorate %__1 XfbStride 20
+               OpDecorate %__1 Offset 0
+               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
+    %float_0 = OpConstant %float 0
+         %17 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+      %block = OpTypeStruct %float %v2float %v3float %v3float
+%_ptr_Output_block = OpTypePointer Output %block
+        %__0 = OpVariable %_ptr_Output_block Output
+    %float_4 = OpConstant %float 4
+%_ptr_Output_float = OpTypePointer Output %float
+      %int_1 = OpConstant %int 1
+    %float_5 = OpConstant %float 5
+    %float_6 = OpConstant %float 6
+         %31 = OpConstantComposite %v2float %float_5 %float_6
+%_ptr_Output_v2float = OpTypePointer Output %v2float
+      %int_3 = OpConstant %int 3
+    %float_1 = OpConstant %float 1
+    %float_2 = OpConstant %float 2
+    %float_3 = OpConstant %float 3
+         %38 = OpConstantComposite %v3float %float_1 %float_2 %float_3
+%_ptr_Output_v3float = OpTypePointer Output %v3float
+     %block2 = OpTypeStruct %float %v4float
+%_ptr_Output_block2 = OpTypePointer Output %block2
+        %__1 = OpVariable %_ptr_Output_block2 Output
+    %float_7 = OpConstant %float 7
+    %float_8 = OpConstant %float 8
+    %float_9 = OpConstant %float 9
+   %float_10 = OpConstant %float 10
+   %float_11 = OpConstant %float 11
+         %50 = OpConstantComposite %v4float %float_8 %float_9 %float_10 %float_11
+%_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
+         %19 = OpAccessChain %_ptr_Output_v4float %_ %int_0
+               OpStore %19 %17
+         %27 = OpAccessChain %_ptr_Output_float %__0 %int_0
+               OpStore %27 %float_4
+         %33 = OpAccessChain %_ptr_Output_v2float %__0 %int_1
+               OpStore %33 %31
+         %40 = OpAccessChain %_ptr_Output_v3float %__0 %int_3
+               OpStore %40 %38
+         %45 = OpAccessChain %_ptr_Output_float %__1 %int_0
+               OpStore %45 %float_7
+         %51 = OpAccessChain %_ptr_Output_v4float %__1 %int_1
+               OpStore %51 %50
+               OpReturn
+               OpFunctionEnd
+
+[vertex shader]
+#version 150
+#extension GL_ARB_enhanced_layouts: require
+
+out block {
+  layout(xfb_offset = 12) out float x1_out;
+  layout(xfb_offset = 16) out vec2 x2_out;
+  layout(xfb_buffer = 0) out vec3 not_captured;
+  layout(xfb_offset = 0) out vec3 x3_out;
+};
+layout(xfb_buffer = 2) out;
+layout(xfb_offset = 0) out block2 {
+  float y1_out;
+  vec4 y2_out;
+};
+
+void main() {
+  gl_Position = vec4(0.0);
+  x1_out = 4.0;
+  x2_out = vec2(5.0, 6.0);
+  x3_out = vec3(1.0, 2.0, 3.0);
+  y1_out = 7.0;
+  y2_out = vec4(8.0, 9.0, 10.0, 11.0);
+}
diff --git a/tests/spec/arb_enhanced_layouts/shader_test/vs_two_sets_named_ifc.shader_test b/tests/spec/arb_enhanced_layouts/shader_test/vs_two_sets_named_ifc.shader_test
new file mode 100644
index 000000000..028c5261a
--- /dev/null
+++ b/tests/spec/arb_enhanced_layouts/shader_test/vs_two_sets_named_ifc.shader_test
@@ -0,0 +1,122 @@ 
+[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: 55
+; Schema: 0
+               OpCapability Shader
+               OpCapability TransformFeedback
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Vertex %main "main" %_ %x %y %gl_VertexID %gl_InstanceID
+               OpExecutionMode %main Xfb
+               OpSource GLSL 450
+               OpSourceExtension "GL_ARB_enhanced_layouts"
+               OpName %_ ""
+               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 %_ XfbBuffer 0
+               OpDecorate %_ XfbStride 24
+               OpMemberDecorate %block 0 Offset 0
+               OpMemberDecorate %block 1 Offset 4
+               OpMemberDecorate %block 3 Offset 12
+               OpDecorate %block Block
+               OpDecorate %x Location 0
+               OpDecorate %x XfbBuffer 0
+               OpDecorate %x XfbStride 24
+               OpDecorate %block2 Block
+               OpDecorate %y Location 4
+               OpDecorate %y XfbBuffer 2
+               OpDecorate %y XfbStride 20
+               OpDecorate %y Offset 0
+               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
+    %float_0 = OpConstant %float 0
+         %17 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+    %v2float = OpTypeVector %float 2
+    %v3float = OpTypeVector %float 3
+      %block = OpTypeStruct %float %v2float %v3float %v3float
+%_ptr_Output_block = OpTypePointer Output %block
+          %x = OpVariable %_ptr_Output_block Output
+    %float_1 = OpConstant %float 1
+%_ptr_Output_float = OpTypePointer Output %float
+      %int_1 = OpConstant %int 1
+    %float_2 = OpConstant %float 2
+    %float_3 = OpConstant %float 3
+         %31 = OpConstantComposite %v2float %float_2 %float_3
+%_ptr_Output_v2float = OpTypePointer Output %v2float
+      %int_3 = OpConstant %int 3
+    %float_4 = OpConstant %float 4
+    %float_5 = OpConstant %float 5
+    %float_6 = OpConstant %float 6
+         %38 = OpConstantComposite %v3float %float_4 %float_5 %float_6
+%_ptr_Output_v3float = OpTypePointer Output %v3float
+     %block2 = OpTypeStruct %float %v4float
+%_ptr_Output_block2 = OpTypePointer Output %block2
+          %y = OpVariable %_ptr_Output_block2 Output
+    %float_7 = OpConstant %float 7
+    %float_8 = OpConstant %float 8
+    %float_9 = OpConstant %float 9
+   %float_10 = OpConstant %float 10
+   %float_11 = OpConstant %float 11
+         %50 = OpConstantComposite %v4float %float_8 %float_9 %float_10 %float_11
+%_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
+         %19 = OpAccessChain %_ptr_Output_v4float %_ %int_0
+               OpStore %19 %17
+         %27 = OpAccessChain %_ptr_Output_float %x %int_0
+               OpStore %27 %float_1
+         %33 = OpAccessChain %_ptr_Output_v2float %x %int_1
+               OpStore %33 %31
+         %40 = OpAccessChain %_ptr_Output_v3float %x %int_3
+               OpStore %40 %38
+         %45 = OpAccessChain %_ptr_Output_float %y %int_0
+               OpStore %45 %float_7
+         %51 = OpAccessChain %_ptr_Output_v4float %y %int_1
+               OpStore %51 %50
+               OpReturn
+               OpFunctionEnd
+
+[vertex shader]
+#version 150
+#extension GL_ARB_enhanced_layouts: require
+
+out block {
+  layout(xfb_offset = 0) out float x1_out;
+  layout(xfb_offset = 4) out vec2 x2_out;
+  layout(xfb_buffer = 0) out vec3 not_captured;
+  layout(xfb_offset = 12) out vec3 x3_out;
+} x;
+layout(xfb_buffer = 2) out;
+layout(xfb_offset = 0) out block2 {
+  float y1_out;
+  vec4 y2_out;
+} y;
+void main() {
+  gl_Position = vec4(0.0);
+  x.x1_out = 1.0;
+  x.x2_out = vec2(2.0, 3.0);
+  x.x3_out = vec3(4.0, 5.0, 6.0);
+  y.y1_out = 7.0;
+  y.y2_out = vec4(8.0, 9.0, 10.0, 11.0);
+}
\ No newline at end of file
diff --git a/tests/spec/arb_enhanced_layouts/shader_test/vs_two_sets_struct.shader_test b/tests/spec/arb_enhanced_layouts/shader_test/vs_two_sets_struct.shader_test
new file mode 100644
index 000000000..783d28402
--- /dev/null
+++ b/tests/spec/arb_enhanced_layouts/shader_test/vs_two_sets_struct.shader_test
@@ -0,0 +1,131 @@ 
+[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: 57
+; Schema: 0
+               OpCapability Shader
+               OpCapability TransformFeedback
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Vertex %main "main" %_ %s1 %s2 %gl_VertexID %gl_InstanceID
+               OpExecutionMode %main Xfb
+               OpSource GLSL 450
+               OpSourceExtension "GL_ARB_enhanced_layouts"
+               OpName %_ ""
+               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 %_ XfbBuffer 0
+               OpDecorate %_ XfbStride 24
+               OpDecorate %s1 Location 0
+               OpDecorate %s1 XfbBuffer 0
+               OpDecorate %s1 XfbStride 24
+               OpDecorate %s1 Offset 0
+               OpDecorate %s2 Location 6
+               OpDecorate %s2 XfbBuffer 2
+               OpDecorate %s2 XfbStride 20
+               OpDecorate %s2 Offset 0
+               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
+    %float_0 = OpConstant %float 0
+         %17 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+      %Array = OpTypeStruct %float
+     %uint_2 = OpConstant %uint 2
+%_arr_Array_uint_2 = OpTypeArray %Array %uint_2
+        %AoA = OpTypeStruct %_arr_Array_uint_2
+%_arr_AoA_uint_2 = OpTypeArray %AoA %uint_2
+          %S = OpTypeStruct %float %_arr_AoA_uint_2 %float
+%_ptr_Output_S = OpTypePointer Output %S
+         %s1 = OpVariable %_ptr_Output_S Output
+    %float_1 = OpConstant %float 1
+%_ptr_Output_float = OpTypePointer Output %float
+      %int_1 = OpConstant %int 1
+    %float_2 = OpConstant %float 2
+    %float_3 = OpConstant %float 3
+    %float_4 = OpConstant %float 4
+    %float_5 = OpConstant %float 5
+      %int_2 = OpConstant %int 2
+    %float_6 = OpConstant %float 6
+         %S2 = OpTypeStruct %float %v4float
+%_ptr_Output_S2 = OpTypePointer Output %S2
+         %s2 = OpVariable %_ptr_Output_S2 Output
+    %float_7 = OpConstant %float 7
+    %float_8 = OpConstant %float 8
+    %float_9 = OpConstant %float 9
+   %float_10 = OpConstant %float 10
+   %float_11 = OpConstant %float 11
+         %52 = OpConstantComposite %v4float %float_8 %float_9 %float_10 %float_11
+%_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
+         %19 = OpAccessChain %_ptr_Output_v4float %_ %int_0
+               OpStore %19 %17
+         %30 = OpAccessChain %_ptr_Output_float %s1 %int_0
+               OpStore %30 %float_1
+         %33 = OpAccessChain %_ptr_Output_float %s1 %int_1 %int_0 %int_0 %int_0 %int_0
+               OpStore %33 %float_2
+         %35 = OpAccessChain %_ptr_Output_float %s1 %int_1 %int_0 %int_0 %int_1 %int_0
+               OpStore %35 %float_3
+         %37 = OpAccessChain %_ptr_Output_float %s1 %int_1 %int_1 %int_0 %int_0 %int_0
+               OpStore %37 %float_4
+         %39 = OpAccessChain %_ptr_Output_float %s1 %int_1 %int_1 %int_0 %int_1 %int_0
+               OpStore %39 %float_5
+         %42 = OpAccessChain %_ptr_Output_float %s1 %int_2
+               OpStore %42 %float_6
+         %47 = OpAccessChain %_ptr_Output_float %s2 %int_0
+               OpStore %47 %float_7
+         %53 = OpAccessChain %_ptr_Output_v4float %s2 %int_1
+               OpStore %53 %52
+               OpReturn
+               OpFunctionEnd
+
+[vertex shader]
+#version 150
+#extension GL_ARB_enhanced_layouts: require
+
+struct Array {
+  float x2_out;
+};
+struct AoA {
+  Array x2_Array[2];
+};
+struct S {
+  float x1_out;
+  AoA x2_AoA[2];
+  float x3_out;
+};
+layout(xfb_offset = 0) out S s1;
+layout(xfb_offset = 0, xfb_buffer = 2) out struct S2 {
+  float y1_out;
+  vec4 y2_out;
+} s2;
+void main() {
+  gl_Position = vec4(0.0);
+  s1.x1_out = 1.0;
+  s1.x2_AoA[0].x2_Array[0].x2_out = 2.0;
+  s1.x2_AoA[0].x2_Array[1].x2_out = 3.0;
+  s1.x2_AoA[1].x2_Array[0].x2_out = 4.0;
+  s1.x2_AoA[1].x2_Array[1].x2_out = 5.0;
+  s1.x3_out = 6.0;
+  s2.y1_out = 7.0;
+  s2.y2_out = vec4(8.0, 9.0, 10.0, 11.0);
+}
diff --git a/tests/spec/arb_enhanced_layouts/transform-feedback-layout-qualifiers.c b/tests/spec/arb_enhanced_layouts/transform-feedback-layout-qualifiers.c
index b51a1ac4e..a18b95ccd 100644
--- a/tests/spec/arb_enhanced_layouts/transform-feedback-layout-qualifiers.c
+++ b/tests/spec/arb_enhanced_layouts/transform-feedback-layout-qualifiers.c
@@ -23,6 +23,8 @@ 
 
 #include "piglit-util-gl.h"
 
+#include "piglit-shader-test.h"
+
 PIGLIT_GL_TEST_CONFIG_BEGIN
 
 	config.supports_gl_compat_version = 32;
@@ -36,105 +38,13 @@  static const char vs_pass_thru_text[] =
 	"  gl_Position = vec4(0.0);\n"
 	"}\n";
 
-static const char vs_two_sets_text[] =
-	"#version 150\n"
-	"#extension GL_ARB_enhanced_layouts: require\n"
-	"\n"
-	"layout(xfb_offset = 0) out float x1_out;\n"
-	"layout(xfb_offset = 4) out float x2_out[2];\n"
-	"layout(xfb_offset = 12) out vec3 x3_out;\n"
-	"layout(xfb_buffer = 2) out;\n"
-	"layout(xfb_offset = 0, xfb_buffer = 2) out float y1_out;\n"
-	"layout(xfb_offset = 4) out vec4 y2_out;\n"
-	"void main() {\n"
-	"  gl_Position = vec4(0.0);\n"
-	"  x1_out = 1.0;\n"
-	"  x2_out[0] = 2.0;\n"
-	"  x2_out[1] = 3.0;\n"
-	"  x3_out = vec3(4.0, 5.0, 6.0);\n"
-	"  y1_out = 7.0;\n"
-	"  y2_out = vec4(8.0, 9.0, 10.0, 11.0);\n"
-	"}";
+#define VS_TWO_SETS_NAME "vs_two_sets.shader_test"
 
-static const char vs_two_sets_ifc_text[] =
-	"#version 150\n"
-	"#extension GL_ARB_enhanced_layouts: require\n"
-	"\n"
-	"out block {\n"
-	"  layout(xfb_offset = 12) out float x1_out;\n"
-	"  layout(xfb_offset = 16) out vec2 x2_out;\n"
-	"  layout(xfb_buffer = 0) out vec3 not_captured;\n"
-	"  layout(xfb_offset = 0) out vec3 x3_out;\n"
-	"};"
-	"layout(xfb_buffer = 2) out;\n"
-	"layout(xfb_offset = 0) out block2 {\n"
-	"  float y1_out;\n"
-	"  vec4 y2_out;\n"
-	"};\n"
-	"void main() {\n"
-	"  gl_Position = vec4(0.0);\n"
-	"  x1_out = 4.0;\n"
-	"  x2_out = vec2(5.0, 6.0);\n"
-	"  x3_out = vec3(1.0, 2.0, 3.0);\n"
-	"  y1_out = 7.0;\n"
-	"  y2_out = vec4(8.0, 9.0, 10.0, 11.0);\n"
-	"}";
+#define VS_TWO_SETS_IFC_NAME "vs_two_sets_ifc.shader_test"
 
-static const char vs_two_sets_named_ifc_text[] =
-	"#version 150\n"
-	"#extension GL_ARB_enhanced_layouts: require\n"
-	"\n"
-	"out block {\n"
-	"  layout(xfb_offset = 0) out float x1_out;\n"
-	"  layout(xfb_offset = 4) out vec2 x2_out;\n"
-	"  layout(xfb_buffer = 0) out vec3 not_captured;\n"
-	"  layout(xfb_offset = 12) out vec3 x3_out;\n"
-	"} x;"
-	"layout(xfb_buffer = 2) out;\n"
-	"layout(xfb_offset = 0) out block2 {\n"
-	"  float y1_out;\n"
-	"  vec4 y2_out;\n"
-	"} y;\n"
-	"void main() {\n"
-	"  gl_Position = vec4(0.0);\n"
-	"  x.x1_out = 1.0;\n"
-	"  x.x2_out = vec2(2.0, 3.0);\n"
-	"  x.x3_out = vec3(4.0, 5.0, 6.0);\n"
-	"  y.y1_out = 7.0;\n"
-	"  y.y2_out = vec4(8.0, 9.0, 10.0, 11.0);\n"
-	"}";
+#define VS_TWO_SETS_NAMED_IFC_NAME "vs_two_sets_named_ifc.shader_test"
 
-static const char vs_two_sets_struct_text[] =
-	"#version 150\n"
-	"#extension GL_ARB_enhanced_layouts: require\n"
-	"\n"
-	"struct Array {\n"
-	"  float x2_out;\n"
-	"};\n"
-	"struct AoA {\n"
-	"  Array x2_Array[2];\n"
-	"};\n"
-	"struct S {\n"
-	"  float x1_out;\n"
-	"  AoA x2_AoA[2];\n"
-	"  float x3_out;\n"
-	"};"
-	"layout(xfb_offset = 0) out S s1;\n"
-	"layout(xfb_offset = 0, xfb_buffer = 2) out struct S2 {\n"
-	"  float y1_out;\n"
-	"  vec4 y2_out;\n"
-	"} s2;\n"
-	"void main() {\n"
-	"  gl_Position = vec4(0.0);\n"
-	"  s1.x1_out = 1.0;\n"
-	"  s1.x2_AoA[0].x2_Array[0].x2_out = 2.0;\n"
-	"  s1.x2_AoA[0].x2_Array[1].x2_out = 3.0;\n"
-	"  s1.x2_AoA[1].x2_Array[0].x2_out = 4.0;\n"
-	"  s1.x2_AoA[1].x2_Array[1].x2_out = 5.0;\n"
-	"  s1.x3_out = 6.0;\n"
-	"  s2.y1_out = 7.0;\n"
-	"  s2.y2_out = vec4(8.0, 9.0, 10.0, 11.0);\n"
-	"}";
+#define VS_TWO_SETS_STRUCT_NAME "vs_two_sets_struct.shader_test"
 
 static const char gs_text_two_sets_tmpl[] =
 	"#version 150\n"
@@ -167,13 +77,20 @@  static const char gs_text_two_sets_tmpl[] =
 	"  EndPrimitive();\n"
 	"}";
 
+struct test_config {
+	const char *shader_test_filename;
+	bool spirv;
+	GLint gs_invocation_n;
+};
+
 #define BUF_1_FLOAT_N 6
 #define BUF_2_FLOAT_N 5
 
+
 static void
 print_usage_and_exit(const char *prog_name)
 {
-	printf("Usage: %s <subtest>\n"
+	printf("Usage: %s <subtest> [spirv]\n"
 	       "  where <subtest> is one of the following:\n"
 	       "    vs (vertex shader only)\n"
 	       "    vs_ifc (vertex shader only, with interface block)\n"
@@ -181,22 +98,84 @@  print_usage_and_exit(const char *prog_name)
 	       "    vs_struct (vertex shader only, with structs)\n"
 	       "    gs (with geometry shader invoked once per stage)\n"
 	       "    gs_max (with geometry shader invoked max times per "
-	       "stage)\n", prog_name);
+	       "stage)\n"
+	       "  add “spirv” to the command line to use SPIR-V shaders "
+	       "instead of GLSL. Only vs* tests suport SPIR-V shaders.\n",
+	       prog_name);
 	piglit_report_result(PIGLIT_FAIL);
 }
 
+static GLuint
+compile_spirv_program(GLenum shader_type,
+		      const unsigned spirv_asm_size,
+		      const char *spirv_asm)
+{
+	GLuint shader, prog;
+
+	shader = piglit_assemble_spirv(shader_type,
+				       spirv_asm_size,
+				       spirv_asm);
+
+	glSpecializeShader(shader,
+			   "main",
+			   0, /* numSpecializationConstants */
+			   NULL /* pConstantIndex */,
+			   NULL /* pConstantValue */);
+
+	prog = glCreateProgram();
+	glAttachShader(prog, shader);
+	glDeleteShader(shader);
+
+	return prog;
+}
+
 static void
-build_and_use_program(unsigned gs_invocation_n, const char *vs_text)
+build_and_use_program(const struct test_config *config)
 {
 	GLuint prog;
 
-	if (gs_invocation_n == 0) {
-		prog = piglit_build_simple_program_multiple_shaders(
-				GL_VERTEX_SHADER, vs_text, 0);
+	if (config->gs_invocation_n == 0) {
+		char filepath[4096];
+		char *source;
+		unsigned source_size;
+
+		piglit_join_paths(filepath,
+				  sizeof(filepath),
+				  6, /* num parts */
+				  piglit_source_dir(),
+				  "tests",
+				  "spec",
+				  "arb_enhanced_layouts",
+				  "shader_test",
+				  config->shader_test_filename);
+
+		piglit_load_source_from_shader_test(filepath,
+						    GL_VERTEX_SHADER,
+						    config->spirv,
+						    &source,
+						    &source_size);
+
+		if (config->spirv) {
+			prog = compile_spirv_program(GL_VERTEX_SHADER,
+						     source_size,
+						     source);
+		} else {
+			prog = piglit_build_simple_program_multiple_shaders(
+				GL_VERTEX_SHADER, source, 0);
+		}
+
+		free(source);
 	} else {
+		if (config->spirv) {
+			fprintf(stderr, "SPIR-V not supported for this subtest\n");
+			piglit_report_result(PIGLIT_FAIL);
+		}
+
 		char *gs_text;
 
-		(void)!asprintf(&gs_text, gs_text_two_sets_tmpl, gs_invocation_n);
+		(void)!asprintf(&gs_text,
+				gs_text_two_sets_tmpl,
+				config->gs_invocation_n);
 		prog = piglit_build_simple_program_multiple_shaders(
 				GL_VERTEX_SHADER, vs_pass_thru_text,
 				GL_GEOMETRY_SHADER, gs_text, 0);
@@ -268,72 +247,119 @@  probe_buffers(const GLuint *xfb, const GLuint *queries, unsigned primitive_n)
 	return pass;
 }
 
-static unsigned
-parse_args(int argc, char **argv, const char **vs_text)
+static void
+parse_args(int argc, char **argv, struct test_config *config)
 {
-	GLint gs_invocation_n;
-
-	if (argc != 2)
-		print_usage_and_exit(argv[0]);
-
-	if (strcmp(argv[1], "vs") == 0) {
-		*vs_text = vs_two_sets_text;
-		return 0;
+	int i, j;
+	bool option_was_handled = false;
+	static const struct {
+		const char *name;
+		const char *shader_test_filename;
+		unsigned gs_invocation_n;
+	} test_types[] = {
+		{
+			"vs",
+			"vs_two_sets.shader_test",
+			0
+		},
+		{
+			"vs_ifc",
+			"vs_two_sets_ifc.shader_test",
+			0
+		},
+		{
+			"vs_named_ifc",
+			"vs_two_sets_named_ifc.shader_test",
+			0
+		},
+		{
+			"vs_struct",
+			"vs_two_sets_struct.shader_test",
+			0
+		},
+		{
+			"gs",
+			NULL,
+			1
+		},
+		{
+			"gs_max",
+			NULL,
+			INT_MAX
+		}
+	};
+
+	memset(config, 0, sizeof *config);
+
+	for (i = 1; i < argc; i++) {
+		for (j = 0; j < ARRAY_SIZE(test_types); j++) {
+			if (!strcmp(argv[i], test_types[j].name)) {
+				config->shader_test_filename =
+					test_types[j].shader_test_filename,
+				config->gs_invocation_n =
+					test_types[j].gs_invocation_n;
+				option_was_handled = true;
+				goto option_handled;
+			}
+		}
+
+		if (!strcmp(argv[i], "spirv"))
+			config->spirv = true;
+
+	option_handled:
+		continue;
 	}
 
-	if (strcmp(argv[1], "vs_ifc") == 0) {
-		*vs_text = vs_two_sets_ifc_text;
-		return 0;
-	}
-
-	if (strcmp(argv[1], "vs_named_ifc") == 0) {
-		*vs_text = vs_two_sets_named_ifc_text;
-		return 0;
-	}
-
-	if (strcmp(argv[1], "vs_struct") == 0) {
-		*vs_text = vs_two_sets_struct_text;
-		return 0;
-	}
-
-	piglit_require_extension("GL_ARB_gpu_shader5");
-
-	if (strcmp(argv[1], "gs") == 0)
-		return 1;
-
-	if (strcmp(argv[1], "gs_max") != 0)
+	if (!option_was_handled)
 		print_usage_and_exit(argv[0]);
-
-	glGetIntegerv(GL_MAX_GEOMETRY_SHADER_INVOCATIONS, &gs_invocation_n);
-	if (gs_invocation_n <= 0) {
-		printf("Maximum amount of geometry shader invocations "
-		       "needs to be positive (%u).\n", gs_invocation_n);
-		piglit_report_result(PIGLIT_FAIL);
-	}
-
-	return gs_invocation_n;
 }
 
 void
 piglit_init(int argc, char **argv)
 {
 	bool pass;
-	unsigned primitive_n, gs_invocation_n;
-	const char *vs_text;
+	unsigned primitive_n;
 	GLuint queries[2];
 	GLuint xfb[2];
 	GLuint vao;
+	struct test_config config;
 
 	piglit_require_GLSL_version(150);
 	piglit_require_extension("GL_ARB_transform_feedback3");
 	piglit_require_extension("GL_ARB_enhanced_layouts");
 
-	gs_invocation_n = parse_args(argc, argv, &vs_text);
+	parse_args(argc, argv, &config);
+
+	if (config.gs_invocation_n > 0) {
+		piglit_require_extension("GL_ARB_gpu_shader5");
+
+		if (config.gs_invocation_n == INT_MAX) {
+			glGetIntegerv(GL_MAX_GEOMETRY_SHADER_INVOCATIONS,
+				      &config.gs_invocation_n);
+			if (config.gs_invocation_n <= 0) {
+				printf("Maximum amount of geometry shader "
+				       "invocations needs to be positive "
+				       "(%u).\n",
+				       config.gs_invocation_n);
+				piglit_report_result(PIGLIT_FAIL);
+			}
+		}
+	}
+
+	if (config.spirv) {
+		piglit_require_extension("GL_ARB_gl_spirv");
+
+		if (config.gs_invocation_n > 0) {
+			printf("Geometry shader invocations is not supported "
+			       "with SPIR-V\n");
+			piglit_report_result(PIGLIT_FAIL);
+		}
+	}
 
 	/* Zero invocations means the feedback is produced by vertex shader */
-	primitive_n = gs_invocation_n ? gs_invocation_n : 1;
+	primitive_n = config.gs_invocation_n ? config.gs_invocation_n : 1;
 
-	build_and_use_program(gs_invocation_n, vs_text);
+	build_and_use_program(&config);
 
 	/* Set up the transform feedback buffers. */
 	glGenBuffers(ARRAY_SIZE(xfb), xfb);