Merge vk-gl-cts/master into vk-gl-cts/vulkan-cts-1.3.1
authorMatthew Netsch <quic_mnetsch@quicinc.com>
Sat, 11 Dec 2021 16:34:18 +0000 (11:34 -0500)
committerMatthew Netsch <quic_mnetsch@quicinc.com>
Sat, 11 Dec 2021 16:34:18 +0000 (11:34 -0500)
Change-Id: I851afbc7c49096c4a2e088335bf504eddea773ad

26 files changed:
1  2 
android/cts/master/vk-master-2021-03-01/api.txt
android/cts/master/vk-master-2021-03-01/image.txt
android/cts/master/vk-master-2021-03-01/pipeline.txt
android/cts/master/vk-master-2021-03-01/spirv-assembly.txt
android/cts/master/vk-master/api.txt
android/cts/master/vk-master/image.txt
android/cts/master/vk-master/pipeline.txt
android/cts/master/vk-master/spirv-assembly.txt
external/vulkancts/framework/vulkan/vkShaderToSpirV.cpp
external/vulkancts/modules/vulkan/amber/vktAmberTestCase.cpp
external/vulkancts/modules/vulkan/api/vktApiCopiesAndBlittingTests.cpp
external/vulkancts/modules/vulkan/api/vktApiFeatureInfo.cpp
external/vulkancts/modules/vulkan/binding_model/vktBindingValveMutableTests.cpp
external/vulkancts/modules/vulkan/draw/vktDrawMultipleInterpolationTests.cpp
external/vulkancts/modules/vulkan/fragment_shading_rate/vktAttachmentRateTests.cpp
external/vulkancts/modules/vulkan/pipeline/vktPipelineExtendedDynamicStateTests.cpp
external/vulkancts/modules/vulkan/renderpass/vktRenderPassFragmentDensityMapTests.cpp
external/vulkancts/modules/vulkan/renderpass/vktRenderPassTests.cpp
external/vulkancts/modules/vulkan/subgroups/vktSubgroupsMultipleDispatchesUniformSubgroupSizeTests.cpp
external/vulkancts/modules/vulkan/synchronization/vktSynchronizationImageLayoutTransitionTests.cpp
external/vulkancts/modules/vulkan/wsi/vktWsiSwapchainTests.cpp
external/vulkancts/mustpass/master/vk-default/api.txt
external/vulkancts/mustpass/master/vk-default/image.txt
external/vulkancts/mustpass/master/vk-default/pipeline.txt
external/vulkancts/mustpass/master/vk-default/spirv-assembly.txt
external/vulkancts/scripts/src/extensions_data.txt

@@@ -2104,11 -2147,10 +2284,15 @@@ dEQP-VK.spirv_assembly.instruction.comp
  dEQP-VK.spirv_assembly.instruction.compute.empty_struct.function.global_variable_shared
  dEQP-VK.spirv_assembly.instruction.compute.empty_struct.function.local_variable
  dEQP-VK.spirv_assembly.instruction.compute.oparraylength.array-stride-larger-than-element-size
+ dEQP-VK.spirv_assembly.instruction.compute.physical_storage_buffer.push_constants
+ dEQP-VK.spirv_assembly.instruction.compute.physical_storage_buffer.push_constants_function
+ dEQP-VK.spirv_assembly.instruction.compute.physical_storage_buffer.vertex_in_out_in
+ dEQP-VK.spirv_assembly.instruction.compute.physical_storage_buffer.addrs_in_ssbo
 +dEQP-VK.spirv_assembly.instruction.graphics.spirv_version.1_6_vertex
 +dEQP-VK.spirv_assembly.instruction.graphics.spirv_version.1_6_tesselation_evaluation
 +dEQP-VK.spirv_assembly.instruction.graphics.spirv_version.1_6_tesselation_control
 +dEQP-VK.spirv_assembly.instruction.graphics.spirv_version.1_6_geometry
 +dEQP-VK.spirv_assembly.instruction.graphics.spirv_version.1_6_fragment
  dEQP-VK.spirv_assembly.instruction.graphics.switch_block_order.switch-case-to-merge-block
  dEQP-VK.spirv_assembly.instruction.graphics.opspecconstantop.shiftrightlogical_i64_vert
  dEQP-VK.spirv_assembly.instruction.graphics.opspecconstantop.shiftrightlogical_i64_tessc
Simple merge
@@@ -6367,20 -6669,53 +6669,53 @@@ void ResolveImageToImage::copyMSImageTo
        }
        else
        {
-               DE_ASSERT(m_params.extensionUse == EXTENSION_USE_COPY_COMMANDS2);
-               const VkCopyImageInfo2KHR copyImageInfo2KHR =
+               if(m_options == COPY_MS_IMAGE_TO_MS_IMAGE_NO_CAB)
                {
-                       VK_STRUCTURE_TYPE_COPY_IMAGE_INFO_2_KHR,        // VkStructureType                      sType;
-                       DE_NULL,                                                                        // const void*                          pNext;
-                       m_multisampledImage.get(),                                      // VkImage                                      srcImage;
-                       m_params.src.image.operationLayout,                     // VkImageLayout                        srcImageLayout;
-                       m_multisampledCopyImage.get(),                          // VkImage                                      dstImage;
-                       m_params.dst.image.operationLayout,                     // VkImageLayout                        dstImageLayout;
-                       (deUint32)imageCopies2KHR.size(),                       // uint32_t                                     regionCount;
-                       imageCopies2KHR.data()                                          // const VkImageCopy2KHR*       pRegions;
-               };
+                       DE_ASSERT(m_params.extensionUse == EXTENSION_USE_COPY_COMMANDS2);
+                       const VkCopyImageInfo2KHR copyImageInfo2KHR =
+                       {
+                               VK_STRUCTURE_TYPE_COPY_IMAGE_INFO_2_KHR,        // VkStructureType                      sType;
+                               DE_NULL,                                                                        // const void*                          pNext;
+                               m_multisampledImage.get(),                                      // VkImage                                      srcImage;
+                               m_params.src.image.operationLayout,                     // VkImageLayout                        srcImageLayout;
+                               m_multisampledCopyNoCabImage.get(),                     // VkImage                                      dstImage;
+                               VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,           // VkImageLayout                        dstImageLayout;
+                               (deUint32)imageCopies2KHR.size(),                       // uint32_t                                     regionCount;
+                               imageCopies2KHR.data()                                          // const VkImageCopy2KHR*       pRegions;
+                       };
+                       const VkCopyImageInfo2KHR copyImageInfo2KHRCopy =
+                       {
+                               VK_STRUCTURE_TYPE_COPY_IMAGE_INFO_2_KHR,        // VkStructureType                      sType;
+                               DE_NULL,                                                                        // const void*                          pNext;
+                               m_multisampledCopyNoCabImage.get(),                     // VkImage                                      srcImage;
+                               vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,       // VkImageLayout                        srcImageLayout;
+                               m_multisampledCopyImage.get(),                          // VkImage                                      dstImage;
+                               m_params.dst.image.operationLayout,                     // VkImageLayout                        dstImageLayout;
+                               (deUint32)imageCopies2KHR.size(),                       // uint32_t                                     regionCount;
+                               imageCopies2KHR.data()                                          // const VkImageCopy2KHR*       pRegions;
+                       };
  
-               vk.cmdCopyImage2(*m_cmdBuffer, &copyImageInfo2KHR);
 -                      vk.cmdCopyImage2KHR(*m_cmdBuffer, &copyImageInfo2KHR);
++                      vk.cmdCopyImage2(*m_cmdBuffer, &copyImageInfo2KHR);
+                       vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1u, &betweenCopyImageBarrier);
 -                      vk.cmdCopyImage2KHR(*m_cmdBuffer, &copyImageInfo2KHRCopy);
++                      vk.cmdCopyImage2(*m_cmdBuffer, &copyImageInfo2KHRCopy);
+               }
+               else
+               {
+                       DE_ASSERT(m_params.extensionUse == EXTENSION_USE_COPY_COMMANDS2);
+                       const VkCopyImageInfo2KHR copyImageInfo2KHR =
+                       {
+                               VK_STRUCTURE_TYPE_COPY_IMAGE_INFO_2_KHR,        // VkStructureType                      sType;
+                               DE_NULL,                                                                        // const void*                          pNext;
+                               m_multisampledImage.get(),                                      // VkImage                                      srcImage;
+                               m_params.src.image.operationLayout,                     // VkImageLayout                        srcImageLayout;
+                               m_multisampledCopyImage.get(),                          // VkImage                                      dstImage;
+                               m_params.dst.image.operationLayout,                     // VkImageLayout                        dstImageLayout;
+                               (deUint32)imageCopies2KHR.size(),                       // uint32_t                                     regionCount;
+                               imageCopies2KHR.data()                                          // const VkImageCopy2KHR*       pRegions;
+                       };
 -                      vk.cmdCopyImage2KHR(*m_cmdBuffer, &copyImageInfo2KHR);
++                      vk.cmdCopyImage2(*m_cmdBuffer, &copyImageInfo2KHR);
+               }
        }
  
        vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1u, &postImageBarriers);
index 0000000,3addc94..77a38bb
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,2406 +1,2406 @@@
 -              vk.cmdBeginRenderingKHR(commandBuffer, &renderingInfo);
