Add CTS_ARB_gl_spirv test implementation
authorAdam Czupryna <adam.czupryna@mobica.com>
Fri, 7 Jul 2017 09:42:37 +0000 (11:42 +0200)
committerAlexander Galazin <Alexander.Galazin@arm.com>
Fri, 3 Nov 2017 10:53:53 +0000 (06:53 -0400)
Add CTS_ARB_gl_spirv test implementation that contains:
SpirvModulesPositiveTest,
SpirvModulesShaderBinaryMultipleShaderObjectsTest,
SpirvModulesStateQueriesTest,
SpirvModulesErrorVerificationTest,
SpirvGlslToSpirVEnableTest,
SpirvGlslToSpirVBuiltInFunctionsTest,
SpirvGlslToSpirVSpecializationConstantsTest,
SpirvValidationBuiltInVariableDecorationsTest

Affects:

KHR-GL45.gl_spirv.*

Components: Framework, OpenGL

VK-GL-CTS issue: 554

Change-Id: I0d54c70df619dbbd80b28350d2ac5e31aca08927

67 files changed:
external/openglcts/data/mustpass/gl/khronos_mustpass/4.6.0.x/gl45-master.txt
external/openglcts/data/mustpass/gl/khronos_mustpass/4.6.0.x/gl46-master.txt
external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_0.nspv [new file with mode: 0644]
external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_1.nspv [new file with mode: 0644]
external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_10.nspv [new file with mode: 0644]
external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_11.nspv [new file with mode: 0644]
external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_12.nspv [new file with mode: 0644]
external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_13.nspv [new file with mode: 0644]
external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_14.nspv [new file with mode: 0644]
external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_15.nspv [new file with mode: 0644]
external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_16.nspv [new file with mode: 0644]
external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_17.nspv [new file with mode: 0644]
external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_18.nspv [new file with mode: 0644]
external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_19.nspv [new file with mode: 0644]
external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_2.nspv [new file with mode: 0644]
external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_20.nspv [new file with mode: 0644]
external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_21.nspv [new file with mode: 0644]
external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_22.nspv [new file with mode: 0644]
external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_23.nspv [new file with mode: 0644]
external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_24.nspv [new file with mode: 0644]
external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_25.nspv [new file with mode: 0644]
external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_26.nspv [new file with mode: 0644]
external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_27.nspv [new file with mode: 0644]
external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_28.nspv [new file with mode: 0644]
external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_29.nspv [new file with mode: 0644]
external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_3.nspv [new file with mode: 0644]
external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_4.nspv [new file with mode: 0644]
external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_5.nspv [new file with mode: 0644]
external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_6.nspv [new file with mode: 0644]
external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_7.nspv [new file with mode: 0644]
external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_8.nspv [new file with mode: 0644]
external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_9.nspv [new file with mode: 0644]
external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/common_tesseval.nspv [new file with mode: 0644]
external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/common_vertex.nspv [new file with mode: 0644]
external/openglcts/data/spirv/glsl_to_spirv_specialization_constants/fragment.nspv [new file with mode: 0644]
external/openglcts/data/spirv/glsl_to_spirv_specialization_constants/vertex.nspv [new file with mode: 0644]
external/openglcts/data/spirv/modules_error_verification/vertex.nspv [new file with mode: 0644]
external/openglcts/data/spirv/modules_positive/fragment.nspv [new file with mode: 0644]
external/openglcts/data/spirv/modules_positive/geometry.nspv [new file with mode: 0644]
external/openglcts/data/spirv/modules_positive/tess_control.nspv [new file with mode: 0644]
external/openglcts/data/spirv/modules_positive/tess_evaluation.nspv [new file with mode: 0644]
external/openglcts/data/spirv/modules_positive/vertex.nspv [new file with mode: 0644]
external/openglcts/data/spirv/modules_state_queries/vertex.nspv [new file with mode: 0644]
external/openglcts/data/spirv/spirv_modules_shader_binary_multiple_shader_objects/binary.nspv [new file with mode: 0644]
external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_0_0.nspv [new file with mode: 0644]
external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_1_0.nspv [new file with mode: 0644]
external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_1_1.nspv [new file with mode: 0644]
external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_2_0.nspv [new file with mode: 0644]
external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_2_1.nspv [new file with mode: 0644]
external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_3_0.nspv [new file with mode: 0644]
external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_3_1.nspv [new file with mode: 0644]
external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_4_0.nspv [new file with mode: 0644]
external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_4_1.nspv [new file with mode: 0644]
external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_4_2.nspv [new file with mode: 0644]
external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_4_3.nspv [new file with mode: 0644]
external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_4_4.nspv [new file with mode: 0644]
external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_5_0.nspv [new file with mode: 0644]
external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_5_1.nspv [new file with mode: 0644]
external/openglcts/modules/gl/CMakeLists.txt
external/openglcts/modules/gl/gl4cGlSpirvTests.cpp [new file with mode: 0644]
external/openglcts/modules/gl/gl4cGlSpirvTests.hpp [new file with mode: 0644]
external/openglcts/modules/gl/gl4cTestPackages.cpp
framework/opengl/gluShaderProgram.cpp
framework/opengl/gluShaderProgram.hpp
framework/opengl/wrapper/glwEnums.inl
framework/opengl/wrapper/glwInitExtGL.inl
scripts/opengl/src_util.py

index c5b3131..db5583c 100644 (file)
@@ -7403,3 +7403,11 @@ KHR-GL45.polygon_offset_clamp.PolygonOffsetClampZeroInfinity
 KHR-GL45.separable_programs_tf.tessellation_active
 KHR-GL45.separable_programs_tf.geometry_active
 KHR-GL45.spirv_extensions.spirv_extensions_queries
+KHR-GL45.gl_spirv.spirv_modules_positive_test
+KHR-GL45.gl_spirv.spirv_modules_shader_binary_multiple_shader_objects_test
+KHR-GL45.gl_spirv.spirv_modules_state_queries_test
+KHR-GL45.gl_spirv.spirv_modules_error_verification_test
+KHR-GL45.gl_spirv.spirv_glsl_to_spirv_enable_test
+KHR-GL45.gl_spirv.spirv_glsl_to_spirv_builtin_functions_test
+KHR-GL45.gl_spirv.spirv_glsl_to_spirv_specialization_constants_test
+KHR-GL45.gl_spirv.spirv_validation_builtin_variable_decorations_test
index 893ee14..5f3dfd8 100644 (file)
@@ -7403,3 +7403,11 @@ KHR-GL46.polygon_offset_clamp.PolygonOffsetClampZeroInfinity
 KHR-GL46.separable_programs_tf.tessellation_active
 KHR-GL46.separable_programs_tf.geometry_active
 KHR-GL46.spirv_extensions.spirv_extensions_queries
