Use proper image tiling in synchronization test support checks
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / synchronization / vktSynchronizationUtil.cpp
index ac2c7ae..9b6c58d 100644 (file)
@@ -24,7 +24,9 @@
 #include "vktSynchronizationUtil.hpp"
 #include "vkTypeUtil.hpp"
 #include "vkCmdUtil.hpp"
+#include "vkBarrierUtil.hpp"
 #include "deStringUtil.hpp"
+#include <set>
 #include <limits>
 
 namespace vkt
@@ -85,9 +87,14 @@ Move<VkPipeline> makeComputePipeline (const DeviceInterface&         vk,
        }
 }
 
-VkImageCreateInfo makeImageCreateInfo (const VkImageType imageType, const VkExtent3D& extent, const VkFormat format, const VkImageUsageFlags usage)
+VkImageCreateInfo makeImageCreateInfo (const VkImageType                       imageType,
+                                                                          const VkExtent3D&                    extent,
+                                                                          const VkFormat                               format,
+                                                                          const VkImageUsageFlags              usage,
+                                                                          const VkSampleCountFlagBits  samples,
+                                                                          const VkImageTiling                  tiling)
 {
-       const VkImageCreateInfo imageInfo =
+       return
        {
                VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,            // VkStructureType          sType;
                DE_NULL,                                                                        // const void*              pNext;
@@ -97,15 +104,14 @@ VkImageCreateInfo makeImageCreateInfo (const VkImageType imageType, const VkExte
                extent,                                                                         // VkExtent3D               extent;
                1u,                                                                                     // uint32_t                 mipLevels;
                1u,                                                                                     // uint32_t                 arrayLayers;
-               VK_SAMPLE_COUNT_1_BIT,                                          // VkSampleCountFlagBits    samples;
-               VK_IMAGE_TILING_OPTIMAL,                                        // VkImageTiling            tiling;
+               samples,                                                                        // VkSampleCountFlagBits    samples;
+               tiling,                                                                         // VkImageTiling            tiling;
                usage,                                                                          // VkImageUsageFlags        usage;
                VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode            sharingMode;
                0u,                                                                                     // uint32_t                 queueFamilyIndexCount;
                DE_NULL,                                                                        // const uint32_t*          pQueueFamilyIndices;
                VK_IMAGE_LAYOUT_UNDEFINED,                                      // VkImageLayout            initialLayout;
        };
-       return imageInfo;
 }
 
 void beginRenderPassWithRasterizationDisabled (const DeviceInterface&  vk,
@@ -375,6 +381,591 @@ Move<VkPipeline> GraphicsPipelineBuilder::build (const DeviceInterface&   vk,
        }
 }
 
+// Uses some structures added by VK_KHR_synchronization2 to fill legacy structures.
+// With this approach we dont have to create branch in each test (one for legacy
+// second for new synchronization), this helps to reduce code of some tests.
+class LegacySynchronizationWrapper : public SynchronizationWrapperBase
+{
+protected:
+
+       struct SubmitInfoData
+       {
+               deUint32                waitSemaphoreCount;
+               std::size_t             waitSemaphoreIndex;
+               std::size_t             waitSemaphoreValueIndexPlusOne;
+               deUint32                commandBufferCount;
+               deUint32                commandBufferIndex;
+               deUint32                signalSemaphoreCount;
+               std::size_t             signalSemaphoreIndex;
+               std::size_t             signalSemaphoreValueIndexPlusOne;
+       };
+
+       bool isStageFlagAllowed(VkPipelineStageFlags2KHR stage) const
+       {
+               // synchronization2 suports more stages then legacy synchronization
+               // and so SynchronizationWrapper can only be used for cases that
+               // operate on stages also supported by legacy synchronization
+               // NOTE: if some tests hits assertion that uses this method then this
+               // test should not use synchronizationWrapper - it should be synchronization2 exclusive
+
+               static const std::set<deUint32> allowedStages
+               {
+                       VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+                       VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT,
+                       VK_PIPELINE_STAGE_VERTEX_INPUT_BIT,
+                       VK_PIPELINE_STAGE_VERTEX_SHADER_BIT,
+                       VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT,
+                       VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT,
+                       VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT,
+                       VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
+                       VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,
+                       VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
+                       VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
+                       VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
+                       VK_PIPELINE_STAGE_TRANSFER_BIT,
+                       VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
+                       VK_PIPELINE_STAGE_HOST_BIT,
+                       VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
+                       VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
+                       VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT,
+                       VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT,
+                       VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR,
+                       VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR,
+                       VK_PIPELINE_STAGE_SHADING_RATE_IMAGE_BIT_NV,
+                       VK_PIPELINE_STAGE_TASK_SHADER_BIT_NV,
+                       VK_PIPELINE_STAGE_MESH_SHADER_BIT_NV,
+                       VK_PIPELINE_STAGE_FRAGMENT_DENSITY_PROCESS_BIT_EXT,
+                       VK_PIPELINE_STAGE_COMMAND_PREPROCESS_BIT_NV,
+                       VK_PIPELINE_STAGE_NONE_KHR,
+               };
+
+               if (stage > static_cast<deUint64>(std::numeric_limits<deUint32>::max()))
+                       return false;
+
+               return (allowedStages.find(static_cast<deUint32>(stage)) != allowedStages.end());
+       }
+
+       bool isAccessFlagAllowed(VkAccessFlags2KHR access) const
+       {
+               // synchronization2 suports more access flags then legacy synchronization
+               // and so SynchronizationWrapper can only be used for cases that
+               // operate on access flags also supported by legacy synchronization
+               // NOTE: if some tests hits assertion that uses this method then this
+               // test should not use synchronizationWrapper - it should be synchronization2 exclusive
+
+               static const std::set<deUint32> allowedAccessFlags
+               {
+                       VK_ACCESS_INDIRECT_COMMAND_READ_BIT,
+                       VK_ACCESS_INDEX_READ_BIT,
+                       VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT,
+                       VK_ACCESS_UNIFORM_READ_BIT,
+                       VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
+                       VK_ACCESS_SHADER_READ_BIT,
+                       VK_ACCESS_SHADER_WRITE_BIT,
+                       VK_ACCESS_COLOR_ATTACHMENT_READ_BIT,
+                       VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
+                       VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
+                       VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
+                       VK_ACCESS_TRANSFER_READ_BIT,
+                       VK_ACCESS_TRANSFER_WRITE_BIT,
+                       VK_ACCESS_HOST_READ_BIT,
+                       VK_ACCESS_HOST_WRITE_BIT,
+                       VK_ACCESS_MEMORY_READ_BIT,
+                       VK_ACCESS_MEMORY_WRITE_BIT,
+                       VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT,
+                       VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT,
+                       VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT,
+                       VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT,
+                       VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT,
+                       VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR,
+                       VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR,
+                       VK_ACCESS_SHADING_RATE_IMAGE_READ_BIT_NV ,
+                       VK_ACCESS_FRAGMENT_DENSITY_MAP_READ_BIT_EXT,
+                       VK_ACCESS_COMMAND_PREPROCESS_READ_BIT_NV,
+                       VK_ACCESS_COMMAND_PREPROCESS_WRITE_BIT_NV,
+                       VK_ACCESS_NONE_KHR,
+               };
+
+               if (access > static_cast<deUint64>(std::numeric_limits<deUint32>::max()))
+                       return false;
+
+               return (allowedAccessFlags.find(static_cast<deUint32>(access)) != allowedAccessFlags.end());
+       }
+
+public:
+       LegacySynchronizationWrapper(const DeviceInterface& vk, bool usingTimelineSemaphores, deUint32 submitInfoCount = 1u)
+               : SynchronizationWrapperBase    (vk)
+               , m_submited                                    (DE_FALSE)
+       {
+               m_waitSemaphores.reserve(submitInfoCount);
+               m_signalSemaphores.reserve(submitInfoCount);
+               m_waitDstStageMasks.reserve(submitInfoCount);
+               m_commandBuffers.reserve(submitInfoCount);
+               m_submitInfoData.reserve(submitInfoCount);
+
+               if (usingTimelineSemaphores)
+                       m_timelineSemaphoreValues.reserve(2 * submitInfoCount);
+       }
+
+       ~LegacySynchronizationWrapper() = default;
+
+       void addSubmitInfo(deUint32                                                             waitSemaphoreInfoCount,
+                                          const VkSemaphoreSubmitInfoKHR*              pWaitSemaphoreInfos,
+                                          deUint32                                                             commandBufferInfoCount,
+                                          const VkCommandBufferSubmitInfoKHR*  pCommandBufferInfos,
+                                          deUint32                                                             signalSemaphoreInfoCount,
+                                          const VkSemaphoreSubmitInfoKHR*              pSignalSemaphoreInfos,
+                                          bool                                                                 usingWaitTimelineSemaphore,
+                                          bool                                                                 usingSignalTimelineSemaphore) override
+       {
+               m_submitInfoData.push_back(SubmitInfoData{ waitSemaphoreInfoCount, 0, 0, commandBufferInfoCount, 0u, signalSemaphoreInfoCount, 0, 0 });
+               SubmitInfoData& si = m_submitInfoData.back();
+
+               // memorize wait values
+               if (usingWaitTimelineSemaphore)
+               {
+                       DE_ASSERT(pWaitSemaphoreInfos);
+                       si.waitSemaphoreValueIndexPlusOne = m_timelineSemaphoreValues.size() + 1;
+                       for (deUint32 i = 0; i < waitSemaphoreInfoCount; ++i)
+                               m_timelineSemaphoreValues.push_back(pWaitSemaphoreInfos[i].value);
+               }
+
+               // memorize signal values
+               if (usingSignalTimelineSemaphore)
+               {
+                       DE_ASSERT(pSignalSemaphoreInfos);
+                       si.signalSemaphoreValueIndexPlusOne = m_timelineSemaphoreValues.size() + 1;
+                       for (deUint32 i = 0; i < signalSemaphoreInfoCount; ++i)
+                               m_timelineSemaphoreValues.push_back(pSignalSemaphoreInfos[i].value);
+               }
+
+               // construct list of semaphores that we need to wait on
+               if (waitSemaphoreInfoCount)
+               {
+                       si.waitSemaphoreIndex = m_waitSemaphores.size();
+                       for (deUint32 i = 0; i < waitSemaphoreInfoCount; ++i)
+                       {
+                               DE_ASSERT(isStageFlagAllowed(pWaitSemaphoreInfos[i].stageMask));
+                               m_waitSemaphores.push_back(pWaitSemaphoreInfos[i].semaphore);
+                               m_waitDstStageMasks.push_back(static_cast<VkPipelineStageFlags>(pWaitSemaphoreInfos[i].stageMask));
+                       }
+               }
+
+               // construct list of command buffers
+               if (commandBufferInfoCount)
+               {
+                       si.commandBufferIndex = static_cast<deUint32>(m_commandBuffers.size());
+                       for (deUint32 i = 0; i < commandBufferInfoCount; ++i)
+                               m_commandBuffers.push_back(pCommandBufferInfos[i].commandBuffer);
+               }
+
+               // construct list of semaphores that will be signaled
+               if (signalSemaphoreInfoCount)
+               {
+                       si.signalSemaphoreIndex = m_signalSemaphores.size();
+                       for (deUint32 i = 0; i < signalSemaphoreInfoCount; ++i)
+                               m_signalSemaphores.push_back(pSignalSemaphoreInfos[i].semaphore);
+               }
+       }
+
+       void cmdPipelineBarrier(VkCommandBuffer commandBuffer, const VkDependencyInfoKHR* pDependencyInfo) const override
+       {
+               DE_ASSERT(pDependencyInfo);
+
+               VkPipelineStageFlags    srcStageMask                            = VK_PIPELINE_STAGE_NONE_KHR;
+               VkPipelineStageFlags    dstStageMask                            = VK_PIPELINE_STAGE_NONE_KHR;
+               deUint32                                memoryBarrierCount                      = pDependencyInfo->memoryBarrierCount;
+               VkMemoryBarrier*                pMemoryBarriers                         = DE_NULL;
+               deUint32                                bufferMemoryBarrierCount        = pDependencyInfo->bufferMemoryBarrierCount;
+               VkBufferMemoryBarrier*  pBufferMemoryBarriers           = DE_NULL;
+               deUint32                                imageMemoryBarrierCount         = pDependencyInfo->imageMemoryBarrierCount;
+               VkImageMemoryBarrier*   pImageMemoryBarriers            = DE_NULL;
+
+               // translate VkMemoryBarrier2KHR to VkMemoryBarrier
+               std::vector<VkMemoryBarrier> memoryBarriers;
+               if (memoryBarrierCount)
+               {
+                       memoryBarriers.reserve(memoryBarrierCount);
+                       for (deUint32 i = 0; i < memoryBarrierCount; ++i)
+                       {
+                               const VkMemoryBarrier2KHR& pMemoryBarrier = pDependencyInfo->pMemoryBarriers[i];
+
+                               DE_ASSERT(isStageFlagAllowed(pMemoryBarrier.srcStageMask));
+                               DE_ASSERT(isStageFlagAllowed(pMemoryBarrier.dstStageMask));
+                               DE_ASSERT(isAccessFlagAllowed(pMemoryBarrier.srcAccessMask));
+                               DE_ASSERT(isAccessFlagAllowed(pMemoryBarrier.dstAccessMask));
+
+                               srcStageMask |= static_cast<VkPipelineStageFlags>(pMemoryBarrier.srcStageMask);
+                               dstStageMask |= static_cast<VkPipelineStageFlags>(pMemoryBarrier.dstStageMask);
+                               memoryBarriers.push_back(makeMemoryBarrier(
+                                       static_cast<VkAccessFlags>(pMemoryBarrier.srcAccessMask),
+                                       static_cast<VkAccessFlags>(pMemoryBarrier.dstAccessMask)
+                               ));
+                       }
+                       pMemoryBarriers = &memoryBarriers[0];
+               }
+
+               // translate VkBufferMemoryBarrier2KHR to VkBufferMemoryBarrier
+               std::vector<VkBufferMemoryBarrier> bufferMemoryBarriers;
+               if (bufferMemoryBarrierCount)
+               {
+                       bufferMemoryBarriers.reserve(bufferMemoryBarrierCount);
+                       for (deUint32 i = 0; i < bufferMemoryBarrierCount; ++i)
+                       {
+                               const VkBufferMemoryBarrier2KHR& pBufferMemoryBarrier = pDependencyInfo->pBufferMemoryBarriers[i];
+
+                               DE_ASSERT(isStageFlagAllowed(pBufferMemoryBarrier.srcStageMask));
+                               DE_ASSERT(isStageFlagAllowed(pBufferMemoryBarrier.dstStageMask));
+                               DE_ASSERT(isAccessFlagAllowed(pBufferMemoryBarrier.srcAccessMask));
+                               DE_ASSERT(isAccessFlagAllowed(pBufferMemoryBarrier.dstAccessMask));
+
+                               srcStageMask |= static_cast<VkPipelineStageFlags>(pBufferMemoryBarrier.srcStageMask);
+                               dstStageMask |= static_cast<VkPipelineStageFlags>(pBufferMemoryBarrier.dstStageMask);
+                               bufferMemoryBarriers.push_back(makeBufferMemoryBarrier(
+                                       static_cast<VkAccessFlags>(pBufferMemoryBarrier.srcAccessMask),
+                                       static_cast<VkAccessFlags>(pBufferMemoryBarrier.dstAccessMask),
+                                       pBufferMemoryBarrier.buffer,
+                                       pBufferMemoryBarrier.offset,
+                                       pBufferMemoryBarrier.size,
+                                       pBufferMemoryBarrier.srcQueueFamilyIndex,
+                                       pBufferMemoryBarrier.dstQueueFamilyIndex
+                               ));
+                       }
+                       pBufferMemoryBarriers = &bufferMemoryBarriers[0];
+               }
+
+               // translate VkImageMemoryBarrier2KHR to VkImageMemoryBarrier
+               std::vector<VkImageMemoryBarrier> imageMemoryBarriers;
+               if (imageMemoryBarrierCount)
+               {
+                       imageMemoryBarriers.reserve(imageMemoryBarrierCount);
+                       for (deUint32 i = 0; i < imageMemoryBarrierCount; ++i)
+                       {
+                               const VkImageMemoryBarrier2KHR& pImageMemoryBarrier = pDependencyInfo->pImageMemoryBarriers[i];
+
+                               DE_ASSERT(isStageFlagAllowed(pImageMemoryBarrier.srcStageMask));
+                               DE_ASSERT(isStageFlagAllowed(pImageMemoryBarrier.dstStageMask));
+                               DE_ASSERT(isAccessFlagAllowed(pImageMemoryBarrier.srcAccessMask));
+                               DE_ASSERT(isAccessFlagAllowed(pImageMemoryBarrier.dstAccessMask));
+
+                               srcStageMask |= static_cast<VkPipelineStageFlags>(pImageMemoryBarrier.srcStageMask);
+                               dstStageMask |= static_cast<VkPipelineStageFlags>(pImageMemoryBarrier.dstStageMask);
+                               imageMemoryBarriers.push_back(makeImageMemoryBarrier(
+                                       static_cast<VkAccessFlags>(pImageMemoryBarrier.srcAccessMask),
+                                       static_cast<VkAccessFlags>(pImageMemoryBarrier.dstAccessMask),
+                                       pImageMemoryBarrier.oldLayout,
+                                       pImageMemoryBarrier.newLayout,
+                                       pImageMemoryBarrier.image,
+                                       pImageMemoryBarrier.subresourceRange,
+                                       pImageMemoryBarrier.srcQueueFamilyIndex,
+                                       pImageMemoryBarrier.dstQueueFamilyIndex
+                               ));
+                       }
+                       pImageMemoryBarriers = &imageMemoryBarriers[0];
+               }
+
+               m_vk.cmdPipelineBarrier(
+                       commandBuffer,
+                       srcStageMask,
+                       dstStageMask,
+                       (VkDependencyFlags)0,
+                       memoryBarrierCount,
+                       pMemoryBarriers,
+                       bufferMemoryBarrierCount,
+                       pBufferMemoryBarriers,
+                       imageMemoryBarrierCount,
+                       pImageMemoryBarriers
+               );
+       }
+
+       void cmdSetEvent(VkCommandBuffer commandBuffer, VkEvent event, const VkDependencyInfoKHR* pDependencyInfo) const override
+       {
+               DE_ASSERT(pDependencyInfo);
+
+               VkPipelineStageFlags2KHR srcStageMask = VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR;
+               if (pDependencyInfo->pMemoryBarriers)
+                       srcStageMask = pDependencyInfo->pMemoryBarriers[0].srcStageMask;
+               if (pDependencyInfo->pBufferMemoryBarriers)
+                       srcStageMask = pDependencyInfo->pBufferMemoryBarriers[0].srcStageMask;
+               if (pDependencyInfo->pImageMemoryBarriers)
+                       srcStageMask = pDependencyInfo->pImageMemoryBarriers[0].srcStageMask;
+
+               DE_ASSERT(isStageFlagAllowed(srcStageMask));
+               m_vk.cmdSetEvent(commandBuffer, event, static_cast<VkPipelineStageFlags>(srcStageMask));
+       }
+
+       void cmdResetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags2KHR flag) const override
+       {
+               DE_ASSERT(isStageFlagAllowed(flag));
+               VkPipelineStageFlags legacyStageMask = static_cast<VkPipelineStageFlags>(flag);
+               m_vk.cmdResetEvent(commandBuffer, event, legacyStageMask);
+       }
+
+       void cmdWaitEvents(VkCommandBuffer commandBuffer, deUint32 eventCount, const VkEvent* pEvents, const VkDependencyInfoKHR* pDependencyInfo) const override
+       {
+               DE_ASSERT(pDependencyInfo);
+
+               VkPipelineStageFlags2KHR                        srcStageMask                            = VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR;
+               VkPipelineStageFlags2KHR                        dstStageMask                            = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT_KHR;
+               deUint32                                                        memoryBarrierCount                      = pDependencyInfo->memoryBarrierCount;
+               deUint32                                                        bufferMemoryBarrierCount        = pDependencyInfo->bufferMemoryBarrierCount;
+               deUint32                                                        imageMemoryBarrierCount         = pDependencyInfo->imageMemoryBarrierCount;
+               VkMemoryBarrier*                                        pMemoryBarriers                         = DE_NULL;
+               VkBufferMemoryBarrier*                          pBufferMemoryBarriers           = DE_NULL;
+               VkImageMemoryBarrier*                           pImageMemoryBarriers            = DE_NULL;
+               std::vector<VkMemoryBarrier>            memoryBarriers;
+               std::vector<VkBufferMemoryBarrier>      bufferMemoryBarriers;
+               std::vector<VkImageMemoryBarrier>       imageMemoryBarriers;
+
+               if (pDependencyInfo->pMemoryBarriers)
+               {
+                       srcStageMask = pDependencyInfo->pMemoryBarriers[0].srcStageMask;
+                       dstStageMask = pDependencyInfo->pMemoryBarriers[0].dstStageMask;
+
+                       memoryBarriers.reserve(memoryBarrierCount);
+                       for (deUint32 i = 0; i < memoryBarrierCount; ++i)
+                       {
+                               const VkMemoryBarrier2KHR& mb = pDependencyInfo->pMemoryBarriers[i];
+                               DE_ASSERT(isAccessFlagAllowed(mb.srcAccessMask));
+                               DE_ASSERT(isAccessFlagAllowed(mb.dstAccessMask));
+                               memoryBarriers.push_back(
+                                       makeMemoryBarrier(
+                                               static_cast<VkAccessFlags>(mb.srcAccessMask),
+                                               static_cast<VkAccessFlags>(mb.dstAccessMask)
+                                       )
+                               );
+                       }
+                       pMemoryBarriers = &memoryBarriers[0];
+               }
+               if (pDependencyInfo->pBufferMemoryBarriers)
+               {
+                       srcStageMask = pDependencyInfo->pBufferMemoryBarriers[0].srcStageMask;
+                       dstStageMask = pDependencyInfo->pBufferMemoryBarriers[0].dstStageMask;
+
+                       bufferMemoryBarriers.reserve(bufferMemoryBarrierCount);
+                       for (deUint32 i = 0; i < bufferMemoryBarrierCount; ++i)
+                       {
+                               const VkBufferMemoryBarrier2KHR& bmb = pDependencyInfo->pBufferMemoryBarriers[i];
+                               DE_ASSERT(isAccessFlagAllowed(bmb.srcAccessMask));
+                               DE_ASSERT(isAccessFlagAllowed(bmb.dstAccessMask));
+                               bufferMemoryBarriers.push_back(
+                                       makeBufferMemoryBarrier(
+                                               static_cast<VkAccessFlags>(bmb.srcAccessMask),
+                                               static_cast<VkAccessFlags>(bmb.dstAccessMask),
+                                               bmb.buffer,
+                                               bmb.offset,
+                                               bmb.size,
+                                               bmb.srcQueueFamilyIndex,
+                                               bmb.dstQueueFamilyIndex
+                                       )
+                               );
+                       }
+                       pBufferMemoryBarriers = &bufferMemoryBarriers[0];
+               }
+               if (pDependencyInfo->pImageMemoryBarriers)
+               {
+                       srcStageMask = pDependencyInfo->pImageMemoryBarriers[0].srcStageMask;
+                       dstStageMask = pDependencyInfo->pImageMemoryBarriers[0].dstStageMask;
+
+                       imageMemoryBarriers.reserve(imageMemoryBarrierCount);
+                       for (deUint32 i = 0; i < imageMemoryBarrierCount; ++i)
+                       {
+                               const VkImageMemoryBarrier2KHR& imb = pDependencyInfo->pImageMemoryBarriers[i];
+                               DE_ASSERT(isAccessFlagAllowed(imb.srcAccessMask));
+                               DE_ASSERT(isAccessFlagAllowed(imb.dstAccessMask));
+                               imageMemoryBarriers.push_back(
+                                       makeImageMemoryBarrier(
+                                               static_cast<VkAccessFlags>(imb.srcAccessMask),
+                                               static_cast<VkAccessFlags>(imb.dstAccessMask),
+                                               imb.oldLayout,
+                                               imb.newLayout,
+                                               imb.image,
+                                               imb.subresourceRange,
+                                               imb.srcQueueFamilyIndex,
+                                               imb.dstQueueFamilyIndex
+                                       )
+                               );
+                       }
+                       pImageMemoryBarriers = &imageMemoryBarriers[0];
+               }
+
+               DE_ASSERT(isStageFlagAllowed(srcStageMask));
+               DE_ASSERT(isStageFlagAllowed(dstStageMask));
+               m_vk.cmdWaitEvents(commandBuffer, eventCount, pEvents,
+                       static_cast<VkPipelineStageFlags>(srcStageMask), static_cast<VkPipelineStageFlags>(dstStageMask),
+                       memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers);
+       }
+
+       VkResult queueSubmit(VkQueue queue, VkFence fence) override
+       {
+               // make sure submit info was added
+               DE_ASSERT(!m_submitInfoData.empty());
+
+               // make sure separate LegacySynchronizationWrapper is created per single submit
+               DE_ASSERT(!m_submited);
+
+               std::vector<VkSubmitInfo> submitInfo(m_submitInfoData.size(), { VK_STRUCTURE_TYPE_SUBMIT_INFO, DE_NULL, 0u, DE_NULL, DE_NULL, 0u, DE_NULL, 0u, DE_NULL });
+
+               std::vector<VkTimelineSemaphoreSubmitInfo> timelineSemaphoreSubmitInfo;
+               timelineSemaphoreSubmitInfo.reserve(m_submitInfoData.size());
+
+               // translate indexes from m_submitInfoData to pointers and construct VkSubmitInfo
+               for (deUint32 i = 0; i < m_submitInfoData.size(); ++i)
+               {
+                       auto&                   data    = m_submitInfoData[i];
+                       VkSubmitInfo&   si              = submitInfo[i];
+
+                       si.waitSemaphoreCount   = data.waitSemaphoreCount;
+                       si.commandBufferCount   = data.commandBufferCount;
+                       si.signalSemaphoreCount = data.signalSemaphoreCount;
+
+                       if (data.waitSemaphoreValueIndexPlusOne || data.signalSemaphoreValueIndexPlusOne)
+                       {
+                               deUint64* pWaitSemaphoreValues = DE_NULL;
+                               if (data.waitSemaphoreValueIndexPlusOne)
+                                       pWaitSemaphoreValues = &m_timelineSemaphoreValues[data.waitSemaphoreValueIndexPlusOne - 1];
+
+                               deUint64* pSignalSemaphoreValues = DE_NULL;
+                               if (data.signalSemaphoreValueIndexPlusOne)
+                                       pSignalSemaphoreValues = &m_timelineSemaphoreValues[data.signalSemaphoreValueIndexPlusOne - 1];
+
+                               timelineSemaphoreSubmitInfo.push_back({
+                                       VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO,               // VkStructureType      sType;
+                                       DE_NULL,                                                                                                // const void*          pNext;
+                                       data.waitSemaphoreCount,                                                                // deUint32                     waitSemaphoreValueCount
+                                       pWaitSemaphoreValues,                                                                   // const deUint64*      pWaitSemaphoreValues
+                                       data.signalSemaphoreCount,                                                              // deUint32                     signalSemaphoreValueCount
+                                       pSignalSemaphoreValues                                                                  // const deUint64*      pSignalSemaphoreValues
+                               });
+                               si.pNext = &timelineSemaphoreSubmitInfo.back();
+                       }
+
+                       if (data.waitSemaphoreCount)
+                       {
+                               si.pWaitSemaphores              = &m_waitSemaphores[data.waitSemaphoreIndex];
+                               si.pWaitDstStageMask    = &m_waitDstStageMasks[data.waitSemaphoreIndex];
+                       }
+
+                       if (data.commandBufferCount)
+                               si.pCommandBuffers = &m_commandBuffers[data.commandBufferIndex];
+
+                       if (data.signalSemaphoreCount)
+                               si.pSignalSemaphores = &m_signalSemaphores[data.signalSemaphoreIndex];
+               }
+
+               m_submited = DE_TRUE;
+               return m_vk.queueSubmit(queue, static_cast<deUint32>(submitInfo.size()), &submitInfo[0], fence);
+       }
+
+protected:
+
+       std::vector<VkSemaphore>                        m_waitSemaphores;
+       std::vector<VkSemaphore>                        m_signalSemaphores;
+       std::vector<VkPipelineStageFlags>       m_waitDstStageMasks;
+       std::vector<VkCommandBuffer>            m_commandBuffers;
+       std::vector<SubmitInfoData>                     m_submitInfoData;
+       std::vector<deUint64>                           m_timelineSemaphoreValues;
+       bool                                                            m_submited;
+};
+
+class Synchronization2Wrapper : public SynchronizationWrapperBase
+{
+public:
+       Synchronization2Wrapper(const DeviceInterface& vk, deUint32 submitInfoCount)
+               : SynchronizationWrapperBase(vk)
+       {
+               m_submitInfo.reserve(submitInfoCount);
+       }
+
+       ~Synchronization2Wrapper() = default;
+
+       void addSubmitInfo(deUint32                                                             waitSemaphoreInfoCount,
+                                          const VkSemaphoreSubmitInfoKHR*              pWaitSemaphoreInfos,
+                                          deUint32                                                             commandBufferInfoCount,
+                                          const VkCommandBufferSubmitInfoKHR*  pCommandBufferInfos,
+                                          deUint32                                                             signalSemaphoreInfoCount,
+                                          const VkSemaphoreSubmitInfoKHR*              pSignalSemaphoreInfos,
+                                          bool                                                                 usingWaitTimelineSemaphore,
+                                          bool                                                                 usingSignalTimelineSemaphore) override
+       {
+               DE_UNREF(usingWaitTimelineSemaphore);
+               DE_UNREF(usingSignalTimelineSemaphore);
+
+               m_submitInfo.push_back(VkSubmitInfo2KHR{
+                       VK_STRUCTURE_TYPE_SUBMIT_INFO_2_KHR,            // VkStructureType                                              sType
+                       DE_NULL,                                                                        // const void*                                                  pNext
+                       0u,                                                                                     // VkSubmitFlagsKHR                                             flags
+                       waitSemaphoreInfoCount,                                         // deUint32                                                             waitSemaphoreInfoCount
+                       pWaitSemaphoreInfos,                                            // const VkSemaphoreSubmitInfoKHR*              pWaitSemaphoreInfos
+                       commandBufferInfoCount,                                         // deUint32                                                             commandBufferInfoCount
+                       pCommandBufferInfos,                                            // const VkCommandBufferSubmitInfoKHR*  pCommandBufferInfos
+                       signalSemaphoreInfoCount,                                       // deUint32                                                             signalSemaphoreInfoCount
+                       pSignalSemaphoreInfos                                           // const VkSemaphoreSubmitInfoKHR*              pSignalSemaphoreInfos
+               });
+       }
+
+       void cmdPipelineBarrier(VkCommandBuffer commandBuffer, const VkDependencyInfoKHR* pDependencyInfo) const override
+       {
+               m_vk.cmdPipelineBarrier2KHR(commandBuffer, pDependencyInfo);
+       }
+
+       void cmdSetEvent(VkCommandBuffer commandBuffer, VkEvent event, const VkDependencyInfoKHR* pDependencyInfo) const override
+       {
+               m_vk.cmdSetEvent2KHR(commandBuffer, event, pDependencyInfo);
+       }
+
+       void cmdWaitEvents(VkCommandBuffer commandBuffer, deUint32 eventCount, const VkEvent* pEvents, const VkDependencyInfoKHR* pDependencyInfo) const override
+       {
+               m_vk.cmdWaitEvents2KHR(commandBuffer, eventCount, pEvents, pDependencyInfo);
+       }
+
+       void cmdResetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags2KHR flag) const override
+       {
+               m_vk.cmdResetEvent2KHR(commandBuffer, event, flag);
+       }
+
+       VkResult queueSubmit(VkQueue queue, VkFence fence) override
+       {
+               return m_vk.queueSubmit2KHR(queue, static_cast<deUint32>(m_submitInfo.size()), &m_submitInfo[0], fence);
+       }
+
+protected:
+
+       std::vector<VkSubmitInfo2KHR> m_submitInfo;
+};
+
+SynchronizationWrapperPtr getSynchronizationWrapper(SynchronizationType                type,
+                                                                                                       const DeviceInterface&  vk,
+                                                                                                       bool                                    usingTimelineSemaphores,
+                                                                                                       deUint32                                submitInfoCount)
+{
+       return (type == SynchronizationType::LEGACY)
+               ? SynchronizationWrapperPtr(new LegacySynchronizationWrapper(vk, usingTimelineSemaphores, submitInfoCount))
+               : SynchronizationWrapperPtr(new Synchronization2Wrapper(vk, submitInfoCount));
+}
+
+void submitCommandsAndWait(SynchronizationWrapperPtr   synchronizationWrapper,
+                                                  const DeviceInterface&               vk,
+                                                  const VkDevice                               device,
+                                                  const VkQueue                                queue,
+                                                  const VkCommandBuffer                cmdBuffer)
+{
+       VkCommandBufferSubmitInfoKHR commandBufferInfoCount = makeCommonCommandBufferSubmitInfo(cmdBuffer);
+
+       synchronizationWrapper->addSubmitInfo(
+               0u,                                                                             // deUint32                                                             waitSemaphoreInfoCount
+               DE_NULL,                                                                // const VkSemaphoreSubmitInfoKHR*              pWaitSemaphoreInfos
+               1u,                                                                             // deUint32                                                             commandBufferInfoCount
+               &commandBufferInfoCount,                                // const VkCommandBufferSubmitInfoKHR*  pCommandBufferInfos
+               0u,                                                                             // deUint32                                                             signalSemaphoreInfoCount
+               DE_NULL                                                                 // const VkSemaphoreSubmitInfoKHR*              pSignalSemaphoreInfos
+       );
+
+       const Unique<VkFence> fence(createFence(vk, device));
+       VK_CHECK(synchronizationWrapper->queueSubmit(queue, *fence));
+       VK_CHECK(vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, ~0ull));
+}
+
 void requireFeatures (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const FeatureFlags flags)
 {
        const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physDevice);