+ /*------------------------------------------------------------------------
+  * Vulkan Conformance Tests
+  * ------------------------
+  *
+  * Copyright (c) 2021 The Khronos Group Inc.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *      http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  *
+  *//*!
+  * \file
+  * \brief Tests for VK_KHR_fragment_shading_rate
+  *//*--------------------------------------------------------------------*/
+ #include "vktAttachmentRateTests.hpp"
+ #include "vkBufferWithMemory.hpp"
+ #include "vkImageWithMemory.hpp"
+ #include "vkQueryUtil.hpp"
+ #include "vkBarrierUtil.hpp"
+ #include "vkCmdUtil.hpp"
+ #include "vkTypeUtil.hpp"
+ #include "vkObjUtil.hpp"
+ #include "vkImageUtil.hpp"
+ #include "vkQueryUtil.hpp"
+ #include "vkPlatform.hpp"
+ #include "vkBuilderUtil.hpp"
+ #include "vktTestGroupUtil.hpp"
+ #include "vktTestCase.hpp"
+ #include "vktCustomInstancesDevices.hpp"
+ #include "deDefs.h"
+ #include "deMath.h"
+ #include "deSharedPtr.hpp"
+ #include "deString.h"
+ #include "deSTLUtil.hpp"
+ #include "tcuTestCase.hpp"
+ #include "tcuTestLog.hpp"
+ #include "tcuTextureUtil.hpp"
+ #include "tcuStringTemplate.hpp"
+ #include <string>
+ #include <vector>
+ #include <limits>
+ #include <map>
+ namespace vkt
+ {
+ namespace FragmentShadingRate
+ {
+ namespace
+ {
+ using namespace vk;
+ // flag used to test TM_SETUP_RATE_WITH_ATOMICS_IN_COMPUTE_SHADER;
+ // when it is 1 instead of using atomic operations to fill image
+ // plain store will be used as it is always supported
+ #define DEBUG_USE_STORE_INSTEAD_OF_ATOMICS 0
+ enum TestMode
+ {
+       TM_SETUP_RATE_WITH_ATOMICS_IN_COMPUTE_SHADER = 0,
+       TM_SETUP_RATE_WITH_FRAGMENT_SHADER,
+       TM_SETUP_RATE_WITH_COPYING_FROM_OTHER_IMAGE,
+       TM_SETUP_RATE_WITH_COPYING_FROM_EXCLUSIVE_IMAGE_USING_TRANSFER_QUEUE,
+       TM_SETUP_RATE_WITH_COPYING_FROM_CONCURENT_IMAGE_USING_TRANSFER_QUEUE,
+       TM_SETUP_RATE_WITH_LINEAR_TILED_IMAGE,
+       TM_TWO_SUBPASS
+ };
+ struct TestParams
+ {
+       TestMode                mode;
+       VkFormat                srFormat;
+       VkExtent2D              srRate;
+       bool                    useDynamicRendering;
+       bool                    useImagelessFramebuffer;
+ };
+ deUint32 calculateRate(deUint32 rateWidth, deUint32 rateHeight)
+ {
+       return (deCtz32(rateWidth) << 2u) | deCtz32(rateHeight);
+ }
+ class AttachmentRateInstance : public TestInstance
+ {
+ public:
+                                                       AttachmentRateInstance  (Context& context, const de::SharedPtr<TestParams> params);
+       tcu::TestStatus                 iterate                                 (void);
+ private:
+       // Helper structure used by buildFramebuffer method.
+       // It is used to build regular or imageless framebuffer.
+       struct FBAttachmentInfo
+       {
+               VkFormat                        format;
+               VkImageUsageFlags       usage;
+               deUint32                        width;
+               deUint32                        height;
+               VkImageView                     view;
+       };
+ private:
+       de::MovePtr<ImageWithMemory>    buildImageWithMemory            (VkFormat                                               format,
+                                                                                                                                deUint32                                               width,
+                                                                                                                                deUint32                                               height,
+                                                                                                                                VkImageUsageFlags                              usage,
+                                                                                                                                VkImageTiling                                  tiling = VK_IMAGE_TILING_OPTIMAL,
+                                                                                                                                std::vector<deUint32>                  queueFamilies = std::vector<deUint32>());
+       de::MovePtr<BufferWithMemory>   buildBufferWithMemory           (deUint32                                               size,
+                                                                                                                                VkBufferUsageFlags                             usage);
+       Move<VkImageView>                               buildImageView                          (VkFormat                                               format,
+                                                                                                                                VkImage                                                image);
+       void                                                    buildColorBufferObjects         (deUint32                                               cbIindex,
+                                                                                                                                VkImageUsageFlags                              cbUsage);
+       void                                                    buildShadingRateObjects         (deUint32                                               srIndex,
+                                                                                                                                deUint32                                               width,
+                                                                                                                                deUint32                                               height,
+                                                                                                                                VkImageUsageFlags                              srUsage,
+                                                                                                                                VkImageTiling                                  srTiling = VK_IMAGE_TILING_OPTIMAL);
+       void                                                    buildCounterBufferObjects       ();
+       Move<VkRenderPass>                              buildRenderPass                         (VkFormat                                                               cbFormat,
+                                                                                                                                deUint32                                                               sr1TileWidth = 0,
+                                                                                                                                deUint32                                                               sr1TileHeight = 0,
+                                                                                                                                deUint32                                                               sr2TileWidth = 0,
+                                                                                                                                deUint32                                                               sr2TileHeight = 0) const;
+       Move<VkFramebuffer>                             buildFramebuffer                        (VkRenderPass                                                   renderPass,
+                                                                                                                                const std::vector<FBAttachmentInfo>&   attachmentInfo) const;
+       Move<VkPipelineLayout>                  buildPipelineLayout                     (const VkDescriptorSetLayout*                   setLayouts = DE_NULL) const;
+       Move<VkPipeline>                                buildGraphicsPipeline           (deUint32                                                               subpass,
+                                                                                                                                VkRenderPass                                                   renderPass,
+                                                                                                                                VkPipelineLayout                                               layout,
+                                                                                                                                VkShaderModule                                                 vertShader,
+                                                                                                                                VkShaderModule                                                 fragShader,
+                                                                                                                                bool                                                                   useShadingRate = VK_TRUE) const;
+       Move<VkPipeline>                                buildComputePipeline            (VkShaderModule                                                 compShader,
+                                                                                                                                VkPipelineLayout                                               pipelineLayout) const;
+       VkDescriptorSetAllocateInfo             makeDescriptorSetAllocInfo      (VkDescriptorPool                                               descriptorPool,
+                                                                                                                                const VkDescriptorSetLayout*                   pSetLayouts) const;
+       void                                                    startRendering                          (const VkCommandBuffer                                  commandBuffer,
+                                                                                                                                const VkRenderPass                                             renderPass,
+                                                                                                                                const VkFramebuffer                                    framebuffer,
+                                                                                                                                const VkRect2D&                                                renderArea,
+                                                                                                                                const std::vector<FBAttachmentInfo>&   attachmentInfo) const;
+       void                                                    finishRendering                         (const VkCommandBuffer                                  commandBuffer) const;
+       bool                                                    verifyUsingAtomicChecks         (deUint32                                               tileWidth,
+                                                                                                                                deUint32                                               tileHeight,
+                                                                                                                                deUint32                                               rateWidth,
+                                                                                                                                deUint32                                               rateHeight,
+                                                                                                                                deUint32*                                              outBufferPtr) const;
+       bool                                                    runComputeShaderMode            (void);
+       bool                                                    runFragmentShaderMode           (void);
+       bool                                                    runCopyMode                                     (void);
+       bool                                                    runCopyModeOnTransferQueue      (void);
+       bool                                                    runFillLinearTiledImage         (void);
+       bool                                                    runTwoSubpassMode                       (void);
+ private:
+       // When custom device is used then m_device and m_allocator are used in all
+       // helper methods. Otherwise default device and allocator from context are used.
+       // Those objects are used only by tests from runCopyModeOnTransferQueue.
+       Move<VkDevice>                                  m_device;
+       de::MovePtr<Allocator>                  m_allocator;
+       const de::SharedPtr<TestParams> m_params;
+       const deUint32                                  m_cbWidth;
+       const deUint32                                  m_cbHeight;
+       VkFormat                                                m_cbFormat;
+       VkImageUsageFlags                               m_cbUsage;
+       VkImageUsageFlags                               m_srUsage;
+       // structures commonly used by most of tests
+       const VkImageSubresourceLayers  m_defaultImageSubresourceLayers;
+       const VkImageSubresourceRange   m_defaultImageSubresourceRange;
+       const VkBufferImageCopy                 m_defaultBufferImageCopy;
+       // objects commonly used by most of tests
+       de::MovePtr<ImageWithMemory>    m_cbImage[2];
+       Move<VkImageView>                               m_cbImageView[2];
+       de::MovePtr<BufferWithMemory>   m_cbReadBuffer[2];
+       de::MovePtr<ImageWithMemory>    m_srImage[2];
+       Move<VkImageView>                               m_srImageView[2];
+       Move<VkDescriptorSetLayout>             m_counterBufferDescriptorSetLayout;
+       Move<VkDescriptorPool>                  m_counterBufferDescriptorPool;
+       Move<VkDescriptorSet>                   m_counterBufferDescriptorSet;
+       de::MovePtr<BufferWithMemory>   m_counterBuffer;
+       // properties commonly used by most of tests
+       VkExtent2D                                              m_minTileSize;
+       VkExtent2D                                              m_maxTileSize;
+       deUint32                                                m_maxAspectRatio;
+ };
+ AttachmentRateInstance::AttachmentRateInstance(Context& context, const de::SharedPtr<TestParams> params)
+       : vkt::TestInstance                                     (context)
+       , m_params                                                      (params)
+       , m_cbWidth                                                     (60)
+       , m_cbHeight                                            (60)
+       , m_cbFormat                                            (VK_FORMAT_R32G32B32A32_UINT)
+       , m_cbUsage                                                     (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)
+       , m_srUsage                                                     (VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR | VK_IMAGE_USAGE_TRANSFER_DST_BIT)
+       , m_defaultImageSubresourceLayers       (makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u))
+       , m_defaultImageSubresourceRange        (makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0, 1u))
+       , m_defaultBufferImageCopy                      (makeBufferImageCopy({ m_cbWidth, m_cbHeight, 1u }, m_defaultImageSubresourceLayers))
+ {
+       // prepare data needed to calculate tile sizes
+       const auto& srProperties        = m_context.getFragmentShadingRateProperties();
+       m_minTileSize                           = srProperties.minFragmentShadingRateAttachmentTexelSize;
+       m_maxTileSize                           = srProperties.maxFragmentShadingRateAttachmentTexelSize;
+       m_maxAspectRatio                        = srProperties.maxFragmentShadingRateAttachmentTexelSizeAspectRatio;
+ }
+ de::MovePtr<ImageWithMemory> AttachmentRateInstance::buildImageWithMemory (VkFormat                                   format,
+                                                                                                                                                  deUint32                                     width,
+                                                                                                                                                  deUint32                                     height,
+                                                                                                                                                  VkImageUsageFlags            usage,
+                                                                                                                                                  VkImageTiling                        tiling,
+                                                                                                                                                  std::vector<deUint32>        queueFamilies)
+ {
+       VkImageCreateInfo imageCreateInfo
+       {
+               VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,            // VkStructureType                      sType;
+               DE_NULL,                                                                        // const void*                          pNext;
+               (VkImageCreateFlags)0u,                                         // VkImageCreateFlags           flags;
+               VK_IMAGE_TYPE_2D,                                                       // VkImageType                          imageType;
+               format,                                                                         // VkFormat                                     format;
+               {
+                       width,                                                                  // deUint32                                     width;
+                       height,                                                                 // deUint32                                     height;
+                       1u                                                                              // deUint32                                     depth;
+               },                                                                                      // VkExtent3D                           extent;
+               1u,                                                                                     // deUint32                                     mipLevels;
+               1u,                                                                                     // deUint32                                     arrayLayers;
+               VK_SAMPLE_COUNT_1_BIT,                                          // VkSampleCountFlagBits        samples;
+               tiling,                                                                         // VkImageTiling                        tiling;
+               usage,                                                                          // VkImageUsageFlags            usage;
+               queueFamilies.empty() ?
+                       VK_SHARING_MODE_EXCLUSIVE :
+                       VK_SHARING_MODE_CONCURRENT,                             // VkSharingMode                        sharingMode;
+               (deUint32)queueFamilies.size(),                         // deUint32                                     queueFamilyIndexCount;
+               queueFamilies.data(),                                           // const deUint32*                      pQueueFamilyIndices;
+               VK_IMAGE_LAYOUT_UNDEFINED                                       // VkImageLayout                        initialLayout;
+       };
+       const DeviceInterface&  vk                                      = m_context.getDeviceInterface();
+       VkDevice                                device                          = m_device.get() ? *m_device : m_context.getDevice();
+       vk::Allocator&                  allocator                       = m_allocator.get() ? *m_allocator : m_context.getDefaultAllocator();
+       vk::MemoryRequirement   memoryRequirement       = (tiling == VK_IMAGE_TILING_LINEAR) ? MemoryRequirement::HostVisible : MemoryRequirement::Any;
+       return de::MovePtr<ImageWithMemory>(new ImageWithMemory(vk, device, allocator, imageCreateInfo, memoryRequirement));
+ }
+ de::MovePtr<BufferWithMemory> AttachmentRateInstance::buildBufferWithMemory(deUint32 size, VkBufferUsageFlags usage)
+ {
+       const DeviceInterface&          vk                              = m_context.getDeviceInterface();
+       VkDevice                                        device                  = m_device.get() ? *m_device : m_context.getDevice();
+       vk::Allocator&                          allocator               = m_allocator.get() ? *m_allocator : m_context.getDefaultAllocator();
+       const VkBufferCreateInfo        readBufferInfo  = makeBufferCreateInfo(size, usage);
+       return de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, readBufferInfo, MemoryRequirement::HostVisible));
+ }
+ Move<VkImageView> AttachmentRateInstance::buildImageView (VkFormat format, VkImage image)
+ {
+       const DeviceInterface&  vk                                      = m_context.getDeviceInterface();
+       VkDevice                                device                          = m_device.get() ? *m_device : m_context.getDevice();
+       VkImageSubresourceRange subresourceRange        = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
+       return makeImageView(vk, device, image, VK_IMAGE_VIEW_TYPE_2D, format, subresourceRange);
+ };
+ void AttachmentRateInstance::buildColorBufferObjects(deUint32 cbIndex, VkImageUsageFlags cbUsage)
+ {
+       DE_ASSERT(cbIndex < 2);
+       m_cbImage[cbIndex]                      = buildImageWithMemory(m_cbFormat, m_cbWidth, m_cbHeight, cbUsage);
+       m_cbImageView[cbIndex]          = buildImageView(m_cbFormat, m_cbImage[cbIndex]->get());
+       m_cbReadBuffer[cbIndex]         = buildBufferWithMemory(m_cbWidth * m_cbHeight * deUint32(sizeof(int)) * 4u, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
+ }
+ void AttachmentRateInstance::buildShadingRateObjects(deUint32 srIndex, deUint32 width, deUint32 height, VkImageUsageFlags srUsage, VkImageTiling srTiling)
+ {
+       DE_ASSERT(srIndex < 2);
+       m_srImage[srIndex]              = buildImageWithMemory(m_params->srFormat, width, height, srUsage, srTiling);
+       m_srImageView[srIndex]  = buildImageView(m_params->srFormat, m_srImage[srIndex]->get());
+ }
+ void AttachmentRateInstance::buildCounterBufferObjects()
+ {
+       const DeviceInterface&  vk              = m_context.getDeviceInterface();
+       VkDevice                                device  = m_device.get() ? *m_device : m_context.getDevice();
+       m_counterBufferDescriptorPool           = DescriptorPoolBuilder()
+                                                                                       .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u)
+                                                                                       .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
+       m_counterBufferDescriptorSetLayout      = DescriptorSetLayoutBuilder()
+                                                                                       .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
+                                                                                       .build(vk, device);
+       const VkDescriptorSetAllocateInfo descriptorSetAllocInfo = makeDescriptorSetAllocInfo(*m_counterBufferDescriptorPool,
+                                                                                                                                                                                 &(*m_counterBufferDescriptorSetLayout));
+       m_counterBufferDescriptorSet = allocateDescriptorSet(vk, device, &descriptorSetAllocInfo);
+       // create ssbo buffer for atomic counter
+       deUint32 ssboSize       = deUint32(sizeof(deUint32));
+       m_counterBuffer         = buildBufferWithMemory(ssboSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
+       const VkDescriptorBufferInfo descriptorInfo = makeDescriptorBufferInfo(**m_counterBuffer, 0, ssboSize);
+       DescriptorSetUpdateBuilder()
+               .writeSingle(*m_counterBufferDescriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorInfo)
+               .update(vk, device);
+       // reset counter
+       *((deUint32*)m_counterBuffer->getAllocation().getHostPtr()) = 0u;
+       flushAlloc(vk, device, m_counterBuffer->getAllocation());
+ }
+ Move<VkRenderPass> AttachmentRateInstance::buildRenderPass(VkFormat cbFormat,
+                                                                                                                  deUint32 sr0TileWidth, deUint32 sr0TileHeight,
+                                                                                                                  deUint32 sr1TileWidth, deUint32 sr1TileHeight) const
+ {
+       if (m_params->useDynamicRendering)
+               return Move<VkRenderPass>();
+       const bool              useShadingRate0         = (sr0TileWidth * sr0TileHeight > 0);
+       const bool              useShadingRate1         = (sr1TileWidth * sr1TileHeight > 0);
+       deUint32                attachmentCount         = 1;
+       const deUint32  subpassCount            = 1 + useShadingRate1;
+       std::vector<VkAttachmentReference2> colorAttachmentReferences(subpassCount, {
+               VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,                                                       // VkStructureType                                      sType;
+               DE_NULL,                                                                                                                        // const void*                                          pNext;
+               0,                                                                                                                                      // uint32_t                                                     attachment;
+               VK_IMAGE_LAYOUT_GENERAL,                                                                                        // VkImageLayout                                        layout;
+               0,                                                                                                                                      // VkImageAspectFlags                           aspectMask;
+       });
+       std::vector<VkAttachmentReference2> fragmentShadingRateAttachments(subpassCount, {
+               VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,                                                       // VkStructureType                                      sType;
+               DE_NULL,                                                                                                                        // const void*                                          pNext;
+               1,                                                                                                                                      // uint32_t                                                     attachment;
+               VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR,           // VkImageLayout                                        layout;
+               0,                                                                                                                                      // VkImageAspectFlags                           aspectMask;
+       });
+       std::vector<VkFragmentShadingRateAttachmentInfoKHR> shadingRateAttachmentInfos(subpassCount, {
+               VK_STRUCTURE_TYPE_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR,            // VkStructureType                                      sType;
+               DE_NULL,                                                                                                                        // const void*                                          pNext;
+               &fragmentShadingRateAttachments[0],                                                                     // const VkAttachmentReference2*        pFragmentShadingRateAttachment;
+               { sr0TileWidth, sr0TileHeight },                                                                        // VkExtent2D                                           shadingRateAttachmentTexelSize;
+       });
+       std::vector<VkSubpassDescription2> subpassDescriptions(subpassCount, {
+               VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2,                                                        // VkStructureType                                      sType;
+               DE_NULL,                                                                                                                        // const void*                                          pNext;
+               (vk::VkSubpassDescriptionFlags)0,                                                                       // VkSubpassDescriptionFlags            flags;
+               vk::VK_PIPELINE_BIND_POINT_GRAPHICS,                                                            // VkPipelineBindPoint                          pipelineBindPoint;
+               0u,                                                                                                                                     // uint32_t                                                     viewMask;
+               0u,                                                                                                                                     // uint32_t                                                     inputAttachmentCount;
+               DE_NULL,                                                                                                                        // const VkAttachmentReference2*        pInputAttachments;
+               1,                                                                                                                                      // uint32_t                                                     colorAttachmentCount;
+               &colorAttachmentReferences[0],                                                                          // const VkAttachmentReference2*        pColorAttachments;
+               DE_NULL,                                                                                                                        // const VkAttachmentReference2*        pResolveAttachments;
+               DE_NULL,                                                                                                                        // const VkAttachmentReference2*        pDepthStencilAttachment;
+               0u,                                                                                                                                     // uint32_t                                                     preserveAttachmentCount;
+               DE_NULL,                                                                                                                        // const uint32_t*                                      pPreserveAttachments;
+       });
+       std::vector<VkAttachmentDescription2> attachmentDescriptions(2 * subpassCount, {
+               VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,                                                     // VkStructureType                                      sType;
+               DE_NULL,                                                                                                                        // const void*                                          pNext;
+               (VkAttachmentDescriptionFlags)0u,                                                                       // VkAttachmentDescriptionFlags         flags;
+               cbFormat,                                                                                                                       // VkFormat                                                     format;
+               VK_SAMPLE_COUNT_1_BIT,                                                                                          // VkSampleCountFlagBits                        samples;
+               VK_ATTACHMENT_LOAD_OP_CLEAR,                                                                            // VkAttachmentLoadOp                           loadOp;
+               VK_ATTACHMENT_STORE_OP_STORE,                                                                           // VkAttachmentStoreOp                          storeOp;
+               VK_ATTACHMENT_LOAD_OP_DONT_CARE,                                                                        // VkAttachmentLoadOp                           stencilLoadOp;
+               VK_ATTACHMENT_STORE_OP_DONT_CARE,                                                                       // VkAttachmentStoreOp                          stencilStoreOp;
+               VK_IMAGE_LAYOUT_GENERAL,                                                                                        // VkImageLayout                                        initialLayout;
+               VK_IMAGE_LAYOUT_GENERAL                                                                                         // VkImageLayout                                        finalLayout;
+       });
+       if (useShadingRate0)
+       {
+               attachmentCount                                                 = 2;
+               subpassDescriptions[0].pNext                    = &shadingRateAttachmentInfos[0];
+               attachmentDescriptions[1].format                = m_params->srFormat;
+               attachmentDescriptions[1].loadOp                = VK_ATTACHMENT_LOAD_OP_LOAD;
+               attachmentDescriptions[1].storeOp               = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+               attachmentDescriptions[1].initialLayout = VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR;
+       }
+       if (useShadingRate1)
+       {
+               attachmentCount                                                                                                 = 4;
+               colorAttachmentReferences[1].attachment                                                 = 2;
+               fragmentShadingRateAttachments[1].attachment                                    = 3;
+               shadingRateAttachmentInfos[1].pFragmentShadingRateAttachment    = &fragmentShadingRateAttachments[1];
+               shadingRateAttachmentInfos[1].shadingRateAttachmentTexelSize    = { sr1TileWidth, sr1TileHeight };
+               subpassDescriptions[1].pNext                                                                    = &shadingRateAttachmentInfos[1];
+               subpassDescriptions[1].pColorAttachments                                                = &colorAttachmentReferences[1];
+               attachmentDescriptions[3].format                = m_params->srFormat;
+               attachmentDescriptions[3].loadOp                = VK_ATTACHMENT_LOAD_OP_LOAD;
+               attachmentDescriptions[3].storeOp               = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+               attachmentDescriptions[3].initialLayout = VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR;
+       }
+       const VkRenderPassCreateInfo2 renderPassParams
+       {
+               VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2,                                            // VkStructureType                                      sType;
+               DE_NULL,                                                                                                                        // const void*                                          pNext;
+               (vk::VkRenderPassCreateFlags)0,                                                                         // VkRenderPassCreateFlags                      flags;
+               attachmentCount,                                                                                                        // uint32_t                                                     attachmentCount;
+               attachmentDescriptions.data(),                                                                          // const VkAttachmentDescription2*      pAttachments;
+               subpassCount,                                                                                                           // uint32_t                                                     subpassCount;
+               subpassDescriptions.data(),                                                                                     // const VkSubpassDescription2*         pSubpasses;
+               0u,                                                                                                                                     // uint32_t                                                     dependencyCount;
+               DE_NULL,                                                                                                                        // const VkSubpassDependency2*          pDependencies;
+               0u,                                                                                                                                     // uint32_t                                                     correlatedViewMaskCount;
+               DE_NULL,                                                                                                                        // const uint32_t*                                      pCorrelatedViewMasks;
+       };
+       VkDevice device = m_device.get() ? *m_device : m_context.getDevice();
+       return createRenderPass2(m_context.getDeviceInterface(), device, &renderPassParams);
+ }
+ Move<VkFramebuffer> AttachmentRateInstance::buildFramebuffer(VkRenderPass renderPass, const std::vector<FBAttachmentInfo>& attachmentInfo) const
+ {
+       if (m_params->useDynamicRendering)
+               return Move<VkFramebuffer>();
+       VkDevice device = m_device.get() ? *m_device : m_context.getDevice();
+       VkFramebufferCreateInfo framebufferParams
+       {
+               vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,                                          // VkStructureType                              sType;
+               DE_NULL,                                                                                                                        // const void*                                  pNext;
+               (vk::VkFramebufferCreateFlags)0u,                                                                       // VkFramebufferCreateFlags             flags;
+               renderPass,                                                                                                                     // VkRenderPass                                 renderPass;
+               (deUint32)attachmentInfo.size(),                                                                        // uint32_t                                             attachmentCount;
+               DE_NULL,                                                                                                                        // const VkImageView*                   pAttachments;
+               attachmentInfo[0].width,                                                                                        // uint32_t                                             width;
+               attachmentInfo[0].height,                                                                                       // uint32_t                                             height;
+               1u,                                                                                                                                     // uint32_t                                             layers;
+       };
+       if (m_params->useImagelessFramebuffer)
+       {
+               std::vector<VkFramebufferAttachmentImageInfo> framebufferAttachmentImageInfo(attachmentInfo.size(),
+                       {
+                               VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO,            // VkStructureType              sType;
+                               DE_NULL,                                                                                                        // const void*                  pNext;
+                               (VkImageCreateFlags)0u,                                                                         // VkImageCreateFlags   flags;
+                               0u,                                                                                                                     // VkImageUsageFlags    usage;
+                               0u,                                                                                                                     // deUint32                             width;
+                               0u,                                                                                                                     // deUint32                             height;
+                               1u,                                                                                                                     // deUint32                             layerCount;
+                               1u,                                                                                                                     // deUint32                             viewFormatCount;
+                               DE_NULL                                                                                                         // const VkFormat*              pViewFormats;
+                       }
+               );
+               for (deUint32 i = 0; i < (deUint32)attachmentInfo.size(); ++i)
+               {
+                       const auto&     src = attachmentInfo[i];
+                       auto&           dst = framebufferAttachmentImageInfo[i];
+                       dst.usage                       = src.usage;
+                       dst.width                       = src.width;
+                       dst.height                      = src.height;
+                       dst.pViewFormats        = &src.format;
+               }
+               VkFramebufferAttachmentsCreateInfo framebufferAttachmentsCreateInfo
+               {
+                       VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO,                  // VkStructureType                                                      sType;
+                       DE_NULL,                                                                                                                // const void*                                                          pNext;
+                       (deUint32)framebufferAttachmentImageInfo.size(),                                // deUint32                                                                     attachmentImageInfoCount;
+                       framebufferAttachmentImageInfo.data()                                                   // const VkFramebufferAttachmentImageInfo*      pAttachmentImageInfos;
+               };
+               framebufferParams.pNext = &framebufferAttachmentsCreateInfo;
+               framebufferParams.flags = VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT;
+               return createFramebuffer(m_context.getDeviceInterface(), device, &framebufferParams);
+       }
+       // create array containing just attachment views
+       std::vector<VkImageView> attachments(attachmentInfo.size(), 0);
+       for (deUint32 i = 0; i < (deUint32)attachmentInfo.size(); ++i)
+               attachments[i] = attachmentInfo[i].view;
+       framebufferParams.pAttachments = attachments.data();
+       return createFramebuffer(m_context.getDeviceInterface(), device, &framebufferParams);
+ }
+ Move<VkPipelineLayout> AttachmentRateInstance::buildPipelineLayout(const VkDescriptorSetLayout* setLayouts) const
+ {
+       const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,          // VkStructureType                                      sType;
+               DE_NULL,                                                                                        // const void*                                          pNext;
+               (VkPipelineLayoutCreateFlags)0,                                         // VkPipelineLayoutCreateFlags          flags;
+               (setLayouts != DE_NULL),                                                        // uint32_t                                                     setLayoutCount;
+               setLayouts,                                                                                     // const VkDescriptorSetLayout*         pSetLayouts;
+               0u,                                                                                                     // uint32_t                                                     pushConstantRangeCount;
+               DE_NULL,                                                                                        // const VkPushConstantRange*           pPushConstantRanges;
+       };
+       VkDevice device = m_device.get() ? *m_device : m_context.getDevice();
+       return createPipelineLayout(m_context.getDeviceInterface(), device, &pipelineLayoutCreateInfo, NULL);
+ }
+ Move<VkPipeline> AttachmentRateInstance::buildGraphicsPipeline(deUint32 subpass, VkRenderPass renderPass, VkPipelineLayout pipelineLayout,
+                                                                                                                          VkShaderModule vertShader, VkShaderModule fragShader, bool useShadingRate) const
+ {
+       std::vector<VkPipelineShaderStageCreateInfo> pipelineShaderStageParams(2,
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,                    // VkStructureType                                                              sType
+               DE_NULL,                                                                                                                // const void*                                                                  pNext
+               0u,                                                                                                                             // VkPipelineShaderStageCreateFlags                             flags
+               VK_SHADER_STAGE_VERTEX_BIT,                                                                             // VkShaderStageFlagBits                                                stage
+               vertShader,                                                                                                             // VkShaderModule                                                               module
+               "main",                                                                                                                 // const char*                                                                  pName
+               DE_NULL                                                                                                                 // const VkSpecializationInfo*                                  pSpecializationInfo
+       });
+       pipelineShaderStageParams[1].stage      = VK_SHADER_STAGE_FRAGMENT_BIT;
+       pipelineShaderStageParams[1].module     = fragShader;
+       const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,              // VkStructureType                                                              sType
+               DE_NULL,                                                                                                                // const void*                                                                  pNext
+               (VkPipelineVertexInputStateCreateFlags)0,                                               // VkPipelineVertexInputStateCreateFlags                flags
+               0u,                                                                                                                             // deUint32                                                                             vertexBindingDescriptionCount
+               DE_NULL,                                                                                                                // const VkVertexInputBindingDescription*               pVertexBindingDescriptions
+               0u,                                                                                                                             // deUint32                                                                             vertexAttributeDescriptionCount
+               DE_NULL                                                                                                                 // const VkVertexInputAttributeDescription*             pVertexAttributeDescriptions
+       };
+       const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,    // VkStructureType                                                              sType
+               DE_NULL,                                                                                                                // const void*                                                                  pNext
+               0u,                                                                                                                             // VkPipelineInputAssemblyStateCreateFlags              flags
+               VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,                                                   // VkPrimitiveTopology                                                  topology
+               VK_FALSE                                                                                                                // VkBool32                                                                             primitiveRestartEnable
+       };
+       tcu::UVec2      size            (m_cbWidth, m_cbHeight);
+       VkViewport      viewport        = makeViewport  (size);
+       VkRect2D        scissor         = makeRect2D    (size);
+       const VkPipelineViewportStateCreateInfo viewportStateCreateInfo
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,                  // VkStructureType                                                              sType
+               DE_NULL,                                                                                                                // const void*                                                                  pNext
+               (VkPipelineViewportStateCreateFlags)0,                                                  // VkPipelineViewportStateCreateFlags                   flags
+               1u,                                                                                                                             // deUint32                                                                             viewportCount
+               &viewport,                                                                                                              // const VkViewport*                                                    pViewports
+               1u,                                                                                                                             // deUint32                                                                             scissorCount
+               &scissor                                                                                                                // const VkRect2D*                                                              pScissors
+       };
+       const VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,             // VkStructureType                                                              sType
+               DE_NULL,                                                                                                                // const void*                                                                  pNext
+               0u,                                                                                                                             // VkPipelineRasterizationStateCreateFlags              flags
+               VK_FALSE,                                                                                                               // VkBool32                                                                             depthClampEnable
+               VK_FALSE,                                                                                                               // VkBool32                                                                             rasterizerDiscardEnable
+               VK_POLYGON_MODE_FILL,                                                                                   // VkPolygonMode                                                                polygonMode
+               VK_CULL_MODE_NONE,                                                                                              // VkCullModeFlags                                                              cullMode
+               VK_FRONT_FACE_COUNTER_CLOCKWISE,                                                                // VkFrontFace                                                                  frontFace
+               VK_FALSE,                                                                                                               // VkBool32                                                                             depthBiasEnable
+               0.0f,                                                                                                                   // float                                                                                depthBiasConstantFactor
+               0.0f,                                                                                                                   // float                                                                                depthBiasClamp
+               0.0f,                                                                                                                   // float                                                                                depthBiasSlopeFactor
+               1.0f                                                                                                                    // float                                                                                lineWidth
+       };
+       const VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,               // VkStructureType                                                              sType
+               DE_NULL,                                                                                                                // const void*                                                                  pNext
+               0u,                                                                                                                             // VkPipelineMultisampleStateCreateFlags                flags
+               VK_SAMPLE_COUNT_1_BIT,                                                                                  // VkSampleCountFlagBits                                                rasterizationSamples
+               VK_FALSE,                                                                                                               // VkBool32                                                                             sampleShadingEnable
+               1.0f,                                                                                                                   // float                                                                                minSampleShading
+               DE_NULL,                                                                                                                // const VkSampleMask*                                                  pSampleMask
+               VK_FALSE,                                                                                                               // VkBool32                                                                             alphaToCoverageEnable
+               VK_FALSE                                                                                                                // VkBool32                                                                             alphaToOneEnable
+       };
+       const VkStencilOpState stencilOpState
+       {
+               VK_STENCIL_OP_KEEP,                                                                                             // VkStencilOp                                                                  failOp
+               VK_STENCIL_OP_KEEP,                                                                                             // VkStencilOp                                                                  passOp
+               VK_STENCIL_OP_KEEP,                                                                                             // VkStencilOp                                                                  depthFailOp
+               VK_COMPARE_OP_NEVER,                                                                                    // VkCompareOp                                                                  compareOp
+               0,                                                                                                                              // deUint32                                                                             compareMask
+               0,                                                                                                                              // deUint32                                                                             writeMask
+               0                                                                                                                               // deUint32                                                                             reference
+       };
+       const VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,             // VkStructureType                                                              sType
+               DE_NULL,                                                                                                                // const void*                                                                  pNext
+               0u,                                                                                                                             // VkPipelineDepthStencilStateCreateFlags               flags
+               VK_FALSE,                                                                                                               // VkBool32                                                                             depthTestEnable
+               VK_FALSE,                                                                                                               // VkBool32                                                                             depthWriteEnable
+               VK_COMPARE_OP_LESS_OR_EQUAL,                                                                    // VkCompareOp                                                                  depthCompareOp
+               VK_FALSE,                                                                                                               // VkBool32                                                                             depthBoundsTestEnable
+               VK_FALSE,                                                                                                               // VkBool32                                                                             stencilTestEnable
+               stencilOpState,                                                                                                 // VkStencilOpState                                                             front
+               stencilOpState,                                                                                                 // VkStencilOpState                                                             back
+               0.0f,                                                                                                                   // float                                                                                minDepthBounds
+               1.0f,                                                                                                                   // float                                                                                maxDepthBounds
+       };
+       const VkPipelineColorBlendAttachmentState colorBlendAttachmentState
+       {
+               VK_FALSE,                                                                                                               // VkBool32                                                                             blendEnable
+               VK_BLEND_FACTOR_ZERO,                                                                                   // VkBlendFactor                                                                srcColorBlendFactor
+               VK_BLEND_FACTOR_ZERO,                                                                                   // VkBlendFactor                                                                dstColorBlendFactor
+               VK_BLEND_OP_ADD,                                                                                                // VkBlendOp                                                                    colorBlendOp
+               VK_BLEND_FACTOR_ZERO,                                                                                   // VkBlendFactor                                                                srcAlphaBlendFactor
+               VK_BLEND_FACTOR_ZERO,                                                                                   // VkBlendFactor                                                                dstAlphaBlendFactor
+               VK_BLEND_OP_ADD,                                                                                                // VkBlendOp                                                                    alphaBlendOp
+               VK_COLOR_COMPONENT_R_BIT                                                                                // VkColorComponentFlags                                                colorWriteMask
+               | VK_COLOR_COMPONENT_G_BIT
+               | VK_COLOR_COMPONENT_B_BIT
+               | VK_COLOR_COMPONENT_A_BIT
+       };
+       const VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfo
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,               // VkStructureType                                                              sType
+               DE_NULL,                                                                                                                // const void*                                                                  pNext
+               0u,                                                                                                                             // VkPipelineColorBlendStateCreateFlags                 flags
+               VK_FALSE,                                                                                                               // VkBool32                                                                             logicOpEnable
+               VK_LOGIC_OP_CLEAR,                                                                                              // VkLogicOp                                                                    logicOp
+               1u,                                                                                                                             // deUint32                                                                             attachmentCount
+               &colorBlendAttachmentState,                                                                             // const VkPipelineColorBlendAttachmentState*   pAttachments
+               { 0.0f, 0.0f, 0.0f, 0.0f }                                                                              // float                                                                                blendConstants[4]
+       };
+       const VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,                   // VkStructureType                                                              sType
+               DE_NULL,                                                                                                                // const void*                                                                  pNext
+               0u,                                                                                                                             // VkPipelineDynamicStateCreateFlags                    flags
+               0u,                                                                                                                             // deUint32                                                                             dynamicStateCount
+               DE_NULL                                                                                                                 // const VkDynamicState*                                                pDynamicStates
+       };
+       VkPipelineFragmentShadingRateStateCreateInfoKHR shadingRateStateCreateInfo
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_STATE_CREATE_INFO_KHR, // VkStructureType                                              sType;
+               DE_NULL,                                                                                                                                // const void*                                                  pNext;
+               { 1, 1 },                                                                                                                               // VkExtent2D                                                   fragmentSize;
+               { VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR,
+                 VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR }                                    // VkFragmentShadingRateCombinerOpKHR   combinerOps[2];
+       };
+       void* pNext = useShadingRate ? &shadingRateStateCreateInfo : DE_NULL;
+       VkPipelineRenderingCreateInfoKHR renderingCreateInfo
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
+               pNext,
+               0u,
+               1u,
+               &m_cbFormat,
+               VK_FORMAT_UNDEFINED,
+               VK_FORMAT_UNDEFINED
+       };
+       if (m_params->useDynamicRendering)
+               pNext = &renderingCreateInfo;
+       const VkGraphicsPipelineCreateInfo pipelineCreateInfo
+       {
+               VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,                // VkStructureType                                                                      sType
+               pNext,                                                                                                  // const void*                                                                          pNext
+               0u,                                                                                                             // VkPipelineCreateFlags                                                        flags
+               (deUint32)pipelineShaderStageParams.size(),                             // deUint32                                                                                     stageCount
+               &pipelineShaderStageParams[0],                                                  // const VkPipelineShaderStageCreateInfo*                       pStages
+               &vertexInputStateCreateInfo,                                                    // const VkPipelineVertexInputStateCreateInfo*          pVertexInputState
+               &inputAssemblyStateCreateInfo,                                                  // const VkPipelineInputAssemblyStateCreateInfo*        pInputAssemblyState
+               DE_NULL,                                                                                                // const VkPipelineTessellationStateCreateInfo*         pTessellationState
+               &viewportStateCreateInfo,                                                               // const VkPipelineViewportStateCreateInfo*                     pViewportState
+               &rasterizationStateCreateInfo,                                                  // const VkPipelineRasterizationStateCreateInfo*        pRasterizationState
+               &multisampleStateCreateInfo,                                                    // const VkPipelineMultisampleStateCreateInfo*          pMultisampleState
+               &depthStencilStateCreateInfo,                                                   // const VkPipelineDepthStencilStateCreateInfo*         pDepthStencilState
+               &colorBlendStateCreateInfo,                                                             // const VkPipelineColorBlendStateCreateInfo*           pColorBlendState
+               &dynamicStateCreateInfo,                                                                // const VkPipelineDynamicStateCreateInfo*                      pDynamicState
+               pipelineLayout,                                                                                 // VkPipelineLayout                                                                     layout
+               renderPass,                                                                                             // VkRenderPass                                                                         renderPass
+               subpass,                                                                                                // deUint32                                                                                     subpass
+               DE_NULL,                                                                                                // VkPipeline                                                                           basePipelineHandle
+               0                                                                                                               // deInt32                                                                                      basePipelineIndex;
+       };
+       VkDevice device = m_device.get() ? *m_device : m_context.getDevice();
+       return createGraphicsPipeline(m_context.getDeviceInterface(), device, DE_NULL, &pipelineCreateInfo);
+ }
+ Move<VkPipeline> AttachmentRateInstance::buildComputePipeline(VkShaderModule compShader, VkPipelineLayout pipelineLayout) const
+ {
+       const VkPipelineShaderStageCreateInfo stageCreateInfo
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,    // VkStructureType                                              sType;
+               DE_NULL,                                                                                                // const void*                                                  pNext;
+               0u,                                                                                                             // VkPipelineShaderStageCreateFlags             flags;
+               VK_SHADER_STAGE_COMPUTE_BIT,                                                    // VkShaderStageFlagBits                                stage;
+               compShader,                                                                                             // VkShaderModule                                               module;
+               "main",                                                                                                 // const char*                                                  pName;
+               DE_NULL                                                                                                 // const VkSpecializationInfo*                  pSpecializationInfo;
+       };
+       const VkComputePipelineCreateInfo createInfo
+       {
+               VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,                 // VkStructureType                                              sType;
+               DE_NULL,                                                                                                // const void*                                                  pNext;
+               0u,                                                                                                             // VkPipelineCreateFlags                                flags;
+               stageCreateInfo,                                                                                // VkPipelineShaderStageCreateInfo              stage;
+               pipelineLayout,                                                                                 // VkPipelineLayout                                             layout;
+               (VkPipeline)0,                                                                                  // VkPipeline                                                   basePipelineHandle;
+               0u,                                                                                                             // int32_t                                                              basePipelineIndex;
+       };
+       VkDevice device = m_device.get() ? *m_device : m_context.getDevice();
+       return createComputePipeline(m_context.getDeviceInterface(), device, (vk::VkPipelineCache)0u, &createInfo);
+ }
+ VkDescriptorSetAllocateInfo AttachmentRateInstance::makeDescriptorSetAllocInfo(VkDescriptorPool descriptorPool, const VkDescriptorSetLayout* pSetLayouts) const
+ {
+       return
+       {
+               VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,         // VkStructureType                                      sType;
+               DE_NULL,                                                                                        // const void*                                          pNext;
+               descriptorPool,                                                                         // VkDescriptorPool                                     descriptorPool;
+               1u,                                                                                                     // uint32_t                                                     setLayoutCount;
+               pSetLayouts,                                                                            // const VkDescriptorSetLayout*         pSetLayouts;
+       };
+ }
+ void AttachmentRateInstance::startRendering(const VkCommandBuffer                                     commandBuffer,
+                                                                                       const VkRenderPass                                              renderPass,
+                                                                                       const VkFramebuffer                                             framebuffer,
+                                                                                       const VkRect2D&                                                 renderArea,
+                                                                                       const std::vector<FBAttachmentInfo>&    attachmentInfo) const
+ {
+       const DeviceInterface&          vk                      (m_context.getDeviceInterface());
+       std::vector<VkClearValue>       clearColor      (attachmentInfo.size(), makeClearValueColorU32(0, 0, 0, 0));
+       if (m_params->useDynamicRendering)
+       {
+               VkRenderingFragmentShadingRateAttachmentInfoKHR shadingRateAttachmentInfo
+               {
+                       VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR,  // VkStructureType              sType;
+                       DE_NULL,                                                                                                                                // const void*                  pNext;
+                       DE_NULL,                                                                                                                                // VkImageView                  imageView;
+                       VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR,                   // VkImageLayout                imageLayout;
+                       { 0, 0 }                                                                                                                                // VkExtent2D                   shadingRateAttachmentTexelSize;
+               };
+               VkRenderingAttachmentInfoKHR colorAttachment
+               {
+                       vk::VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR,    // VkStructureType                                              sType;
+                       DE_NULL,                                                                                                // const void*                                                  pNext;
+                       attachmentInfo[0].view,                                                                 // VkImageView                                                  imageView;
+                       VK_IMAGE_LAYOUT_GENERAL,                                                                // VkImageLayout                                                imageLayout;
+                       VK_RESOLVE_MODE_NONE,                                                                   // VkResolveModeFlagBits                                resolveMode;
+                       DE_NULL,                                                                                                // VkImageView                                                  resolveImageView;
+                       VK_IMAGE_LAYOUT_UNDEFINED,                                                              // VkImageLayout                                                resolveImageLayout;
+                       VK_ATTACHMENT_LOAD_OP_CLEAR,                                                    // VkAttachmentLoadOp                                   loadOp;
+                       VK_ATTACHMENT_STORE_OP_STORE,                                                   // VkAttachmentStoreOp                                  storeOp;
+                       clearColor[0]                                                                                   // VkClearValue                                                 clearValue;
+               };
+               VkRenderingInfoKHR renderingInfo
+               {
+                       vk::VK_STRUCTURE_TYPE_RENDERING_INFO_KHR,
+                       DE_NULL,
+                       0,                                                                                                              // VkRenderingFlagsKHR                                  flags;
+                       renderArea,                                                                                             // VkRect2D                                                             renderArea;
+                       1u,                                                                                                             // deUint32                                                             layerCount;
+                       0u,                                                                                                             // deUint32                                                             viewMask;
+                       1u,                                                                                                             // deUint32                                                             colorAttachmentCount;
+                       &colorAttachment,                                                                               // const VkRenderingAttachmentInfoKHR*  pColorAttachments;
+                       DE_NULL,                                                                                                // const VkRenderingAttachmentInfoKHR*  pDepthAttachment;
+                       DE_NULL,                                                                                                // const VkRenderingAttachmentInfoKHR*  pStencilAttachment;
+               };
+               // when shading rate is used it is defined as a second entry in attachmentInfo
+               if ((attachmentInfo.size() == 2) &&
+                       (attachmentInfo[1].usage & VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR))
+               {
+                       shadingRateAttachmentInfo.imageView                                                     = attachmentInfo[1].view;
+                       shadingRateAttachmentInfo.shadingRateAttachmentTexelSize        = { attachmentInfo[1].width, attachmentInfo[1].height };
+                       renderingInfo.pNext                                                                                     = &shadingRateAttachmentInfo;
+               }
++              vk.cmdBeginRendering(commandBuffer, &renderingInfo);
+               return;
+       }
+       std::vector<VkImageView>                        attachments(attachmentInfo.size(), 0);
+       VkRenderPassAttachmentBeginInfo         renderPassAttachmentBeginInfo;
+       void*                                                           pNext(DE_NULL);
+       if (m_params->useImagelessFramebuffer)
+       {
+               // create array containing attachment views
+               for (deUint32 i = 0; i < (deUint32)attachmentInfo.size(); ++i)
+                       attachments[i] = attachmentInfo[i].view;
+               renderPassAttachmentBeginInfo =
+               {
+                       VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO,            // VkStructureType              sType;
+                       DE_NULL,                                                                                                        // const void*                  pNext;
+                       (deUint32)attachments.size(),                                                           // deUint32                             attachmentCount;
+                       attachments.data()                                                                                      // const VkImageView*   pAttachments;
+               };
+               pNext = &renderPassAttachmentBeginInfo;
+       }
+       beginRenderPass(vk, commandBuffer, renderPass, framebuffer, renderArea,
+                                       (deUint32)clearColor.size(), clearColor.data(), VK_SUBPASS_CONTENTS_INLINE, pNext);
+ }
+ void AttachmentRateInstance::finishRendering(const VkCommandBuffer commandBuffer) const
+ {
+       const DeviceInterface& vk = m_context.getDeviceInterface();
+       if (m_params->useDynamicRendering)
+               endRendering(vk, commandBuffer);
+       else
+               endRenderPass(vk, commandBuffer);
+ }
+ tcu::TestStatus AttachmentRateInstance::iterate(void)
+ {
+       // instead of creating many classes that derive from large common class
+       // each test mode is defined in separate run* method, those methods
+       // then use same helper methods defined in this class
+       typedef bool (AttachmentRateInstance::*MethodPtr)();
+       const std::map<TestMode, MethodPtr> modeFuncMap
+       {
+               { TM_SETUP_RATE_WITH_ATOMICS_IN_COMPUTE_SHADER,                                                 &AttachmentRateInstance::runComputeShaderMode },
+               { TM_SETUP_RATE_WITH_FRAGMENT_SHADER,                                                                   &AttachmentRateInstance::runFragmentShaderMode },
+               { TM_SETUP_RATE_WITH_COPYING_FROM_OTHER_IMAGE,                                                  &AttachmentRateInstance::runCopyMode },
+               { TM_SETUP_RATE_WITH_COPYING_FROM_EXCLUSIVE_IMAGE_USING_TRANSFER_QUEUE, &AttachmentRateInstance::runCopyModeOnTransferQueue },
+               { TM_SETUP_RATE_WITH_COPYING_FROM_CONCURENT_IMAGE_USING_TRANSFER_QUEUE, &AttachmentRateInstance::runCopyModeOnTransferQueue },
+               { TM_SETUP_RATE_WITH_LINEAR_TILED_IMAGE,                                                                &AttachmentRateInstance::runFillLinearTiledImage },
+               { TM_TWO_SUBPASS,                                                                                                               &AttachmentRateInstance::runTwoSubpassMode },
+       };
+       if ((this->*modeFuncMap.at(m_params->mode))())
+               return tcu::TestStatus::pass("Pass");
+       return tcu::TestStatus::fail("Fail");
+ }
+ bool AttachmentRateInstance::verifyUsingAtomicChecks(deUint32 tileWidth, deUint32 tileHeight,
+                                                                                                        deUint32 rateWidth, deUint32 rateHeight,
+                                                                                                        deUint32* outBufferPtr) const
+ {
+       tcu::TestLog&                   log                                     (m_context.getTestContext().getLog());
+       tcu::TextureLevel               errorMaskStorage        (tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), m_cbWidth, m_cbHeight, 1u);
+       tcu::PixelBufferAccess  errorMaskAccess         (errorMaskStorage.getAccess());
+       deUint32                wrongFragments                                          = 0;
+       const deUint32  fragmentsWithSameAtomicValueCount       = rateWidth * rateHeight;
+       // map that uses atomic value as a kay and maps it to all fragments sharing same atomic
+       std::map<deUint32, std::vector<tcu::UVec2> > fragmentsWithSameAtomicValueMap;
+       // this method asumes that top and left edge of triangle are parallel to axes
+       // and we can store just single coordinate for those edges
+       deUint32 triangleLeftEdgeX      = 0;
+       deUint32 triangleTopEdgeY       = 0;
+       // this method assumes that greatest angle in the triangle points to the top-left corner of FB;
+       // this vector will then store fragments on the right edge of triangle; vector index represents y coordinate and value is x
+       std::vector<deUint32> fragmentsOnTheRightTriangleEdgeVect(m_cbHeight, 0);
+       tcu::clear(errorMaskAccess, tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0));
+       // loop over all fragments and validate the output
+       for (deUint32 cbFragmentY = 0; cbFragmentY < m_cbHeight; ++cbFragmentY)
+       for (deUint32 cbFragmentX = 0; cbFragmentX < m_cbWidth;  ++cbFragmentX)
+       {
+               deUint32* fragmentColor = &outBufferPtr[4 * (cbFragmentY * m_cbWidth + cbFragmentX)];
+               // fragment not covered by primitive, skip it
+               if (fragmentColor[2] == 0)
+                       continue;
+               // first fragment we hit will define top and left triangle edges
+               if ((triangleTopEdgeY + triangleLeftEdgeX) == 0)
+               {
+                       triangleLeftEdgeX       = cbFragmentX;
+                       triangleTopEdgeY        = cbFragmentY;
+               }
+               // constantly overwrite coordinate on right edge so that we are left with the farthest one
+               fragmentsOnTheRightTriangleEdgeVect[cbFragmentY] = cbFragmentX;
+               // make sure that fragment g and a components are 0
+               if ((fragmentColor[1] != 0) || (fragmentColor[3] != 0))
+               {
+                       ++wrongFragments;
+                       continue;
+               }
+               deUint32 rate                   = fragmentColor[0];
+               deUint32 fragmentRateX  = 1 << ((rate / 4) & 3);
+               deUint32 fragmentRateY  = 1 << (rate & 3);
+               // check if proper rate was used for fragment
+               if ((fragmentRateX != rateWidth) ||
+                       (fragmentRateY != rateHeight))
+               {
+                       ++wrongFragments;
+                       errorMaskAccess.setPixel(tcu::Vec4(1.0f, 0.5f, 0.0f, 1.0f), cbFragmentX, cbFragmentY, 0u);
+                       continue;
+               }
+               // mark correct fragments using few green shades so rates are visible
+               deUint32 atomicValue = fragmentColor[2];
+               errorMaskAccess.setPixel(tcu::Vec4(0.0f, 1.0f - float(atomicValue % 7) * 0.1f, 0.0f, 1.0f), cbFragmentX, cbFragmentY, 0u);
+               // find proper set in map and add value to it after doing verification with existing items
+               auto fragmentsSetMapIt = fragmentsWithSameAtomicValueMap.find(atomicValue);
+               if (fragmentsSetMapIt == fragmentsWithSameAtomicValueMap.end())
+               {
+                       fragmentsWithSameAtomicValueMap[atomicValue] = { tcu::UVec2(cbFragmentX, cbFragmentY) };
+                       fragmentsWithSameAtomicValueMap[atomicValue].reserve(fragmentsWithSameAtomicValueCount);
+               }
+               else
+               {
+                       // make sure that fragments added to set are near the top-left fragment
+                       auto& fragmentsSet = fragmentsSetMapIt->second;
+                       if (((cbFragmentX - fragmentsSet[0].x()) > rateWidth) ||
+                               ((cbFragmentY - fragmentsSet[0].y()) > rateHeight))
+                       {
+                               ++wrongFragments;
+                               errorMaskAccess.setPixel(tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), cbFragmentX, cbFragmentY, 0u);
+                       }
+                       fragmentsWithSameAtomicValueMap[atomicValue].emplace_back(cbFragmentX, cbFragmentY);
+               }
+       }
+       // check if there are no valid fragmenst at all
+       if ((triangleTopEdgeY + triangleLeftEdgeX) == 0)
+       {
+               log << tcu::TestLog::Message
+                       << "No valid fragments."
+                       << tcu::TestLog::EndMessage;
+               return false;
+       }
+       // if checks failed skip checking other tile sizes
+       if (wrongFragments)
+       {
+               log << tcu::TestLog::Message
+                       << "Failed " << wrongFragments << " fragments for tileWidth: " << tileWidth << ", tileHeight: " << tileHeight
+                       << tcu::TestLog::EndMessage
+                       << tcu::TestLog::Image("ErrorMask", "Error mask", errorMaskAccess);
+               return false;
+       }
+       // do additional checks
+       tcu::Vec4 fragmentColor(0.0f, 1.0f, 0.0f, 1.0f);
+       tcu::clear(errorMaskAccess, tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0));
+       // make sure that there is same number of fragments that share same atomic value
+       for (auto& fragmentsSetMapIt : fragmentsWithSameAtomicValueMap)
+       {
+               // mark correct fragments using few green shades so rates are visible
+               fragmentColor = tcu::Vec4(0.0f, 1.0f - float(fragmentsSetMapIt.first % 7) * 0.1f, 0.0f, 1.0f);
+               const auto& fragmentSet = fragmentsSetMapIt.second;;
+               if (fragmentSet.size() != fragmentsWithSameAtomicValueCount)
+               {
+                       const auto&     topLeftFragment         = fragmentSet[0];
+                       deUint32        triangleRightEdgeX      = fragmentsOnTheRightTriangleEdgeVect[topLeftFragment.y()];
+                       // we can only count this as an error if set is fully inside of triangle, sets on
+                       // edges may not have same number of fragments as sets fully located in the triangle
+                       if ((topLeftFragment.y() > (triangleTopEdgeY)) &&
+                               (topLeftFragment.x() > (triangleLeftEdgeX)) &&
+                               (topLeftFragment.x() < (triangleRightEdgeX - rateWidth)))
+                       {
+                               wrongFragments += (deUint32)fragmentSet.size();
+                               fragmentColor   = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
+                       }
+               }
+               // mark all fragmens from set with proper color
+               for (auto& fragment : fragmentSet)
+                       errorMaskAccess.setPixel(fragmentColor, fragment.x(), fragment.y(), 0u);
+       }
+       if (wrongFragments)
+       {
+               log << tcu::TestLog::Message
+                       << "Wrong number of fragments with same atomic value (" << wrongFragments << ") for tileWidth: " << tileWidth << ", tileHeight: " << tileHeight
+                       << tcu::TestLog::EndMessage
+                       << tcu::TestLog::Image("ErrorMask", "Error mask", errorMaskAccess);
+               return false;
+       }
+       return true;
+ }
+ bool AttachmentRateInstance::runComputeShaderMode(void)
+ {
+       // clear the shading rate attachment, then using a compute shader, set the shading rate attachment
+       // values to the desired rate using various atomic operations, then use it to draw a basic triangle
+       // and do basic checks
+       const DeviceInterface&  vk                                      = m_context.getDeviceInterface();
+       VkDevice                                device                          = m_context.getDevice();
+       deUint32                                queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
+       VkMemoryBarrier                 memoryBarrier           { VK_STRUCTURE_TYPE_MEMORY_BARRIER, DE_NULL, 0u, 0u };
+       Move<VkShaderModule>    compShader                      = createShaderModule(vk, device, m_context.getBinaryCollection().get("comp"), 0);
+       Move<VkShaderModule>    vertShader                      = createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0);
+       Move<VkShaderModule>    fragShader                      = createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0);
+       Move<VkCommandPool>             cmdPool                         = createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
+       Move<VkCommandBuffer>   cmdBuffer                       = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
+       // setup descriptor set with storage image for compute pipeline
+       Move<VkDescriptorSetLayout>                     computeDescriptorSetLayout              = DescriptorSetLayoutBuilder()
+                                                                                                                                                       .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
+                                                                                                                                                       .build(vk, device);
+       Move<VkDescriptorPool>                          computeDescriptorPool                   = DescriptorPoolBuilder()
+                                                                                                                                                       .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1u)
+                                                                                                                                                       .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
+       const VkDescriptorSetAllocateInfo       computeDescriptorSetAllocInfo   = makeDescriptorSetAllocInfo(*computeDescriptorPool, &(*computeDescriptorSetLayout));
+       Move<VkDescriptorSet>                           computeDescriptorSet                    = allocateDescriptorSet(vk, device, &computeDescriptorSetAllocInfo);
+       m_srUsage |= VK_IMAGE_USAGE_STORAGE_BIT;
+       buildCounterBufferObjects();
+       buildColorBufferObjects(0, m_cbUsage);
+       // iterate over all possible tile sizes
+       for (deUint32 tileWidth  = m_minTileSize.width;  tileWidth  <= m_maxTileSize.width;  tileWidth  *= 2)
+       for (deUint32 tileHeight = m_minTileSize.height; tileHeight <= m_maxTileSize.height; tileHeight *= 2)
+       {
+               // skip tile sizes that have unsuported aspect ratio
+               deUint32 aspectRatio = (tileHeight > tileWidth) ? (tileHeight / tileWidth) : (tileWidth / tileHeight);
+               if (aspectRatio > m_maxAspectRatio)
+                       continue;
+               // calculate size of shading rate attachment
+               deUint32 srWidth  = (m_cbWidth  + tileWidth  - 1) / tileWidth;
+               deUint32 srHeight = (m_cbHeight + tileHeight - 1) / tileHeight;
+               buildShadingRateObjects(0, srWidth, srHeight, m_srUsage);
+               const VkDescriptorImageInfo  computeDescriptorInfo  = makeDescriptorImageInfo(DE_NULL, *m_srImageView[0], VK_IMAGE_LAYOUT_GENERAL);
+               DescriptorSetUpdateBuilder()
+                       .writeSingle(*computeDescriptorSet,  DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,  &computeDescriptorInfo)
+                       .update(vk, device);
+               Move<VkPipelineLayout>  computePipelineLayout   = buildPipelineLayout(&(*computeDescriptorSetLayout));
+               Move<VkPipelineLayout>  graphicsPipelineLayout  = buildPipelineLayout(&(*m_counterBufferDescriptorSetLayout));
+               Move<VkPipeline>                computePipeline                 = buildComputePipeline(*compShader, *computePipelineLayout);
+               Move<VkRenderPass>              renderPass                              = buildRenderPass(m_cbFormat, tileWidth, tileHeight);
+               Move<VkPipeline>                graphicsPipeline                = buildGraphicsPipeline(0, *renderPass, *graphicsPipelineLayout, *vertShader, *fragShader);
+               std::vector<FBAttachmentInfo> attachmentInfo
+               {
+                       { m_cbFormat,                   m_cbUsage, m_cbWidth, m_cbHeight, *m_cbImageView[0] },
+                       { m_params->srFormat,   m_srUsage, srWidth,   srHeight,   *m_srImageView[0] }
+               };
+               Move<VkFramebuffer> framebuffer = buildFramebuffer(*renderPass, attachmentInfo);
+               beginCommandBuffer(vk, *cmdBuffer, 0u);
+               // wait till sr image layout is changed
+               VkPipelineStageFlags srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
+               VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
+               VkImageMemoryBarrier srImageBarrierGeneral =
+                       makeImageMemoryBarrier(
+                               VK_ACCESS_NONE_KHR,
+                               VK_ACCESS_NONE_KHR,
+                               VK_IMAGE_LAYOUT_UNDEFINED,
+                               VK_IMAGE_LAYOUT_GENERAL,
+                               **m_srImage[0],
+                               m_defaultImageSubresourceRange);
+               vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1, &srImageBarrierGeneral);
+               // fill sr image using compute shader
+               vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *computePipeline);
+               vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *computePipelineLayout, 0, 1, &(*computeDescriptorSet), 0, DE_NULL);
+               vk.cmdDispatch(*cmdBuffer, srWidth, srHeight, 1);
+               // wait till sr image is ready and change sr images layout
+               srcStageMask = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
+               dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
+               memoryBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
+               memoryBarrier.dstAccessMask = VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR;
+               VkImageMemoryBarrier srImageBarrierShadingRate =
+                       makeImageMemoryBarrier(
+                               VK_ACCESS_SHADER_WRITE_BIT,
+                               VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR,
+                               VK_IMAGE_LAYOUT_GENERAL,
+                               VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR,
+                               **m_srImage[0],
+                               m_defaultImageSubresourceRange);
+               vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 1, &memoryBarrier, 0, DE_NULL, 1, &srImageBarrierShadingRate);
+               // wait till cb image layout is changed
+               srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
+               dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+               VkImageMemoryBarrier cbImageBarrier =
+                       makeImageMemoryBarrier(
+                               VK_ACCESS_NONE_KHR,
+                               VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
+                               VK_IMAGE_LAYOUT_UNDEFINED,
+                               VK_IMAGE_LAYOUT_GENERAL,
+                               **m_cbImage[0],
+                               m_defaultImageSubresourceRange);
+               vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1, &cbImageBarrier);
+               startRendering(*cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_cbWidth, m_cbHeight), attachmentInfo);
+               // draw single triangle to cb
+               vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipelineLayout, 0, 1, &(*m_counterBufferDescriptorSet), 0, DE_NULL);
+               vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
+               vk.cmdDraw(*cmdBuffer, 3u, 1, 0u, 0u);
+               finishRendering(*cmdBuffer);
+               // wait till color attachment is fully written
+               srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+               dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
+               memoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+               memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
+               vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 1, &memoryBarrier, 0, DE_NULL, 0, DE_NULL);
+               // read back color buffer image
+               vk.cmdCopyImageToBuffer(*cmdBuffer, **m_cbImage[0], VK_IMAGE_LAYOUT_GENERAL, **m_cbReadBuffer[0], 1u, &m_defaultBufferImageCopy);
+               endCommandBuffer(vk, *cmdBuffer);
+               // submit commands and wait
+               const VkQueue queue = m_context.getUniversalQueue();
+               submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
+               invalidateAlloc(vk, device, m_cbReadBuffer[0]->getAllocation());
+               if (!verifyUsingAtomicChecks(tileWidth, tileHeight,
+                                                                        m_params->srRate.width, m_params->srRate.height,
+                                                                        (deUint32*)m_cbReadBuffer[0]->getAllocation().getHostPtr()))
+                       return false;
+       }  // iterate over all possible tile sizes
+       return true;
+ }
+ bool AttachmentRateInstance::runFragmentShaderMode(void)
+ {
+       // Set up the image as a color attachment, and render rate to it,
+       // then use it to draw a basic triangle and do basic checks
+       const DeviceInterface&  vk                                      = m_context.getDeviceInterface();
+       VkDevice                                device                          = m_context.getDevice();
+       deUint32                                queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
+       VkMemoryBarrier                 memoryBarrier           { VK_STRUCTURE_TYPE_MEMORY_BARRIER, DE_NULL, 0u, 0u };
+       Move<VkShaderModule>    vertSetupShader         = createShaderModule(vk, device, m_context.getBinaryCollection().get("vert_setup"), 0);
+       Move<VkShaderModule>    fragSetupShader         = createShaderModule(vk, device, m_context.getBinaryCollection().get("frag_setup"), 0);
+       Move<VkShaderModule>    vertShader                      = createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0);
+       Move<VkShaderModule>    fragShader                      = createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0);
+       Move<VkCommandPool>             cmdPool                         = createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
+       Move<VkCommandBuffer>   cmdBuffer                       = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
+       m_srUsage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+       buildCounterBufferObjects();
+       buildColorBufferObjects(0, m_cbUsage);
+       // iterate over all possible tile sizes
+       for (deUint32 tileWidth  = m_minTileSize.width;  tileWidth  <= m_maxTileSize.width;  tileWidth  *= 2)
+       for (deUint32 tileHeight = m_minTileSize.height; tileHeight <= m_maxTileSize.height; tileHeight *= 2)
+       {
+               // skip tile sizes that have unsuported aspect ratio
+               deUint32 aspectRatio = (tileHeight > tileWidth) ? (tileHeight / tileWidth) : (tileWidth / tileHeight);
+               if (aspectRatio > m_maxAspectRatio)
+                       continue;
+               // calculate size of shading rate attachment
+               deUint32 srWidth  = (m_cbWidth  + tileWidth  - 1) / tileWidth;
+               deUint32 srHeight = (m_cbHeight + tileHeight - 1) / tileHeight;
+               buildShadingRateObjects(0, srWidth, srHeight, m_srUsage);
+               Move<VkPipelineLayout>  setupPipelineLayout     = buildPipelineLayout();
+               Move<VkPipelineLayout>  ratePipelineLayout      = buildPipelineLayout(&(*m_counterBufferDescriptorSetLayout));
+               Move<VkRenderPass>              setupRenderPass         = buildRenderPass(m_params->srFormat);
+               Move<VkRenderPass>              rateRenderPass          = buildRenderPass(m_cbFormat, tileWidth, tileHeight);
+               Move<VkPipeline>                setupPipeline           = buildGraphicsPipeline(0, *setupRenderPass, *setupPipelineLayout, *vertSetupShader, *fragSetupShader, DE_FALSE);
+               Move<VkPipeline>                ratePipeline            = buildGraphicsPipeline(0, *rateRenderPass, *ratePipelineLayout, *vertShader, *fragShader);
+               std::vector<FBAttachmentInfo> setupAttachmentInfo
+               {
+                       { m_params->srFormat, m_srUsage, srWidth, srHeight, *m_srImageView[0] }
+               };
+               std::vector<FBAttachmentInfo> rateAttachmentInfo
+               {
+                       { m_cbFormat,                   m_cbUsage, m_cbWidth, m_cbHeight, *m_cbImageView[0] },
+                       { m_params->srFormat,   m_srUsage, srWidth,   srHeight,   *m_srImageView[0] }
+               };
+               Move<VkFramebuffer> setupFramebuffer    = buildFramebuffer(*setupRenderPass, setupAttachmentInfo);
+               Move<VkFramebuffer> rateFramebuffer             = buildFramebuffer(*rateRenderPass, rateAttachmentInfo);
+               beginCommandBuffer(vk, *cmdBuffer, 0u);
+               // wait till sr image layout is changed
+               VkPipelineStageFlags srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
+               VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+               VkImageMemoryBarrier srImageBarrierGeneral =
+                       makeImageMemoryBarrier(
+                               VK_ACCESS_NONE_KHR,
+                               VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
+                               VK_IMAGE_LAYOUT_UNDEFINED,
+                               VK_IMAGE_LAYOUT_GENERAL,
+                               **m_srImage[0],
+                               m_defaultImageSubresourceRange);
+               vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1, &srImageBarrierGeneral);
+               // render rate to sr image
+               startRendering(*cmdBuffer, *setupRenderPass, *setupFramebuffer, makeRect2D(srWidth, srHeight), setupAttachmentInfo);
+               // draw single triangle to cb
+               vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *setupPipeline);
+               vk.cmdDraw(*cmdBuffer, 3u, 1, 0u, 0u);
+               finishRendering(*cmdBuffer);
+               // wait till sr image is ready and change sr images layout
+               srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+               dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
+               VkImageMemoryBarrier srImageBarrierShadingRate =
+                       makeImageMemoryBarrier(
+                               VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
+                               VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR,
+                               VK_IMAGE_LAYOUT_GENERAL,
+                               VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR,
+                               **m_srImage[0],
+                               m_defaultImageSubresourceRange);
+               vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1, &srImageBarrierShadingRate);
+               // wait till cb image layout is changed
+               srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
+               dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+               VkImageMemoryBarrier cbImageBarrier =
+                       makeImageMemoryBarrier(
+                               VK_ACCESS_NONE_KHR,
+                               VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
+                               VK_IMAGE_LAYOUT_UNDEFINED,
+                               VK_IMAGE_LAYOUT_GENERAL,
+                               **m_cbImage[0],
+                               m_defaultImageSubresourceRange);
+               vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1, &cbImageBarrier);
+               startRendering(*cmdBuffer, *rateRenderPass, *rateFramebuffer, makeRect2D(m_cbWidth, m_cbHeight), rateAttachmentInfo);
+               // draw single triangle to cb
+               vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *ratePipelineLayout, 0, 1, &(*m_counterBufferDescriptorSet), 0, DE_NULL);
+               vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *ratePipeline);
+               vk.cmdDraw(*cmdBuffer, 3u, 1, 0u, 0u);
+               finishRendering(*cmdBuffer);
+               // wait till color attachment is fully written
+               srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+               dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
+               memoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+               memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
+               vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 1, &memoryBarrier, 0, DE_NULL, 0, DE_NULL);
+               // read back color buffer image
+               vk.cmdCopyImageToBuffer(*cmdBuffer, **m_cbImage[0], VK_IMAGE_LAYOUT_GENERAL, **m_cbReadBuffer[0], 1u, &m_defaultBufferImageCopy);
+               endCommandBuffer(vk, *cmdBuffer);
+               // submit commands and wait
+               const VkQueue queue = m_context.getUniversalQueue();
+               submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
+               invalidateAlloc(vk, device, m_cbReadBuffer[0]->getAllocation());
+               if (!verifyUsingAtomicChecks(tileWidth, tileHeight,
+                                                                        m_params->srRate.width, m_params->srRate.height,
+                                                                        (deUint32*)m_cbReadBuffer[0]->getAllocation().getHostPtr()))
+                       return false;
+       } // iterate over all possible tile sizes
+       return true;
+ }
+ bool AttachmentRateInstance::runCopyMode (void)
+ {
+       // Clear a separate image of the same format to that rate, copy it to
+       // the shading rate image, then use it to draw a basic triangle and do basic checks
+       const DeviceInterface&  vk                                      = m_context.getDeviceInterface();
+       VkDevice                                device                          = m_context.getDevice();
+       deUint32                                queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
+       VkMemoryBarrier                 memoryBarrier           { VK_STRUCTURE_TYPE_MEMORY_BARRIER, DE_NULL, 0u, 0u };
+       Move<VkShaderModule>    vertShader                      = createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0);
+       Move<VkShaderModule>    fragShader                      = createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0);
+       Move<VkCommandPool>             cmdPool                         = createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
+       Move<VkCommandBuffer>   cmdBuffer                       = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
+       buildCounterBufferObjects();
+       buildColorBufferObjects(0, m_cbUsage);
+       // iterate over all possible tile sizes
+       for (deUint32 tileWidth  = m_minTileSize.width;  tileWidth  <= m_maxTileSize.width;  tileWidth  *= 2)
+       for (deUint32 tileHeight = m_minTileSize.height; tileHeight <= m_maxTileSize.height; tileHeight *= 2)
+       {
+               // skip tile sizes that have unsuported aspect ratio
+               deUint32 aspectRatio = (tileHeight > tileWidth) ? (tileHeight / tileWidth) : (tileWidth / tileHeight);
+               if (aspectRatio > m_maxAspectRatio)
+                       continue;
+               // calculate size of shading rate attachment
+               deUint32 srWidth  = (m_cbWidth  + tileWidth  - 1) / tileWidth;
+               deUint32 srHeight = (m_cbHeight + tileHeight - 1) / tileHeight;
+               buildShadingRateObjects(0, srWidth, srHeight, m_srUsage);
+               // create image that will be source for shading rate image
+               de::MovePtr<ImageWithMemory> srSrcImage = buildImageWithMemory(m_params->srFormat, srWidth, srHeight, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
+               Move<VkPipelineLayout>  graphicsPipelineLayout  = buildPipelineLayout(&(*m_counterBufferDescriptorSetLayout));
+               Move<VkRenderPass>              renderPass                              = buildRenderPass(m_cbFormat, tileWidth, tileHeight);
+               Move<VkPipeline>                graphicsPipeline                = buildGraphicsPipeline(0, *renderPass, *graphicsPipelineLayout, *vertShader, *fragShader);
+               std::vector<FBAttachmentInfo> attachmentInfo
+               {
+                       { m_cbFormat,                   m_cbUsage, m_cbWidth, m_cbHeight, *m_cbImageView[0] },
+                       { m_params->srFormat,   m_srUsage, srWidth,   srHeight,   *m_srImageView[0] }
+               };
+               Move<VkFramebuffer> framebuffer = buildFramebuffer(*renderPass, attachmentInfo);
+               beginCommandBuffer(vk, *cmdBuffer, 0u);
+               // wait till sr images layout are changed
+               VkPipelineStageFlags srcStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
+               VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
+               std::vector<VkImageMemoryBarrier> srImageBarrierGeneral(2,
+                       makeImageMemoryBarrier(
+                               VK_ACCESS_NONE_KHR,
+                               VK_ACCESS_NONE_KHR,
+                               VK_IMAGE_LAYOUT_UNDEFINED,
+                               VK_IMAGE_LAYOUT_GENERAL,
+                               **m_srImage[0],
+                               m_defaultImageSubresourceRange));
+               srImageBarrierGeneral[1].image = **srSrcImage;
+               vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 2, srImageBarrierGeneral.data());
+               // clear source sr image with proper rate
+               VkClearColorValue clearValue = { { 0, 0, 0, 0 } };
+               clearValue.uint32[0] = calculateRate(m_params->srRate.width, m_params->srRate.height);
+               vk.cmdClearColorImage(*cmdBuffer, **srSrcImage, VK_IMAGE_LAYOUT_GENERAL, &clearValue, 1, &m_defaultImageSubresourceRange);
+               // wait till sr source image is ready
+               srcStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
+               dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
+               memoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+               memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
+               vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 1, &memoryBarrier, 0, DE_NULL, 0, DE_NULL);
+               // copy sr source image to sr image used during rendering
+               VkImageCopy imageCopyRegion
+               {
+                       m_defaultImageSubresourceLayers,        // VkImageSubresourceLayers     srcSubresource;
+                       {0, 0, 0},                                                      // VkOffset3D                           srcOffset;
+                       m_defaultImageSubresourceLayers,        // VkImageSubresourceLayers     dstSubresource;
+                       {0, 0, 0},                                                      // VkOffset3D                           dstOffset;
+                       { srWidth, srHeight, 1u }                       // VkExtent3D                           extent;
+               };
+               vk.cmdCopyImage(*cmdBuffer, **srSrcImage, VK_IMAGE_LAYOUT_GENERAL, **m_srImage[0], VK_IMAGE_LAYOUT_GENERAL, 1, &imageCopyRegion);
+               // wait till sr image is ready and change sr images layout
+               srcStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
+               dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
+               memoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+               memoryBarrier.dstAccessMask = VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR;
+               VkImageMemoryBarrier srImageBarrierShadingRate =
+                       makeImageMemoryBarrier(
+                               VK_ACCESS_TRANSFER_WRITE_BIT,
+                               VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR,
+                               VK_IMAGE_LAYOUT_GENERAL,
+                               VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR,
+                               **m_srImage[0],
+                               m_defaultImageSubresourceRange);
+               vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 1, &memoryBarrier, 0, DE_NULL, 1, &srImageBarrierShadingRate);
+               // wait till cb image layout is changed
+               srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
+               dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+               VkImageMemoryBarrier cbImageBarrier =
+                       makeImageMemoryBarrier(
+                               VK_ACCESS_NONE_KHR,
+                               VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
+                               VK_IMAGE_LAYOUT_UNDEFINED,
+                               VK_IMAGE_LAYOUT_GENERAL,
+                               **m_cbImage[0],
+                               m_defaultImageSubresourceRange);
+               vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1, &cbImageBarrier);
+               startRendering(*cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_cbWidth, m_cbHeight), attachmentInfo);
+               // draw single triangle to cb
+               vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipelineLayout, 0, 1, &(*m_counterBufferDescriptorSet), 0, DE_NULL);
+               vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
+               vk.cmdDraw(*cmdBuffer, 3u, 1, 0u, 0u);
+               finishRendering(*cmdBuffer);
+               // wait till color attachment is fully written
+               srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+               dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
+               memoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+               memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
+               vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 1, &memoryBarrier, 0, DE_NULL, 0, DE_NULL);
+               // read back color buffer image
+               vk.cmdCopyImageToBuffer(*cmdBuffer, **m_cbImage[0], VK_IMAGE_LAYOUT_GENERAL, **m_cbReadBuffer[0], 1u, &m_defaultBufferImageCopy);
+               endCommandBuffer(vk, *cmdBuffer);
+               // submit commands and wait
+               const VkQueue queue = m_context.getUniversalQueue();
+               submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
+               invalidateAlloc(vk, device, m_cbReadBuffer[0]->getAllocation());
+               if (!verifyUsingAtomicChecks(tileWidth, tileHeight,
+                                                                        m_params->srRate.width, m_params->srRate.height,
+                                                                        (deUint32*)m_cbReadBuffer[0]->getAllocation().getHostPtr()))
+                       return false;
+       } // iterate over all possible tile sizes
+       return true;
+ }
+ bool AttachmentRateInstance::runCopyModeOnTransferQueue(void)
+ {
+       // Clear a separate image of the same format to that rate, copy it to
+       // the shading rate image on separate transfer queue and then use copied
+       // image to draw a basic triangle and do basic checks
+       const DeviceInterface&                                  vk                                                      = m_context.getDeviceInterface();
+       const PlatformInterface&                                vkp                                                     = m_context.getPlatformInterface();
+       const InstanceInterface&                                vki                                                     = m_context.getInstanceInterface();
+       VkPhysicalDevice                                                pd                                                      = m_context.getPhysicalDevice();
+       deUint32                                                                transferQueueFamilyIndex        = std::numeric_limits<deUint32>::max();
+       deUint32                                                                graphicsQueueFamilyIndex        = std::numeric_limits<deUint32>::max();
+       VkMemoryBarrier                                                 memoryBarrier                           { VK_STRUCTURE_TYPE_MEMORY_BARRIER, DE_NULL, 0u, 0u };
+       std::vector<VkQueueFamilyProperties>    queueFamilyProperties           = getPhysicalDeviceQueueFamilyProperties(vki, pd);
+       // find graphics and transfer queue families
+       for (deUint32 queueNdx = 0; queueNdx < queueFamilyProperties.size(); queueNdx++)
+       {
+               VkQueueFlags queueFlags = queueFamilyProperties[queueNdx].queueFlags;
+               if ((graphicsQueueFamilyIndex == std::numeric_limits<deUint32>::max()) && (queueFlags & VK_QUEUE_GRAPHICS_BIT))
+                       graphicsQueueFamilyIndex = queueNdx;
+               else if ((queueNdx != graphicsQueueFamilyIndex) && (queueFlags & VK_QUEUE_TRANSFER_BIT))
+                       transferQueueFamilyIndex = queueNdx;
+       }
+       if (transferQueueFamilyIndex == std::numeric_limits<deUint32>::max())
+               TCU_THROW(NotSupportedError, "No separate transfer queue");
+       // using queueFamilies vector to determine if sr image uses exclusiv or concurrent sharing
+       std::vector<deUint32> queueFamilies;
+       if (m_params->mode == TM_SETUP_RATE_WITH_COPYING_FROM_CONCURENT_IMAGE_USING_TRANSFER_QUEUE)
+               queueFamilies = { graphicsQueueFamilyIndex, transferQueueFamilyIndex };
+       // create custom device
+       {
+               const float queuePriorities = 1.0f;
+               std::vector<VkDeviceQueueCreateInfo> queueInfo(2,
+                       {
+                               VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,             // VkStructureType                                      sType;
+                               DE_NULL,                                                                                // const void*                                          pNext;
+                               (VkDeviceQueueCreateFlags)0u,                                   // VkDeviceQueueCreateFlags                     flags;
+                               transferQueueFamilyIndex,                                               // uint32_t                                                     queueFamilyIndex;
+                               1u,                                                                                             // uint32_t                                                     queueCount;
+                               &queuePriorities                                                                // const float*                                         pQueuePriorities;
+                       });
+               queueInfo[1].queueFamilyIndex = graphicsQueueFamilyIndex;
+               VkPhysicalDeviceFeatures deviceFeatures;
+               vki.getPhysicalDeviceFeatures(pd, &deviceFeatures);
+               VkPhysicalDeviceFragmentShadingRateFeaturesKHR  fsrFeatures                             { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR, DE_NULL, DE_FALSE, DE_FALSE, DE_TRUE };
+               VkPhysicalDeviceImagelessFramebufferFeaturesKHR ifbFeatures                             { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES, DE_NULL, DE_TRUE };
+               VkPhysicalDeviceFeatures2                                               createPhysicalFeature   { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, &fsrFeatures, deviceFeatures };
+               std::vector<const char*> enabledExtensions = { "VK_KHR_fragment_shading_rate" };
+               if (m_params->useImagelessFramebuffer)
+               {
+                       enabledExtensions.push_back("VK_KHR_imageless_framebuffer");
+                       fsrFeatures.pNext = &ifbFeatures;
+               }
+               std::vector<const char*> enabledLayers = getValidationLayers(vki, pd);
+               VkDeviceCreateInfo deviceInfo
+               {
+                       VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,                           // VkStructureType                                      sType;
+                       &createPhysicalFeature,                                                         // const void*                                          pNext;
+                       (VkDeviceCreateFlags)0u,                                                        // VkDeviceCreateFlags                          flags;
+                       2u,                                                                                                     // uint32_t                                                     queueCreateInfoCount;
+                       queueInfo.data(),                                                                       // const VkDeviceQueueCreateInfo*       pQueueCreateInfos;
+                       static_cast<deUint32>(enabledLayers.size()),            // uint32_t                                                     enabledLayerCount;
+                       de::dataOrNull(enabledLayers),                                          // const char* const*                           ppEnabledLayerNames;
+                       static_cast<deUint32>(enabledExtensions.size()),        // uint32_t                                                     enabledExtensionCount;
+                       enabledExtensions.data(),                                                       // const char* const*                           ppEnabledExtensionNames;
+                       DE_NULL                                                                                         // const VkPhysicalDeviceFeatures*      pEnabledFeatures;
+               };
+               m_device                = createDevice(vkp, m_context.getInstance(), vki, pd, &deviceInfo);
+               m_allocator             = de::MovePtr<Allocator>(new SimpleAllocator(m_context.getDeviceInterface(), *m_device, getPhysicalDeviceMemoryProperties(vki, pd)));
+       }
+       VkQueue transferQueue;
+       vk.getDeviceQueue(*m_device, transferQueueFamilyIndex, 0u, &transferQueue);
+       VkQueue graphicsQueue;
+       vk.getDeviceQueue(*m_device, graphicsQueueFamilyIndex, 0u, &graphicsQueue);
+       // create transfer and graphics command buffers
+       Move<VkCommandPool>             transferCmdPool         = createCommandPool(vk, *m_device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, transferQueueFamilyIndex);
+       Move<VkCommandBuffer>   transferCmdBuffer       = allocateCommandBuffer(vk, *m_device, *transferCmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
+       Move<VkCommandPool>             graphicsCmdPool         = createCommandPool(vk, *m_device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, graphicsQueueFamilyIndex);
+       Move<VkCommandBuffer>   graphicsCmdBuffer       = allocateCommandBuffer(vk, *m_device, *graphicsCmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
+       Move<VkShaderModule>    vertShader                      = createShaderModule(vk, *m_device, m_context.getBinaryCollection().get("vert"), 0);
+       Move<VkShaderModule>    fragShader                      = createShaderModule(vk, *m_device, m_context.getBinaryCollection().get("frag"), 0);
+       buildColorBufferObjects(0, m_cbUsage);
+       buildCounterBufferObjects();
+       // iterate over all possible tile sizes
+       for (deUint32 tileWidth  = m_minTileSize.width;  tileWidth  <= m_maxTileSize.width;  tileWidth  *= 2)
+       for (deUint32 tileHeight = m_minTileSize.height; tileHeight <= m_maxTileSize.height; tileHeight *= 2)
+       {
+               // skip tile sizes that have unsuported aspect ratio
+               deUint32 aspectRatio = (tileHeight > tileWidth) ? (tileHeight / tileWidth) : (tileWidth / tileHeight);
+               if (aspectRatio > m_maxAspectRatio)
+                       continue;
+               // calculate size of shading rate attachment
+               deUint32 srWidth  = (m_cbWidth  + tileWidth  - 1) / tileWidth;
+               deUint32 srHeight = (m_cbHeight + tileHeight - 1) / tileHeight;
+               // create image that will be source for shading rate image
+               de::MovePtr<ImageWithMemory> srSrcImage = buildImageWithMemory(m_params->srFormat, srWidth, srHeight,
+                                                                                                                                          VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
+               // create buffer that will contain shading rate source data
+               tcu::TextureFormat                              srTextureFormat         = mapVkFormat(m_params->srFormat);
+               deUint32                                                srWriteBufferSize       = srWidth * srHeight * getNumUsedChannels(srTextureFormat.order) * getChannelSize(srTextureFormat.type);
+               de::MovePtr<BufferWithMemory>   srSrcBuffer                     = buildBufferWithMemory(srWriteBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
+               // fill buffer with tested shading rate
+               deUint8*        srWriteBufferHostPtr    = (deUint8*)srSrcBuffer->getAllocation().getHostPtr();
+               deUint8         value                                   = (deUint8)calculateRate(m_params->srRate.width, m_params->srRate.height);
+               deMemset(srWriteBufferHostPtr, value, (size_t)srWriteBufferSize);
+               flushAlloc(vk, *m_device, srSrcBuffer->getAllocation());
+               // create shading rate iamge
+               m_srImage[0]            = buildImageWithMemory(m_params->srFormat, srWidth, srHeight,
+                                                                                                  VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
+                                                                                                  VK_IMAGE_TILING_OPTIMAL, queueFamilies);
+               m_srImageView[0]        = buildImageView(m_params->srFormat, m_srImage[0]->get());
+               Move<VkPipelineLayout>  graphicsPipelineLayout  = buildPipelineLayout(&(*m_counterBufferDescriptorSetLayout));
+               Move<VkRenderPass>              renderPass                              = buildRenderPass(m_cbFormat, tileWidth, tileHeight);
+               Move<VkPipeline>                graphicsPipeline                = buildGraphicsPipeline(0, *renderPass, *graphicsPipelineLayout, *vertShader, *fragShader);
+               std::vector<FBAttachmentInfo> attachmentInfo
+               {
+                       { m_cbFormat,                   m_cbUsage, m_cbWidth, m_cbHeight, *m_cbImageView[0] },
+                       { m_params->srFormat,   m_srUsage, srWidth,   srHeight,   *m_srImageView[0] }
+               };
+               Move<VkFramebuffer> framebuffer = buildFramebuffer(*renderPass, attachmentInfo);
+               beginCommandBuffer(vk, *transferCmdBuffer, 0u);
+               // wait till sr data is ready in buffer and change sr image layouts to general
+               VkPipelineStageFlags srcStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
+               VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
+               memoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+               memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
+               std::vector<VkImageMemoryBarrier> srImageBarrierGeneral(2,
+                       makeImageMemoryBarrier(
+                               VK_ACCESS_NONE_KHR,
+                               VK_ACCESS_NONE_KHR,
+                               VK_IMAGE_LAYOUT_UNDEFINED,
+                               VK_IMAGE_LAYOUT_GENERAL,
+                               **m_srImage[0],
+                               m_defaultImageSubresourceRange));
+               srImageBarrierGeneral[1].image = **srSrcImage;
+               vk.cmdPipelineBarrier(*transferCmdBuffer, srcStageMask, dstStageMask, 0, 1, &memoryBarrier, 0, DE_NULL, 2, srImageBarrierGeneral.data());
+               // copy sr data to images
+               const VkBufferImageCopy srCopyBuffer = makeBufferImageCopy({ srWidth, srHeight, 1u }, m_defaultImageSubresourceLayers);
+               vk.cmdCopyBufferToImage(*transferCmdBuffer, **srSrcBuffer, **srSrcImage, VK_IMAGE_LAYOUT_GENERAL, 1, &srCopyBuffer);
+               // wait till sr source image is ready
+               srcStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
+               dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
+               memoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+               memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
+               vk.cmdPipelineBarrier(*transferCmdBuffer, srcStageMask, dstStageMask, 0, 1, &memoryBarrier, 0, DE_NULL, 0, DE_NULL);
+               // copy sr source image to sr image used during rendering
+               VkImageCopy imageCopyRegion
+               {
+                       m_defaultImageSubresourceLayers,        // VkImageSubresourceLayers     srcSubresource;
+                       {0, 0, 0},                                                      // VkOffset3D                           srcOffset;
+                       m_defaultImageSubresourceLayers,        // VkImageSubresourceLayers     dstSubresource;
+                       {0, 0, 0},                                                      // VkOffset3D                           dstOffset;
+                       { srWidth, srHeight, 1u }                       // VkExtent3D                           extent;
+               };
+               vk.cmdCopyImage(*transferCmdBuffer, **srSrcImage, VK_IMAGE_LAYOUT_GENERAL, **m_srImage[0], VK_IMAGE_LAYOUT_GENERAL, 1, &imageCopyRegion);
+               // release exclusive ownership from the transfer queue family
+               srcStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
+               dstStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
+               VkImageMemoryBarrier srImageBarrierOwnershipTransfer =
+                       makeImageMemoryBarrier(
+                               VK_ACCESS_TRANSFER_WRITE_BIT,
+                               VK_ACCESS_NONE_KHR,
+                               VK_IMAGE_LAYOUT_GENERAL,
+                               VK_IMAGE_LAYOUT_GENERAL,
+                               **m_srImage[0], m_defaultImageSubresourceRange);
+               if (m_params->mode == TM_SETUP_RATE_WITH_COPYING_FROM_EXCLUSIVE_IMAGE_USING_TRANSFER_QUEUE)
+               {
+                       srImageBarrierOwnershipTransfer.srcQueueFamilyIndex = transferQueueFamilyIndex;
+                       srImageBarrierOwnershipTransfer.dstQueueFamilyIndex = graphicsQueueFamilyIndex;
+               }
+               vk.cmdPipelineBarrier(*transferCmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1, &srImageBarrierOwnershipTransfer);
+               endCommandBuffer(vk, *transferCmdBuffer);
+               beginCommandBuffer(vk, *graphicsCmdBuffer, 0u);
+               // acquire exclusive ownership for the graphics queue family - while changing sr images layout
+               vk.cmdPipelineBarrier(*graphicsCmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1, &srImageBarrierOwnershipTransfer);
+               // wait till sr image layout is changed
+               srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
+               dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
+               VkImageMemoryBarrier srImageBarrierShadingRate =
+                       makeImageMemoryBarrier(
+                               VK_ACCESS_NONE_KHR,
+                               VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR,
+                               VK_IMAGE_LAYOUT_GENERAL,
+                               VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR,
+                               **m_srImage[0],
+                               m_defaultImageSubresourceRange);
+               vk.cmdPipelineBarrier(*graphicsCmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1, &srImageBarrierShadingRate);
+               // wait till cb image layout is changed
+               srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
+               dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+               VkImageMemoryBarrier cbImageBarrier =
+                       makeImageMemoryBarrier(
+                               VK_ACCESS_NONE_KHR,
+                               VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
+                               VK_IMAGE_LAYOUT_UNDEFINED,
+                               VK_IMAGE_LAYOUT_GENERAL,
+                               **m_cbImage[0],
+                               m_defaultImageSubresourceRange);
+               vk.cmdPipelineBarrier(*graphicsCmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1, &cbImageBarrier);
+               startRendering(*graphicsCmdBuffer, *renderPass, *framebuffer, makeRect2D(m_cbWidth, m_cbHeight), attachmentInfo);
+               // draw single triangle to cb
+               vk.cmdBindDescriptorSets(*graphicsCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipelineLayout, 0, 1, &(*m_counterBufferDescriptorSet), 0, DE_NULL);
+               vk.cmdBindPipeline(*graphicsCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
+               vk.cmdDraw(*graphicsCmdBuffer, 3u, 1, 0u, 0u);
+               finishRendering(*graphicsCmdBuffer);
+               // wait till color attachment is fully written
+               srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+               dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
+               memoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+               memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
+               vk.cmdPipelineBarrier(*graphicsCmdBuffer, srcStageMask, dstStageMask, 0, 1, &memoryBarrier, 0, DE_NULL, 0, DE_NULL);
+               // read back color buffer image
+               vk.cmdCopyImageToBuffer(*graphicsCmdBuffer, **m_cbImage[0], VK_IMAGE_LAYOUT_GENERAL, **m_cbReadBuffer[0], 1u, &m_defaultBufferImageCopy);
+               endCommandBuffer(vk, *graphicsCmdBuffer);
+               // create synchronization objects
+               Move<VkSemaphore>       semaphore               = createSemaphore(vk, *m_device);
+               Move<VkFence>           transferFence   = createFence(vk, *m_device);
+               Move<VkFence>           graphicsFence   = createFence(vk, *m_device);
+               const VkSubmitInfo transferSubmitInfo
+               {
+                       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;
+                       &*transferCmdBuffer,                                                            // const VkCommandBuffer*               pCommandBuffers;
+                       1u,                                                                                                     // deUint32                                             signalSemaphoreCount;
+                       &*semaphore,                                                                            // const VkSemaphore*                   pSignalSemaphores;
+               };
+               const VkPipelineStageFlags waitDstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
+               const VkSubmitInfo graphicsSubmitInfo
+               {
+                       VK_STRUCTURE_TYPE_SUBMIT_INFO,                                          // VkStructureType                              sType;
+                       DE_NULL,                                                                                        // const void*                                  pNext;
+                       1u,                                                                                                     // deUint32                                             waitSemaphoreCount;
+                       &*semaphore,                                                                            // const VkSemaphore*                   pWaitSemaphores;
+                       &waitDstStageMask,                                                                      // const VkPipelineStageFlags*  pWaitDstStageMask;
+                       1u,                                                                                                     // deUint32                                             commandBufferCount;
+                       &*graphicsCmdBuffer,                                                            // const VkCommandBuffer*               pCommandBuffers;
+                       0u,                                                                                                     // deUint32                                             signalSemaphoreCount;
+                       DE_NULL,                                                                                        // const VkSemaphore*                   pSignalSemaphores;
+               };
+               // submit commands to both queues
+               VK_CHECK(vk.queueSubmit(transferQueue, 1u, &transferSubmitInfo, *transferFence));
+               VK_CHECK(vk.queueSubmit(graphicsQueue, 1u, &graphicsSubmitInfo, *graphicsFence));
+               VkFence fences[] = { *graphicsFence, *transferFence };
+               VK_CHECK(vk.waitForFences(*m_device, 2u, fences, DE_TRUE, ~0ull));
+               invalidateAlloc(vk, *m_device, m_cbReadBuffer[0]->getAllocation());
+               if (!verifyUsingAtomicChecks(tileWidth, tileHeight,
+                                                                        m_params->srRate.width, m_params->srRate.height,
+                                                                        (deUint32*)m_cbReadBuffer[0]->getAllocation().getHostPtr()))
+                       return false;
+       } // iterate over all possible tile sizes
+       return true;
+ }
+ bool AttachmentRateInstance::runFillLinearTiledImage(void)
+ {
+       // Create a linear tiled fragment shading rate attachment image and set
+       // its data on the host, then draw a basic triangle and do basic checks
+       const DeviceInterface&  vk                                      = m_context.getDeviceInterface();
+       VkDevice                                device                          = m_context.getDevice();
+       deUint32                                queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
+       VkImageSubresource              imageSubresource        = makeImageSubresource(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u);
+       VkMemoryBarrier                 memoryBarrier           { VK_STRUCTURE_TYPE_MEMORY_BARRIER, DE_NULL, 0u, 0u };
+       VkSubresourceLayout             srImageLayout;
+       Move<VkShaderModule>    vertShader                      = createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0);
+       Move<VkShaderModule>    fragShader                      = createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0);
+       Move<VkCommandPool>             cmdPool                         = createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
+       Move<VkCommandBuffer>   cmdBuffer                       = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
+       buildCounterBufferObjects();
+       buildColorBufferObjects(0, m_cbUsage);
+       // iterate over all possible tile sizes
+       for (deUint32 tileWidth  = m_minTileSize.width;  tileWidth  <= m_maxTileSize.width;  tileWidth  *= 2)
+       for (deUint32 tileHeight = m_minTileSize.height; tileHeight <= m_maxTileSize.height; tileHeight *= 2)
+       {
+               // skip tile sizes that have unsuported aspect ratio
+               deUint32 aspectRatio = (tileHeight > tileWidth) ? (tileHeight / tileWidth) : (tileWidth / tileHeight);
+               if (aspectRatio > m_maxAspectRatio)
+                       continue;
+               // calculate size of shading rate attachment
+               deUint32 srWidth  = (m_cbWidth  + tileWidth  - 1) / tileWidth;
+               deUint32 srHeight = (m_cbHeight + tileHeight - 1) / tileHeight;
+               buildShadingRateObjects(0, srWidth, srHeight, m_srUsage, VK_IMAGE_TILING_LINEAR);
+               deUint8*        imagePtr        = reinterpret_cast<deUint8*>(m_srImage[0]->getAllocation().getHostPtr());
+               deUint8         value           = (deUint8)calculateRate(m_params->srRate.width, m_params->srRate.height);
+               // fill sr image on the host row by row
+               vk.getImageSubresourceLayout(device, **m_srImage[0], &imageSubresource, &srImageLayout);
+               for (deUint32 srTexelRow = 0; srTexelRow < srHeight; srTexelRow++)
+               {
+                       deUint8* rowDst = imagePtr + srImageLayout.offset + srImageLayout.rowPitch * srTexelRow;
+                       deMemset(rowDst, value, (size_t)srWidth);
+               }
+               Move<VkPipelineLayout>  graphicsPipelineLayout  = buildPipelineLayout(&(*m_counterBufferDescriptorSetLayout));
+               Move<VkRenderPass>              renderPass                              = buildRenderPass(m_cbFormat, tileWidth, tileHeight);
+               Move<VkPipeline>                graphicsPipeline                = buildGraphicsPipeline(0, *renderPass, *graphicsPipelineLayout, *vertShader, *fragShader);
+               std::vector<FBAttachmentInfo> attachmentInfo
+               {
+                       { m_cbFormat,                   m_cbUsage, m_cbWidth, m_cbHeight, *m_cbImageView[0] },
+                       { m_params->srFormat,   m_srUsage, srWidth,   srHeight,   *m_srImageView[0] }
+               };
+               Move<VkFramebuffer> framebuffer = buildFramebuffer(*renderPass, attachmentInfo);
+               beginCommandBuffer(vk, *cmdBuffer, 0u);
+               // wait till sr image layout is changed
+               VkPipelineStageFlags srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
+               VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
+               VkImageMemoryBarrier srImageBarrierAttachment =
+                       makeImageMemoryBarrier(
+                               VK_ACCESS_NONE_KHR,
+                               VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR,
+                               VK_IMAGE_LAYOUT_UNDEFINED,
+                               VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR,
+                               **m_srImage[0],
+                               m_defaultImageSubresourceRange);
+               vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1, &srImageBarrierAttachment);
+               // wait till cb image layout is changed
+               srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
+               dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+               VkImageMemoryBarrier cbImageBarrier =
+                       makeImageMemoryBarrier(
+                               VK_ACCESS_NONE_KHR,
+                               VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
+                               VK_IMAGE_LAYOUT_UNDEFINED,
+                               VK_IMAGE_LAYOUT_GENERAL,
+                               **m_cbImage[0],
+                               m_defaultImageSubresourceRange);
+               vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1, &cbImageBarrier);
+               startRendering(*cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_cbWidth, m_cbHeight), attachmentInfo);
+               // draw single triangle to cb
+               vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipelineLayout, 0, 1, &(*m_counterBufferDescriptorSet), 0, DE_NULL);
+               vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
+               vk.cmdDraw(*cmdBuffer, 3u, 1, 0u, 0u);
+               finishRendering(*cmdBuffer);
+               // wait till color attachment is fully written
+               srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+               dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
+               memoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+               memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
+               vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 1, &memoryBarrier, 0, DE_NULL, 0, DE_NULL);
+               // read back color buffer image
+               vk.cmdCopyImageToBuffer(*cmdBuffer, **m_cbImage[0], VK_IMAGE_LAYOUT_GENERAL, **m_cbReadBuffer[0], 1u, &m_defaultBufferImageCopy);
+               endCommandBuffer(vk, *cmdBuffer);
+               // submit commands and wait
+               const VkQueue queue = m_context.getUniversalQueue();
+               submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
+               invalidateAlloc(vk, device, m_cbReadBuffer[0]->getAllocation());
+               if (!verifyUsingAtomicChecks(tileWidth, tileHeight,
+                                                                        m_params->srRate.width, m_params->srRate.height,
+                                                                        (deUint32*)m_cbReadBuffer[0]->getAllocation().getHostPtr()))
+                       return false;
+       } // iterate over all possible tile sizes
+       return true;
+ }
+ bool AttachmentRateInstance::runTwoSubpassMode(void)
+ {
+       // Set up a two-subpass render pass with different shading rate attachments used in each subpass.
+       // Then draw a basic triangle in each subpass and do basic checks.
+       const InstanceInterface&        vki                                     = m_context.getInstanceInterface();
+       const DeviceInterface&          vk                                      = m_context.getDeviceInterface();
+       VkPhysicalDevice                        pd                                      = m_context.getPhysicalDevice();
+       VkDevice                                        device                          = m_context.getDevice();
+       deUint32                                        queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
+       VkMemoryBarrier                         memoryBarrier           { VK_STRUCTURE_TYPE_MEMORY_BARRIER, DE_NULL, 0u, 0u };
+       Move<VkShaderModule>            vertShader0                     = createShaderModule(vk, device, m_context.getBinaryCollection().get("vert0"), 0);
+       Move<VkShaderModule>            vertShader1                     = createShaderModule(vk, device, m_context.getBinaryCollection().get("vert1"), 0);
+       Move<VkShaderModule>            fragShader                      = createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0);
+       Move<VkCommandPool>                     cmdPool                         = createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
+       Move<VkCommandBuffer>           cmdBuffer                       = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
+       // fetch information about supported rates
+       deUint32 supportedFragmentShadingRateCount;
+       std::vector<VkPhysicalDeviceFragmentShadingRateKHR> supportedFragmentShadingRates;
+       vki.getPhysicalDeviceFragmentShadingRatesKHR(pd, &supportedFragmentShadingRateCount, DE_NULL);
+       supportedFragmentShadingRates.resize(supportedFragmentShadingRateCount, {
+               VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_KHR,                            // VkStructureType              sType;
+               DE_NULL,                                                                                                                                        // void*                                pNext;
+               VK_SAMPLE_COUNT_1_BIT,                                                                                                          // VkSampleCountFlags   sampleCounts;
+               { 0, 0 }                                                                                                                                        // VkExtent2D                   fragmentSize;
+               });
+       vki.getPhysicalDeviceFragmentShadingRatesKHR(pd, &supportedFragmentShadingRateCount, &supportedFragmentShadingRates[0]);
+       // grab min and max tile sieze and biggest and smallest rate
+       deUint32 sr0Width               = (m_cbWidth + m_minTileSize.width - 1) / m_minTileSize.width;
+       deUint32 sr0Height              = (m_cbHeight + m_minTileSize.height - 1) / m_minTileSize.height;
+       deUint32 sr1Width               = (m_cbWidth + m_maxTileSize.width - 1) / m_maxTileSize.width;
+       deUint32 sr1Height              = (m_cbHeight + m_maxTileSize.height - 1) / m_maxTileSize.height;
+       deUint32 sr0RateWidth   = supportedFragmentShadingRates[0].fragmentSize.width;                                                                          // bigets supported rate
+       deUint32 sr0RateHeight  = supportedFragmentShadingRates[0].fragmentSize.height;
+       deUint32 sr1RateWidth   = supportedFragmentShadingRates[supportedFragmentShadingRateCount - 2].fragmentSize.width;      // smallest supported rate excluding {1, 1}
+       deUint32 sr1RateHeight  = supportedFragmentShadingRates[supportedFragmentShadingRateCount - 2].fragmentSize.height;
+       buildColorBufferObjects(0, m_cbUsage);
+       buildColorBufferObjects(1, m_cbUsage);
+       buildShadingRateObjects(0, sr0Width, sr0Height, m_srUsage);
+       buildShadingRateObjects(1, sr1Width, sr1Height, m_srUsage);
+       buildCounterBufferObjects();
+       Move<VkRenderPass>              renderPass                      = buildRenderPass(m_cbFormat, m_minTileSize.width, m_minTileSize.height, m_maxTileSize.width, m_maxTileSize.height);
+       Move<VkPipelineLayout>  pipelineLayout          = buildPipelineLayout(&(*m_counterBufferDescriptorSetLayout));
+       Move<VkPipeline>                graphicsPipeline0       = buildGraphicsPipeline(0, *renderPass, *pipelineLayout, *vertShader0, *fragShader);
+       Move<VkPipeline>                graphicsPipeline1       = buildGraphicsPipeline(1, *renderPass, *pipelineLayout, *vertShader1, *fragShader);
+       std::vector<FBAttachmentInfo> attachmentInfo
+       {
+               { m_cbFormat,                   m_cbUsage, m_cbWidth, m_cbHeight, *m_cbImageView[0] },
+               { m_params->srFormat,   m_srUsage, sr0Width,  sr0Height,  *m_srImageView[0] },
+               { m_cbFormat,                   m_cbUsage, m_cbWidth, m_cbHeight, *m_cbImageView[1] },
+               { m_params->srFormat,   m_srUsage, sr1Width,  sr1Height,  *m_srImageView[1] }
+       };
+       Move<VkFramebuffer> framebuffer = buildFramebuffer(*renderPass, attachmentInfo);
+       beginCommandBuffer(vk, *cmdBuffer, 0u);
+       // change sr image layouts to general
+       VkPipelineStageFlags srcStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
+       VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
+       std::vector<VkImageMemoryBarrier> srImageBarrierGeneral(2,
+               makeImageMemoryBarrier(
+                       VK_ACCESS_NONE_KHR,
+                       VK_ACCESS_NONE_KHR,
+                       VK_IMAGE_LAYOUT_UNDEFINED,
+                       VK_IMAGE_LAYOUT_GENERAL,
+                       **m_srImage[0],
+                       m_defaultImageSubresourceRange));
+       srImageBarrierGeneral[1].image = **m_srImage[1];
+       vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 2, srImageBarrierGeneral.data());
+       VkClearColorValue clearValues[2] = { { { 0, 0, 0, 0 } }, { { 0, 0, 0, 0 } } };
+       clearValues[0].uint32[0] = calculateRate(sr0RateWidth, sr0RateHeight);
+       clearValues[1].uint32[0] = calculateRate(sr1RateWidth, sr1RateHeight);
+       vk.cmdClearColorImage(*cmdBuffer, **m_srImage[0], VK_IMAGE_LAYOUT_GENERAL, &clearValues[0], 1, &m_defaultImageSubresourceRange);
+       vk.cmdClearColorImage(*cmdBuffer, **m_srImage[1], VK_IMAGE_LAYOUT_GENERAL, &clearValues[1], 1, &m_defaultImageSubresourceRange);
+       // wait till sr data is ready and change sr images layout
+       srcStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
+       dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
+       memoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+       memoryBarrier.dstAccessMask = VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR;
+       std::vector<VkImageMemoryBarrier> srImageBarrierShadingRate(2,
+               makeImageMemoryBarrier(
+                       VK_ACCESS_TRANSFER_WRITE_BIT,
+                       VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR,
+                       VK_IMAGE_LAYOUT_GENERAL,
+                       VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR,
+                       **m_srImage[0],
+                       m_defaultImageSubresourceRange));
+       srImageBarrierShadingRate[1].image = **m_srImage[1];
+       vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 1, &memoryBarrier, 0, DE_NULL, 2, srImageBarrierShadingRate.data());
+       // wait till cb image layouts are changed
+       srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
+       dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+       std::vector<VkImageMemoryBarrier> cbImageBarrier(2,
+               makeImageMemoryBarrier(
+                       VK_ACCESS_NONE_KHR,
+                       VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
+                       VK_IMAGE_LAYOUT_UNDEFINED,
+                       VK_IMAGE_LAYOUT_GENERAL,
+                       **m_cbImage[0],
+                       m_defaultImageSubresourceRange));
+       cbImageBarrier[1].image = **m_cbImage[1];
+       vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 2, cbImageBarrier.data());
+       startRendering(*cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_cbWidth, m_cbHeight), attachmentInfo);
+       // draw single triangle to first cb
+       vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0, 1, &(*m_counterBufferDescriptorSet), 0, DE_NULL);
+       vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline0);
+       vk.cmdDraw(*cmdBuffer, 3u, 1, 0u, 0u);
+       vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
+       // draw single triangle to second cb
+       vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline1);
+       vk.cmdDraw(*cmdBuffer, 3u, 1, 0u, 0u);
+       finishRendering(*cmdBuffer);
+       // wait till color attachments are fully written
+       srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+       dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
+       memoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+       memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
+       vk.cmdPipelineBarrier(*cmdBuffer, srcStageMask, dstStageMask, 0, 1, &memoryBarrier, 0, DE_NULL, 0, DE_NULL);
+       // read back color buffer images
+       vk.cmdCopyImageToBuffer(*cmdBuffer, **m_cbImage[0], VK_IMAGE_LAYOUT_GENERAL, **m_cbReadBuffer[0], 1u, &m_defaultBufferImageCopy);
+       vk.cmdCopyImageToBuffer(*cmdBuffer, **m_cbImage[1], VK_IMAGE_LAYOUT_GENERAL, **m_cbReadBuffer[1], 1u, &m_defaultBufferImageCopy);
+       endCommandBuffer(vk, *cmdBuffer);
+       // submit commands and wait
+       const VkQueue queue = m_context.getUniversalQueue();
+       submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
+       // read back buffer with color attachment 1 data
+       Allocation& cb0BuffAlloc = m_cbReadBuffer[0]->getAllocation();
+       invalidateAlloc(vk, device, cb0BuffAlloc);
+       // read back buffer with color attachment 2 data
+       Allocation& cb1BuffAlloc = m_cbReadBuffer[1]->getAllocation();
+       invalidateAlloc(vk, device, cb1BuffAlloc);
+       // validate both attachemtns triangle
+       return (verifyUsingAtomicChecks(m_minTileSize.width, m_minTileSize.height,
+                                                                       sr0RateWidth, sr0RateHeight,
+                                                                       (deUint32*)m_cbReadBuffer[0]->getAllocation().getHostPtr()) &&
+                       verifyUsingAtomicChecks(m_maxTileSize.width, m_maxTileSize.height,
+                                                                       sr1RateWidth, sr1RateHeight,
+                                                                       (deUint32*)m_cbReadBuffer[1]->getAllocation().getHostPtr()));
+ }
+ class AttachmentRateTestCase : public TestCase
+ {
+ public:
+                                       AttachmentRateTestCase  (tcu::TestContext& context, const char* name, de::SharedPtr<TestParams> params);
+                                       ~AttachmentRateTestCase (void) = default;
+       void                    initPrograms                    (SourceCollections& programCollection) const override;
+       TestInstance*   createInstance                  (Context& context) const override;
+       void                    checkSupport                    (Context& context) const override;
+ private:
+       const de::SharedPtr<TestParams> m_params;
+ };
+ AttachmentRateTestCase::AttachmentRateTestCase(tcu::TestContext& context, const char* name, de::SharedPtr<TestParams> params)
+       : vkt::TestCase (context, name, "")
+       , m_params              (params)
+ {
+ }
+ void AttachmentRateTestCase::checkSupport(Context& context) const
+ {
+       context.requireDeviceFunctionality("VK_KHR_fragment_shading_rate");
+       if (m_params->useDynamicRendering)
+               context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
+       if (m_params->useImagelessFramebuffer)
+               context.requireDeviceFunctionality("VK_KHR_imageless_framebuffer");
+       if (!context.getFragmentShadingRateFeatures().attachmentFragmentShadingRate)
+               TCU_THROW(NotSupportedError, "pipelineFragmentShadingRate not supported");
+       const vk::InstanceInterface&    vk                                      = context.getInstanceInterface();
+       const vk::VkPhysicalDevice              pd                                      = context.getPhysicalDevice();
+       VkImageFormatProperties                 imageProperties;
+       VkImageUsageFlags                               srUsage                         = VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR |
+                                                                                                                 VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+       VkResult result = vk.getPhysicalDeviceImageFormatProperties(pd, m_params->srFormat, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, srUsage, 0, &imageProperties);
+       if (result == VK_ERROR_FORMAT_NOT_SUPPORTED)
+               TCU_THROW(NotSupportedError, "Format not supported");
+       if (m_params->mode != TM_TWO_SUBPASS)
+       {
+               deUint32                                                                                                supportedFragmentShadingRateCount;
+               VkExtent2D                                                                                              testedRate = m_params->srRate;
+               std::vector<VkPhysicalDeviceFragmentShadingRateKHR>             supportedFragmentShadingRates;
+               // fetch information about supported rates
+               vk.getPhysicalDeviceFragmentShadingRatesKHR(pd, &supportedFragmentShadingRateCount, DE_NULL);
+               supportedFragmentShadingRates.resize(supportedFragmentShadingRateCount, {
+                       VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_KHR,                            // VkStructureType              sType;
+                       DE_NULL,                                                                                                                                        // void*                                pNext;
+                       VK_SAMPLE_COUNT_1_BIT,                                                                                                          // VkSampleCountFlags   sampleCounts;
+                       { 0, 0 }                                                                                                                                        // VkExtent2D                   fragmentSize;
+                       });
+               vk.getPhysicalDeviceFragmentShadingRatesKHR(pd, &supportedFragmentShadingRateCount, &supportedFragmentShadingRates[0]);
+               // check if rate required by test is not supported
+               if (std::none_of(supportedFragmentShadingRates.begin(), supportedFragmentShadingRates.end(),
+                       [&testedRate](const VkPhysicalDeviceFragmentShadingRateKHR& r)
+                       { return (r.fragmentSize.width == testedRate.width && r.fragmentSize.height == testedRate.height); }))
+               {
+                       TCU_THROW(NotSupportedError, "Rate not supported");
+               }
+       }
+       VkFormatFeatureFlags requiredFeatures = 0;
+       if (m_params->mode == TM_SETUP_RATE_WITH_ATOMICS_IN_COMPUTE_SHADER)
+               requiredFeatures = VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR | VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT;
+       else if ((m_params->mode == TM_SETUP_RATE_WITH_COPYING_FROM_OTHER_IMAGE) ||
+                        (m_params->mode == TM_SETUP_RATE_WITH_COPYING_FROM_EXCLUSIVE_IMAGE_USING_TRANSFER_QUEUE) ||
+                        (m_params->mode == TM_SETUP_RATE_WITH_COPYING_FROM_CONCURENT_IMAGE_USING_TRANSFER_QUEUE) ||
+                        (m_params->mode == TM_SETUP_RATE_WITH_LINEAR_TILED_IMAGE))
+               requiredFeatures = VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR;
+       else if (m_params->mode == TM_SETUP_RATE_WITH_FRAGMENT_SHADER)
+               requiredFeatures = VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
+ #if DEBUG_USE_STORE_INSTEAD_OF_ATOMICS == 1
+       if (m_params->mode == TM_SETUP_RATE_WITH_ATOMICS_IN_COMPUTE_SHADER)
+               requiredFeatures = VK_FORMAT_FEATURE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
+ #endif
+       if (requiredFeatures)
+       {
+               const VkFormatProperties formatProperties = getPhysicalDeviceFormatProperties(vk, pd, m_params->srFormat);
+               if (m_params->mode == TM_SETUP_RATE_WITH_LINEAR_TILED_IMAGE)
+               {
+                       if ((formatProperties.linearTilingFeatures & requiredFeatures) != requiredFeatures)
+                               TCU_THROW(NotSupportedError, "Required format feature bits not supported");
+               }
+               else if ((formatProperties.optimalTilingFeatures & requiredFeatures) != requiredFeatures)
+                       TCU_THROW(NotSupportedError, "Required format feature bits not supported");
+       }
+ }
+ void AttachmentRateTestCase::initPrograms(SourceCollections& programCollection) const
+ {
+       deUint32 rateValue = calculateRate(m_params->srRate.width, m_params->srRate.height);
+       if (m_params->mode == TM_SETUP_RATE_WITH_ATOMICS_IN_COMPUTE_SHADER)
+       {
+               std::stringstream compStream;
+               compStream <<
+                       "#version 450\n"
+                       "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
+                       "layout(r32ui, binding = 0) coherent uniform highp uimage2D srImage;\n"
+                       "void main (void)\n"
+                       "{\n"
+ #if DEBUG_USE_STORE_INSTEAD_OF_ATOMICS == 1
+                       "  imageStore(srImage, ivec2(gl_GlobalInvocationID.xy), uvec4(" << rateValue << "));\n"
+ #else
+                       "  imageAtomicAdd(srImage, ivec2(gl_GlobalInvocationID.xy), " << rateValue << ");\n"
+ #endif
+                       "}\n";
+               programCollection.glslSources.add("comp") << glu::ComputeSource(compStream.str());
+       }
+       tcu::StringTemplate vertTemplate(
+               "#version 450 core\n"
+               "out gl_PerVertex\n"
+               "{\n"
+               "  vec4 gl_Position;\n"
+               "};\n"
+               "void main()\n"
+               "{\n"
+               "  gl_Position = vec4(float(1.0 - 2.0 * int(gl_VertexIndex != 1)) * ${SCALE} + ${TRANSLATE},\n"
+               "                     float(1.0 - 2.0 * int(gl_VertexIndex > 0))  * ${SCALE} + ${TRANSLATE}, 0.0, 1.0);\n"
+               "}\n");
+       std::map<std::string, std::string> specializationMap
+       {
+               {"SCALE",               "0.8" },
+               {"TRANSLATE",   "0.0" },
+       };
+       if (m_params->mode == TM_TWO_SUBPASS)
+       {
+               specializationMap["SCALE"]              =  "0.4";
+               specializationMap["TRANSLATE"]  = "-0.5";
+               programCollection.glslSources.add("vert0") << glu::VertexSource(vertTemplate.specialize(specializationMap));
+               specializationMap["SCALE"]              = "0.4";
+               specializationMap["TRANSLATE"]  = "0.5";
+               programCollection.glslSources.add("vert1") << glu::VertexSource(vertTemplate.specialize(specializationMap));
+       }
+       else
+       {
+               programCollection.glslSources.add("vert") << glu::VertexSource(vertTemplate.specialize(specializationMap));
+       }
+       if (m_params->mode == TM_SETUP_RATE_WITH_FRAGMENT_SHADER)
+       {
+               // use large triangle that will cover whole color buffer
+               specializationMap["SCALE"]              = "9.0";
+               specializationMap["TRANSLATE"]  = "0.0";
+               programCollection.glslSources.add("vert_setup") << glu::VertexSource(vertTemplate.specialize(specializationMap));
+               std::stringstream fragStream;
+               fragStream <<
+                       "#version 450 core\n"
+                       "layout(location = 0) out uint outColor;\n"
+                       "void main()\n"
+                       "{\n"
+                       "  outColor.x = " << rateValue << ";\n"
+                       "}\n";
+               programCollection.glslSources.add("frag_setup") << glu::FragmentSource(fragStream.str());
+       }
+       std::string frag =
+               "#version 450 core\n"
+               "#extension GL_EXT_fragment_shading_rate : enable\n"
+               "layout(set = 0, binding = 0) buffer Block { uint counter; } buf;\n"
+               "layout(location = 0) out uvec4 outColor;\n"
+               "void main()\n"
+               "{\n"
+               "  outColor.x = gl_ShadingRateEXT;\n"
+               "  outColor.y = 0;\n"
+               "  outColor.z = atomicAdd(buf.counter, 1);\n"
+               "  outColor.w = 0;\n"
+               "}\n";
+       programCollection.glslSources.add("frag") << glu::FragmentSource(frag);
+ }
+ TestInstance* AttachmentRateTestCase::createInstance(Context& context) const
+ {
+       return new AttachmentRateInstance(context, m_params);
+ }
+ }     // anonymous
+ void createAttachmentRateTests(tcu::TestContext& testCtx, tcu::TestCaseGroup* parentGroup, bool useDynamicRendering)
+ {
+       struct SRFormat
+       {
+               VkFormat                format;
+               const char*             name;
+       };
+       const std::vector<SRFormat> srFormats
+       {
+               { VK_FORMAT_R8_UINT,                            "r8_uint" },
+               { VK_FORMAT_R8G8_UINT,                          "r8g8_uint" },
+               { VK_FORMAT_R8G8B8_UINT,                        "r8g8b8_uint" },
+               { VK_FORMAT_R8G8B8A8_UINT,                      "r8g8b8a8_uint" },
+               { VK_FORMAT_R16_UINT,                           "r16_uint" },
+               { VK_FORMAT_R16G16_UINT,                        "r16g16_uint" },
+               { VK_FORMAT_R16G16B16_UINT,                     "r16g16b16_uint" },
+               { VK_FORMAT_R16G16B16A16_UINT,          "r16g16b16a16_uint" },
+               { VK_FORMAT_R32_UINT,                           "r32_uint" },
+               { VK_FORMAT_R32G32_UINT,                        "r32g32_uint" },
+               { VK_FORMAT_R32G32B32_UINT,                     "r32g32b32_uint" },
+               { VK_FORMAT_R32G32B32A32_UINT,          "r32g32b32a32_uint" },
+               { VK_FORMAT_R64_UINT,                           "r64_uint" },
+               { VK_FORMAT_R64G64_UINT,                        "r64g64_uint" },
+               { VK_FORMAT_R64G64B64_UINT,                     "r64g64b64_uint" },
+               { VK_FORMAT_R64G64B64A64_UINT,          "r64g64b64a64_uint" },
+       };
+       struct SRRate
+       {
+               VkExtent2D              count;
+               const char*             name;
+       };
+       const std::vector<SRRate> srRates
+       {
+               { {1, 1},       "rate_1x1" },
+               { {1, 2},       "rate_1x2" },
+               { {1, 4},       "rate_1x4" },
+               { {2, 1},       "rate_2x1" },
+               { {2, 2},       "rate_2x2" },
+               { {2, 4},       "rate_2x4" },
+               { {4, 1},       "rate_4x1" },
+               { {4, 2},       "rate_4x2" },
+               { {4, 4},       "rate_4x4" },
+       };
+       struct TestModeParam
+       {
+               TestMode                mode;
+               const char*             name;
+       };
+       const std::vector<TestModeParam> testModeParams
+       {
+               { TM_SETUP_RATE_WITH_ATOMICS_IN_COMPUTE_SHADER,                                                 "setup_with_atomics" },
+               { TM_SETUP_RATE_WITH_FRAGMENT_SHADER,                                                                   "setup_with_fragment" },
+               { TM_SETUP_RATE_WITH_COPYING_FROM_OTHER_IMAGE,                                                  "setup_with_copying" },
+               { TM_SETUP_RATE_WITH_COPYING_FROM_CONCURENT_IMAGE_USING_TRANSFER_QUEUE, "setup_with_copying_using_transfer_queue_concurent" },
+               { TM_SETUP_RATE_WITH_COPYING_FROM_EXCLUSIVE_IMAGE_USING_TRANSFER_QUEUE, "setup_with_copying_using_transfer_queue_exclusive" },
+               { TM_SETUP_RATE_WITH_LINEAR_TILED_IMAGE,                                                                "setup_with_linear_tiled_image" },
+       };
+       de::MovePtr<tcu::TestCaseGroup> mainGroup(new tcu::TestCaseGroup(testCtx, "attachment_rate", ""));
+       for (const auto& testModeParam : testModeParams)
+       {
+               de::MovePtr<tcu::TestCaseGroup> testModeGroup(new tcu::TestCaseGroup(testCtx, testModeParam.name, ""));
+               for (const auto& srFormat : srFormats)
+               {
+                       de::MovePtr<tcu::TestCaseGroup> formatGroup(new tcu::TestCaseGroup(testCtx, srFormat.name, ""));
+                       for (const auto& srRate : srRates)
+                       {
+                               formatGroup->addChild(new AttachmentRateTestCase(testCtx, srRate.name, de::SharedPtr<TestParams>(
+                                       new TestParams
+                                       {
+                                               testModeParam.mode,                                             // TestMode                     mode;
+                                               srFormat.format,                                                // VkFormat                     srFormat;
+                                               srRate.count,                                                   // VkExtent2D           srRate;
+                                               useDynamicRendering,                                    // bool                         useDynamicRendering;
+                                               false                                                                   // bool                         useImagelessFramebuffer;
+                                       }
+                               )));
+                               // duplicate all tests for imageless framebuffer
+                               if (!useDynamicRendering)
+                               {
+                                       std::string imagelessName = std::string(srRate.name) + "_imageless";
+                                       formatGroup->addChild(new AttachmentRateTestCase(testCtx, imagelessName.c_str(), de::SharedPtr<TestParams>(
+                                               new TestParams
+                                               {
+                                                       testModeParam.mode,                                     // TestMode                     mode;
+                                                       srFormat.format,                                        // VkFormat                     srFormat;
+                                                       srRate.count,                                           // VkExtent2D           srRate;
+                                                       false,                                                          // bool                         useDynamicRendering;
+                                                       true                                                            // bool                         useImagelessFramebuffer;
+                                               }
+                                       )));
+                               }
+                       }
+                       testModeGroup->addChild(formatGroup.release());
+               }
+               mainGroup->addChild(testModeGroup.release());
+       }
+       if (!useDynamicRendering)
+       {
+               de::MovePtr<tcu::TestCaseGroup> miscGroup(new tcu::TestCaseGroup(testCtx, "misc", ""));
+               miscGroup->addChild(new AttachmentRateTestCase(testCtx, "two_subpass", de::SharedPtr<TestParams>(
+                       new TestParams
+                       {
+                               TM_TWO_SUBPASS,                                                                 // TestMode                     mode;
+                               VK_FORMAT_R8_UINT,                                                              // VkFormat                     srFormat;
+                               {0, 0},                                                                                 // VkExtent2D           srRate;                                 // not used in TM_TWO_SUBPASS
+                               false,                                                                                  // bool                         useDynamicRendering;
+                               false                                                                                   // bool                         useImagelessFramebuffer;
+                       }
+               )));
+               mainGroup->addChild(miscGroup.release());
+       }
+       parentGroup->addChild(mainGroup.release());
+ }
+ }     // FragmentShadingRage
+ }     // vkt
@@@ -1678,35 -1857,163 +1857,163 @@@ FragmentDensityMapTestInstance::Fragmen
        if (testParams.dynamicDensityMap)
        {
                std::vector<VkClearValue>       attachmentClearValuesDDM { makeClearValueColorF32(1.0f, 1.0f, 1.0f, 1.0f) };
-               const VkRenderPassBeginInfo renderPassBeginInfoProduceDynamicDensityMap
+               if (isDynamicRendering)
                {
-                       VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,                                                       // VkStructureType              sType;
-                       DE_NULL,                                                                                                                        // const void*                  pNext;
-                       *m_renderPassProduceDynamicDensityMap,                                                          // VkRenderPass                 renderPass;
-                       *m_framebufferProduceDynamicDensityMap,                                                         // VkFramebuffer                framebuffer;
-                       makeRect2D(densityMapImageSize.width, densityMapImageSize.height),      // VkRect2D                             renderArea;
-                       static_cast<deUint32>(attachmentClearValuesDDM.size()),                         // uint32_t                             clearValueCount;
-                       attachmentClearValuesDDM.data()                                                                         // const VkClearValue*  pClearValues;
-               };
-               RPS2::cmdBeginRenderPass(vk, *m_cmdBuffer, &renderPassBeginInfoProduceDynamicDensityMap, &subpassBeginInfo);
+                       // change layout of density map - after filling it layout was changed
+                       // to density map optimal but here we want to render values to it
+                       const VkImageSubresourceRange   subresourceRange        = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, densityMapImageLayers, 0u, 1u);
+                       const VkImageMemoryBarrier              imageBarrier            = makeImageMemoryBarrier(
+                               VK_ACCESS_FRAGMENT_DENSITY_MAP_READ_BIT_EXT,            // VkAccessFlags                        srcAccessMask;
+                               VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,                           // VkAccessFlags                        dstAccessMask;
+                               VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT,       // VkImageLayout                        oldLayout;
+                               VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                       // VkImageLayout                        newLayout;
+                               **m_densityMapImages[0],                                                        // VkImage                                      image;
+                               subresourceRange                                                                        // VkImageSubresourceRange      subresourceRange;
+                       );
+                       vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_NONE_KHR, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
+                                                                 0, 0, DE_NULL, 0, DE_NULL, 1, &imageBarrier);
+                       VkRenderingAttachmentInfoKHR colorAttachment
+                       {
+                               VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR,        // VkStructureType                                              sType;
+                               DE_NULL,                                                                                        // const void*                                                  pNext;
+                               **m_densityMapImageViews[0],                                            // VkImageView                                                  imageView;
+                               VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                       // VkImageLayout                                                imageLayout;
+                               VK_RESOLVE_MODE_NONE,                                                           // VkResolveModeFlagBits                                resolveMode;
+                               DE_NULL,                                                                                        // VkImageView                                                  resolveImageView;
+                               VK_IMAGE_LAYOUT_UNDEFINED,                                                      // VkImageLayout                                                resolveImageLayout;
+                               VK_ATTACHMENT_LOAD_OP_CLEAR,                                            // VkAttachmentLoadOp                                   loadOp;
+                               VK_ATTACHMENT_STORE_OP_STORE,                                           // VkAttachmentStoreOp                                  storeOp;
+                               attachmentClearValuesDDM[0]                                                     // VkClearValue                                                 clearValue;
+                       };
+                       VkRenderingInfoKHR renderingInfo
+                       {
+                               VK_STRUCTURE_TYPE_RENDERING_INFO_KHR,
+                               DE_NULL,
+                               0u,                                                                                                     // VkRenderingFlagsKHR                                  flags;
+                               dynamicDensityMapRenderArea,                                            // VkRect2D                                                             renderArea;
+                               densityMapImageLayers,                                                          // deUint32                                                             layerCount;
+                               m_viewMask,                                                                                     // deUint32                                                             viewMask;
+                               1u,                                                                                                     // deUint32                                                             colorAttachmentCount;
+                               &colorAttachment,                                                                       // const VkRenderingAttachmentInfoKHR*  pColorAttachments;
+                               DE_NULL,                                                                                        // const VkRenderingAttachmentInfoKHR*  pDepthAttachment;
+                               DE_NULL,                                                                                        // const VkRenderingAttachmentInfoKHR*  pStencilAttachment;
+                       };
 -                      vk.cmdBeginRenderingKHR(*m_cmdBuffer, &renderingInfo);
