Add tests for SPV_KHR_variable_pointers extension
authorEhsan Nasiri <ehsann@google.com>
Fri, 31 Mar 2017 20:40:35 +0000 (16:40 -0400)
committerAlexander Galazin <Alexander.Galazin@arm.com>
Tue, 4 Jul 2017 08:41:37 +0000 (04:41 -0400)
Compute tests and graphics tests are added for the
VK_KHR_variable_pointers
extension.

Components: Vulkan, Framework
VK-GL-CTS issue: 123
New Tests: dEQP-VK.spirv_assembly.instruction.*.variable_pointers.*

Change-Id: If2d01d626428d89a27432e2b1df33778e0b29f3b

19 files changed:
android/cts/master/vk-master.txt
external/fetch_sources.py
external/vulkancts/framework/vulkan/vkBasicTypes.inl
external/vulkancts/framework/vulkan/vkStrUtil.inl
external/vulkancts/framework/vulkan/vkStrUtilImpl.inl
external/vulkancts/framework/vulkan/vkStructTypes.inl
external/vulkancts/modules/vulkan/spirv_assembly/CMakeLists.txt
external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsm16bitStorageTests.cpp
external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderCase.cpp
external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderTestUtil.hpp
external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmGraphicsShaderTestUtil.cpp
external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmGraphicsShaderTestUtil.hpp
external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmInstructionTests.cpp
external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmUtils.cpp
external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmUtils.hpp
external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmVariablePointersTests.cpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmVariablePointersTests.hpp [new file with mode: 0644]
external/vulkancts/mustpass/1.0.3/vk-default.txt
external/vulkancts/scripts/src/vulkan.h.in

index 8809f71..8260b88 100644 (file)
@@ -140908,6 +140908,23 @@ dEQP-VK.spirv_assembly.instruction.compute.16bit_storage.push_constant_16_to_32.
 dEQP-VK.spirv_assembly.instruction.compute.16bit_storage.push_constant_16_to_32.scalar_uint
 dEQP-VK.spirv_assembly.instruction.compute.16bit_storage.push_constant_16_to_32.vector_sint
 dEQP-VK.spirv_assembly.instruction.compute.16bit_storage.push_constant_16_to_32.vector_uint
+dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.compute.reads_opselect_single_buffer
+dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.compute.reads_opfunctioncall_single_buffer
+dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.compute.reads_opphi_single_buffer
+dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.compute.reads_opcopyobject_single_buffer
+dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.compute.stores_private_single_buffer
+dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.compute.stores_function_single_buffer
+dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.compute.reads_opptraccesschain_single_buffer
+dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.compute.writes_single_buffer
+dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.compute.reads_opselect_two_buffers
+dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.compute.reads_opfunctioncall_two_buffers
+dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.compute.reads_opphi_two_buffers
+dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.compute.reads_opcopyobject_two_buffers
+dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.compute.stores_private_two_buffers
+dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.compute.stores_function_two_buffers
+dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.compute.reads_opptraccesschain_two_buffers
+dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.compute.writes_two_buffers
+dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.compute.workgroup_two_buffers
 dEQP-VK.spirv_assembly.instruction.compute.android.opsrem.positive
 dEQP-VK.spirv_assembly.instruction.compute.android.opsrem.all
 dEQP-VK.spirv_assembly.instruction.compute.android.opsmod.positive
@@ -142790,6 +142807,86 @@ dEQP-VK.spirv_assembly.instruction.graphics.16bit_storage.push_constant_int_16_t
 dEQP-VK.spirv_assembly.instruction.graphics.16bit_storage.push_constant_int_16_to_32.uint_vector_tesse
 dEQP-VK.spirv_assembly.instruction.graphics.16bit_storage.push_constant_int_16_to_32.uint_vector_geom
 dEQP-VK.spirv_assembly.instruction.graphics.16bit_storage.push_constant_int_16_to_32.uint_vector_frag
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opselect_single_buffer_vert
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opselect_single_buffer_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opselect_single_buffer_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opselect_single_buffer_geom
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opselect_single_buffer_frag
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opfunctioncall_single_buffer_vert
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opfunctioncall_single_buffer_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opfunctioncall_single_buffer_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opfunctioncall_single_buffer_geom
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opfunctioncall_single_buffer_frag
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opphi_single_buffer_vert
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opphi_single_buffer_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opphi_single_buffer_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opphi_single_buffer_geom
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opphi_single_buffer_frag
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opcopyobject_single_buffer_vert
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opcopyobject_single_buffer_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opcopyobject_single_buffer_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opcopyobject_single_buffer_geom
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opcopyobject_single_buffer_frag
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.stores_private_single_buffer_vert
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.stores_private_single_buffer_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.stores_private_single_buffer_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.stores_private_single_buffer_geom
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.stores_private_single_buffer_frag
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.stores_function_single_buffer_vert
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.stores_function_single_buffer_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.stores_function_single_buffer_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.stores_function_single_buffer_geom
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.stores_function_single_buffer_frag
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opptraccesschain_single_buffer_vert
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opptraccesschain_single_buffer_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opptraccesschain_single_buffer_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opptraccesschain_single_buffer_geom
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opptraccesschain_single_buffer_frag
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.writes_single_buffer_vert
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.writes_single_buffer_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.writes_single_buffer_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.writes_single_buffer_geom
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.writes_single_buffer_frag
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opselect_two_buffers_vert
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opselect_two_buffers_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opselect_two_buffers_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opselect_two_buffers_geom
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opselect_two_buffers_frag
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opfunctioncall_two_buffers_vert
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opfunctioncall_two_buffers_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opfunctioncall_two_buffers_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opfunctioncall_two_buffers_geom
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opfunctioncall_two_buffers_frag
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opphi_two_buffers_vert
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opphi_two_buffers_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opphi_two_buffers_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opphi_two_buffers_geom
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opphi_two_buffers_frag
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opcopyobject_two_buffers_vert
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opcopyobject_two_buffers_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opcopyobject_two_buffers_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opcopyobject_two_buffers_geom
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opcopyobject_two_buffers_frag
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.stores_private_two_buffers_vert
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.stores_private_two_buffers_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.stores_private_two_buffers_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.stores_private_two_buffers_geom
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.stores_private_two_buffers_frag
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.stores_function_two_buffers_vert
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.stores_function_two_buffers_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.stores_function_two_buffers_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.stores_function_two_buffers_geom
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.stores_function_two_buffers_frag
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opptraccesschain_two_buffers_vert
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opptraccesschain_two_buffers_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opptraccesschain_two_buffers_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opptraccesschain_two_buffers_geom
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opptraccesschain_two_buffers_frag
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.writes_two_buffers_vert
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.writes_two_buffers_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.writes_two_buffers_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.writes_two_buffers_geom
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.writes_two_buffers_frag
 dEQP-VK.glsl.arrays.constructor.float3_vertex
 dEQP-VK.glsl.arrays.constructor.float3_fragment
 dEQP-VK.glsl.arrays.constructor.float4_vertex
index 8aafb38..e81473c 100644 (file)
@@ -241,9 +241,9 @@ PACKAGES = [
                "libpng",
                postExtract = postExtractLibpng),
        GitRepo(
-               "https://github.com/KhronosGroup/SPIRV-Tools.git",
-               None,
-               "bf68c814268cfa8b0311f93f16db4c3eed6eb7d2",
+               "https://gitlab.khronos.org/spirv/spirv-tools.git",
+               "git@gitlab.khronos.org:spirv/spirv-tools.git",
+               "5ef1440f3ec5a5fc6e5cf368383c4b1ae323f0f8",
                "spirv-tools"),
        GitRepo(
                "https://github.com/KhronosGroup/glslang.git",
@@ -251,9 +251,9 @@ PACKAGES = [
                "a5c5fb61180e8703ca85f36d618f98e16dc317e2",
                "glslang"),
        GitRepo(
-               "https://github.com/KhronosGroup/SPIRV-Headers.git",
-               None,
-               "db5cf6176137003ca4c25df96f7c0649998c3499",
+               "https://gitlab.khronos.org/spirv/SPIRV-Headers.git",
+               "git@gitlab.khronos.org:spirv/SPIRV-Headers.git",
+               "de4c26af39f243b0c2176f9e15089f5968d52394",
                "spirv-headers"),
 ]
 
index 6766582..a80965e 100644 (file)
@@ -191,6 +191,7 @@ enum VkStructureType
        VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR                            = 1000119000,
        VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR                                            = 1000119001,
        VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR                                                          = 1000119002,
+       VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR         = 1000120000,
        VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR                                     = 1000127000,
        VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR                            = 1000127001,
        VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2_KHR                         = 1000146000,
index b5abb10..565ed2b 100644 (file)
@@ -387,3 +387,4 @@ std::ostream&       operator<<      (std::ostream& s, const VkRefreshCycleDurationGOOGLE& v
 std::ostream&  operator<<      (std::ostream& s, const VkPastPresentationTimingGOOGLE& value);
 std::ostream&  operator<<      (std::ostream& s, const VkPresentTimeGOOGLE& value);
 std::ostream&  operator<<      (std::ostream& s, const VkPresentTimesInfoGOOGLE& value);
+std::ostream&  operator<<      (std::ostream& s, const VkPhysicalDeviceVariablePointerFeaturesKHR& value);
index 86c0194..5019a3f 100644 (file)
@@ -202,6 +202,7 @@ const char* getStructureTypeName (VkStructureType value)
                case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR:                              return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR";
                case VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR:                                              return "VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR";
                case VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR:                                                    return "VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR";
+               case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR:   return "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR";
                case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR:                               return "VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR";
                case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR:                              return "VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR";
                case VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2_KHR:                   return "VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2_KHR";
@@ -4026,3 +4027,14 @@ std::ostream& operator<< (std::ostream& s, const VkPresentTimesInfoGOOGLE& value
        s << '}';
        return s;
 }
+
+std::ostream& operator<< (std::ostream& s, const VkPhysicalDeviceVariablePointerFeaturesKHR& value)
+{
+       s << "VkPhysicalDeviceVariablePointerFeaturesKHR = {\n";
+       s << "\tsType = " << value.sType << '\n';
+       s << "\tpNext = " << value.pNext << '\n';
+       s << "\tvariablePointersStorageBuffer = " << value.variablePointersStorageBuffer << '\n';
+       s << "\tvariablePointers = " << value.variablePointers << '\n';
+       s << '}';
+       return s;
+}
index 42515d5..7f1f6e3 100644 (file)
@@ -1821,3 +1821,11 @@ struct VkPresentTimesInfoGOOGLE
        const VkPresentTimeGOOGLE*      pTimes;
 };
 
+struct VkPhysicalDeviceVariablePointerFeaturesKHR
+{
+       VkStructureType sType;
+       const void*             pNext;
+       VkBool32                variablePointersStorageBuffer;
+       VkBool32                variablePointers;
+};
+
index d73b374..31c82a4 100644 (file)
@@ -17,6 +17,8 @@ set(DEQP_VK_SPIRV_ASSEMBLY_SRCS
        vktSpvAsmTests.hpp
        vktSpvAsmUtils.cpp
        vktSpvAsmUtils.hpp
+       vktSpvAsmVariablePointersTests.cpp
+       vktSpvAsmVariablePointersTests.hpp
        )
 
 set(DEQP_VK_SPIRV_ASSEMBLY_LIBS
index 50a6c4e..ddf4268 100644 (file)
@@ -117,16 +117,17 @@ static const Capability   CAPABILITIES[]  =
        {"uniform",                                     "StorageUniform16",                             "Block",                VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER},
 };
 
-ExtensionFeatures      get16BitStorageFeatures (const char* cap)
+VulkanFeatures get16BitStorageFeatures (const char* cap)
 {
+       VulkanFeatures features;
        if (string(cap) == "uniform_buffer_block")
-               return ExtensionFeatures(EXT16BITSTORAGEFEATURES_UNIFORM_BUFFER_BLOCK);
+               features.ext16BitStorage = EXT16BITSTORAGEFEATURES_UNIFORM_BUFFER_BLOCK;
+       else if (string(cap) == "uniform")
+               features.ext16BitStorage = EXT16BITSTORAGEFEATURES_UNIFORM;
+       else
+               DE_ASSERT(false && "not supported");
 
-       if (string(cap) == "uniform")
-               return ExtensionFeatures(EXT16BITSTORAGEFEATURES_UNIFORM);
-
-       DE_ASSERT(false && "not supported");
-       return ExtensionFeatures(0);
+       return features;
 }
 
 
@@ -613,7 +614,7 @@ void addCompute16bitStorageUniform16To32Group (tcu::TestCaseGroup* group)
                                spec.inputs.push_back(BufferSp(new Float16Buffer(float16Data)));
                                spec.outputs.push_back(BufferSp(new Float32Buffer(float32Data)));
                                spec.extensions.push_back("VK_KHR_16bit_storage");
-                               spec.requestedExtensionFeatures = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
+                               spec.requestedVulkanFeatures = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
 
                                group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), testName.c_str(), spec));
                        }
@@ -707,7 +708,7 @@ void addCompute16bitStorageUniform16To32Group (tcu::TestCaseGroup* group)
                                else
                                        spec.outputs.push_back(BufferSp(new Int32Buffer(uOutputs)));
                                spec.extensions.push_back("VK_KHR_16bit_storage");
-                               spec.requestedExtensionFeatures = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
+                               spec.requestedVulkanFeatures = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
 
                                group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), testName.c_str(), spec));
                        }
@@ -863,7 +864,7 @@ void addCompute16bitStoragePushConstant16To32Group (tcu::TestCaseGroup* group)
 
                        spec.outputs.push_back(BufferSp(new Float32Buffer(float32Data)));
                        spec.extensions.push_back("VK_KHR_16bit_storage");
-                       spec.requestedExtensionFeatures.ext16BitStorage = EXT16BITSTORAGEFEATURES_PUSH_CONSTANT;
+                       spec.requestedVulkanFeatures.ext16BitStorage = EXT16BITSTORAGEFEATURES_PUSH_CONSTANT;
 
                        group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), testName.c_str(), spec));
                }
@@ -952,7 +953,7 @@ void addCompute16bitStoragePushConstant16To32Group (tcu::TestCaseGroup* group)
                        else
                                spec.outputs.push_back(BufferSp(new Int32Buffer(uOutputs)));
                        spec.extensions.push_back("VK_KHR_16bit_storage");
-                       spec.requestedExtensionFeatures.ext16BitStorage = EXT16BITSTORAGEFEATURES_PUSH_CONSTANT;
+                       spec.requestedVulkanFeatures.ext16BitStorage = EXT16BITSTORAGEFEATURES_PUSH_CONSTANT;
 
                        group->addChild(new SpvAsmComputeShaderCase(testCtx, testName, testName, spec));
                }
@@ -1341,7 +1342,7 @@ void addCompute16bitStorageUniform32To16Group (tcu::TestCaseGroup* group)
                                        // So put dummy data in the expected values.
                                        spec.outputs.push_back(BufferSp(new Float16Buffer(float16DummyData)));
                                        spec.extensions.push_back("VK_KHR_16bit_storage");
-                                       spec.requestedExtensionFeatures = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
+                                       spec.requestedVulkanFeatures = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
 
                                        group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), testName.c_str(), spec));
                                }
@@ -1420,7 +1421,7 @@ void addCompute16bitStorageUniform32To16Group (tcu::TestCaseGroup* group)
                                spec.inputs.push_back(BufferSp(new Int32Buffer(inputs)));
                                spec.outputs.push_back(BufferSp(new Int16Buffer(outputs)));
                                spec.extensions.push_back("VK_KHR_16bit_storage");