@@ -398,10 +989,12 @@ void requireFeatures (const InstanceInterface& vki, const VkPhysicalDevice physD
                throw tcu::NotSupportedError("Tessellation and geometry shaders don't support PointSize built-in");
 }
 
-void requireStorageImageSupport(const InstanceInterface& vki, const VkPhysicalDevice physDevice, const VkFormat fmt)
+void requireStorageImageSupport(const InstanceInterface& vki, const VkPhysicalDevice physDevice, const VkFormat fmt, const VkImageTiling tiling)
 {
-       const VkFormatProperties p = getPhysicalDeviceFormatProperties(vki, physDevice, fmt);
-       if ((p.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) == 0)
+       const VkFormatProperties        p                       = getPhysicalDeviceFormatProperties(vki, physDevice, fmt);
+       const auto&                                     features        = ((tiling == VK_IMAGE_TILING_LINEAR) ? p.linearTilingFeatures : p.optimalTilingFeatures);
+
+       if ((features & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) == 0)
                throw tcu::NotSupportedError("Storage image format not supported");
 }
 
@@ -409,8 +1002,11 @@ std::string getResourceName (const ResourceDescription& resource)
 {
        std::ostringstream str;
 
-       if (resource.type == RESOURCE_TYPE_BUFFER)
+       if ((resource.type == RESOURCE_TYPE_BUFFER) ||
+               (resource.type == RESOURCE_TYPE_INDEX_BUFFER))
+       {
                str << "buffer_" << resource.size.x();
+       }
        else if (resource.type == RESOURCE_TYPE_IMAGE)
        {
                str << "image_" << resource.size.x()
@@ -440,6 +1036,47 @@ bool isIndirectBuffer (const ResourceType type)
        }
 }
 