++                      vk.cmdBeginRendering(*m_cmdBuffer, &renderingInfo);
+               }
+               else
+               {
+                       const VkRenderPassBeginInfo renderPassBeginInfoProduceDynamicDensityMap
+                       {
+                               VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,                                       // VkStructureType              sType;
+                               DE_NULL,                                                                                                        // const void*                  pNext;
+                               *m_renderPassProduceDynamicDensityMap,                                          // VkRenderPass                 renderPass;
+                               *m_framebufferProduceDynamicDensityMap,                                         // VkFramebuffer                framebuffer;
+                               dynamicDensityMapRenderArea,                                                            // VkRect2D                             renderArea;
+                               static_cast<deUint32>(attachmentClearValuesDDM.size()),         // uint32_t                             clearValueCount;
+                               attachmentClearValuesDDM.data()                                                         // const VkClearValue*  pClearValues;
+                       };
+                       renderPassWrapper->cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfoProduceDynamicDensityMap);
+               }
                vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipelineProduceDynamicDensityMap);
                vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBufferDDM.get(), &vertexBufferOffset);
                vk.cmdDraw(*m_cmdBuffer, (deUint32)m_verticesDDM.size(), 1, 0, 0);
-               RPS2::cmdEndRenderPass(vk, *m_cmdBuffer, &subpassEndInfo);
+               if (isDynamicRendering)
+               {
 -                      vk.cmdEndRenderingKHR(*m_cmdBuffer);
++                      vk.cmdEndRendering(*m_cmdBuffer);
+                       // barrier that will change layout of density map
+                       VkImageMemoryBarrier densityMapImageBarrier = makeImageMemoryBarrier(
+                               VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,                                           // VkAccessFlags                        srcAccessMask;
+                               VK_ACCESS_FRAGMENT_DENSITY_MAP_READ_BIT_EXT,                            // VkAccessFlags                        dstAccessMask;
+                               VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                                       // VkImageLayout                        oldLayout;
+                               VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT,                       // VkImageLayout                        newLayout;
+                               **m_densityMapImages[0],                                                                        // VkImage                                      image;
+                               densityMapSubresourceRange                                                                      // VkImageSubresourceRange      subresourceRange;
+                       );
+                       vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT,
+                               0, 0, DE_NULL, 0, DE_NULL, 1, &densityMapImageBarrier);
+               }
+               else
+                       renderPassWrapper->cmdEndRenderPass(*m_cmdBuffer);
        }
  
        // Render subsampled image
