Test separate and combined images and samplers in SPIR-V
authorPaavo Pessi <paavo.pessi@siru.fi>
Fri, 15 Sep 2017 07:05:52 +0000 (10:05 +0300)
committerAlexander Galazin <Alexander.Galazin@arm.com>
Wed, 25 Oct 2017 09:31:54 +0000 (05:31 -0400)
Tests were added to verify that the following Image Instructions
work with related descriptor types in all possible shader stages:

OpImageRead
- Storage image

OpImageFetch
- Sampled image with separate sampler
- Combined image sampler

OpImageSampleExplicitLod
- Sampled image with separate sampler
- Combined image sampler

The following scenarios are covered to verify that images and samplers
work as function parameters and that you can combine an image and a
sampler both before and after passing it into a function.

- Use image and sampler as local variables
- Pass image to function
- Pass sampler to function
- Pass image and sampler to function

New tests:

dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.*
dEQP-VK.spirv_assembly.instruction.compute.image_sampler.*

Components: Vulkan

VK-GL-CTS issue: 104

Change-Id: I1de35fc0099881b3242f6e953a5c9624004e0f3e

AndroidGen.mk
android/cts/master/vk-master.txt
external/vulkancts/modules/vulkan/spirv_assembly/CMakeLists.txt
external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderCase.cpp
external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmGraphicsShaderTestUtil.cpp
external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmGraphicsShaderTestUtil.hpp
external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmImageSamplerTests.cpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmImageSamplerTests.hpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmInstructionTests.cpp
external/vulkancts/mustpass/1.0.3/vk-default.txt

index f7ed0e7..35d3d36 100644 (file)
@@ -215,6 +215,7 @@ LOCAL_SRC_FILES := \
        external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmComputeShaderTestUtil.cpp \
        external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmConditionalBranchTests.cpp \
        external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmGraphicsShaderTestUtil.cpp \
+       external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmImageSamplerTests.cpp \
        external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmIndexingTests.cpp \
        external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmInstructionTests.cpp \
        external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmTests.cpp \
index 5b27f97..f270b8b 100644 (file)
@@ -168547,6 +168547,18 @@ dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.complex_types_compu
 dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.complex_types_compute.opptraccesschain_float_single_buffer_first_input
 dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.nullptr_compute.opvariable_initialized_null
 dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.nullptr_compute.opselect_null_or_valid_ptr
+dEQP-VK.spirv_assembly.instruction.compute.image_sampler.imageread.storage_image.all_local_variables
+dEQP-VK.spirv_assembly.instruction.compute.image_sampler.imageread.storage_image.pass_image_to_function
+dEQP-VK.spirv_assembly.instruction.compute.image_sampler.imagefetch.sampled_image.all_local_variables
+dEQP-VK.spirv_assembly.instruction.compute.image_sampler.imagefetch.sampled_image.pass_image_to_function
+dEQP-VK.spirv_assembly.instruction.compute.image_sampler.imagefetch.sampled_image.pass_sampler_to_function
+dEQP-VK.spirv_assembly.instruction.compute.image_sampler.imagefetch.sampled_image.pass_image_and_sampler_to_function
+dEQP-VK.spirv_assembly.instruction.compute.image_sampler.imagefetch.combined_image_sampler.all_local_variables
+dEQP-VK.spirv_assembly.instruction.compute.image_sampler.imagesample.sampled_image.all_local_variables
+dEQP-VK.spirv_assembly.instruction.compute.image_sampler.imagesample.sampled_image.pass_image_to_function
+dEQP-VK.spirv_assembly.instruction.compute.image_sampler.imagesample.sampled_image.pass_sampler_to_function
+dEQP-VK.spirv_assembly.instruction.compute.image_sampler.imagesample.sampled_image.pass_image_and_sampler_to_function
+dEQP-VK.spirv_assembly.instruction.compute.image_sampler.imagesample.combined_image_sampler.all_local_variables
 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
@@ -171320,6 +171332,66 @@ dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.nullptr_graphics.o
 dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.nullptr_graphics.opselect_null_or_valid_ptr_tesse
 dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.nullptr_graphics.opselect_null_or_valid_ptr_geom
 dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.nullptr_graphics.opselect_null_or_valid_ptr_frag
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imageread.storage_image.all_local_variables.shader_vert
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imageread.storage_image.all_local_variables.shader_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imageread.storage_image.all_local_variables.shader_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imageread.storage_image.all_local_variables.shader_geom
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imageread.storage_image.all_local_variables.shader_frag
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imageread.storage_image.pass_image_to_function.shader_vert
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imageread.storage_image.pass_image_to_function.shader_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imageread.storage_image.pass_image_to_function.shader_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imageread.storage_image.pass_image_to_function.shader_geom
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imageread.storage_image.pass_image_to_function.shader_frag
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.sampled_image.all_local_variables.shader_vert
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.sampled_image.all_local_variables.shader_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.sampled_image.all_local_variables.shader_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.sampled_image.all_local_variables.shader_geom
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.sampled_image.all_local_variables.shader_frag
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.sampled_image.pass_image_to_function.shader_vert
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.sampled_image.pass_image_to_function.shader_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.sampled_image.pass_image_to_function.shader_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.sampled_image.pass_image_to_function.shader_geom
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.sampled_image.pass_image_to_function.shader_frag
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.sampled_image.pass_sampler_to_function.shader_vert
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.sampled_image.pass_sampler_to_function.shader_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.sampled_image.pass_sampler_to_function.shader_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.sampled_image.pass_sampler_to_function.shader_geom
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.sampled_image.pass_sampler_to_function.shader_frag
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.sampled_image.pass_image_and_sampler_to_function.shader_vert
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.sampled_image.pass_image_and_sampler_to_function.shader_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.sampled_image.pass_image_and_sampler_to_function.shader_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.sampled_image.pass_image_and_sampler_to_function.shader_geom
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.sampled_image.pass_image_and_sampler_to_function.shader_frag
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.combined_image_sampler.all_local_variables.shader_vert
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.combined_image_sampler.all_local_variables.shader_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.combined_image_sampler.all_local_variables.shader_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.combined_image_sampler.all_local_variables.shader_geom
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.combined_image_sampler.all_local_variables.shader_frag
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.sampled_image.all_local_variables.shader_vert
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.sampled_image.all_local_variables.shader_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.sampled_image.all_local_variables.shader_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.sampled_image.all_local_variables.shader_geom
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.sampled_image.all_local_variables.shader_frag
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.sampled_image.pass_image_to_function.shader_vert
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.sampled_image.pass_image_to_function.shader_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.sampled_image.pass_image_to_function.shader_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.sampled_image.pass_image_to_function.shader_geom
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.sampled_image.pass_image_to_function.shader_frag
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.sampled_image.pass_sampler_to_function.shader_vert
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.sampled_image.pass_sampler_to_function.shader_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.sampled_image.pass_sampler_to_function.shader_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.sampled_image.pass_sampler_to_function.shader_geom
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.sampled_image.pass_sampler_to_function.shader_frag
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.sampled_image.pass_image_and_sampler_to_function.shader_vert
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.sampled_image.pass_image_and_sampler_to_function.shader_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.sampled_image.pass_image_and_sampler_to_function.shader_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.sampled_image.pass_image_and_sampler_to_function.shader_geom
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.sampled_image.pass_image_and_sampler_to_function.shader_frag
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.combined_image_sampler.all_local_variables.shader_vert
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.combined_image_sampler.all_local_variables.shader_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.combined_image_sampler.all_local_variables.shader_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.combined_image_sampler.all_local_variables.shader_geom
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.combined_image_sampler.all_local_variables.shader_frag
 dEQP-VK.glsl.arrays.constructor.float3_vertex
 dEQP-VK.glsl.arrays.constructor.float3_fragment
 dEQP-VK.glsl.arrays.constructor.float4_vertex