+VkCommandBufferSubmitInfoKHR makeCommonCommandBufferSubmitInfo (const VkCommandBuffer cmdBuf)
+{
+       return
+       {
+               VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO_KHR,       // VkStructureType              sType
+               DE_NULL,                                                                                        // const void*                  pNext
+               cmdBuf,                                                                                         // VkCommandBuffer              commandBuffer
+               0u                                                                                                      // uint32_t                             deviceMask
+       };
+}
+
+VkSemaphoreSubmitInfoKHR makeCommonSemaphoreSubmitInfo(VkSemaphore semaphore, deUint64 value, VkPipelineStageFlags2KHR stageMask)
+{
+       return
+       {
+               VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO_KHR,    // VkStructureType                              sType
+               DE_NULL,                                                                                // const void*                                  pNext
+               semaphore,                                                                              // VkSemaphore                                  semaphore
+               value,                                                                                  // deUint64                                             value
+               stageMask,                                                                              // VkPipelineStageFlags2KHR             stageMask
+               0u                                                                                              // deUint32                                             deviceIndex
+       };
+}
+
+VkDependencyInfoKHR makeCommonDependencyInfo(const VkMemoryBarrier2KHR* pMemoryBarrier, const VkBufferMemoryBarrier2KHR* pBufferMemoryBarrier, const VkImageMemoryBarrier2KHR* pImageMemoryBarrier,
+                                                                                        bool eventDependency)
+{
+       return
+       {
+               VK_STRUCTURE_TYPE_DEPENDENCY_INFO_KHR,                          // VkStructureType                                      sType
+               DE_NULL,                                                                                        // const void*                                          pNext
+               eventDependency ? (VkDependencyFlags)0u : (VkDependencyFlags)VK_DEPENDENCY_BY_REGION_BIT,       // VkDependencyFlags                            dependencyFlags
+               !!pMemoryBarrier,                                                                       // deUint32                                                     memoryBarrierCount
+               pMemoryBarrier,                                                                         // const VkMemoryBarrier2KHR*           pMemoryBarriers
+               !!pBufferMemoryBarrier,                                                         // deUint32                                                     bufferMemoryBarrierCount
+               pBufferMemoryBarrier,                                                           // const VkBufferMemoryBarrier2KHR* pBufferMemoryBarriers
+               !!pImageMemoryBarrier,                                                          // deUint32                                                     imageMemoryBarrierCount
+               pImageMemoryBarrier                                                                     // const VkImageMemoryBarrier2KHR*      pImageMemoryBarriers
+       };
+};
+
 PipelineCacheData::PipelineCacheData (void)
 {
 }