+KHR-GL46.gl_spirv.spirv_modules_positive_test
+KHR-GL46.gl_spirv.spirv_modules_shader_binary_multiple_shader_objects_test
+KHR-GL46.gl_spirv.spirv_modules_state_queries_test
+KHR-GL46.gl_spirv.spirv_modules_error_verification_test
+KHR-GL46.gl_spirv.spirv_glsl_to_spirv_enable_test
+KHR-GL46.gl_spirv.spirv_glsl_to_spirv_builtin_functions_test
+KHR-GL46.gl_spirv.spirv_glsl_to_spirv_specialization_constants_test
+KHR-GL46.gl_spirv.spirv_validation_builtin_variable_decorations_test
diff --git a/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_0.nspv b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_0.nspv
new file mode 100644 (file)
index 0000000..ccdc3ee
Binary files /dev/null and b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_0.nspv differ
diff --git a/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_1.nspv b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_1.nspv
new file mode 100644 (file)
index 0000000..42c8063
Binary files /dev/null and b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_1.nspv differ
diff --git a/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_10.nspv b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_10.nspv
new file mode 100644 (file)
index 0000000..c7def26
Binary files /dev/null and b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_10.nspv differ
diff --git a/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_11.nspv b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_11.nspv
new file mode 100644 (file)
index 0000000..321c421
Binary files /dev/null and b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_11.nspv differ
diff --git a/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_12.nspv b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_12.nspv
new file mode 100644 (file)
index 0000000..f7a95cc
Binary files /dev/null and b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_12.nspv differ
diff --git a/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_13.nspv b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_13.nspv
new file mode 100644 (file)
index 0000000..2d2a85d
Binary files /dev/null and b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_13.nspv differ
diff --git a/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_14.nspv b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_14.nspv
new file mode 100644 (file)
index 0000000..aee9d4b
Binary files /dev/null and b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_14.nspv differ
diff --git a/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_15.nspv b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_15.nspv
new file mode 100644 (file)
index 0000000..c77aedc
Binary files /dev/null and b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_15.nspv differ
diff --git a/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_16.nspv b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_16.nspv
new file mode 100644 (file)
index 0000000..e22b70c
Binary files /dev/null and b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_16.nspv differ
diff --git a/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_17.nspv b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_17.nspv
new file mode 100644 (file)
index 0000000..92012c4
Binary files /dev/null and b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_17.nspv differ
diff --git a/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_18.nspv b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_18.nspv
new file mode 100644 (file)
index 0000000..07e621c
Binary files /dev/null and b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_18.nspv differ
diff --git a/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_19.nspv b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_19.nspv
new file mode 100644 (file)
index 0000000..276198c
Binary files /dev/null and b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_19.nspv differ
diff --git a/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_2.nspv b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_2.nspv
new file mode 100644 (file)
index 0000000..ebc623f
Binary files /dev/null and b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_2.nspv differ
diff --git a/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_20.nspv b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_20.nspv
new file mode 100644 (file)
index 0000000..205ebb9
Binary files /dev/null and b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_20.nspv differ
diff --git a/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_21.nspv b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_21.nspv
new file mode 100644 (file)
index 0000000..7cf280b
Binary files /dev/null and b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_21.nspv differ
diff --git a/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_22.nspv b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_22.nspv
new file mode 100644 (file)
index 0000000..e579075
Binary files /dev/null and b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_22.nspv differ
diff --git a/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_23.nspv b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_23.nspv
new file mode 100644 (file)
index 0000000..638e475
Binary files /dev/null and b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_23.nspv differ
diff --git a/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_24.nspv b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_24.nspv
new file mode 100644 (file)
index 0000000..9a744d4
Binary files /dev/null and b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_24.nspv differ
diff --git a/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_25.nspv b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_25.nspv
new file mode 100644 (file)
index 0000000..ee0e1db
Binary files /dev/null and b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_25.nspv differ
diff --git a/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_26.nspv b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_26.nspv
new file mode 100644 (file)
index 0000000..d5fdb95
Binary files /dev/null and b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_26.nspv differ
diff --git a/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_27.nspv b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_27.nspv
new file mode 100644 (file)
index 0000000..d987399
Binary files /dev/null and b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_27.nspv differ
diff --git a/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_28.nspv b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_28.nspv
new file mode 100644 (file)
index 0000000..237285b
Binary files /dev/null and b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_28.nspv differ
diff --git a/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_29.nspv b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_29.nspv
new file mode 100644 (file)
index 0000000..fa82565
Binary files /dev/null and b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_29.nspv differ
diff --git a/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_3.nspv b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_3.nspv
new file mode 100644 (file)
index 0000000..ffc43e1
Binary files /dev/null and b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_3.nspv differ
diff --git a/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_4.nspv b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_4.nspv
new file mode 100644 (file)
index 0000000..58ae79b
Binary files /dev/null and b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_4.nspv differ
diff --git a/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_5.nspv b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_5.nspv
new file mode 100644 (file)
index 0000000..a21b53e
Binary files /dev/null and b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_5.nspv differ
diff --git a/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_6.nspv b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_6.nspv
new file mode 100644 (file)
index 0000000..955c434
Binary files /dev/null and b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_6.nspv differ
diff --git a/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_7.nspv b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_7.nspv
new file mode 100644 (file)
index 0000000..d1a69f3
Binary files /dev/null and b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_7.nspv differ
diff --git a/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_8.nspv b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_8.nspv
new file mode 100644 (file)
index 0000000..7f59625
Binary files /dev/null and b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_8.nspv differ
diff --git a/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_9.nspv b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_9.nspv
new file mode 100644 (file)
index 0000000..3d3600a
Binary files /dev/null and b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/binary_9.nspv differ
diff --git a/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/common_tesseval.nspv b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/common_tesseval.nspv
new file mode 100644 (file)
index 0000000..ec2f82f
Binary files /dev/null and b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/common_tesseval.nspv differ
diff --git a/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/common_vertex.nspv b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/common_vertex.nspv
new file mode 100644 (file)
index 0000000..8f4dcff
Binary files /dev/null and b/external/openglcts/data/spirv/glsl_to_spirv_builtin_functions/common_vertex.nspv differ
diff --git a/external/openglcts/data/spirv/glsl_to_spirv_specialization_constants/fragment.nspv b/external/openglcts/data/spirv/glsl_to_spirv_specialization_constants/fragment.nspv
new file mode 100644 (file)
index 0000000..1278e68
Binary files /dev/null and b/external/openglcts/data/spirv/glsl_to_spirv_specialization_constants/fragment.nspv differ
diff --git a/external/openglcts/data/spirv/glsl_to_spirv_specialization_constants/vertex.nspv b/external/openglcts/data/spirv/glsl_to_spirv_specialization_constants/vertex.nspv
new file mode 100644 (file)
index 0000000..a0564fd
Binary files /dev/null and b/external/openglcts/data/spirv/glsl_to_spirv_specialization_constants/vertex.nspv differ
diff --git a/external/openglcts/data/spirv/modules_error_verification/vertex.nspv b/external/openglcts/data/spirv/modules_error_verification/vertex.nspv
new file mode 100644 (file)
index 0000000..33f7707
Binary files /dev/null and b/external/openglcts/data/spirv/modules_error_verification/vertex.nspv differ
diff --git a/external/openglcts/data/spirv/modules_positive/fragment.nspv b/external/openglcts/data/spirv/modules_positive/fragment.nspv
new file mode 100644 (file)
index 0000000..08b2c71
Binary files /dev/null and b/external/openglcts/data/spirv/modules_positive/fragment.nspv differ
diff --git a/external/openglcts/data/spirv/modules_positive/geometry.nspv b/external/openglcts/data/spirv/modules_positive/geometry.nspv
new file mode 100644 (file)
index 0000000..8522d2d
Binary files /dev/null and b/external/openglcts/data/spirv/modules_positive/geometry.nspv differ
diff --git a/external/openglcts/data/spirv/modules_positive/tess_control.nspv b/external/openglcts/data/spirv/modules_positive/tess_control.nspv
new file mode 100644 (file)
index 0000000..0bf59a1
Binary files /dev/null and b/external/openglcts/data/spirv/modules_positive/tess_control.nspv differ
diff --git a/external/openglcts/data/spirv/modules_positive/tess_evaluation.nspv b/external/openglcts/data/spirv/modules_positive/tess_evaluation.nspv
new file mode 100644 (file)
index 0000000..28bcc83
Binary files /dev/null and b/external/openglcts/data/spirv/modules_positive/tess_evaluation.nspv differ
diff --git a/external/openglcts/data/spirv/modules_positive/vertex.nspv b/external/openglcts/data/spirv/modules_positive/vertex.nspv
new file mode 100644 (file)
index 0000000..f765289
Binary files /dev/null and b/external/openglcts/data/spirv/modules_positive/vertex.nspv differ
diff --git a/external/openglcts/data/spirv/modules_state_queries/vertex.nspv b/external/openglcts/data/spirv/modules_state_queries/vertex.nspv
new file mode 100644 (file)
index 0000000..41cb7c7
Binary files /dev/null and b/external/openglcts/data/spirv/modules_state_queries/vertex.nspv differ
diff --git a/external/openglcts/data/spirv/spirv_modules_shader_binary_multiple_shader_objects/binary.nspv b/external/openglcts/data/spirv/spirv_modules_shader_binary_multiple_shader_objects/binary.nspv
new file mode 100644 (file)
index 0000000..1ea715f
Binary files /dev/null and b/external/openglcts/data/spirv/spirv_modules_shader_binary_multiple_shader_objects/binary.nspv differ
diff --git a/external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_0_0.nspv b/external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_0_0.nspv
new file mode 100644 (file)
index 0000000..a9b2499
Binary files /dev/null and b/external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_0_0.nspv differ
diff --git a/external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_1_0.nspv b/external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_1_0.nspv
new file mode 100644 (file)
index 0000000..508b1d2
Binary files /dev/null and b/external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_1_0.nspv differ
diff --git a/external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_1_1.nspv b/external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_1_1.nspv
new file mode 100644 (file)
index 0000000..4d6b161
Binary files /dev/null and b/external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_1_1.nspv differ
diff --git a/external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_2_0.nspv b/external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_2_0.nspv
new file mode 100644 (file)
index 0000000..591448d
Binary files /dev/null and b/external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_2_0.nspv differ
diff --git a/external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_2_1.nspv b/external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_2_1.nspv
new file mode 100644 (file)
index 0000000..24a71ff
Binary files /dev/null and b/external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_2_1.nspv differ
diff --git a/external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_3_0.nspv b/external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_3_0.nspv
new file mode 100644 (file)
index 0000000..f27d3c8
Binary files /dev/null and b/external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_3_0.nspv differ
diff --git a/external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_3_1.nspv b/external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_3_1.nspv
new file mode 100644 (file)
index 0000000..f2da4b0
Binary files /dev/null and b/external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_3_1.nspv differ
diff --git a/external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_4_0.nspv b/external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_4_0.nspv
new file mode 100644 (file)
index 0000000..591448d
Binary files /dev/null and b/external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_4_0.nspv differ
diff --git a/external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_4_1.nspv b/external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_4_1.nspv
new file mode 100644 (file)
index 0000000..5ff409f
Binary files /dev/null and b/external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_4_1.nspv differ
diff --git a/external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_4_2.nspv b/external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_4_2.nspv
new file mode 100644 (file)
index 0000000..2e67053
Binary files /dev/null and b/external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_4_2.nspv differ
diff --git a/external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_4_3.nspv b/external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_4_3.nspv
new file mode 100644 (file)
index 0000000..8be0d63
Binary files /dev/null and b/external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_4_3.nspv differ
diff --git a/external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_4_4.nspv b/external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_4_4.nspv
new file mode 100644 (file)
index 0000000..c157ad2
Binary files /dev/null and b/external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_4_4.nspv differ
diff --git a/external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_5_0.nspv b/external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_5_0.nspv
new file mode 100644 (file)
index 0000000..591448d
Binary files /dev/null and b/external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_5_0.nspv differ
diff --git a/external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_5_1.nspv b/external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_5_1.nspv
new file mode 100644 (file)
index 0000000..bf19166
Binary files /dev/null and b/external/openglcts/data/spirv/spirv_validation_builtin_variable_decorations/shader_5_1.nspv differ
index 6084bd6..a50d553 100644 (file)
@@ -122,6 +122,8 @@ set(GLCTS_GL_SRCS
        gl4cIndirectParametersTests.hpp
        gl4cLimitsTests.cpp
        gl4cLimitsTests.hpp
+       gl4cGlSpirvTests.cpp
+       gl4cGlSpirvTests.hpp
        )
 
 set(GLCTS_GL_LIBS
@@ -130,6 +132,31 @@ set(GLCTS_GL_LIBS
        tcutil
        )
 
+# Add glslang
+if (DEQP_HAVE_GLSLANG)
+       include_directories(${GLSLANG_INCLUDE_PATH})
+       add_definitions(-DDEQP_HAVE_GLSLANG=1)
+
+       # \note Code interfacing with glslang needs to include third-party headers
+       #       that cause all sorts of warnings to appear.
+       if (DE_COMPILER_IS_GCC OR DE_COMPILER_IS_CLANG)
+               set_source_files_properties(
+                       FILES gl4cGlSpirvTests.cpp
+                       PROPERTIES COMPILE_FLAGS "${DE_3RD_PARTY_CXX_FLAGS} -std=c++11")
+       endif ()
+
+       set(GLCTS_GL_LIBS ${GLCTS_GL_LIBS} ${GLSLANG_LIBRARY})
+endif ()
+
+# Add spirv-tools
+if(DEQP_HAVE_SPIRV_TOOLS)
+       include_directories(${spirv-tools_SOURCE_DIR}/include)
+       include_directories(${spirv-tools_SOURCE_DIR}/external/include)
+
+       add_definitions(-DDEQP_HAVE_SPIRV_TOOLS=1)
+       set(GLCTS_GL_LIBS ${GLCTS_GL_LIBS} SPIRV-Tools)
+endif()
+
 if (DEQP_GTF_AVAILABLE)
        list(APPEND GLCTS_GL_LIBS glcts-gtf)
 endif ()
diff --git a/external/openglcts/modules/gl/gl4cGlSpirvTests.cpp b/external/openglcts/modules/gl/gl4cGlSpirvTests.cpp
new file mode 100644 (file)
index 0000000..696572e
--- /dev/null
@@ -0,0 +1,3444 @@
+/*-------------------------------------------------------------------------
+ * OpenGL Conformance Test Suite
+ * -----------------------------
+ *
+ * Copyright (c) 2017 The Khronos Group Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */ /*!
+ * \file
+ * \brief
+ */ /*-------------------------------------------------------------------*/
+
+/**
+ */ /*!
+ * \file  gl4cGlSpirvTests.cpp
+ * \brief Conformance tests for the GL_ARB_gl_spirv functionality.
+ */ /*-------------------------------------------------------------------*/
+
+#include "gl4cGlSpirvTests.hpp"
+#include "deArrayUtil.hpp"
+#include "deSingleton.h"
+#include "deStringUtil.hpp"
+#include "gluContextInfo.hpp"
+#include "gluDefs.hpp"
+#include "gluShaderProgram.hpp"
+#include "gluStrUtil.hpp"
+#include "glwEnums.hpp"
+#include "glwFunctions.hpp"
+#include "tcuRenderTarget.hpp"
+#include "tcuResource.hpp"
+#include "tcuTestLog.hpp"
+
+#if defined DEQP_HAVE_GLSLANG
+#include "SPIRV/GlslangToSpv.h"
+#include "SPIRV/disassemble.h"
+#include "SPIRV/doc.h"
+#include "glslang/MachineIndependent/localintermediate.h"
+#include "glslang/Public/ShaderLang.h"
+#endif // DEQP_HAVE_GLSLANG
+
+#if defined DEQP_HAVE_SPIRV_TOOLS
+#include "spirv-tools/libspirv.hpp"
+#include "spirv-tools/optimizer.hpp"
+#endif // DEQP_HAVE_SPIRV_TOOLS
+
+using namespace glu;
+using namespace glw;
+
+namespace gl4cts
+{
+
+namespace glslangUtils
+{
+
+#if defined DEQP_HAVE_GLSLANG
+
+EShLanguage getGlslangStage(glu::ShaderType type)
+{
+       static const EShLanguage stageMap[] = {
+               EShLangVertex, EShLangFragment, EShLangGeometry, EShLangTessControl, EShLangTessEvaluation, EShLangCompute,
+       };
+
+       return de::getSizedArrayElement<glu::SHADERTYPE_LAST>(stageMap, type);
+}
+
+static volatile deSingletonState s_glslangInitState = DE_SINGLETON_STATE_NOT_INITIALIZED;
+
+void initGlslang(void*)
+{
+       // Main compiler
+       glslang::InitializeProcess();
+
+       // SPIR-V disassembly
+       spv::Parameterize();
+}
+
+void prepareGlslang(void)
+{
+       deInitSingleton(&s_glslangInitState, initGlslang, DE_NULL);
+}
+
+void getDefaultLimits(TLimits* limits)
+{
+       limits->nonInductiveForLoops                             = true;
+       limits->whileLoops                                                       = true;
+       limits->doWhileLoops                                             = true;
+       limits->generalUniformIndexing                           = true;
+       limits->generalAttributeMatrixVectorIndexing = true;
+       limits->generalVaryingIndexing                           = true;
+       limits->generalSamplerIndexing                           = true;
+       limits->generalVariableIndexing                          = true;
+       limits->generalConstantMatrixVectorIndexing  = true;
+}
+
+void getDefaultBuiltInResources(TBuiltInResource* builtin)
+{
+       getDefaultLimits(&builtin->limits);
+
+       builtin->maxLights                                                                 = 32;
+       builtin->maxClipPlanes                                                     = 6;
+       builtin->maxTextureUnits                                                   = 32;
+       builtin->maxTextureCoords                                                  = 32;
+       builtin->maxVertexAttribs                                                  = 64;
+       builtin->maxVertexUniformComponents                                = 4096;
+       builtin->maxVaryingFloats                                                  = 64;
+       builtin->maxVertexTextureImageUnits                                = 32;
+       builtin->maxCombinedTextureImageUnits                      = 80;
+       builtin->maxTextureImageUnits                                      = 32;
+       builtin->maxFragmentUniformComponents                      = 4096;
+       builtin->maxDrawBuffers                                                    = 32;
+       builtin->maxVertexUniformVectors                                   = 128;
+       builtin->maxVaryingVectors                                                 = 8;
+       builtin->maxFragmentUniformVectors                                 = 16;
+       builtin->maxVertexOutputVectors                                    = 16;
+       builtin->maxFragmentInputVectors                                   = 15;
+       builtin->minProgramTexelOffset                                     = -8;
+       builtin->maxProgramTexelOffset                                     = 7;
+       builtin->maxClipDistances                                                  = 8;
+       builtin->maxComputeWorkGroupCountX                                 = 65535;
+       builtin->maxComputeWorkGroupCountY                                 = 65535;
+       builtin->maxComputeWorkGroupCountZ                                 = 65535;
+       builtin->maxComputeWorkGroupSizeX                                  = 1024;
+       builtin->maxComputeWorkGroupSizeY                                  = 1024;
+       builtin->maxComputeWorkGroupSizeZ                                  = 64;
+       builtin->maxComputeUniformComponents                       = 1024;
+       builtin->maxComputeTextureImageUnits                       = 16;
+       builtin->maxComputeImageUniforms                                   = 8;
+       builtin->maxComputeAtomicCounters                                  = 8;
+       builtin->maxComputeAtomicCounterBuffers                    = 1;
+       builtin->maxVaryingComponents                                      = 60;
+       builtin->maxVertexOutputComponents                                 = 64;
+       builtin->maxGeometryInputComponents                                = 64;
+       builtin->maxGeometryOutputComponents                       = 128;
+       builtin->maxFragmentInputComponents                                = 128;
+       builtin->maxImageUnits                                                     = 8;
+       builtin->maxCombinedImageUnitsAndFragmentOutputs   = 8;
+       builtin->maxCombinedShaderOutputResources                  = 8;
+       builtin->maxImageSamples                                                   = 0;
+       builtin->maxVertexImageUniforms                                    = 0;
+       builtin->maxTessControlImageUniforms                       = 0;
+       builtin->maxTessEvaluationImageUniforms                    = 0;
+       builtin->maxGeometryImageUniforms                                  = 0;
+       builtin->maxFragmentImageUniforms                                  = 8;
+       builtin->maxCombinedImageUniforms                                  = 8;
+       builtin->maxGeometryTextureImageUnits                      = 16;
+       builtin->maxGeometryOutputVertices                                 = 256;
+       builtin->maxGeometryTotalOutputComponents                  = 1024;
+       builtin->maxGeometryUniformComponents                      = 1024;
+       builtin->maxGeometryVaryingComponents                      = 64;
+       builtin->maxTessControlInputComponents                     = 128;
+       builtin->maxTessControlOutputComponents                    = 128;
+       builtin->maxTessControlTextureImageUnits                   = 16;
+       builtin->maxTessControlUniformComponents                   = 1024;
+       builtin->maxTessControlTotalOutputComponents       = 4096;
+       builtin->maxTessEvaluationInputComponents                  = 128;
+       builtin->maxTessEvaluationOutputComponents                 = 128;
+       builtin->maxTessEvaluationTextureImageUnits                = 16;
+       builtin->maxTessEvaluationUniformComponents                = 1024;
+       builtin->maxTessPatchComponents                                    = 120;
+       builtin->maxPatchVertices                                                  = 32;
+       builtin->maxTessGenLevel                                                   = 64;
+       builtin->maxViewports                                                      = 16;
+       builtin->maxVertexAtomicCounters                                   = 0;
+       builtin->maxTessControlAtomicCounters                      = 0;
+       builtin->maxTessEvaluationAtomicCounters                   = 0;
+       builtin->maxGeometryAtomicCounters                                 = 0;
+       builtin->maxFragmentAtomicCounters                                 = 8;
+       builtin->maxCombinedAtomicCounters                                 = 8;
+       builtin->maxAtomicCounterBindings                                  = 1;
+       builtin->maxVertexAtomicCounterBuffers                     = 0;
+       builtin->maxTessControlAtomicCounterBuffers                = 0;
+       builtin->maxTessEvaluationAtomicCounterBuffers   = 0;
+       builtin->maxGeometryAtomicCounterBuffers                   = 0;
+       builtin->maxFragmentAtomicCounterBuffers                   = 1;
+       builtin->maxCombinedAtomicCounterBuffers                   = 1;
+       builtin->maxAtomicCounterBufferSize                                = 16384;
+       builtin->maxTransformFeedbackBuffers                       = 4;
+       builtin->maxTransformFeedbackInterleavedComponents = 64;
+       builtin->maxCullDistances                                                  = 8;
+       builtin->maxCombinedClipAndCullDistances                   = 8;
+       builtin->maxSamples                                                                = 4;
+};
+
+bool compileGlslToSpirV(tcu::TestLog& log, std::string source, glu::ShaderType type, ShaderBinaryDataType* dst)
+{
+       TBuiltInResource builtinRes;
+
+       prepareGlslang();
+       getDefaultBuiltInResources(&builtinRes);
+
+       const EShLanguage shaderStage = getGlslangStage(type);
+
+       glslang::TShader  shader(shaderStage);
+       glslang::TProgram program;
+
+       const char* src[] = { source.c_str() };
+
+       shader.setStrings(src, 1);
+       program.addShader(&shader);
+
+       const int compileRes = shader.parse(&builtinRes, 100, false, EShMsgSpvRules);
+       if (compileRes != 0)
+       {
+               const int linkRes = program.link(EShMsgSpvRules);
+
+               if (linkRes != 0)
+               {
+                       const glslang::TIntermediate* const intermediate = program.getIntermediate(shaderStage);
+                       glslang::GlslangToSpv(*intermediate, *dst);
+
+                       return true;
+               }
+               else
+               {
+                       log << tcu::TestLog::Message << "Program linking error:\n"
+                               << program.getInfoLog() << "\n"
+                               << "Source:\n"
+                               << source << "\n"
+                               << tcu::TestLog::EndMessage;
+               }
+       }
+       else
+       {
+               log << tcu::TestLog::Message << "Shader compilation error:\n"
+                       << shader.getInfoLog() << "\n"
+                       << "Source:\n"
+                       << source << "\n"
+                       << tcu::TestLog::EndMessage;
+       }
+
+       return false;
+}
+
+#else // DEQP_HAVE_GLSLANG
+
+bool compileGlslToSpirV(tcu::TestLog& log, std::string source, glu::ShaderType type, ShaderBinaryDataType* dst)
+{
+       DE_UNREF(log);
+       DE_UNREF(source);
+       DE_UNREF(type);
+       DE_UNREF(dst);
+
+       TCU_THROW(InternalError, "Glslang not available.");
+
+       return false;
+}
+
+#endif // DEQP_HAVE_GLSLANG
+
+#if defined DEQP_HAVE_SPIRV_TOOLS
+
+void spirvAssemble(ShaderBinaryDataType& dst, const std::string& src)
+{
+       spvtools::SpirvTools core(SPV_ENV_OPENGL_4_5);
+
+       auto print_msg_to_stderr = [](spv_message_level_t, const char*, const spv_position_t&, const char* m) {
+               std::cerr << "error: " << m << std::endl;
+       };
+
+       core.SetMessageConsumer(print_msg_to_stderr);
+
+       if (!core.Assemble(src, &dst))
+               TCU_THROW(InternalError, "Failed to assemble Spir-V source.");
+       if (!core.Validate(dst))
+               TCU_THROW(InternalError, "Failed to validate Spir-V module.");
+}
+
+void spirvDisassemble(std::string& dst, const ShaderBinaryDataType& src)
+{
+       spvtools::SpirvTools core(SPV_ENV_OPENGL_4_5);
+
+       auto print_msg_to_stderr = [](spv_message_level_t, const char*, const spv_position_t&, const char* m) {
+               std::cerr << "error: " << m << std::endl;
+       };
+
+       core.SetMessageConsumer(print_msg_to_stderr);
+
+       if (!core.Disassemble(src, &dst))
+               TCU_THROW(InternalError, "Failed to disassemble Spir-V module.");
+}
+
+#else //DEQP_HAVE_SPIRV_TOOLS
+
+void spirvAssemble(ShaderBinaryDataType& dst, const std::string& src)
+{
+       DE_UNREF(dst);
+       DE_UNREF(src);
+
+       TCU_THROW(InternalError, "Spirv-tools not available.");
+}
+
+void spirvDisassemble(std::string& dst, ShaderBinaryDataType& src)
+{
+       DE_UNREF(dst);
+       DE_UNREF(src);
+
+       TCU_THROW(InternalError, "Glslang not available.");
+}
+
+#endif // DEQP_HAVE_SPIRV_TOOLS
+
+ShaderBinary makeSpirV(tcu::TestLog& log, ShaderSource source)
+{
+       ShaderBinary binary;
+
+       if (!glslangUtils::compileGlslToSpirV(log, source.source, source.shaderType, &binary.binary))
+               TCU_THROW(InternalError, "Failed to convert GLSL to Spir-V");
+
+       binary << source.shaderType << "main";
+
+       return binary;
+}
+
+/** Verifying if GLSL to SpirV mapping was performed correctly
+ *
+ * @param glslSource       GLSL shader template
+ * @param spirVSource      SpirV disassembled source
+ * @param mappings         Glsl to SpirV mappings vector
+ * @param anyOf            any occurence indicator
+ *
+ * @return true if GLSL code occurs as many times as all of SpirV code for each mapping if anyOf is false
+ *         or true if SpirV code occurs at least once if GLSL code found, false otherwise.
+ **/
+bool verifyMappings(std::string glslSource, std::string spirVSource, SpirVMapping& mappings, bool anyOf)
+{
+       std::vector<std::string> spirVSourceLines = de::splitString(spirVSource, '\n');
+
+       // Iterate through all glsl functions
+       for (SpirVMapping::iterator it = mappings.begin(); it != mappings.end(); it++)
+       {
+               int glslCodeCount  = 0;
+               int spirVCodeCount = 0;
+
+               // To avoid finding functions with similar names (ie. "cos", "acos", "cosh")
+               // add characteristic characters that delimits finding results
+               std::string glslCode = it->first;
+
+               // Count GLSL code occurrences in GLSL source
+               size_t codePosition = glslSource.find(glslCode);
+               while (codePosition != std::string::npos)
+               {
+                       glslCodeCount++;
+                       codePosition = glslSource.find(glslCode, codePosition + 1);
+               }
+
+               if (glslCodeCount > 0)
+               {
+                       // Count all SpirV code variants occurrences in SpirV source
+                       for (int s = 0; s < it->second.size(); ++s)
+                       {
+                               std::vector<std::string> spirVCodes = de::splitString(it->second[s], ' ');
+
+                               for (int v = 0; v < spirVSourceLines.size(); ++v)
+                               {
+                                       std::vector<std::string> spirVLineCodes = de::splitString(spirVSourceLines[v], ' ');
+
+                                       bool matchAll = true;
+                                       for (int j = 0; j < spirVCodes.size(); ++j)
+                                       {
+                                               bool match = false;
+                                               for (int i = 0; i < spirVLineCodes.size(); ++i)
+                                               {
+                                                       if (spirVLineCodes[i] == spirVCodes[j])
+                                                               match = true;
+                                               }
+
+                                               matchAll = matchAll && match;
+                                       }
+
+                                       if (matchAll)
+                                               spirVCodeCount++;
+                               }
+                       }
+
+                       // Check if both counts match
+                       if (anyOf && (glslCodeCount > 0 && spirVCodeCount == 0))
+                               return false;
+                       else if (!anyOf && glslCodeCount != spirVCodeCount)
+                               return false;
+               }
+       }
+
+       return true;
+}
+
+} // namespace glslangUtils
+
+namespace commonUtils
+{
+
+void writeSpirV(const char* filename, ShaderBinary binary)
+{
+       FILE* file = fopen(filename, "wb");
+       if (file)
+       {
+               // As one binary could be associated with many shader objects it should be stored either a type of each shader
+               // This will be extended in the future
+               deUint8 count = (deUint8)binary.shaderTypes.size();
+               fwrite((void*)&count, 1, 1, file);
+               for (int i = 0; i < binary.shaderTypes.size(); ++i)
+               {
+                       fwrite((void*)&binary.shaderTypes[i], 1, sizeof(ShaderType), file);
+
+                       if (count > 1)
+                       {
+                               deUint8 strLen = (deUint8)binary.shaderEntryPoints[i].size();
+                               fwrite((void*)&strLen, 1, 1, file);
+                               fwrite((void*)binary.shaderEntryPoints[i].data(), 1, strLen, file);
+                       }
+               }
+
+               fwrite((void*)binary.binary.data(), 1, binary.binary.size() * 4, file);
+               fclose(file);
+       }
+}
+
+ShaderBinary readSpirV(tcu::Resource* resource)
+{
+       ShaderBinary binary;
+       if (!resource)
+               return binary;
+
+       // As one binary could be associated with many shader objects it should be stored either a type of each shader
+       deUint8 count;
+       resource->read(&count, 1);
+       binary.shaderTypes.resize(count);
+       binary.shaderEntryPoints.resize(count);
+       for (int i = 0; i < binary.shaderTypes.size(); ++i)
+       {
+               resource->read((deUint8*)&binary.shaderTypes[i], sizeof(ShaderType));
+
+               if (count > 1)
+               {
+                       deUint8 strLen;
+                       resource->read(&strLen, 1);
+
+                       binary.shaderEntryPoints[i].resize(strLen);
+                       resource->read((deUint8*)binary.shaderEntryPoints[i].data(), strLen);
+               }
+               else
+                       binary.shaderEntryPoints[i] = "main";
+       }
+
+       binary.binary.resize((resource->getSize() - resource->getPosition()) / sizeof(deUint32));
+       resource->read((deUint8*)binary.binary.data(), binary.binary.size() * sizeof(deUint32));
+
+       return binary;
+}
+
+/** Replace all occurance of <token> with <text> in <string>
+ *
+ * @param token           Token string
+ * @param text            String th at will be used as replacement for <token>
+ * @param string          String to work on
+ **/
+void replaceToken(const GLchar* token, const GLchar* text, std::string& string)
+{
+       const size_t text_length  = strlen(text);
+       const size_t token_length = strlen(token);
+
+       size_t token_position;
+       while ((token_position = string.find(token, 0)) != std::string::npos)
+       {
+               string.replace(token_position, token_length, text, text_length);
+       }
+}
+
+bool compareUintColors(const GLuint inColor, const GLuint refColor, const int epsilon)
+{
+       int r1 = (inColor & 0xFF);
+       int g1 = ((inColor >> 8) & 0xFF);
+       int b1 = ((inColor >> 16) & 0xFF);
+       int a1 = ((inColor >> 24) & 0xFF);
+
+       int r2 = (refColor & 0xFF);
+       int g2 = ((refColor >> 8) & 0xFF);
+       int b2 = ((refColor >> 16) & 0xFF);
+       int a2 = ((refColor >> 24) & 0xFF);
+
+       if (r1 >= r2 - epsilon && r1 <= r2 + epsilon && g1 >= g2 - epsilon && g1 <= g2 + epsilon && b1 >= b2 - epsilon &&
+               b1 <= b2 + epsilon)
+       {
+               return true;
+       }
+
+       return false;
+}
+
+} // namespace commonUtils
+
+/** Constructor.
+ *
+ *  @param context     Rendering context
+ *  @param name        Test name
+ *  @param description Test description
+ */
+SpirvModulesPositiveTest::SpirvModulesPositiveTest(deqp::Context& context)
+       : TestCase(context, "spirv_modules_positive_test",
+                          "Test verifies if using SPIR-V modules for each shader stage works as expected")
+{
+       /* Left blank intentionally */
+}
+
+/** Stub init method */
+void SpirvModulesPositiveTest::init()
+{
+       if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gl_spirv"))
+               TCU_THROW(NotSupportedError, "GL_ARB_gl_spirv is not supported");
+
+       m_vertex = "#version 450\n"
+                          "\n"
+                          "layout (location = 0) in vec3 position;\n"
+                          "\n"
+                          "layout (location = 1) out vec4 vColor;\n"
+                          "\n"
+                          "void main()\n"
+                          "{\n"
+                          "    gl_Position = vec4(position, 1.0);\n"
+                          "    vColor = vec4(0.0, 0.0, 0.0, 1.0);\n"
+                          "}\n";
+
+       m_tesselationCtrl = "#version 450\n"
+                                               "\n"
+                                               "layout (vertices = 3) out;\n"
+                                               "\n"
+                                               "layout (location = 1) in vec4 vColor[];\n"
+                                               "layout (location = 2) out vec4 tcColor[];\n"
+                                               "\n"
+                                               "void main()\n"
+                                               "{\n"
+                                               "    tcColor[gl_InvocationID] = vColor[gl_InvocationID];\n"
+                                               "    tcColor[gl_InvocationID].r = 1.0;\n"
+                                               "\n"
+                                               "    if (gl_InvocationID == 0) {\n"
+                                               "        gl_TessLevelOuter[0] = 1.0;\n"
+                                               "        gl_TessLevelOuter[1] = 1.0;\n"
+                                               "        gl_TessLevelOuter[2] = 1.0;\n"
+                                               "        gl_TessLevelInner[0] = 1.0;\n"
+                                               "    }\n"
+                                               "\n"
+                                               "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
+                                               "}\n";
+
+       m_tesselationEval = "#version 450\n"
+                                               "\n"
+                                               "layout (triangles) in;\n"
+                                               "\n"
+                                               "layout (location = 2) in vec4 tcColor[];\n"
+                                               "layout (location = 3) out vec4 teColor;\n"
+                                               "\n"
+                                               "void main()\n"
+                                               "{\n"
+                                               "    teColor = tcColor[0];\n"
+                                               "    teColor.g = 1.0;\n"
+                                               "\n"
+                                               "    gl_Position = gl_TessCoord.x * gl_in[0].gl_Position +\n"
+                                               "                  gl_TessCoord.y * gl_in[1].gl_Position +\n"
+                                               "                  gl_TessCoord.z * gl_in[2].gl_Position;\n"
+                                               "}\n";
+
+       m_geometry = "#version 450\n"
+                                "\n"
+                                "layout (triangles) in;\n"
+                                "layout (triangle_strip, max_vertices = 3) out;\n"
+                                "\n"
+                                "layout (location = 3) in vec4 teColor[];\n"
+                                "layout (location = 4) out vec4 gColor;\n"
+                                "\n"
+                                "void main()\n"
+                                "{\n"
+                                "    gColor = teColor[0];\n"
+                                "    gColor.b = 1.0;\n"
+                                "\n"
+                                "    for (int i = 0; i < 3; ++i) {\n"
+                                "        gl_Position = gl_in[i].gl_Position;\n"
+                                "        EmitVertex();\n"
+                                "    }\n"
+                                "    EndPrimitive();\n"
+                                "}\n";
+
+       m_fragment = "#version 450\n"
+                                "\n"
+                                "layout (location = 4) in vec4 gColor;\n"
+                                "layout (location = 0) out vec4 fColor;\n"
+                                "\n"
+                                "void main()\n"
+                                "{\n"
+                                "    fColor = gColor;\n"
+                                "}\n";
+
+       const Functions& gl = m_context.getRenderContext().getFunctions();
+
+       gl.genTextures(1, &m_texture);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "genTextures");
+       gl.bindTexture(GL_TEXTURE_2D, m_texture);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "bindTexture");
+       gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 32, 32);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "texStorage2D");
+
+       gl.genFramebuffers(1, &m_fbo);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "genFramenuffers");
+       gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "bindFramebuffer");
+       gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture, 0);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "framebufferTexture2D");
+
+       gl.viewport(0, 0, 32, 32);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "viewport");
+}
+
+/** Stub de-init method */
+void SpirvModulesPositiveTest::deinit()
+{
+       const Functions& gl = m_context.getRenderContext().getFunctions();
+
+       if (m_fbo)
+       {
+               gl.deleteFramebuffers(1, &m_fbo);
+               GLU_EXPECT_NO_ERROR(gl.getError(), "deleteFramebuffers");
+       }
+       if (m_texture)
+       {
+               gl.deleteTextures(1, &m_texture);
+               GLU_EXPECT_NO_ERROR(gl.getError(), "deleteTextures");
+       }
+}
+
+/** Executes test iteration.
+ *
+ *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
+ */
+tcu::TestNode::IterateResult SpirvModulesPositiveTest::iterate()
+{
+       const Functions& gl = m_context.getRenderContext().getFunctions();
+
+       const GLfloat vertices[] = { -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f };
+
+       GLuint vao;
+       gl.genVertexArrays(1, &vao);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays");
+       gl.bindVertexArray(vao);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray");
+
+       GLuint vbo;
+       gl.genBuffers(1, &vbo);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers");
+       gl.bindBuffer(GL_ARRAY_BUFFER, vbo);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");
+
+       gl.bufferData(GL_ARRAY_BUFFER, 9 * sizeof(GLfloat), (GLvoid*)vertices, GL_DYNAMIC_DRAW);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");
+
+       enum Iterates
+       {
+               ITERATE_GLSL,
+               ITERATE_SPIRV,
+               ITERATE_LAST
+       };
+
+       deUint32 outputs[ITERATE_LAST];
+       for (int it = ITERATE_GLSL; it < ITERATE_LAST; ++it)
+       {
+               ShaderProgram* program = DE_NULL;
+               if (it == ITERATE_GLSL)
+               {
+                       ProgramSources sources;
+                       sources << VertexSource(m_vertex);
+                       sources << TessellationControlSource(m_tesselationCtrl);
+                       sources << TessellationEvaluationSource(m_tesselationEval);
+                       sources << GeometrySource(m_geometry);
+                       sources << FragmentSource(m_fragment);
+                       program = new ShaderProgram(gl, sources);
+               }
+               else if (it == ITERATE_SPIRV)
+               {
+#if defined                                    DEQP_HAVE_GLSLANG
+                       ProgramBinaries binaries;
+                       binaries << glslangUtils::makeSpirV(m_context.getTestContext().getLog(), VertexSource(m_vertex));
+                       binaries << glslangUtils::makeSpirV(m_context.getTestContext().getLog(),
+                                                                                               TessellationControlSource(m_tesselationCtrl));
+                       binaries << glslangUtils::makeSpirV(m_context.getTestContext().getLog(),
+                                                                                               TessellationEvaluationSource(m_tesselationEval));
+                       binaries << glslangUtils::makeSpirV(m_context.getTestContext().getLog(), GeometrySource(m_geometry));
+                       binaries << glslangUtils::makeSpirV(m_context.getTestContext().getLog(), FragmentSource(m_fragment));
+                       program = new ShaderProgram(gl, binaries);
+#else  // DEQP_HAVE_GLSLANG
+                       tcu::Archive&   archive = m_testCtx.getArchive();
+                       ProgramBinaries binaries;
+                       binaries << commonUtils::readSpirV(archive.getResource("spirv/modules_positive/vertex.nspv"));
+                       binaries << commonUtils::readSpirV(archive.getResource("spirv/modules_positive/tess_control.nspv"));
+                       binaries << commonUtils::readSpirV(archive.getResource("spirv/modules_positive/tess_evaluation.nspv"));
+                       binaries << commonUtils::readSpirV(archive.getResource("spirv/modules_positive/geometry.nspv"));
+                       binaries << commonUtils::readSpirV(archive.getResource("spirv/modules_positive/fragment.nspv"));
+                       program           = new ShaderProgram(gl, binaries);
+#endif // DEQP_HAVE_GLSLANG
+               }
+
+               if (!program->isOk())
+               {
+                       m_testCtx.getLog() << tcu::TestLog::Message << "Shader build failed.\n"
+                                                          << "Vertex: " << program->getShaderInfo(SHADERTYPE_VERTEX).infoLog << "\n"
+                                                          << m_vertex << "\n"
+                                                          << "TesselationCtrl: " << program->getShaderInfo(SHADERTYPE_TESSELLATION_CONTROL).infoLog
+                                                          << "\n"
+                                                          << m_tesselationCtrl << "\n"
+                                                          << "TesselationEval: "
+                                                          << program->getShaderInfo(SHADERTYPE_TESSELLATION_EVALUATION).infoLog << "\n"
+                                                          << m_tesselationEval << "\n"
+                                                          << "Geometry: " << program->getShaderInfo(SHADERTYPE_GEOMETRY).infoLog << "\n"
+                                                          << m_geometry << "\n"
+                                                          << "Fragment: " << program->getShaderInfo(SHADERTYPE_FRAGMENT).infoLog << "\n"
+                                                          << m_fragment << "\n"
+                                                          << "Program: " << program->getProgramInfo().infoLog << tcu::TestLog::EndMessage;
+
+                       m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
+                       return STOP;
+               }
+
+               gl.useProgram(program->getProgram());
+               GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
+
+               gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
+               GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor");
+               gl.clear(GL_COLOR_BUFFER_BIT);
+               GLU_EXPECT_NO_ERROR(gl.getError(), "glClear");
+
+               gl.enableVertexAttribArray(0);
+               GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray");
+
+               gl.vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, DE_NULL);
+               GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer");
+
+               gl.patchParameteri(GL_PATCH_VERTICES, 3);
+               gl.drawArrays(GL_PATCHES, 0, 3);
+               GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArray");
+
+               gl.disableVertexAttribArray(0);
+               GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray");
+
+               gl.readPixels(16, 16, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)&outputs[it]);
+               GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");
+
+               if (program)
+                       delete program;
+       }
+
+       if (vbo)
+       {
+               gl.deleteBuffers(1, &vbo);
+               GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteBuffers");
+       }
+
+       if (vao)
+       {
+               gl.deleteVertexArrays(1, &vao);
+               GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteVertexArrays");
+       }
+
+       if ((outputs[ITERATE_GLSL] & outputs[ITERATE_SPIRV]) != 0xFFFFFFFF)
+       {
+               m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
+               m_testCtx.getLog() << tcu::TestLog::Message << "Wrong output color read from framebuffer.\n"
+                                                  << "GLSL: " << outputs[ITERATE_GLSL] << ", SPIR-V: " << outputs[ITERATE_SPIRV]
+                                                  << "Expected: " << (deUint32)0xFFFFFFFF << tcu::TestLog::EndMessage;
+               return STOP;
+       }
+
+       m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
+       return STOP;
+}
+
+/** Constructor.
+ *
+ *  @param context     Rendering context
+ *  @param name        Test name
+ *  @param description Test description
+ */
+SpirvShaderBinaryMultipleShaderObjectsTest::SpirvShaderBinaryMultipleShaderObjectsTest(deqp::Context& context)
+       : TestCase(context, "spirv_modules_shader_binary_multiple_shader_objects_test",
+                          "Test verifies if one binary module can be associated with multiple shader objects.")
+{
+       /* Left blank intentionally */
+}
+
+/** Stub init method */
+void SpirvShaderBinaryMultipleShaderObjectsTest::init()
+{
+       m_spirv = "OpCapability Shader\n"
+                         "%1 = OpExtInstImport \"GLSL.std.450\"\n"
+                         "OpMemoryModel Logical GLSL450\n"
+                         "OpEntryPoint Vertex %mainv \"mainv\" %_ %position %gl_VertexID %gl_InstanceID\n"
+                         "OpEntryPoint Fragment %mainf \"mainf\" %fColor\n"
+                         "OpSource GLSL 450\n"
+                         "OpName %mainv \"mainv\"\n"
+                         "OpName %mainf \"mainf\"\n"
+                         "OpName %gl_PerVertex \"gl_PerVertex\"\n"
+                         "OpMemberName %gl_PerVertex 0 \"gl_Position\"\n"
+                         "OpMemberName %gl_PerVertex 1 \"gl_PointSize\"\n"
+                         "OpMemberName %gl_PerVertex 2 \"gl_ClipDistance\"\n"
+                         "OpMemberName %gl_PerVertex 3 \"gl_CullDistance\"\n"
+                         "OpName %_ \"\"\n"
+                         "OpName %position \"position\"\n"
+                         "OpName %gl_VertexID \"gl_VertexID\"\n"
+                         "OpName %gl_InstanceID \"gl_InstanceID\"\n"
+                         "OpMemberDecorate %gl_PerVertex 0 BuiltIn Position\n"
+                         "OpMemberDecorate %gl_PerVertex 1 BuiltIn PointSize\n"
+                         "OpMemberDecorate %gl_PerVertex 2 BuiltIn ClipDistance\n"
+                         "OpMemberDecorate %gl_PerVertex 3 BuiltIn CullDistance\n"
+                         "OpDecorate %gl_PerVertex Block\n"
+                         "OpDecorate %position Location 0\n"
+                         "OpDecorate %gl_VertexID BuiltIn VertexId\n"
+                         "OpDecorate %gl_InstanceID BuiltIn InstanceId\n"
+                         "OpDecorate %fColor Location 0\n"
+                         "%void = OpTypeVoid\n"
+                         "%3 = OpTypeFunction %void\n"
+                         "%float = OpTypeFloat 32\n"
+                         "%v4float = OpTypeVector %float 4\n"
+                         "%uint = OpTypeInt 32 0\n"
+                         "%uint_1 = OpConstant %uint 1\n"
+                         "%_arr_float_uint_1 = OpTypeArray %float %uint_1\n"
+                         "%gl_PerVertex = OpTypeStruct %v4float %float %_arr_float_uint_1 %_arr_float_uint_1\n"
+                         "%_ptr_Output_gl_PerVertex = OpTypePointer Output %gl_PerVertex\n"
+                         "%_ = OpVariable %_ptr_Output_gl_PerVertex Output\n"
+                         "%int = OpTypeInt 32 1\n"
+                         "%int_0 = OpConstant %int 0\n"
+                         "%v3float = OpTypeVector %float 3\n"
+                         "%_ptr_Input_v3float = OpTypePointer Input %v3float\n"
+                         "%position = OpVariable %_ptr_Input_v3float Input\n"
+                         "%float_1 = OpConstant %float 1\n"
+                         "%_ptr_Output_v4float = OpTypePointer Output %v4float\n"
+                         "%_ptr_Input_int = OpTypePointer Input %int\n"
+                         "%gl_VertexID = OpVariable %_ptr_Input_int Input\n"
+                         "%gl_InstanceID = OpVariable %_ptr_Input_int Input\n"
+                         "%fColor = OpVariable %_ptr_Output_v4float Output\n"
+                         "%fVec4_1 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1\n"
+                         "\n"
+                         "%mainv = OpFunction %void None %3\n"
+                         "%5 = OpLabel\n"
+                         "%19 = OpLoad %v3float %position\n"
+                         "%21 = OpCompositeExtract %float %19 0\n"
+                         "%22 = OpCompositeExtract %float %19 1\n"
+                         "%23 = OpCompositeExtract %float %19 2\n"
+                         "%24 = OpCompositeConstruct %v4float %21 %22 %23 %float_1\n"
+                         "%26 = OpAccessChain %_ptr_Output_v4float %_ %int_0\n"
+                         "OpStore %26 %24\n"
+                         "OpReturn\n"
+                         "OpFunctionEnd\n"
+                         "\n"
+                         "%mainf = OpFunction %void None %3\n"
+                         "%32 = OpLabel\n"
+                         "OpStore %fColor %fVec4_1\n"
+                         "OpReturn\n"
+                         "OpFunctionEnd\n";
+}
+
+/** Stub init method */
+void SpirvShaderBinaryMultipleShaderObjectsTest::deinit()
+{
+}
+
+/** Executes test iteration.
+ *
+ *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
+ */
+tcu::TestNode::IterateResult SpirvShaderBinaryMultipleShaderObjectsTest::iterate()
+{
+       const Functions& gl = m_context.getRenderContext().getFunctions();
+
+       const GLfloat vertices[] = { -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f };
+
+       GLuint texture;
+       GLuint fbo;
+
+       gl.genTextures(1, &texture);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "genTextures");
+       gl.bindTexture(GL_TEXTURE_2D, texture);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "bindTexture");
+       gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 32, 32);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "texStorage2D");
+
+       gl.genFramebuffers(1, &fbo);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "genFramenuffers");
+       gl.bindFramebuffer(GL_FRAMEBUFFER, fbo);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "bindFramebuffer");
+       gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "framebufferTexture2D");
+
+       GLuint vao;
+       gl.genVertexArrays(1, &vao);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays");
+       gl.bindVertexArray(vao);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray");
+
+       GLuint vbo;
+       gl.genBuffers(1, &vbo);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers");
+       gl.bindBuffer(GL_ARRAY_BUFFER, vbo);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");
+
+       gl.bufferData(GL_ARRAY_BUFFER, 9 * sizeof(GLfloat), (GLvoid*)vertices, GL_DYNAMIC_DRAW);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");
+
+#if DEQP_HAVE_SPIRV_TOOLS
+       ShaderBinary binary;
+       binary << SHADERTYPE_VERTEX << "mainv";
+       binary << SHADERTYPE_FRAGMENT << "mainf";
+
+       glslangUtils::spirvAssemble(binary.binary, m_spirv);
+#else  // DEQP_HAVE_SPIRV_TOOLS
+       tcu::Archive& archive = m_testCtx.getArchive();
+       ShaderBinary  binary  = commonUtils::readSpirV(
+               archive.getResource("spirv/spirv_modules_shader_binary_multiple_shader_objects/binary.nspv"));
+#endif // DEQP_HAVE_SPIRV_TOOLS
+
+       ProgramBinaries binaries;
+       binaries << binary;
+       ShaderProgram program(gl, binaries);
+
+       if (!program.isOk())
+       {
+               m_testCtx.getLog() << tcu::TestLog::Message << "Shader build failed.\n"
+                                                  << "Vertex: " << program.getShaderInfo(SHADERTYPE_VERTEX).infoLog << "\n"
+                                                  << "Fragment: " << program.getShaderInfo(SHADERTYPE_FRAGMENT).infoLog << "\n"
+                                                  << "Program: " << program.getProgramInfo().infoLog << tcu::TestLog::EndMessage;
+
+               m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
+               return STOP;
+       }
+
+       gl.viewport(0, 0, 32, 32);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport");
+
+       gl.useProgram(program.getProgram());
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
+
+       gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor");
+       gl.clear(GL_COLOR_BUFFER_BIT);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glClear");
+
+       gl.enableVertexAttribArray(0);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray");
+
+       gl.vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, DE_NULL);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer");
+
+       gl.drawArrays(GL_TRIANGLE_STRIP, 0, 3);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArray");
+
+       gl.disableVertexAttribArray(0);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray");
+
+       GLuint insidePixel;
+       GLuint outsidePixel;
+       gl.readPixels(16, 16, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)&insidePixel);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");
+       gl.readPixels(2, 30, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)&outsidePixel);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");
+
+       if (vbo)
+       {
+               gl.deleteBuffers(1, &vbo);
+               GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteBuffers");
+       }
+
+       if (vao)
+       {
+               gl.deleteVertexArrays(1, &vao);
+               GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteVertexArrays");
+       }
+
+       if (fbo)
+       {
+               gl.deleteFramebuffers(1, &fbo);
+               GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteFramebuffers");
+       }
+
+       if (texture)
+       {
+               gl.deleteTextures(1, &texture);
+               GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures");
+       }
+
+       if (insidePixel == 0xFFFFFFFF && outsidePixel == 0xFF000000)
+               m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
+       else
+       {
+               m_testCtx.getLog() << tcu::TestLog::Message << "Wrong pixels color read.\n"
+                                                  << "Expected (inside/outside): " << 0xFFFFFFFF << "/" << 0xFF000000 << "\n"
+                                                  << "Read: " << insidePixel << "/" << outsidePixel << tcu::TestLog::EndMessage;
+
+               m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
+       }
+
+       return STOP;
+}
+
+/** Constructor.
+ *
+ *  @param context     Rendering context
+ *  @param name        Test name
+ *  @param description Test description
+ */
+SpirvModulesStateQueriesTest::SpirvModulesStateQueriesTest(deqp::Context& context)
+       : TestCase(context, "spirv_modules_state_queries_test",
+                          "Test verifies if state queries for new features added by ARB_gl_spirv works as expected.")
+{
+       /* Left blank intentionally */
+}
+
+/** Stub init method */
+void SpirvModulesStateQueriesTest::init()
+{
+       if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gl_spirv"))
+               TCU_THROW(NotSupportedError, "GL_ARB_gl_spirv is not supported");
+
+       m_vertex = "#version 450\n"
+                          "\n"
+                          "layout (location = 0) in vec4 position;\n"
+                          "layout (location = 20) uniform vec4 extPosition;\n"
+                          "layout (location = 40) uniform ComponentsBlock\n"
+                          "{\n"
+                          "    vec4 c1;\n"
+                          "    vec2 c2;\n"
+                          "} components;\n"
+                          "\n"
+                          "void main()\n"
+                          "{\n"
+                          "    gl_Position = position + extPosition + components.c1 + vec4(components.c2, 0.0, 0.0);\n"
+                          "}\n";
+}
+
+/** Stub de-init method */
+void SpirvModulesStateQueriesTest::deinit()
+{
+}
+
+/** Executes test iteration.
+ *
+ *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
+ */
+tcu::TestNode::IterateResult SpirvModulesStateQueriesTest::iterate()
+{
+       const Functions& gl = m_context.getRenderContext().getFunctions();
+
+       ProgramBinaries binaries;
+       ShaderBinary    vertexBinary;
+
+#if defined DEQP_HAVE_GLSLANG && DEQP_HAVE_SPIRV_TOOLS
+       {
+               vertexBinary = glslangUtils::makeSpirV(m_context.getTestContext().getLog(), VertexSource(m_vertex));
+
+               // Disassemble Spir-V module
+               std::string output;
+               glslangUtils::spirvDisassemble(output, vertexBinary.binary);
+
+               // Remove name reflection for defined variables
+               std::vector<std::string> lines = de::splitString(output, '\n');
+               std::string                              input;
+               for (int i = 0; i < lines.size(); ++i)
+               {
+                       if (lines[i].find("OpName %position") != std::string::npos)
+                               continue;
+                       if (lines[i].find("OpName %extPosition") != std::string::npos)
+                               continue;
+                       if (lines[i].find("OpName %ComponentsBlock") != std::string::npos)
+                               continue;
+                       if (lines[i].find("OpName %components") != std::string::npos)
+                               continue;
+
+                       input.append(lines[i] + "\n");
+               }
+
+               // Assemble Spir-V module
+               vertexBinary.binary.clear();
+               glslangUtils::spirvAssemble(vertexBinary.binary, input);
+       }
+#else  // DEQP_HAVE_GLSLANG && DEQP_HAVE_SPIRV_TOOLS
+       tcu::Archive& archive = m_testCtx.getArchive();
+       vertexBinary              = commonUtils::readSpirV(archive.getResource("spirv/modules_state_queries/vertex.nspv"));
+#endif // DEQP_HAVE_GLSLANG && DEQP_HAVE_SPIRV_TOOLS
+
+       binaries << vertexBinary;
+       ShaderProgram program(gl, binaries);
+
+       Shader* shader = program.getShader(SHADERTYPE_VERTEX);
+
+       // 1) Check compile status
+       if (!program.getShaderInfo(SHADERTYPE_VERTEX).compileOk)
+       {
+               m_testCtx.getLog() << tcu::TestLog::Message << "Check compile status failed.\n"
+                                                  << "Vertex: " << program.getShaderInfo(SHADERTYPE_VERTEX).infoLog << "\n"
+                                                  << m_vertex << "\n"
+                                                  << "Program: " << program.getProgramInfo().infoLog << tcu::TestLog::EndMessage;
+
+               m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
+               return STOP;
+       }
+
+       // 2) Check if SPIR_V_BINARY_ARB state is TRUE
+       GLint shaderState;
+       gl.getShaderiv(shader->getShader(), GL_SPIR_V_BINARY_ARB, &shaderState);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "getShaderiv");
+       if (shaderState != GL_TRUE)
+       {
+               m_testCtx.getLog() << tcu::TestLog::Message << "SPIR_V_BINARY_ARB state set to FALSE. Expected TRUE."
+                                                  << tcu::TestLog::EndMessage;
+
+               m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
+               return STOP;
+       }
+
+       // 3) Check if queries for ACTIVE_ATTRIBUTE_MAX_LENGTH, ACTIVE_UNIFORM_MAX_LENGTH, TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH,
+       //    ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH return value equal to 1.
+       GLint programState[4];
+       gl.getProgramiv(program.getProgram(), GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &programState[0]);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "getProgramiv");
+
+       gl.getProgramiv(program.getProgram(), GL_ACTIVE_UNIFORM_MAX_LENGTH, &programState[1]);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "getProgramiv");
+
+       gl.getProgramiv(program.getProgram(), GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, &programState[2]);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "getProgramiv");
+
+       gl.getProgramiv(program.getProgram(), GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &programState[3]);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "getProgramiv");
+
+       bool programStateResult = true;
+       for (int i = 0; i < 4; ++i)
+       {
+               if (programState[i] != 1)
+               {
+                       m_testCtx.getLog() << tcu::TestLog::Message << "Check max name length [" << i << "] failed. "
+                                                          << "Expected: 1, Queried: " << programState[i] << "\n"
+                                                          << tcu::TestLog::EndMessage;
+                       programStateResult = false;
+               }
+       }
+
+       if (!programStateResult)
+       {
+               m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
+               return STOP;
+       }
+
+       // 4) Check if ShaderSource command usage on Spir-V binary shader will change SPIR_V_BINARY_ARB state to FALSE
+       const char* source = m_vertex.c_str();
+       const int   length = m_vertex.length();
+       gl.shaderSource(shader->getShader(), 1, &source, &length);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "shaderSource");
+
+       gl.getShaderiv(shader->getShader(), GL_SPIR_V_BINARY_ARB, &shaderState);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "getShaderiv");
+       if (shaderState != GL_FALSE)
+       {
+               m_testCtx.getLog() << tcu::TestLog::Message << "SPIR_V_BINARY_ARB state set to TRUE. Expected FALSE."
+                                                  << tcu::TestLog::EndMessage;
+
+               m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
+               return STOP;
+       }
+
+       m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
+       return STOP;
+}
+
+/** Constructor.
+ *
+ *  @param context     Rendering context
+ *  @param name        Test name
+ *  @param description Test description
+ */
+SpirvModulesErrorVerificationTest::SpirvModulesErrorVerificationTest(deqp::Context& context)
+       : TestCase(context, "spirv_modules_error_verification_test",
+                          "Test verifies if new features added by ARB_gl_spirv generate error messages as expected.")
+{
+       /* Left blank intentionally */
+}
+
+/** Stub init method */
+void SpirvModulesErrorVerificationTest::init()
+{
+       if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gl_spirv"))
+               TCU_THROW(NotSupportedError, "GL_ARB_gl_spirv is not supported");
+
+       const Functions& gl = m_context.getRenderContext().getFunctions();
+
+       m_vertex = "#version 450\n"
+                          "\n"
+                          "layout (location = 0) in vec4 position;\n"
+                          "\n"
+                          "void main()\n"
+                          "{\n"
+                          "    gl_Position = position;\n"
+                          "}\n";
+
+       m_glslShaderId = gl.createShader(GL_VERTEX_SHADER);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "createShader");
+
+       m_spirvShaderId = gl.createShader(GL_VERTEX_SHADER);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "createShader");
+
+       m_programId = gl.createProgram();
+       GLU_EXPECT_NO_ERROR(gl.getError(), "createProgram");
+
+       gl.genTextures(1, &m_textureId);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "genTextures");
+}
+
+/** Stub de-init method */
+void SpirvModulesErrorVerificationTest::deinit()
+{
+       const Functions& gl = m_context.getRenderContext().getFunctions();
+
+       gl.deleteTextures(1, &m_textureId);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "deleteTextures");
+
+       gl.deleteProgram(m_programId);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "deleteProgram");
+
+       gl.deleteShader(m_glslShaderId);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "deleteShader");
+
+       gl.deleteShader(m_spirvShaderId);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "deleteShader");
+}
+
+/** Executes test iteration.
+ *
+ *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
+ */
+tcu::TestNode::IterateResult SpirvModulesErrorVerificationTest::iterate()
+{
+       const Functions& gl = m_context.getRenderContext().getFunctions();
+
+       const char* shaderSrc = m_vertex.c_str();
+       const int   shaderLen = m_vertex.length();
+
+       ShaderBinary vertexBinary;
+
+#if defined DEQP_HAVE_GLSLANG
+       vertexBinary = glslangUtils::makeSpirV(m_context.getTestContext().getLog(), VertexSource(m_vertex));
+#else  // DEQP_HAVE_GLSLANG
+       tcu::Archive& archive = m_testCtx.getArchive();
+       vertexBinary              = commonUtils::readSpirV(archive.getResource("spirv/modules_error_verification/vertex.nspv"));
+#endif // DEQP_HAVE_GLSLANG
+
+       gl.shaderSource(m_glslShaderId, 1, &shaderSrc, &shaderLen);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "shaderSource");
+
+       gl.shaderBinary(1, &m_spirvShaderId, GL_SHADER_BINARY_FORMAT_SPIR_V_ARB, (GLvoid*)vertexBinary.binary.data(),
+                                       vertexBinary.binary.size() * sizeof(deUint32));
+       GLU_EXPECT_NO_ERROR(gl.getError(), "shaderBinary");
+
+       gl.attachShader(m_programId, m_spirvShaderId);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "attachShader");
+
+       GLint err;
+
+       // 1) Verify if CompileShader function used on shader with SPIR_V_BINARY_ARB state
+       //    will result in generating INVALID_OPERATION error.
+       gl.compileShader(m_spirvShaderId);
+       err = gl.getError();
+       if (err != GL_INVALID_OPERATION)
+       {
+               m_testCtx.getLog()
+                       << tcu::TestLog::Message
+                       << "Unexpected error code generated by CompileShader [1]. Expected INVALID_OPERATION, generated: "
+                       << glu::getErrorName(err) << tcu::TestLog::EndMessage;
+
+               m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
+               return STOP;
+       }
+
+       // 2) Verify if SpecializeShader function generate INVALID_VALUE error when
+       //    <shader> is not the name of either a program or shader object.
+       gl.specializeShader(0xFFFF, "main", 0, DE_NULL, DE_NULL);
+       err = gl.getError();
+       if (err != GL_INVALID_VALUE)
+       {
+               m_testCtx.getLog()
+                       << tcu::TestLog::Message
+                       << "Unexpected error code generated by SpecializeShader [2]. Expected INVALID_VALUE, generated: "
+                       << glu::getErrorName(err) << tcu::TestLog::EndMessage;
+
+               m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
+               return STOP;
+       }
+
+       // 3) Verify if SpecializeShader function generate INVALID_OPERATION error when
+       //    <shader> is the name of a program object.
+       gl.specializeShader(m_programId, "main", 0, DE_NULL, DE_NULL);
+       err = gl.getError();
+       if (err != GL_INVALID_OPERATION)
+       {
+               m_testCtx.getLog()
+                       << tcu::TestLog::Message
+                       << "Unexpected error code generated by SpecializeShader [3]. Expected INVALID_OPERATION, generated: "
+                       << glu::getErrorName(err) << tcu::TestLog::EndMessage;
+
+               m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
+               return STOP;
+       }
+
+       // 4) Verify if SpecializeShader function generate INVALID_OPERATION error when
+       //    SPIR_V_BINARY_ARB state for <shader> is not TRUE.
+       gl.specializeShader(m_glslShaderId, "main", 0, DE_NULL, DE_NULL);
+       err = gl.getError();
+       if (err != GL_INVALID_OPERATION)
+       {
+               m_testCtx.getLog()
+                       << tcu::TestLog::Message
+                       << "Unexpected error code generated by SpecializeShader [4]. Expected INVALID_OPERATION, generated: "
+                       << glu::getErrorName(err) << tcu::TestLog::EndMessage;
+
+               m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
+               return STOP;
+       }
+
+       // 5) Verify if SpecializeShader function generate INVALID_VALUE when <pEntryPoint>
+       //    does not name a valid entry point for <shader>.
+       gl.specializeShader(m_spirvShaderId, "entry", 0, DE_NULL, DE_NULL);
+       err = gl.getError();
+       if (err != GL_INVALID_VALUE)
+       {
+               m_testCtx.getLog()
+                       << tcu::TestLog::Message
+                       << "Unexpected error code generated by SpecializeShader [5]. Expected INVALID_VALUE, generated: "
+                       << glu::getErrorName(err) << tcu::TestLog::EndMessage;
+
+               m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
+               return STOP;
+       }
+
+       // 6) Verify if SpecializeShader function generate INVALID_VALUE when any element
+       //    of <pConstantIndex> refers to a specialization constant that does not exist
+       //    in the shader module contained in <shader>.
+       const GLuint specID     = 10;
+       const GLuint specValue = 10;
+       gl.specializeShader(m_spirvShaderId, "main", 1, &specID, &specValue);
+       err = gl.getError();
+       if (err != GL_INVALID_VALUE)
+       {
+               m_testCtx.getLog()
+                       << tcu::TestLog::Message
+                       << "Unexpected error code generated by SpecializeShader [6]. Expected INVALID_VALUE, generated: "
+                       << glu::getErrorName(err) << tcu::TestLog::EndMessage;
+
+               m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
+               return STOP;
+       }
+
+       // 7) Verify if LinkProgram fail when one or more of the shader objects attached to
+       //    <program> are not specialized.
+       gl.linkProgram(m_programId);
+       err = gl.getError();
+       if (err == GL_NO_ERROR)
+       {
+               GLint linkStatus;
+               gl.getProgramiv(m_programId, GL_LINK_STATUS, &linkStatus);
+               GLU_EXPECT_NO_ERROR(gl.getError(), "getProgramiv");
+
+               if (linkStatus != 0)
+               {
+                       m_testCtx.getLog() << tcu::TestLog::Message << "Unexpected result of LinkProgram [7]."
+                                                          << tcu::TestLog::EndMessage;
+
+                       m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
+                       return STOP;
+               }
+       }
+
+       // 8) Verify if SpecializeShader function generate INVALID_OPERATION error if the
+       //    shader has already been specialized.
+       gl.specializeShader(m_spirvShaderId, "main", 0, DE_NULL, DE_NULL);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "specializeShader");
+
+       gl.specializeShader(m_spirvShaderId, "main", 0, DE_NULL, DE_NULL);
+       err = gl.getError();
+       if (err != GL_INVALID_OPERATION)
+       {
+               m_testCtx.getLog()
+                       << tcu::TestLog::Message
+                       << "Unexpected error code generated by SpecializeShader [8]. Expected INVALID_OPERATION, generated: "
+                       << glu::getErrorName(err) << tcu::TestLog::EndMessage;
+
+               m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
+               return STOP;
+       }
+
+       // 9) Verify if LinkProgram fail when not all of shaders attached to <program> have
+       //    the same value for the SPIR_V_BINARY_ARB state.
+       gl.compileShader(m_glslShaderId);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "compileShader");
+
+       gl.attachShader(m_programId, m_glslShaderId);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "attachShader");
+
+       gl.linkProgram(m_programId);
+       err = gl.getError();
+       if (err == GL_NO_ERROR)
+       {
+               GLint linkStatus;
+               gl.getProgramiv(m_programId, GL_LINK_STATUS, &linkStatus);
+               GLU_EXPECT_NO_ERROR(gl.getError(), "getProgramiv");
+
+               if (linkStatus != 0)
+               {
+                       m_testCtx.getLog() << tcu::TestLog::Message << "Unexpected result of LinkProgram [9]."
+                                                          << tcu::TestLog::EndMessage;
+
+                       m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
+                       return STOP;
+               }
+       }
+
+       m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
+       return STOP;
+}
+
+/** Constructor.
+ *
+ *  @param context     Rendering context
+ *  @param name        Test name
+ *  @param description Test description
+ */
+SpirvGlslToSpirVEnableTest::SpirvGlslToSpirVEnableTest(deqp::Context& context)
+       : TestCase(context, "spirv_glsl_to_spirv_enable_test", "Test verifies if glsl supports Spir-V features.")
+{
+       /* Left blank intentionally */
+}
+
+/** Stub init method */
+void SpirvGlslToSpirVEnableTest::init()
+{
+       if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gl_spirv"))
+               TCU_THROW(NotSupportedError, "GL_ARB_gl_spirv is not supported");
+
+       m_vertex = "#version 450\n"
+                          "\n"
+                          "#ifdef GL_SPIRV\n"
+                          "  layout (location = 0) in vec4 enabled;\n"
+                          "#else\n"
+                          "  layout (location = 0) in vec4 notEnabled;\n"
+                          "#endif // GL_SPIRV\n"
+                          "\n"
+                          "void main()\n"
+                          "{\n"
+                          "    gl_Position = vec4(0.0, 0.0, 0.0, 0.0);\n"
+                          "}\n";
+}
+
+/** Stub de-init method */
+void SpirvGlslToSpirVEnableTest::deinit()
+{
+}
+
+/** Executes test iteration.
+ *
+ *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
+ */
+tcu::TestNode::IterateResult SpirvGlslToSpirVEnableTest::iterate()
+{
+
+#if defined DEQP_HAVE_GLSLANG && DEQP_HAVE_SPIRV_TOOLS
+       {
+               const Functions& gl = m_context.getRenderContext().getFunctions();
+
+               ProgramBinaries binaries;
+               ShaderBinary    vertexBinary =
+                       glslangUtils::makeSpirV(m_context.getTestContext().getLog(), VertexSource(m_vertex));
+               binaries << vertexBinary;
+               ShaderProgram spirvProgram(gl, binaries);
+
+               std::string spirvSource;
+               glslangUtils::spirvDisassemble(spirvSource, vertexBinary.binary);
+
+               if (spirvSource.find("OpName %enabled") == std::string::npos)
+               {
+                       m_testCtx.getLog() << tcu::TestLog::Message << "GL_SPIRV not defined. Spir-V source:\n"
+                                                          << spirvSource.c_str() << tcu::TestLog::EndMessage;
+
+                       m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
+                       return STOP;
+               }
+
+               if (!spirvProgram.isOk())
+               {
+                       m_testCtx.getLog() << tcu::TestLog::Message << "Shader compilation failed. Source:\n"
+                                                          << spirvSource.c_str() << "InfoLog:\n"
+                                                          << spirvProgram.getShaderInfo(SHADERTYPE_VERTEX).infoLog << "\n"
+                                                          << tcu::TestLog::EndMessage;
+
+                       m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
+                       return STOP;
+               }
+
+               m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
+       }
+#else // DEQP_HAVE_GLSLANG && DEQP_HAVE_SPIRV_TOOLS
+
+       TCU_THROW(InternalError, "Either glslang or spirv-tools not available.");
+
+#endif // DEQP_HAVE_GLSLANG && DEQP_HAVE_SPIRV_TOOLS
+
+       return STOP;
+}
+
+enum EShaderTemplate
+{
+       COMPUTE_TEMPLATE,
+       TESSCTRL_TEMPLATE,
+       GEOMETRY_TEMPLATE,
+       FRAGMENT_TEMPLATE
+};
+
+struct FunctionMapping
+{
+       EShaderTemplate shaderTemplate;
+       std::string             glslFunc;
+       std::string             glslArgs;
+       std::string             spirVFunc;
+
+       FunctionMapping() : shaderTemplate(COMPUTE_TEMPLATE), glslFunc(""), glslArgs(""), spirVFunc("")
+       {
+       }
+
+       FunctionMapping(EShaderTemplate shaderTemplate_, std::string glslFunc_, std::string glslArgs_,
+                                       std::string spirVFunc_)
+               : shaderTemplate(shaderTemplate_), glslFunc(glslFunc_), glslArgs(glslArgs_), spirVFunc(spirVFunc_)
+       {
+       }
+};
+
+/** Constructor.
+ *
+ *  @param context     Rendering context
+ *  @param name        Test name
+ *  @param description Test description
+ */
+SpirvGlslToSpirVBuiltInFunctionsTest::SpirvGlslToSpirVBuiltInFunctionsTest(deqp::Context& context)
+       : TestCase(context, "spirv_glsl_to_spirv_builtin_functions_test",
+                          "Test verifies if GLSL built-in functions are supported by Spir-V.")
+{
+       /* Left blank intentionally */
+}
+
+/** Stub init method */
+void SpirvGlslToSpirVBuiltInFunctionsTest::init()
+{
+       if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gl_spirv"))
+               TCU_THROW(NotSupportedError, "GL_ARB_gl_spirv is not supported");
+
+       initMappings();
+
+       m_commonVertex = "#version 450\n"
+                                        "\n"
+                                        "layout (location = 0) in vec3 position;\n"
+                                        "layout (location = 1) out vec2 texCoord;\n"
+                                        "\n"
+                                        "void main()\n"
+                                        "{\n"
+                                        "    texCoord = vec2(0.0, 0.0);\n"
+                                        "    gl_Position = vec4(position, 1.0);\n"
+                                        "}\n";
+
+       m_commonTessEval = "#version 450\n"
+                                          "\n"
+                                          "layout (triangles) in;\n"
+                                          "\n"
+                                          "void main()\n"
+                                          "{\n"
+                                          "    gl_Position = gl_TessCoord.x * gl_in[0].gl_Position +\n"
+                                          "                  gl_TessCoord.y * gl_in[1].gl_Position +\n"
+                                          "                  gl_TessCoord.z * gl_in[2].gl_Position;\n"
+                                          "}\n";
+
+       m_sources.clear();
+
+       // Angle Trigonometry
+       m_sources.push_back(ComputeSource("#version 450\n"
+                                                                         "\n"
+                                                                         "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
+                                                                         "\n"
+                                                                         "void main()\n"
+                                                                         "{\n"
+                                                                         "    float tmp0 = 0.5;\n"
+                                                                         "    float value;\n"
+                                                                         "    value = radians(tmp0) +\n"
+                                                                         "            degrees(tmp0) +\n"
+                                                                         "            sin(tmp0) +\n"
+                                                                         "            cos(tmp0) +\n"
+                                                                         "            tan(tmp0) +\n"
+                                                                         "            asin(tmp0) +\n"
+                                                                         "            acos(tmp0) +\n"
+                                                                         "            atan(tmp0) +\n"
+                                                                         "            atan(tmp0) +\n"
+                                                                         "            sinh(tmp0) +\n"
+                                                                         "            cosh(tmp0) +\n"
+                                                                         "            tanh(tmp0) +\n"
+                                                                         "            asinh(tmp0) +\n"
+                                                                         "            acosh(tmp0) +\n"
+                                                                         "            atanh(tmp0);\n"
+                                                                         "}\n"));
+
+       // To avoid duplicated mappings create additional shaders for specific functions
+       const std::string strAnlgeVariants = "#version 450\n"
+                                                                                "\n"
+                                                                                "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
+                                                                                "\n"
+                                                                                "void main()\n"
+                                                                                "{\n"
+                                                                                "    float tmp0 = 0.5;\n"
+                                                                                "    float value = <ATANGENT>;\n"
+                                                                                "}\n";
+       std::string strATan  = strAnlgeVariants;
+       std::string strATan2 = strAnlgeVariants;
+       commonUtils::replaceToken("<ATANGENT>", "atan(tmp0, tmp0)", strATan);
+       commonUtils::replaceToken("<ATANGENT>", "atan(tmp0)", strATan2);
+
+       m_sources.push_back(ComputeSource(strATan));
+       m_sources.push_back(ComputeSource(strATan2));
+
+       // Exponential
+       m_sources.push_back(ComputeSource("#version 450\n"
+                                                                         "\n"
+                                                                         "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
+                                                                         "\n"
+                                                                         "void main()\n"
+                                                                         "{\n"
+                                                                         "    float tmp0;\n"
+                                                                         "    float tmp1;\n"
+                                                                         "    float value;\n"
+                                                                         "    value = pow(tmp1, tmp0) +\n"
+                                                                         "            exp(tmp0) +\n"
+                                                                         "            log(tmp1) +\n"
+                                                                         "            exp2(tmp0) +\n"
+                                                                         "            log2(tmp1) +\n"
+                                                                         "            sqrt(tmp1) +\n"
+                                                                         "            inversesqrt(tmp1);\n"
+                                                                         "}\n"));
+
+       // Common (without bit operations)
+       m_sources.push_back(ComputeSource("#version 450\n"
+                                                                         "\n"
+                                                                         "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
+                                                                         "\n"
+                                                                         "void main()\n"
+                                                                         "{\n"
+                                                                         "    float value;\n"
+                                                                         "    float outval;\n"
+                                                                         "    float fpval = 0.5;\n"
+                                                                         "    float fnval = -0.5;\n"
+                                                                         "    int ival = 0x43800000;\n"
+                                                                         "    uint uival= 0xC3800000;\n"
+                                                                         "    value = abs(fnval) +\n"
+                                                                         "            sign(fpval) +\n"
+                                                                         "            floor(fpval) +\n"
+                                                                         "            trunc(fpval) +\n"
+                                                                         "            round(fpval) +\n"
+                                                                         "            roundEven(fpval) +\n"
+                                                                         "            ceil(fpval) +\n"
+                                                                         "            fract(fpval) +\n"
+                                                                         "            mod(fpval, 2.0) +\n"
+                                                                         "            modf(fpval, outval) +\n"
+                                                                         "            min(fpval, 0.2) +\n"
+                                                                         "            max(fpval, 0.2) +\n"
+                                                                         "            clamp(fpval, 0.8, 2.0) +\n"
+                                                                         "            mix(fnval, fpval, 0.5) +\n"
+                                                                         "            step(1.0, fpval) +\n"
+                                                                         "            smoothstep(0.0, 1.0, fpval) +\n"
+                                                                         "            float( isnan(fpval)) +\n"
+                                                                         "            float( isinf(fpval)) +\n"
+                                                                         "            fma(fpval, 1.0, fnval) +\n"
+                                                                         "            frexp(4.0, ival) +\n"
+                                                                         "            ldexp(4.0, ival);\n"
+                                                                         "}\n"));
+
+       // To avoid duplicated mappings create additional shaders for specific functions
+       const std::string strBitsOpsVariants = "#version 450\n"
+                                                                                  "\n"
+                                                                                  "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
+                                                                                  "\n"
+                                                                                  "void main()\n"
+                                                                                  "{\n"
+                                                                                  "    float value;\n"
+                                                                                  "    int ival = 0x43800000;\n"
+                                                                                  "    uint uval = 0x43800000;\n"
+                                                                                  "    value = <BITS_TO_FLOAT>;\n"
+                                                                                  "}\n";
+       std::string strIntBits  = strBitsOpsVariants;
+       std::string strUIntBits = strBitsOpsVariants;
+       commonUtils::replaceToken("<BITS_TO_FLOAT>", "intBitsToFloat(ival)", strIntBits);
+       commonUtils::replaceToken("<BITS_TO_FLOAT>", "uintBitsToFloat(uval)", strUIntBits);
+
+       m_sources.push_back(ComputeSource(strIntBits));
+       m_sources.push_back(ComputeSource(strUIntBits));
+
+       // Float Pack Unpack
+       m_sources.push_back(ComputeSource("#version 450\n"
+                                                                         "\n"
+                                                                         "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
+                                                                         "\n"
+                                                                         "void main()\n"
+                                                                         "{\n"
+                                                                         "    vec2 v2val = vec2(0.1, 0.2);\n"
+                                                                         "    vec4 v4val = vec4(0.1, 0.2, 0.3, 0.4);\n"
+                                                                         "    uint uival1 = packUnorm2x16(v2val);\n"
+                                                                         "    uint uival2 = packSnorm2x16(v2val);\n"
+                                                                         "    uint uival3 = packUnorm4x8(v4val);\n"
+                                                                         "    uint uival4 = packSnorm4x8(v4val);\n"
+                                                                         "    v2val = unpackUnorm2x16(uival1);\n"
+                                                                         "    v2val = unpackSnorm2x16(uival2);\n"
+                                                                         "    v4val = unpackUnorm4x8(uival3);\n"
+                                                                         "    v4val = unpackSnorm4x8(uival4);\n"
+                                                                         "    uvec2 uv2val = uvec2(10, 20);\n"
+                                                                         "    double dval = packDouble2x32(uv2val);\n"
+                                                                         "    uv2val = unpackDouble2x32(dval);\n"
+                                                                         "    uint uival5 = packHalf2x16(v2val);\n"
+                                                                         "    v2val = unpackHalf2x16(uival5);\n"
+                                                                         "}\n"));
+
+       // Geometric
+       m_sources.push_back(ComputeSource("#version 450\n"
+                                                                         "\n"
+                                                                         "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
+                                                                         "\n"
+                                                                         "void main()\n"
+                                                                         "{\n"
+                                                                         "    vec3 v3val1 = vec3(0.1, 0.5, 1.0);\n"
+                                                                         "    vec3 v3val2 = vec3(0.5, 0.3, 0.9);\n"
+                                                                         "    vec3 v3val3 = vec3(1.0, 0.0, 0.0);\n"
+                                                                         "    float fval = length(v3val1) +\n"
+                                                                         "                 distance(v3val1, v3val2) +\n"
+                                                                         "                 dot(v3val1, v3val2);\n"
+                                                                         "    vec3 crossp = cross(v3val1, v3val2);\n"
+                                                                         "    vec3 norm = normalize(crossp);\n"
+                                                                         "    vec3 facef = faceforward(v3val1, v3val2, v3val3);\n"
+                                                                         "    vec3 refl = reflect(v3val1, v3val2);\n"
+                                                                         "    float eta = 0.1;\n"
+                                                                         "    vec3 refr = refract(v3val1, v3val2, eta);"
+                                                                         "}\n"));
+
+       // Matrix
+       m_sources.push_back(ComputeSource("#version 450\n"
+                                                                         "\n"
+                                                                         "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
+                                                                         "\n"
+                                                                         "void main()\n"
+                                                                         "{\n"
+                                                                         "    mat2 m2val1 = mat2(\n"
+                                                                         "        0.1, 0.5,\n"
+                                                                         "        0.2, 0.4\n"
+                                                                         "    );\n"
+                                                                         "    mat2 m2val2 = mat2(\n"
+                                                                         "        0.8, 0.2,\n"
+                                                                         "        0.9, 0.1\n"
+                                                                         "    );\n"
+                                                                         "    vec2 v2val1 = vec2(0.3, 0.4);\n"
+                                                                         "    vec2 v2val2 = vec2(0.5, 0.6);\n"
+                                                                         "\n"
+                                                                         "    mat2 m2comp = matrixCompMult(m2val1, m2val2);\n"
+                                                                         "    mat2 m2outerp = outerProduct(v2val1, v2val2);\n"
+                                                                         "    mat2 m2trans = transpose(m2val1);\n"
+                                                                         "    float fdet = determinant(m2val2);\n"
+                                                                         "    mat2 m2inv = inverse(m2trans);\n"
+                                                                         "}\n"));
+
+       // Vector Relational
+       m_sources.push_back(ComputeSource("#version 450\n"
+                                                                         "\n"
+                                                                         "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
+                                                                         "\n"
+                                                                         "void main()\n"
+                                                                         "{\n"
+                                                                         "    vec2 v2val1 = vec2(0.5, 0.2);\n"
+                                                                         "    vec2 v2val2 = vec2(0.1, 0.8);\n"
+                                                                         "    bvec2 bv2val1 = lessThan(v2val1, v2val2);\n"
+                                                                         "    bvec2 bv2val2 = lessThanEqual(v2val1, v2val2);\n"
+                                                                         "    bvec2 bv2val3 = greaterThan(v2val1, v2val2);\n"
+                                                                         "    bvec2 bv2val4 = greaterThanEqual(v2val1, v2val2);\n"
+                                                                         "    bvec2 bv2val5 = equal(v2val1, v2val2);\n"
+                                                                         "    bvec2 bv2val6 = notEqual(v2val1, v2val2);\n"
+                                                                         "    bool bval1 = any(bv2val1);\n"
+                                                                         "    bool bval2 = all(bv2val1);\n"
+                                                                         "    bvec2 bv2val7 = not(bv2val1);\n"
+                                                                         "}\n"));
+
+       // Integer
+       m_sources.push_back(ComputeSource("#version 450\n"
+                                                                         "\n"
+                                                                         "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
+                                                                         "\n"
+                                                                         "void main()\n"
+                                                                         "{\n"
+                                                                         "    int ival = 0;\n"
+                                                                         "    uint uival = 200;\n"
+                                                                         "    uint uivalRet1;\n"
+                                                                         "    uint uivalRet2;\n"
+                                                                         "    uivalRet2 = uaddCarry(uival, 0xFFFFFFFF, uivalRet1);\n"
+                                                                         "    uivalRet2 = usubBorrow(uival, 0xFFFFFFFF, uivalRet1);\n"
+                                                                         "    umulExtended(uival, 0xFFFFFFFF, uivalRet1, uivalRet2);\n"
+                                                                         "    uivalRet1 = bitfieldExtract(uival, 3, 8);\n"
+                                                                         "    uivalRet1 = bitfieldInsert(uival, 0xFFFFFFFF, 3, 8);\n"
+                                                                         "    uivalRet1 = bitfieldReverse(uival);\n"
+                                                                         "    ival = bitCount(uival);\n"
+                                                                         "    ival = findLSB(uival);\n"
+                                                                         "    ival = findMSB(uival);\n"
+                                                                         "}\n"));
+
+       // Texture
+       m_sources.push_back(
+               FragmentSource("#version 450\n"
+                                          "\n"
+                                          "layout (location = 0) out vec4 fragColor;\n"
+                                          "\n"
+                                          "layout (location = 1) uniform sampler2D tex2D;\n"
+                                          "layout (location = 2) uniform sampler2DMS tex2DMS;\n"
+                                          "\n"
+                                          "void main()\n"
+                                          "{\n"
+                                          "    ivec2 iv2size = textureSize(tex2D, 0);\n"
+                                          "    vec2 v2lod = textureQueryLod(tex2D, vec2(0.0));\n"
+                                          "    int ilev = textureQueryLevels(tex2D);\n"
+                                          "    int isamp = textureSamples(tex2DMS);\n"
+                                          "    vec4 v4pix = textureLod(tex2D, vec2(0.0), 0.0) +\n"
+                                          "                 textureOffset(tex2D, vec2(0.0), ivec2(2)) +\n"
+                                          "                 texelFetch(tex2D, ivec2(2), 0) +\n"
+                                          "                 texelFetchOffset(tex2D, ivec2(2), 0, ivec2(2)) +\n"
+                                          "                 textureProjOffset(tex2D, vec3(0.0), ivec2(2)) +\n"
+                                          "                 textureLodOffset(tex2D, vec2(0.0), 0.0, ivec2(2)) +\n"
+                                          "                 textureProjLod(tex2D, vec3(0.0), 0.0) +\n"
+                                          "                 textureProjLodOffset(tex2D, vec3(0.0), 0.0, ivec2(2)) +\n"
+                                          "                 textureGrad(tex2D, vec2(0.0), vec2(0.2), vec2(0.5)) +\n"
+                                          "                 textureGradOffset(tex2D, vec2(0.0), vec2(0.2), vec2(0.5), ivec2(2)) +\n"
+                                          "                 textureProjGrad(tex2D, vec3(0.0), vec2(0.2), vec2(0.5)) +\n"
+                                          "                 textureProjGradOffset(tex2D, vec3(0.0), vec2(0.2), vec2(0.5), ivec2(2)) +\n"
+                                          "                 textureGatherOffset(tex2D, vec2(0.0), ivec2(2), 0);\n"
+                                          "    fragColor = vec4(0.0);\n"
+                                          "}\n"));
+
+       // To avoid duplicated mappings create additional shaders for specific functions
+       const std::string strTextureVariants = "#version 450\n"
+                                                                                  "\n"
+                                                                                  "layout (location = 0) out vec4 fragColor;\n"
+                                                                                  "\n"
+                                                                                  "layout (location = 1) uniform sampler2D tex2D;\n"
+                                                                                  "\n"
+                                                                                  "void main()\n"
+                                                                                  "{\n"
+                                                                                  "    fragColor = <TEXTURE>;\n"
+                                                                                  "}\n";
+       std::string strTexture           = strTextureVariants;
+       std::string strTextureProj   = strTextureVariants;
+       std::string strTextureGather = strTextureVariants;
+       commonUtils::replaceToken("<TEXTURE>", "texture(tex2D, vec2(0.0))", strTexture);
+       commonUtils::replaceToken("<TEXTURE>", "textureProj(tex2D, vec3(0.0))", strTextureProj);
+       commonUtils::replaceToken("<TEXTURE>", "textureGather(tex2D, vec2(0.0), 0)", strTextureGather);
+
+       m_sources.push_back(FragmentSource(strTexture));
+       m_sources.push_back(FragmentSource(strTextureProj));
+       m_sources.push_back(FragmentSource(strTextureGather));
+
+       // Atomic Counter
+       m_sources.push_back(ComputeSource("#version 450\n"
+                                                                         "\n"
+                                                                         "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
+                                                                         "\n"
+                                                                         "layout (binding = 0) uniform atomic_uint auival;\n"
+                                                                         "\n"
+                                                                         "void main()\n"
+                                                                         "{\n"
+                                                                         "    uint uival = atomicCounterIncrement(auival) +\n"
+                                                                         "                 atomicCounterDecrement(auival) +\n"
+                                                                         "                 atomicCounter(auival);\n"
+                                                                         "}\n"));
+
+       // Atomic Memory
+       m_sources.push_back(ComputeSource("#version 450\n"
+                                                                         "\n"
+                                                                         "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
+                                                                         "\n"
+                                                                         "shared uint uishared;\n"
+                                                                         "\n"
+                                                                         "void main()\n"
+                                                                         "{\n"
+                                                                         "    uint uival2 = 5;\n"
+                                                                         "    uint uivalRet = atomicAdd(uishared, uival2) +\n"
+                                                                         "                    atomicMin(uishared, uival2) +\n"
+                                                                         "                    atomicMax(uishared, uival2) +\n"
+                                                                         "                    atomicAnd(uishared, uival2) +\n"
+                                                                         "                    atomicOr(uishared, uival2) +\n"
+                                                                         "                    atomicXor(uishared, uival2) +\n"
+                                                                         "                    atomicExchange(uishared, uival2) +\n"
+                                                                         "                    atomicCompSwap(uishared, uishared, uival2);\n"
+                                                                         "}\n"));
+
+       // Image
+       m_sources.push_back(ComputeSource("#version 450\n"
+                                                                         "\n"
+                                                                         "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
+                                                                         "\n"
+                                                                         "layout (location = 1, rgba8ui) uniform readonly uimage2D rimg2D;\n"
+                                                                         "layout (location = 2, rgba8ui) uniform readonly uimage2DMS rimg2DMS;\n"
+                                                                         "layout (location = 3, rgba8ui) uniform writeonly uimage2D wimg2D;\n"
+                                                                         "layout (location = 4, r32ui) uniform uimage2D aimg2D;\n"
+                                                                         "\n"
+                                                                         "void main()\n"
+                                                                         "{\n"
+                                                                         "    ivec2 size = imageSize(rimg2D);\n"
+                                                                         "    int samp = imageSamples(rimg2DMS);\n"
+                                                                         "    uvec4 v4pix = imageLoad(rimg2D, ivec2(0));\n"
+                                                                         "    imageStore(wimg2D, ivec2(0), uvec4(255));\n"
+                                                                         "    uint uivalRet = imageAtomicAdd(aimg2D, ivec2(0), 1) +\n"
+                                                                         "                    imageAtomicMin(aimg2D, ivec2(0), 1) +\n"
+                                                                         "                    imageAtomicMax(aimg2D, ivec2(0), 1) +\n"
+                                                                         "                    imageAtomicAnd(aimg2D, ivec2(0), 1) +\n"
+                                                                         "                    imageAtomicOr(aimg2D, ivec2(0), 1) +\n"
+                                                                         "                    imageAtomicXor(aimg2D, ivec2(0), 1) +\n"
+                                                                         "                    imageAtomicExchange(aimg2D, ivec2(0), 1) +\n"
+                                                                         "                    imageAtomicCompSwap(aimg2D, ivec2(0), 1, 2);\n"
+                                                                         "}\n"));
+
+       // Fragment Processing
+       m_sources.push_back(FragmentSource("#version 450\n"
+                                                                          "\n"
+                                                                          "layout (location = 0) out vec4 fragColor;\n"
+                                                                          "layout (location = 1) in vec2 texCoord;\n"
+                                                                          "\n"
+                                                                          "void main()\n"
+                                                                          "{\n"
+                                                                          "    vec2 p = vec2(0.0);\n"
+                                                                          "    vec2 dx = dFdx(p);\n"
+                                                                          "    vec2 dy = dFdy(p);\n"
+                                                                          "    dx = dFdxFine(p);\n"
+                                                                          "    dy = dFdyFine(p);\n"
+                                                                          "    dx = dFdxCoarse(p);\n"
+                                                                          "    dy = dFdyCoarse(p);\n"
+                                                                          "    vec2 fw = fwidth(p);\n"
+                                                                          "    fw = fwidthFine(p);\n"
+                                                                          "    fw = fwidthCoarse(p);\n"
+                                                                          "    vec2 interp = interpolateAtCentroid(texCoord) +\n"
+                                                                          "                  interpolateAtSample(texCoord, 0) +\n"
+                                                                          "                  interpolateAtOffset(texCoord, vec2(0.0));\n"
+                                                                          "    fragColor = vec4(1.0);\n"
+                                                                          "}\n"));
+
+       // To avoid duplicated mappings create additional shaders for specific functions
+       const std::string strEmitVariants = "#version 450\n"
+                                                                               "\n"
+                                                                               "layout (points) in;\n"
+                                                                               "layout (points, max_vertices = 3) out;\n"
+                                                                               "\n"
+                                                                               "void main()\n"
+                                                                               "{\n"
+                                                                               "    gl_Position = vec4(0.0);\n"
+                                                                               "    <EMIT>;\n"
+                                                                               "    <END>;\n"
+                                                                               "}\n";
+       std::string strEmit               = strEmitVariants;
+       std::string strEmitStream = strEmitVariants;
+       commonUtils::replaceToken("<EMIT>", "EmitVertex()", strEmit);
+       commonUtils::replaceToken("<EMIT>", "EmitStreamVertex(0)", strEmitStream);
+       commonUtils::replaceToken("<END>", "EndPrimitive()", strEmit);
+       commonUtils::replaceToken("<END>", "EndStreamPrimitive(0)", strEmitStream);
+
+       m_sources.push_back(GeometrySource(strEmit));
+       m_sources.push_back(GeometrySource(strEmitStream));
+
+       // Shader Invocation Control
+       m_sources.push_back(
+               TessellationControlSource("#version 450\n"
+                                                                 "\n"
+                                                                 "layout (vertices = 3) out;\n"
+                                                                 "\n"
+                                                                 "void main()\n"
+                                                                 "{\n"
+                                                                 "    barrier();\n"
+                                                                 "\n"
+                                                                 "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
+                                                                 "}\n"));
+
+       // Shared Memory Control
+       // To avoid duplicated mappings create additional shaders for specific functions
+       const std::string strMemoryBarrierSource = "#version 450\n"
+                                                                                          "\n"
+                                                                                          "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
+                                                                                          "\n"
+                                                                                          "void main()\n"
+                                                                                          "{\n"
+                                                                                          "    <MEMORY_BARRIER>;\n"
+                                                                                          "}\n";
+       std::string strMemoryBarrier                      = strMemoryBarrierSource;
+       std::string strMemoryBarrierAtomicCounter = strMemoryBarrierSource;
+       std::string strMemoryBarrierBuffer                = strMemoryBarrierSource;
+       std::string strMemoryBarrierShared                = strMemoryBarrierSource;
+       std::string strMemoryBarrierImage                 = strMemoryBarrierSource;
+       std::string strGroupMemoryBarrier                 = strMemoryBarrierSource;
+       commonUtils::replaceToken("<MEMORY_BARRIER>", "memoryBarrier()", strMemoryBarrier);
+       commonUtils::replaceToken("<MEMORY_BARRIER>", "memoryBarrierAtomicCounter()", strMemoryBarrierAtomicCounter);
+       commonUtils::replaceToken("<MEMORY_BARRIER>", "memoryBarrierBuffer()", strMemoryBarrierBuffer);
+       commonUtils::replaceToken("<MEMORY_BARRIER>", "memoryBarrierShared()", strMemoryBarrierShared);
+       commonUtils::replaceToken("<MEMORY_BARRIER>", "memoryBarrierImage()", strMemoryBarrierImage);
+       commonUtils::replaceToken("<MEMORY_BARRIER>", "groupMemoryBarrier()", strGroupMemoryBarrier);
+
+       m_sources.push_back(ComputeSource(strMemoryBarrier));
+       m_sources.push_back(ComputeSource(strMemoryBarrierAtomicCounter));
+       m_sources.push_back(ComputeSource(strMemoryBarrierBuffer));
+       m_sources.push_back(ComputeSource(strMemoryBarrierShared));
+       m_sources.push_back(ComputeSource(strMemoryBarrierImage));
+       m_sources.push_back(ComputeSource(strGroupMemoryBarrier));
+}
+
+/** Stub de-init method */
+void SpirvGlslToSpirVBuiltInFunctionsTest::deinit()
+{
+}
+
+/** Executes test iteration.
+ *
+ *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
+ */
+tcu::TestNode::IterateResult SpirvGlslToSpirVBuiltInFunctionsTest::iterate()
+{
+       const Functions& gl = m_context.getRenderContext().getFunctions();
+
+       for (int i = 0; i < m_sources.size(); ++i)
+       {
+               ShaderSource shaderSource = m_sources[i];
+
+               ProgramSources  sources;
+               ProgramBinaries binaries;
+
+               if (shaderSource.shaderType != glu::SHADERTYPE_COMPUTE)
+               {
+                       ShaderSource vertexSource(glu::SHADERTYPE_VERTEX, m_commonVertex);
+
+                       sources << vertexSource;
+                       ShaderBinary vertexBinary;
+#if defined                             DEQP_HAVE_GLSLANG
+                       vertexBinary = glslangUtils::makeSpirV(m_context.getTestContext().getLog(), vertexSource);
+#else  // DEQP_HAVE_GLSLANG
+                       tcu::Archive& archive = m_testCtx.getArchive();
+                       vertexBinary =
+                               commonUtils::readSpirV(archive.getResource("spirv/glsl_to_spirv_builtin_functions/common_vertex.nspv"));
+#endif //DEQP_HAVE_GLSLANG
+                       binaries << vertexBinary;
+               }
+
+               sources << shaderSource;
+               ShaderBinary shaderBinary;
+               std::string  spirvSource;
+
+#if defined DEQP_HAVE_GLSLANG
+               shaderBinary = glslangUtils::makeSpirV(m_context.getTestContext().getLog(), shaderSource);
+#else  // DEQP_HAVE_GLSLANG
+               {
+                       std::stringstream ss;
+                       ss << "spirv/glsl_to_spirv_builtin_functions/binary_" << i << ".nspv";
+
+                       tcu::Archive& archive = m_testCtx.getArchive();
+                       shaderBinary              = commonUtils::readSpirV(archive.getResource(ss.str().c_str()));
+               }
+#endif // DEQP_HAVE_GLSLANG
+
+#if defined DEQP_HAVE_SPIRV_TOOLS
+               {
+                       glslangUtils::spirvDisassemble(spirvSource, shaderBinary.binary);
+
+                       if (!glslangUtils::verifyMappings(shaderSource.source, spirvSource, m_mappings, false))
+                       {
+                               m_testCtx.getLog() << tcu::TestLog::Message << "Mappings for shader failed.\n"
+                                                                  << "GLSL source:\n"
+                                                                  << shaderSource.source.c_str() << "\n"
+                                                                  << "SpirV source:\n"
+                                                                  << spirvSource.c_str() << tcu::TestLog::EndMessage;
+
+                               TCU_THROW(InternalError, "Mappings for shader failed.");
+                       }
+               }
+#else  // DEQP_HAVE_SPIRV_TOOLS
+               spirvSource                               = "Could not disassemble Spir-V module. SPIRV-TOOLS not available.";
+#endif // DEQP_HAVE_SPIRV_TOOLS
+
+               binaries << shaderBinary;
+
+               if (shaderSource.shaderType == glu::SHADERTYPE_TESSELLATION_CONTROL)
+               {
+                       ShaderSource tessEvalSource(glu::SHADERTYPE_TESSELLATION_EVALUATION, m_commonTessEval);
+
+                       sources << tessEvalSource;
+                       ShaderBinary tessEvalBinary;
+#if defined                             DEQP_HAVE_GLSLANG
+                       tessEvalBinary = glslangUtils::makeSpirV(m_context.getTestContext().getLog(), tessEvalSource);
+#else  // DEQP_HAVE_GLSLANG
+                       tcu::Archive& archive = m_testCtx.getArchive();
+                       tessEvalBinary            = commonUtils::readSpirV(
+                               archive.getResource("spirv/glsl_to_spirv_builtin_functions/common_tesseval.nspv"));
+#endif // DEQP_HAVE_GLSLANG
+                       binaries << tessEvalBinary;
+               }
+
+               ShaderProgram glslProgram(gl, sources);
+               if (!glslProgram.isOk())
+               {
+                       m_testCtx.getLog() << tcu::TestLog::Message << "GLSL shader compilation failed. Source:\n"
+                                                          << shaderSource.source.c_str() << "InfoLog:\n"
+                                                          << glslProgram.getShaderInfo(shaderSource.shaderType).infoLog << "\n"
+                                                          << tcu::TestLog::EndMessage;
+
+                       m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
+                       return STOP;
+               }
+
+               ShaderProgram spirvProgram(gl, binaries);
+               if (!spirvProgram.isOk())
+               {
+                       m_testCtx.getLog() << tcu::TestLog::Message << "SpirV shader compilation failed. Source:\n"
+                                                          << spirvSource.c_str() << "InfoLog:\n"
+                                                          << spirvProgram.getShaderInfo(shaderSource.shaderType).infoLog << "\n"
+                                                          << tcu::TestLog::EndMessage;
+
+                       m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
+                       return STOP;
+               }
+       }
+
+       m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
+       return STOP;
+}
+
+/** Mappings init method */
+void SpirvGlslToSpirVBuiltInFunctionsTest::initMappings()
+{
+       m_mappings.clear();
+       m_mappings["radians"].push_back("OpExtInst Radians");
+       m_mappings["degrees"].push_back("OpExtInst Degrees");
+       m_mappings["sin"].push_back("OpExtInst Sin");
+       m_mappings["cos"].push_back("OpExtInst Cos");
+       m_mappings["tan"].push_back("OpExtInst Tan");
+       m_mappings["asin"].push_back("OpExtInst Asin");
+       m_mappings["acos"].push_back("OpExtInst Acos");
+       m_mappings["atan"].push_back("OpExtInst Atan2");
+       m_mappings["atan"].push_back("OpExtInst Atan");
+       m_mappings["sinh"].push_back("OpExtInst Sinh");
+       m_mappings["cosh"].push_back("OpExtInst Cosh");
+       m_mappings["tanh"].push_back("OpExtInst Tanh");
+       m_mappings["asinh"].push_back("OpExtInst Asinh");
+       m_mappings["acosh"].push_back("OpExtInst Acosh");
+       m_mappings["atanh"].push_back("OpExtInst Atanh");
+       m_mappings["pow"].push_back("OpExtInst Pow");
+       m_mappings["exp"].push_back("OpExtInst Exp");
+       m_mappings["log"].push_back("OpExtInst Log");
+       m_mappings["exp2"].push_back("OpExtInst Exp2");
+       m_mappings["log2"].push_back("OpExtInst Log2");
+       m_mappings["sqrt"].push_back("OpExtInst Sqrt");
+       m_mappings["inversesqrt"].push_back("OpExtInst InverseSqrt");
+       m_mappings["abs"].push_back("OpExtInst FAbs");
+       m_mappings["sign"].push_back("OpExtInst FSign");
+       m_mappings["floor"].push_back("OpExtInst Floor");
+       m_mappings["trunc"].push_back("OpExtInst Trunc");
+       m_mappings["round"].push_back("OpExtInst Round");
+       m_mappings["roundEven"].push_back("OpExtInst RoundEven");
+       m_mappings["ceil"].push_back("OpExtInst Ceil");
+       m_mappings["fract"].push_back("OpExtInst Fract");
+       m_mappings["mod"].push_back("OpFMod");
+       m_mappings["modf"].push_back("OpExtInst Modf");
+       m_mappings["min"].push_back("OpExtInst FMin");
+       m_mappings["max"].push_back("OpExtInst FMax");
+       m_mappings["clamp"].push_back("OpExtInst FClamp");
+       m_mappings["mix"].push_back("OpExtInst FMix");
+       m_mappings["step"].push_back("OpExtInst Step");
+       m_mappings["smoothstep"].push_back("OpExtInst SmoothStep");
+       m_mappings["intBitsToFloat"].push_back("OpBitcast");
+       m_mappings["uintBitsToFloat"].push_back("OpBitcast");
+       m_mappings["isnan"].push_back("OpIsNan");
+       m_mappings["isinf"].push_back("OpIsInf");
+       m_mappings["fma"].push_back("OpExtInst Fma");
+       m_mappings["frexp"].push_back("OpExtInst FrexpStruct");
+       m_mappings["ldexp"].push_back("OpExtInst Ldexp");
+       m_mappings["packUnorm2x16"].push_back("OpExtInst PackUnorm2x16");
+       m_mappings["packSnorm2x16"].push_back("OpExtInst PackSnorm2x16");
+       m_mappings["packUnorm4x8"].push_back("OpExtInst PackUnorm4x8");
+       m_mappings["packSnorm4x8"].push_back("OpExtInst PackSnorm4x8");
+       m_mappings["unpackUnorm2x16"].push_back("OpExtInst UnpackUnorm2x16");
+       m_mappings["unpackSnorm2x16"].push_back("OpExtInst UnpackSnorm2x16");
+       m_mappings["unpackUnorm4x8"].push_back("OpExtInst UnpackUnorm4x8");
+       m_mappings["unpackSnorm4x8"].push_back("OpExtInst UnpackSnorm4x8");
+       m_mappings["packDouble2x32"].push_back("OpExtInst PackDouble2x32");
+       m_mappings["unpackDouble2x32"].push_back("OpExtInst UnpackDouble2x32");
+       m_mappings["packHalf2x16"].push_back("OpExtInst PackHalf2x16");
+       m_mappings["unpackHalf2x16"].push_back("OpExtInst UnpackHalf2x16");
+       m_mappings["length"].push_back("OpExtInst Length");
+       m_mappings["distance"].push_back("OpExtInst Distance");
+       m_mappings["dot"].push_back("OpDot");
+       m_mappings["cross"].push_back("OpExtInst Cross");
+       m_mappings["normalize"].push_back("OpExtInst Normalize");
+       m_mappings["faceforward"].push_back("OpExtInst FaceForward");
+       m_mappings["reflect"].push_back("OpExtInst Reflect");
+       m_mappings["refract"].push_back("OpExtInst Refract");
+       // This one could not be mapped as Spir-V equivalent need more steps
+       // m_mappings["matrixCompMult"].push_back("");
+       m_mappings["outerProduct"].push_back("OpOuterProduct");
+       m_mappings["transpose"].push_back("OpTranspose");
+       m_mappings["determinant"].push_back("OpExtInst Determinant");
+       m_mappings["inverse"].push_back("OpExtInst MatrixInverse");
+       m_mappings["lessThan"].push_back("OpFOrdLessThan");
+       m_mappings["lessThanEqual"].push_back("OpFOrdLessThanEqual");
+       m_mappings["greaterThan"].push_back("OpFOrdGreaterThan");
+       m_mappings["greaterThanEqual"].push_back("OpFOrdGreaterThanEqual");
+       m_mappings["equal"].push_back("OpFOrdEqual");
+       m_mappings["notEqual"].push_back("OpFOrdNotEqual");
+       m_mappings["any"].push_back("OpAny");
+       m_mappings["all"].push_back("OpAll");
+       m_mappings["not"].push_back("OpLogicalNot");
+       m_mappings["uaddCarry"].push_back("OpIAddCarry");
+       m_mappings["usubBorrow"].push_back("OpISubBorrow");
+       m_mappings["umulExtended"].push_back("OpUMulExtended");
+       m_mappings["bitfieldExtract"].push_back("OpBitFieldUExtract");
+       m_mappings["bitfieldInsert"].push_back("OpBitFieldInsert");
+       m_mappings["bitfieldReverse"].push_back("OpBitReverse");
+       m_mappings["bitCount"].push_back("OpBitCount");
+       m_mappings["findLSB"].push_back("OpExtInst FindILsb");
+       m_mappings["findMSB"].push_back("OpExtInst FindUMsb");
+       m_mappings["textureSize"].push_back("OpImageQuerySizeLod");
+       m_mappings["textureQueryLod"].push_back("OpImageQueryLod");
+       m_mappings["textureQueryLevels"].push_back("OpImageQueryLevels");
+       m_mappings["textureSamples"].push_back("OpImageQuerySamples");
+       m_mappings["texture"].push_back("OpImageSampleImplicitLod");
+       m_mappings["textureProj"].push_back("OpImageSampleProjImplicitLod");
+       m_mappings["textureLod"].push_back("OpImageSampleExplicitLod Lod");
+       m_mappings["textureOffset"].push_back("OpImageSampleImplicitLod ConstOffset");
+       m_mappings["texelFetch"].push_back("OpImageFetch Lod");
+       m_mappings["texelFetchOffset"].push_back("OpImageFetch Lod|ConstOffset");
+       m_mappings["textureProjOffset"].push_back("OpImageSampleProjImplicitLod ConstOffset");
+       m_mappings["textureLodOffset"].push_back("OpImageSampleExplicitLod Lod|ConstOffset");
+       m_mappings["textureProjLod"].push_back("OpImageSampleProjExplicitLod Lod");
+       m_mappings["textureProjLodOffset"].push_back("OpImageSampleProjExplicitLod Lod|ConstOffset");
+       m_mappings["textureGrad"].push_back("OpImageSampleExplicitLod Grad");
+       m_mappings["textureGradOffset"].push_back("OpImageSampleExplicitLod Grad|ConstOffset");
+       m_mappings["textureProjGrad"].push_back("OpImageSampleProjExplicitLod Grad");
+       m_mappings["textureProjGradOffset"].push_back("OpImageSampleProjExplicitLod Grad|ConstOffset");
+       m_mappings["textureGather"].push_back("OpImageGather");
+       m_mappings["textureGatherOffset"].push_back("OpImageGather ConstOffset");
+       m_mappings["atomicCounterIncrement"].push_back("OpAtomicIIncrement");
+       m_mappings["atomicCounterDecrement"].push_back("OpAtomicIDecrement");
+       m_mappings["atomicCounter"].push_back("OpAtomicLoad");
+       m_mappings["atomicAdd"].push_back("OpAtomicIAdd");
+       m_mappings["atomicMin"].push_back("OpAtomicUMin");
+       m_mappings["atomicMax"].push_back("OpAtomicUMax");
+       m_mappings["atomicAnd"].push_back("OpAtomicAnd");
+       m_mappings["atomicOr"].push_back("OpAtomicOr");
+       m_mappings["atomicXor"].push_back("OpAtomicXor");
+       m_mappings["atomicExchange"].push_back("OpAtomicExchange");
+       m_mappings["atomicCompSwap"].push_back("OpAtomicCompareExchange");
+       m_mappings["imageSize"].push_back("OpImageQuerySize");
+       m_mappings["imageSamples"].push_back("OpImageQuerySamples");
+       m_mappings["imageLoad"].push_back("OpImageRead");
+       m_mappings["imageStore"].push_back("OpImageWrite");
+       m_mappings["imageAtomicAdd"].push_back("OpAtomicIAdd");
+       m_mappings["imageAtomicMin"].push_back("OpAtomicUMin");
+       m_mappings["imageAtomicMax"].push_back("OpAtomicUMax");
+       m_mappings["imageAtomicAnd"].push_back("OpAtomicAnd");
+       m_mappings["imageAtomicOr"].push_back("OpAtomicOr");
+       m_mappings["imageAtomicXor"].push_back("OpAtomicXor");
+       m_mappings["imageAtomicExchange"].push_back("OpAtomicExchange");
+       m_mappings["imageAtomicCompSwap"].push_back("OpAtomicCompareExchange");
+       m_mappings["dFdx"].push_back("OpDPdx");
+       m_mappings["dFdy"].push_back("OpDPdy");
+       m_mappings["dFdxFine"].push_back("OpDPdxFine");
+       m_mappings["dFdyFine"].push_back("OpDPdyFine");
+       m_mappings["dFdxCoarse"].push_back("OpDPdxCoarse");
+       m_mappings["dFdyCoarse"].push_back("OpDPdyCoarse");
+       m_mappings["fwidth"].push_back("OpFwidth");
+       m_mappings["fwidthFine"].push_back("OpFwidthFine");
+       m_mappings["fwidthCoarse"].push_back("OpFwidthCoarse");
+       m_mappings["interpolateAtCentroid"].push_back("OpExtInst InterpolateAtCentroid");
+       m_mappings["interpolateAtSample"].push_back("OpExtInst InterpolateAtSample");
+       m_mappings["interpolateAtOffset"].push_back("OpExtInst InterpolateAtOffset");
+       m_mappings["EmitStreamVertex"].push_back("OpEmitStreamVertex");
+       m_mappings["EndStreamPrimitive"].push_back("OpEndStreamPrimitive");
+       m_mappings["EmitVertex"].push_back("OpEmitVertex");
+       m_mappings["EndPrimitive"].push_back("OpEndPrimitive");
+       m_mappings["barrier"].push_back("OpControlBarrier");
+       m_mappings["memoryBarrier"].push_back("OpMemoryBarrier");
+       m_mappings["memoryBarrierAtomicCounter"].push_back("OpMemoryBarrier");
+       m_mappings["memoryBarrierBuffer"].push_back("OpMemoryBarrier");
+       m_mappings["memoryBarrierShared"].push_back("OpMemoryBarrier");
+       m_mappings["memoryBarrierImage"].push_back("OpMemoryBarrier");
+       m_mappings["groupMemoryBarrier"].push_back("OpMemoryBarrier");
+
+       // Add a space prefix and parenthesis sufix to avoid searching for similar names
+       SpirVMapping               tempMappings;
+       SpirVMapping::iterator it;
+       for (it = m_mappings.begin(); it != m_mappings.end(); ++it)
+       {
+               tempMappings[std::string(" ") + it->first + "("] = it->second;
+       }
+
+       m_mappings = tempMappings;
+}
+
+/** Constructor.
+ *
+ *  @param context     Rendering context
+ *  @param name        Test name
+ *  @param description Test description
+ */
+SpirvGlslToSpirVSpecializationConstantsTest::SpirvGlslToSpirVSpecializationConstantsTest(deqp::Context& context)
+       : TestCase(context, "spirv_glsl_to_spirv_specialization_constants_test",
+                          "Test verifies if constant specialization feature works as expected.")
+{
+       /* Left blank intentionally */
+}
+
+/** Stub init method */
+void SpirvGlslToSpirVSpecializationConstantsTest::init()
+{
+       if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gl_spirv"))
+               TCU_THROW(NotSupportedError, "GL_ARB_gl_spirv is not supported");
+
+       const Functions& gl = m_context.getRenderContext().getFunctions();
+
+       m_vertex = "#version 450\n"
+                          "\n"
+                          "layout (location = 0) in vec3 position;\n"
+                          "\n"
+                          "void main()\n"
+                          "{\n"
+                          "    gl_Position = vec4(position, 1.0);\n"
+                          "}\n";
+
+       m_fragment = "#version 450\n"
+                                "\n"
+                                "layout (constant_id = 10) const int red = 255;\n"
+                                "\n"
+                                "layout (location = 0) out vec4 fragColor;\n"
+                                "\n"
+                                "void main()\n"
+                                "{\n"
+                                "    fragColor = vec4(float(red) / 255, 0.0, 1.0, 1.0);\n"
+                                "}\n";
+
+       gl.genTextures(1, &m_texture);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "genTextures");
+       gl.bindTexture(GL_TEXTURE_2D, m_texture);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "bindTexture");
+       gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 32, 32);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "texStorage2D");
+
+       gl.genFramebuffers(1, &m_fbo);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "genFramenuffers");
+       gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "bindFramebuffer");
+       gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture, 0);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "framebufferTexture2D");
+
+       gl.viewport(0, 0, 32, 32);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "viewport");
+}
+
+/** Stub de-init method */
+void SpirvGlslToSpirVSpecializationConstantsTest::deinit()
+{
+       const Functions& gl = m_context.getRenderContext().getFunctions();
+
+       if (m_fbo)
+       {
+               gl.deleteFramebuffers(1, &m_fbo);
+               GLU_EXPECT_NO_ERROR(gl.getError(), "deleteFramebuffers");
+       }
+       if (m_texture)
+       {
+               gl.deleteTextures(1, &m_texture);
+               GLU_EXPECT_NO_ERROR(gl.getError(), "deleteTextures");
+       }
+}
+
+/** Executes test iteration.
+ *
+ *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
+ */
+tcu::TestNode::IterateResult SpirvGlslToSpirVSpecializationConstantsTest::iterate()
+{
+       const Functions& gl = m_context.getRenderContext().getFunctions();
+
+       const GLfloat vertices[] = { -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f };
+
+       GLuint vao;
+       gl.genVertexArrays(1, &vao);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays");
+       gl.bindVertexArray(vao);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray");
+
+       GLuint vbo;
+       gl.genBuffers(1, &vbo);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers");
+       gl.bindBuffer(GL_ARRAY_BUFFER, vbo);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");
+
+       gl.bufferData(GL_ARRAY_BUFFER, 9 * sizeof(GLfloat), (GLvoid*)vertices, GL_DYNAMIC_DRAW);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");
+
+       ShaderBinary vertexBinary;
+       ShaderBinary fragmentBinary;
+#if defined             DEQP_HAVE_GLSLANG
+       {
+               vertexBinary   = glslangUtils::makeSpirV(m_context.getTestContext().getLog(), VertexSource(m_vertex));
+               fragmentBinary = glslangUtils::makeSpirV(m_context.getTestContext().getLog(), FragmentSource(m_fragment));
+       }
+#else  // DEQP_HAVE_GLSLANG
+       {
+               tcu::Archive& archive = m_testCtx.getArchive();
+               vertexBinary =
+                       commonUtils::readSpirV(archive.getResource("spirv/glsl_to_spirv_specialization_constants/vertex.nspv"));
+               fragmentBinary =
+                       commonUtils::readSpirV(archive.getResource("spirv/glsl_to_spirv_specialization_constants/fragment.nspv"));
+       }
+#endif // DEQP_HAVE_GLSLANG
+       fragmentBinary << SpecializationData(10, 128);
+
+       ProgramBinaries binaries;
+       binaries << vertexBinary;
+       binaries << fragmentBinary;
+       ShaderProgram spirvProgram(gl, binaries);
+
+       if (!spirvProgram.isOk())
+       {
+               m_testCtx.getLog() << tcu::TestLog::Message << "Shader compilation failed.\n"
+                                                  << "Vertex:\n"
+                                                  << m_vertex.c_str() << "Fragment:\n"
+                                                  << m_fragment.c_str() << "InfoLog:\n"
+                                                  << spirvProgram.getShaderInfo(SHADERTYPE_VERTEX).infoLog << tcu::TestLog::EndMessage;
+
+               m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
+               return STOP;
+       }
+
+       gl.useProgram(spirvProgram.getProgram());
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
+
+       gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor");
+       gl.clear(GL_COLOR_BUFFER_BIT);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glClear");
+
+       gl.enableVertexAttribArray(0);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray");
+
+       gl.vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, DE_NULL);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer");
+
+       gl.drawArrays(GL_TRIANGLES, 0, 3);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArray");
+
+       gl.disableVertexAttribArray(0);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray");
+
+       GLuint output;
+
+       gl.readPixels(16, 16, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)&output);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");
+
+       if (output != 0xFFFF0080)
+       {
+               m_testCtx.getLog() << tcu::TestLog::Message
+                                                  << "Color value read from framebuffer is wrong. Expected: " << 0xFFFF0080
+                                                  << ", Read: " << output << tcu::TestLog::EndMessage;
+
+               m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
+               return STOP;
+       }
+
+       m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
+       return STOP;
+}
+
+/** Constructor.
+ *
+ *  @param context     Rendering context
+ *  @param name        Test name
+ *  @param description Test description
+ */
+SpirvValidationBuiltInVariableDecorationsTest::SpirvValidationBuiltInVariableDecorationsTest(deqp::Context& context)
+       : TestCase(context, "spirv_validation_builtin_variable_decorations_test",
+                          "Test verifies if Spir-V built in variable decorations works as expected.")
+{
+       /* Left blank intentionally */
+}
+
+/** Stub init method */
+void SpirvValidationBuiltInVariableDecorationsTest::init()
+{
+       if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gl_spirv"))
+               TCU_THROW(NotSupportedError, "GL_ARB_gl_spirv is not supported");
+
+       m_compute = "#version 450\n"
+                               "\n"
+                               "layout (local_size_x = 1, local_size_y = 2, local_size_z = 1) in;\n"
+                               "\n"
+                               "layout (location = 0, rgba8ui) uniform uimage2D img0;\n"
+                               "layout (location = 1, rgba8ui) uniform uimage2D img1;\n"
+                               "layout (location = 2, rgba8ui) uniform uimage2D img2;\n"
+                               "layout (location = 3, rgba8ui) uniform uimage2D img3;\n"
+                               "layout (location = 4, rgba8ui) uniform uimage2D img4;\n"
+                               "\n"
+                               "void main()\n"
+                               "{\n"
+                               "    ivec3 point = ivec3(gl_GlobalInvocationID);\n"
+                               "    uvec3 color0 = uvec3(gl_NumWorkGroups);\n"
+                               "    uvec3 color1 = uvec3(gl_WorkGroupSize);\n"
+                               "    uvec3 color2 = uvec3(gl_WorkGroupID);\n"
+                               "    uvec3 color3 = uvec3(gl_LocalInvocationID);\n"
+                               "    uvec3 color4 = uvec3(gl_LocalInvocationIndex);\n"
+                               "    imageStore(img0, point.xy, uvec4(color0, 0xFF));\n"
+                               "    imageStore(img1, point.xy, uvec4(color1, 0xFF));\n"
+                               "    imageStore(img2, point.xy, uvec4(color2, 0xFF));\n"
+                               "    imageStore(img3, point.xy, uvec4(color3, 0xFF));\n"
+                               "    imageStore(img4, point.xy, uvec4(color4, 0xFF));\n"
+                               "    memoryBarrier();\n"
+                               "}\n";
+
+       m_vertex = "#version 450\n"
+                          "\n"
+                          "layout (location = 0) in vec3 position;\n"
+                          "\n"
+                          "layout (location = 1) out vec4 vColor;\n"
+                          "\n"
+                          "void main()\n"
+                          "{\n"
+                          "    gl_PointSize = 10.0f;\n"
+                          "    gl_Position = vec4(position.x, position.y + 0.3 * gl_InstanceID, position.z, 1.0);\n"
+                          "    gl_ClipDistance[0] = <CLIP_DISTANCE>;\n"
+                          "    gl_CullDistance[0] = <CULL_DISTANCE>;\n"
+                          "    vColor = <VERTEX_COLOR>;\n"
+                          "}\n";
+
+       m_tesselationCtrl = "#version 450\n"
+                                               "\n"
+                                               "layout (vertices = 3) out;\n"
+                                               "\n"
+                                               "layout (location = 1) in vec4 vColor[];\n"
+                                               "layout (location = 2) out vec4 tcColor[];\n"
+                                               "\n"
+                                               "void main()\n"
+                                               "{\n"
+                                               "    tcColor[gl_InvocationID] = vColor[gl_InvocationID];\n"
+                                               "    tcColor[gl_InvocationID].r = float(gl_PatchVerticesIn) / 3;\n"
+                                               "\n"
+                                               "    if (gl_InvocationID == 0) {\n"
+                                               "        gl_TessLevelOuter[0] = 1.0;\n"
+                                               "        gl_TessLevelOuter[1] = 1.0;\n"
+                                               "        gl_TessLevelOuter[2] = 1.0;\n"
+                                               "        gl_TessLevelInner[0] = 1.0;\n"
+                                               "    }\n"
+                                               "\n"
+                                               "    gl_out[gl_InvocationID].gl_ClipDistance[0] = gl_in[gl_InvocationID].gl_ClipDistance[0];\n"
+                                               "    gl_out[gl_InvocationID].gl_CullDistance[0] = gl_in[gl_InvocationID].gl_CullDistance[0];\n"
+                                               "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
+                                               "}\n";
+
+       m_tesselationEval = "#version 450\n"
+                                               "\n"
+                                               "layout (triangles) in;\n"
+                                               "\n"
+                                               "layout (location = 2) in vec4 tcColor[];\n"
+                                               "layout (location = 3) out vec4 teColor;\n"
+                                               "\n"
+                                               "void main()\n"
+                                               "{\n"
+                                               "    teColor = tcColor[0];\n"
+                                               "\n"
+                                               "    gl_ClipDistance[0] = gl_in[0].gl_ClipDistance[0];\n"
+                                               "    gl_CullDistance[0] = gl_in[0].gl_CullDistance[0];\n"
+                                               "    gl_Position = gl_TessCoord.x * gl_in[0].gl_Position +\n"
+                                               "                  gl_TessCoord.y * gl_in[1].gl_Position +\n"
+                                               "                  gl_TessCoord.z * gl_in[2].gl_Position;\n"
+                                               "}\n";
+
+       m_geometry = "#version 450\n"
+                                "\n"
+                                "layout (triangles) in;\n"
+                                "layout (triangle_strip, max_vertices = 3) out;\n"
+                                "\n"
+                                "layout (location = 3) in vec4 teColor[];\n"
+                                "layout (location = 4) out vec4 gColor;\n"
+                                "\n"
+                                "void main()\n"
+                                "{\n"
+                                "    gColor = teColor[0];\n"
+                                "    gColor.b = float(gl_PrimitiveIDIn);\n"
+                                "\n"
+                                "    gl_Layer = 1;\n"
+                                "    gl_ViewportIndex = 1;\n"
+                                "\n"
+                                "    for (int i = 0; i < 3; ++i) {\n"
+                                "        gl_ClipDistance[0] = gl_in[i].gl_ClipDistance[0];\n"
+                                "        gl_CullDistance[0] = gl_in[i].gl_CullDistance[0];\n"
+                                "        gl_Position = gl_in[i].gl_Position;\n"
+                                "        EmitVertex();\n"
+                                "    }\n"
+                                "    EndPrimitive();\n"
+                                "}\n";
+
+       m_fragment = "#version 450\n"
+                                "\n"
+                                "layout (location = <INPUT_LOCATION>) in vec4 <INPUT_NAME>;\n"
+                                "layout (location = 0) out vec4 fColor;\n"
+                                "\n"
+                                "void main()\n"
+                                "{\n"
+                                "    vec4 color = <INPUT_NAME>;\n"
+                                "    <ADDITIONAL_CODE>\n"
+                                "    fColor = color;\n"
+                                "}\n";
+
+       ValidationStruct validationCompute(&SpirvValidationBuiltInVariableDecorationsTest::validComputeFunc);
+       validationCompute.shaders.push_back(ComputeSource(m_compute));
+       m_validations.push_back(validationCompute);
+
+       std::string clipNegativeVertex   = m_vertex;
+       std::string clipNegativeFragment = m_fragment;
+       commonUtils::replaceToken("<CLIP_DISTANCE>", "-1.0", clipNegativeVertex);
+       commonUtils::replaceToken("<CULL_DISTANCE>", "1.0", clipNegativeVertex);
+       commonUtils::replaceToken("<VERTEX_COLOR>", "vec4(1.0, 1.0, 1.0, 1.0)", clipNegativeVertex);
+       commonUtils::replaceToken("<INPUT_LOCATION>", "1", clipNegativeFragment);
+       commonUtils::replaceToken("<INPUT_NAME>", "vColor", clipNegativeFragment);
+       commonUtils::replaceToken("<ADDITIONAL_CODE>", "", clipNegativeFragment);
+       ValidationStruct validationClipNegative(&SpirvValidationBuiltInVariableDecorationsTest::validPerVertexFragFunc);
+       validationClipNegative.shaders.push_back(VertexSource(clipNegativeVertex));
+       validationClipNegative.shaders.push_back(FragmentSource(clipNegativeFragment));
+       validationClipNegative.outputs.push_back(ValidationOutputStruct(32, 32, 0xFF000000));
+       m_validations.push_back(validationClipNegative);
+
+       std::string perVertexFragVertex   = m_vertex;
+       std::string perVertexFragFragment = m_fragment;
+       std::string fragCode                      = "vec4 coord = gl_FragCoord;\n"
+                                                  "color = vec4(0.0, coord.s / 64, coord.t / 64, 1.0);\n";
+       commonUtils::replaceToken("<CLIP_DISTANCE>", "1.0", perVertexFragVertex);
+       commonUtils::replaceToken("<CULL_DISTANCE>", "1.0", perVertexFragVertex);
+       commonUtils::replaceToken("<VERTEX_COLOR>", "vec4(1.0, 1.0, 1.0, 1.0)", perVertexFragVertex);
+       commonUtils::replaceToken("<INPUT_LOCATION>", "1", perVertexFragFragment);
+       commonUtils::replaceToken("<INPUT_NAME>", "vColor", perVertexFragFragment);
+       commonUtils::replaceToken("<ADDITIONAL_CODE>", fragCode.c_str(), perVertexFragFragment);
+       ValidationStruct validationFrag(&SpirvValidationBuiltInVariableDecorationsTest::validPerVertexFragFunc);
+       validationFrag.shaders.push_back(VertexSource(perVertexFragVertex));
+       validationFrag.shaders.push_back(FragmentSource(perVertexFragFragment));
+       validationFrag.outputs.push_back(ValidationOutputStruct(32, 32, 0xFF7F7F00));
+       m_validations.push_back(validationFrag);
+
+       std::string perVertexPointVertex   = m_vertex;
+       std::string perVertexPointFragment = m_fragment;
+       std::string pointCode                      = "vec2 coord = gl_PointCoord;\n"
+                                                       "color.b = coord.s * coord.t;\n";
+       commonUtils::replaceToken("<CLIP_DISTANCE>", "1.0", perVertexPointVertex);
+       commonUtils::replaceToken("<CULL_DISTANCE>", "1.0", perVertexPointVertex);
+       commonUtils::replaceToken("<VERTEX_COLOR>", "vec4(float(gl_VertexID) / 3, 0.0, 0.0, 1.0)", perVertexPointVertex);
+       commonUtils::replaceToken("<INPUT_LOCATION>", "1", perVertexPointFragment);
+       commonUtils::replaceToken("<INPUT_NAME>", "vColor", perVertexPointFragment);
+       commonUtils::replaceToken("<ADDITIONAL_CODE>", pointCode.c_str(), perVertexPointFragment);
+       ValidationStruct validationPoint(&SpirvValidationBuiltInVariableDecorationsTest::validPerVertexPointFunc);
+       validationPoint.shaders.push_back(VertexSource(perVertexPointVertex));
+       validationPoint.shaders.push_back(FragmentSource(perVertexPointFragment));
+       validationPoint.outputs.push_back(ValidationOutputStruct(64, 64, 0xFF3F0055));
+       validationPoint.outputs.push_back(ValidationOutputStruct(45, 45, 0xFF3F0000));
+       validationPoint.outputs.push_back(ValidationOutputStruct(83, 83, 0xFF3F00AA));
+       m_validations.push_back(validationPoint);
+
+       std::string tessGeomVertex   = m_vertex;
+       std::string tessGeomFragment = m_fragment;
+       commonUtils::replaceToken("<CLIP_DISTANCE>", "1.0", tessGeomVertex);
+       commonUtils::replaceToken("<CULL_DISTANCE>", "1.0", tessGeomVertex);
+       commonUtils::replaceToken("<VERTEX_COLOR>", "vec4(1.0, 1.0, 1.0, 1.0)", tessGeomVertex);
+       commonUtils::replaceToken("<INPUT_LOCATION>", "4", tessGeomFragment);
+       commonUtils::replaceToken("<INPUT_NAME>", "gColor", tessGeomFragment);
+       commonUtils::replaceToken("<ADDITIONAL_CODE>", "", tessGeomFragment);
+       ValidationStruct validationTessGeom(&SpirvValidationBuiltInVariableDecorationsTest::validTesselationGeometryFunc);
+       validationTessGeom.shaders.push_back(VertexSource(tessGeomVertex));
+       validationTessGeom.shaders.push_back(TessellationControlSource(m_tesselationCtrl));
+       validationTessGeom.shaders.push_back(TessellationEvaluationSource(m_tesselationEval));
+       validationTessGeom.shaders.push_back(GeometrySource(m_geometry));
+       validationTessGeom.shaders.push_back(FragmentSource(tessGeomFragment));
+       validationTessGeom.outputs.push_back(ValidationOutputStruct(48, 32, 1, 0xFF00FFFF));
+       m_validations.push_back(validationTessGeom);
+
+       std::string multisampleVertex   = m_vertex;
+       std::string multisampleFragment = m_fragment;
+       std::string samplingCode                = "if (gl_SampleID == 0)\n"
+                                                          "{\n"
+                                                          "   vec2 sampPos = gl_SamplePosition;\n"
+                                                          "    color = vec4(1.0, sampPos.x, sampPos.y, 1.0);\n"
+                                                          "}\n"
+                                                          "else\n"
+                                                          "{\n"
+                                                          "    color = vec4(0.0, 1.0, 0.0, 1.0);\n"
+                                                          "}\n"
+                                                          "gl_SampleMask[0] = 0x02;";
+       commonUtils::replaceToken("<CLIP_DISTANCE>", "1.0", multisampleVertex);
+       commonUtils::replaceToken("<CULL_DISTANCE>", "1.0", multisampleVertex);
+       commonUtils::replaceToken("<VERTEX_COLOR>", "vec4(1.0, 1.0, 1.0, 1.0)", multisampleVertex);
+       commonUtils::replaceToken("<INPUT_LOCATION>", "1", multisampleFragment);
+       commonUtils::replaceToken("<INPUT_NAME>", "vColor", multisampleFragment);
+       commonUtils::replaceToken("<ADDITIONAL_CODE>", samplingCode.c_str(), multisampleFragment);
+       ValidationStruct validationMultisample(&SpirvValidationBuiltInVariableDecorationsTest::validMultiSamplingFunc);
+       validationMultisample.shaders.push_back(VertexSource(multisampleVertex));
+       validationMultisample.shaders.push_back(FragmentSource(multisampleFragment));
+       validationMultisample.outputs.push_back(ValidationOutputStruct(16, 16, 0xFF00BC00));
+       m_validations.push_back(validationMultisample);
+
+       m_mappings["gl_NumWorkGroups"].push_back("BuiltIn NumWorkgroups");
+       m_mappings["gl_WorkGroupSize"].push_back("BuiltIn WorkgroupSize");
+       m_mappings["gl_WorkGroupID"].push_back("BuiltIn WorkgroupId");
+       m_mappings["gl_LocalInvocationID"].push_back("BuiltIn LocalInvocationId");
+       m_mappings["gl_GlobalInvocationID"].push_back("BuiltIn GlobalInvocationId");
+       m_mappings["gl_LocalInvocationIndex"].push_back("BuiltIn LocalInvocationIndex");
+       m_mappings["gl_VertexID"].push_back("BuiltIn VertexId");
+       m_mappings["gl_InstanceID"].push_back("BuiltIn InstanceId");
+       m_mappings["gl_Position"].push_back("BuiltIn Position");
+       m_mappings["gl_PointSize"].push_back("BuiltIn PointSize");
+       m_mappings["gl_ClipDistance"].push_back("BuiltIn ClipDistance");
+       m_mappings["gl_CullDistance"].push_back("BuiltIn CullDistance");
+       m_mappings["gl_PrimitiveIDIn"].push_back("BuiltIn PrimitiveId");
+       m_mappings["gl_InvocationID"].push_back("BuiltIn InvocationId");
+       m_mappings["gl_Layer"].push_back("BuiltIn Layer");
+       m_mappings["gl_ViewportIndex"].push_back("BuiltIn ViewportIndex");
+       m_mappings["gl_PatchVerticesIn"].push_back("BuiltIn PatchVertices");
+       m_mappings["gl_TessLevelOuter"].push_back("BuiltIn TessLevelOuter");
+       m_mappings["gl_TessLevelInner"].push_back("BuiltIn TessLevelInner");
+       m_mappings["gl_TessCoord"].push_back("BuiltIn TessCoord");
+       m_mappings["gl_FragCoord"].push_back("BuiltIn FragCoord");
+       m_mappings["gl_FrontFacing"].push_back("BuiltIn FrontFacing");
+       m_mappings["gl_PointCoord"].push_back("BuiltIn PointCoord");
+       m_mappings["gl_SampleId"].push_back("BuiltIn SampleId");
+       m_mappings["gl_SamplePosition"].push_back("BuiltIn SamplePosition");
+       m_mappings["gl_SampleMask"].push_back("BuiltIn SampleMask");
+}
+
+/** Stub de-init method */
+void SpirvValidationBuiltInVariableDecorationsTest::deinit()
+{
+}
+
+/** Executes test iteration.
+ *
+ *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
+ */
+tcu::TestNode::IterateResult SpirvValidationBuiltInVariableDecorationsTest::iterate()
+{
+       const Functions& gl = m_context.getRenderContext().getFunctions();
+
+       GLuint vao;
+       gl.genVertexArrays(1, &vao);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays");
+       gl.bindVertexArray(vao);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray");
+
+       GLuint vbo;
+       gl.genBuffers(1, &vbo);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers");
+       gl.bindBuffer(GL_ARRAY_BUFFER, vbo);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");
+
+       enum Iterates
+       {
+               ITERATE_GLSL,
+               ITERATE_SPIRV,
+               ITERATE_LAST
+       };
+
+       bool result = true;
+
+       for (int v = 0; v < m_validations.size(); ++v)
+       {
+               for (int it = ITERATE_GLSL; it < ITERATE_LAST; ++it)
+               {
+                       ShaderProgram* program = DE_NULL;
+                       if (it == ITERATE_GLSL)
+                       {
+                               ProgramSources sources;
+                               for (int s = 0; s < m_validations[v].shaders.size(); ++s)
+                                       sources << m_validations[v].shaders[s];
+
+                               program = new ShaderProgram(gl, sources);
+                       }
+                       else if (it == ITERATE_SPIRV)
+                       {
+                               std::vector<ShaderBinary> binariesVec;
+
+#if defined                                            DEQP_HAVE_GLSLANG
+                               ProgramBinaries binaries;
+                               for (int s = 0; s < m_validations[v].shaders.size(); ++s)
+                               {
+                                       ShaderBinary shaderBinary =
+                                               glslangUtils::makeSpirV(m_context.getTestContext().getLog(), m_validations[v].shaders[s]);
+                                       binariesVec.push_back(shaderBinary);
+                                       binaries << shaderBinary;
+                               }
+#else  // DEQP_HAVE_GLSLANG
+                               tcu::Archive&   archive = m_testCtx.getArchive();
+                               ProgramBinaries binaries;
+                               for (int s = 0; s < m_validations[v].shaders.size(); ++s)
+                               {
+                                       std::stringstream ss;
+                                       ss << "spirv/spirv_validation_builtin_variable_decorations/shader_" << v << "_" << s << ".nspv";
+
+                                       ShaderBinary shaderBinary = commonUtils::readSpirV(archive.getResource(ss.str().c_str()));
+                                       binariesVec.push_back(shaderBinary);
+                                       binaries << shaderBinary;
+                               }
+#endif // DEQP_HAVE_GLSLANG
+                               program = new ShaderProgram(gl, binaries);
+
+#if defined                                    DEQP_HAVE_SPIRV_TOOLS
+                               std::string spirvSource;
+
+                               for (int s = 0; s < m_validations[v].shaders.size(); ++s)
+                               {
+                                       ShaderSource shaderSource = m_validations[v].shaders[s];
+
+                                       glslangUtils::spirvDisassemble(spirvSource, binariesVec[s].binary);
+
+                                       if (!glslangUtils::verifyMappings(shaderSource.source, spirvSource, m_mappings, true))
+                                       {
+                                               m_testCtx.getLog() << tcu::TestLog::Message << "Mappings for shader failed.\n"
+                                                                                  << "GLSL source:\n"
+                                                                                  << shaderSource.source.c_str() << "\n"
+                                                                                  << "SpirV source:\n"
+                                                                                  << spirvSource.c_str() << tcu::TestLog::EndMessage;
+
+                                               TCU_THROW(InternalError, "Mappings for shader failed.");
+                                       }
+                               }
+#endif // DEQP_HAVE_SPIRV_TOOLS
+                       }
+
+                       if (!program->isOk())
+                       {
+                               std::stringstream message;
+                               message << "Shader build failed.\n";
+
+                               if (program->hasShader(SHADERTYPE_COMPUTE))
+                                       message << "ComputeInfo: " << program->getShaderInfo(SHADERTYPE_COMPUTE).infoLog << "\n"
+                                                       << "ComputeSource: " << program->getShader(SHADERTYPE_COMPUTE)->getSource() << "\n";
+                               if (program->hasShader(SHADERTYPE_VERTEX))
+                                       message << "VertexInfo: " << program->getShaderInfo(SHADERTYPE_VERTEX).infoLog << "\n"
+                                                       << "VertexSource: " << program->getShader(SHADERTYPE_VERTEX)->getSource() << "\n";
+                               if (program->hasShader(SHADERTYPE_TESSELLATION_CONTROL))
+                                       message << "TesselationCtrlInfo: "
+                                                       << program->getShaderInfo(SHADERTYPE_TESSELLATION_CONTROL).infoLog << "\n"
+                                                       << "TesselationCtrlSource: "
+                                                       << program->getShader(SHADERTYPE_TESSELLATION_CONTROL)->getSource() << "\n";
+                               if (program->hasShader(SHADERTYPE_TESSELLATION_EVALUATION))
+                                       message << "TesselationEvalInfo: "
+                                                       << program->getShaderInfo(SHADERTYPE_TESSELLATION_EVALUATION).infoLog << "\n"
+                                                       << "TesselationEvalSource: "
+                                                       << program->getShader(SHADERTYPE_TESSELLATION_EVALUATION)->getSource() << "\n";
+                               if (program->hasShader(SHADERTYPE_GEOMETRY))
+                                       message << "GeometryInfo: " << program->getShaderInfo(SHADERTYPE_GEOMETRY).infoLog << "\n"
+                                                       << "GeometrySource: " << program->getShader(SHADERTYPE_GEOMETRY)->getSource() << "\n";
+                               if (program->hasShader(SHADERTYPE_FRAGMENT))
+                                       message << "FragmentInfo: " << program->getShaderInfo(SHADERTYPE_FRAGMENT).infoLog << "\n"
+                                                       << "FragmentSource: " << program->getShader(SHADERTYPE_FRAGMENT)->getSource() << "\n";
+
+                               message << "ProgramInfo: " << program->getProgramInfo().infoLog;
+
+                               m_testCtx.getLog() << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage;
+
+                               m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
+                               return STOP;
+                       }
+
+                       gl.useProgram(program->getProgram());
+                       GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
+
+                       ValidationFuncPtr funcPtr = m_validations[v].validationFuncPtr;
+                       result                                    = (this->*funcPtr)(m_validations[v].outputs);
+
+                       if (program)
+                               delete program;
+
+                       if (!result)
+                       {
+                               m_testCtx.getLog() << tcu::TestLog::Message << "Validation " << v << " failed!"
+                                                                  << tcu::TestLog::EndMessage;
+
+                               break;
+                       }
+               }
+       }
+
+       if (vbo)
+       {
+               gl.deleteBuffers(1, &vbo);
+               GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteBuffers");
+       }
+
+       if (vao)
+       {
+               gl.deleteVertexArrays(1, &vao);
+               GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteVertexArrays");
+       }
+
+       if (result)
+               m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
+       else
+               m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
+       return STOP;
+}
+
+bool SpirvValidationBuiltInVariableDecorationsTest::validComputeFunc(ValidationOutputVec& outputs)
+{
+       const Functions& gl = m_context.getRenderContext().getFunctions();
+
+       GLuint textures[5];
+
+       gl.genTextures(5, textures);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "genTextures");
+       for (int i = 0; i < 5; ++i)
+       {
+               gl.bindTexture(GL_TEXTURE_2D, textures[i]);
+               GLU_EXPECT_NO_ERROR(gl.getError(), "bindTexture");
+               gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8UI, 4, 4);
+               GLU_EXPECT_NO_ERROR(gl.getError(), "texStorage2D");
+       }
+
+       gl.bindImageTexture(0, textures[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8UI);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "bindImageTexture");
+       gl.bindImageTexture(1, textures[1], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8UI);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "bindImageTexture");
+       gl.bindImageTexture(2, textures[2], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8UI);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "bindImageTexture");
+       gl.bindImageTexture(3, textures[3], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8UI);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "bindImageTexture");
+       gl.bindImageTexture(4, textures[4], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8UI);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "bindImageTexture");
+       gl.uniform1i(0, 0);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "uniform1i");
+       gl.uniform1i(1, 1);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "uniform1i");
+       gl.uniform1i(2, 2);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "uniform1i");
+       gl.uniform1i(3, 3);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "uniform1i");
+       gl.uniform1i(4, 4);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "uniform1i");
+       gl.dispatchCompute(4, 2, 1);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "dispatchCompute");
+
+       gl.memoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "memoryBarrier");
+
+       std::vector<GLubyte> expectedResults[5];
+       for (int i = 0; i < 5; ++i)
+       {
+               for (int y = 0; y < 4; ++y)
+               {
+                       for (int x = 0; x < 4; ++x)
+                       {
+                               //"uvec3 color0 = uvec3(gl_NumWorkGroups);"
+                               if (i == 0)
+                               {
+                                       expectedResults[i].push_back(4);
+                                       expectedResults[i].push_back(2);
+                                       expectedResults[i].push_back(1);
+                                       expectedResults[i].push_back(0xFF);
+                               }
+                               //"uvec3 color1 = uvec3(gl_WorkGroupSize);"
+                               else if (i == 1)
+                               {
+                                       expectedResults[i].push_back(1);
+                                       expectedResults[i].push_back(2);
+                                       expectedResults[i].push_back(1);
+                                       expectedResults[i].push_back(0xFF);
+                               }
+                               //"uvec3 color2 = uvec3(gl_WorkGroupID);"
+                               else if (i == 2)
+                               {
+                                       expectedResults[i].push_back(x);
+                                       expectedResults[i].push_back(y / 2);
+                                       expectedResults[i].push_back(0);
+                                       expectedResults[i].push_back(0xFF);
+                               }
+                               //"uvec3 color3 = uvec3(gl_LocalInvocationID);"
+                               else if (i == 3)
+                               {
+                                       expectedResults[i].push_back(0);
+                                       expectedResults[i].push_back(y % 2);
+                                       expectedResults[i].push_back(0);
+                                       expectedResults[i].push_back(0xFF);
+                               }
+                               //"uvec3 color4 = uvec3(gl_LocalInvocationIndex);"
+                               else if (i == 4)
+                               {
+                                       expectedResults[i].push_back(y % 2);
+                                       expectedResults[i].push_back(y % 2);
+                                       expectedResults[i].push_back(y % 2);
+                                       expectedResults[i].push_back(0xFF);
+                               }
+                       }
+               }
+       }
+
+       bool result = true;
+       for (int i = 0; i < 5; ++i)
+       {
+               gl.bindTexture(GL_TEXTURE_2D, textures[i]);
+               GLU_EXPECT_NO_ERROR(gl.getError(), "bindTexture");
+
+               std::vector<GLubyte> pixels;
+               pixels.resize(4 * 4 * 4);
+               gl.getTexImage(GL_TEXTURE_2D, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, (GLvoid*)pixels.data());
+               GLU_EXPECT_NO_ERROR(gl.getError(), "getTexImage");
+
+               if (pixels != expectedResults[i])
+               {
+                       m_testCtx.getLog() << tcu::TestLog::Message << "Invalid image computed [" << i << "]."
+                                                          << tcu::TestLog::EndMessage;
+
+                       result = false;
+               }
+       }
+
+       if (textures)
+       {
+               gl.deleteTextures(5, textures);
+               GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures");
+       }
+
+       return result;
+}
+
+bool SpirvValidationBuiltInVariableDecorationsTest::validPerVertexFragFunc(ValidationOutputVec& outputs)
+{
+       const Functions& gl = m_context.getRenderContext().getFunctions();
+
+       const GLfloat vertices[] = { -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f };
+
+       GLuint texture;
+       GLuint fbo;
+
+       gl.genTextures(1, &texture);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "genTextures");
+       gl.bindTexture(GL_TEXTURE_2D, texture);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "bindTexture");
+       gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 64, 64);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "texStorage2D");
+
+       gl.genFramebuffers(1, &fbo);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "genFramenuffers");
+       gl.bindFramebuffer(GL_FRAMEBUFFER, fbo);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "bindFramebuffer");
+       gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "framebufferTexture2D");
+
+       gl.viewport(0, 0, 64, 64);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport");
+
+       gl.bufferData(GL_ARRAY_BUFFER, 9 * sizeof(GLfloat), (GLvoid*)vertices, GL_DYNAMIC_DRAW);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");
+
+       gl.enable(GL_CLIP_DISTANCE0);
+
+       gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor");
+       gl.clear(GL_COLOR_BUFFER_BIT);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glClear");
+
+       gl.enableVertexAttribArray(0);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray");
+
+       gl.vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, DE_NULL);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer");
+
+       gl.drawArrays(GL_TRIANGLES, 0, 3);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArray");
+
+       gl.disableVertexAttribArray(0);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray");
+
+       gl.disable(GL_CLIP_DISTANCE0);
+
+       bool result = true;
+       for (int o = 0; o < outputs.size(); ++o)
+       {
+               GLuint output;
+               gl.readPixels(outputs[o].x, outputs[o].y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)&output);
+               GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");
+
+               if (!commonUtils::compareUintColors(output, outputs[o].value, 2))
+               {
+                       m_testCtx.getLog() << tcu::TestLog::Message << "Invalid output color read at [" << (int)outputs[o].x << "/"
+                                                          << (int)outputs[o].y << "]. Expected: " << outputs[o].value << ", "
+                                                          << "Read: " << output << tcu::TestLog::EndMessage;
+
+                       result = false;
+               }
+       }
+
+       if (fbo)
+       {
+               gl.deleteFramebuffers(1, &fbo);
+               GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteFramebuffers");
+       }
+
+       if (texture)
+       {
+               gl.deleteTextures(1, &texture);
+               GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures");
+       }
+
+       return result;
+}
+
+bool SpirvValidationBuiltInVariableDecorationsTest::validPerVertexPointFunc(ValidationOutputVec& outputs)
+{
+       const Functions& gl = m_context.getRenderContext().getFunctions();
+
+       const GLfloat vertices[] = { -0.3f, -0.3f, 0.0f, 0.0f, -0.3f, 0.0f, 0.3f, -0.3f, 0.0f };
+
+       GLuint texture;
+       GLuint fbo;
+
+       gl.genTextures(1, &texture);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "genTextures");
+       gl.bindTexture(GL_TEXTURE_2D, texture);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "bindTexture");
+       gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 128, 128);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "texStorage2D");
+
+       gl.genFramebuffers(1, &fbo);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "genFramenuffers");
+       gl.bindFramebuffer(GL_FRAMEBUFFER, fbo);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "bindFramebuffer");
+       gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "framebufferTexture2D");
+
+       gl.viewport(0, 0, 128, 128);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport");
+
+       gl.bufferData(GL_ARRAY_BUFFER, 9 * sizeof(GLfloat), (GLvoid*)vertices, GL_DYNAMIC_DRAW);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");
+
+       gl.enable(GL_CLIP_DISTANCE0);
+       gl.enable(GL_PROGRAM_POINT_SIZE);
+
+       gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor");
+       gl.clear(GL_COLOR_BUFFER_BIT);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glClear");
+
+       gl.enableVertexAttribArray(0);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray");
+
+       gl.vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, DE_NULL);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer");
+
+       gl.drawArraysInstanced(GL_POINTS, 0, 3, 3);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArray");
+
+       gl.disableVertexAttribArray(0);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray");
+
+       gl.disable(GL_PROGRAM_POINT_SIZE);
+       gl.disable(GL_CLIP_DISTANCE0);
+
+       bool result = true;
+       for (int o = 0; o < outputs.size(); ++o)
+       {
+               GLuint output;
+               gl.readPixels(outputs[o].x, outputs[o].y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)&output);
+               GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");
+
+               if (!commonUtils::compareUintColors(output, outputs[o].value, 2))
+               {
+                       m_testCtx.getLog() << tcu::TestLog::Message << "Invalid output color read at [" << (int)outputs[o].x << "/"
+                                                          << (int)outputs[o].y << "]. Expected: " << outputs[o].value << ", "
+                                                          << "Read: " << output << tcu::TestLog::EndMessage;
+
+                       result = false;
+               }
+       }
+
+       if (fbo)
+       {
+               gl.deleteFramebuffers(1, &fbo);
+               GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteFramebuffers");
+       }
+
+       if (texture)
+       {
+               gl.deleteTextures(1, &texture);
+               GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures");
+       }
+
+       return result;
+}
+
+bool SpirvValidationBuiltInVariableDecorationsTest::validTesselationGeometryFunc(ValidationOutputVec& outputs)
+{
+       const Functions& gl = m_context.getRenderContext().getFunctions();
+
+       const GLfloat vertices[] = { -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f };
+
+       GLuint texture;
+       GLuint fbo;
+
+       gl.genTextures(1, &texture);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "genTextures");
+       gl.bindTexture(GL_TEXTURE_2D_ARRAY, texture);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "bindTexture");
+       gl.texStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, 64, 64, 2);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "texStorage2D");
+
+       gl.genFramebuffers(1, &fbo);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "genFramenuffers");
+       gl.bindFramebuffer(GL_FRAMEBUFFER, fbo);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "bindFramebuffer");
+       gl.framebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "framebufferTexture2D");
+
+       gl.viewportIndexedf(0, 0.0f, 0.0f, 32.0f, 64.0f);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glViewportIndexed");
+
+       gl.viewportIndexedf(1, 32.0f, 0.0f, 32.0f, 64.0f);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glViewportIndexed");
+
+       gl.bufferData(GL_ARRAY_BUFFER, 9 * sizeof(GLfloat), (GLvoid*)vertices, GL_DYNAMIC_DRAW);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");
+
+       gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor");
+       gl.clear(GL_COLOR_BUFFER_BIT);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glClear");
+
+       gl.enableVertexAttribArray(0);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray");
+
+       gl.vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, DE_NULL);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer");
+
+       gl.patchParameteri(GL_PATCH_VERTICES, 3);
+       gl.drawArrays(GL_PATCHES, 0, 3);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArray");
+
+       gl.disableVertexAttribArray(0);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray");
+
+       gl.viewport(0, 0, 128, 64);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport");
+
+       std::vector<GLuint> pixels;
+       pixels.resize(64 * 64 * 2);
+       gl.getTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)pixels.data());
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTexImage");
+
+       bool result = true;
+       for (int o = 0; o < outputs.size(); ++o)
+       {
+               GLuint output = pixels[(outputs[o].x + outputs[o].y * 64) + outputs[o].z * 64 * 64];
+
+               if (!commonUtils::compareUintColors(output, outputs[o].value, 2))
+               {
+                       m_testCtx.getLog() << tcu::TestLog::Message << "Invalid output color read at [" << (int)outputs[o].x << "/"
+                                                          << (int)outputs[o].y << "/" << (int)outputs[o].z << "]. Expected: " << outputs[o].value
+                                                          << ", "
+                                                          << "Read: " << output << tcu::TestLog::EndMessage;
+
+                       result = false;
+               }
+       }
+
+       if (fbo)
+       {
+               gl.deleteFramebuffers(1, &fbo);
+               GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteFramebuffers");
+       }
+
+       if (texture)
+       {
+               gl.deleteTextures(1, &texture);
+               GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures");
+       }
+
+       return result;
+}
+
+bool SpirvValidationBuiltInVariableDecorationsTest::validMultiSamplingFunc(ValidationOutputVec& outputs)
+{
+       const Functions& gl = m_context.getRenderContext().getFunctions();
+
+       const GLfloat vertices[] = { -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f };
+
+       GLuint textureMS;
+       GLuint texture;
+       GLuint fboMS;
+       GLuint fbo;
+
+       gl.genTextures(1, &textureMS);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "genTextures");
+       gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, textureMS);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "bindTexture");
+       gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 2, GL_RGBA8, 32, 32, GL_TRUE);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "texStorage2DMultisample");
+
+       gl.genTextures(1, &texture);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "genTextures");
+       gl.bindTexture(GL_TEXTURE_2D, texture);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "bindTexture");
+       gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 32, 32);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "texStorage2D");
+
+       gl.genFramebuffers(1, &fboMS);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "genFramenuffers");
+       gl.bindFramebuffer(GL_FRAMEBUFFER, fboMS);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "bindFramebuffer");
+       gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, textureMS, 0);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "framebufferTexture2D");
+
+       gl.genFramebuffers(1, &fbo);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "genFramenuffers");
+       gl.bindFramebuffer(GL_FRAMEBUFFER, fbo);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "bindFramebuffer");
+       gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "framebufferTexture2D");
+
+       gl.bindFramebuffer(GL_FRAMEBUFFER, fboMS);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "bindFramebuffer");
+
+       gl.viewport(0, 0, 32, 32);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport");
+
+       gl.bufferData(GL_ARRAY_BUFFER, 9 * sizeof(GLfloat), (GLvoid*)vertices, GL_DYNAMIC_DRAW);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");
+
+       gl.enable(GL_CLIP_DISTANCE0);
+
+       gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor");
+       gl.clear(GL_COLOR_BUFFER_BIT);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glClear");
+
+       gl.enableVertexAttribArray(0);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray");
+
+       gl.vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, DE_NULL);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer");
+
+       gl.drawArrays(GL_TRIANGLES, 0, 3);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArray");
+
+       gl.disableVertexAttribArray(0);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray");
+
+       gl.disable(GL_CLIP_DISTANCE0);
+
+       gl.bindFramebuffer(GL_READ_FRAMEBUFFER, fboMS);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "bindFramebuffer");
+       gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "bindFramebuffer");
+
+       gl.blitFramebuffer(0, 0, 32, 32, 0, 0, 32, 32, GL_COLOR_BUFFER_BIT, GL_NEAREST);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "blitFramebuffer");
+
+       gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "bindFramebuffer");
+
+       bool result = true;
+       for (int o = 0; o < outputs.size(); ++o)
+       {
+               GLuint output;
+               gl.readPixels(outputs[o].x, outputs[o].y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)&output);
+               GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");
+
+               if (!commonUtils::compareUintColors(output, outputs[o].value, 2))
+               {
+                       m_testCtx.getLog() << tcu::TestLog::Message << "Invalid output color read at [" << (int)outputs[o].x << "/"
+                                                          << (int)outputs[o].y << "]. Expected: " << outputs[o].value << ", "
+                                                          << "Read: " << output << tcu::TestLog::EndMessage;
+
+                       result = false;
+               }
+       }
+
+       if (fboMS)
+       {
+               gl.deleteFramebuffers(1, &fboMS);
+               GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteFramebuffers");
+       }
+
+       if (fbo)
+       {
+               gl.deleteFramebuffers(1, &fbo);
+               GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteFramebuffers");
+       }
+
+       if (textureMS)
+       {
+               gl.deleteTextures(1, &texture);
+               GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures");
+       }
+
+       if (texture)
+       {
+               gl.deleteTextures(1, &texture);
+               GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteTextures");
+       }
+
+       return result;
+}
+
+/** Constructor.
+ *
+ *  @param context Rendering context.
+ */
+GlSpirvTests::GlSpirvTests(deqp::Context& context)
+       : TestCaseGroup(context, "gl_spirv", "Verify conformance of ARB_gl_spirv implementation")
+{
+}
+
+/** Initializes the test group contents. */
+void GlSpirvTests::init()
+{
+       addChild(new SpirvModulesPositiveTest(m_context));
+       addChild(new SpirvShaderBinaryMultipleShaderObjectsTest(m_context));
+       addChild(new SpirvModulesStateQueriesTest(m_context));
+       addChild(new SpirvModulesErrorVerificationTest(m_context));
+       addChild(new SpirvGlslToSpirVEnableTest(m_context));
+       addChild(new SpirvGlslToSpirVBuiltInFunctionsTest(m_context));
+       addChild(new SpirvGlslToSpirVSpecializationConstantsTest(m_context));
+       addChild(new SpirvValidationBuiltInVariableDecorationsTest(m_context));
+}
+
+} /* gl4cts namespace */
diff --git a/external/openglcts/modules/gl/gl4cGlSpirvTests.hpp b/external/openglcts/modules/gl/gl4cGlSpirvTests.hpp
new file mode 100644 (file)
index 0000000..25034b0
--- /dev/null
@@ -0,0 +1,288 @@
+#ifndef _GL4CGLSPIRVTESTS_HPP
+#define _GL4CGLSPIRVTESTS_HPP
+/*-------------------------------------------------------------------------
+ * OpenGL Conformance Test Suite
+ * -----------------------------
+ *
+ * Copyright (c) 2017 The Khronos Group Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */ /*!
+ * \file
+ * \brief
+ */ /*-------------------------------------------------------------------*/
+
+/**
+ */ /*!
+ * \file  gl4cGlSpirvTests.hpp
+ * \brief Conformance tests for the GL_ARB_gl_spirv functionality.
+ */ /*-------------------------------------------------------------------*/
+
+#include "glcTestCase.hpp"
+#include "gluShaderProgram.hpp"
+#include "glwDefs.hpp"
+#include "tcuDefs.hpp"
+#include <map>
+#include <vector>
+
+using namespace glu;
+using namespace glw;
+
+namespace gl4cts
+{
+
+typedef std::map<std::string, std::vector<std::string> > SpirVMapping;
+
+/**  Verifies if using SPIR-V modules for each shader stage works as expected. */
+class SpirvModulesPositiveTest : public deqp::TestCase
+{
+public:
+       /* Public methods */
+       SpirvModulesPositiveTest(deqp::Context& context);
+
+       void init();
+       void deinit();
+
+       tcu::TestNode::IterateResult iterate();
+
+private:
+       /* Private methods */
+
+       /* Private members */
+       GLuint m_texture;
+       GLuint m_fbo;
+
+       std::string m_vertex;
+       std::string m_tesselationCtrl;
+       std::string m_tesselationEval;
+       std::string m_geometry;
+       std::string m_fragment;
+};
+
+/**  Verifies if one binary module can be associated with multiple shader objects. */
+class SpirvShaderBinaryMultipleShaderObjectsTest : public deqp::TestCase
+{
+public:
+       /* Public methods */
+       SpirvShaderBinaryMultipleShaderObjectsTest(deqp::Context& context);
+
+       void init();
+       void deinit();
+
+       tcu::TestNode::IterateResult iterate();
+
+private:
+       /* Private methods */
+
+       /* Private members */
+       std::string m_spirv;
+};
+
+/**  Verifies if state queries for new features added by ARB_gl_spirv works as expected. */
+class SpirvModulesStateQueriesTest : public deqp::TestCase
+{
+public:
+       /* Public methods */
+       SpirvModulesStateQueriesTest(deqp::Context& context);
+
+       void init();
+       void deinit();
+
+       tcu::TestNode::IterateResult iterate();
+
+private:
+       /* Private methods */
+
+       /* Private members */
+       std::string m_vertex;
+};
+
+/**  Verifies if new features added by ARB_gl_spirv generate error messages as expected. */
+class SpirvModulesErrorVerificationTest : public deqp::TestCase
+{
+public:
+       /* Public methods */
+       SpirvModulesErrorVerificationTest(deqp::Context& context);
+
+       void init();
+       void deinit();
+
+       tcu::TestNode::IterateResult iterate();
+
+private:
+       /* Private methods */
+
+       /* Private members */
+       std::string m_vertex;
+
+       GLuint m_glslShaderId;
+       GLuint m_spirvShaderId;
+       GLuint m_programId;
+       GLuint m_textureId;
+};
+
+/**  Verifies if GLSL to Spir-V converter supports Spir-V features. */
+class SpirvGlslToSpirVEnableTest : public deqp::TestCase
+{
+public:
+       /* Public methods */
+       SpirvGlslToSpirVEnableTest(deqp::Context& context);
+
+       void init();
+       void deinit();
+
+       tcu::TestNode::IterateResult iterate();
+
+private:
+       /* Private methods */
+
+       /* Private members */
+       std::string m_vertex;
+};
+
+/**  Verifies if GLSL built-in functions are supported by Spir-V. */
+class SpirvGlslToSpirVBuiltInFunctionsTest : public deqp::TestCase
+{
+public:
+       /* Public methods */
+       SpirvGlslToSpirVBuiltInFunctionsTest(deqp::Context& context);
+
+       void init();
+       void deinit();
+
+       tcu::TestNode::IterateResult iterate();
+
+private:
+       /* Private methods */
+       void initMappings();
+
+       /* Private members */
+       SpirVMapping m_mappings;
+
+       std::string                               m_commonVertex;
+       std::string                               m_commonTessEval;
+       std::vector<ShaderSource> m_sources;
+};
+
+/**  Verifies if constant specialization feature works as expected. */
+class SpirvGlslToSpirVSpecializationConstantsTest : public deqp::TestCase
+{
+public:
+       /* Public methods */
+       SpirvGlslToSpirVSpecializationConstantsTest(deqp::Context& context);
+
+       void init();
+       void deinit();
+
+       tcu::TestNode::IterateResult iterate();
+
+private:
+       /* Private methods */
+
+       /* Private members */
+       GLuint m_texture;
+       GLuint m_fbo;
+
+       std::string m_vertex;
+       std::string m_fragment;
+};
+
+/**  Verifies if Spir-V built in variable decorations works as expected. */
+class SpirvValidationBuiltInVariableDecorationsTest : public deqp::TestCase
+{
+public:
+       /* Public methods */
+       SpirvValidationBuiltInVariableDecorationsTest(deqp::Context& context);
+
+       void init();
+       void deinit();
+
+       tcu::TestNode::IterateResult iterate();
+
+private:
+       /* Private structs */
+       struct ValidationOutputStruct
+       {
+               GLubyte x, y, z;
+               GLuint  value;
+
+               ValidationOutputStruct() : x(0), y(0), z(0), value(0)
+               {
+               }
+
+               ValidationOutputStruct(GLubyte _x, GLubyte _y, GLuint _value) : x(_x), y(_y), z(0), value(_value)
+               {
+               }
+
+               ValidationOutputStruct(GLubyte _x, GLubyte _y, GLubyte _z, GLuint _value) : x(_x), y(_y), z(_z), value(_value)
+               {
+               }
+       };
+
+       typedef std::vector<ValidationOutputStruct> ValidationOutputVec;
+
+       typedef bool (SpirvValidationBuiltInVariableDecorationsTest::*ValidationFuncPtr)(ValidationOutputVec& outputs);
+
+       struct ValidationStruct
+       {
+               std::vector<ShaderSource> shaders;
+               ValidationOutputVec               outputs;
+               ValidationFuncPtr                 validationFuncPtr;
+
+               ValidationStruct() : validationFuncPtr(DE_NULL)
+               {
+               }
+
+               ValidationStruct(ValidationFuncPtr funcPtr) : validationFuncPtr(funcPtr)
+               {
+               }
+       };
+
+       /* Private methods */
+       bool validComputeFunc(ValidationOutputVec& outputs);
+       bool validPerVertexFragFunc(ValidationOutputVec& outputs);
+       bool validPerVertexPointFunc(ValidationOutputVec& outputs);
+       bool validTesselationGeometryFunc(ValidationOutputVec& outputs);
+       bool validMultiSamplingFunc(ValidationOutputVec& outputs);
+
+       /* Private members */
+       SpirVMapping m_mappings;
+
+       std::vector<ValidationStruct> m_validations;
+
+       std::string m_compute;
+       std::string m_vertex;
+       std::string m_tesselationCtrl;
+       std::string m_tesselationEval;
+       std::string m_geometry;
+       std::string m_fragment;
+};
+
+/** Test group which encapsulates all sparse buffer conformance tests */
+class GlSpirvTests : public deqp::TestCaseGroup
+{
+public:
+       /* Public methods */
+       GlSpirvTests(deqp::Context& context);
+
+       void init();
+
+private:
+       GlSpirvTests(const GlSpirvTests& other);
+       GlSpirvTests& operator=(const GlSpirvTests& other);
+};
+
+} /* glcts namespace */
+
+#endif // _GL4CGLSPIRVTESTS_HPP
index 73d4cb1..a1bc0a7 100644 (file)
@@ -35,6 +35,7 @@
 #include "gl4cEnhancedLayoutsTests.hpp"
 #include "gl4cGPUShaderFP64Tests.hpp"
 #include "gl4cGetTextureSubImageTests.hpp"