-       const VkRenderPassBeginInfo renderPassBeginInfoProduceSubsampledImage
-       {
-               VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,                                               // VkStructureType              sType;
-               DE_NULL,                                                                                                                // const void*                  pNext;
-               *m_renderPassProduceSubsampledImage,                                                    // VkRenderPass                 renderPass;
-               *m_framebufferProduceSubsampledImage,                                                   // VkFramebuffer                framebuffer;
-               makeRect2D(colorImageSize.width, colorImageSize.height),                // VkRect2D                             renderArea;
-               static_cast<deUint32>(attachmentClearValues.size()),                    // uint32_t                             clearValueCount;
-               attachmentClearValues.data()                                                                    // const VkClearValue*  pClearValues;
-       };
-       RPS2::cmdBeginRenderPass(vk, *m_cmdBuffer, &renderPassBeginInfoProduceSubsampledImage, &subpassBeginInfo);
+       if (isDynamicRendering)
+       {
+               // barier that will change layout of color and resolve attachments
+               std::vector<VkImageMemoryBarrier> cbImageBarrier(2, makeImageMemoryBarrier(
+                       VK_ACCESS_NONE_KHR,                                                                                                                             // VkAccessFlags                        srcAccessMask;
+                       VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,                                                                                   // VkAccessFlags                        dstAccessMask;
+                       VK_IMAGE_LAYOUT_UNDEFINED,                                                                                                              // VkImageLayout                        oldLayout;
+                       VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                                                                               // VkImageLayout                        newLayout;
+                       *m_colorImage,                                                                                                                                  // VkImage                                      image;
+                       colorSubresourceRange                                                                                                                   // VkImageSubresourceRange      subresourceRange;
+               ));
+               cbImageBarrier[1].image = *m_colorResolvedImage;
+               vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_NONE_KHR, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
+                       0, 0, DE_NULL, 0, DE_NULL, 1 + isColorImageMultisampled, cbImageBarrier.data());
+               VkRenderingAttachmentInfoKHR colorAttachment
+               {
+                       VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR,                                                                // VkStructureType                                              sType;
+                       DE_NULL,                                                                                                                                                // const void*                                                  pNext;
+                       *m_colorImageView,                                                                                                                              // VkImageView                                                  imageView;
+                       VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                                                                               // VkImageLayout                                                imageLayout;
+                       isColorImageMultisampled ? VK_RESOLVE_MODE_AVERAGE_BIT : VK_RESOLVE_MODE_NONE,  // VkResolveModeFlagBits                                resolveMode;
+                       isColorImageMultisampled ? *m_colorResolvedImageView : DE_NULL,                                 // VkImageView                                                  resolveImageView;
+                       isColorImageMultisampled ? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
+                                                                        : VK_IMAGE_LAYOUT_UNDEFINED,                                                   // VkImageLayout                                                resolveImageLayout;
+                       VK_ATTACHMENT_LOAD_OP_CLEAR,                                                                                                    // VkAttachmentLoadOp                                   loadOp;
+                       VK_ATTACHMENT_STORE_OP_STORE,                                                                                                   // VkAttachmentStoreOp                                  storeOp;
+                       attachmentClearValues[0]                                                                                                                // VkClearValue                                                 clearValue;
+               };
+               VkRenderingFragmentDensityMapAttachmentInfoEXT densityMapAttachment
+               {
+                       VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_INFO_EXT,                   // VkStructureType                                              sType;
+                       DE_NULL,                                                                                                                                                // const void*                                                  pNext;
+                       **m_densityMapImageViews[0],                                                                                                    // VkImageView                                                  imageView;
+                       VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT                                                                // VkImageLayout                                                imageLayout;
+               };
+               VkRenderingInfoKHR renderingInfo
+               {
+                       VK_STRUCTURE_TYPE_RENDERING_INFO_KHR,
+                       &densityMapAttachment,
+                       0u,                                                                                                                                                             // VkRenderingFlagsKHR                                  flags;
+                       colorImageRenderArea,                                                                                                                   // VkRect2D                                                             renderArea;
+                       densityMapImageLayers,                                                                                                                  // deUint32                                                             layerCount;
+                       m_viewMask,                                                                                                                                             // deUint32                                                             viewMask;
+                       1u,                                                                                                                                                             // deUint32                                                             colorAttachmentCount;
+                       &colorAttachment,                                                                                                                               // const VkRenderingAttachmentInfoKHR*  pColorAttachments;
+                       DE_NULL,                                                                                                                                                // const VkRenderingAttachmentInfoKHR*  pDepthAttachment;
+                       DE_NULL,                                                                                                                                                // const VkRenderingAttachmentInfoKHR*  pStencilAttachment;
+               };
 -              vk.cmdBeginRenderingKHR(*m_cmdBuffer, &renderingInfo);