-                               spec.requestedExtensionFeatures = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
+                               spec.requestedVulkanFeatures = get16BitStorageFeatures(CAPABILITIES[capIdx].name);
 
                                group->addChild(new SpvAsmComputeShaderCase(testCtx, testName.c_str(), testName.c_str(), spec));
                        }
@@ -1845,8 +1846,8 @@ void addGraphics16BitStorageInputOutputFloat32To16Group (tcu::TestCaseGroup* tes
                }
        };
 
-       ExtensionFeatures       extensionFeatures;
-       extensionFeatures.ext16BitStorage = EXT16BITSTORAGEFEATURES_INPUT_OUTPUT;
+       VulkanFeatures  requiredFeatures;
+       requiredFeatures.ext16BitStorage = EXT16BITSTORAGEFEATURES_INPUT_OUTPUT;
 
        for (deUint32 caseIdx = 0; caseIdx < DE_LENGTH_OF_ARRAY(cases); ++caseIdx)
                for (deUint32 rndModeIdx = 0; rndModeIdx < DE_LENGTH_OF_ARRAY(rndModes); ++rndModeIdx)
@@ -1878,7 +1879,7 @@ void addGraphics16BitStorageInputOutputFloat32To16Group (tcu::TestCaseGroup* tes
                                }
                                interfaces.setInputOutput(std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_FLOAT32), BufferSp(new Float32Buffer(subInputs))),
                                                                                  std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_FLOAT16), BufferSp(new Float16Buffer(subOutputs))));
-                               createTestsForAllStages(testName, defaultColors, defaultColors, fragments, interfaces, extensions, testGroup, extensionFeatures);
+                               createTestsForAllStages(testName, defaultColors, defaultColors, fragments, interfaces, extensions, testGroup, requiredFeatures);
                        }
                }
 }
@@ -1966,8 +1967,8 @@ void addGraphics16BitStorageInputOutputFloat16To32Group (tcu::TestCaseGroup* tes
                }
        };
 
-       ExtensionFeatures       extensionFeatures;
-       extensionFeatures.ext16BitStorage = EXT16BITSTORAGEFEATURES_INPUT_OUTPUT;
+       VulkanFeatures  requiredFeatures;
+       requiredFeatures.ext16BitStorage = EXT16BITSTORAGEFEATURES_INPUT_OUTPUT;
 
        for (deUint32 caseIdx = 0; caseIdx < DE_LENGTH_OF_ARRAY(cases); ++caseIdx)
        {
@@ -1993,7 +1994,7 @@ void addGraphics16BitStorageInputOutputFloat16To32Group (tcu::TestCaseGroup* tes
                        }
                        interfaces.setInputOutput(std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_FLOAT16), BufferSp(new Float16Buffer(subInputs))),
                                                                          std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_FLOAT32), BufferSp(new Float32Buffer(subOutputs))));
-                       createTestsForAllStages(testName, defaultColors, defaultColors, fragments, interfaces, extensions, testGroup, extensionFeatures);
+                       createTestsForAllStages(testName, defaultColors, defaultColors, fragments, interfaces, extensions, testGroup, requiredFeatures);
                }
        }
 }
@@ -2081,8 +2082,8 @@ void addGraphics16BitStorageInputOutputInt32To16Group (tcu::TestCaseGroup* testG
                {"vector_uint", vecInterfaceOpFunc,             vecPreMain,             "v4u32",        "v4u16",        "0",    "OpUConvert",   4 * 4,  4},
        };
 
-       ExtensionFeatures       extensionFeatures;
-       extensionFeatures.ext16BitStorage = EXT16BITSTORAGEFEATURES_INPUT_OUTPUT;
+       VulkanFeatures  requiredFeatures;
+       requiredFeatures.ext16BitStorage = EXT16BITSTORAGEFEATURES_INPUT_OUTPUT;
 
        for (deUint32 caseIdx = 0; caseIdx < DE_LENGTH_OF_ARRAY(cases); ++caseIdx)
        {
@@ -2122,7 +2123,7 @@ void addGraphics16BitStorageInputOutputInt32To16Group (tcu::TestCaseGroup* testG
                                interfaces.setInputOutput(std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_UINT32), BufferSp(new Int32Buffer(subInputs))),
                                                                                  std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_UINT16), BufferSp(new Int16Buffer(subOutputs))));
                        }
-                       createTestsForAllStages(testName, defaultColors, defaultColors, fragments, interfaces, extensions, testGroup, extensionFeatures);
+                       createTestsForAllStages(testName, defaultColors, defaultColors, fragments, interfaces, extensions, testGroup, requiredFeatures);
                }
        }
 }
@@ -2221,8 +2222,8 @@ void addGraphics16BitStorageInputOutputInt16To32Group (tcu::TestCaseGroup* testG
                {"vector_uint", vecIfOpFunc,    vecPreMain,             "v4u32",        "v4u16",        "0",    "OpUConvert",   4 * 4,  4},
        };
 
-       ExtensionFeatures       extensionFeatures;
-       extensionFeatures.ext16BitStorage = EXT16BITSTORAGEFEATURES_INPUT_OUTPUT;
+       VulkanFeatures  requiredFeatures;
+       requiredFeatures.ext16BitStorage = EXT16BITSTORAGEFEATURES_INPUT_OUTPUT;
 
        for (deUint32 caseIdx = 0; caseIdx < DE_LENGTH_OF_ARRAY(cases); ++caseIdx)
        {
@@ -2265,7 +2266,7 @@ void addGraphics16BitStorageInputOutputInt16To32Group (tcu::TestCaseGroup* testG
                                interfaces.setInputOutput(std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_UINT16), BufferSp(new Int16Buffer(subInputs))),
                                                                                  std::make_pair(IFDataType(cases[caseIdx].numElements, NUMBERTYPE_UINT32), BufferSp(new Int32Buffer(subOutputs))));
                        }
-                       createTestsForAllStages(testName, defaultColors, defaultColors, fragments, interfaces, extensions, testGroup, extensionFeatures);
+                       createTestsForAllStages(testName, defaultColors, defaultColors, fragments, interfaces, extensions, testGroup, requiredFeatures);
                }
        }
 }
@@ -2281,14 +2282,14 @@ void addGraphics16BitStoragePushConstantFloat16To32Group (tcu::TestCaseGroup* te
        const deUint32                                          numDataPoints           = 64;
        vector<deFloat16>                                       float16Data                     (getFloat16s(rnd, numDataPoints));
        vector<float>                                           float32Data;
-       ExtensionFeatures               extensionFeatures;
+       VulkanFeatures                                          requiredFeatures;
 
        float32Data.reserve(numDataPoints);
        for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
                float32Data.push_back(deFloat16To32(float16Data[numIdx]));
 
        extensions.push_back("VK_KHR_16bit_storage");
-       extensionFeatures.ext16BitStorage = EXT16BITSTORAGEFEATURES_PUSH_CONSTANT;
+       requiredFeatures.ext16BitStorage = EXT16BITSTORAGEFEATURES_PUSH_CONSTANT;
 
        fragments["capability"]                         = "OpCapability StoragePushConstant16\n";
        fragments["extension"]                          = "OpExtension \"SPV_KHR_16bit_storage\"";
@@ -2372,7 +2373,7 @@ void addGraphics16BitStoragePushConstantFloat16To32Group (tcu::TestCaseGroup* te
 
                fragments["testfun"]    = testFun.specialize(specs);
 
-               createTestsForAllStages("scalar", defaultColors, defaultColors, fragments, pcs, resources, extensions, testGroup, extensionFeatures);
+               createTestsForAllStages("scalar", defaultColors, defaultColors, fragments, pcs, resources, extensions, testGroup, requiredFeatures);
        }
 
        {  // Vector cases
@@ -2411,7 +2412,7 @@ void addGraphics16BitStoragePushConstantFloat16To32Group (tcu::TestCaseGroup* te
 
                fragments["testfun"]    = testFun.specialize(specs);
 
-               createTestsForAllStages("vector", defaultColors, defaultColors, fragments, pcs, resources, extensions, testGroup, extensionFeatures);
+               createTestsForAllStages("vector", defaultColors, defaultColors, fragments, pcs, resources, extensions, testGroup, requiredFeatures);
        }
 
        {  // Matrix cases
@@ -2463,7 +2464,7 @@ void addGraphics16BitStoragePushConstantFloat16To32Group (tcu::TestCaseGroup* te
 
                fragments["testfun"]    = testFun.specialize(specs);
 
-               createTestsForAllStages("matrix", defaultColors, defaultColors, fragments, pcs, resources, extensions, testGroup, extensionFeatures);
+               createTestsForAllStages("matrix", defaultColors, defaultColors, fragments, pcs, resources, extensions, testGroup, requiredFeatures);
        }
 }
 
@@ -2481,7 +2482,7 @@ void addGraphics16BitStoragePushConstantInt16To32Group (tcu::TestCaseGroup* test
        vector<string>                                          extensions;
        const deUint16                                          signBitMask                     = 0x8000;
        const deUint32                                          signExtendMask          = 0xffff0000;
-       ExtensionFeatures               extensionFeatures;
+       VulkanFeatures                                          requiredFeatures;
 
        sOutputs.reserve(inputs.size());
        uOutputs.reserve(inputs.size());
@@ -2496,7 +2497,7 @@ void addGraphics16BitStoragePushConstantInt16To32Group (tcu::TestCaseGroup* test
        }
 
        extensions.push_back("VK_KHR_16bit_storage");
-       extensionFeatures.ext16BitStorage = EXT16BITSTORAGEFEATURES_PUSH_CONSTANT;
+       requiredFeatures.ext16BitStorage = EXT16BITSTORAGEFEATURES_PUSH_CONSTANT;
 
        fragments["capability"]                         = "OpCapability StoragePushConstant16\n";
        fragments["extension"]                          = "OpExtension \"SPV_KHR_16bit_storage\"";
@@ -2580,7 +2581,7 @@ void addGraphics16BitStoragePushConstantInt16To32Group (tcu::TestCaseGroup* test
 
                        resources.outputs.clear();
                        resources.outputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Int32Buffer(sOutputs))));
-                       createTestsForAllStages("sint_scalar", defaultColors, defaultColors, fragments, pcs, resources, extensions, testGroup, extensionFeatures);
+                       createTestsForAllStages("sint_scalar", defaultColors, defaultColors, fragments, pcs, resources, extensions, testGroup, requiredFeatures);
                }
                {  // signed int
                        map<string, string>             specs;
@@ -2597,7 +2598,7 @@ void addGraphics16BitStoragePushConstantInt16To32Group (tcu::TestCaseGroup* test
 
                        resources.outputs.clear();
                        resources.outputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Int32Buffer(uOutputs))));
-                       createTestsForAllStages("uint_scalar", defaultColors, defaultColors, fragments, pcs, resources, extensions, testGroup, extensionFeatures);
+                       createTestsForAllStages("uint_scalar", defaultColors, defaultColors, fragments, pcs, resources, extensions, testGroup, requiredFeatures);
                }
        }
 
@@ -2643,7 +2644,7 @@ void addGraphics16BitStoragePushConstantInt16To32Group (tcu::TestCaseGroup* test
 
                        resources.outputs.clear();
                        resources.outputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Int32Buffer(sOutputs))));
-                       createTestsForAllStages("sint_vector", defaultColors, defaultColors, fragments, pcs, resources, extensions, testGroup, extensionFeatures);
+                       createTestsForAllStages("sint_vector", defaultColors, defaultColors, fragments, pcs, resources, extensions, testGroup, requiredFeatures);
                }
                {  // signed int
                        map<string, string>             specs;
@@ -2661,7 +2662,7 @@ void addGraphics16BitStoragePushConstantInt16To32Group (tcu::TestCaseGroup* test
 
                        resources.outputs.clear();
                        resources.outputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Int32Buffer(uOutputs))));
-                       createTestsForAllStages("uint_vector", defaultColors, defaultColors, fragments, pcs, resources, extensions, testGroup, extensionFeatures);
+                       createTestsForAllStages("uint_vector", defaultColors, defaultColors, fragments, pcs, resources, extensions, testGroup, requiredFeatures);
                }
        }
 }
index 6d485d5..c727aa3 100644 (file)
@@ -329,9 +329,15 @@ tcu::TestStatus SpvAsmComputeShaderInstance::iterate (void)
 
                // 16bit storage features
                {
-                       if (!is16BitStorageFeaturesSupported(vki, physicalDevice, m_context.getInstanceExtensions(), m_shaderSpec.requestedExtensionFeatures.ext16BitStorage))
+                       if (!is16BitStorageFeaturesSupported(vki, physicalDevice, m_context.getInstanceExtensions(), m_shaderSpec.requestedVulkanFeatures.ext16BitStorage))
                                TCU_THROW(NotSupportedError, "Requested 16bit storage features not supported");
                }
+
+               // VariablePointers features
+               {
+                       if (!isVariablePointersFeaturesSupported(vki, physicalDevice, m_context.getInstanceExtensions(), m_shaderSpec.requestedVulkanFeatures.extVariablePointers))
+                               TCU_THROW(NotSupportedError, "Request Variable Pointer feature not supported");
+               }
        }
 
        // defer device and resource creation until after feature checks
index 2461756..1e89644 100644 (file)
@@ -109,7 +109,7 @@ struct ComputeShaderSpec
        std::vector<deUint32>                                   specConstants;
        BufferSp                                                                pushConstants;
        std::vector<std::string>                                extensions;
-       ExtensionFeatures                                               requestedExtensionFeatures;
+       VulkanFeatures                                                  requestedVulkanFeatures;
        qpTestResult                                                    failResult;
        std::string                                                             failMessage;
        // If null, a default verification will be performed by comparing the memory pointed to by outputAllocations
@@ -121,7 +121,7 @@ struct ComputeShaderSpec
                                                                                        ComputeShaderSpec (void)
                                                                                                : entryPoint                                    ("main")
                                                                                                , pushConstants                                 (DE_NULL)
-                                                                                               , requestedExtensionFeatures    ()
+                                                                                               , requestedVulkanFeatures               ()
                                                                                                , failResult                                    (QP_TEST_RESULT_FAIL)
                                                                                                , failMessage                                   ("Output doesn't match with expected")
                                                                                                , verifyIO                                              (DE_NULL)
index cb1f629..861af34 100644 (file)
@@ -233,15 +233,17 @@ InstanceContext::InstanceContext (const RGBA                                              (&inputs)[4],
                                                                  const GraphicsInterfaces&                     interfaces_,
                                                                  const vector<string>&                         extensions_,
                                                                  const vector<string>&                         features_,
-                                                                 ExtensionFeatures                                     extensionFeatures_)
+                                                                 VulkanFeatures                                        vulkanFeatures_,
+                                                                 VkShaderStageFlags                            customizedStages_)
        : testCodeFragments                             (testCodeFragments_)
        , specConstants                                 (specConstants_)
        , hasTessellation                               (false)
        , requiredStages                                (static_cast<VkShaderStageFlagBits>(0))
        , requiredDeviceExtensions              (extensions_)
        , requiredDeviceFeatures                (features_)
-       , requestedExtensionFeatures    (extensionFeatures_)
+       , requestedFeatures                             (vulkanFeatures_)
        , pushConstants                                 (pushConsants_)
+       , customizedStages                              (customizedStages_)
        , resources                                             (resources_)
        , interfaces                                    (interfaces_)
        , failResult                                    (QP_TEST_RESULT_FAIL)