+#include "gl4cGlSpirvTests.hpp"
 #include "gl4cIncompleteTextureAccessTests.hpp"
 #include "gl4cIndirectParametersTests.hpp"
 #include "gl4cKHRDebugTests.hpp"
@@ -372,6 +373,7 @@ void GL45TestPackage::init(void)
                addChild(new glcts::PolygonOffsetClamp(getContext()));
                addChild(new glcts::SeparableProgramsTransformFeedbackTests(getContext()));
                addChild(new gl4cts::SpirvExtensionsTests(getContext()));
+               addChild(new gl4cts::GlSpirvTests(getContext()));
        }
        catch (...)
        {
index 333e0d5..94b310b 100644 (file)
@@ -132,6 +132,65 @@ void Shader::compile (void)
        }
 }
 
+void Shader::specialize (const char* entryPoint, glw::GLuint numSpecializationConstants,
+                                                const glw::GLuint* constantIndex, const glw::GLuint* constantValue)
+{
+       m_info.compileOk                = false;
+       m_info.compileTimeUs    = 0;
+       m_info.infoLog.clear();
+
+       {
+               deUint64 compileStart = deGetMicroseconds();
+               m_gl.specializeShader(m_shader, entryPoint, numSpecializationConstants, constantIndex, constantValue);
+               m_info.compileTimeUs = deGetMicroseconds() - compileStart;
+       }
+
+       GLU_EXPECT_NO_ERROR(m_gl.getError(), "glSpecializeShader()");
+
+       // Query status
+       {
+               int compileStatus = 0;
+
+               m_gl.getShaderiv(m_shader, GL_COMPILE_STATUS, &compileStatus);
+               GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGetShaderiv()");
+
+               m_info.compileOk = compileStatus != GL_FALSE;
+       }
+
+       // Query log
+       {
+               int infoLogLen = 0;
+               int unusedLen;
+
+               m_gl.getShaderiv(m_shader, GL_INFO_LOG_LENGTH, &infoLogLen);
+               GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGetShaderiv()");
+
+               if (infoLogLen > 0)
+               {
+                       // The INFO_LOG_LENGTH query and the buffer query implementations have
+                       // very commonly off-by-one errors. Try to work around these issues.
+
+                       // add tolerance for off-by-one in log length, buffer write, and for terminator
+                       std::vector<char> infoLog(infoLogLen + 3, '\0');
+
+                       // claim buf size is one smaller to protect from off-by-one writing over buffer bounds
+                       m_gl.getShaderInfoLog(m_shader, (int)infoLog.size() - 1, &unusedLen, &infoLog[0]);
+                       GLU_EXPECT_NO_ERROR(m_gl.getError(), "glGetShaderInfoLog()");
+
+                       if (infoLog[(int)(infoLog.size()) - 1] != '\0')
+                       {
+                               // return whole buffer if null terminator was overwritten
+                               m_info.infoLog = std::string(&infoLog[0], infoLog.size());
+                       }
+                       else
+                       {
+                               // read as C string. infoLog is guaranteed to be 0-terminated
+                               m_info.infoLog = std::string(&infoLog[0]);
+                       }
+               }
+       }
+}
+
 // Program
 
 static bool getProgramLinkStatus (const glw::Functions& gl, deUint32 program)