++              vk.cmdBeginRendering(*m_cmdBuffer, &renderingInfo);
+       }
+       else
+       {
+               const VkRenderPassBeginInfo renderPassBeginInfoProduceSubsampledImage
+               {
+                       VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,                                               // VkStructureType              sType;
+                       DE_NULL,                                                                                                                // const void*                  pNext;
+                       *m_renderPassProduceSubsampledImage,                                                    // VkRenderPass                 renderPass;
+                       *m_framebufferProduceSubsampledImage,                                                   // VkFramebuffer                framebuffer;
+                       colorImageRenderArea,                                                                                   // VkRect2D                             renderArea;
+                       static_cast<deUint32>(attachmentClearValues.size()),                    // uint32_t                             clearValueCount;
+                       attachmentClearValues.data()                                                                    // const VkClearValue*  pClearValues;
+               };
+               renderPassWrapper->cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfoProduceSubsampledImage);
+       }
        vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipelineProduceSubsampledImage);
        vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
        vk.cmdDraw(*m_cmdBuffer, (deUint32)m_vertices.size(), 1, 0, 0);
                vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
                vk.cmdDraw(*m_cmdBuffer, (deUint32)m_vertices.size(), 1, 0, 0);
        }
-       RPS2::cmdEndRenderPass(vk, *m_cmdBuffer, &subpassEndInfo);
+       if (isDynamicRendering)
 -              vk.cmdEndRenderingKHR(*m_cmdBuffer);