@@ -266,8 +268,9 @@ InstanceContext::InstanceContext (const InstanceContext& other)
        , requiredStages                                (other.requiredStages)
        , requiredDeviceExtensions              (other.requiredDeviceExtensions)
        , requiredDeviceFeatures                (other.requiredDeviceFeatures)
-       , requestedExtensionFeatures    (other.requestedExtensionFeatures)
+       , requestedFeatures                             (other.requestedFeatures)
        , pushConstants                                 (other.pushConstants)
+       , customizedStages                              (other.customizedStages)
        , resources                                             (other.resources)
        , interfaces                                    (other.interfaces)
        , failResult                                    (other.failResult)
@@ -798,8 +801,20 @@ string makeTessEvalShaderAssembly(const map<string, string>& fragments)
                "%isUniqueIdZero = OpFunction %bool None %bool_function\n"
                "%getId_label = OpLabel\n"
                "%primitive_id = OpLoad %i32 %BP_gl_PrimitiveID\n"
-               "%is_id_0 = OpIEqual %bool %primitive_id %c_i32_0\n"
-               "OpReturnValue %is_id_0\n"
+               "%is_primitive_0 = OpIEqual %bool %primitive_id %c_i32_0\n"
+               "%TC_0_loc = OpAccessChain %ip_f32 %BP_gl_TessCoord %c_u32_0\n"
+               "%TC_1_loc = OpAccessChain %ip_f32 %BP_gl_TessCoord %c_u32_1\n"
+               "%TC_2_loc = OpAccessChain %ip_f32 %BP_gl_TessCoord %c_u32_2\n"
+               "%TC_W_0 = OpLoad %f32 %TC_0_loc\n"
+               "%TC_W_1 = OpLoad %f32 %TC_1_loc\n"
+               "%TC_W_2 = OpLoad %f32 %TC_2_loc\n"
+               "%is_W_0_1 = OpFOrdEqual %bool %TC_W_0 %c_f32_1\n"
+               "%is_W_1_0 = OpFOrdEqual %bool %TC_W_1 %c_f32_0\n"
+               "%is_W_2_0 = OpFOrdEqual %bool %TC_W_2 %c_f32_0\n"
+               "%is_tessCoord_1_0 = OpLogicalAnd %bool %is_W_0_1 %is_W_1_0\n"
+               "%is_tessCoord_1_0_0 = OpLogicalAnd %bool %is_tessCoord_1_0 %is_W_2_0\n"
+               "%is_unique_id_0 = OpLogicalAnd %bool %is_tessCoord_1_0_0 %is_primitive_0\n"
+               "OpReturnValue %is_unique_id_0\n"
                "OpFunctionEnd\n"
 
                "${testfun}\n";
@@ -874,12 +889,15 @@ string makeGeometryShaderAssembly(const map<string, string>& fragments)
                "%BP_per_vertex_in = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
                "%BP_a3_per_vertex_in = OpTypeArray %BP_per_vertex_in %c_u32_3\n"
                "%BP_ip_a3_per_vertex_in = OpTypePointer Input %BP_a3_per_vertex_in\n"
+               "%BP_pp_i32 = OpTypePointer Private %i32\n"
+               "%BP_pp_v4i32 = OpTypePointer Private %v4i32\n"
 
                "%BP_gl_in = OpVariable %BP_ip_a3_per_vertex_in Input\n"
                "%BP_out_color = OpVariable %op_v4f32 Output\n"
                "%BP_in_color = OpVariable %ip_a3v4f32 Input\n"
                "%BP_gl_PrimitiveID = OpVariable %ip_i32 Input\n"
                "%BP_out_gl_position = OpVariable %op_v4f32 Output\n"
+               "%BP_vertexIdInCurrentPatch = OpVariable %BP_pp_v4i32 Private\n"
                "${pre_main:opt}\n"
                "${IF_variable:opt}\n"
 
@@ -888,6 +906,9 @@ string makeGeometryShaderAssembly(const map<string, string>& fragments)
 
                "${IF_carryforward:opt}\n"
 
+               "%BP_primitiveId = OpLoad %i32 %BP_gl_PrimitiveID\n"
+               "%BP_addr_vertexIdInCurrentPatch = OpAccessChain %BP_pp_i32 %BP_vertexIdInCurrentPatch %BP_primitiveId\n"
+
                "%BP_gl_in_0_gl_position = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_0 %c_i32_0\n"
                "%BP_gl_in_1_gl_position = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_1 %c_i32_0\n"
                "%BP_gl_in_2_gl_position = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_2 %c_i32_0\n"
@@ -904,8 +925,11 @@ string makeGeometryShaderAssembly(const map<string, string>& fragments)
                "%BP_in_color_1 = OpLoad %v4f32 %BP_in_color_1_ptr\n"
                "%BP_in_color_2 = OpLoad %v4f32 %BP_in_color_2_ptr\n"
 
+               "OpStore %BP_addr_vertexIdInCurrentPatch %c_i32_0\n"
                "%BP_transformed_in_color_0 = OpFunctionCall %v4f32 %test_code %BP_in_color_0\n"
+               "OpStore %BP_addr_vertexIdInCurrentPatch %c_i32_1\n"
                "%BP_transformed_in_color_1 = OpFunctionCall %v4f32 %test_code %BP_in_color_1\n"
+               "OpStore %BP_addr_vertexIdInCurrentPatch %c_i32_2\n"
                "%BP_transformed_in_color_2 = OpFunctionCall %v4f32 %test_code %BP_in_color_2\n"
 
 
@@ -929,8 +953,12 @@ string makeGeometryShaderAssembly(const map<string, string>& fragments)
                "%isUniqueIdZero = OpFunction %bool None %bool_function\n"
                "%getId_label = OpLabel\n"
                "%primitive_id = OpLoad %i32 %BP_gl_PrimitiveID\n"
-               "%is_id_0 = OpIEqual %bool %primitive_id %c_i32_0\n"
-               "OpReturnValue %is_id_0\n"
+               "%addr_vertexIdInCurrentPatch = OpAccessChain %BP_pp_i32 %BP_vertexIdInCurrentPatch %primitive_id\n"
+               "%vertexIdInCurrentPatch = OpLoad %i32 %addr_vertexIdInCurrentPatch\n"
+               "%is_primitive_0 = OpIEqual %bool %primitive_id %c_i32_0\n"
+               "%is_vertex_0 = OpIEqual %bool %vertexIdInCurrentPatch %c_i32_0\n"
+               "%is_unique_id_0 = OpLogicalAnd %bool %is_primitive_0 %is_vertex_0\n"
+               "OpReturnValue %is_unique_id_0\n"
                "OpFunctionEnd\n"
 
                "${testfun}\n";
@@ -2188,10 +2216,35 @@ TestStatus runAndVerifyDefaultPipeline (Context& context, InstanceContext instan
 
        // 16bit storage features
        {
-               if (!is16BitStorageFeaturesSupported(vkInstance, vkPhysicalDevice, context.getInstanceExtensions(), instance.requestedExtensionFeatures.ext16BitStorage))
+               if (!is16BitStorageFeaturesSupported(vkInstance, vkPhysicalDevice, context.getInstanceExtensions(), instance.requestedFeatures.ext16BitStorage))
                        TCU_THROW(NotSupportedError, "Requested 16bit storage features not supported");
        }
 
+       // Variable Pointers features
+       {
+               if (!isVariablePointersFeaturesSupported(vkInstance, vkPhysicalDevice, context.getInstanceExtensions(), instance.requestedFeatures.extVariablePointers))
+                       TCU_THROW(NotSupportedError, "Requested Variable Pointer features not supported");
+
+               if (instance.requestedFeatures.extVariablePointers)
+               {
+                       // The device doesn't have the vertexPipelineStoresAndAtomics feature, but the test requires the feature for
+                       // vertex, tesselation, and geometry stages.
+                       if (features.vertexPipelineStoresAndAtomics == DE_FALSE &&
+                               instance.requestedFeatures.coreFeatures.vertexPipelineStoresAndAtomics == DE_TRUE &&
+                           (instance.customizedStages & vk::VK_SHADER_STAGE_VERTEX_BIT ||
+                                instance.customizedStages & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT ||
+                                instance.customizedStages & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT ||
+                                instance.customizedStages & vk::VK_SHADER_STAGE_GEOMETRY_BIT))
+                               TCU_THROW(NotSupportedError, "This VK_KHR_variable_pointers extension test requires vertexPipelineStoresAndAtomics device feature.");
+
+                       // The device doesn't have the fragmentStoresAndAtomics feature, but the test requires this feature for the fragment stage.
+                       if (features.fragmentStoresAndAtomics == DE_FALSE &&
+                           instance.requestedFeatures.coreFeatures.fragmentStoresAndAtomics == DE_TRUE &&
+                               instance.customizedStages & vk::VK_SHADER_STAGE_FRAGMENT_BIT)
+                               TCU_THROW(NotSupportedError, "This VK_KHR_variable_pointers extension test requires fragmentStoresAndAtomics device feature.");
+               }
+       }
+
        // defer device and other resource creation until after feature checks
        const Unique<VkDevice>                                          vkDevice                                (createDeviceWithExtensions(context, queueFamilyIndex, context.getDeviceExtensions(), instance.requiredDeviceExtensions));
        const DeviceDriver                                                      vk                                              (vkInstance, *vkDevice);
@@ -3479,7 +3532,7 @@ void createTestsForAllStages (const std::string&                  name,
                                                          const GraphicsInterfaces&             interfaces,
                                                          const vector<string>&                 extensions,
                                                          const vector<string>&                 features,
-                                                         ExtensionFeatures                             extensionFeatures,
+                                                         VulkanFeatures                                vulkanFeatures,
                                                          tcu::TestCaseGroup*                   tests,
                                                          const qpTestResult                    failResult,
                                                          const string&                                 failMessageTemplate)
@@ -3511,35 +3564,35 @@ void createTestsForAllStages (const std::string&                        name,
        addFunctionCaseWithPrograms<InstanceContext>(
                        tests, name + "_vert", "", addShaderCodeCustomVertex, runAndVerifyDefaultPipeline,
                        createInstanceContext(vertFragPipelineStages, inputColors, outputColors, testCodeFragments,
-                               specConstantMap, pushConstants, resources, interfaces, extensions, features, extensionFeatures, failResult, failMessageTemplate));
+                               specConstantMap, pushConstants, resources, interfaces, extensions, features, vulkanFeatures, vk::VK_SHADER_STAGE_VERTEX_BIT, failResult, failMessageTemplate));
 
        specConstantMap.clear();
        specConstantMap[VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT] = specConstants;
        addFunctionCaseWithPrograms<InstanceContext>(
                        tests, name + "_tessc", "", addShaderCodeCustomTessControl, runAndVerifyDefaultPipeline,
                        createInstanceContext(tessPipelineStages, inputColors, outputColors, testCodeFragments,
-                               specConstantMap, pushConstants, resources, interfaces, extensions, features, extensionFeatures, failResult, failMessageTemplate));
+                               specConstantMap, pushConstants, resources, interfaces, extensions, features, vulkanFeatures, vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, failResult, failMessageTemplate));
 
        specConstantMap.clear();
        specConstantMap[VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT] = specConstants;
        addFunctionCaseWithPrograms<InstanceContext>(
                        tests, name + "_tesse", "", addShaderCodeCustomTessEval, runAndVerifyDefaultPipeline,
                        createInstanceContext(tessPipelineStages, inputColors, outputColors, testCodeFragments,
-                               specConstantMap, pushConstants, resources, interfaces, extensions, features, extensionFeatures, failResult, failMessageTemplate));
+                               specConstantMap, pushConstants, resources, interfaces, extensions, features, vulkanFeatures, vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, failResult, failMessageTemplate));
 
        specConstantMap.clear();
        specConstantMap[VK_SHADER_STAGE_GEOMETRY_BIT] = specConstants;
        addFunctionCaseWithPrograms<InstanceContext>(
                        tests, name + "_geom", "", addShaderCodeCustomGeometry, runAndVerifyDefaultPipeline,
                        createInstanceContext(geomPipelineStages, inputColors, outputColors, testCodeFragments,
-                               specConstantMap, pushConstants, resources, interfaces, extensions, features, extensionFeatures, failResult, failMessageTemplate));
+                               specConstantMap, pushConstants, resources, interfaces, extensions, features, vulkanFeatures, vk::VK_SHADER_STAGE_GEOMETRY_BIT, failResult, failMessageTemplate));
 
        specConstantMap.clear();
        specConstantMap[VK_SHADER_STAGE_FRAGMENT_BIT] = specConstants;
        addFunctionCaseWithPrograms<InstanceContext>(
                        tests, name + "_frag", "", addShaderCodeCustomFragment, runAndVerifyDefaultPipeline,
                        createInstanceContext(vertFragPipelineStages, inputColors, outputColors, testCodeFragments,
-                               specConstantMap, pushConstants, resources, interfaces, extensions, features, extensionFeatures, failResult, failMessageTemplate));
+                               specConstantMap, pushConstants, resources, interfaces, extensions, features, vulkanFeatures, vk::VK_SHADER_STAGE_FRAGMENT_BIT, failResult, failMessageTemplate));
 }
 
 void addTessCtrlTest(tcu::TestCaseGroup* group, const char* name, const map<string, string>& fragments)
@@ -3560,7 +3613,7 @@ void addTessCtrlTest(tcu::TestCaseGroup* group, const char* name, const map<stri
                                pipelineStages, defaultColors, defaultColors, fragments,
                                StageToSpecConstantMap(), PushConstants(), GraphicsResources(),
                                GraphicsInterfaces(), vector<string>(), vector<string>(),
-                               ExtensionFeatures()));
+                               VulkanFeatures(), vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT));
 }
 
 } // SpirVAssembly
index de253af..b1b93c0 100644 (file)
@@ -254,8 +254,10 @@ struct InstanceContext
        vk::VkShaderStageFlagBits                               requiredStages;
        std::vector<std::string>                                requiredDeviceExtensions;
        std::vector<std::string>                                requiredDeviceFeatures;
-       ExtensionFeatures                                               requestedExtensionFeatures;
+       VulkanFeatures                                                  requestedFeatures;
        PushConstants                                                   pushConstants;
+       // Specifies the (one or more) stages that use a customized shader code.
+       VkShaderStageFlags                                              customizedStages;
        // Possible resources used by the graphics pipeline.
        // If it is not empty, a single descriptor set (number 0) will be allocated
        // to point to all resources specified. Binding numbers are allocated in
@@ -280,7 +282,8 @@ struct InstanceContext
                                         const GraphicsInterfaces&                                      interfaces_,
                                         const std::vector<std::string>&                        extensions_,
                                         const std::vector<std::string>&                        features_,
-                                        ExtensionFeatures                                                      extFeatures_);
+                                        VulkanFeatures                                                         vulkanFeatures_,
+                                        VkShaderStageFlags                                                     customizedStages_);
 
        InstanceContext (const InstanceContext& other);
 