@@ -312,12 +371,24 @@ ShaderProgram::ShaderProgram (const RenderContext& renderCtx, const ProgramSourc
        init(renderCtx.getFunctions(), sources);
 }
 
+ShaderProgram::ShaderProgram (const RenderContext& renderCtx, const ProgramBinaries& binaries)
+       : m_program(renderCtx.getFunctions())
+{
+       init(renderCtx.getFunctions(), binaries);
+}
+
 ShaderProgram::ShaderProgram (const glw::Functions& gl, const ProgramSources& sources)
        : m_program(gl)
 {
        init(gl, sources);
 }
 
+ShaderProgram::ShaderProgram (const glw::Functions& gl, const ProgramBinaries& binaries)
+       : m_program(gl)
+{
+       init(gl, binaries);
+}
+
 void ShaderProgram::init (const glw::Functions& gl, const ProgramSources& sources)
 {
        try
@@ -375,6 +446,85 @@ void ShaderProgram::init (const glw::Functions& gl, const ProgramSources& source
        }
 }
 
+void ShaderProgram::init (const glw::Functions& gl, const ProgramBinaries& binaries)
+{
+       try
+       {
+               bool shadersOk = true;
+
+               for (deUint32 binaryNdx = 0; binaryNdx < binaries.binaries.size(); ++binaryNdx)
+               {
+                       ShaderBinary shaderBinary = binaries.binaries[binaryNdx];
+                       if (!shaderBinary.binary.empty())
+                       {
+                               const char* binary      = (const char*)shaderBinary.binary.data();
+                               const int       length  = (int)(shaderBinary.binary.size() * sizeof(deUint32));
+
+                               DE_ASSERT(shaderBinary.shaderEntryPoints.size() == shaderBinary.shaderTypes.size());
+
+                               std::vector<Shader*> shaders;
+                               for (deUint32 shaderTypeNdx = 0; shaderTypeNdx < shaderBinary.shaderTypes.size(); ++shaderTypeNdx)
+                               {
+                                       ShaderType shaderType = shaderBinary.shaderTypes[shaderTypeNdx];
+
+                                       Shader* shader = new Shader(gl, ShaderType(shaderType));
+
+                                       m_shaders[shaderType].reserve(m_shaders[shaderType].size() + 1);
+                                       m_shaders[shaderType].push_back(shader);
+                                       shaders.push_back(shader);
+                               }
+
+                               setBinary(gl, shaders, binaries.binaryFormat, binary, length);
+
+                               for (deUint32 shaderNdx = 0; shaderNdx < shaders.size(); ++shaderNdx)
+                               {
+                                       shaders[shaderNdx]->specialize(shaderBinary.shaderEntryPoints[shaderNdx].c_str(),
+                                                                                                  (deUint32)shaderBinary.specializationIndices.size(),
+                                                                                                  shaderBinary.specializationIndices.data(),
+                                                                                                  shaderBinary.specializationValues.data());
+
+                                       shadersOk = shadersOk && shaders[shaderNdx]->getCompileStatus();
+                               }
+                       }
+               }
+
+               if (shadersOk)
+               {
+                       for (int shaderType = 0; shaderType < SHADERTYPE_LAST; shaderType++)
+                               for (int shaderNdx = 0; shaderNdx < (int)m_shaders[shaderType].size(); ++shaderNdx)
+                                       m_program.attachShader(m_shaders[shaderType][shaderNdx]->getShader());
+
+                       m_program.link();
+               }
+       }
+       catch (...)
+       {
+               for (int shaderType = 0; shaderType < SHADERTYPE_LAST; shaderType++)
+                       for (int shaderNdx = 0; shaderNdx < (int)m_shaders[shaderType].size(); ++shaderNdx)
+                               delete m_shaders[shaderType][shaderNdx];
+               throw;
+       }
+}
+
+void ShaderProgram::setBinary (const glw::Functions& gl, std::vector<Shader*>& shaders, glw::GLenum binaryFormat, const void* binaryData, const int length)
+{
+       std::vector<glw::GLuint> shaderVec;
+       for (deUint32 shaderNdx = 0; shaderNdx < shaders.size(); ++shaderNdx)
+               shaderVec.push_back(shaders[shaderNdx]->getShader());
+
+       gl.shaderBinary((glw::GLsizei)shaderVec.size(), shaderVec.data(), binaryFormat, binaryData, length);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderBinary");
+
+       for (deUint32 shaderNdx = 0; shaderNdx < shaders.size(); ++shaderNdx)
+       {
+               glw::GLint shaderState;
+               gl.getShaderiv(shaders[shaderNdx]->getShader(), GL_SPIR_V_BINARY_ARB, &shaderState);
+               GLU_EXPECT_NO_ERROR(gl.getError(), "getShaderiv");
+
+               DE_ASSERT(shaderState == GL_TRUE);
+       }
+}
+
 ShaderProgram::~ShaderProgram (void)
 {
        for (int shaderType = 0; shaderType < SHADERTYPE_LAST; shaderType++)
index e2c7ad2..3a8b263 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "gluDefs.hpp"
 #include "gluShaderUtil.hpp"
+#include "glwEnums.hpp"
 #include "qpTestLog.h"
 
 #include <string>
@@ -40,6 +41,8 @@ namespace glu
 
 class RenderContext;
 
+typedef std::vector<deUint32> ShaderBinaryDataType;
+
 /*--------------------------------------------------------------------*//*!
  * \brief Shader information (compile status, log, etc.).
  *//*--------------------------------------------------------------------*/
@@ -87,6 +90,8 @@ public:
 
        void                                    setSources                      (int numSourceStrings, const char* const* sourceStrings, const int* lengths);
        void                                    compile                         (void);
+       void                                    specialize                      (const char* entryPoint, glw::GLuint numSpecializationConstants,
+                                                                                                const glw::GLuint* constantIndex, const glw::GLuint* constantValue);
 
        deUint32                                getShader                       (void) const { return m_shader;                         }
        const ShaderInfo&               getInfo                         (void) const { return m_info;                           }
@@ -173,6 +178,7 @@ private:
 };
 
 struct ProgramSources;