++              vk.cmdEndRendering(*m_cmdBuffer);
+       else
+               renderPassWrapper->cmdEndRenderPass(*m_cmdBuffer);
  
        // Resample subsampled image
        if (testParams.subsampledLoads)
        {
-               const VkRenderPassBeginInfo renderPassBeginInfoUpdateSubsampledImage
+               if (isDynamicRendering)
                {
-                       VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,                                       // VkStructureType              sType;
-                       DE_NULL,                                                                                                        // const void*                  pNext;
-                       *m_renderPassUpdateSubsampledImage,                                                     // VkRenderPass                 renderPass;
-                       *m_framebufferUpdateSubsampledImage,                                            // VkFramebuffer                framebuffer;
-                       makeRect2D(colorImageSize.width, colorImageSize.height),        // VkRect2D                             renderArea;
-                       0u,                                                                                                                     // uint32_t                             clearValueCount;
-                       DE_NULL                                                                                                         // const VkClearValue*  pClearValues;
-               };
-               RPS2::cmdBeginRenderPass(vk, *m_cmdBuffer, &renderPassBeginInfoUpdateSubsampledImage, &subpassBeginInfo);
+                       VkRenderingAttachmentInfoKHR colorAttachment
+                       {
+                               VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR,                                                // VkStructureType                                              sType;
+                               DE_NULL,                                                                                                                                // const void*                                                  pNext;
+                               *m_colorImageView,                                                                                                              // VkImageView                                                  imageView;
+                               VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                                                               // VkImageLayout                                                imageLayout;
+                               VK_RESOLVE_MODE_NONE,                                                                                                   // VkResolveModeFlagBits                                resolveMode;
+                               DE_NULL,                                                                                                                                // VkImageView                                                  resolveImageView;
+                               VK_IMAGE_LAYOUT_UNDEFINED,                                                                                              // VkImageLayout                                                resolveImageLayout;
+                               VK_ATTACHMENT_LOAD_OP_LOAD,                                                                                             // VkAttachmentLoadOp                                   loadOp;
+                               VK_ATTACHMENT_STORE_OP_STORE,                                                                                   // VkAttachmentStoreOp                                  storeOp;
+                               attachmentClearValues[0]                                                                                                // VkClearValue                                                 clearValue;
+                       };
+                       VkRenderingFragmentDensityMapAttachmentInfoEXT densityMapAttachment
+                       {
+                               VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_INFO_EXT,   // VkStructureType                                              sType;
+                               DE_NULL,                                                                                                                                // const void*                                                  pNext;
+                               **m_densityMapImageViews[1],                                                                                    // VkImageView                                                  imageView;
+                               VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT                                                // VkImageLayout                                                imageLayout;
+                       };
+                       VkRenderingInfoKHR renderingInfo
+                       {
+                               VK_STRUCTURE_TYPE_RENDERING_INFO_KHR,
+                               &densityMapAttachment,
+                               0u,                                                                                                                                             // VkRenderingFlagsKHR                                  flags;
+                               colorImageRenderArea,                                                                                                   // VkRect2D                                                             renderArea;
+                               densityMapImageLayers,                                                                                                  // deUint32                                                             layerCount;
+                               m_viewMask,                                                                                                                             // deUint32                                                             viewMask;
+                               1u,                                                                                                                                             // deUint32                                                             colorAttachmentCount;
+                               &colorAttachment,                                                                                                               // const VkRenderingAttachmentInfoKHR*  pColorAttachments;
+                               DE_NULL,                                                                                                                                // const VkRenderingAttachmentInfoKHR*  pDepthAttachment;
+                               DE_NULL,                                                                                                                                // const VkRenderingAttachmentInfoKHR*  pStencilAttachment;
+                       };
 -                      vk.cmdBeginRenderingKHR(*m_cmdBuffer, &renderingInfo);
++                      vk.cmdBeginRendering(*m_cmdBuffer, &renderingInfo);
+               }
+               else
+               {
+                       const VkRenderPassBeginInfo renderPassBeginInfoUpdateSubsampledImage
+                       {
+                               VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,                                       // VkStructureType              sType;
+                               DE_NULL,                                                                                                        // const void*                  pNext;
+                               *m_renderPassUpdateSubsampledImage,                                                     // VkRenderPass                 renderPass;
+                               *m_framebufferUpdateSubsampledImage,                                            // VkFramebuffer                framebuffer;
+                               makeRect2D(colorImageSize.width, colorImageSize.height),        // VkRect2D                             renderArea;
+                               0u,                                                                                                                     // uint32_t                             clearValueCount;
+                               DE_NULL                                                                                                         // const VkClearValue*  pClearValues;
+                       };
+                       renderPassWrapper->cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfoUpdateSubsampledImage);
+               }
                vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipelineUpdateSubsampledImage);
                vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayoutOperateOnSubsampledImage, 0, 1, &m_descriptorSetOperateOnSubsampledImage.get(), 0, DE_NULL);
                vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
                vk.cmdDraw(*m_cmdBuffer, (deUint32)m_vertices.size(), 1, 0, 0);