index 00e9cc3..1ebefa2 100644 (file)
@@ -11,6 +11,8 @@ set(DEQP_VK_SPIRV_ASSEMBLY_SRCS
        vktSpvAsmConditionalBranchTests.hpp
        vktSpvAsmIndexingTests.cpp
        vktSpvAsmIndexingTests.hpp
+       vktSpvAsmImageSamplerTests.cpp
+       vktSpvAsmImageSamplerTests.hpp
        vktSpvAsmComputeShaderCase.cpp
        vktSpvAsmComputeShaderCase.hpp
        vktSpvAsmComputeShaderTestUtil.cpp
index 487f394..79f1e17 100644 (file)
@@ -42,27 +42,39 @@ using std::vector;
 typedef vkt::SpirVAssembly::AllocationMp                       AllocationMp;
 typedef vkt::SpirVAssembly::AllocationSp                       AllocationSp;
 
-typedef Unique<VkBuffer>                                                       BufferHandleUp;
+//typedef Unique<VkBuffer>                                                     BufferHandleUp;
+//typedef de::SharedPtr<BufferHandleUp>                                BufferHandleSp;
+
+typedef vk::Unique<VkBuffer>                                           BufferHandleUp;
+typedef vk::Unique<VkImage>                                                    ImageHandleUp;
+typedef vk::Unique<VkImageView>                                                ImageViewHandleUp;
+typedef vk::Unique<VkSampler>                                          SamplerHandleUp;
 typedef de::SharedPtr<BufferHandleUp>                          BufferHandleSp;
+typedef de::SharedPtr<ImageHandleUp>                           ImageHandleSp;
+typedef de::SharedPtr<ImageViewHandleUp>                       ImageViewHandleSp;
+typedef de::SharedPtr<SamplerHandleUp>                         SamplerHandleSp;
 
 /*--------------------------------------------------------------------*//*!
- * \brief Create storage buffer, allocate and bind memory for the buffer
+ * \brief Create a buffer, allocate and bind memory for the buffer
  *
  * The memory is created as host visible and passed back as a vk::Allocation
  * instance via outMemory.
  *//*--------------------------------------------------------------------*/
 Move<VkBuffer> createBufferAndBindMemory (const DeviceInterface& vkdi, const VkDevice& device, VkDescriptorType dtype, Allocator& allocator, size_t numBytes, AllocationMp* outMemory)
 {
-       VkBufferUsageFlags                      usageBit                = (VkBufferUsageFlags)0;
+       VkBufferUsageFlags                      usageBit                        = (VkBufferUsageFlags)0;
 
        switch (dtype)
        {
-               case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: usageBit = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; break;
-               case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: usageBit = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; break;
-               default:                                                                DE_ASSERT(false);
+               case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:                 usageBit = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;  break;
+               case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:                 usageBit = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;  break;
+               case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:                  usageBit = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;    break;
+               case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:                  usageBit = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;    break;
+               case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: usageBit = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;    break;
+               default:                                                                                DE_FATAL("Not implemented");
        }
 
-       const VkBufferCreateInfo bufferCreateInfo       =
+       const VkBufferCreateInfo        bufferCreateInfo        =
        {
                VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,   // sType
                DE_NULL,                                                                // pNext
@@ -74,9 +86,9 @@ Move<VkBuffer> createBufferAndBindMemory (const DeviceInterface& vkdi, const VkD
                DE_NULL,                                                                // pQueueFamilyIndices
        };
 
-       Move<VkBuffer>                          buffer                  (createBuffer(vkdi, device, &bufferCreateInfo));
-       const VkMemoryRequirements      requirements    = getBufferMemoryRequirements(vkdi, device, *buffer);
-       AllocationMp                            bufferMemory    = allocator.allocate(requirements, MemoryRequirement::HostVisible);
+       Move<VkBuffer>                          buffer                          (createBuffer(vkdi, device, &bufferCreateInfo));
+       const VkMemoryRequirements      requirements            = getBufferMemoryRequirements(vkdi, device, *buffer);
+       AllocationMp                            bufferMemory            = allocator.allocate(requirements, MemoryRequirement::HostVisible);
 
        VK_CHECK(vkdi.bindBufferMemory(device, *buffer, bufferMemory->getMemory(), bufferMemory->getOffset()));
        *outMemory = bufferMemory;
@@ -84,6 +96,154 @@ Move<VkBuffer> createBufferAndBindMemory (const DeviceInterface& vkdi, const VkD
        return buffer;
 }
 
+/*--------------------------------------------------------------------*//*!
+ * \brief Create image, allocate and bind memory for the image
+ *
+ *//*--------------------------------------------------------------------*/
+Move<VkImage> createImageAndBindMemory (const DeviceInterface& vkdi, const VkDevice& device, VkDescriptorType dtype, Allocator& allocator, deUint32 queueFamilyIndex, AllocationMp* outMemory)
+{
+       VkImageUsageFlags                       usageBits                       = (VkImageUsageFlags)0;
+
+       switch (dtype)
+       {
+               case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:                  usageBits = VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;       break;
+               case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:                  usageBits = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;       break;
+               case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: usageBits = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;       break;
+               default:                                                                                DE_FATAL("Not implemented");
+       }
+
+       const VkImageCreateInfo         resourceImageParams     =
+       {
+               VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                                                    //      VkStructureType         sType;
+               DE_NULL,                                                                                                                                //      const void*                     pNext;
+               0u,                                                                                                                                             //      VkImageCreateFlags      flags;
+               VK_IMAGE_TYPE_2D,                                                                                                               //      VkImageType                     imageType;
+               VK_FORMAT_R32G32B32A32_SFLOAT,                                                                                  //      VkFormat                        format;
+               { 8, 8, 1 },                                                                                                                    //  VkExtent3D                  extent;
+               1u,                                                                                                                                             //      deUint32                        mipLevels;
+               1u,                                                                                                                                             //      deUint32                        arraySize;
+               VK_SAMPLE_COUNT_1_BIT,                                                                                                  //      deUint32                        samples;
+               VK_IMAGE_TILING_OPTIMAL,                                                                                                //      VkImageTiling           tiling;
+               usageBits,                                                                                                                              //  VkImageUsageFlags   usage;
+               VK_SHARING_MODE_EXCLUSIVE,                                                                                              //      VkSharingMode           sharingMode;
+               1u,                                                                                                                                             //      deUint32                        queueFamilyCount;
+               &queueFamilyIndex,                                                                                                              //      const deUint32*         pQueueFamilyIndices;
+               VK_IMAGE_LAYOUT_UNDEFINED,                                                                                              //      VkImageLayout           initialLayout;
+       };
+
+       // Create image
+       Move<VkImage>                           image                           = createImage(vkdi, device, &resourceImageParams);
+       const VkMemoryRequirements      requirements            = getImageMemoryRequirements(vkdi, device, *image);
+       de::MovePtr<Allocation>         imageMemory                     = allocator.allocate(requirements, MemoryRequirement::Any);
+
+       VK_CHECK(vkdi.bindImageMemory(device, *image, imageMemory->getMemory(), imageMemory->getOffset()));
+       *outMemory = imageMemory;
+
+       return image;
+}
+
+void copyBufferToImage (const DeviceInterface& vkdi, const VkDevice& device, const VkQueue& queue, VkCommandBuffer cmdBuffer, VkBuffer buffer, VkImage image)
+{
+       const VkBufferImageCopy                 copyRegion                      =
+       {
+               0u,                                                                                             // VkDeviceSize                         bufferOffset;
+               0u,                                                                                             // deUint32                                     bufferRowLength;
+               0u,                                                                                             // deUint32                                     bufferImageHeight;
+               {
+                       VK_IMAGE_ASPECT_COLOR_BIT,                                              // VkImageAspectFlags           aspect;
+                       0u,                                                                                             // deUint32                                     mipLevel;
+                       0u,                                                                                             // deUint32                                     baseArrayLayer;
+                       1u,                                                                                             // deUint32                                     layerCount;
+               },                                                                                              // VkImageSubresourceLayers     imageSubresource;
+               { 0, 0, 0 },                                                                    // VkOffset3D                           imageOffset;
+               { 8, 8, 1 }                                                                             // VkExtent3D                           imageExtent;
+       };
+
+       // Copy buffer to image
+       const VkCommandBufferBeginInfo  cmdBufferBeginInfo      =
+       {
+               VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,    // VkStructureType                                                      sType;
+               DE_NULL,                                                                                // const void*                                                          pNext;
+               VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,    // VkCommandBufferUsageFlags                            flags;
+               DE_NULL                                                                                 // const VkCommandBufferInheritanceInfo*        pInheritanceInfo;
+       };
+
+       const VkImageMemoryBarrier              imageBarriers[]         =
+       {
+               {
+                       VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,         // VkStructureType                      sType;
+                       DE_NULL,                                                                        // const void*                          pNext;
+                       DE_NULL,                                                                        // VkAccessFlags                        srcAccessMask;
+                       VK_ACCESS_TRANSFER_WRITE_BIT,                           // VkAccessFlags                        dstAccessMask;
+                       VK_IMAGE_LAYOUT_UNDEFINED,                                      // VkImageLayout                        oldLayout;
+                       VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,           // VkImageLayout                        newLayout;
+                       VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                                     srcQueueFamilyIndex;
+                       VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                                     dstQueueFamilyIndex;
+                       image,                                                                          // VkImage                                      image;
+                       {                                                                                       // VkImageSubresourceRange      subresourceRange;
+                               VK_IMAGE_ASPECT_COLOR_BIT,              // VkImageAspectFlags   aspectMask;
+                               0u,                                                             // deUint32                             baseMipLevel;
+                               1u,                                                             // deUint32                             mipLevels;
+                               0u,                                                             // deUint32                             baseArraySlice;
+                               1u                                                              // deUint32                             arraySize;
+                       }
+               },
+               {
+                       VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,         // VkStructureType                      sType;
+                       DE_NULL,                                                                        // const void*                          pNext;
+                       VK_ACCESS_TRANSFER_WRITE_BIT,                           // VkAccessFlags                        srcAccessMask;
+                       VK_ACCESS_SHADER_READ_BIT,                                      // VkAccessFlags                        dstAccessMask;
+                       VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,           // VkImageLayout                        oldLayout;
+                       VK_IMAGE_LAYOUT_GENERAL,                                        // VkImageLayout                        newLayout;
+                       VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                                     srcQueueFamilyIndex;
+                       VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                                     dstQueueFamilyIndex;
+                       image,                                                                          // VkImage                                      image;
+                       {                                                                                       // VkImageSubresourceRange      subresourceRange;
+                               VK_IMAGE_ASPECT_COLOR_BIT,              // VkImageAspectFlags   aspectMask;
+                               0u,                                                             // deUint32                             baseMipLevel;
+                               1u,                                                             // deUint32                             mipLevels;
+                               0u,                                                             // deUint32                             baseArraySlice;
+                               1u                                                              // deUint32                             arraySize;
+                       }
+               },
+       };
+
+       VK_CHECK(vkdi.beginCommandBuffer(cmdBuffer, &cmdBufferBeginInfo));
+       vkdi.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL,
+               0u, DE_NULL, 1u, &imageBarriers[0]);
+       vkdi.cmdCopyBufferToImage(cmdBuffer, buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &copyRegion);
+       vkdi.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL,
+               0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &imageBarriers[1]);
+
+       VK_CHECK(vkdi.endCommandBuffer(cmdBuffer));
+
+       {
+               const VkFenceCreateInfo fenceParams     =
+               {
+                       VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,    //      VkStructureType         sType;
+                       DE_NULL,                                                                //      const void*                     pNext;
+                       0u,                                                                             //      VkFenceCreateFlags      flags;
+               };
+
+               const Unique<VkFence>   fence           (createFence(vkdi, device, &fenceParams));
+               const VkSubmitInfo              submitInfo      =
+               {
+                       VK_STRUCTURE_TYPE_SUBMIT_INFO,                  // VkStructureType                              sType;
+                       DE_NULL,                                                                // const void*                                  pNext;
+                       0u,                                                                             // deUint32                                             waitSemaphoreCount;
+                       DE_NULL,                                                                // const VkSemaphore*                   pWaitSemaphores;
+                       DE_NULL,                                                                // const VkPipelineStageFlags*  pWaitDstStageMask;
+                       1u,                                                                             // deUint32                                             commandBufferCount;
+                       &cmdBuffer,                                                             // const VkCommandBuffer*               pCommandBuffers;
+                       0u,                                                                             // deUint32                                             signalSemaphoreCount;
+                       DE_NULL                                                                 // const VkSemaphore*                   pSignalSemaphores;
+               };
+
+               VK_CHECK(vkdi.queueSubmit(queue, 1u, &submitInfo, *fence));
+               VK_CHECK(vkdi.waitForFences(device, 1u, &fence.get(), DE_TRUE, ~0ull));
+       }
+}
+
 void setMemory (const DeviceInterface& vkdi, const VkDevice& device, Allocation* destAlloc, size_t numBytes, const void* data)
 {
        void* const hostPtr = destAlloc->getHostPtr();
@@ -176,9 +336,9 @@ inline Move<VkDescriptorPool> createDescriptorPool (const DeviceInterface& vkdi,
  * The descriptor set's layout contains the given descriptor types,
  * sequentially binded to binding points starting from 0.
  *//*--------------------------------------------------------------------*/
-Move<VkDescriptorSet> createDescriptorSet (const DeviceInterface& vkdi, const VkDevice& device, VkDescriptorPool pool, VkDescriptorSetLayout layout, const vector<VkDescriptorType>& dtypes, const vector<VkDescriptorBufferInfo>& descriptorInfos)
+Move<VkDescriptorSet> createDescriptorSet (const DeviceInterface& vkdi, const VkDevice& device, VkDescriptorPool pool, VkDescriptorSetLayout layout, const vector<VkDescriptorType>& dtypes, const vector<VkDescriptorBufferInfo>& descriptorInfos, const vector<VkDescriptorImageInfo>& descriptorImageInfos)
 {
-       DE_ASSERT(dtypes.size() == descriptorInfos.size());
+       DE_ASSERT(dtypes.size() == descriptorInfos.size() + descriptorImageInfos.size());
 
        const VkDescriptorSetAllocateInfo       allocInfo       =
        {
@@ -192,8 +352,31 @@ Move<VkDescriptorSet> createDescriptorSet (const DeviceInterface& vkdi, const Vk
        Move<VkDescriptorSet>                           descriptorSet   = allocateDescriptorSet(vkdi, device, &allocInfo);
        DescriptorSetUpdateBuilder                      builder;
 
+       deUint32                                                        bufferNdx               = 0u;
+       deUint32                                                        imageNdx                = 0u;
+
        for (deUint32 descriptorNdx = 0; descriptorNdx < dtypes.size(); ++descriptorNdx)
-               builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(descriptorNdx), dtypes[descriptorNdx], &descriptorInfos[descriptorNdx]);
+       {
+               switch (dtypes[descriptorNdx])
+               {
+                       // Write buffer descriptor
+                       case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
+                       case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
+                               builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(descriptorNdx), dtypes[descriptorNdx], &descriptorInfos[bufferNdx++]);
+                               break;
+
+                       // Write image/sampler descriptor
+                       case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
+                       case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
+                       case VK_DESCRIPTOR_TYPE_SAMPLER:
+                       case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
+                               builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(descriptorNdx), dtypes[descriptorNdx], &descriptorImageInfos[imageNdx++]);
+                               break;
+
+                       default:
+                               DE_FATAL("Not implemented");
+               }
+       }
        builder.update(vkdi, device);
 
        return descriptorSet;
@@ -249,17 +432,6 @@ Move<VkPipeline> createComputePipeline (const DeviceInterface& vkdi, const VkDev
        return createComputePipeline(vkdi, device, (VkPipelineCache)0u, &pipelineCreateInfo);
 }
 
-/*--------------------------------------------------------------------*//*!
- * \brief Create a command pool
- *
- * The created command pool is designated for use on the queue type
- * represented by the given queueFamilyIndex.
- *//*--------------------------------------------------------------------*/
-Move<VkCommandPool> createCommandPool (const DeviceInterface& vkdi, VkDevice device, deUint32 queueFamilyIndex)
-{
-       return createCommandPool(vkdi, device, 0u, queueFamilyIndex);
-}
-
 } // anonymous
 
 namespace vkt
@@ -317,6 +489,18 @@ SpvAsmComputeShaderInstance::SpvAsmComputeShaderInstance (Context& ctx, const Co
 {
 }
 
+VkImageUsageFlags getMatchingComputeImageUsageFlags (VkDescriptorType dType)
+{
+       switch (dType)
+       {
+               case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:                  return VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+               case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:                  return VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+               case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: return VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+               default:                                                                                DE_FATAL("Not implemented");
+       }
+       return (VkImageUsageFlags)0;
+}
+
 tcu::TestStatus SpvAsmComputeShaderInstance::iterate (void)
 {
        const VkPhysicalDeviceFeatures&         features                        = m_context.getDeviceFeatures();
@@ -360,24 +544,34 @@ tcu::TestStatus SpvAsmComputeShaderInstance::iterate (void)
        }
 
        // defer device and resource creation until after feature checks
-       const Unique<VkDevice>                          vkDevice                        (createDeviceWithExtensions(m_context, m_context.getUniversalQueueFamilyIndex(), m_context.getDeviceExtensions(), m_shaderSpec.extensions));
+       const deUint32                                          queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
+       const Unique<VkDevice>                          vkDevice                        (createDeviceWithExtensions(m_context, queueFamilyIndex, m_context.getDeviceExtensions(), m_shaderSpec.extensions));
        const VkDevice&                                         device                          = *vkDevice;
        const DeviceDriver                                      vkDeviceInterface       (m_context.getInstanceInterface(), device);
        const DeviceInterface&                          vkdi                            = vkDeviceInterface;
        const de::UniquePtr<vk::Allocator>      vkAllocator                     (createAllocator(m_context.getInstanceInterface(), m_context.getPhysicalDevice(), vkDeviceInterface, device));
        Allocator&                                                      allocator                       = *vkAllocator;
-       const VkQueue                                           queue                           (getDeviceQueue(vkDeviceInterface, device, m_context.getUniversalQueueFamilyIndex(), 0));
+       const VkQueue                                           queue                           (getDeviceQueue(vkDeviceInterface, device, queueFamilyIndex, 0));
 
        vector<AllocationSp>                            inputAllocs;
        vector<AllocationSp>                            outputAllocs;
        vector<BufferHandleSp>                          inputBuffers;
+       vector<ImageHandleSp>                           inputImages;
+       vector<ImageViewHandleSp>                       inputImageViews;
+       vector<SamplerHandleSp>                         inputSamplers;
        vector<BufferHandleSp>                          outputBuffers;
        vector<VkDescriptorBufferInfo>          descriptorInfos;
+       vector<VkDescriptorImageInfo>           descriptorImageInfos;
        vector<VkDescriptorType>                        descriptorTypes;
 
        DE_ASSERT(!m_shaderSpec.outputs.empty());
 
-       // Create buffer object, allocate storage, and create view for all input/output buffers.
+       // Create command pool and command buffer
+
+       const Unique<VkCommandPool>                     cmdPool                         (createCommandPool(vkdi, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
+       Unique<VkCommandBuffer>                         cmdBuffer                       (allocateCommandBuffer(vkdi, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
+
+       // Create buffer and image objects, allocate storage, and create view for all input/output buffers and images.
 
        for (deUint32 inputNdx = 0; inputNdx < m_shaderSpec.inputs.size(); ++inputNdx)
        {
@@ -386,19 +580,194 @@ tcu::TestStatus SpvAsmComputeShaderInstance::iterate (void)
                else
                        descriptorTypes.push_back(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
 
-               AllocationMp            alloc;
-               const BufferSp&         input           = m_shaderSpec.inputs[inputNdx];
-               vector<deUint8>         inputBytes;
+               const VkDescriptorType  descType        = descriptorTypes[inputNdx];
 
-               input->getBytes(inputBytes);
+               const bool                              hasImage        = (descType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)        ||
+                                                                                         (descType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)        ||
+                                                                                         (descType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
 
-               const size_t            numBytes        = inputBytes.size();
-               BufferHandleUp*         buffer          = new BufferHandleUp(createBufferAndBindMemory(vkdi, device, descriptorTypes.back(), allocator, numBytes, &alloc));
+               const bool                              hasSampler      = (descType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)        ||
+                                                                                         (descType == VK_DESCRIPTOR_TYPE_SAMPLER)                      ||
+                                                                                         (descType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
 
-               setMemory(vkdi, device, &*alloc, numBytes, &inputBytes.front());
-               descriptorInfos.push_back(vk::makeDescriptorBufferInfo(**buffer, 0u, numBytes));
-               inputBuffers.push_back(BufferHandleSp(buffer));
-               inputAllocs.push_back(de::SharedPtr<Allocation>(alloc.release()));
+               // Buffer
+               if (!hasImage && !hasSampler)
+               {
+                       const BufferSp&         input                   = m_shaderSpec.inputs[inputNdx];
+                       vector<deUint8>         inputBytes;
+
+                       input->getBytes(inputBytes);
+
+                       const size_t            numBytes                = inputBytes.size();
+
+                       AllocationMp            bufferAlloc;
+                       BufferHandleUp*         buffer                  = new BufferHandleUp(createBufferAndBindMemory(vkdi, device, descType, allocator, numBytes, &bufferAlloc));
+
+                       setMemory(vkdi, device, &*bufferAlloc, numBytes, &inputBytes.front());
+                       inputBuffers.push_back(BufferHandleSp(buffer));
+                       inputAllocs.push_back(de::SharedPtr<Allocation>(bufferAlloc.release()));
+               }
+               // Image
+               else if (hasImage)
+               {
+                       const BufferSp&         input                   = m_shaderSpec.inputs[inputNdx];
+                       vector<deUint8>         inputBytes;
+
+                       input->getBytes(inputBytes);
+
+                       const size_t            numBytes                = inputBytes.size();
+
+                       AllocationMp            bufferAlloc;
+                       BufferHandleUp*         buffer                  = new BufferHandleUp(createBufferAndBindMemory(vkdi, device, descType, allocator, numBytes, &bufferAlloc));
+
+                       AllocationMp            imageAlloc;
+                       ImageHandleUp*          image                   = new ImageHandleUp(createImageAndBindMemory(vkdi, device, descType, allocator, queueFamilyIndex, &imageAlloc));
+
+                       setMemory(vkdi, device, &*bufferAlloc, numBytes, &inputBytes.front());
+
+                       inputBuffers.push_back(BufferHandleSp(buffer));
+                       inputAllocs.push_back(de::SharedPtr<Allocation>(bufferAlloc.release()));
+
+                       inputImages.push_back(ImageHandleSp(image));
+                       inputAllocs.push_back(de::SharedPtr<Allocation>(imageAlloc.release()));
+
+                       copyBufferToImage(vkdi, device, queue, cmdBuffer.get(), buffer->get(), image->get());
+               }
+       }
+
+       deUint32                                                        imageNdx                        = 0u;
+       deUint32                                                        bufferNdx                       = 0u;
+
+       for (deUint32 inputNdx = 0; inputNdx < descriptorTypes.size(); ++inputNdx)
+       {
+               const VkDescriptorType  descType        = descriptorTypes[inputNdx];
+
+               const bool                              hasImage        = (descType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)        ||
+                                                                                         (descType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)        ||
+                                                                                         (descType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
+
+               const bool                              hasSampler      = (descType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)        ||
+                                                                                         (descType == VK_DESCRIPTOR_TYPE_SAMPLER)                      ||
+                                                                                         (descType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
+
+               // Create image view and sampler
+               if (hasImage || hasSampler)
+               {
+                       if (descType != VK_DESCRIPTOR_TYPE_SAMPLER)
+                       {
+                               const VkImageViewCreateInfo     imgViewParams   =
+                               {
+                                       VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,       //      VkStructureType                 sType;
+                                       DE_NULL,                                                                        //      const void*                             pNext;
+                                       0u,                                                                                     //      VkImageViewCreateFlags  flags;
+                                       **inputImages[imageNdx++],                                      //      VkImage                                 image;
+                                       VK_IMAGE_VIEW_TYPE_2D,                                          //      VkImageViewType                 viewType;
+                                       VK_FORMAT_R32G32B32A32_SFLOAT,                          //      VkFormat                                format;
+                                       {
+                                               VK_COMPONENT_SWIZZLE_R,
+                                               VK_COMPONENT_SWIZZLE_G,
+                                               VK_COMPONENT_SWIZZLE_B,
+                                               VK_COMPONENT_SWIZZLE_A
+                                       },                                                                                      //      VkChannelMapping                channels;
+                                       {
+                                               VK_IMAGE_ASPECT_COLOR_BIT,                                      //      VkImageAspectFlags              aspectMask;
+                                               0u,                                                                                     //      deUint32                                baseMipLevel;
+                                               1u,                                                                                     //      deUint32                                mipLevels;
+                                               0u,                                                                                     //      deUint32                                baseArrayLayer;
+                                               1u,                                                                                     //      deUint32                                arraySize;
+                                       },                                                                                      //      VkImageSubresourceRange subresourceRange;
+                               };
+
+                               Move<VkImageView>                       imgView                 (createImageView(vkdi, *vkDevice, &imgViewParams));
+                               inputImageViews.push_back(ImageViewHandleSp(new ImageViewHandleUp(imgView)));
+                       }
+
+                       if (hasSampler)
+                       {
+                               const VkSamplerCreateInfo       samplerParams   =
+                               {
+                                       VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,          // VkStructureType                      sType;
+                                       DE_NULL,                                                                        // const void*                          pNext;
+                                       0,                                                                                      // VkSamplerCreateFlags         flags;
+                                       VK_FILTER_NEAREST,                                                      // VkFilter                                     magFilter:
+                                       VK_FILTER_NEAREST,                                                      // VkFilter                                     minFilter;
+                                       VK_SAMPLER_MIPMAP_MODE_NEAREST,                         // VkSamplerMipmapMode          mipmapMode;
+                                       VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,          // VkSamplerAddressMode         addressModeU;
+                                       VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,          // VkSamplerAddressMode         addressModeV;
+                                       VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,          // VkSamplerAddressMode         addressModeW;
+                                       0.0f,                                                                           // float                                        mipLodBias;
+                                       VK_FALSE,                                                                       // VkBool32                                     anistoropyÉnable;
+                                       1.0f,                                                                           // float                                        maxAnisotropy;
+                                       VK_FALSE,                                                                       // VkBool32                                     compareEnable;
+                                       VK_COMPARE_OP_ALWAYS,                                           // VkCompareOp                          compareOp;
+                                       0.0f,                                                                           // float                                        minLod;
+                                       0.0f,                                                                           // float                                        maxLod;
+                                       VK_BORDER_COLOR_INT_OPAQUE_BLACK,                       // VkBorderColor                        borderColor;
+                                       VK_FALSE                                                                        // VkBool32                                     unnormalizedCoordinates;
+                               };
+
+                               Move<VkSampler>                         sampler                 (createSampler(vkdi, *vkDevice, &samplerParams));
+                               inputSamplers.push_back(SamplerHandleSp(new SamplerHandleUp(sampler)));
+                       }
+               }
+
+               // Create descriptor buffer and image infos
+               switch (descType)
+               {
+                       case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
+                       case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
+                       {
+                               const VkDescriptorBufferInfo bufInfo =
+                               {
+                                       **inputBuffers[bufferNdx++],                            // VkBuffer                                     buffer;
+                                       0,                                                                                      // VkDeviceSize                         offset;
+                                       VK_WHOLE_SIZE,                                                          // VkDeviceSize                         size;
+                               };
+                               descriptorInfos.push_back(bufInfo);
+                               break;
+                       }
+
+                       case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
+                       case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
+                       {
+                               const VkDescriptorImageInfo     imgInfo =
+                               {
+                                       DE_NULL,                                                                        // VkSampler                            sampler;
+                                       **inputImageViews.back(),                                       // VkImageView                          imageView;
+                                       VK_IMAGE_LAYOUT_GENERAL                                         // VkImageLayout                        imageLayout;
+                               };
+                               descriptorImageInfos.push_back(imgInfo);
+                               break;
+                       }
+
+                       case VK_DESCRIPTOR_TYPE_SAMPLER:
+                       {
+                               const VkDescriptorImageInfo     imgInfo =
+                               {
+                                       **inputSamplers.back(),                                         // VkSampler                            sampler;
+                                       DE_NULL,                                                                        // VkImageView                          imageView;
+                                       VK_IMAGE_LAYOUT_GENERAL                                         // VkImageLayout                        imageLayout;
+                               };
+                               descriptorImageInfos.push_back(imgInfo);
+                               break;
+                       }
+
+                       case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
+                       {
+
+                               const VkDescriptorImageInfo     imgInfo =
+                               {
+                                       **inputSamplers.back(),                                         // VkSampler                            sampler;
+                                       **inputImageViews.back(),                                       // VkImageView                          imageView;
+                                       VK_IMAGE_LAYOUT_GENERAL                                         // VkImageLayout                        imageLayout;
+                               };
+                               descriptorImageInfos.push_back(imgInfo);
+                               break;
+                       }
+
+                       default:
+                               DE_FATAL("Not implemented");
+               }
        }
 
        for (deUint32 outputNdx = 0; outputNdx < m_shaderSpec.outputs.size(); ++outputNdx)
@@ -425,7 +794,7 @@ tcu::TestStatus SpvAsmComputeShaderInstance::iterate (void)
        Unique<VkDescriptorSetLayout>           descriptorSetLayout     (createDescriptorSetLayout(vkdi, device, descriptorTypes));
        Unique<VkPipelineLayout>                        pipelineLayout          (createPipelineLayout(vkdi, device, *descriptorSetLayout, m_shaderSpec.pushConstants));
        Unique<VkDescriptorPool>                        descriptorPool          (createDescriptorPool(vkdi, device, descriptorTypes));
-       Unique<VkDescriptorSet>                         descriptorSet           (createDescriptorSet(vkdi, device, *descriptorPool, *descriptorSetLayout, descriptorTypes, descriptorInfos));
+       Unique<VkDescriptorSet>                         descriptorSet           (createDescriptorSet(vkdi, device, *descriptorPool, *descriptorSetLayout, descriptorTypes, descriptorInfos, descriptorImageInfos));
 
        // Create compute shader and pipeline.
 
@@ -434,11 +803,6 @@ tcu::TestStatus SpvAsmComputeShaderInstance::iterate (void)
 
        Unique<VkPipeline>                                      computePipeline         (createComputePipeline(vkdi, device, *pipelineLayout, *module, m_shaderSpec.entryPoint.c_str(), m_shaderSpec.specConstants));
 
-       // Create command buffer and record commands
-
-       const Unique<VkCommandPool>                     cmdPool                         (createCommandPool(vkdi, device, m_context.getUniversalQueueFamilyIndex()));
-       Unique<VkCommandBuffer>                         cmdBuffer                       (allocateCommandBuffer(vkdi, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
-
        const VkCommandBufferBeginInfo          cmdBufferBeginInfo      =
        {
                VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,    // sType
index 45207d9..e0434c4 100644 (file)
@@ -176,13 +176,28 @@ VkBufferUsageFlagBits getMatchingBufferUsageFlagBit(VkDescriptorType dType)
 {
        switch (dType)
        {
-               case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: return VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
-               case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: return VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
-               default:                                                                DE_ASSERT(0 && "not implemented");
+               case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:                 return VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
+               case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:                 return VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
+               case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:                  return VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
+               case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:                  return VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
+               case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: return VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
+               default:                                                                                DE_ASSERT(0 && "not implemented");
        }
        return (VkBufferUsageFlagBits)0;
 }
 
+VkImageUsageFlags getMatchingImageUsageFlags(VkDescriptorType dType)
+{
+       switch (dType)
+       {
+               case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:                  return VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+               case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:                  return VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+               case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: return VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+               default:                                                                                DE_FATAL("Not implemented");
+       }
+       return (VkImageUsageFlags)0;
+}
+
 static void requireFormatUsageSupport(const InstanceInterface& vki, VkPhysicalDevice physicalDevice, VkFormat format, VkImageTiling imageTiling, VkImageUsageFlags requiredUsageFlags)
 {
        VkFormatProperties              properties;
@@ -1102,7 +1117,7 @@ map<string, string> passthruInterface(const IFDataType& data_type)
 // %ip_${input_type} and %op_${output_type} should also be defined in the final code.
 map<string, string> fillInterfacePlaceholderVert (void)
 {
-       map<string, string>     fragments       ;
+       map<string, string>     fragments;
 
        fragments["IF_entrypoint"]              = "%IF_input %IF_output";
        fragments["IF_variable"]                =
@@ -1136,7 +1151,7 @@ map<string, string> fillInterfacePlaceholderVert (void)
 // %ip_${input_type} and %op_${output_type} should also be defined in the final code.
 map<string, string> fillInterfacePlaceholderFrag (void)
 {
-       map<string, string>     fragments       ;
+       map<string, string>     fragments;
 
        fragments["IF_entrypoint"]              = "%IF_input %IF_output";
        fragments["IF_variable"]                =
@@ -1172,7 +1187,7 @@ map<string, string> fillInterfacePlaceholderFrag (void)
 // should also be defined in the final code.
 map<string, string> fillInterfacePlaceholderTessCtrl (void)
 {
-       map<string, string>     fragments       ;
+       map<string, string>     fragments;
 
        fragments["IF_entrypoint"]              = "%IF_input %IF_output";
        fragments["IF_variable"]                =
@@ -1219,7 +1234,7 @@ map<string, string> fillInterfacePlaceholderTessCtrl (void)
 // should also be defined in the final code.
 map<string, string> fillInterfacePlaceholderTessEvalGeom (void)
 {
-       map<string, string>     fragments       ;
+       map<string, string>     fragments;
 
        fragments["IF_entrypoint"]              = "%IF_input %IF_output";
        fragments["IF_variable"]                =
@@ -2152,7 +2167,7 @@ bool compare32BitFloat (float expected, float returned, tcu::TestLog& log)
        return false;
 }
 
-Move<VkBuffer> createBufferForResource(const DeviceInterface& vk, const VkDevice vkDevice, const Resource& resource, deUint32 queueFamilyIndex)
+Move<VkBuffer> createBufferForResource (const DeviceInterface& vk, const VkDevice vkDevice, const Resource& resource, deUint32 queueFamilyIndex)
 {
        vector<deUint8> resourceBytes;
        resource.second->getBytes(resourceBytes);
@@ -2172,6 +2187,132 @@ Move<VkBuffer> createBufferForResource(const DeviceInterface& vk, const VkDevice
        return createBuffer(vk, vkDevice, &resourceBufferParams);
 }
 
+Move<VkImage> createImageForResource (const DeviceInterface& vk, const VkDevice vkDevice, const Resource& resource, deUint32 queueFamilyIndex)
+{
+       const VkImageCreateInfo resourceImageParams     =
+       {
+               VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                                            //      VkStructureType         sType;
+               DE_NULL,                                                                                                                        //      const void*                     pNext;
+               0u,                                                                                                                                     //      VkImageCreateFlags      flags;
+               VK_IMAGE_TYPE_2D,                                                                                                       //      VkImageType                     imageType;
+               VK_FORMAT_R32G32B32A32_SFLOAT,                                                                          //      VkFormat                        format;
+               { 8, 8, 1 },                                                                                                            //      VkExtent3D                      extent;
+               1u,                                                                                                                                     //      deUint32                        mipLevels;
+               1u,                                                                                                                                     //      deUint32                        arraySize;
+               VK_SAMPLE_COUNT_1_BIT,                                                                                          //      deUint32                        samples;
+               VK_IMAGE_TILING_OPTIMAL,                                                                                        //      VkImageTiling           tiling;
+               getMatchingImageUsageFlags(resource.first),                                                     //      VkImageUsageFlags       usage;
+               VK_SHARING_MODE_EXCLUSIVE,                                                                                      //      VkSharingMode           sharingMode;
+               1u,                                                                                                                                     //      deUint32                        queueFamilyCount;
+               &queueFamilyIndex,                                                                                                      //      const deUint32*         pQueueFamilyIndices;
+               VK_IMAGE_LAYOUT_UNDEFINED                                                                                       //      VkImageLayout           initialLayout;
+       };
+
+       return createImage(vk, vkDevice, &resourceImageParams);
+}
+
+void copyBufferToImage (const DeviceInterface& vk, const VkDevice& device, const VkQueue& queue, VkCommandBuffer cmdBuffer, VkBuffer buffer, VkImage image)
+{
+       const VkBufferImageCopy                 copyRegion                      =
+       {
+               0u,                                                                                             // VkDeviceSize                         bufferOffset;
+               0u,                                                                                             // deUint32                                     bufferRowLength;
+               0u,                                                                                             // deUint32                                     bufferImageHeight;
+               {
+                       VK_IMAGE_ASPECT_COLOR_BIT,                                              // VkImageAspectFlags           aspect;
+                       0u,                                                                                             // deUint32                                     mipLevel;
+                       0u,                                                                                             // deUint32                                     baseArrayLayer;
+                       1u,                                                                                             // deUint32                                     layerCount;
+               },                                                                                              // VkImageSubresourceLayers     imageSubresource;
+               { 0, 0, 0 },                                                                    // VkOffset3D                           imageOffset;
+               { 8, 8, 1 }                                                                             // VkExtent3D                           imageExtent;
+       };
+
+       // Copy buffer to image
+       const VkCommandBufferBeginInfo  cmdBufferBeginInfo      =
+       {
+               VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,    // VkStructureType                                                      sType;
+               DE_NULL,                                                                                // const void*                                                          pNext;
+               VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,    // VkCommandBufferUsageFlags                            flags;
+               DE_NULL                                                                                 // const VkCommandBufferInheritanceInfo*        pInheritanceInfo;
+       };
+
+       const VkImageMemoryBarrier              imageBarriers[]         =
+       {
+               {
+                       VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,         // VkStructureType                      sType;
+                       DE_NULL,                                                                        // const void*                          pNext;
+                       DE_NULL,                                                                        // VkAccessFlags                        srcAccessMask;
+                       VK_ACCESS_TRANSFER_WRITE_BIT,                           // VkAccessFlags                        dstAccessMask;
+                       VK_IMAGE_LAYOUT_UNDEFINED,                                      // VkImageLayout                        oldLayout;
+                       VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,           // VkImageLayout                        newLayout;
+                       VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                                     srcQueueFamilyIndex;
+                       VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                                     dstQueueFamilyIndex;
+                       image,                                                                          // VkImage                                      image;
+                       {                                                                                       // VkImageSubresourceRange      subresourceRange;
+                               VK_IMAGE_ASPECT_COLOR_BIT,              // VkImageAspectFlags   aspectMask;
+                               0u,                                                             // deUint32                             baseMipLevel;
+                               1u,                                                             // deUint32                             mipLevels;
+                               0u,                                                             // deUint32                             baseArraySlice;
+                               1u                                                              // deUint32                             arraySize;
+                       }
+               },
+               {
+                       VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,         // VkStructureType                      sType;
+                       DE_NULL,                                                                        // const void*                          pNext;
+                       VK_ACCESS_TRANSFER_WRITE_BIT,                           // VkAccessFlags                        srcAccessMask;
+                       VK_ACCESS_SHADER_READ_BIT,                                      // VkAccessFlags                        dstAccessMask;
+                       VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,           // VkImageLayout                        oldLayout;
+                       VK_IMAGE_LAYOUT_GENERAL,                                        // VkImageLayout                        newLayout;
+                       VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                                     srcQueueFamilyIndex;
+                       VK_QUEUE_FAMILY_IGNORED,                                        // deUint32                                     dstQueueFamilyIndex;
+                       image,                                                                          // VkImage                                      image;
+                       {                                                                                       // VkImageSubresourceRange      subresourceRange;
+                               VK_IMAGE_ASPECT_COLOR_BIT,              // VkImageAspectFlags   aspectMask;
+                               0u,                                                             // deUint32                             baseMipLevel;
+                               1u,                                                             // deUint32                             mipLevels;
+                               0u,                                                             // deUint32                             baseArraySlice;
+                               1u                                                              // deUint32                             arraySize;
+                       }
+               },
+       };
+
+       VK_CHECK(vk.beginCommandBuffer(cmdBuffer, &cmdBufferBeginInfo));
+       vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL,
+               0u, DE_NULL, 1u, &imageBarriers[0]);
+       vk.cmdCopyBufferToImage(cmdBuffer, buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &copyRegion);
+       vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL,
+               0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &imageBarriers[1]);
+
+       VK_CHECK(vk.endCommandBuffer(cmdBuffer));
+
+       {
+               const VkFenceCreateInfo fenceParams     =
+               {
+                       VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,    //      VkStructureType         sType;
+                       DE_NULL,                                                                //      const void*                     pNext;
+                       0u,                                                                             //      VkFenceCreateFlags      flags;
+               };
+
+               const Unique<VkFence>   fence           (createFence(vk, device, &fenceParams));
+               const VkSubmitInfo              submitInfo      =
+               {
+                       VK_STRUCTURE_TYPE_SUBMIT_INFO,                  // VkStructureType                              sType;
+                       DE_NULL,                                                                // const void*                                  pNext;
+                       0u,                                                                             // deUint32                                             waitSemaphoreCount;
+                       DE_NULL,                                                                // const VkSemaphore*                   pWaitSemaphores;
+                       DE_NULL,                                                                // const VkPipelineStageFlags*  pWaitDstStageMask;
+                       1u,                                                                             // deUint32                                             commandBufferCount;
+                       &cmdBuffer,                                                             // const VkCommandBuffer*               pCommandBuffers;
+                       0u,                                                                             // deUint32                                             signalSemaphoreCount;
+                       DE_NULL                                                                 // const VkSemaphore*                   pSignalSemaphores;
+               };
+
+               VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence));
+               VK_CHECK(vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, ~0ull));
+       }
+}
+
 TestStatus runAndVerifyDefaultPipeline (Context& context, InstanceContext instance)
 {
        const InstanceInterface&                                        vkInstance                              = context.getInstanceInterface();
@@ -2295,13 +2436,13 @@ TestStatus runAndVerifyDefaultPipeline (Context& context, InstanceContext instan
        const size_t                                                    singleVertexDataSize    = 2 * sizeof(Vec4);
        const size_t                                                    vertexCount                             = sizeof(vertexData) / singleVertexDataSize;
 
-       Move<VkBuffer>                                                  vertexInputBuffer               ;
-       de::MovePtr<Allocation>                                 vertexInputMemory               ;
-       Move<VkBuffer>                                                  fragOutputBuffer                ;
-       de::MovePtr<Allocation>                                 fragOutputMemory                ;
-       Move<VkImage>                                                   fragOutputImage                 ;
-       de::MovePtr<Allocation>                                 fragOutputImageMemory   ;
-       Move<VkImageView>                                               fragOutputImageView             ;
+       Move<VkBuffer>                                                  vertexInputBuffer;
+       de::MovePtr<Allocation>                                 vertexInputMemory;
+       Move<VkBuffer>                                                  fragOutputBuffer;
+       de::MovePtr<Allocation>                                 fragOutputMemory;
+       Move<VkImage>                                                   fragOutputImage;
+       de::MovePtr<Allocation>                                 fragOutputImageMemory;
+       Move<VkImageView>                                               fragOutputImageView;
 
        const VkBufferCreateInfo                                vertexBufferParams              =
        {
@@ -2417,8 +2558,8 @@ TestStatus runAndVerifyDefaultPipeline (Context& context, InstanceContext instan
                VK_CHECK(vk.bindImageMemory(*vkDevice, *fragOutputImage, fragOutputImageMemory->getMemory(), fragOutputImageMemory->getOffset()));
        }
 
-       vector<VkAttachmentDescription>                 colorAttDescs                   ;
-       vector<VkAttachmentReference>                   colorAttRefs                    ;
+       vector<VkAttachmentDescription>                 colorAttDescs;
+       vector<VkAttachmentReference>                   colorAttRefs;
        {
                const VkAttachmentDescription           attDesc                                 =
                {
@@ -2525,26 +2666,34 @@ TestStatus runAndVerifyDefaultPipeline (Context& context, InstanceContext instan
        };
        const Unique<VkImageView>                               colorAttView                    (createImageView(vk, *vkDevice, &colorAttViewParams));
 
-       vector<VkImageView>                                             attViews                                ;
+       vector<VkImageView>                                             attViews;
        attViews.push_back(*colorAttView);
 
        // Handle resources requested by the test instantiation.
        const deUint32                                                  numInResources                  = static_cast<deUint32>(instance.resources.inputs.size());
        const deUint32                                                  numOutResources                 = static_cast<deUint32>(instance.resources.outputs.size());
        // These variables should be placed out of the following if block to avoid deallocation after out of scope.
-       vector<AllocationSp>                                    inResourceMemories              ;
-       vector<AllocationSp>                                    outResourceMemories             ;
-       vector<BufferHandleSp>                                  inResourceBuffers               ;
-       vector<BufferHandleSp>                                  outResourceBuffers              ;
-       Move<VkDescriptorPool>                                  descriptorPool                  ;
-       Move<VkDescriptorSetLayout>                             setLayout                               ;
+       vector<AllocationSp>                                    inResourceMemories;
+       vector<AllocationSp>                                    outResourceMemories;
+       vector<BufferHandleSp>                                  inResourceBuffers;
+       vector<BufferHandleSp>                                  outResourceBuffers;
+       vector<ImageHandleSp>                                   inResourceImages;
+       vector<ImageViewHandleSp>                               inResourceImageViews;
+       vector<SamplerHandleSp>                                 inResourceSamplers;
+       Move<VkDescriptorPool>                                  descriptorPool;
+       Move<VkDescriptorSetLayout>                             setLayout;
        VkDescriptorSetLayout                                   rawSetLayout                    = DE_NULL;
        VkDescriptorSet                                                 rawSet                                  = DE_NULL;
 
+       const Unique<VkCommandPool>                             cmdPool                                 (createCommandPool(vk, *vkDevice, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
+
+       // Command buffer
+       const Unique<VkCommandBuffer>                   cmdBuf                                  (allocateCommandBuffer(vk, *vkDevice, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
+
        if (numResources != 0)
        {
-               vector<VkDescriptorSetLayoutBinding>    setLayoutBindings       ;
-               vector<VkDescriptorPoolSize>                    poolSizes                       ;
+               vector<VkDescriptorSetLayoutBinding>    setLayoutBindings;
+               vector<VkDescriptorPoolSize>                    poolSizes;
 
                setLayoutBindings.reserve(numResources);
                poolSizes.reserve(numResources);
@@ -2552,30 +2701,81 @@ TestStatus runAndVerifyDefaultPipeline (Context& context, InstanceContext instan
                // Process all input resources.
                for (deUint32 inputNdx = 0; inputNdx < numInResources; ++inputNdx)
                {
-                       const Resource&                                 resource                                = instance.resources.inputs[inputNdx];
-                       // Create buffer and allocate memory.
-                       Move<VkBuffer>                                  resourceBuffer                  = createBufferForResource(vk, *vkDevice, resource, queueFamilyIndex);
-                       de::MovePtr<Allocation>                 resourceMemory                  = allocator.allocate(getBufferMemoryRequirements(vk, *vkDevice, *resourceBuffer), MemoryRequirement::HostVisible);
-                       vector<deUint8>                                 resourceBytes;
+                       const Resource& resource        = instance.resources.inputs[inputNdx];
 
-                       VK_CHECK(vk.bindBufferMemory(*vkDevice, *resourceBuffer, resourceMemory->getMemory(), resourceMemory->getOffset()));
+                       const bool              hasImage        = (resource.first == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)  ||
+                                                                                 (resource.first == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)  ||
+                                                                                 (resource.first == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
 
-                       // Copy data to memory.
-                       const VkMappedMemoryRange               range                                   =
+                       const bool              hasSampler      = (resource.first == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)  ||
+                                                                                 (resource.first == VK_DESCRIPTOR_TYPE_SAMPLER)                ||
+                                                                                 (resource.first == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
+
+                       // Resource is a buffer
+                       if (!hasImage && !hasSampler)
                        {
-                               VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,                          //      VkStructureType sType;
-                               DE_NULL,                                                                                        //      const void*             pNext;
-                               resourceMemory->getMemory(),                                            //      VkDeviceMemory  mem;
-                               0,                                                                                                      //      VkDeviceSize    offset;
-                               VK_WHOLE_SIZE,                                                                          //      VkDeviceSize    size;
-                       };
+                               Move<VkBuffer>                                  resourceBuffer                  = createBufferForResource(vk, *vkDevice, resource, queueFamilyIndex);
+                               de::MovePtr<Allocation>                 resourceMemory                  = allocator.allocate(getBufferMemoryRequirements(vk, *vkDevice, *resourceBuffer), MemoryRequirement::HostVisible);
+
+                               VK_CHECK(vk.bindBufferMemory(*vkDevice, *resourceBuffer, resourceMemory->getMemory(), resourceMemory->getOffset()));
+
+                               // Copy data to memory.
+                               {
+                                       const VkMappedMemoryRange               range                                   =
+                                       {
+                                               VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,                          //      VkStructureType sType;
+                                               DE_NULL,                                                                                        //      const void*             pNext;
+                                               resourceMemory->getMemory(),                                            //      VkDeviceMemory  mem;
+                                               0,                                                                                                      //      VkDeviceSize    offset;
+                                               VK_WHOLE_SIZE,                                                                          //      VkDeviceSize    size;
+                                       };
+
+                                       vector<deUint8>                                 resourceBytes;
+                                       resource.second->getBytes(resourceBytes);
+
+                                       deMemcpy(resourceMemory->getHostPtr(), &resourceBytes.front(), resourceBytes.size());
+                                       VK_CHECK(vk.flushMappedMemoryRanges(*vkDevice, 1u, &range));
+                               }
+
+                               inResourceMemories.push_back(AllocationSp(resourceMemory.release()));
+                               inResourceBuffers.push_back(BufferHandleSp(new BufferHandleUp(resourceBuffer)));
+                       }
+                       // Resource is an image
+                       else if (hasImage)
+                       {
+                               Move<VkBuffer>                                  resourceBuffer                  = createBufferForResource(vk, *vkDevice, resource, queueFamilyIndex);
+                               de::MovePtr<Allocation>                 resourceMemory                  = allocator.allocate(getBufferMemoryRequirements(vk, *vkDevice, *resourceBuffer), MemoryRequirement::HostVisible);
 
-                       resource.second->getBytes(resourceBytes);
-                       deMemcpy(resourceMemory->getHostPtr(), &resourceBytes.front(), resourceBytes.size());
-                       VK_CHECK(vk.flushMappedMemoryRanges(*vkDevice, 1u, &range));
+                               VK_CHECK(vk.bindBufferMemory(*vkDevice, *resourceBuffer, resourceMemory->getMemory(), resourceMemory->getOffset()));
+
+                               // Copy data to memory.
+                               {
+                                       const VkMappedMemoryRange               range                                   =
+                                       {
+                                               VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,                          //      VkStructureType sType;
+                                               DE_NULL,                                                                                        //      const void*             pNext;
+                                               resourceMemory->getMemory(),                                            //      VkDeviceMemory  mem;
+                                               0,                                                                                                      //      VkDeviceSize    offset;
+                                               VK_WHOLE_SIZE,                                                                          //      VkDeviceSize    size;
+                                       };
+
+                                       vector<deUint8>                                 resourceBytes;
+                                       resource.second->getBytes(resourceBytes);
+
+                                       deMemcpy(resourceMemory->getHostPtr(), &resourceBytes.front(), resourceBytes.size());
+                                       VK_CHECK(vk.flushMappedMemoryRanges(*vkDevice, 1u, &range));
+                               }
+
+                               Move<VkImage>                                   resourceImage                   = createImageForResource(vk, *vkDevice, resource, queueFamilyIndex);
+                               de::MovePtr<Allocation>                 resourceImageMemory             = allocator.allocate(getImageMemoryRequirements(vk, *vkDevice, *resourceImage), MemoryRequirement::Any);
 
-                       inResourceMemories.push_back(AllocationSp(resourceMemory.release()));
-                       inResourceBuffers.push_back(BufferHandleSp(new BufferHandleUp(resourceBuffer)));
+                               VK_CHECK(vk.bindImageMemory(*vkDevice, *resourceImage, resourceImageMemory->getMemory(), resourceImageMemory->getOffset()));
+
+                               copyBufferToImage(vk, *vkDevice, queue, *cmdBuf, resourceBuffer.get(), resourceImage.get());
+
+                               inResourceMemories.push_back(AllocationSp(resourceImageMemory.release()));
+                               inResourceImages.push_back(ImageHandleSp(new ImageHandleUp(resourceImage)));
+                       }
 
                        // Prepare descriptor bindings and pool sizes for creating descriptor set layout and pool.
                        const VkDescriptorSetLayoutBinding      binding                         =
@@ -2679,36 +2879,159 @@ TestStatus runAndVerifyDefaultPipeline (Context& context, InstanceContext instan
                VK_CHECK(vk.allocateDescriptorSets(*vkDevice, &setAllocParams, &rawSet));
 
                // Update descriptor set.
-               vector<VkWriteDescriptorSet>                    writeSpecs                      ;
-               vector<VkDescriptorBufferInfo>                  dBufferInfos            ;
+               vector<VkWriteDescriptorSet>                    writeSpecs;
+               vector<VkDescriptorBufferInfo>                  dBufferInfos;
+               vector<VkDescriptorImageInfo>                   dImageInfos;
 
                writeSpecs.reserve(numResources);
                dBufferInfos.reserve(numResources);
+               dImageInfos.reserve(numResources);
+
+               deUint32                                                                imgResourceNdx          = 0u;
+               deUint32                                                                bufResourceNdx          = 0u;
 
                for (deUint32 inputNdx = 0; inputNdx < numInResources; ++inputNdx)
                {
-                       const VkDescriptorBufferInfo            bufInfo                         =
+                       const Resource& resource        = instance.resources.inputs[inputNdx];
+
+                       const bool              hasImage        = (resource.first == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)  ||
+                                                                                 (resource.first == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)  ||
+                                                                                 (resource.first == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
+
+                       const bool              hasSampler      = (resource.first == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)  ||
+                                                                                 (resource.first == VK_DESCRIPTOR_TYPE_SAMPLER)                ||
+                                                                                 (resource.first == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
+
+                       // Create image view and sampler
+                       if (hasImage || hasSampler)
                        {
-                               **inResourceBuffers[inputNdx],                                          // buffer
-                               0,                                                                                                      // offset
-                               VK_WHOLE_SIZE,                                                                          // size
-                       };
-                       dBufferInfos.push_back(bufInfo);
+                               if (resource.first != VK_DESCRIPTOR_TYPE_SAMPLER)
+                               {
+                                       const VkImageViewCreateInfo     imgViewParams   =
+                                       {
+                                               VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,                       //      VkStructureType                         sType;
+                                               DE_NULL,                                                                                        //      const void*                                     pNext;
+                                               0u,                                                                                                     //      VkImageViewCreateFlags          flags;
+                                               **inResourceImages[imgResourceNdx++],                           //      VkImage                                         image;
+                                               VK_IMAGE_VIEW_TYPE_2D,                                                          //      VkImageViewType                         viewType;
+                                               VK_FORMAT_R32G32B32A32_SFLOAT,                                          //      VkFormat                                        format;
+                                               {
+                                                       VK_COMPONENT_SWIZZLE_R,
+                                                       VK_COMPONENT_SWIZZLE_G,
+                                                       VK_COMPONENT_SWIZZLE_B,
+                                                       VK_COMPONENT_SWIZZLE_A
+                                               },                                                                                                      //      VkChannelMapping                        channels;
+                                               {
+                                                       VK_IMAGE_ASPECT_COLOR_BIT,                                              //      VkImageAspectFlags      aspectMask;
+                                                       0u,                                                                                             //      deUint32                        baseMipLevel;
+                                                       1u,                                                                                             //      deUint32                        mipLevels;
+                                                       0u,                                                                                             //      deUint32                        baseArrayLayer;
+                                                       1u,                                                                                             //      deUint32                        arraySize;
+                                               },                                                                                                      //      VkImageSubresourceRange         subresourceRange;
+                                       };
+
+                                       Move<VkImageView>                       imgView                 (createImageView(vk, *vkDevice, &imgViewParams));
+                                       inResourceImageViews.push_back(ImageViewHandleSp(new ImageViewHandleUp(imgView)));
+                               }
+
+                               if (hasSampler)
+                               {
+                                       const VkSamplerCreateInfo       samplerParams   =
+                                       {
+                                               VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,          // VkStructureType                      sType;
+                                               DE_NULL,                                                                        // const void*                          pNext;
+                                               0,                                                                                      // VkSamplerCreateFlags         flags;
+                                               VK_FILTER_NEAREST,                                                      // VkFilter                                     magFilter:
+                                               VK_FILTER_NEAREST,                                                      // VkFilter                                     minFilter;
+                                               VK_SAMPLER_MIPMAP_MODE_NEAREST,                         // VkSamplerMipmapMode          mipmapMode;
+                                               VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,          // VkSamplerAddressMode         addressModeU;
+                                               VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,          // VkSamplerAddressMode         addressModeV;
+                                               VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,          // VkSamplerAddressMode         addressModeW;
+                                               0.0f,                                                                           // float                                        mipLodBias;
+                                               VK_FALSE,                                                                       // VkBool32                                     anistoropyÉnable;
+                                               1.0f,                                                                           // float                                        maxAnisotropy;
+                                               VK_FALSE,                                                                       // VkBool32                                     compareEnable;
+                                               VK_COMPARE_OP_ALWAYS,                                           // VkCompareOp                          compareOp;
+                                               0.0f,                                                                           // float                                        minLod;
+                                               0.0f,                                                                           // float                                        maxLod;
+                                               VK_BORDER_COLOR_INT_OPAQUE_BLACK,                       // VkBorderColor                        borderColor;
+                                               VK_FALSE                                                                        // VkBool32                                     unnormalizedCoordinates;
+                                       };
+
+                                       Move<VkSampler>                         sampler                 (createSampler(vk, *vkDevice, &samplerParams));
+                                       inResourceSamplers.push_back(SamplerHandleSp(new SamplerHandleUp(sampler)));
+                               }
+                       }
+
+                       // Create descriptor buffer and image infos
+                       switch (resource.first)
+                       {
+                               case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
+                               case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
+                               {
+                                       const VkDescriptorBufferInfo    bufInfo =
+                                       {
+                                               **inResourceBuffers[bufResourceNdx++],                          // buffer
+                                               0,                                                                                                      // offset
+                                               VK_WHOLE_SIZE,                                                                          // size
+                                       };
+                                       dBufferInfos.push_back(bufInfo);
+                                       break;
+                               }
+                               case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
+                               case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
+                               {
+                                       const VkDescriptorImageInfo             imgInfo =
+                                       {
+                                               DE_NULL,                                                                                                // sampler
+                                               **inResourceImageViews.back(),                                                  // imageView
+                                               VK_IMAGE_LAYOUT_GENERAL                                                                 // imageLayout
+                                       };
+                                       dImageInfos.push_back(imgInfo);
+                                       break;
+                               }
+                               case VK_DESCRIPTOR_TYPE_SAMPLER:
+                               {
+                                       const VkDescriptorImageInfo             imgInfo =
+                                       {
+                                               **inResourceSamplers.back(),                                                    // sampler
+                                               DE_NULL,                                                                                                // imageView
+                                               VK_IMAGE_LAYOUT_GENERAL                                                                 // imageLayout
+                                       };
+                                       dImageInfos.push_back(imgInfo);
+                                       break;
+                               }
+                               case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
+                               {
+
+                                       const VkDescriptorImageInfo             imgInfo =
+                                       {
+                                               **inResourceSamplers.back(),                                                    // sampler
+                                               **inResourceImageViews.back(),                                                  // imageView
+                                               VK_IMAGE_LAYOUT_GENERAL                                                                 // imageLayout
+                                       };
+                                       dImageInfos.push_back(imgInfo);
+                                       break;
+                               }
+                               default:
+                                       DE_FATAL("Not implemented");
+                       }
 
                        const VkWriteDescriptorSet                      writeSpec                       = {
-                               VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,                         // sType
-                               DE_NULL,                                                                                        // pNext
-                               rawSet,                                                                                         // dstSet
-                               inputNdx,                                                                                       // binding
-                               0,                                                                                                      // dstArrayElement
-                               1u,                                                                                                     // descriptorCount
-                               instance.resources.inputs[inputNdx].first,                      // descriptorType
-                               DE_NULL,                                                                                        // pImageInfo
-                               &dBufferInfos.back(),                                                           // pBufferInfo
-                               DE_NULL,                                                                                        // pTexelBufferView
+                               VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,                                                 // sType
+                               DE_NULL,                                                                                                                // pNext
+                               rawSet,                                                                                                                 // dstSet
+                               inputNdx,                                                                                                               // binding
+                               0,                                                                                                                              // dstArrayElement
+                               1u,                                                                                                                             // descriptorCount
+                               instance.resources.inputs[inputNdx].first,                                              // descriptorType
+                               ( (hasImage | hasSampler)       ? &dImageInfos.back()   : DE_NULL),     // pImageInfo
+                               (!(hasImage | hasSampler)       ? &dBufferInfos.back()  : DE_NULL),     // pBufferInfo
+                               DE_NULL,                                                                                                                // pTexelBufferView
                        };
                        writeSpecs.push_back(writeSpec);
                }
+
                for (deUint32 outputNdx = 0; outputNdx < numOutResources; ++outputNdx)
                {
                        const VkDescriptorBufferInfo            bufInfo                         =
@@ -2985,7 +3308,7 @@ TestStatus runAndVerifyDefaultPipeline (Context& context, InstanceContext instan
                vertexInputStateParams.vertexAttributeDescriptionCount += 1;
        }
 
-       vector<VkPipelineColorBlendAttachmentState>     attBlendStates                  ;
+       vector<VkPipelineColorBlendAttachmentState>     attBlendStates;
        const VkPipelineColorBlendAttachmentState       attBlendState                   =
        {
                DE_FALSE,                                                                                                       //      deUint32                blendEnable;
@@ -3101,11 +3424,6 @@ TestStatus runAndVerifyDefaultPipeline (Context& context, InstanceContext instan
 
        const Unique<VkFramebuffer>                             framebuffer                             (createFramebuffer(vk, *vkDevice, &framebufferParams));
 
-       const Unique<VkCommandPool>                             cmdPool                                 (createCommandPool(vk, *vkDevice, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
-
-       // Command buffer
-       const Unique<VkCommandBuffer>                   cmdBuf                                  (allocateCommandBuffer(vk, *vkDevice, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
-
        const VkCommandBufferBeginInfo                  cmdBufBeginParams               =
        {
                VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,                    //      VkStructureType                         sType;
@@ -3125,7 +3443,7 @@ TestStatus runAndVerifyDefaultPipeline (Context& context, InstanceContext instan
                        VK_ACCESS_HOST_WRITE_BIT,                                       //      VkMemoryOutputFlags     outputMask;
                        VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT,            //      VkMemoryInputFlags      inputMask;
                };
-               vector<VkImageMemoryBarrier>    colorAttBarriers        ;
+               vector<VkImageMemoryBarrier>    colorAttBarriers;
 
                VkImageMemoryBarrier                    imgBarrier          =
                {
@@ -3160,7 +3478,7 @@ TestStatus runAndVerifyDefaultPipeline (Context& context, InstanceContext instan
        }
 
        {
-               vector<VkClearValue>                    clearValue              ;
+               vector<VkClearValue>                    clearValue;
                clearValue.push_back(makeClearValueColorF32(0.125f, 0.25f, 0.75f, 1.0f));
                if (needInterface)
                {
@@ -3270,7 +3588,7 @@ TestStatus runAndVerifyDefaultPipeline (Context& context, InstanceContext instan
        }
 
        {
-               vector<VkBufferMemoryBarrier> cpFinishBarriers          ;
+               vector<VkBufferMemoryBarrier> cpFinishBarriers;
                VkBufferMemoryBarrier                   copyFinishBarrier       =
                {
                        VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,        //      VkStructureType         sType;
index b1b93c0..6c62933 100644 (file)
@@ -45,7 +45,13 @@ namespace SpirVAssembly
 {
 
 typedef vk::Unique<VkBuffer>                                                                           BufferHandleUp;
+typedef vk::Unique<VkImage>                                                                                    ImageHandleUp;
+typedef vk::Unique<VkImageView>                                                                                ImageViewHandleUp;
+typedef vk::Unique<VkSampler>                                                                          SamplerHandleUp;
 typedef de::SharedPtr<BufferHandleUp>                                                          BufferHandleSp;
+typedef de::SharedPtr<ImageHandleUp>                                                           ImageHandleSp;
+typedef de::SharedPtr<ImageViewHandleUp>                                                       ImageViewHandleSp;
+typedef de::SharedPtr<SamplerHandleUp>                                                         SamplerHandleSp;
 typedef vk::Unique<vk::VkShaderModule>                                                         ModuleHandleUp;
 typedef de::SharedPtr<ModuleHandleUp>                                                          ModuleHandleSp;
 typedef std::pair<std::string, vk::VkShaderStageFlagBits>                      EntryToStage;
diff --git a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmImageSamplerTests.cpp b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmImageSamplerTests.cpp
new file mode 100644 (file)
index 0000000..46c6135
--- /dev/null
@@ -0,0 +1,815 @@
+/*-------------------------------------------------------------------------
+ * 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 images and samplers.
+ *//*--------------------------------------------------------------------*/
+
+#include "vktSpvAsmImageSamplerTests.hpp"
+#include "vktSpvAsmComputeShaderCase.hpp"
+#include "vktSpvAsmComputeShaderTestUtil.hpp"
+#include "vktSpvAsmGraphicsShaderTestUtil.hpp"
+
+namespace vkt
+{
+namespace SpirVAssembly
+{
+
+using namespace vk;
+using std::map;
+using std::string;
+using std::vector;
+using tcu::IVec3;
+using tcu::RGBA;
+using tcu::Vec4;
+
+namespace
+{
+enum TestType
+{
+       TESTTYPE_LOCAL_VARIABLES = 0,
+       TESTTYPE_PASS_IMAGE_TO_FUNCTION,
+       TESTTYPE_PASS_SAMPLER_TO_FUNCTION,
+       TESTTYPE_PASS_IMAGE_AND_SAMPLER_TO_FUNCTION,
+
+       TESTTYPE_LAST
+};
+
+enum ReadOp
+{
+       READOP_IMAGEREAD = 0,
+       READOP_IMAGEFETCH,
+       READOP_IMAGESAMPLE,
+
+       READOP_LAST
+};
+
+enum DescriptorType
+{
+       DESCRIPTOR_TYPE_STORAGE_IMAGE = 0,
+       DESCRIPTOR_TYPE_SAMPLED_IMAGE,
+       DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
+
+       DESCRIPTOR_TYPE_LAST
+};
+
+bool isValidTestCase (TestType testType, DescriptorType descriptorType, ReadOp readOp)
+{
+       // Check valid descriptor type and test type combinations
+       switch (testType)
+       {
+               case TESTTYPE_PASS_IMAGE_TO_FUNCTION:
+                       if (descriptorType != DESCRIPTOR_TYPE_STORAGE_IMAGE                             &&
+                               descriptorType != DESCRIPTOR_TYPE_SAMPLED_IMAGE                         )
+                                       return false;
+                       break;
+
+               case TESTTYPE_PASS_SAMPLER_TO_FUNCTION:
+                       if (descriptorType != DESCRIPTOR_TYPE_SAMPLED_IMAGE)
+                               return false;
+                       break;
+
+               case TESTTYPE_PASS_IMAGE_AND_SAMPLER_TO_FUNCTION:
+                       if (descriptorType != DESCRIPTOR_TYPE_SAMPLED_IMAGE)
+                               return false;
+                       break;
+
+               default:
+                       break;
+       }
+
+       // Check valid descriptor type and read operation combinations
+       switch (readOp)
+       {
+               case READOP_IMAGEREAD:
+                       if (descriptorType != DESCRIPTOR_TYPE_STORAGE_IMAGE)
+                               return false;
+                       break;
+
+               case READOP_IMAGEFETCH:
+                       if (descriptorType != DESCRIPTOR_TYPE_SAMPLED_IMAGE                             &&
+                               descriptorType != DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER        )
+                               return false;
+                       break;
+
+               case READOP_IMAGESAMPLE:
+                       if (descriptorType != DESCRIPTOR_TYPE_SAMPLED_IMAGE                             &&
+                               descriptorType != DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER        )
+                               return false;
+                       break;
+
+               default:
+                       break;
+       }
+
+       return true;
+}
+
+const char* getTestTypeName (TestType testType)
+{
+       switch (testType)
+       {
+               case TESTTYPE_LOCAL_VARIABLES:
+                       return "all_local_variables";
+
+               case TESTTYPE_PASS_IMAGE_TO_FUNCTION:
+                       return "pass_image_to_function";
+
+               case TESTTYPE_PASS_SAMPLER_TO_FUNCTION:
+                       return "pass_sampler_to_function";
+
+               case TESTTYPE_PASS_IMAGE_AND_SAMPLER_TO_FUNCTION:
+                       return "pass_image_and_sampler_to_function";
+
+               default:
+                       DE_FATAL("Unknown test type");
+                       return "";
+       }
+}
+
+const char* getReadOpName (ReadOp readOp)
+{
+       switch (readOp)
+       {
+               case READOP_IMAGEREAD:
+                       return "imageread";
+
+               case READOP_IMAGEFETCH:
+                       return "imagefetch";
+
+               case READOP_IMAGESAMPLE:
+                       return "imagesample";
+
+               default:
+                       DE_FATAL("Unknown readop");
+                       return "";
+       }
+}
+
+const char* getDescriptorName (DescriptorType descType)
+{
+       switch (descType)
+       {
+               case DESCRIPTOR_TYPE_STORAGE_IMAGE:
+                       return "storage_image";
+
+               case DESCRIPTOR_TYPE_SAMPLED_IMAGE:
+                       return "sampled_image";
+
+               case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
+                       return "combined_image_sampler";
+
+               default:
+                       DE_FATAL("Unknown descriptor type");
+                       return "";
+       }
+}
+
+VkDescriptorType getVkDescriptorType (DescriptorType descType)
+{
+       switch (descType)
+       {
+               case DESCRIPTOR_TYPE_STORAGE_IMAGE:
+                       return VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
+
+               case DESCRIPTOR_TYPE_SAMPLED_IMAGE:
+                       return VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
+
+               case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
+                       return VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+
+               default:
+                       DE_FATAL("Unknown descriptor type");
+                       return VK_DESCRIPTOR_TYPE_LAST;
+       }
+}
+
+// Get variables that are declared in the read function, ie. not passed as parameters
+std::string getFunctionDstVariableStr (ReadOp readOp, DescriptorType descType, TestType testType)
+{
+       const bool passNdx = (testType == TESTTYPE_LOCAL_VARIABLES);
+       const bool passImg = ((testType == TESTTYPE_PASS_IMAGE_TO_FUNCTION)                     || (testType == TESTTYPE_PASS_IMAGE_AND_SAMPLER_TO_FUNCTION));
+       const bool passSmp = ((testType == TESTTYPE_PASS_SAMPLER_TO_FUNCTION)           || (testType == TESTTYPE_PASS_IMAGE_AND_SAMPLER_TO_FUNCTION));
+
+       std::string result = "";
+
+       switch (descType)
+       {
+               case DESCRIPTOR_TYPE_STORAGE_IMAGE:
+               {
+                       switch (readOp)
+                       {
+                               case READOP_IMAGEREAD:
+                                       if (passNdx)
+                                               return  "           %func_img = OpLoad %Image %InputData\n";
+                                       break;
+
+                               default:
+                                       DE_FATAL("Not possible");
+                                       break;
+                       }
+                       break;
+               }
+               case DESCRIPTOR_TYPE_SAMPLED_IMAGE:
+               {
+                       switch (readOp)
+                       {
+                               case READOP_IMAGEFETCH:
+                                       if (passNdx)
+                                               return  "           %func_img = OpLoad %Image %InputData\n";
+
+                                       if (passSmp && !passImg)
+                                               return  "           %func_tmp = OpLoad %Image %InputData\n"
+                                                               "           %func_smi = OpSampledImage %SampledImage %func_tmp %func_smp\n"
+                                                               "           %func_img = OpImage %Image %func_smi\n";
+
+                                       if (passSmp && passImg)
+                                               return  "           %func_smi = OpSampledImage %SampledImage %func_tmp %func_smp\n"
+                                                               "           %func_img = OpImage %Image %func_smi\n";
+                                       break;
+
+                               case READOP_IMAGESAMPLE:
+                                       if (passNdx)
+                                               return  "           %func_img = OpLoad %Image %InputData\n"
+                                                               "           %func_smp = OpLoad %Sampler %SamplerData\n"
+                                                               "           %func_smi = OpSampledImage %SampledImage %func_img %func_smp\n";
+
+                                       if (passImg && !passSmp)
+                                               return  "           %func_smp = OpLoad %Sampler %SamplerData\n"
+                                                               "           %func_smi = OpSampledImage %SampledImage %func_img %func_smp\n";
+
+                                       if (passSmp && !passImg)
+                                               return  "           %func_img = OpLoad %Image %InputData\n"
+                                                               "           %func_smi = OpSampledImage %SampledImage %func_img %func_smp\n";
+
+                                       if (passSmp && passImg)
+                                               return  "           %func_smi = OpSampledImage %SampledImage %func_img %func_smp\n";
+                                       break;
+
+                               default:
+                                       DE_FATAL("Not possible");
+                       }
+                       break;
+               }
+
+               case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
+               {
+                       switch (readOp)
+                       {
+                               case READOP_IMAGEFETCH:
+                                       if (passNdx)
+                                               return  "           %func_smi = OpLoad %SampledImage %InputData\n"
+                                                               "           %func_img = OpImage %Image %func_smi\n";
+                                       break;
+
+                               case READOP_IMAGESAMPLE:
+                                       if (passNdx)
+                                               return  "           %func_smi = OpLoad %SampledImage %InputData\n";
+                                       break;
+
+                               default:
+                                       DE_FATAL("Not possible");
+                       }
+                       break;
+               }
+
+               default:
+                       DE_FATAL("Unknown descriptor type");
+       }
+
+       return result;
+}
+
+// Get variables that are passed to the read function
+std::string getFunctionSrcVariableStr (ReadOp readOp, DescriptorType descType, TestType testType)
+{
+       const bool passImg = ((testType == TESTTYPE_PASS_IMAGE_TO_FUNCTION)                     || (testType == TESTTYPE_PASS_IMAGE_AND_SAMPLER_TO_FUNCTION));
+       const bool passSmp = ((testType == TESTTYPE_PASS_SAMPLER_TO_FUNCTION)           || (testType == TESTTYPE_PASS_IMAGE_AND_SAMPLER_TO_FUNCTION));
+
+       string result = "";
+
+       switch (descType)
+       {
+               case DESCRIPTOR_TYPE_STORAGE_IMAGE:
+               {
+                       switch (readOp)
+                       {
+                               case READOP_IMAGEREAD:
+                                       if (passImg)
+                                               result +=       "           %call_img = OpLoad %Image %InputData\n";
+                                       break;
+
+                               default:
+                                       DE_FATAL("Not possible");
+                       }
+                       break;
+               }
+               case DESCRIPTOR_TYPE_SAMPLED_IMAGE:
+               {
+                       switch (readOp)
+                       {
+                               case READOP_IMAGEFETCH:
+                               case READOP_IMAGESAMPLE:
+                                       if (passImg)
+                                               result +=       "           %call_img = OpLoad %Image %InputData\n";
+
+                                       if (passSmp)
+                                               result +=       "           %call_smp = OpLoad %Sampler %SamplerData\n";
+                                       break;
+
+                               default:
+                                       DE_FATAL("Not possible");
+                       }
+                       break;
+               }
+               case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
+               {
+                       break;
+               }
+               default:
+                       DE_FATAL("Unknown descriptor type");
+       }
+
+       return result;
+}
+
+// Get parameter types for OpTypeFunction
+std::string getFunctionParamTypeStr (TestType testType)
+{
+       const bool passImg = ((testType == TESTTYPE_PASS_IMAGE_TO_FUNCTION)                     || (testType == TESTTYPE_PASS_IMAGE_AND_SAMPLER_TO_FUNCTION));
+       const bool passSmp = ((testType == TESTTYPE_PASS_SAMPLER_TO_FUNCTION)           || (testType == TESTTYPE_PASS_IMAGE_AND_SAMPLER_TO_FUNCTION));
+
+       string result = "";
+
+       if (passImg)
+               result += " %Image";
+
+       if (passSmp)
+               result += " %Sampler";
+
+       return result;
+}
+
+// Get argument names for OpFunctionCall
+std::string getFunctionSrcParamStr (TestType testType)
+{
+       const bool passImg = ((testType == TESTTYPE_PASS_IMAGE_TO_FUNCTION)                     || (testType == TESTTYPE_PASS_IMAGE_AND_SAMPLER_TO_FUNCTION));
+       const bool passSmp = ((testType == TESTTYPE_PASS_SAMPLER_TO_FUNCTION)           || (testType == TESTTYPE_PASS_IMAGE_AND_SAMPLER_TO_FUNCTION));
+
+       string result = "";
+
+       if (passImg)
+               result += " %call_img";
+
+       if (passSmp)
+               result += " %call_smp";
+
+       return result;
+}
+
+// Get OpFunctionParameters
+std::string getFunctionDstParamStr (ReadOp readOp, TestType testType)
+{
+       const bool passImg = ((testType == TESTTYPE_PASS_IMAGE_TO_FUNCTION)                     || (testType == TESTTYPE_PASS_IMAGE_AND_SAMPLER_TO_FUNCTION));
+       const bool passSmp = ((testType == TESTTYPE_PASS_SAMPLER_TO_FUNCTION)           || (testType == TESTTYPE_PASS_IMAGE_AND_SAMPLER_TO_FUNCTION));
+
+       string result = "";
+
+       if (readOp == READOP_IMAGESAMPLE)
+       {
+               if (passImg)
+                       result +=       "           %func_img = OpFunctionParameter %Image\n";
+
+               if (passSmp)
+                       result +=       "           %func_smp = OpFunctionParameter %Sampler\n";
+       }
+       else
+       {
+               if (passImg && !passSmp)
+                       result +=       "           %func_img = OpFunctionParameter %Image\n";
+
+               if (passSmp && !passImg)
+                       result +=       "           %func_smp = OpFunctionParameter %Sampler\n";
+
+               if (passImg && passSmp)
+                       result +=       "           %func_tmp = OpFunctionParameter %Image\n"
+                                               "           %func_smp = OpFunctionParameter %Sampler\n";
+       }
+
+       return result;
+}
+
+// Get read operation
+std::string getImageReadOpStr (ReadOp readOp)
+{
+       switch (readOp)
+       {
+               case READOP_IMAGEREAD:
+                       return "OpImageRead %v4f32 %func_img %coord";
+
+               case READOP_IMAGEFETCH:
+                       return "OpImageFetch %v4f32 %func_img %coord";
+
+               case READOP_IMAGESAMPLE:
+                       return "OpImageSampleExplicitLod %v4f32 %func_smi %normalcoordf Lod %c_f32_0";
+
+               default:
+                       DE_FATAL("Unknown readop");
+                       return "";
+       }
+}
+
+// Get types and pointers for input images and samplers
+std::string getImageSamplerTypeStr (DescriptorType descType)
+{
+       switch (descType)
+       {
+               case DESCRIPTOR_TYPE_STORAGE_IMAGE:
+                       return  "              %Image = OpTypeImage %f32 2D 0 0 0 2 Rgba32f\n"
+                                       "           %ImagePtr = OpTypePointer UniformConstant %Image\n"
+                                       "          %InputData = OpVariable %ImagePtr UniformConstant\n";
+
+               case DESCRIPTOR_TYPE_SAMPLED_IMAGE:
+                       return  "              %Image = OpTypeImage %f32 2D 0 0 0 1 Rgba32f\n"
+                                       "           %ImagePtr = OpTypePointer UniformConstant %Image\n"
+                                       "          %InputData = OpVariable %ImagePtr UniformConstant\n"
+
+                                       "            %Sampler = OpTypeSampler\n"
+                                       "         %SamplerPtr = OpTypePointer UniformConstant %Sampler\n"
+                                       "        %SamplerData = OpVariable %SamplerPtr UniformConstant\n"
+                                       "       %SampledImage = OpTypeSampledImage %Image\n";
+
+               case DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
+                       return  "              %Image = OpTypeImage %f32 2D 0 0 0 1 Rgba32f\n"
+                                       "       %SampledImage = OpTypeSampledImage %Image\n"
+                                       "         %SamplerPtr = OpTypePointer UniformConstant %SampledImage\n"
+                                       "          %InputData = OpVariable %SamplerPtr UniformConstant\n";
+
+               default:
+                       DE_FATAL("Unknown descriptor type");
+                       return "";
+       }
+}
+
+void addComputeImageSamplerTest (tcu::TestCaseGroup* group)
+{
+       tcu::TestContext& testCtx = group->getTestContext();
+
+       de::Random                              rnd                                     (deStringHash(group->getName()));
+       const deUint32                  numDataPoints           = 64;
+       RGBA                                    defaultColors[4];
+       vector<tcu::Vec4>               inputData;
+       vector<tcu::Vec4>               outputData;
+
+       inputData.reserve(numDataPoints);
+       outputData.reserve(numDataPoints);
+
+       for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
+               inputData.push_back(tcu::Vec4(rnd.getFloat(), rnd.getFloat(), rnd.getFloat(), rnd.getFloat()));
+
+       for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
+               outputData.push_back(inputData.at(numIdx));
+
+       for (deUint32 opNdx = 0u; opNdx < READOP_LAST; opNdx++)
+       {
+               de::MovePtr<tcu::TestCaseGroup> readOpGroup     (new tcu::TestCaseGroup(testCtx, getReadOpName((ReadOp)opNdx), ""));
+
+               for (deUint32 descNdx = 0u; descNdx < DESCRIPTOR_TYPE_LAST; descNdx++)
+               {
+                       de::MovePtr<tcu::TestCaseGroup> descGroup (new tcu::TestCaseGroup(testCtx, getDescriptorName((DescriptorType)descNdx), ""));
+
+                       for (deUint32 testNdx = 0u; testNdx < TESTTYPE_LAST; testNdx++)
+                       {
+                               if (!isValidTestCase((TestType)testNdx, (DescriptorType)descNdx, (ReadOp)opNdx))
+                                       continue;
+
+                               const std::string       imageReadOp                             = getImageReadOpStr((ReadOp)opNdx);
+
+                               const std::string       imageSamplerTypes               = getImageSamplerTypeStr((DescriptorType)descNdx);
+                               const std::string       functionParamTypes              = getFunctionParamTypeStr((TestType)testNdx);
+
+                               const std::string       functionSrcVariables    = getFunctionSrcVariableStr((ReadOp)opNdx, (DescriptorType)descNdx, (TestType)testNdx);
+                               const std::string       functionDstVariables    = getFunctionDstVariableStr((ReadOp)opNdx, (DescriptorType)descNdx, (TestType)testNdx);
+
+                               const std::string       functionSrcParams               = getFunctionSrcParamStr(TestType(testNdx));
+                               const std::string       functionDstParams               = getFunctionDstParamStr((ReadOp)opNdx, TestType(testNdx));
+
+                               getDefaultColors(defaultColors);
+
+                               ComputeShaderSpec       spec;
+
+                               spec.numWorkGroups      = IVec3(numDataPoints, 1, 1);
+                               spec.inputTypes[0]      = getVkDescriptorType((DescriptorType)descNdx);
+
+                               spec.inputs.push_back(BufferSp(new Vec4Buffer(inputData)));
+
+                               // Separate sampler for sampled images
+                               if ((DescriptorType)descNdx == DESCRIPTOR_TYPE_SAMPLED_IMAGE)
+                               {
+                                       vector<tcu::Vec4> dummyData;
+                                       spec.inputTypes[1] = VK_DESCRIPTOR_TYPE_SAMPLER;
+                                       spec.inputs.push_back(BufferSp(new Vec4Buffer(dummyData)));
+                               }
+
+                               // Shader is expected to pass the input image data to the output buffer
+                               spec.outputs.push_back(BufferSp(new Vec4Buffer(inputData)));
+
+                               const std::string       samplerDecoration               = spec.inputs.size() > 1?
+                                       "                       OpDecorate %SamplerData DescriptorSet 0\n"
+                                       "                       OpDecorate %SamplerData Binding 1\n"
+                                       : "";
+
+                               const string            shaderSource    =
+                                       "                       OpCapability Shader\n"
+                                       "                  %1 = OpExtInstImport \"GLSL.std.450\"\n"
+                                       "                       OpMemoryModel Logical GLSL450\n"
+                                       "                       OpEntryPoint GLCompute %main \"main\" %id\n"
+                                       "                       OpExecutionMode %main LocalSize 1 1 1\n"
+                                       "                       OpSource GLSL 430\n"
+                                       "                       OpDecorate %id BuiltIn GlobalInvocationId\n"
+                                       "                       OpDecorate %_arr_v4f_u32_64 ArrayStride 16\n"
+                                       "                       OpMemberDecorate %Output 0 Offset 0\n"
+                                       "                       OpDecorate %Output BufferBlock\n"
+                                       "                       OpDecorate %InputData DescriptorSet 0\n"
+                                       "                       OpDecorate %InputData Binding 0\n"
+
+                                       + samplerDecoration +
+
+                                       "                       OpDecorate %OutputData DescriptorSet 0\n"
+                                       "                       OpDecorate %OutputData Binding " + de::toString(spec.inputs.size()) + "\n"
+
+                                       "               %void = OpTypeVoid\n"
+                                       "                  %3 = OpTypeFunction %void\n"
+                                       "                %u32 = OpTypeInt 32 0\n"
+                                       "                %i32 = OpTypeInt 32 1\n"
+                                       "                %f32 = OpTypeFloat 32\n"
+                                       " %_ptr_Function_uint = OpTypePointer Function %u32\n"
+                                       "              %v3u32 = OpTypeVector %u32 3\n"
+                                       "   %_ptr_Input_v3u32 = OpTypePointer Input %v3u32\n"
+                                       "                 %id = OpVariable %_ptr_Input_v3u32 Input\n"
+                                       "            %c_f32_0 = OpConstant %f32 0.0\n"
+                                       "            %c_u32_0 = OpConstant %u32 0\n"
+                                       "            %c_i32_0 = OpConstant %i32 0\n"
+                                       "    %_ptr_Input_uint = OpTypePointer Input %u32\n"
+                                       "              %v2u32 = OpTypeVector %u32 2\n"
+                                       "              %v2f32 = OpTypeVector %f32 2\n"
+                                       "              %v4f32 = OpTypeVector %f32 4\n"
+                                       "           %uint_128 = OpConstant %u32 128\n"
+                                       "           %c_u32_64 = OpConstant %u32 64\n"
+                                       "            %c_u32_8 = OpConstant %u32 8\n"
+                                       "            %c_f32_8 = OpConstant %f32 8.0\n"
+                                       "        %c_v2f32_8_8 = OpConstantComposite %v2f32 %c_f32_8 %c_f32_8\n"
+                                       "    %_arr_v4f_u32_64 = OpTypeArray %v4f32 %c_u32_64\n"
+                                       "   %_ptr_Uniform_v4f = OpTypePointer Uniform %v4f32\n"
+                                       "             %Output = OpTypeStruct %_arr_v4f_u32_64\n"
+                                       "%_ptr_Uniform_Output = OpTypePointer Uniform %Output\n"
+                                       "         %OutputData = OpVariable %_ptr_Uniform_Output Uniform\n"
+
+                                       + imageSamplerTypes +
+
+                                       "     %read_func_type = OpTypeFunction %void %u32" + functionParamTypes + "\n"
+
+                                       "          %read_func = OpFunction %void None %read_func_type\n"
+                                       "           %func_ndx = OpFunctionParameter %u32\n"
+
+                                       + functionDstParams +
+
+                                       "          %funcentry = OpLabel\n"
+                                       "                %row = OpUMod %u32 %func_ndx %c_u32_8\n"
+                                       "                %col = OpUDiv %u32 %func_ndx %c_u32_8\n"
+                                       "              %coord = OpCompositeConstruct %v2u32 %row %col\n"
+                                       "             %coordf = OpConvertUToF %v2f32 %coord\n"
+                                       "       %normalcoordf = OpFDiv %v2f32 %coordf %c_v2f32_8_8\n"
+
+                                       + functionDstVariables +
+
+                                       "              %color = " + imageReadOp + "\n"
+                                       "                 %36 = OpAccessChain %_ptr_Uniform_v4f %OutputData %c_u32_0 %func_ndx\n"
+                                       "                       OpStore %36 %color\n"
+                                       "                       OpReturn\n"
+                                       "                       OpFunctionEnd\n"
+
+                                       "               %main = OpFunction %void None %3\n"
+                                       "                  %5 = OpLabel\n"
+                                       "                  %i = OpVariable %_ptr_Function_uint Function\n"
+                                       "                 %14 = OpAccessChain %_ptr_Input_uint %id %c_u32_0\n"
+                                       "                 %15 = OpLoad %u32 %14\n"
+                                       "                       OpStore %i %15\n"
+                                       "              %index = OpLoad %u32 %14\n"
+
+                                       + functionSrcVariables +
+
+                                       "                %res = OpFunctionCall %void %read_func %index" + functionSrcParams + "\n"
+                                       "                       OpReturn\n"
+                                       "                       OpFunctionEnd\n";
+
+                               spec.assembly                   = shaderSource;
+
+                               descGroup->addChild(new SpvAsmComputeShaderCase(testCtx, getTestTypeName((TestType)testNdx), "", spec));
+                       }
+                       readOpGroup->addChild(descGroup.release());
+               }
+               group->addChild(readOpGroup.release());
+       }
+}
+
+void addGraphicsImageSamplerTest (tcu::TestCaseGroup* group)
+{
+       tcu::TestContext& testCtx = group->getTestContext();
+
+       de::Random                              rnd                                     (deStringHash(group->getName()));
+       const deUint32                  numDataPoints           = 64;
+       RGBA                                    defaultColors[4];
+       vector<tcu::Vec4>               inputData;
+       vector<tcu::Vec4>               outputData;
+
+       inputData.reserve(numDataPoints);
+       outputData.reserve(numDataPoints);
+
+       for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
+               inputData.push_back(tcu::Vec4(rnd.getFloat(), rnd.getFloat(), rnd.getFloat(), rnd.getFloat()));
+
+       for (deUint32 numIdx = 0; numIdx < numDataPoints; ++numIdx)
+               outputData.push_back(inputData.at(numIdx));
+
+       for (deUint32 opNdx = 0u; opNdx < READOP_LAST; opNdx++)
+       {
+               de::MovePtr<tcu::TestCaseGroup> readOpGroup     (new tcu::TestCaseGroup(testCtx, getReadOpName((ReadOp)opNdx), ""));
+
+               for (deUint32 descNdx = 0u; descNdx < DESCRIPTOR_TYPE_LAST; descNdx++)
+               {
+                       de::MovePtr<tcu::TestCaseGroup> descGroup (new tcu::TestCaseGroup(testCtx, getDescriptorName((DescriptorType)descNdx), ""));
+
+                       for (deUint32 testNdx = 0u; testNdx < TESTTYPE_LAST; testNdx++)
+                       {
+                               if (!isValidTestCase((TestType)testNdx, (DescriptorType)descNdx, (ReadOp)opNdx))
+                                       continue;
+
+                               const std::string                               imageReadOp                             = getImageReadOpStr((ReadOp)opNdx);
+
+                               const std::string                               imageSamplerTypes               = getImageSamplerTypeStr((DescriptorType)descNdx);
+                               const std::string                               functionParamTypes              = getFunctionParamTypeStr((TestType)testNdx);
+
+                               const std::string                               functionSrcVariables    = getFunctionSrcVariableStr((ReadOp)opNdx, (DescriptorType)descNdx, (TestType)testNdx);
+                               const std::string                               functionDstVariables    = getFunctionDstVariableStr((ReadOp)opNdx, (DescriptorType)descNdx, (TestType)testNdx);
+
+                               const std::string                               functionSrcParams               = getFunctionSrcParamStr(TestType(testNdx));
+                               const std::string                               functionDstParams               = getFunctionDstParamStr((ReadOp)opNdx, TestType(testNdx));
+
+                               de::MovePtr<tcu::TestCaseGroup> typeGroup                               (new tcu::TestCaseGroup(testCtx, getTestTypeName((TestType)testNdx), ""));
+
+                               map<string, string>                             fragments;
+                               GraphicsResources                               resources;
+
+                               resources.inputs.push_back(std::make_pair(getVkDescriptorType((DescriptorType)descNdx), BufferSp(new Vec4Buffer(inputData))));
+
+                               // Separate sampler for sampled images
+                               if ((DescriptorType)descNdx == DESCRIPTOR_TYPE_SAMPLED_IMAGE)
+                               {
+                                       vector<tcu::Vec4> dummyData;
+                                       resources.inputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_SAMPLER, BufferSp(new Vec4Buffer(dummyData))));
+                               }
+
+                               // Shader is expected to pass the input image data to output buffer
+                               resources.outputs.push_back(std::make_pair(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,                   BufferSp(new Vec4Buffer(outputData))));
+
+                               const std::string                               samplerDecoration               = resources.inputs.size() > 1?
+                                       "                       OpDecorate %SamplerData DescriptorSet 0\n"
+                                       "                       OpDecorate %SamplerData Binding 1\n"
+                                       : "";
+
+                               getDefaultColors(defaultColors);
+
+                               fragments["pre_main"]   =
+                                       "           %c_u32_64 = OpConstant %u32 64\n"
+                                       "           %c_i32_64 = OpConstant %i32 64\n"
+                                       "            %c_i32_8 = OpConstant %i32 8\n"
+                                       "        %c_v2f32_8_8 = OpConstantComposite %v2f32 %c_f32_8 %c_f32_8\n"
+
+                                       "    %_arr_v4f_u32_64 = OpTypeArray %v4f32 %c_u32_64\n"
+                                       "   %_ptr_Uniform_v4f = OpTypePointer Uniform %v4f32\n"
+
+                                       "             %Output = OpTypeStruct %_arr_v4f_u32_64\n"
+                                       "%_ptr_Uniform_Output = OpTypePointer Uniform %Output\n"
+                                       "         %OutputData = OpVariable %_ptr_Uniform_Output Uniform\n"
+
+                                       + imageSamplerTypes +
+
+                                       "     %read_func_type = OpTypeFunction %void %i32" + functionParamTypes + "\n";
+
+                               fragments["decoration"] =
+                                       "                       OpDecorate %_arr_v4f_u32_64 ArrayStride 16\n"
+                                       "                       OpMemberDecorate %Output 0 Offset 0\n"
+                                       "                       OpDecorate %Output BufferBlock\n"
+                                       "                       OpDecorate %InputData DescriptorSet 0\n"
+                                       "                       OpDecorate %InputData Binding 0\n"
+
+                                       + samplerDecoration +
+
+                                       "OpDecorate %OutputData DescriptorSet 0\n"
+                                       "OpDecorate %OutputData Binding " + de::toString(resources.inputs.size()) + "\n";
+
+                               fragments["testfun"]    =
+                                       "          %read_func = OpFunction %void None %read_func_type\n"
+                                       "           %func_ndx = OpFunctionParameter %i32\n"
+
+                                       + functionDstParams +
+
+                                       "          %funcentry = OpLabel\n"
+
+                                       "                %row = OpSRem %i32 %func_ndx %c_i32_8\n"
+                                       "                %col = OpSDiv %i32 %func_ndx %c_i32_8\n"
+                                       "              %coord = OpCompositeConstruct %v2i32 %row %col\n"
+                                       "             %coordf = OpConvertSToF %v2f32 %coord\n"
+                                       "       %normalcoordf = OpFDiv %v2f32 %coordf %c_v2f32_8_8\n"
+
+                                       + functionDstVariables +
+
+                                       "              %color = " + imageReadOp + "\n"
+                                       "                 %36 = OpAccessChain %_ptr_Uniform_v4f %OutputData %c_i32_0 %func_ndx\n"
+                                       "                       OpStore %36 %color\n"
+
+                                       "                       OpReturn\n"
+                                       "                       OpFunctionEnd\n"
+
+                                       "          %test_code = OpFunction %v4f32 None %v4f32_function\n"
+                                       "              %param = OpFunctionParameter %v4f32\n"
+
+                                       "              %entry = OpLabel\n"
+
+                                       "                  %i = OpVariable %fp_i32 Function\n"
+                                       "                       OpStore %i %c_i32_0\n"
+                                       "                       OpBranch %loop\n"
+
+                                       "               %loop = OpLabel\n"
+                                       "                 %15 = OpLoad %i32 %i\n"
+                                       "                 %lt = OpSLessThan %bool %15 %c_i32_64\n"
+                                       "                       OpLoopMerge %merge %inc None\n"
+                                       "                       OpBranchConditional %lt %write %merge\n"
+
+                                       "              %write = OpLabel\n"
+                                       "              %index = OpLoad %i32 %i\n"
+
+                                       + functionSrcVariables +
+
+                                       "                %res = OpFunctionCall %void %read_func %index" + functionSrcParams + "\n"
+                                       "                       OpBranch %inc\n"
+
+                                       "                %inc = OpLabel\n"
+
+                                       "                 %37 = OpLoad %i32 %i\n"
+                                       "                 %39 = OpIAdd %i32 %37 %c_i32_1\n"
+                                       "                       OpStore %i %39\n"
+                                       "                       OpBranch %loop\n"
+
+                                       "              %merge = OpLabel\n"
+                                       "                       OpReturnValue %param\n"
+                                       "                       OpFunctionEnd\n"
+
+                                       "";
+
+                               createTestsForAllStages("shader", defaultColors, defaultColors, fragments, resources, vector<string>(), typeGroup.get());
+
+                               descGroup->addChild(typeGroup.release());
+                       }
+                       readOpGroup->addChild(descGroup.release());
+               }
+               group->addChild(readOpGroup.release());
+       }
+}
+} // anonymous
+
+tcu::TestCaseGroup* createImageSamplerComputeGroup (tcu::TestContext& testCtx)
+{
+       de::MovePtr<tcu::TestCaseGroup> group           (new tcu::TestCaseGroup(testCtx, "image_sampler", "Compute tests for combining images and samplers."));
+       addComputeImageSamplerTest(group.get());
+
+       return group.release();
+}
+
+tcu::TestCaseGroup* createImageSamplerGraphicsGroup (tcu::TestContext& testCtx)
+{
+       de::MovePtr<tcu::TestCaseGroup> group           (new tcu::TestCaseGroup(testCtx, "image_sampler", "Graphics tests for combining images and samplers."));
+       addGraphicsImageSamplerTest(group.get());
+
+       return group.release();
+}
+
+} // SpirVAssembly
+} // vkt
diff --git a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmImageSamplerTests.hpp b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmImageSamplerTests.hpp
new file mode 100644 (file)
index 0000000..378d4dc
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef _VKTSPVASMIMAGESAMPLERTESTS_HPP
+#define _VKTSPVASMIMAGESAMPLERTESTS_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 images and samplers.
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTestCase.hpp"
+
+namespace vkt
+{
+namespace SpirVAssembly
+{
+
+tcu::TestCaseGroup*    createImageSamplerComputeGroup  (tcu::TestContext& testCtx);
+tcu::TestCaseGroup*    createImageSamplerGraphicsGroup (tcu::TestContext& testCtx);
+
+} // SpirVAssembly
+} // vkt
+
+#endif // _VKTSPVASMIMAGESAMPLERTESTS_HPP
index d33010b..cded1bd 100644 (file)
@@ -53,6 +53,7 @@
 #include "vktSpvAsmUboMatrixPaddingTests.hpp"
 #include "vktSpvAsmConditionalBranchTests.hpp"
 #include "vktSpvAsmIndexingTests.hpp"
+#include "vktSpvAsmImageSamplerTests.hpp"
 #include "vktSpvAsmComputeShaderCase.hpp"
 #include "vktSpvAsmComputeShaderTestUtil.hpp"
 #include "vktSpvAsmGraphicsShaderTestUtil.hpp"
@@ -6234,8 +6235,7 @@ tcu::TestCaseGroup* createNoContractionTests(tcu::TestContext& testCtx)
                "%c_vec4_1       = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_1\n"
                "%c_f32_1pl2_23  = OpConstant %f32 0x1.000002p+0\n" // 1 + 2^-23
                "%c_f32_1mi2_23  = OpConstant %f32 0x1.fffffcp-1\n" // 1 - 2^-23
-               "%c_f32_n1pn24   = OpConstant %f32 -0x1p-24\n"
-               ;
+               "%c_f32_n1pn24   = OpConstant %f32 -0x1p-24\n";
 
        const char                                              function[]       =
                "%test_code      = OpFunction %v4f32 None %v4f32_function\n"
@@ -6421,8 +6421,8 @@ tcu::TestCaseGroup* createOpUndefTests(tcu::TestContext& testCtx)
                "%b = OpFAdd %f32 %a %actually_zero\n"
                "%ret = OpVectorInsertDynamic %v4f32 %param1 %b %c_i32_0\n"
                "OpReturnValue %ret\n"
-               "OpFunctionEnd\n"
-               ;
+               "OpFunctionEnd\n";
+
        createTestsForAllStages("float32", defaultColors, defaultColors, fragments, opUndefTests.get());
 
        fragments["testfun"] =
@@ -6434,8 +6434,8 @@ tcu::TestCaseGroup* createOpUndefTests(tcu::TestContext& testCtx)
                "%a = OpVectorExtractDynamic %f32 %param1 %zero\n"
                "%ret = OpVectorInsertDynamic %v4f32 %param1 %a %c_i32_0\n"
                "OpReturnValue %ret\n"
-               "OpFunctionEnd\n"
-               ;
+               "OpFunctionEnd\n";
+
        createTestsForAllStages("sint32", defaultColors, defaultColors, fragments, opUndefTests.get());
 
        fragments["testfun"] =
@@ -6447,8 +6447,8 @@ tcu::TestCaseGroup* createOpUndefTests(tcu::TestContext& testCtx)
                "%a = OpVectorExtractDynamic %f32 %param1 %zero\n"
                "%ret = OpVectorInsertDynamic %v4f32 %param1 %a %c_i32_0\n"
                "OpReturnValue %ret\n"
-               "OpFunctionEnd\n"
-               ;
+               "OpFunctionEnd\n";
+
        createTestsForAllStages("uint32", defaultColors, defaultColors, fragments, opUndefTests.get());
 
        fragments["testfun"] =
@@ -6482,8 +6482,8 @@ tcu::TestCaseGroup* createOpUndefTests(tcu::TestContext& testCtx)
                "%ret1 = OpVectorInsertDynamic %v4f32 %ret2 %sum_1 %c_i32_1\n"
                "%ret = OpVectorInsertDynamic %v4f32 %ret1 %sum_0 %c_i32_0\n"
                "OpReturnValue %ret\n"
-               "OpFunctionEnd\n"
-               ;
+               "OpFunctionEnd\n";
+
        createTestsForAllStages("vec4float32", defaultColors, defaultColors, fragments, opUndefTests.get());
 
        fragments["pre_main"] =
@@ -6519,8 +6519,8 @@ tcu::TestCaseGroup* createOpUndefTests(tcu::TestContext& testCtx)
                "%ret1 = OpVectorInsertDynamic %v4f32 %ret2 %sum_1 %c_i32_1\n"
                "%ret = OpVectorInsertDynamic %v4f32 %ret1 %sum_0 %c_i32_0\n"
                "OpReturnValue %ret\n"
-               "OpFunctionEnd\n"
-               ;
+               "OpFunctionEnd\n";
+
        createTestsForAllStages("matrix", defaultColors, defaultColors, fragments, opUndefTests.get());
 
        return opUndefTests.release();
@@ -6946,8 +6946,8 @@ tcu::TestCaseGroup* createLoopTests(tcu::TestContext& testCtx)
                "%result = OpVectorInsertDynamic %v4f32 %param1 %val %c_i32_0\n"
                "OpReturnValue %result\n"
 
-               "OpFunctionEnd\n"
-               ;
+               "OpFunctionEnd\n";
+
        createTestsForAllStages("single_block", defaultColors, defaultColors, fragments, testGroup.get());
 
        // Body comprised of multiple basic blocks.
@@ -8645,6 +8645,7 @@ tcu::TestCaseGroup* createInstructionTests (tcu::TestContext& testCtx)
        computeTests->addChild(createConditionalBranchComputeGroup(testCtx));
        computeTests->addChild(createIndexingComputeGroup(testCtx));
        computeTests->addChild(createVariablePointersComputeGroup(testCtx));
+       computeTests->addChild(createImageSamplerComputeGroup(testCtx));
        graphicsTests->addChild(createOpNopTests(testCtx));
        graphicsTests->addChild(createOpSourceTests(testCtx));
        graphicsTests->addChild(createOpSourceContinuedTests(testCtx));
@@ -8683,6 +8684,7 @@ tcu::TestCaseGroup* createInstructionTests (tcu::TestContext& testCtx)
        graphicsTests->addChild(createConditionalBranchGraphicsGroup(testCtx));
        graphicsTests->addChild(createIndexingGraphicsGroup(testCtx));
        graphicsTests->addChild(createVariablePointersGraphicsGroup(testCtx));
+       graphicsTests->addChild(createImageSamplerGraphicsGroup(testCtx));
 
        instructionTests->addChild(computeTests.release());
        instructionTests->addChild(graphicsTests.release());
index a55691f..b8e79bd 100644 (file)
@@ -168548,6 +168548,18 @@ dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.complex_types_compu
 dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.complex_types_compute.opptraccesschain_float_single_buffer_first_input
 dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.nullptr_compute.opvariable_initialized_null
 dEQP-VK.spirv_assembly.instruction.compute.variable_pointers.nullptr_compute.opselect_null_or_valid_ptr
+dEQP-VK.spirv_assembly.instruction.compute.image_sampler.imageread.storage_image.all_local_variables
+dEQP-VK.spirv_assembly.instruction.compute.image_sampler.imageread.storage_image.pass_image_to_function
+dEQP-VK.spirv_assembly.instruction.compute.image_sampler.imagefetch.sampled_image.all_local_variables
+dEQP-VK.spirv_assembly.instruction.compute.image_sampler.imagefetch.sampled_image.pass_image_to_function
+dEQP-VK.spirv_assembly.instruction.compute.image_sampler.imagefetch.sampled_image.pass_sampler_to_function
+dEQP-VK.spirv_assembly.instruction.compute.image_sampler.imagefetch.sampled_image.pass_image_and_sampler_to_function
+dEQP-VK.spirv_assembly.instruction.compute.image_sampler.imagefetch.combined_image_sampler.all_local_variables
+dEQP-VK.spirv_assembly.instruction.compute.image_sampler.imagesample.sampled_image.all_local_variables
+dEQP-VK.spirv_assembly.instruction.compute.image_sampler.imagesample.sampled_image.pass_image_to_function
+dEQP-VK.spirv_assembly.instruction.compute.image_sampler.imagesample.sampled_image.pass_sampler_to_function
+dEQP-VK.spirv_assembly.instruction.compute.image_sampler.imagesample.sampled_image.pass_image_and_sampler_to_function
+dEQP-VK.spirv_assembly.instruction.compute.image_sampler.imagesample.combined_image_sampler.all_local_variables
 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
@@ -171301,6 +171313,66 @@ dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.nullptr_graphics.o
 dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.nullptr_graphics.opselect_null_or_valid_ptr_tesse
 dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.nullptr_graphics.opselect_null_or_valid_ptr_geom
 dEQP-VK.spirv_assembly.instruction.graphics.variable_pointers.nullptr_graphics.opselect_null_or_valid_ptr_frag
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imageread.storage_image.all_local_variables.shader_vert
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imageread.storage_image.all_local_variables.shader_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imageread.storage_image.all_local_variables.shader_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imageread.storage_image.all_local_variables.shader_geom
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imageread.storage_image.all_local_variables.shader_frag
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imageread.storage_image.pass_image_to_function.shader_vert
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imageread.storage_image.pass_image_to_function.shader_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imageread.storage_image.pass_image_to_function.shader_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imageread.storage_image.pass_image_to_function.shader_geom
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imageread.storage_image.pass_image_to_function.shader_frag
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.sampled_image.all_local_variables.shader_vert
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.sampled_image.all_local_variables.shader_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.sampled_image.all_local_variables.shader_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.sampled_image.all_local_variables.shader_geom
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.sampled_image.all_local_variables.shader_frag
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.sampled_image.pass_image_to_function.shader_vert
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.sampled_image.pass_image_to_function.shader_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.sampled_image.pass_image_to_function.shader_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.sampled_image.pass_image_to_function.shader_geom
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.sampled_image.pass_image_to_function.shader_frag
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.sampled_image.pass_sampler_to_function.shader_vert
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.sampled_image.pass_sampler_to_function.shader_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.sampled_image.pass_sampler_to_function.shader_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.sampled_image.pass_sampler_to_function.shader_geom
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.sampled_image.pass_sampler_to_function.shader_frag
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.sampled_image.pass_image_and_sampler_to_function.shader_vert
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.sampled_image.pass_image_and_sampler_to_function.shader_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.sampled_image.pass_image_and_sampler_to_function.shader_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.sampled_image.pass_image_and_sampler_to_function.shader_geom
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.sampled_image.pass_image_and_sampler_to_function.shader_frag
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.combined_image_sampler.all_local_variables.shader_vert
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.combined_image_sampler.all_local_variables.shader_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.combined_image_sampler.all_local_variables.shader_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.combined_image_sampler.all_local_variables.shader_geom
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagefetch.combined_image_sampler.all_local_variables.shader_frag
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.sampled_image.all_local_variables.shader_vert
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.sampled_image.all_local_variables.shader_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.sampled_image.all_local_variables.shader_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.sampled_image.all_local_variables.shader_geom
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.sampled_image.all_local_variables.shader_frag
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.sampled_image.pass_image_to_function.shader_vert
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.sampled_image.pass_image_to_function.shader_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.sampled_image.pass_image_to_function.shader_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.sampled_image.pass_image_to_function.shader_geom
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.sampled_image.pass_image_to_function.shader_frag
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.sampled_image.pass_sampler_to_function.shader_vert
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.sampled_image.pass_sampler_to_function.shader_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.sampled_image.pass_sampler_to_function.shader_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.sampled_image.pass_sampler_to_function.shader_geom
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.sampled_image.pass_sampler_to_function.shader_frag
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.sampled_image.pass_image_and_sampler_to_function.shader_vert
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.sampled_image.pass_image_and_sampler_to_function.shader_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.sampled_image.pass_image_and_sampler_to_function.shader_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.sampled_image.pass_image_and_sampler_to_function.shader_geom
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.sampled_image.pass_image_and_sampler_to_function.shader_frag
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.combined_image_sampler.all_local_variables.shader_vert
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.combined_image_sampler.all_local_variables.shader_tessc
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.combined_image_sampler.all_local_variables.shader_tesse
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.combined_image_sampler.all_local_variables.shader_geom
+dEQP-VK.spirv_assembly.instruction.graphics.image_sampler.imagesample.combined_image_sampler.all_local_variables.shader_frag
 dEQP-VK.glsl.arrays.constructor.float3_vertex
 dEQP-VK.glsl.arrays.constructor.float3_fragment
 dEQP-VK.glsl.arrays.constructor.float4_vertex