@@ -354,11 +357,12 @@ InstanceContext createInstanceContext (const ShaderElement                                                        (&elements)[N],
                                                                           const GraphicsInterfaces&                                    interfaces,
                                                                           const std::vector<std::string>&                              extensions,
                                                                           const std::vector<std::string>&                              features,
-                                                                          ExtensionFeatures                                                    extensionFeatures,
+                                                                          VulkanFeatures                                                               vulkanFeatures,
+                                                                          VkShaderStageFlags                                                   customizedStages,
                                                                           const qpTestResult                                                   failResult                      = QP_TEST_RESULT_FAIL,
                                                                           const std::string&                                                   failMessageTemplate     = std::string())
 {
-       InstanceContext ctx (inputColors, outputColors, testCodeFragments, specConstants, pushConstants, resources, interfaces, extensions, features, extensionFeatures);
+       InstanceContext ctx (inputColors, outputColors, testCodeFragments, specConstants, pushConstants, resources, interfaces, extensions, features, vulkanFeatures, customizedStages);
        for (size_t i = 0; i < N; ++i)
        {
                ctx.moduleMap[elements[i].moduleName].push_back(std::make_pair(elements[i].entryName, elements[i].stage));
@@ -380,7 +384,7 @@ inline InstanceContext createInstanceContext (const ShaderElement                                           (&element
        return createInstanceContext(elements, inputColors, outputColors, testCodeFragments,
                                                                 StageToSpecConstantMap(), PushConstants(), GraphicsResources(),
                                                                 GraphicsInterfaces(), std::vector<std::string>(), std::vector<std::string>(),
-                                                                ExtensionFeatures());
+                                                                VulkanFeatures(), vk::VK_SHADER_STAGE_ALL);
 }
 
 // The same as createInstanceContext above, but with default colors.
@@ -404,7 +408,7 @@ void createTestsForAllStages (const std::string&                                            name,
                                                          const GraphicsInterfaces&                                     interfaces,
                                                          const std::vector<std::string>&                       extensions,
                                                          const std::vector<std::string>&                       features,
-                                                         ExtensionFeatures                                                     extensionFeatures,
+                                                         VulkanFeatures                                                        vulkanFeatures,
                                                          tcu::TestCaseGroup*                                           tests,
                                                          const qpTestResult                                            failResult                      = QP_TEST_RESULT_FAIL,
                                                          const std::string&                                            failMessageTemplate     = std::string());
@@ -426,7 +430,7 @@ inline void createTestsForAllStages (const std::string&                                                     name,
 
        createTestsForAllStages(
                        name, inputColors, outputColors, testCodeFragments, noSpecConstants, noPushConstants,
-                       noResources, noInterfaces, noExtensions, noFeatures, ExtensionFeatures(),
+                       noResources, noInterfaces, noExtensions, noFeatures, VulkanFeatures(),
                        tests, failResult, failMessageTemplate);
 }
 
@@ -447,7 +451,7 @@ inline void createTestsForAllStages (const std::string&                                                     name,
 
        createTestsForAllStages(
                        name, inputColors, outputColors, testCodeFragments, specConstants, noPushConstants,
-                       noResources, noInterfaces, noExtensions, noFeatures, ExtensionFeatures(),
+                       noResources, noInterfaces, noExtensions, noFeatures, VulkanFeatures(),
                        tests, failResult, failMessageTemplate);
 }
 
@@ -458,7 +462,7 @@ inline void createTestsForAllStages (const std::string&                                                     name,
                                                                         const GraphicsResources&                                       resources,
                                                                         const std::vector<std::string>&                        extensions,
                                                                         tcu::TestCaseGroup*                                            tests,
-                                                                        ExtensionFeatures                                                      extensionFeatures       = ExtensionFeatures(),
+                                                                        VulkanFeatures                                                         vulkanFeatures          = VulkanFeatures(),
                                                                         const qpTestResult                                                     failResult                      = QP_TEST_RESULT_FAIL,
                                                                         const std::string&                                                     failMessageTemplate     = std::string())
 {
@@ -469,7 +473,7 @@ inline void createTestsForAllStages (const std::string&                                                     name,
 
        createTestsForAllStages(
                        name, inputColors, outputColors, testCodeFragments, noSpecConstants, noPushConstants,
-                       resources, noInterfaces, extensions, noFeatures, extensionFeatures,
+                       resources, noInterfaces, extensions, noFeatures, vulkanFeatures,
                        tests, failResult, failMessageTemplate);
 }
 
@@ -480,7 +484,7 @@ inline void createTestsForAllStages (const std::string& name,
                                                                         const GraphicsInterfaces                                       interfaces,
                                                                         const std::vector<std::string>&                        extensions,
                                                                         tcu::TestCaseGroup*                                            tests,
-                                                                        ExtensionFeatures                                                      extensionFeatures       = ExtensionFeatures(),
+                                                                        VulkanFeatures                                                         vulkanFeatures          = VulkanFeatures(),
                                                                         const qpTestResult                                                     failResult                      = QP_TEST_RESULT_FAIL,
                                                                         const std::string&                                                     failMessageTemplate     = std::string())
 {
@@ -491,7 +495,7 @@ inline void createTestsForAllStages (const std::string& name,
 
        createTestsForAllStages(
                        name, inputColors, outputColors, testCodeFragments, noSpecConstants, noPushConstants,
-                       noResources, interfaces, extensions, noFeatures, extensionFeatures,
+                       noResources, interfaces, extensions, noFeatures, vulkanFeatures,
                        tests, failResult, failMessageTemplate);
 }
 
@@ -503,7 +507,7 @@ inline void createTestsForAllStages (const std::string& name,
                                                                         const GraphicsResources&                                       resources,
                                                                         const std::vector<std::string>&                        extensions,
                                                                         tcu::TestCaseGroup*                                            tests,
-                                                                        ExtensionFeatures                                                      extensionFeatures       = ExtensionFeatures(),
+                                                                        VulkanFeatures                                                         vulkanFeatures          = VulkanFeatures(),
                                                                         const qpTestResult                                                     failResult                      = QP_TEST_RESULT_FAIL,
                                                                         const std::string&                                                     failMessageTemplate     = std::string())
 {
@@ -513,7 +517,7 @@ inline void createTestsForAllStages (const std::string& name,
 
        createTestsForAllStages(
                        name, inputColors, outputColors, testCodeFragments, noSpecConstants, pushConstants,
-                       resources, noInterfaces, extensions, noFeatures, extensionFeatures,
+                       resources, noInterfaces, extensions, noFeatures, vulkanFeatures,
                        tests, failResult, failMessageTemplate);
 }
 
index 7b89dcc..714b0b0 100644 (file)
@@ -53,6 +53,7 @@
 #include "vktSpvAsmComputeShaderCase.hpp"
 #include "vktSpvAsmComputeShaderTestUtil.hpp"
 #include "vktSpvAsmGraphicsShaderTestUtil.hpp"
+#include "vktSpvAsmVariablePointersTests.hpp"
 #include "vktTestCaseUtil.hpp"
 
 #include <cmath>
@@ -7439,7 +7440,7 @@ tcu::TestCaseGroup* createInstructionTests (tcu::TestContext& testCtx)
        computeTests->addChild(createShaderDefaultOutputGroup(testCtx));
 
        computeTests->addChild(create16BitStorageComputeGroup(testCtx));
-
+       computeTests->addChild(createVariablePointersComputeGroup(testCtx));
        {
                de::MovePtr<tcu::TestCaseGroup> computeAndroidTests     (new tcu::TestCaseGroup(testCtx, "android", "Android CTS Tests"));
 
@@ -7483,6 +7484,7 @@ tcu::TestCaseGroup* createInstructionTests (tcu::TestContext& testCtx)
        }
 
        graphicsTests->addChild(create16BitStorageGraphicsGroup(testCtx));
+       graphicsTests->addChild(createVariablePointersGraphicsGroup(testCtx));
 
        instructionTests->addChild(computeTests.release());
        instructionTests->addChild(graphicsTests.release());
index 8966e67..cadebe6 100644 (file)
@@ -74,6 +74,30 @@ VkPhysicalDevice16BitStorageFeaturesKHR      querySupported16BitStorageFeatures (cons
        return extensionFeatures;
 }
 
+VkPhysicalDeviceVariablePointerFeaturesKHR querySupportedVariablePointersFeatures (const InstanceInterface& vki, VkPhysicalDevice device, const std::vector<std::string>& instanceExtensions)
+{
+       VkPhysicalDeviceVariablePointerFeaturesKHR extensionFeatures    =
+       {
+               VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR,        // sType
+               DE_NULL,                                                                                                                        // pNext
+               false,                                                                                                                          // variablePointersStorageBuffer
+               false,                                                                                                                          // variablePointers
+       };
+
+       VkPhysicalDeviceFeatures2KHR    features;
+       deMemset(&features, 0, sizeof(features));
+       features.sType  = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR;
+       features.pNext  = &extensionFeatures;
+
+       // Call the getter only if supported. Otherwise above "zero" defaults are used
+       if (de::contains(instanceExtensions.begin(), instanceExtensions.end(), "VK_KHR_get_physical_device_properties2"))
+       {
+               vki.getPhysicalDeviceFeatures2KHR(device, &features);
+       }
+
+       return extensionFeatures;
+}
+
 } // anonymous
 
 bool is16BitStorageFeaturesSupported (const InstanceInterface& vki, VkPhysicalDevice device, const std::vector<std::string>& instanceExtensions, Extension16BitStorageFeatures toCheck)
@@ -95,15 +119,31 @@ bool is16BitStorageFeaturesSupported (const InstanceInterface& vki, VkPhysicalDe
        return true;
 }
 
+bool isVariablePointersFeaturesSupported (const InstanceInterface& vki, VkPhysicalDevice device, const std::vector<std::string>& instanceExtensions, ExtensionVariablePointersFeatures toCheck)
+{
+       VkPhysicalDeviceVariablePointerFeaturesKHR extensionFeatures = querySupportedVariablePointersFeatures(vki, device, instanceExtensions);
+
+       if ((toCheck & EXTVARIABLEPOINTERSFEATURES_VARIABLE_POINTERS_STORAGEBUFFER) != 0 && extensionFeatures.variablePointersStorageBuffer == VK_FALSE)
+               return false;
+
+       if ((toCheck & EXTVARIABLEPOINTERSFEATURES_VARIABLE_POINTERS) != 0 && extensionFeatures.variablePointers == VK_FALSE)
+               return false;
+
+       return true;
+}
+
 Move<VkDevice> createDeviceWithExtensions (Context&                                                    context,
                                                                                   const deUint32                                       queueFamilyIndex,
                                                                                   const std::vector<std::string>&      supportedExtensions,
                                                                                   const std::vector<std::string>&      requiredExtensions)
 {
-       const InstanceInterface&                vki                                                             = context.getInstanceInterface();
-       const VkPhysicalDevice                  physicalDevice                                  = context.getPhysicalDevice();
-       std::vector<const char*>                extensions                                              (requiredExtensions.size());
-       bool                                                    requires16BitStorageExtension   = false;
+       const InstanceInterface&                                        vki                                                     = context.getInstanceInterface();
+       const VkPhysicalDevice                                          physicalDevice                          = context.getPhysicalDevice();
+       std::vector<const char*>                                        extensions                                      (requiredExtensions.size());
+       void*                                                                           pExtension                                      = DE_NULL;
+       const VkPhysicalDeviceFeatures                          deviceFeatures                          = getPhysicalDeviceFeatures(vki, physicalDevice);
+       VkPhysicalDevice16BitStorageFeaturesKHR         ext16BitStorageFeatures;
+       VkPhysicalDeviceVariablePointerFeaturesKHR      extVariablePointerFeatures;
 
        for (deUint32 extNdx = 0; extNdx < requiredExtensions.size(); ++extNdx)
        {
@@ -115,19 +155,25 @@ Move<VkDevice> createDeviceWithExtensions (Context&                                                       context,
                        TCU_THROW(NotSupportedError, (std::string("Device extension not supported: ") + ext).c_str());
                }
 
+               // Currently don't support enabling multiple extensions at the same time.
                if (ext == "VK_KHR_16bit_storage")
                {
-                       requires16BitStorageExtension = true;
+                       // For the 16bit storage extension, we have four features to test. Requesting all features supported.
+                       // Note that we don't throw NotImplemented errors here if a specific feature is not supported;
+                       // that should be done when actually trying to use that specific feature.
+                       ext16BitStorageFeatures = querySupported16BitStorageFeatures(vki, physicalDevice, context.getInstanceExtensions());
+                       pExtension = &ext16BitStorageFeatures;
+               }
+               else if (ext == "VK_KHR_variable_pointers")
+               {
+                       // For the VariablePointers extension, we have two features to test. Requesting all features supported.
+                       extVariablePointerFeatures      = querySupportedVariablePointersFeatures(vki, physicalDevice, context.getInstanceExtensions());
+                       pExtension = &extVariablePointerFeatures;
                }
 
                extensions[extNdx] = ext.c_str();
        }
 
-       // For the 16bit storage extension, we have four features to test. Requesting all features supported.
-       // Note that we don't throw NotImplemented errors here if a specific feature is not supported;
-       // that should be done when actually trying to use that specific feature.
-       VkPhysicalDevice16BitStorageFeaturesKHR ext16BitStorageFeatures = querySupported16BitStorageFeatures(vki, physicalDevice, context.getInstanceExtensions());
-
        const float                                             queuePriorities[]       = { 1.0f };
        const VkDeviceQueueCreateInfo   queueInfos[]            =
        {
@@ -140,11 +186,11 @@ Move<VkDevice> createDeviceWithExtensions (Context&                                                       context,
                        &queuePriorities[0]
                }
        };
-       const VkPhysicalDeviceFeatures  features                        = filterDefaultDeviceFeatures(getPhysicalDeviceFeatures(vki, physicalDevice));
+       const VkPhysicalDeviceFeatures  features                        = filterDefaultDeviceFeatures(deviceFeatures);
        const VkDeviceCreateInfo                deviceParams            =
        {
                VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
-               (requires16BitStorageExtension ? &ext16BitStorageFeatures : DE_NULL),
+               pExtension,
                (VkDeviceCreateFlags)0,
                DE_LENGTH_OF_ARRAY(queueInfos),
                &queueInfos[0],
index f73d1c9..392dbb6 100644 (file)
@@ -46,15 +46,23 @@ enum Extension16BitStorageFeatureBits
 };
 typedef deUint32 Extension16BitStorageFeatures;
 
-struct ExtensionFeatures
+enum ExtensionVariablePointersFeaturesBits
 {
-       Extension16BitStorageFeatures   ext16BitStorage;
+       EXTVARIABLEPOINTERSFEATURES_VARIABLE_POINTERS_STORAGEBUFFER     = (1u << 1),
+       EXTVARIABLEPOINTERSFEATURES_VARIABLE_POINTERS                           = (1u << 2),
+};
+typedef deUint32 ExtensionVariablePointersFeatures;
 
-       ExtensionFeatures       (void)
-               : ext16BitStorage       (0)
-       {}
-       explicit ExtensionFeatures      (Extension16BitStorageFeatures  ext16BitStorage_)
-               : ext16BitStorage       (ext16BitStorage_)
+struct VulkanFeatures
+{
+       Extension16BitStorageFeatures           ext16BitStorage;
+       ExtensionVariablePointersFeatures       extVariablePointers;
+       vk::VkPhysicalDeviceFeatures            coreFeatures;
+
+       VulkanFeatures                          (void)
+               : ext16BitStorage               (0)
+               , extVariablePointers   (0)
+               , coreFeatures                  (vk::VkPhysicalDeviceFeatures())
        {}
 };
 
@@ -64,6 +72,12 @@ bool is16BitStorageFeaturesSupported (const vk::InstanceInterface&   vkInstance,
                                                                          const std::vector<std::string>& instanceExtensions,
                                                                          Extension16BitStorageFeatures toCheck);
 
+// Returns true if the given variable pointers extension features in `toCheck` are all supported.
+bool isVariablePointersFeaturesSupported (const vk::InstanceInterface&         vkInstance,
+                                                                                 vk::VkPhysicalDevice                          device,
+                                                                             const std::vector<std::string>&   instanceExtensions,
+                                                                                 ExtensionVariablePointersFeatures toCheck);
+
 // Creates a Vulkan logical device with the requiredExtensions enabled and all other extensions disabled.
 // The logical device will be created from the instance and physical device in the given context.
 // A single queue will be created from the given queue family.
diff --git a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmVariablePointersTests.cpp b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmVariablePointersTests.cpp
new file mode 100644 (file)
index 0000000..967ecd4
--- /dev/null
@@ -0,0 +1,869 @@
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2017 Google 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 SPIR-V Assembly Tests for the SPV_KHR_variable_pointers extension
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuFloat.hpp"
+#include "tcuRGBA.hpp"
+#include "tcuStringTemplate.hpp"
+#include "tcuTestLog.hpp"
+#include "tcuVectorUtil.hpp"
+
+#include "vkDefs.hpp"
+#include "vkDeviceUtil.hpp"
+#include "vkMemUtil.hpp"
+#include "vkPlatform.hpp"
+#include "vkPrograms.hpp"
+#include "vkQueryUtil.hpp"
+#include "vkRef.hpp"
+#include "vkRefUtil.hpp"
+#include "vkStrUtil.hpp"
+#include "vkTypeUtil.hpp"
+
+#include "deRandom.hpp"
+#include "deStringUtil.hpp"
+#include "deUniquePtr.hpp"
+#include "deMath.h"
+
+#include "vktSpvAsmComputeShaderCase.hpp"
+#include "vktSpvAsmComputeShaderTestUtil.hpp"
+#include "vktSpvAsmGraphicsShaderTestUtil.hpp"
+#include "vktSpvAsmVariablePointersTests.hpp"
+#include "vktTestCaseUtil.hpp"
+#include "vktTestGroupUtil.hpp"
+
+#include <limits>
+#include <map>
+#include <string>
+#include <sstream>
+#include <utility>
+
+namespace vkt
+{
+namespace SpirVAssembly
+{
+
+using namespace vk;
+using std::map;
+using std::string;
+using std::vector;
+using tcu::IVec3;
+using tcu::IVec4;
+using tcu::RGBA;
+using tcu::TestLog;
+using tcu::TestStatus;
+using tcu::Vec4;
+using de::UniquePtr;
+using tcu::StringTemplate;
+using tcu::Vec4;
+
+namespace
+{
+
+template<typename T>
+void fillRandomScalars (de::Random& rnd, T minValue, T maxValue, void* dst, int numValues, int offset = 0)
+{
+       T* const typedPtr = (T*)dst;
+       for (int ndx = 0; ndx < numValues; ndx++)
+               typedPtr[offset + ndx] = randomScalar<T>(rnd, minValue, maxValue);
+}
+
+void addComputeVariablePointersGroup (tcu::TestCaseGroup* group)
+{
+       tcu::TestContext&                               testCtx                                 = group->getTestContext();
+       de::Random                                              rnd                                             (deStringHash(group->getName()));
+       const int                                               seed                                    = testCtx.getCommandLine().getBaseSeed();
+       const int                                               numMuxes                                = 100;
+       std::string                                             inputArraySize                  = "200";
+       vector<float>                                   inputAFloats                    (2*numMuxes, 0);
+       vector<float>                                   inputBFloats                    (2*numMuxes, 0);
+       vector<float>                                   inputSFloats                    (numMuxes, 0);
+       vector<float>                                   AmuxAOutputFloats               (numMuxes, 0);
+       vector<float>                                   AmuxBOutputFloats               (numMuxes, 0);
+       vector<float>                                   incrAmuxAOutputFloats   (numMuxes, 0);
+       vector<float>                                   incrAmuxBOutputFloats   (numMuxes, 0);
+       VulkanFeatures                                  requiredFeatures;
+
+       // Each output entry is chosen as follows: ( 0 <= i < numMuxes)
+       // 1) For tests with one input buffer:  output[i] = (s[i] < 0) ? A[2*i] : A[2*i+1];
+       // 2) For tests with two input buffers: output[i] = (s[i] < 0) ? A[i]   : B[i];
+
+       fillRandomScalars(rnd, -100.f, 100.f, &inputAFloats[0], 2*numMuxes);
+       fillRandomScalars(rnd, -100.f, 100.f, &inputBFloats[0], 2*numMuxes);
+
+       // We want to guarantee that the S input has some positive and some negative values.
+       // We choose random negative numbers for the first half, random positive numbers for the second half, and then shuffle.
+       fillRandomScalars(rnd, -100.f, -1.f , &inputSFloats[0], numMuxes / 2);
+       fillRandomScalars(rnd, 1.f   , 100.f, &inputSFloats[numMuxes / 2], numMuxes / 2);
+       de::Random(seed).shuffle(inputSFloats.begin(), inputSFloats.end());
+
+       for (size_t i = 0; i < numMuxes; ++i)
+       {
+               AmuxAOutputFloats[i]     = (inputSFloats[i] < 0) ? inputAFloats[2*i]     : inputAFloats[2*i+1];
+               AmuxBOutputFloats[i]     = (inputSFloats[i] < 0) ? inputAFloats[i]               : inputBFloats[i];
+               incrAmuxAOutputFloats[i] = (inputSFloats[i] < 0) ? 1 + inputAFloats[2*i] : 1+ inputAFloats[2*i+1];
+               incrAmuxBOutputFloats[i] = (inputSFloats[i] < 0) ? 1 + inputAFloats[i]   : 1 + inputBFloats[i];
+       }
+
+       const StringTemplate shaderTemplate (
+               "OpCapability Shader\n"
+
+               "${ExtraCapability}\n"
+
+               "OpExtension \"SPV_KHR_variable_pointers\"\n"
+               "OpExtension \"SPV_KHR_storage_buffer_storage_class\"\n"
+               "OpMemoryModel Logical GLSL450\n"
+               "OpEntryPoint GLCompute %main \"main\" %id\n"
+               "OpExecutionMode %main LocalSize 1 1 1\n"
+
+               "OpSource GLSL 430\n"
+               "OpName %main           \"main\"\n"
+               "OpName %id             \"gl_GlobalInvocationID\"\n"
+
+               // Decorations
+               "OpDecorate %id BuiltIn GlobalInvocationId\n"
+               "OpDecorate %indata_a DescriptorSet 0\n"
+               "OpDecorate %indata_a Binding 0\n"
+               "OpDecorate %indata_b DescriptorSet 0\n"
+               "OpDecorate %indata_b Binding 1\n"
+               "OpDecorate %indata_s DescriptorSet 0\n"
+               "OpDecorate %indata_s Binding 2\n"
+               "OpDecorate %outdata DescriptorSet 0\n"
+               "OpDecorate %outdata Binding 3\n"
+               "OpDecorate %f32arr ArrayStride 4\n"
+               "OpDecorate %sb_f32ptr ArrayStride 4\n"
+               "OpDecorate %buf Block\n"
+               "OpMemberDecorate %buf 0 Offset 0\n"
+
+               + string(getComputeAsmCommonTypes()) +
+
+               "%sb_f32ptr                             = OpTypePointer StorageBuffer %f32\n"
+               "%buf                                   = OpTypeStruct %f32arr\n"
+               "%bufptr                                = OpTypePointer StorageBuffer %buf\n"
+               "%indata_a                              = OpVariable %bufptr StorageBuffer\n"
+               "%indata_b                              = OpVariable %bufptr StorageBuffer\n"
+               "%indata_s                              = OpVariable %bufptr StorageBuffer\n"
+               "%outdata                               = OpVariable %bufptr StorageBuffer\n"
+               "%id                                    = OpVariable %uvec3ptr Input\n"
+               "%zero                              = OpConstant %i32 0\n"
+               "%one                                   = OpConstant %i32 1\n"
+               "%fzero                                 = OpConstant %f32 0\n"
+               "%fone                                  = OpConstant %f32 1\n"
+
+               "${ExtraTypes}"
+
+               "${ExtraGlobalScopeVars}"
+
+               // We're going to put the "selector" function here.
+               // This function type is needed tests that use OpFunctionCall.
+               "%selector_func_type    = OpTypeFunction %sb_f32ptr %bool %sb_f32ptr %sb_f32ptr\n"
+               "%choose_input_func             = OpFunction %sb_f32ptr None %selector_func_type\n"
+               "%is_neg_param                  = OpFunctionParameter %bool\n"
+               "%first_ptr_param               = OpFunctionParameter %sb_f32ptr\n"
+               "%second_ptr_param              = OpFunctionParameter %sb_f32ptr\n"
+               "%selector_func_begin   = OpLabel\n"
+               "%result_ptr                    = OpSelect %sb_f32ptr %is_neg_param %first_ptr_param %second_ptr_param\n"
+               "OpReturnValue %result_ptr\n"
+               "OpFunctionEnd\n"
+
+               // main function is the entry_point
+               "%main                                  = OpFunction %void None %voidf\n"
+               "%label                                 = OpLabel\n"
+
+               "${ExtraFunctionScopeVars}"
+
+               "%idval                                 = OpLoad %uvec3 %id\n"
+               "%i                                             = OpCompositeExtract %u32 %idval 0\n"
+               "%two_i                                 = OpIAdd %u32 %i %i\n"
+               "%two_i_plus_1                  = OpIAdd %u32 %two_i %one\n"
+               "%inloc_a_i                             = OpAccessChain %sb_f32ptr %indata_a %zero %i\n"
+               "%inloc_b_i                             = OpAccessChain %sb_f32ptr %indata_b %zero %i\n"
+               "%inloc_s_i             = OpAccessChain %sb_f32ptr %indata_s %zero %i\n"
+               "%outloc_i              = OpAccessChain %sb_f32ptr %outdata  %zero %i\n"
+               "%inloc_a_2i                    = OpAccessChain %sb_f32ptr %indata_a %zero %two_i\n"
+               "%inloc_a_2i_plus_1             = OpAccessChain %sb_f32ptr %indata_a %zero %two_i_plus_1\n"
+               "%inval_s_i                             = OpLoad %f32 %inloc_s_i\n"
+               "%is_neg                                = OpFOrdLessThan %bool %inval_s_i %fzero\n"
+
+               "${ExtraSetupComputations}"
+
+               "${ResultStrategy}"
+
+               "%mux_output                    = OpLoad %f32 ${VarPtrName}\n"
+               "                                                 OpStore %outloc_i %mux_output\n"
+               "                                                 OpReturn\n"
+               "                                                 OpFunctionEnd\n");
+
+       const bool singleInputBuffer[]  = { true, false };
+       for (int inputBufferTypeIndex = 0 ; inputBufferTypeIndex < 2; ++inputBufferTypeIndex)
+       {
+               const bool isSingleInputBuffer                  = singleInputBuffer[inputBufferTypeIndex];
+               const string extraCap                                   = isSingleInputBuffer   ? "OpCapability VariablePointersStorageBuffer\n" : "OpCapability VariablePointers\n";
+               const vector<float>& expectedOutput             = isSingleInputBuffer   ? AmuxAOutputFloats              : AmuxBOutputFloats;
+               const vector<float>& expectedIncrOutput = isSingleInputBuffer   ? incrAmuxAOutputFloats  : incrAmuxBOutputFloats;
+               const string bufferType                                 = isSingleInputBuffer   ? "single_buffer"        : "two_buffers";
+               const string muxInput1                                  = isSingleInputBuffer   ? " %inloc_a_2i "                : " %inloc_a_i ";
+               const string muxInput2                                  = isSingleInputBuffer   ? " %inloc_a_2i_plus_1 " : " %inloc_b_i ";
+
+               // Set the proper extension features required for the test
+               if (isSingleInputBuffer)
+                       requiredFeatures.extVariablePointers    = EXTVARIABLEPOINTERSFEATURES_VARIABLE_POINTERS_STORAGEBUFFER;
+               else
+                       requiredFeatures.extVariablePointers    = EXTVARIABLEPOINTERSFEATURES_VARIABLE_POINTERS;
+
+               { // Variable Pointer Reads (using OpSelect)
+                       ComputeShaderSpec                               spec;
+                       map<string, string>                             specs;
+                       string name                                             = "reads_opselect_" + bufferType;
+                       specs["ExtraCapability"]                = extraCap;
+                       specs["ExtraTypes"]                             = "";
+                       specs["ExtraGlobalScopeVars"]   = "";
+                       specs["ExtraFunctionScopeVars"] = "";
+                       specs["ExtraSetupComputations"] = "";
+                       specs["VarPtrName"]                             = "%mux_output_var_ptr";
+                       specs["ResultStrategy"]                 = "%mux_output_var_ptr  = OpSelect %sb_f32ptr %is_neg" + muxInput1 + muxInput2 + "\n";
+                       spec.inputTypes[0]                              = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+                       spec.inputTypes[1]                              = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+                       spec.inputTypes[2]                              = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+                       spec.assembly                                   = shaderTemplate.specialize(specs);
+                       spec.numWorkGroups                              = IVec3(numMuxes, 1, 1);
+                       spec.requestedVulkanFeatures    = requiredFeatures;
+                       spec.inputs.push_back(BufferSp(new Float32Buffer(inputAFloats)));
+                       spec.inputs.push_back(BufferSp(new Float32Buffer(inputBFloats)));
+                       spec.inputs.push_back(BufferSp(new Float32Buffer(inputSFloats)));
+                       spec.outputs.push_back(BufferSp(new Float32Buffer(expectedOutput)));
+                       spec.extensions.push_back("VK_KHR_variable_pointers");
+                       group->addChild(new SpvAsmComputeShaderCase(testCtx, name.c_str(), name.c_str(), spec));
+               }
+               { // Variable Pointer Reads (using OpFunctionCall)
+                       ComputeShaderSpec                               spec;
+                       map<string, string>                             specs;
+                       string name                                             = "reads_opfunctioncall_" + bufferType;
+                       specs["ExtraCapability"]                = extraCap;
+                       specs["ExtraTypes"]                             = "";
+                       specs["ExtraGlobalScopeVars"]   = "";
+                       specs["ExtraFunctionScopeVars"] = "";
+                       specs["ExtraSetupComputations"] = "";
+                       specs["VarPtrName"]                             = "%mux_output_var_ptr";
+                       specs["ResultStrategy"]                 = "%mux_output_var_ptr = OpFunctionCall %sb_f32ptr %choose_input_func %is_neg" + muxInput1 + muxInput2 + "\n";
+                       spec.inputTypes[0]                              = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+                       spec.inputTypes[1]                              = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+                       spec.inputTypes[2]                              = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+                       spec.assembly                                   = shaderTemplate.specialize(specs);
+                       spec.numWorkGroups                              = IVec3(numMuxes, 1, 1);
+                       spec.requestedVulkanFeatures    = requiredFeatures;
+                       spec.inputs.push_back(BufferSp(new Float32Buffer(inputAFloats)));
+                       spec.inputs.push_back(BufferSp(new Float32Buffer(inputBFloats)));
+                       spec.inputs.push_back(BufferSp(new Float32Buffer(inputSFloats)));
+                       spec.outputs.push_back(BufferSp(new Float32Buffer(expectedOutput)));
+                       spec.extensions.push_back("VK_KHR_variable_pointers");
+                       group->addChild(new SpvAsmComputeShaderCase(testCtx, name.c_str(), name.c_str(), spec));
+               }
+               { // Variable Pointer Reads (using OpPhi)
+                       ComputeShaderSpec                               spec;
+                       map<string, string>                             specs;
+                       string name                                             = "reads_opphi_" + bufferType;
+                       specs["ExtraCapability"]                = extraCap;
+                       specs["ExtraTypes"]                             = "";
+                       specs["ExtraGlobalScopeVars"]   = "";
+                       specs["ExtraFunctionScopeVars"] = "";
+                       specs["ExtraSetupComputations"] = "";
+                       specs["VarPtrName"]                             = "%mux_output_var_ptr";
+                       specs["ResultStrategy"]                 =
+                               "                                                         OpSelectionMerge %end_label None\n"
+                               "                                                         OpBranchConditional %is_neg %take_mux_input_1 %take_mux_input_2\n"
+                               "%take_mux_input_1                      = OpLabel\n"
+                               "                                                         OpBranch %end_label\n"
+                               "%take_mux_input_2                      = OpLabel\n"
+                               "                                                     OpBranch %end_label\n"
+                               "%end_label                                     = OpLabel\n"
+                               "%mux_output_var_ptr            = OpPhi %sb_f32ptr" + muxInput1 + "%take_mux_input_1" + muxInput2 + "%take_mux_input_2\n";
+                       spec.inputTypes[0]                              = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+                       spec.inputTypes[1]                              = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+                       spec.inputTypes[2]                              = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+                       spec.assembly                                   = shaderTemplate.specialize(specs);
+                       spec.numWorkGroups                              = IVec3(numMuxes, 1, 1);
+                       spec.requestedVulkanFeatures    = requiredFeatures;
+                       spec.inputs.push_back(BufferSp(new Float32Buffer(inputAFloats)));
+                       spec.inputs.push_back(BufferSp(new Float32Buffer(inputBFloats)));
+                       spec.inputs.push_back(BufferSp(new Float32Buffer(inputSFloats)));
+                       spec.outputs.push_back(BufferSp(new Float32Buffer(expectedOutput)));
+                       spec.extensions.push_back("VK_KHR_variable_pointers");
+                       group->addChild(new SpvAsmComputeShaderCase(testCtx, name.c_str(), name.c_str(), spec));
+               }
+               { // Variable Pointer Reads (using OpCopyObject)
+                       ComputeShaderSpec                               spec;
+                       map<string, string>                             specs;
+                       string name                                             = "reads_opcopyobject_" + bufferType;
+                       specs["ExtraCapability"]                = extraCap;
+                       specs["ExtraTypes"]                             = "";
+                       specs["ExtraGlobalScopeVars"]   = "";
+                       specs["ExtraFunctionScopeVars"] = "";
+                       specs["ExtraSetupComputations"] = "";
+                       specs["VarPtrName"]                             = "%mux_output_var_ptr";
+                       specs["ResultStrategy"]                 =
+                               "%mux_input_1_copy                      = OpCopyObject %sb_f32ptr" + muxInput1 + "\n"
+                               "%mux_input_2_copy                      = OpCopyObject %sb_f32ptr" + muxInput2 + "\n"
+                               "%mux_output_var_ptr            = OpSelect %sb_f32ptr %is_neg %mux_input_1_copy %mux_input_2_copy\n";
+                       spec.inputTypes[0]                              = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+                       spec.inputTypes[1]                              = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+                       spec.inputTypes[2]                              = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+                       spec.assembly                                   = shaderTemplate.specialize(specs);
+                       spec.numWorkGroups                              = IVec3(numMuxes, 1, 1);
+                       spec.requestedVulkanFeatures    = requiredFeatures;
+                       spec.inputs.push_back(BufferSp(new Float32Buffer(inputAFloats)));
+                       spec.inputs.push_back(BufferSp(new Float32Buffer(inputBFloats)));
+                       spec.inputs.push_back(BufferSp(new Float32Buffer(inputSFloats)));
+                       spec.outputs.push_back(BufferSp(new Float32Buffer(expectedOutput)));
+                       spec.extensions.push_back("VK_KHR_variable_pointers");
+                       group->addChild(new SpvAsmComputeShaderCase(testCtx, name.c_str(), name.c_str(), spec));
+               }
+               { // Test storing into Private variables.
+                       const char* storageClasses[]            = {"Private", "Function"};
+                       for (int classId = 0; classId < 2; ++classId)
+                       {
+                               ComputeShaderSpec                               spec;
+                               map<string, string>                             specs;
+                               std::string storageClass                = storageClasses[classId];
+                               std::string name                                = "stores_" + string(de::toLower(storageClass)) + "_" + bufferType;
+                               std::string description                 = "Test storing variable pointer into " + storageClass + " variable.";
+                               std::string extraVariable               = "%mux_output_copy     = OpVariable %sb_f32ptrptr " + storageClass + "\n";
+                               specs["ExtraTypes"]                             = "%sb_f32ptrptr = OpTypePointer " + storageClass + " %sb_f32ptr\n";
+                               specs["ExtraCapability"]                = extraCap;
+                               specs["ExtraGlobalScopeVars"]   = (classId == 0) ? extraVariable : "";
+                               specs["ExtraFunctionScopeVars"] = (classId == 1) ? extraVariable : "";
+                               specs["ExtraSetupComputations"] = "";
+                               specs["VarPtrName"]                             = "%mux_output_var_ptr";
+                               specs["ResultStrategy"]                 =
+                                       "%opselect_result                       = OpSelect %sb_f32ptr %is_neg" + muxInput1 + muxInput2 + "\n"
+                                       "                                                         OpStore %mux_output_copy %opselect_result\n"
+                                       "%mux_output_var_ptr            = OpLoad %sb_f32ptr %mux_output_copy\n";
+                               spec.inputTypes[0]                              = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+                               spec.inputTypes[1]                              = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+                               spec.inputTypes[2]                              = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+                               spec.assembly                                   = shaderTemplate.specialize(specs);
+                               spec.numWorkGroups                              = IVec3(numMuxes, 1, 1);
+                               spec.requestedVulkanFeatures    = requiredFeatures;
+                               spec.inputs.push_back(BufferSp(new Float32Buffer(inputAFloats)));
+                               spec.inputs.push_back(BufferSp(new Float32Buffer(inputBFloats)));
+                               spec.inputs.push_back(BufferSp(new Float32Buffer(inputSFloats)));
+                               spec.outputs.push_back(BufferSp(new Float32Buffer(expectedOutput)));
+                               spec.extensions.push_back("VK_KHR_variable_pointers");
+                               group->addChild(new SpvAsmComputeShaderCase(testCtx, name.c_str(), description.c_str(), spec));
+                       }
+               }
+               { // Variable Pointer Reads (Using OpPtrAccessChain)
+                       ComputeShaderSpec                               spec;
+                       map<string, string>                             specs;
+                       std::string name                                = "reads_opptraccesschain_" + bufferType;
+                       std::string in_1                                = isSingleInputBuffer ? " %a_2i_ptr "            : " %a_i_ptr ";
+                       std::string in_2                                = isSingleInputBuffer ? " %a_2i_plus_1_ptr " : " %b_i_ptr ";
+                       specs["ExtraTypes"]                             = "";
+                       specs["ExtraCapability"]                = extraCap;
+                       specs["ExtraGlobalScopeVars"]   = "";
+                       specs["ExtraFunctionScopeVars"] = "";
+                       specs["ExtraSetupComputations"] = "";
+                       specs["VarPtrName"]                             = "%mux_output_var_ptr";
+                       specs["ResultStrategy"]                 =
+                                       "%a_ptr                                 = OpAccessChain %sb_f32ptr %indata_a %zero %zero\n"
+                                       "%b_ptr                                 = OpAccessChain %sb_f32ptr %indata_b %zero %zero\n"
+                                       "%s_ptr                                 = OpAccessChain %sb_f32ptr %indata_s %zero %zero\n"
+                                       "%out_ptr               = OpAccessChain %sb_f32ptr %outdata  %zero %zero\n"
+                                       "%a_i_ptr               = OpPtrAccessChain %sb_f32ptr %a_ptr %i\n"
+                                       "%b_i_ptr               = OpPtrAccessChain %sb_f32ptr %b_ptr %i\n"
+                                       "%s_i_ptr               = OpPtrAccessChain %sb_f32ptr %s_ptr %i\n"
+                                       "%a_2i_ptr              = OpPtrAccessChain %sb_f32ptr %a_ptr %two_i\n"
+                                       "%a_2i_plus_1_ptr       = OpPtrAccessChain %sb_f32ptr %a_ptr %two_i_plus_1\n"
+                                       "%mux_output_var_ptr    = OpSelect %sb_f32ptr %is_neg " + in_1 + in_2 + "\n";
+                       spec.inputTypes[0]                              = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+                       spec.inputTypes[1]                              = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+                       spec.inputTypes[2]                              = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+                       spec.assembly                                   = shaderTemplate.specialize(specs);
+                       spec.numWorkGroups                              = IVec3(numMuxes, 1, 1);
+                       spec.requestedVulkanFeatures    = requiredFeatures;
+                       spec.inputs.push_back(BufferSp(new Float32Buffer(inputAFloats)));
+                       spec.inputs.push_back(BufferSp(new Float32Buffer(inputBFloats)));
+                       spec.inputs.push_back(BufferSp(new Float32Buffer(inputSFloats)));
+                       spec.outputs.push_back(BufferSp(new Float32Buffer(expectedOutput)));
+                       spec.extensions.push_back("VK_KHR_variable_pointers");
+                       group->addChild(new SpvAsmComputeShaderCase(testCtx, name.c_str(), name.c_str(), spec));
+               }
+               {   // Variable Pointer Writes
+                       ComputeShaderSpec                               spec;
+                       map<string, string>                             specs;
+                       std::string     name                            = "writes_" + bufferType;
+                       specs["ExtraCapability"]                = extraCap;
+                       specs["ExtraTypes"]                             = "";
+                       specs["ExtraGlobalScopeVars"]   = "";
+                       specs["ExtraFunctionScopeVars"] = "";
+                       specs["ExtraSetupComputations"] = "";
+                       specs["VarPtrName"]                             = "%mux_output_var_ptr";
+                       specs["ResultStrategy"]                 = "%mux_output_var_ptr = OpSelect %sb_f32ptr %is_neg" + muxInput1 + muxInput2 + "\n" +
+                                                                                         "               %val = OpLoad %f32 %mux_output_var_ptr\n"
+                                                                                         "        %val_plus_1 = OpFAdd %f32 %val %fone\n"
+                                                                                         "                                              OpStore %mux_output_var_ptr %val_plus_1\n";
+                       spec.inputTypes[0]                              = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+                       spec.inputTypes[1]                              = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+                       spec.inputTypes[2]                              = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+                       spec.assembly                                   = shaderTemplate.specialize(specs);
+                       spec.numWorkGroups                              = IVec3(numMuxes, 1, 1);
+                       spec.requestedVulkanFeatures    = requiredFeatures;
+                       spec.inputs.push_back(BufferSp(new Float32Buffer(inputAFloats)));
+                       spec.inputs.push_back(BufferSp(new Float32Buffer(inputBFloats)));
+                       spec.inputs.push_back(BufferSp(new Float32Buffer(inputSFloats)));
+                       spec.outputs.push_back(BufferSp(new Float32Buffer(expectedIncrOutput)));
+                       spec.extensions.push_back("VK_KHR_variable_pointers");
+                       group->addChild(new SpvAsmComputeShaderCase(testCtx, name.c_str(), name.c_str(), spec));
+               }
+
+               // If we only have VariablePointersStorageBuffer, then the extension does not apply to Workgroup storage class.
+               // Therefore the Workgroup tests apply to cases where the VariablePointers capability is used (when 2 input buffers are used).
+               if (!isSingleInputBuffer)
+               {
+                       // VariablePointers on Workgroup
+                       ComputeShaderSpec                               spec;
+                       map<string, string>                             specs;
+                       std::string name                                = "workgroup_" + bufferType;
+                       specs["ExtraCapability"]                = extraCap;
+                       specs["ExtraTypes"]                             =
+                                       "%c_i32_N                               = OpConstant %i32 " + inputArraySize + " \n"
+                                       "%f32arr_N                              = OpTypeArray %f32 %c_i32_N\n"
+                                       "%f32arr_wrkgrp_ptr             = OpTypePointer Workgroup %f32arr_N\n"
+                                       "%f32_wrkgrp_ptr                = OpTypePointer Workgroup %f32\n";
+                       specs["ExtraGlobalScopeVars"]   =
+                                       "%AW                                    = OpVariable %f32arr_wrkgrp_ptr Workgroup\n"
+                                       "%BW                                    = OpVariable %f32arr_wrkgrp_ptr Workgroup\n";
+                       specs["ExtraFunctionScopeVars"] = "";
+                       specs["ExtraSetupComputations"] =
+                                       "%loc_AW_i                              = OpAccessChain %f32_wrkgrp_ptr %AW %i\n"
+                                       "%loc_BW_i                              = OpAccessChain %f32_wrkgrp_ptr %BW %i\n"
+                                       "%inval_a_i                             = OpLoad %f32 %inloc_a_i\n"
+                                       "%inval_b_i                             = OpLoad %f32 %inloc_b_i\n"
+                                       "%inval_a_2i                    = OpLoad %f32 %inloc_a_2i\n"
+                                       "%inval_a_2i_plus_1             = OpLoad %f32 %inloc_a_2i_plus_1\n";
+                       specs["VarPtrName"]                             = "%output_var_ptr";
+                       specs["ResultStrategy"]                 =
+                                       "                                                 OpStore %loc_AW_i %inval_a_i\n"
+                                       "                                                 OpStore %loc_BW_i %inval_b_i\n"
+                                       "%output_var_ptr                = OpSelect %f32_wrkgrp_ptr %is_neg %loc_AW_i %loc_BW_i\n";
+                       spec.inputTypes[0]                              = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+                       spec.inputTypes[1]                              = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+                       spec.inputTypes[2]                              = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+                       spec.assembly                                   = shaderTemplate.specialize(specs);
+                       spec.numWorkGroups                              = IVec3(numMuxes, 1, 1);
+                       spec.requestedVulkanFeatures    = requiredFeatures;
+                       spec.inputs.push_back(BufferSp(new Float32Buffer(inputAFloats)));
+                       spec.inputs.push_back(BufferSp(new Float32Buffer(inputBFloats)));
+                       spec.inputs.push_back(BufferSp(new Float32Buffer(inputSFloats)));
+                       spec.outputs.push_back(BufferSp(new Float32Buffer(expectedOutput)));
+                       spec.extensions.push_back("VK_KHR_variable_pointers");
+                       group->addChild(new SpvAsmComputeShaderCase(testCtx, name.c_str(), name.c_str(), spec));
+               }
+       }
+}
+
+void addGraphicsVariablePointersGroup (tcu::TestCaseGroup* testGroup)
+{
+       tcu::TestContext&                               testCtx                                 = testGroup->getTestContext();
+       de::Random                                              rnd                                             (deStringHash(testGroup->getName()));
+       map<string, string>                             fragments;
+       RGBA                                                    defaultColors[4];
+       vector<string>                                  extensions;
+       const int                                               seed                                    = testCtx.getCommandLine().getBaseSeed();
+       const int                                               numMuxes                                = 100;
+       const std::string                               numMuxesStr                             = "100";
+       vector<float>                                   inputAFloats                    (2*numMuxes, 0);
+       vector<float>                                   inputBFloats                    (2*numMuxes, 0);
+       vector<float>                                   inputSFloats                    (numMuxes, 0);
+       vector<float>                                   AmuxAOutputFloats               (numMuxes, 0);
+       vector<float>                                   AmuxBOutputFloats               (numMuxes, 0);
+       vector<float>                                   incrAmuxAOutputFloats   (numMuxes, 0);
+       vector<float>                                   incrAmuxBOutputFloats   (numMuxes, 0);
+       VulkanFeatures                                  requiredFeatures;
+
+       extensions.push_back("VK_KHR_variable_pointers");
+       getDefaultColors(defaultColors);
+
+       // Each output entry is chosen as follows: ( 0 <= i < numMuxes)
+       // 1) For tests with one input buffer:  output[i] = (s[i] < 0) ? A[2*i] : A[2*i+1];
+       // 2) For tests with two input buffers: output[i] = (s[i] < 0) ? A[i]   : B[i];
+
+       fillRandomScalars(rnd, -100.f, 100.f, &inputAFloats[0], 2*numMuxes);
+       fillRandomScalars(rnd, -100.f, 100.f, &inputBFloats[0], 2*numMuxes);
+
+       // We want to guarantee that the S input has some positive and some negative values.
+       // We choose random negative numbers for the first half, random positive numbers for the second half, and then shuffle.
+       fillRandomScalars(rnd, -100.f, -1.f , &inputSFloats[0], numMuxes / 2);
+       fillRandomScalars(rnd, 1.f   , 100.f, &inputSFloats[numMuxes / 2], numMuxes / 2);
+       de::Random(seed).shuffle(inputSFloats.begin(), inputSFloats.end());
+
+       for (size_t i = 0; i < numMuxes; ++i)
+       {
+               AmuxAOutputFloats[i]     = (inputSFloats[i] < 0) ? inputAFloats[2*i]     : inputAFloats[2*i+1];
+               AmuxBOutputFloats[i]     = (inputSFloats[i] < 0) ? inputAFloats[i]               : inputBFloats[i];
+               incrAmuxAOutputFloats[i] = (inputSFloats[i] < 0) ? 1 + inputAFloats[2*i] : 1 + inputAFloats[2*i+1];
+               incrAmuxBOutputFloats[i] = (inputSFloats[i] < 0) ? 1 + inputAFloats[i]   : 1 + inputBFloats[i];
+       }
+
+       fragments["extension"]          = "OpExtension \"SPV_KHR_variable_pointers\"\n"
+                                                                 "OpExtension \"SPV_KHR_storage_buffer_storage_class\"\n";
+
+       const StringTemplate preMain            (
+               "%c_i32_limit = OpConstant %i32 " + numMuxesStr + "\n"
+               "     %sb_f32 = OpTypePointer StorageBuffer %f32\n"
+               "     %ra_f32 = OpTypeRuntimeArray %f32\n"
+               "        %buf = OpTypeStruct %ra_f32\n"
+               "     %sb_buf = OpTypePointer StorageBuffer %buf\n"
+
+               " ${ExtraTypes}"
+
+               " ${ExtraGlobalScopeVars}"
+
+               "   %indata_a = OpVariable %sb_buf StorageBuffer\n"
+               "   %indata_b = OpVariable %sb_buf StorageBuffer\n"
+               "   %indata_s = OpVariable %sb_buf StorageBuffer\n"
+               "    %outdata = OpVariable %sb_buf StorageBuffer\n"
+
+               " ${ExtraFunctions} ");
+
+       const std::string selectorFunction      (
+               // We're going to put the "selector" function here.
+               // This function type is needed for tests that use OpFunctionCall.
+               "%selector_func_type    = OpTypeFunction %sb_f32 %bool %sb_f32 %sb_f32\n"
+               "%choose_input_func             = OpFunction %sb_f32 None %selector_func_type\n"
+               "%is_neg_param                  = OpFunctionParameter %bool\n"
+               "%first_ptr_param               = OpFunctionParameter %sb_f32\n"
+               "%second_ptr_param              = OpFunctionParameter %sb_f32\n"
+               "%selector_func_begin   = OpLabel\n"
+               "%result_ptr                    = OpSelect %sb_f32 %is_neg_param %first_ptr_param %second_ptr_param\n"
+               "OpReturnValue %result_ptr\n"
+               "OpFunctionEnd\n");
+
+       const StringTemplate decoration         (
+               "OpMemberDecorate %buf 0 Offset 0\n"
+               "OpDecorate %buf Block\n"
+               "OpDecorate %ra_f32 ArrayStride 4\n"
+               "OpDecorate %sb_f32 ArrayStride 4\n"
+               "OpDecorate %indata_a DescriptorSet 0\n"
+               "OpDecorate %indata_b DescriptorSet 0\n"
+               "OpDecorate %indata_s DescriptorSet 0\n"
+               "OpDecorate %outdata  DescriptorSet 0\n"
+               "OpDecorate %indata_a Binding 0\n"
+               "OpDecorate %indata_b Binding 1\n"
+               "OpDecorate %indata_s Binding 2\n"
+               "OpDecorate %outdata  Binding 3\n");
+
+       const StringTemplate testFunction       (
+               "%test_code             = OpFunction %v4f32 None %v4f32_function\n"
+               "%param                 = OpFunctionParameter %v4f32\n"
+               "%entry                 = OpLabel\n"
+
+               "${ExtraFunctionScopeVars}"
+
+               "%i                             = OpVariable %fp_i32 Function\n"
+
+               "%should_run    = OpFunctionCall %bool %isUniqueIdZero\n"
+               "                 OpSelectionMerge %end_if None\n"
+               "                 OpBranchConditional %should_run %run_test %end_if\n"
+
+               "%run_test      = OpLabel\n"
+               "                               OpStore %i %c_i32_0\n"
+               "                               OpBranch %loop\n"
+               // loop header
+               "%loop                  = OpLabel\n"
+               "%15                    = OpLoad %i32 %i\n"
+               "%lt                    = OpSLessThan %bool %15 %c_i32_limit\n"
+               "                               OpLoopMerge %merge %inc None\n"
+               "                               OpBranchConditional %lt %write %merge\n"
+               // loop body
+               "%write                         = OpLabel\n"
+               "%30                            = OpLoad %i32 %i\n"
+               "%two_i                         = OpIAdd %i32 %30 %30\n"
+               "%two_i_plus_1          = OpIAdd %i32 %two_i %c_i32_1\n"
+               "%loc_s_i                       = OpAccessChain %sb_f32 %indata_s %c_i32_0 %30\n"
+               "%loc_a_i                       = OpAccessChain %sb_f32 %indata_a %c_i32_0 %30\n"
+               "%loc_b_i                       = OpAccessChain %sb_f32 %indata_b %c_i32_0 %30\n"
+               "%loc_a_2i                      = OpAccessChain %sb_f32 %indata_a %c_i32_0 %two_i\n"
+               "%loc_a_2i_plus_1       = OpAccessChain %sb_f32 %indata_a %c_i32_0 %two_i_plus_1\n"
+               "%loc_outdata_i         = OpAccessChain %sb_f32 %outdata  %c_i32_0 %30\n"
+               "%val_s_i                       = OpLoad %f32 %loc_s_i\n"
+               "%is_neg                        = OpFOrdLessThan %bool %val_s_i %c_f32_0\n"
+
+               // select using a strategy.
+               "${ResultStrategy}"
+
+               // load through the variable pointer
+               "%mux_output    = OpLoad %f32 ${VarPtrName}\n"
+
+               // store to the output vector.
+               "                               OpStore %loc_outdata_i %mux_output\n"
+               "                               OpBranch %inc\n"
+               // ++i
+               "  %inc                 = OpLabel\n"
+               "   %37                 = OpLoad %i32 %i\n"
+               "   %39                 = OpIAdd %i32 %37 %c_i32_1\n"
+               "         OpStore %i %39\n"
+               "         OpBranch %loop\n"
+
+               // Return and FunctionEnd
+               "%merge                 = OpLabel\n"
+               "                 OpBranch %end_if\n"
+               "%end_if                = OpLabel\n"
+               "OpReturnValue %param\n"
+               "OpFunctionEnd\n");
+
+       const bool singleInputBuffer[] = { true, false };
+       for (int inputBufferTypeIndex = 0 ; inputBufferTypeIndex < 2; ++inputBufferTypeIndex)
+       {
+               const bool isSingleInputBuffer                  = singleInputBuffer[inputBufferTypeIndex];
+               const string cap                                                = isSingleInputBuffer   ? "OpCapability VariablePointersStorageBuffer\n" : "OpCapability VariablePointers\n";
+               const vector<float>& expectedOutput             = isSingleInputBuffer   ? AmuxAOutputFloats              : AmuxBOutputFloats;
+               const vector<float>& expectedIncrOutput = isSingleInputBuffer   ? incrAmuxAOutputFloats  : incrAmuxBOutputFloats;
+               const string bufferType                                 = isSingleInputBuffer   ? "single_buffer"                : "two_buffers";
+               const string muxInput1                                  = isSingleInputBuffer   ? " %loc_a_2i "                  : " %loc_a_i ";
+               const string muxInput2                                  = isSingleInputBuffer   ? " %loc_a_2i_plus_1 "   : " %loc_b_i ";
+
+               // Set the proper extension features required for the test
+               if (isSingleInputBuffer)
+                       requiredFeatures.extVariablePointers    = EXTVARIABLEPOINTERSFEATURES_VARIABLE_POINTERS_STORAGEBUFFER;
+               else
+                       requiredFeatures.extVariablePointers    = EXTVARIABLEPOINTERSFEATURES_VARIABLE_POINTERS;
+
+               // All of the following tests write their results into an output SSBO, therefore they require the following features.
+               requiredFeatures.coreFeatures.vertexPipelineStoresAndAtomics = DE_TRUE;
+               requiredFeatures.coreFeatures.fragmentStoresAndAtomics           = DE_TRUE;
+
+               { // Variable Pointer Reads (using OpSelect)
+                       GraphicsResources                               resources;
+                       map<string, string>                             specs;
+                       string name                                             = "reads_opselect_" + bufferType;
+                       specs["ExtraTypes"]                             = "";
+                       specs["ExtraGlobalScopeVars"]   = "";
+                       specs["ExtraFunctionScopeVars"] = "";
+                       specs["ExtraFunctions"]                 = "";
+                       specs["VarPtrName"]                             = "%mux_output_var_ptr";
+                       specs["ResultStrategy"]                 = "%mux_output_var_ptr  = OpSelect %sb_f32 %is_neg" + muxInput1 + muxInput2 + "\n";
+
+                       fragments["capability"]                 = cap;
+                       fragments["decoration"]                 = decoration.specialize(specs);
+                       fragments["pre_main"]                   = preMain.specialize(specs);
+                       fragments["testfun"]                    = testFunction.specialize(specs);
+
+                       resources.inputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Float32Buffer(inputAFloats))));
+                       resources.inputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Float32Buffer(inputBFloats))));
+                       resources.inputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Float32Buffer(inputSFloats))));
+                       resources.outputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Float32Buffer(expectedOutput))));
+                       createTestsForAllStages(name.c_str(), defaultColors, defaultColors, fragments, resources, extensions, testGroup, requiredFeatures);
+               }
+               { // Variable Pointer Reads (using OpFunctionCall)
+                       GraphicsResources                               resources;
+                       map<string, string>                             specs;
+                       string name                                             = "reads_opfunctioncall_" + bufferType;
+                       specs["ExtraTypes"]                             = "";
+                       specs["ExtraGlobalScopeVars"]   = "";
+                       specs["ExtraFunctionScopeVars"] = "";
+                       specs["ExtraFunctions"]                 = selectorFunction;
+                       specs["VarPtrName"]                             = "%mux_output_var_ptr";
+                       specs["ResultStrategy"]                 = "%mux_output_var_ptr = OpFunctionCall %sb_f32 %choose_input_func %is_neg" + muxInput1 + muxInput2 + "\n";
+
+                       fragments["capability"]                 = cap;
+                       fragments["decoration"]                 = decoration.specialize(specs);
+                       fragments["pre_main"]                   = preMain.specialize(specs);
+                       fragments["testfun"]                    = testFunction.specialize(specs);
+
+                       resources.inputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Float32Buffer(inputAFloats))));
+                       resources.inputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Float32Buffer(inputBFloats))));
+                       resources.inputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Float32Buffer(inputSFloats))));
+                       resources.outputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Float32Buffer(expectedOutput))));
+                       createTestsForAllStages(name.c_str(), defaultColors, defaultColors, fragments, resources, extensions, testGroup, requiredFeatures);
+               }
+               { // Variable Pointer Reads (using OpPhi)
+                       GraphicsResources                               resources;
+                       map<string, string>                             specs;
+                       string name                                             = "reads_opphi_" + bufferType;
+                       specs["ExtraTypes"]                             = "";
+                       specs["ExtraGlobalScopeVars"]   = "";
+                       specs["ExtraFunctionScopeVars"] = "";
+                       specs["ExtraFunctions"]                 = "";
+                       specs["VarPtrName"]                             = "%mux_output_var_ptr";
+                       specs["ResultStrategy"]                 =
+                               "                                                         OpSelectionMerge %end_label None\n"
+                               "                                                         OpBranchConditional %is_neg %take_mux_input_1 %take_mux_input_2\n"
+                               "%take_mux_input_1                      = OpLabel\n"
+                               "                                                         OpBranch %end_label\n"
+                               "%take_mux_input_2                      = OpLabel\n"
+                               "                                                     OpBranch %end_label\n"
+                               "%end_label                                     = OpLabel\n"
+                               "%mux_output_var_ptr            = OpPhi %sb_f32" + muxInput1 + "%take_mux_input_1" + muxInput2 + "%take_mux_input_2\n";
+
+                       fragments["capability"]                 = cap;
+                       fragments["decoration"]                 = decoration.specialize(specs);
+                       fragments["pre_main"]                   = preMain.specialize(specs);
+                       fragments["testfun"]                    = testFunction.specialize(specs);
+
+                       resources.inputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Float32Buffer(inputAFloats))));
+                       resources.inputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Float32Buffer(inputBFloats))));
+                       resources.inputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Float32Buffer(inputSFloats))));
+                       resources.outputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Float32Buffer(expectedOutput))));
+                       createTestsForAllStages(name.c_str(), defaultColors, defaultColors, fragments, resources, extensions, testGroup, requiredFeatures);
+               }
+               { // Variable Pointer Reads (using OpCopyObject)
+                       GraphicsResources                               resources;
+                       map<string, string>                             specs;
+                       string name                                             = "reads_opcopyobject_" + bufferType;
+                       specs["ExtraTypes"]                             = "";
+                       specs["ExtraGlobalScopeVars"]   = "";
+                       specs["ExtraFunctionScopeVars"] = "";
+                       specs["ExtraFunctions"]                 = "";
+                       specs["VarPtrName"]                             = "%mux_output_var_ptr";
+                       specs["ResultStrategy"]                 =
+                               "%mux_input_1_copy                      = OpCopyObject %sb_f32" + muxInput1 + "\n"
+                               "%mux_input_2_copy                      = OpCopyObject %sb_f32" + muxInput2 + "\n"
+                               "%mux_output_var_ptr            = OpSelect %sb_f32 %is_neg %mux_input_1_copy %mux_input_2_copy\n";
+
+                       fragments["capability"]                 = cap;
+                       fragments["decoration"]                 = decoration.specialize(specs);
+                       fragments["pre_main"]                   = preMain.specialize(specs);
+                       fragments["testfun"]                    = testFunction.specialize(specs);
+
+                       resources.inputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Float32Buffer(inputAFloats))));
+                       resources.inputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Float32Buffer(inputBFloats))));
+                       resources.inputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Float32Buffer(inputSFloats))));
+                       resources.outputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Float32Buffer(expectedOutput))));
+                       createTestsForAllStages(name.c_str(), defaultColors, defaultColors, fragments, resources, extensions, testGroup, requiredFeatures);
+               }
+               { // Test storing into Private variables.
+                       const char* storageClasses[]            = {"Private", "Function"};
+                       for (int classId = 0; classId < 2; ++classId)
+                       {
+                               GraphicsResources                               resources;
+                               map<string, string>                             specs;
+                               std::string storageClass                = storageClasses[classId];
+                               std::string name                                = "stores_" + string(de::toLower(storageClass)) + "_" + bufferType;
+                               std::string extraVariable               = "%mux_output_copy     = OpVariable %sb_f32ptrptr " + storageClass + "\n";
+                               specs["ExtraTypes"]                             = "%sb_f32ptrptr = OpTypePointer " + storageClass + " %sb_f32\n";
+                               specs["ExtraGlobalScopeVars"]   = (classId == 0) ? extraVariable : "";
+                               specs["ExtraFunctionScopeVars"] = (classId == 1) ? extraVariable : "";
+                               specs["ExtraFunctions"]                 = "";
+                               specs["VarPtrName"]                             = "%mux_output_var_ptr";
+                               specs["ResultStrategy"]                 =
+                                       "%opselect_result                       = OpSelect %sb_f32 %is_neg" + muxInput1 + muxInput2 + "\n"
+                                       "                                                         OpStore %mux_output_copy %opselect_result\n"
+                                       "%mux_output_var_ptr            = OpLoad %sb_f32 %mux_output_copy\n";
+
+                               fragments["capability"]                 = cap;
+                               fragments["decoration"]                 = decoration.specialize(specs);
+                               fragments["pre_main"]                   = preMain.specialize(specs);
+                               fragments["testfun"]                    = testFunction.specialize(specs);
+
+                               resources.inputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Float32Buffer(inputAFloats))));
+                               resources.inputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Float32Buffer(inputBFloats))));
+                               resources.inputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Float32Buffer(inputSFloats))));
+                               resources.outputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Float32Buffer(expectedOutput))));
+                               createTestsForAllStages(name.c_str(), defaultColors, defaultColors, fragments, resources, extensions, testGroup, requiredFeatures);
+                       }
+               }
+               { // Variable Pointer Reads (using OpPtrAccessChain)
+                       GraphicsResources                               resources;
+                       map<string, string>                             specs;
+                       std::string name                                = "reads_opptraccesschain_" + bufferType;
+                       std::string in_1                                = isSingleInputBuffer ? " %a_2i_ptr "            : " %a_i_ptr ";
+                       std::string in_2                                = isSingleInputBuffer ? " %a_2i_plus_1_ptr " : " %b_i_ptr ";
+                       specs["ExtraTypes"]                             = "";
+                       specs["ExtraGlobalScopeVars"]   = "";
+                       specs["ExtraFunctionScopeVars"] = "";
+                       specs["ExtraFunctions"]                 = "";
+                       specs["VarPtrName"]                             = "%mux_output_var_ptr";
+                       specs["ResultStrategy"]                 =
+                                       "%a_ptr                                 = OpAccessChain %sb_f32 %indata_a %c_i32_0 %c_i32_0\n"
+                                       "%b_ptr                                 = OpAccessChain %sb_f32 %indata_b %c_i32_0 %c_i32_0\n"
+                                       "%s_ptr                                 = OpAccessChain %sb_f32 %indata_s %c_i32_0 %c_i32_0\n"
+                                       "%out_ptr               = OpAccessChain %sb_f32 %outdata  %c_i32_0 %c_i32_0\n"
+                                       "%a_i_ptr               = OpPtrAccessChain %sb_f32 %a_ptr %30\n"
+                                       "%b_i_ptr               = OpPtrAccessChain %sb_f32 %b_ptr %30\n"
+                                       "%s_i_ptr               = OpPtrAccessChain %sb_f32 %s_ptr %30\n"
+                                       "%a_2i_ptr              = OpPtrAccessChain %sb_f32 %a_ptr %two_i\n"
+                                       "%a_2i_plus_1_ptr       = OpPtrAccessChain %sb_f32 %a_ptr %two_i_plus_1\n"
+                                       "%mux_output_var_ptr    = OpSelect %sb_f32 %is_neg " + in_1 + in_2 + "\n";
+
+                       fragments["decoration"]                 = decoration.specialize(specs);
+                       fragments["pre_main"]                   = preMain.specialize(specs);
+                       fragments["testfun"]                    = testFunction.specialize(specs);
+                       fragments["capability"]                 = cap;
+
+                       resources.inputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Float32Buffer(inputAFloats))));
+                       resources.inputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Float32Buffer(inputBFloats))));
+                       resources.inputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Float32Buffer(inputSFloats))));
+                       resources.outputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Float32Buffer(expectedOutput))));
+                       createTestsForAllStages(name.c_str(), defaultColors, defaultColors, fragments, resources, extensions, testGroup, requiredFeatures);
+               }
+               {   // Variable Pointer Writes
+                       GraphicsResources                               resources;
+                       map<string, string>                             specs;
+                       std::string     name                            = "writes_" + bufferType;
+                       specs["ExtraTypes"]                             = "";
+                       specs["ExtraGlobalScopeVars"]   = "";
+                       specs["ExtraFunctionScopeVars"] = "";
+                       specs["ExtraFunctions"]                 = "";
+                       specs["VarPtrName"]                             = "%mux_output_var_ptr";
+                       specs["ResultStrategy"]                 =
+                                          "%mux_output_var_ptr = OpSelect %sb_f32 %is_neg" + muxInput1 + muxInput2 + "\n" +
+                                          "               %val = OpLoad %f32 %mux_output_var_ptr\n"
+                                          "        %val_plus_1 = OpFAdd %f32 %val %c_f32_1\n"
+                                          "                                      OpStore %mux_output_var_ptr %val_plus_1\n";
+                       fragments["capability"]                 = cap;
+                       fragments["decoration"]                 = decoration.specialize(specs);
+                       fragments["pre_main"]                   = preMain.specialize(specs);
+                       fragments["testfun"]                    = testFunction.specialize(specs);
+
+                       resources.inputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Float32Buffer(inputAFloats))));
+                       resources.inputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Float32Buffer(inputBFloats))));
+                       resources.inputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Float32Buffer(inputSFloats))));
+                       resources.outputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, BufferSp(new Float32Buffer(expectedIncrOutput))));
+                       createTestsForAllStages(name.c_str(), defaultColors, defaultColors, fragments, resources, extensions, testGroup, requiredFeatures);
+               }
+       }
+}
+
+} // anonymous
+
+tcu::TestCaseGroup* createVariablePointersComputeGroup (tcu::TestContext& testCtx)
+{
+       de::MovePtr<tcu::TestCaseGroup> group   (new tcu::TestCaseGroup(testCtx, "variable_pointers", "Compute tests for SPV_KHR_variable_pointers extension"));
+       addTestGroup(group.get(), "compute", "Test the variable pointer extension using a compute shader", addComputeVariablePointersGroup);
+
+       // \todo [2017-03-17 ehsann] A couple of things to do:
+       // * Add more tests (similar to existing ones) using data types other than Float.
+       return group.release();
+}
+
+tcu::TestCaseGroup* createVariablePointersGraphicsGroup (tcu::TestContext& testCtx)
+{
+       de::MovePtr<tcu::TestCaseGroup> group   (new tcu::TestCaseGroup(testCtx, "variable_pointers", "Graphics tests for SPV_KHR_variable_pointers extension"));
+       addTestGroup(group.get(), "graphics", "Testing Variable Pointers in graphics pipeline", addGraphicsVariablePointersGroup);
+
+       // \todo [2017-03-17 ehsann] A couple of things to do:
+       // * Add more tests (similar to existing ones) using data types other than Float.
+       return group.release();
+}
+
+} // SpirVAssembly
+} // vkt
diff --git a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmVariablePointersTests.hpp b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmVariablePointersTests.hpp
new file mode 100644 (file)
index 0000000..2a52090
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef _VKTSPVASMVARIABLEPOINTERSTESTS_HPP
+#define _VKTSPVASMVARIABLEPOINTERSTESTS_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2017 Google 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 SPIR-V Assembly Tests for SPV_KHR_variable_pointers
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTestCase.hpp"
+
+namespace vkt
+{
+namespace SpirVAssembly
+{
+
+tcu::TestCaseGroup*    createVariablePointersComputeGroup      (tcu::TestContext& testCtx);
+tcu::TestCaseGroup*    createVariablePointersGraphicsGroup     (tcu::TestContext& testCtx);
+
+} // SpirVAssembly
+} // vkt
+
+#endif // _VKTSPVASMVARIABLEPOINTERSTESTS_HPP
index b896adf..8d88db8 100644 (file)
@@ -163041,6 +163041,23 @@ dEQP-VK.spirv_assembly.instruction.compute.16bit_storage.push_constant_16_to_32.
 dEQP-VK.spirv_assembly.instruction.compute.16bit_storage.push_constant_16_to_32.scalar_uint
 dEQP-VK.spirv_assembly.instruction.compute.16bit_storage.push_constant_16_to_32.vector_sint
 dEQP-VK.spirv_assembly.instruction.compute.16bit_storage.push_constant_16_to_32.vector_uint
+dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.compute.reads_opselect_single_buffer
+dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.compute.reads_opfunctioncall_single_buffer
+dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.compute.reads_opphi_single_buffer
+dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.compute.reads_opcopyobject_single_buffer
+dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.compute.stores_private_single_buffer
+dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.compute.stores_function_single_buffer
+dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.compute.reads_opptraccesschain_single_buffer
+dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.compute.writes_single_buffer
+dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.compute.reads_opselect_two_buffers
+dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.compute.reads_opfunctioncall_two_buffers
+dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.compute.reads_opphi_two_buffers
+dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.compute.reads_opcopyobject_two_buffers
+dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.compute.stores_private_two_buffers
+dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.compute.stores_function_two_buffers
+dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.compute.reads_opptraccesschain_two_buffers
+dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.compute.writes_two_buffers
+dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.compute.workgroup_two_buffers
 dEQP-VK.spirv_assembly.instruction.graphics.opnop.opnop_vert
 dEQP-VK.spirv_assembly.instruction.graphics.opnop.opnop_tessc
 dEQP-VK.spirv_assembly.instruction.graphics.opnop.opnop_tesse
@@ -164899,6 +164916,86 @@ dEQP-VK.spirv_assembly.instruction.graphics.16bit_storage.push_constant_int_16_t
 dEQP-VK.spirv_assembly.instruction.graphics.16bit_storage.push_constant_int_16_to_32.uint_vector_tesse
 dEQP-VK.spirv_assembly.instruction.graphics.16bit_storage.push_constant_int_16_to_32.uint_vector_geom
 dEQP-VK.spirv_assembly.instruction.graphics.16bit_storage.push_constant_int_16_to_32.uint_vector_frag
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opselect_single_buffer_vert
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opselect_single_buffer_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opselect_single_buffer_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opselect_single_buffer_geom
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opselect_single_buffer_frag
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opfunctioncall_single_buffer_vert
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opfunctioncall_single_buffer_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opfunctioncall_single_buffer_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opfunctioncall_single_buffer_geom
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opfunctioncall_single_buffer_frag
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opphi_single_buffer_vert
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opphi_single_buffer_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opphi_single_buffer_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opphi_single_buffer_geom
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opphi_single_buffer_frag
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opcopyobject_single_buffer_vert
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opcopyobject_single_buffer_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opcopyobject_single_buffer_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opcopyobject_single_buffer_geom
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opcopyobject_single_buffer_frag
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.stores_private_single_buffer_vert
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.stores_private_single_buffer_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.stores_private_single_buffer_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.stores_private_single_buffer_geom
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.stores_private_single_buffer_frag
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.stores_function_single_buffer_vert
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.stores_function_single_buffer_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.stores_function_single_buffer_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.stores_function_single_buffer_geom
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.stores_function_single_buffer_frag
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opptraccesschain_single_buffer_vert
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opptraccesschain_single_buffer_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opptraccesschain_single_buffer_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opptraccesschain_single_buffer_geom
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opptraccesschain_single_buffer_frag
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.writes_single_buffer_vert
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.writes_single_buffer_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.writes_single_buffer_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.writes_single_buffer_geom
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.writes_single_buffer_frag
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opselect_two_buffers_vert
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opselect_two_buffers_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opselect_two_buffers_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opselect_two_buffers_geom
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opselect_two_buffers_frag
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opfunctioncall_two_buffers_vert
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opfunctioncall_two_buffers_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opfunctioncall_two_buffers_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opfunctioncall_two_buffers_geom
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opfunctioncall_two_buffers_frag
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opphi_two_buffers_vert
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opphi_two_buffers_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opphi_two_buffers_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opphi_two_buffers_geom
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opphi_two_buffers_frag
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opcopyobject_two_buffers_vert
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opcopyobject_two_buffers_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opcopyobject_two_buffers_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opcopyobject_two_buffers_geom
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opcopyobject_two_buffers_frag
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.stores_private_two_buffers_vert
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.stores_private_two_buffers_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.stores_private_two_buffers_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.stores_private_two_buffers_geom
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.stores_private_two_buffers_frag
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.stores_function_two_buffers_vert
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.stores_function_two_buffers_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.stores_function_two_buffers_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.stores_function_two_buffers_geom
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.stores_function_two_buffers_frag
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opptraccesschain_two_buffers_vert
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opptraccesschain_two_buffers_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opptraccesschain_two_buffers_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opptraccesschain_two_buffers_geom
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.reads_opptraccesschain_two_buffers_frag
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.writes_two_buffers_vert
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.writes_two_buffers_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.writes_two_buffers_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.writes_two_buffers_geom
+dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.graphics.writes_two_buffers_frag
 dEQP-VK.glsl.arrays.constructor.float3_vertex
 dEQP-VK.glsl.arrays.constructor.float3_fragment
 dEQP-VK.glsl.arrays.constructor.float4_vertex