-               RPS2::cmdEndRenderPass(vk, *m_cmdBuffer, &subpassEndInfo);
+               if (isDynamicRendering)
 -                      vk.cmdEndRenderingKHR(*m_cmdBuffer);
++                      vk.cmdEndRendering(*m_cmdBuffer);
+               else
+                       renderPassWrapper->cmdEndRenderPass(*m_cmdBuffer);
        }
  
        // Copy subsampled image to normal image using sampler that is able to read from subsampled images
        // (subsampled image cannot be copied using vkCmdCopyImageToBuffer)
-       const VkRenderPassBeginInfo renderPassBeginInfoOutputSubsampledImage
-       {
-               VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,                                                       // VkStructureType              sType;
-               DE_NULL,                                                                                                                        // const void*                  pNext;
-               *m_renderPassOutputSubsampledImage,                                                                     // VkRenderPass                 renderPass;
-               *m_framebufferOutputSubsampledImage,                                                            // VkFramebuffer                framebuffer;
-               makeRect2D(outputImageSize.width, outputImageSize.height),                      // VkRect2D                             renderArea;
-               static_cast<deUint32>(attachmentClearValues.size()),                            // uint32_t                             clearValueCount;
-               attachmentClearValues.data()                                                                            // const VkClearValue*  pClearValues;
-       };
-       RPS2::cmdBeginRenderPass(vk, *m_cmdBuffer, &renderPassBeginInfoOutputSubsampledImage, &subpassBeginInfo);
+       if (isDynamicRendering)
+       {
+               // barrier that will change layout of output image
+               VkImageMemoryBarrier outputImageBarrier = makeImageMemoryBarrier(
+                       VK_ACCESS_NONE_KHR,                                                                                                     // VkAccessFlags                                                srcAccessMask;
+                       VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,                                                           // VkAccessFlags                                                dstAccessMask;
+                       VK_IMAGE_LAYOUT_UNDEFINED,                                                                                      // VkImageLayout                                                oldLayout;
+                       VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                                                       // VkImageLayout                                                newLayout;
+                       *m_outputImage,                                                                                                         // VkImage                                                              image;
+                       outputSubresourceRange                                                                                          // VkImageSubresourceRange                              subresourceRange;
+               );
+               vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_NONE_KHR, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
+                       0, 0, DE_NULL, 0, DE_NULL, 1, &outputImageBarrier);
+               VkRenderingAttachmentInfoKHR colorAttachment
+               {
+                       VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR,                                        // VkStructureType                                              sType;
+                       DE_NULL,                                                                                                                        // const void*                                                  pNext;
+                       *m_outputImageView,                                                                                                     // VkImageView                                                  imageView;
+                       VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                                                       // VkImageLayout                                                imageLayout;
+                       VK_RESOLVE_MODE_NONE,                                                                                           // VkResolveModeFlagBits                                resolveMode;
+                       DE_NULL,                                                                                                                        // VkImageView                                                  resolveImageView;
+                       VK_IMAGE_LAYOUT_UNDEFINED,                                                                                      // VkImageLayout                                                resolveImageLayout;
+                       VK_ATTACHMENT_LOAD_OP_CLEAR,                                                                            // VkAttachmentLoadOp                                   loadOp;
+                       VK_ATTACHMENT_STORE_OP_STORE,                                                                           // VkAttachmentStoreOp                                  storeOp;
+                       attachmentClearValues[0]                                                                                        // VkClearValue                                                 clearValue;
+               };
+               VkRenderingInfoKHR renderingInfo
+               {
+                       VK_STRUCTURE_TYPE_RENDERING_INFO_KHR,
+                       DE_NULL,
+                       0u,                                                                                                                                     // VkRenderingFlagsKHR                                  flags;
+                       outputRenderArea,                                                                                                       // VkRect2D                                                             renderArea;
+                       1u,                                                                                                                                     // deUint32                                                             layerCount;
+                       0u,                                                                                                                                     // deUint32                                                             viewMask;
+                       1u,                                                                                                                                     // deUint32                                                             colorAttachmentCount;
+                       &colorAttachment,                                                                                                       // const VkRenderingAttachmentInfoKHR*  pColorAttachments;
+                       DE_NULL,                                                                                                                        // const VkRenderingAttachmentInfoKHR*  pDepthAttachment;
+                       DE_NULL,                                                                                                                        // const VkRenderingAttachmentInfoKHR*  pStencilAttachment;
+               };
 -              vk.cmdBeginRenderingKHR(*m_cmdBuffer, &renderingInfo);
++              vk.cmdBeginRendering(*m_cmdBuffer, &renderingInfo);
+       }
+       else
+       {
+               const VkRenderPassBeginInfo renderPassBeginInfoOutputSubsampledImage
+               {
+                       VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,                                                       // VkStructureType              sType;
+                       DE_NULL,                                                                                                                        // const void*                  pNext;
+                       *m_renderPassOutputSubsampledImage,                                                                     // VkRenderPass                 renderPass;
+                       *m_framebufferOutputSubsampledImage,                                                            // VkFramebuffer                framebuffer;
+                       outputRenderArea,                                                                                                       // VkRect2D                             renderArea;
+                       static_cast<deUint32>(attachmentClearValues.size()),                            // uint32_t                             clearValueCount;
+                       attachmentClearValues.data()                                                                            // const VkClearValue*  pClearValues;
+               };
+               renderPassWrapper->cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfoOutputSubsampledImage);
+       }
        vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipelineOutputSubsampledImage);
        vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayoutOutputSubsampledImage, 0, 1, &m_descriptorSetOutputSubsampledImage.get(), 0, DE_NULL);
        vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBufferOutput.get(), &vertexBufferOffset);
        vk.cmdDraw(*m_cmdBuffer, (deUint32)m_verticesOutput.size(), 1, 0, 0);
-       RPS2::cmdEndRenderPass(vk, *m_cmdBuffer, &subpassEndInfo);
+       if (isDynamicRendering)
 -              vk.cmdEndRenderingKHR(*m_cmdBuffer);
++              vk.cmdEndRendering(*m_cmdBuffer);
+       else
+               renderPassWrapper->cmdEndRenderPass(*m_cmdBuffer);
  
        endCommandBuffer(vk, *m_cmdBuffer);
  }
index 0000000,32d2643..a0a24d4
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,309 +1,309 @@@
 -      const VkPhysicalDeviceSubgroupSizeControlFeaturesEXT&   subgroupSizeControlFeatures     = context.getSubgroupSizeControlFeaturesEXT();
+ /*------------------------------------------------------------------------
+  * Vulkan Conformance Tests
+  * ------------------------
+  *
+  * Copyright (c) 2021 Google LLC.
+  *
+  *
+  * 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 Tests that compute shaders have a subgroup size that is uniform in
+  * command scope.
+  *//*--------------------------------------------------------------------*/
+ #include "deUniquePtr.hpp"
+ #include "vkRef.hpp"
+ #include "vkRefUtil.hpp"
+ #include "vkPrograms.hpp"
+ #include "vkMemUtil.hpp"
+ #include "vkBuilderUtil.hpp"
+ #include "vkCmdUtil.hpp"
+ #include "vkObjUtil.hpp"
+ #include "vkTypeUtil.hpp"
+ #include "vkImageWithMemory.hpp"
+ #include "vkBarrierUtil.hpp"
+ #include "vktTestCaseUtil.hpp"
+ using namespace vk;
+ namespace vkt
+ {
+ namespace subgroups
+ {
+ namespace
+ {
+ using std::vector;
+ using de::MovePtr;
+ class MultipleDispatchesUniformSubgroupSizeInstance : public TestInstance
+ {
+ public:
+                                       MultipleDispatchesUniformSubgroupSizeInstance   (Context&       context);
+       tcu::TestStatus iterate                                                                                 (void);
+ };
+ MultipleDispatchesUniformSubgroupSizeInstance::MultipleDispatchesUniformSubgroupSizeInstance  (Context&       context)
+       :TestInstance                                                                                                                                                           (context)
+ {
+ }
+ tcu::TestStatus MultipleDispatchesUniformSubgroupSizeInstance::iterate (void)
+ {
+       const DeviceInterface&                          vk                                              = m_context.getDeviceInterface();
+       const VkDevice                                          device                                  = m_context.getDevice();
+       Allocator&                                                      allocator                               = m_context.getDefaultAllocator();
+       const VkQueue                                           queue                                   = m_context.getUniversalQueue();
+       const deUint32                                          queueFamilyIndex                = m_context.getUniversalQueueFamilyIndex();
+       const Move<VkCommandPool>                       cmdPool                                 = createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
+       const Move<VkCommandBuffer>                     cmdBuffer                               = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
+       Move<VkShaderModule>                            computeShader                   = createShaderModule (vk, device, m_context.getBinaryCollection().get("comp"), 0u);
+       // The number of invocations in a workgroup.
+       const deUint32                                          maxLocalSize                    = m_context.getDeviceProperties().limits.maxComputeWorkGroupSize[0];
+       // Create a storage buffer to hold the sizes of subgroups.
+       const VkDeviceSize                                      bufferSize                              = maxLocalSize * 2 * sizeof(deUint32);
+       const VkBufferCreateInfo                        resultBufferCreateInfo  = makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
+       Move<VkBuffer>                                          resultBuffer                    = createBuffer(vk, device, &resultBufferCreateInfo);
+       MovePtr<Allocation>                                     resultBufferMemory              = allocator.allocate(getBufferMemoryRequirements(vk, device, *resultBuffer), MemoryRequirement::HostVisible);
+       VK_CHECK(vk.bindBufferMemory(device, *resultBuffer, resultBufferMemory->getMemory(), resultBufferMemory->getOffset()));
+       // Build descriptors for the storage buffer
+       const Unique<VkDescriptorPool>          descriptorPool                  (DescriptorPoolBuilder().addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)
+                                                                                                                                                                               .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
+       const auto                                                      descriptorSetLayout1    (DescriptorSetLayoutBuilder().addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, VK_SHADER_STAGE_COMPUTE_BIT)
+                                                                                                                                                                                        .build(vk, device));
+       const VkDescriptorBufferInfo            resultInfo                              = makeDescriptorBufferInfo(*resultBuffer, 0u,
+                                                                                                                                                                                  (VkDeviceSize) bufferSize - maxLocalSize * sizeof(deUint32));
+       const VkDescriptorSetAllocateInfo       allocInfo                               =
+       {
+               VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // sType
+               DE_NULL,                                                                                // pNext
+               *descriptorPool,                                                                // descriptorPool
+               1u,                                                                                             // descriptorSetCount
+               &(*descriptorSetLayout1)                                                // pSetLayouts
+       };
+       Move<VkDescriptorSet>                           descriptorSet                   = allocateDescriptorSet(vk, device, &allocInfo);
+       DescriptorSetUpdateBuilder                      builder;
+       builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, &resultInfo);
+       builder.update(vk, device);
+       // Compute pipeline
+       const Move<VkPipelineLayout>            computePipelineLayout   = makePipelineLayout (vk, device, *descriptorSetLayout1);
+       for (deUint32 localSize1 = 8; localSize1 < maxLocalSize + 1; localSize1 *= 2)
+       {
+               for (deUint32 localSize2 = 8; localSize2 < maxLocalSize + 1; localSize2 *= 2)
+               {
+                       // On each iteration, change the number of invocations which might affect
+                       // the subgroup size if the driver doesn't behave as expected.
+                       const VkSpecializationMapEntry                  entries                                 =
+                       {
+                               0u,                                     // deUint32 constantID;
+                               0u,                                     // deUint32 offset;
+                               sizeof(localSize1)      // size_t size;
+                       };
+                       const VkSpecializationInfo                              specInfo                                =
+                       {
+                               1,                                      // mapEntryCount
+                               &entries,                       // pMapEntries
+                               sizeof(localSize1),     // dataSize
+                               &localSize1                     // pData
+                       };
+                       const VkSpecializationInfo                              specInfo2                               =
+                       {
+                               1,                                      // mapEntryCount
+                               &entries,                       // pMapEntries
+                               sizeof(localSize2),     // dataSize
+                               &localSize2                     // pData
+                       };
+                       const VkPipelineShaderStageCreateInfo   shaderStageCreateInfo   =
+                       {
+                               VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,                                    // sType
+                               DE_NULL,                                                                                                                                // pNext
+                               VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXT,    // flags
+                               VK_SHADER_STAGE_COMPUTE_BIT,                                                                                    // stage
+                               *computeShader,                                                                                                                 // module
+                               "main",                                                                                                                                 // pName
+                               &specInfo,                                                                                                                              // pSpecializationInfo
+                       };
+                       const VkPipelineShaderStageCreateInfo   shaderStageCreateInfo2  =
+                       {
+                               VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,                                    // sType
+                               DE_NULL,                                                                                                                                // pNext
+                               VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXT,    // flags
+                               VK_SHADER_STAGE_COMPUTE_BIT,                                                                                    // stage
+                               *computeShader,                                                                                                                 // module
+                               "main",                                                                                                                                 // pName
+                               &specInfo2,                                                                                                                             // pSpecializationInfo
+                       };
+                       const VkComputePipelineCreateInfo               pipelineCreateInfo              =
+                       {
+                               VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // sType
+                               DE_NULL,                                                                                // pNext
+                               0u,                                                                                             // flags
+                               shaderStageCreateInfo,                                                  // stage
+                               *computePipelineLayout,                                                 // layout
+                               (VkPipeline) 0,                                                                 // basePipelineHandle
+                               0u,                                                                                             // basePipelineIndex
+                       };
+                       const VkComputePipelineCreateInfo               pipelineCreateInfo2             =
+                       {
+                               VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // sType
+                               DE_NULL,                                                                                // pNext
+                               0u,                                                                                             // flags
+                               shaderStageCreateInfo2,                                                 // stage
+                               *computePipelineLayout,                                                 // layout
+                               (VkPipeline) 0,                                                                 // basePipelineHandle
+                               0u,                                                                                             // basePipelineIndex
+                       };
+                       Move<VkPipeline>                                                computePipeline                 = createComputePipeline(vk, device, (VkPipelineCache) 0u, &pipelineCreateInfo);
+                       Move<VkPipeline>                                                computePipeline2                = createComputePipeline(vk, device, (VkPipelineCache) 0u, &pipelineCreateInfo2);
+                       beginCommandBuffer(vk, *cmdBuffer);
+                       // Clears the values written on the previous iteration.
+                       vk.cmdFillBuffer(*cmdBuffer, *resultBuffer, 0u, VK_WHOLE_SIZE, 0);
+                       const deUint32                                                  zero                                    = 0u;
+                       vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *computePipelineLayout, 0u, 1u, &descriptorSet.get(), 1, &zero);
+                       vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *computePipeline);
+                       vk.cmdDispatch(*cmdBuffer, 1, 1, 1);
+                       const auto                                                              barrier                                 = makeBufferMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_WRITE_BIT, *resultBuffer, 0ull, bufferSize);
+                       vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags) 0,
+                                                                 0, (const VkMemoryBarrier *) DE_NULL, 1, &barrier, 0, (const VkImageMemoryBarrier *) DE_NULL);
+                       const deUint32                                                  offset                                  = static_cast<deUint32>(maxLocalSize * sizeof(deUint32));
+                       vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *computePipelineLayout, 0u, 1u, &descriptorSet.get(), 1u, &offset);
+                       vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *computePipeline2);
+                       vk.cmdDispatch(*cmdBuffer, 1, 1, 1);
+                       endCommandBuffer(vk, *cmdBuffer);
+                       submitCommandsAndWait(vk, device, queue, *cmdBuffer);
+                       invalidateAlloc(vk, device, *resultBufferMemory);
+                       const deUint32                                                  *res                                    = static_cast<const deUint32 *>(resultBufferMemory->getHostPtr());
+                       deUint32                                                                size                                    = 0;
+                       // Search for the first nonzero size. Then go through the data of both pipelines and check that
+                       // the first nonzero size matches with other nonzero values.
+                       for (deUint32 i = 0; i < maxLocalSize; i++)
+                       {
+                               if (res[i] != 0)
+                               {
+                                       size = res[i];
+                                       break;
+                               }
+                       }
+                       // Subgroup size is guaranteed to be at least 1.
+                       DE_ASSERT(size > 0);
+                       for (deUint32 i = 0; i < maxLocalSize * 2; i++)
+                       {
+                               if (size != res[i] && res[i] != 0)
+                                       return tcu::TestStatus::fail("Subgroup size not uniform in command scope. " + std::to_string(res[i]) + " != " + std::to_string(size));
+                       }
+               }
+       }
+       return tcu::TestStatus::pass("pass");
+ }
+ class MultipleDispatchesUniformSubgroupSize : public TestCase
+ {
+ public:
+                                               MultipleDispatchesUniformSubgroupSize (tcu::TestContext&        testCtx,
+                                                                                                                          const std::string&   name,
+                                                                                                                          const std::string&   description);
+       void                            initPrograms                                              (SourceCollections&   programCollection) const;
+       TestInstance*           createInstance                                            (Context&                             context) const;
+       virtual void            checkSupport                                              (Context&                             context) const;
+ };
+ MultipleDispatchesUniformSubgroupSize::MultipleDispatchesUniformSubgroupSize (tcu::TestContext&       testCtx,
+                                                                                                                                                         const std::string&    name,
+                                                                                                                                                         const std::string&    description)
+       : TestCase      (testCtx, name, description)
+ {
+ }
+ void MultipleDispatchesUniformSubgroupSize::checkSupport (Context& context) const
+ {
++      const VkPhysicalDeviceSubgroupSizeControlFeaturesEXT&   subgroupSizeControlFeatures     = context.getSubgroupSizeControlFeatures();
+       if (subgroupSizeControlFeatures.subgroupSizeControl == DE_FALSE)
+               TCU_THROW(NotSupportedError, "Device does not support varying subgroup sizes");
+ }
+ void MultipleDispatchesUniformSubgroupSize::initPrograms (SourceCollections& programCollection) const
+ {
+       std::ostringstream computeSrc;
+       computeSrc
+               << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
+               << "#extension GL_KHR_shader_subgroup_basic : enable\n"
+               << "#extension GL_KHR_shader_subgroup_vote : enable\n"
+               << "#extension GL_KHR_shader_subgroup_ballot : enable\n"
+               << "layout(std430, binding = 0) buffer Outputs { uint sizes[]; };\n"
+               << "layout(local_size_x_id = 0) in;\n"
+               << "void main()\n"
+               << "{\n"
+               << "    if (subgroupElect())\n"
+               << "    {\n"
+               << "        sizes[gl_WorkGroupID.x * gl_NumSubgroups + gl_SubgroupID] = gl_SubgroupSize;\n"
+               << "    }\n"
+               << "}\n";
+       programCollection.glslSources.add("comp") << glu::ComputeSource(computeSrc.str())
+       << ShaderBuildOptions(programCollection.usedVulkanVersion, SPIRV_VERSION_1_3, 0u);
+ }
+ TestInstance* MultipleDispatchesUniformSubgroupSize::createInstance (Context& context) const
+ {
+       return new MultipleDispatchesUniformSubgroupSizeInstance(context);
+ }
+ } // anonymous ns
+ tcu::TestCaseGroup* createMultipleDispatchesUniformSubgroupSizeTests (tcu::TestContext& testCtx)
+ {
+       de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "multiple_dispatches", "Multiple dispatches uniform subgroup size tests"));
+       testGroup->addChild(new MultipleDispatchesUniformSubgroupSize(testCtx, "uniform_subgroup_size", ""));
+       return testGroup.release();
+ }
+ } // compute
+ } // vkt
index 0000000,75153ce..fc87861
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,387 +1,387 @@@
 -      vk.cmdPipelineBarrier2KHR(cmdBuffer.get(), &dependencyInfo);