+struct ProgramBinaries;
 
 /*--------------------------------------------------------------------*//*!
  * \brief Shader program manager.
@@ -184,13 +190,16 @@ class ShaderProgram
 {
 public:
                                                        ShaderProgram                           (const glw::Functions& gl, const ProgramSources& sources);
+                                                       ShaderProgram                           (const glw::Functions& gl, const ProgramBinaries& binaries);
                                                        ShaderProgram                           (const RenderContext& renderCtx, const ProgramSources& sources);
+                                                       ShaderProgram                           (const RenderContext& renderCtx, const ProgramBinaries& binaries);
                                                        ~ShaderProgram                          (void);
 
        bool                                    isOk                                            (void) const                                                                                    { return m_program.getLinkStatus();                                             }
        deUint32                                getProgram                                      (void) const                                                                                    { return m_program.getProgram();                                                }
 
        bool                                    hasShader                                       (glu::ShaderType shaderType) const                                              { return !m_shaders[shaderType].empty();                                }
+       Shader*                                 getShader                                       (glu::ShaderType shaderType, int shaderNdx = 0) const   { return m_shaders[shaderType][shaderNdx];      }
        int                                             getNumShaders                           (glu::ShaderType shaderType) const                                              { return (int)m_shaders[shaderType].size();                             }
        const ShaderInfo&               getShaderInfo                           (glu::ShaderType shaderType, int shaderNdx = 0) const   { return m_shaders[shaderType][shaderNdx]->getInfo();   }
        const ProgramInfo&              getProgramInfo                          (void) const                                                                                    { return m_program.getInfo();                                                   }
@@ -199,6 +208,8 @@ private:
                                                        ShaderProgram                           (const ShaderProgram& other);
        ShaderProgram&                  operator=                                       (const ShaderProgram& other);
        void                                    init                                            (const glw::Functions& gl, const ProgramSources& sources);
+       void                                    init                                            (const glw::Functions& gl, const ProgramBinaries& binaries);
+       void                                    setBinary                                       (const glw::Functions& gl, std::vector<Shader*>& shaders, glw::GLenum binaryFormat, const void* binaryData, const int length);
 
        std::vector<Shader*>    m_shaders[SHADERTYPE_LAST];
        Program                                 m_program;
@@ -317,6 +328,97 @@ struct ProgramSources
        ProgramSources&                                         operator<<                      (const TransformFeedbackVaryings<Iterator>& varyings);
 };
 
+struct SpecializationData
+{
+       deUint32 index;
+       deUint32 value;
+
+       SpecializationData (void) : index(0), value(0) {}
+       SpecializationData (const deUint32 index_, const deUint32 value_) : index(index_), value(value_) {}
+};
+
+struct ShaderBinary
+{
+       ShaderBinaryDataType            binary;
+       std::vector<ShaderType>         shaderTypes;
+       std::vector<std::string>        shaderEntryPoints;
+       std::vector<deUint32>           specializationIndices;
+       std::vector<deUint32>           specializationValues;
+
+       ShaderBinary (void) {}
+       ShaderBinary (const ShaderBinaryDataType binary_) : binary(binary_)
+       {
+               DE_ASSERT(!binary_.empty());
+       }
+       ShaderBinary (const ShaderBinaryDataType binary_, glu::ShaderType shaderType_) : binary(binary_)
+       {
+               DE_ASSERT(!binary_.empty());
+               shaderTypes.push_back(shaderType_);
+               shaderEntryPoints.push_back("main");
+       }
+
+       ShaderBinary& operator<< (const ShaderType& shaderType)
+       {
+               shaderTypes.push_back(shaderType);
+               return *this;
+       }
+
+       ShaderBinary& operator<< (const std::string& entryPoint)
+       {
+               shaderEntryPoints.push_back(entryPoint);
+               return *this;
+       }
+
+       ShaderBinary& operator<< (const SpecializationData& specData)
+       {
+               specializationIndices.push_back(specData.index);
+               specializationValues.push_back(specData.value);
+               return *this;
+       }
+};
+
+struct VertexBinary : public ShaderBinary
+{
+       VertexBinary (const ShaderBinaryDataType binary_) : ShaderBinary(binary_, glu::SHADERTYPE_VERTEX) {}
+};
+
+struct FragmentBinary : public ShaderBinary
+{
+       FragmentBinary (const ShaderBinaryDataType binary_) : ShaderBinary(binary_, glu::SHADERTYPE_FRAGMENT) {}
+};
+
+struct GeometryBinary : public ShaderBinary
+{
+       GeometryBinary (const ShaderBinaryDataType binary_) : ShaderBinary(binary_, glu::SHADERTYPE_GEOMETRY) {}
+};
+
+struct ComputeBinary : public ShaderBinary
+{
+       ComputeBinary (const ShaderBinaryDataType binary_) : ShaderBinary(binary_, glu::SHADERTYPE_COMPUTE) {}
+};
+
+struct TessellationControlBinary : public ShaderBinary
+{
+       TessellationControlBinary (const ShaderBinaryDataType binary_) : ShaderBinary(binary_, glu::SHADERTYPE_TESSELLATION_CONTROL) {}
+};
+
+struct TessellationEvaluationBinary : public ShaderBinary
+{
+       TessellationEvaluationBinary (const ShaderBinaryDataType binary_) : ShaderBinary(binary_, glu::SHADERTYPE_TESSELLATION_EVALUATION) {}
+};
+
+struct ProgramBinaries
+{
+       std::vector<ShaderBinary>       binaries;
+
+       glw::GLenum                                     binaryFormat;
+
+       ProgramBinaries (void) : binaryFormat(GL_SHADER_BINARY_FORMAT_SPIR_V_ARB) {}
+       ProgramBinaries (glw::GLenum binaryFormat_) : binaryFormat(binaryFormat_) {}
+
+       ProgramBinaries& operator<< (const ShaderBinary& shaderBinary)  { binaries.push_back(shaderBinary);     return *this;   }
+};
+
 template<typename Iterator>
 inline ProgramSources& ProgramSources::operator<< (const TransformFeedbackVaryings<Iterator>& varyings)
 {
index e8c9d0b..17b523e 100644 (file)
 #define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12                                                  0x93DD
 #define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR                                              0x93DD
 #define GL_SHADER_BINARY_FORMAT_SPIR_V                                                                 0x9551
+#define GL_SHADER_BINARY_FORMAT_SPIR_V_ARB                                                             0x9551
 #define GL_SPIR_V_BINARY                                                                                               0x9552
+#define GL_SPIR_V_BINARY_ARB                                                                                   0x9552
 #define GL_SPIR_V_EXTENSIONS                                                                                   0x9553
 #define GL_NUM_SPIR_V_EXTENSIONS                                                                               0x9554
index 419398f..5cfe14b 100644 (file)
@@ -705,6 +705,11 @@ if (de::contains(extSet, "GL_ARB_get_program_binary"))
        gl->programParameteri   = (glProgramParameteriFunc)     loader->get("glProgramParameteri");
 }
 
+if (de::contains(extSet, "GL_ARB_gl_spirv"))
+{
+       gl->specializeShader    = (glSpecializeShaderFunc)      loader->get("glSpecializeShaderARB");
+}
+
 if (de::contains(extSet, "GL_ARB_indirect_parameters"))
 {
        gl->multiDrawArraysIndirectCount        = (glMultiDrawArraysIndirectCountFunc)          loader->get("glMultiDrawArraysIndirectCountARB");
index 96ae341..006a5e0 100644 (file)
@@ -100,6 +100,7 @@ EXTENSIONS                  = [
        'GL_ARB_draw_elements_base_vertex',
        'GL_ARB_direct_state_access',
        'GL_ARB_get_program_binary',
+       'GL_ARB_gl_spirv',
        'GL_ARB_indirect_parameters',
        'GL_ARB_internalformat_query',
        'GL_ARB_instanced_arrays',