index bbf250a..05b6d3b 100644 (file)
@@ -256,6 +256,7 @@ typedef enum VkStructureType {
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR = 1000119000,
     VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR = 1000119001,
     VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR = 1000119002,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR = 1000120000,
     VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR = 1000127000,
     VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR = 1000127001,
     VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2_KHR = 1000146000,
@@ -4770,6 +4771,17 @@ VKAPI_ATTR VkResult VKAPI_CALL vkGetPastPresentationTimingGOOGLE(
 #define VK_EXT_SWAPCHAIN_COLOR_SPACE_SPEC_VERSION 2
 #define VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME "VK_EXT_swapchain_colorspace"
 
+#define VK_KHR_variable_pointers 1
+#define VK_KHR_VARIABLE_POINTERS_SPEC_VERSION 1
+#define VK_KHR_VARIABLE_POINTERS_EXTENSION_NAME "VK_KHR_variable_pointers"
+
+typedef struct VkPhysicalDeviceVariablePointerFeaturesKHR {
+    VkStructureType    sType;
+    const void*        pNext;
+    VkBool32           variablePointersStorageBuffer;
+    VkBool32           variablePointers;
+} VkPhysicalDeviceVariablePointerFeaturesKHR;
+
 
 #ifdef __cplusplus
 }