+ /*------------------------------------------------------------------------
+  * Vulkan Conformance Tests
+  * ------------------------
+  *
+  * Copyright (c) 2021 Google LLC.
+  *
+  *
+  * 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 Test no-op image layout transitions in VK_KHR_synchronization2
+  *//*--------------------------------------------------------------------*/
+ #include "deUniquePtr.hpp"
+ #include "tcuTextureUtil.hpp"
+ #include "tcuImageCompare.hpp"
+ #include "vkBarrierUtil.hpp"
+ #include "vkImageUtil.hpp"
+ #include "vkCmdUtil.hpp"
+ #include "vkObjUtil.hpp"
+ #include "vkTypeUtil.hpp"
+ #include "vkImageWithMemory.hpp"
+ #include "vktTestCaseUtil.hpp"
+ #include "vktSynchronizationUtil.hpp"
+ #include "tcuTestLog.hpp"
+ #include <string>
+ using namespace vk;
+ namespace vkt
+ {
+ namespace synchronization
+ {
+ namespace
+ {
+ using tcu::Vec4;
+ using std::vector;
+ using de::MovePtr;
+ using tcu::TextureLevel;
+ const int                     WIDTH   = 64;
+ const int                     HEIGHT  = 64;
+ const VkFormat                FORMAT  = VK_FORMAT_R8G8B8A8_UNORM;
+ inline VkImageCreateInfo makeImageCreateInfo ()
+ {
+       const VkImageUsageFlags usage           = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT
+                                                                                 | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+       const VkImageCreateInfo imageParams     =
+       {
+               VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,    //  VkStructureType         sType;
+               DE_NULL,                                                                //  const void*             pNext;
+               0,                                                                              //  VkImageCreateFlags      flags;
+               VK_IMAGE_TYPE_2D,                                               //  VkImageType             imageType;
+               FORMAT,                                                                 //  VkFormat                format;
+               makeExtent3D(WIDTH, HEIGHT, 1u),                //  VkExtent3D              extent;
+               1u,                                                                             //  deUint32                mipLevels;
+               1u,                                                                             //  deUint32                arrayLayers;
+               VK_SAMPLE_COUNT_1_BIT,                                  //  VkSampleCountFlagBits   samples;
+               VK_IMAGE_TILING_OPTIMAL,                                //  VkImageTiling           tiling;
+               usage,                                                                  //  VkImageUsageFlags       usage;
+               VK_SHARING_MODE_EXCLUSIVE,                              //  VkSharingMode           sharingMode;
+               0u,                                                                             //  deUint32                queueFamilyIndexCount;
+               DE_NULL,                                                                //  const deUint32*         pQueueFamilyIndices;
+               VK_IMAGE_LAYOUT_UNDEFINED,                              //  VkImageLayout           initialLayout;
+       };
+       return imageParams;
+ }
+ Move<VkBuffer> makeVertexBuffer (const DeviceInterface& vk, const VkDevice device, const deUint32 queueFamilyIndex)
+ {
+       const VkBufferCreateInfo vertexBufferParams =
+       {
+               VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,   // VkStructureType      sType;
+               DE_NULL,                                                                // const void*          pNext;
+               0u,                                                                             // VkBufferCreateFlags  flags;
+               1024u,                                                                  // VkDeviceSize         size;
+               VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,              // VkBufferUsageFlags   usage;
+               VK_SHARING_MODE_EXCLUSIVE,                              // VkSharingMode        sharingMode;
+               1u,                                                                             // deUint32             queueFamilyIndexCount;
+               &queueFamilyIndex                                               // const deUint32*      pQueueFamilyIndices;
+       };
+       Move<VkBuffer>                  vertexBuffer            = createBuffer(vk, device, &vertexBufferParams);;
+       return vertexBuffer;
+ }
+ class SynchronizationImageLayoutTransitionTestInstance : public TestInstance
+ {
+ public:
+                                       SynchronizationImageLayoutTransitionTestInstance        (Context&                       context);
+       tcu::TestStatus iterate                                                                                         (void);
+ };
+ SynchronizationImageLayoutTransitionTestInstance::SynchronizationImageLayoutTransitionTestInstance (Context& context)
+       : TestInstance  (context)
+ {
+ }
+ template<typename T>
+ inline size_t sizeInBytes (const vector<T>& vec)
+ {
+       return vec.size() * sizeof(vec[0]);
+ }
+ // Draw a quad covering the whole framebuffer
+ vector<Vec4> genFullQuadVertices (void)
+ {
+       vector<Vec4> vertices;
+       vertices.push_back(Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
+       vertices.push_back(Vec4( 1.0f, -1.0f, 0.0f, 1.0f));
+       vertices.push_back(Vec4(-1.0f,  1.0f, 0.0f, 1.0f));
+       vertices.push_back(Vec4( 1.0f, -1.0f, 0.0f, 1.0f));
+       vertices.push_back(Vec4( 1.0f,  1.0f, 0.0f, 1.0f));
+       vertices.push_back(Vec4(-1.0f,  1.0f, 0.0f, 1.0f));
+       return vertices;
+ }
+ struct Vertex
+ {
+       Vertex(Vec4 vertices_) : vertices(vertices_) {}
+       Vec4 vertices;
+       static VkVertexInputBindingDescription                          getBindingDescription           (void);
+       static vector<VkVertexInputAttributeDescription>        getAttributeDescriptions        (void);
+ };
+ VkVertexInputBindingDescription Vertex::getBindingDescription (void)
+ {
+       static const VkVertexInputBindingDescription desc =
+       {
+               0u,                                                                             // deUint32             binding;
+               static_cast<deUint32>(sizeof(Vertex)),  // deUint32             stride;
+               VK_VERTEX_INPUT_RATE_VERTEX,                    // VkVertexInputRate    inputRate;
+       };
+       return desc;
+ }
+ vector<VkVertexInputAttributeDescription> Vertex::getAttributeDescriptions (void)
+ {
+       static const vector<VkVertexInputAttributeDescription> desc =
+       {
+               {
+                       0u,                                                                                                     // deUint32    location;
+                       0u,                                                                                                     // deUint32    binding;
+                       VK_FORMAT_R32G32B32A32_SFLOAT,                                          // VkFormat    format;
+                       static_cast<deUint32>(offsetof(Vertex, vertices)),      // deUint32    offset;
+               },
+       };
+       return desc;
+ }
+ tcu::TestStatus SynchronizationImageLayoutTransitionTestInstance::iterate (void)
+ {
+       const DeviceInterface&                                          vk                                              = m_context.getDeviceInterface();
+       const VkDevice                                                          device                                  = m_context.getDevice();
+       Allocator&                                                                      allocator                               = m_context.getDefaultAllocator();
+       const VkQueue                                                           queue                                   = m_context.getUniversalQueue();
+       const deUint32                                                          queueFamilyIndex                = m_context.getUniversalQueueFamilyIndex();
+       const VkDeviceSize                                                      bufferSize                              = 16 * 1024;
+       const VkExtent2D                                                        renderSize                              = {deUint32(WIDTH), deUint32(HEIGHT)};
+       const VkRect2D                                                          renderArea                              = makeRect2D(makeExtent3D(WIDTH, HEIGHT, 1u));
+       const vector<VkRect2D>                                          scissors                                (1u, renderArea);
+       const vector<VkViewport>                                        viewports                               (1u, makeViewport(makeExtent3D(WIDTH, HEIGHT, 1u)));
+       const vector<Vec4>                                                      vertices                                = genFullQuadVertices();
+       Move<VkBuffer>                                                          vertexBuffer                    = makeVertexBuffer(vk, device, queueFamilyIndex);
+       MovePtr<Allocation>                                                     vertexBufferAlloc               = bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible);
+       const VkDeviceSize                                                      vertexBufferOffset              = 0ull;
+       deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], sizeInBytes(vertices));
+       flushAlloc(vk, device, *vertexBufferAlloc);
+       const VkImageCreateInfo                                         targetCreateInfo                = makeImageCreateInfo();
+       const VkImageSubresourceRange                           targetSubresourceRange  = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1, 0, 1);
+       const ImageWithMemory                                           targetImage                             (vk, device, m_context.getDefaultAllocator(), targetCreateInfo, MemoryRequirement::Any);
+       Move<VkImageView>                                                       targetImageView                 = makeImageView(vk, device, *targetImage, VK_IMAGE_VIEW_TYPE_2D, FORMAT, targetSubresourceRange);
+       const Move<VkCommandPool>                                       cmdPool                                 = createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
+       const Move<VkCommandBuffer>                                     cmdBuffer                               = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
+       Move<VkRenderPass>                                                      renderPass                              = makeRenderPass(vk, device, FORMAT, VK_FORMAT_UNDEFINED, VK_ATTACHMENT_LOAD_OP_LOAD);
+       Move<VkFramebuffer>                                                     framebuffer                             = makeFramebuffer(vk, device, *renderPass, targetImageView.get(), renderSize.width, renderSize.height);
+       const Move<VkShaderModule>                                      vertexModule                    = createShaderModule (vk, device, m_context.getBinaryCollection().get("vert1"), 0u);
+       const Move<VkShaderModule>                                      fragmentModule                  = createShaderModule (vk, device, m_context.getBinaryCollection().get("frag1"), 0u);
+       const Move<VkPipelineLayout>                            pipelineLayout                  = makePipelineLayout (vk, device, DE_NULL);
+       const VkPipelineColorBlendAttachmentState       clrBlendAttachmentState =
+       {
+               VK_TRUE,                                                                // VkBool32                 blendEnable;
+               VK_BLEND_FACTOR_SRC_ALPHA,                              // VkBlendFactor            srcColorBlendFactor;
+               VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,    // VkBlendFactor            dstColorBlendFactor;
+               VK_BLEND_OP_ADD,                                                // VkBlendOp                colorBlendOp;
+               VK_BLEND_FACTOR_ONE,                                    // VkBlendFactor            srcAlphaBlendFactor;
+               VK_BLEND_FACTOR_ONE,                                    // VkBlendFactor            dstAlphaBlendFactor;
+               VK_BLEND_OP_MAX,                                                // VkBlendOp                alphaBlendOp;
+               (VkColorComponentFlags)0xF                              // VkColorComponentFlags    colorWriteMask;
+       };
+       const VkPipelineColorBlendStateCreateInfo       clrBlendStateCreateInfo =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,       // VkStructureType                               sType;
+               DE_NULL,                                                                                                        // const void*                                   pNext;
+               (VkPipelineColorBlendStateCreateFlags)0u,                                       // VkPipelineColorBlendStateCreateFlags          flags;
+               VK_FALSE,                                                                                                       // VkBool32                                      logicOpEnable;
+               VK_LOGIC_OP_CLEAR,                                                                                      // VkLogicOp                                     logicOp;
+               1u,                                                                                                                     // deUint32                                      attachmentCount;
+               &clrBlendAttachmentState,                                                                       // const VkPipelineColorBlendAttachmentState*    pAttachments;
+               { 1.0f, 1.0f, 1.0f, 1.0f }                                                                      // float                                         blendConstants[4];
+       };
+       const VkVertexInputBindingDescription           vtxBindingDescription   = Vertex::getBindingDescription();
+       const auto                                                                      vtxAttrDescriptions             = Vertex::getAttributeDescriptions();
+       const VkPipelineVertexInputStateCreateInfo      vtxInputStateCreateInfo =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,      // VkStructureType                             sType;
+               DE_NULL,                                                                                                        // const void*                                 pNext;
+               (VkPipelineVertexInputStateCreateFlags)0,                                       // VkPipelineVertexInputStateCreateFlags       flags;
+               1u,                                                                                                                     // deUint32                                    vertexBindingDescriptionCount;
+               &vtxBindingDescription,                                                                         // const VkVertexInputBindingDescription*      pVertexBindingDescriptions
+               static_cast<deUint32>(vtxAttrDescriptions.size()),                      // deUint32                                    vertexAttributeDescriptionCount
+               vtxAttrDescriptions.data(),                                                                     // const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions
+       };
+       const Move<VkPipeline>                                          graphicsPipeline                = makeGraphicsPipeline(vk, device, pipelineLayout.get(), vertexModule.get(), DE_NULL, DE_NULL,
+                                                                                                                                                                                          DE_NULL, fragmentModule.get(), renderPass.get(),
+                                                                                                                                                                                          viewports, scissors, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
+                                                                                                                                                                                          0u, 0u, &vtxInputStateCreateInfo, DE_NULL,
+                                                                                                                                                                                          DE_NULL, DE_NULL, &clrBlendStateCreateInfo);
+       const VkBufferCreateInfo                                        resultBufferCreateInfo  = makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
+       Move<VkBuffer>                                                          resultBuffer                    = createBuffer(vk, device, &resultBufferCreateInfo);
+       MovePtr<Allocation>                                                     resultBufferMemory              = allocator.allocate(getBufferMemoryRequirements(vk, device, *resultBuffer), MemoryRequirement::HostVisible);
+       MovePtr<TextureLevel>                                           resultImage                             (new TextureLevel(mapVkFormat(FORMAT), renderSize.width, renderSize.height, 1));
+       VK_CHECK(vk.bindBufferMemory(device, *resultBuffer, resultBufferMemory->getMemory(), resultBufferMemory->getOffset()));
+       const Vec4                                                                      clearColor                              (0.0f, 0.0f, 0.0f, 0.0f);
+       clearColorImage(vk, device, m_context.getUniversalQueue(), m_context.getUniversalQueueFamilyIndex(),
+                                       targetImage.get(), clearColor, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+                                       VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 1);
+       beginCommandBuffer(vk, *cmdBuffer);
+       vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
+       vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
+       beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, WIDTH, HEIGHT), 0, DE_NULL);
+       vk.cmdDraw(*cmdBuffer, static_cast<deUint32>(vertices.size()), 1u, 0u, 0u);
+       endRenderPass(vk, *cmdBuffer);
+       // Define an execution dependency and skip the layout transition. This is allowed when oldLayout
+       // and newLayout are both UNDEFINED. The test will fail if the driver discards the contents of
+       // the image.
+       const VkImageMemoryBarrier2KHR                          imageMemoryBarrier2             = makeImageMemoryBarrier2(
+               VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,  // VkPipelineStageFlags2KHR    srcStageMask
+               VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,                   // VkAccessFlags2KHR           srcAccessMask
+               VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,  // VkPipelineStageFlags2KHR    dstStageMask
+               VK_ACCESS_COLOR_ATTACHMENT_READ_BIT,                    // VkAccessFlags2KHR           dstAccessMask
+               VK_IMAGE_LAYOUT_UNDEFINED,                                              // VkImageLayout               oldLayout
+               VK_IMAGE_LAYOUT_UNDEFINED,                                              // VkImageLayout               newLayout
+               targetImage.get(),                                                              // VkImage                     image
+               targetSubresourceRange                                                  // VkImageSubresourceRange     subresourceRange
+       );
+       VkDependencyInfoKHR                                                     dependencyInfo                  = makeCommonDependencyInfo(DE_NULL, DE_NULL, &imageMemoryBarrier2);
++      vk.cmdPipelineBarrier2(cmdBuffer.get(), &dependencyInfo);
+       beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, WIDTH, HEIGHT), 0, DE_NULL);
+       vk.cmdDraw(*cmdBuffer, static_cast<deUint32>(vertices.size()), 1u, 0u, 0u);
+       endRenderPass(vk, *cmdBuffer);
+       // Read the result buffer data
+       copyImageToBuffer(vk, *cmdBuffer, *targetImage, *resultBuffer, tcu::IVec2(WIDTH, HEIGHT), VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
+       endCommandBuffer(vk, *cmdBuffer);
+       submitCommandsAndWait(vk, device, queue, *cmdBuffer);
+       invalidateAlloc(vk, device, *resultBufferMemory);
+       tcu::clear(resultImage->getAccess(), tcu::IVec4(0));
+       tcu::copy(resultImage->getAccess(), tcu::ConstPixelBufferAccess(resultImage.get()->getFormat(),
+                         resultImage.get()->getSize(), resultBufferMemory->getHostPtr()));
+       TextureLevel                                                            textureLevel                    (mapVkFormat(FORMAT), WIDTH, HEIGHT, 1);
+       const tcu::PixelBufferAccess                            expectedImage                   = textureLevel.getAccess();
+       const float                                                                     alpha                                   = 0.4f;
+       const float                                                                     red                                             = (2.0f - alpha) * alpha;
+       const float                                                                     green                                   = red;
+       const float                                                                     blue                                    = 0;
+       const Vec4                                                                      color                                   = Vec4(red, green, blue, alpha);
+       for (int y = 0; y < HEIGHT; y++)
+               for (int x = 0; x < WIDTH; x++)
+                       expectedImage.setPixel(color, x, y, 0);
+       bool ok = tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Image comparison", "", expectedImage, resultImage->getAccess(), tcu::Vec4(0.01f), tcu::COMPARE_LOG_RESULT);
+       return ok ? tcu::TestStatus::pass("Pass") : tcu::TestStatus::fail("Fail");
+ }
+ class SynchronizationImageLayoutTransitionTest : public TestCase
+ {
+ public:
+                                               SynchronizationImageLayoutTransitionTest        (tcu::TestContext&      testCtx,
+                                                                                                                                        const std::string&     name,
+                                                                                                                                        const std::string&     description);
+       virtual void            checkSupport                                                            (Context&                       context) const;
+       void                            initPrograms                                                            (SourceCollections& programCollection) const;
+       TestInstance*           createInstance                                                          (Context&                       context) const;
+ };
+ SynchronizationImageLayoutTransitionTest::SynchronizationImageLayoutTransitionTest (tcu::TestContext& testCtx,
+                                                                                                                                                                       const std::string&      name,
+                                                                                                                                                                       const std::string&      description)
+       : TestCase      (testCtx, name, description)
+ {
+ }
+ void SynchronizationImageLayoutTransitionTest::initPrograms (SourceCollections& programCollection) const
+ {
+       std::ostringstream vertexSrc;
+       vertexSrc
+               << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
+               << "layout(location = 0) in vec4 a_position;\n"
+               << "void main (void) {\n"
+               << "    gl_Position = a_position;\n"
+               << "}\n";
+       std::ostringstream fragmentSrc;
+       fragmentSrc
+               << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
+               << "layout(location = 0) out vec4 outColor;\n"
+               << "void main() {\n"
+               << "    outColor = vec4(1., 1., 0., .4);\n"
+               << "}\n";
+       programCollection.glslSources.add("vert1") << glu::VertexSource(vertexSrc.str());
+       programCollection.glslSources.add("frag1") << glu::FragmentSource(fragmentSrc.str());
+ }
+ void SynchronizationImageLayoutTransitionTest::checkSupport (Context& context) const
+ {
+       context.requireDeviceFunctionality("VK_KHR_synchronization2");
+ }
+ TestInstance* SynchronizationImageLayoutTransitionTest::createInstance (Context& context) const
+ {
+       return new SynchronizationImageLayoutTransitionTestInstance(context);
+ }
+ } // anonymous ns
+ tcu::TestCaseGroup* createImageLayoutTransitionTests  (tcu::TestContext& testCtx)
+ {
+       de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "layout_transition", "No-op image layout transition tests"));
+       testGroup->addChild(new SynchronizationImageLayoutTransitionTest(testCtx, "no_op", ""));
+       return testGroup.release();
+ }
+ } // synchronization
+ } // vkt
@@@ -98,23 -98,10 +98,24 @@@ VK_EXT_multi_draw                                                  DEVIC
  VK_KHR_shader_subgroup_uniform_control_flow   DEVICE
  VK_KHR_present_id                                                     DEVICE
  VK_KHR_present_wait                                                   DEVICE
 -VK_KHR_shader_integer_dot_product                     DEVICE
 -VK_KHR_format_feature_flags2                          DEVICE
 -VK_KHR_maintenance4                                                   DEVICE
 -VK_KHR_dynamic_rendering                                      DEVICE
 +VK_KHR_format_feature_flags2                          DEVICE 1_3_0
 +VK_KHR_maintenance4                                                   DEVICE 1_3_0
 +VK_KHR_dynamic_rendering                                      DEVICE 1_3_0
 +VK_EXT_extended_dynamic_state                         DEVICE 1_3_0
 +VK_EXT_extended_dynamic_state2                                DEVICE
 +VK_EXT_4444_formats                                                   DEVICE 1_3_0
 +VK_KHR_shader_integer_dot_product                     DEVICE 1_3_0
 +VK_EXT_image_robustness                                               DEVICE 1_3_0
 +VK_EXT_inline_uniform_block                                   DEVICE 1_3_0
 +VK_EXT_pipeline_creation_cache_control                DEVICE 1_3_0
 +VK_EXT_pipeline_creation_feedback                     DEVICE 1_3_0
 +VK_EXT_private_data                                                   DEVICE 1_3_0
 +VK_EXT_shader_demote_to_helper_invocation     DEVICE 1_3_0
 +VK_EXT_subgroup_size_control                          DEVICE 1_3_0
 +VK_EXT_texel_buffer_alignment                         DEVICE 1_3_0
 +VK_EXT_texture_compression_astc_hdr                   DEVICE 1_3_0
 +VK_EXT_tooling_info                                                   DEVICE 1_3_0
 +VK_EXT_ycbcr_2plane_444_formats                               DEVICE
  VK_EXT_border_color_swizzle                                   DEVICE
  VK_NV_mesh_shader                                                     DEVICE
+ VK_KHR_portability_subset                                     DEVICE