Use local binding for renderImage layout change
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / device_group / vktDeviceGroupRendering.cpp
index 026340f..cea650a 100755 (executable)
@@ -35,6 +35,8 @@
 #include "vkRefUtil.hpp"
 #include "vkStrUtil.hpp"
 #include "vkTypeUtil.hpp"
+#include "vkCmdUtil.hpp"
+#include "vkObjUtil.hpp"
 #include "vktTestCase.hpp"
 #include "vktTestCaseUtil.hpp"
 #include "vktTestGroupUtil.hpp"
@@ -151,7 +153,7 @@ private:
                        deUint32                                        getMemoryIndex                          (deUint32 memoryTypeBits, deUint32 memoryPropertyFlag);
                        void                                            getDeviceLayers                         (vector<string>& enabledLayers);
                        bool                                            isPeerFetchAllowed                      (deUint32 memoryTypeIndex, deUint32 firstdeviceID, deUint32 seconddeviceID);
-                       void                                            SubmitBufferAndWaitForIdle      (const DeviceDriver& vk, VkCommandBuffer cmdBuf, VkDeviceGroupSubmitInfo);
+                       void                                            SubmitBufferAndWaitForIdle      (const DeviceDriver& vk, VkCommandBuffer cmdBuf, deUint32 deviceMask);
        virtual tcu::TestStatus                         iterate                                         (void);
 
                        Move<VkDevice>                          m_deviceGroup;
@@ -199,7 +201,7 @@ bool DeviceGroupTestInstance::isPeerFetchAllowed (deUint32 memoryTypeIndex, deUi
 {
        VkPeerMemoryFeatureFlags                                peerMemFeatures1;
        VkPeerMemoryFeatureFlags                                peerMemFeatures2;
-       const DeviceDriver                                              vk                                              (m_context.getInstanceInterface(), *m_deviceGroup);
+       const DeviceDriver                                              vk                                              (m_context.getPlatformInterface(), m_context.getInstance(), *m_deviceGroup);
        const VkPhysicalDeviceMemoryProperties  deviceMemProps1                 = getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_physicalDevices[firstdeviceID]);
        const VkPhysicalDeviceMemoryProperties  deviceMemProps2                 = getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_physicalDevices[seconddeviceID]);
        vk.getDeviceGroupPeerMemoryFeatures(*m_deviceGroup, deviceMemProps2.memoryTypes[memoryTypeIndex].heapIndex, firstdeviceID, seconddeviceID, &peerMemFeatures1);
@@ -344,44 +346,23 @@ void DeviceGroupTestInstance::init (void)
                        (extensionPtrs.empty() ? DE_NULL : &extensionPtrs[0]),  //ppEnabledExtensionNames;
                        &enabledDeviceFeatures,                                                                 //pEnabledFeatures;
                };
-               m_deviceGroup = createDevice(instanceInterface, physicalDevice, &deviceCreateInfo);
+               m_deviceGroup = createDevice(m_context.getPlatformInterface(), m_context.getInstance(), instanceInterface, physicalDevice, &deviceCreateInfo);
        }
 
-       deviceDriver = de::MovePtr<vk::DeviceDriver>(new vk::DeviceDriver(instanceInterface, *m_deviceGroup));
+       deviceDriver = de::MovePtr<vk::DeviceDriver>(new vk::DeviceDriver(m_context.getPlatformInterface(), m_context.getInstance(), *m_deviceGroup));
        m_deviceGroupQueue = getDeviceQueue(*deviceDriver, *m_deviceGroup, queueFamilyIndex, queueIndex);
 }
 
-void DeviceGroupTestInstance::SubmitBufferAndWaitForIdle(const DeviceDriver& vk, VkCommandBuffer cmdBuf, VkDeviceGroupSubmitInfo deviceGroupSubmitInfo)
+void DeviceGroupTestInstance::SubmitBufferAndWaitForIdle(const DeviceDriver& vk, VkCommandBuffer cmdBuf, deUint32 deviceMask)
 {
-       const VkFenceCreateInfo fenceParams =
-       {
-               VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,    // sType
-               DE_NULL,                                                                // pNext
-               0u,                                                                             // flags
-       };
-       const VkSubmitInfo              submitInfo =
-       {
-               VK_STRUCTURE_TYPE_SUBMIT_INFO,                  // sType
-               &deviceGroupSubmitInfo,                                 // pNext
-               0u,                                                                             // waitSemaphoreCount
-               DE_NULL,                                                                // pWaitSemaphores
-               (const VkPipelineStageFlags*)DE_NULL,   // pWaitDstStageMask
-               1u,                                                                             // commandBufferCount
-               &cmdBuf,                                                                // pCommandBuffers
-               0u,                                                                             // signalSemaphoreCount
-               DE_NULL,                                                                // pSignalSemaphores
-       };
-       const Unique<VkFence>   fence(createFence(vk, *m_deviceGroup, &fenceParams));
-
-       VK_CHECK(vk.queueSubmit(m_deviceGroupQueue, 1u, &submitInfo, *fence));
-       VK_CHECK(vk.waitForFences(*m_deviceGroup, 1u, &fence.get(), DE_TRUE, ~0ull));
+       submitCommandsAndWait(vk, *m_deviceGroup, m_deviceGroupQueue, cmdBuf, true, deviceMask);
        VK_CHECK(vk.deviceWaitIdle(*m_deviceGroup));
 }
 
 tcu::TestStatus DeviceGroupTestInstance::iterate (void)
 {
        const InstanceInterface&        vki                                             (m_context.getInstanceInterface());
-       const DeviceDriver                      vk                                              (vki, *m_deviceGroup);
+       const DeviceDriver                      vk                                              (m_context.getPlatformInterface(), m_context.getInstance(), *m_deviceGroup);
        const deUint32                          queueFamilyIndex                = m_context.getUniversalQueueFamilyIndex();
        const tcu::UVec2                        renderSize                              (256, 256);
        const VkFormat                          colorFormat                             = VK_FORMAT_R8G8B8A8_UNORM;
@@ -496,18 +477,6 @@ tcu::TestStatus DeviceGroupTestInstance::iterate (void)
                        0u,                                                                                             // memoryTypeIndex
                };
 
-               VkDeviceGroupSubmitInfo         deviceGroupSubmitInfo =
-               {
-                       VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO,             // sType
-                       DE_NULL,                                                                                // pNext
-                       0u,                                                                                             // waitSemaphoreCount
-                       DE_NULL,                                                                                // pWaitSemaphoreDeviceIndices
-                       0u,                                                                                             // commandBufferCount
-                       DE_NULL,                                                                                // pCommandBufferDeviceMasks
-                       0u,                                                                                             // signalSemaphoreCount
-                       DE_NULL,                                                                                // pSignalSemaphoreDeviceIndices
-               };
-
                // create vertex buffers
                {
                        const VkBufferCreateInfo        stagingVertexBufferParams =
@@ -880,118 +849,11 @@ tcu::TestStatus DeviceGroupTestInstance::iterate (void)
                        imageMemory = allocateMemory(vk, *m_deviceGroup, &allocInfo);
                }
 
-               if ((m_testMode & TEST_MODE_SFR) && (m_physicalDeviceCount > 1))
-               {
-                       if (m_usePeerFetch && !isPeerFetchAllowed(memoryTypeNdx, firstDeviceID, secondDeviceID))
-                               TCU_THROW(NotSupportedError, "Peer texture reads is not supported.");
-
-                       // Check if peer memory can be used as source of a copy command in case of SFR bindings, always allowed in case of 1 device
-                       VkPeerMemoryFeatureFlags                                peerMemFeatures;
-                       const VkPhysicalDeviceMemoryProperties  deviceMemProps = getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_physicalDevices[secondDeviceID]);
-                       vk.getDeviceGroupPeerMemoryFeatures(*m_deviceGroup, deviceMemProps.memoryTypes[memoryTypeNdx].heapIndex, firstDeviceID, secondDeviceID, &peerMemFeatures);
-                       isPeerMemAsCopySrcAllowed = (peerMemFeatures & VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT);
-
-                       VkRect2D zeroRect = {
-                               {
-                                       0,      //      VkOffset2D.x
-                                       0,      //      VkOffset2D.x
-                               },
-                               {
-                                       0,      //      VkExtent2D.x
-                                       0,      //      VkExtent2D.x
-                               }
-                       };
-                       vector<VkRect2D> sfrRects;
-                       for (deUint32 i = 0; i < m_physicalDeviceCount*m_physicalDeviceCount; i++)
-                               sfrRects.push_back(zeroRect);
-
-                       if (m_physicalDeviceCount == 1u)
-                       {
-                               sfrRects[0].extent.width        = (deInt32)renderSize.x();
-                               sfrRects[0].extent.height       = (deInt32)renderSize.y();
-                       }
-                       else
-                       {
-                               // Split into 2 vertical halves
-                               sfrRects[firstDeviceID * m_physicalDeviceCount + firstDeviceID].extent.width    = (deInt32)renderSize.x() / 2;
-                               sfrRects[firstDeviceID * m_physicalDeviceCount + firstDeviceID].extent.height   = (deInt32)renderSize.y();
-                               sfrRects[firstDeviceID * m_physicalDeviceCount + secondDeviceID]                                = sfrRects[firstDeviceID * m_physicalDeviceCount + firstDeviceID];
-                               sfrRects[firstDeviceID * m_physicalDeviceCount + secondDeviceID].offset.x               = (deInt32)renderSize.x() / 2;
-                               sfrRects[secondDeviceID * m_physicalDeviceCount + firstDeviceID]                                = sfrRects[firstDeviceID * m_physicalDeviceCount + firstDeviceID];
-                               sfrRects[secondDeviceID * m_physicalDeviceCount + secondDeviceID]                               = sfrRects[firstDeviceID * m_physicalDeviceCount + secondDeviceID];
-                       }
-
-                       VkBindImageMemoryDeviceGroupInfo        devGroupBindInfo =
-                       {
-                               VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO,          // sType
-                               DE_NULL,                                                                                                        // pNext
-                               0u,                                                                                                                     // deviceIndexCount
-                               DE_NULL,                                                                                                        // pDeviceIndices
-                               m_physicalDeviceCount*m_physicalDeviceCount,                            // SFRRectCount
-                               &sfrRects[0],                                                                                           // pSFRRects
-                       };
-
-                       VkBindImageMemoryInfo                           bindInfo =
-                       {
-                               VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO,                                       // sType
-                               &devGroupBindInfo,                                                                                      // pNext
-                               *renderImage,                                                                                           // image
-                               imageMemory.get(),                                                                                      // memory
-                               0u,                                                                                                                     // memoryOffset
-                       };
-                       VK_CHECK(vk.bindImageMemory2(*m_deviceGroup, 1, &bindInfo));
-               }
-               else
-                       VK_CHECK(vk.bindImageMemory(*m_deviceGroup, *renderImage, imageMemory.get(), 0));
-
+               VK_CHECK(vk.bindImageMemory(*m_deviceGroup, *renderImage, imageMemory.get(), 0));
                VK_CHECK(vk.bindImageMemory(*m_deviceGroup, *readImage, imageMemory.get(), 0));
 
                // Create renderpass
-               {
-                       const VkAttachmentDescription                   colorAttDesc =
-                       {
-                               0u,                                                                                             // flags
-                               colorFormat,                                                                    // format
-                               VK_SAMPLE_COUNT_1_BIT,                                                  // samples
-                               VK_ATTACHMENT_LOAD_OP_CLEAR,                                    // loadOp
-                               VK_ATTACHMENT_STORE_OP_STORE,                                   // storeOp
-                               VK_ATTACHMENT_LOAD_OP_DONT_CARE,                                // stencilLoadOp
-                               VK_ATTACHMENT_STORE_OP_DONT_CARE,                               // stencilStoreOp
-                               VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,               // initialLayout
-                               VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,               // finalLayout
-                       };
-                       const VkAttachmentReference                             colorAttRef =
-                       {
-                               0u,                                                                                             // attachment
-                               VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,               // layout
-                       };
-                       const VkSubpassDescription                              subpassDesc =
-                       {
-                               (VkSubpassDescriptionFlags)0u,                                  // flags
-                               VK_PIPELINE_BIND_POINT_GRAPHICS,                                // pipelineBindPoint
-                               0u,                                                                                             // inputAttachmentCount
-                               DE_NULL,                                                                                // pInputAttachments
-                               1u,                                                                                             // colorAttachmentCount
-                               &colorAttRef,                                                                   // pColorAttachments
-                               DE_NULL,                                                                                // pResolveAttachments
-                               DE_NULL,                                                                                // depthStencilAttachment
-                               0u,                                                                                             // preserveAttachmentCount
-                               DE_NULL,                                                                                // pPreserveAttachments
-                       };
-                       const VkRenderPassCreateInfo                    renderPassParams =
-                       {
-                               VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,              // sType
-                               DE_NULL,                                                                                // pNext
-                               0u,                                                                                             // flags
-                               1u,                                                                                             // attachmentCount
-                               &colorAttDesc,                                                                  // pAttachments
-                               1u,                                                                                             // subpassCount
-                               &subpassDesc,                                                                   // pSubpasses
-                               0u,                                                                                             // dependencyCount
-                               DE_NULL,                                                                                // pDependencies
-                       };
-                       renderPass = createRenderPass(vk, *m_deviceGroup, &renderPassParams);
-               }
+               renderPass = makeRenderPass(vk, *m_deviceGroup, colorFormat);
 
                // Create descriptors
                {
@@ -1113,14 +975,13 @@ tcu::TestStatus DeviceGroupTestInstance::iterate (void)
 
                // Create Pipeline
                {
-                       vector<VkPipelineShaderStageCreateInfo> shaderStageParams;
-                       Move<VkShaderModule>                                    vertShaderModule;
-                       Move<VkShaderModule>                                    tcssShaderModule;
-                       Move<VkShaderModule>                                    tessShaderModule;
-                       Move<VkShaderModule>                                    fragShaderModule;
+                       Move<VkShaderModule>                                                    vertShaderModule;
+                       Move<VkShaderModule>                                                    tcssShaderModule;
+                       Move<VkShaderModule>                                                    tessShaderModule;
+                       Move<VkShaderModule>                                                    fragShaderModule;
 
-                       const VkDescriptorSetLayout descset = descriptorSetLayout.get();
-                       const VkPipelineLayoutCreateInfo        pipelineLayoutParams =
+                       const VkDescriptorSetLayout                                             descset                                 = descriptorSetLayout.get();
+                       const VkPipelineLayoutCreateInfo                                pipelineLayoutParams    =
                        {
                                VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,                  // sType
                                DE_NULL,                                                                                                // pNext
@@ -1136,142 +997,16 @@ tcu::TestStatus DeviceGroupTestInstance::iterate (void)
                        vertShaderModule = createShaderModule(vk, *m_deviceGroup, m_context.getBinaryCollection().get("vert"), 0);
                        fragShaderModule = createShaderModule(vk, *m_deviceGroup, m_context.getBinaryCollection().get("frag"), 0);
 
-                       const VkSpecializationInfo                              emptyShaderSpecParams =
-                       {
-                               0u,                                                                                                                     // mapEntryCount
-                               DE_NULL,                                                                                                        // pMap
-                               0,                                                                                                                      // dataSize
-                               DE_NULL,                                                                                                        // pData
-                       };
-                       const VkPipelineShaderStageCreateInfo   vertexShaderStageParams =
-                       {
-                               VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,    // sType
-                               DE_NULL,                                                                                                // pNext
-                               0u,                                                                                                             // flags
-                               VK_SHADER_STAGE_VERTEX_BIT,                                                             // stage
-                               *vertShaderModule,                                                                              // module
-                               "main",                                                                                                 // pName
-                               &emptyShaderSpecParams,                                                                 // pSpecializationInfo
-                       };
-                       shaderStageParams.push_back(vertexShaderStageParams);
-
                        if (m_drawTessellatedSphere)
                        {
                                tcssShaderModule = createShaderModule(vk, *m_deviceGroup, m_context.getBinaryCollection().get("tesc"), 0);
                                tessShaderModule = createShaderModule(vk, *m_deviceGroup, m_context.getBinaryCollection().get("tese"), 0);
-
-                               const VkPipelineShaderStageCreateInfo   tessControlShaderStageParams =
-                               {
-                                       VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,    // sType
-                                       DE_NULL,                                                                                                // pNext
-                                       0u,                                                                                                             // flags
-                                       VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,                               // stage
-                                       *tcssShaderModule,                                                                              // module
-                                       "main",                                                                                                 // pName
-                                       &emptyShaderSpecParams,                                                                 // pSpecializationInfo
-                               };
-                               const VkPipelineShaderStageCreateInfo   tessEvalShaderStageParams =
-                               {
-                                       VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,    // sType
-                                       DE_NULL,                                                                                                // pNext
-                                       0u,                                                                                                             // flags
-                                       VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,                    // stage
-                                       *tessShaderModule,                                                                              // module
-                                       "main",                                                                                                 // pName
-                                       &emptyShaderSpecParams,                                                                 // pSpecializationInfo
-                               };
-
-                               shaderStageParams.push_back(tessControlShaderStageParams);
-                               shaderStageParams.push_back(tessEvalShaderStageParams);
                        }
 
-                       const VkPipelineShaderStageCreateInfo   fragmentShaderStageParams =
-                       {
-                               VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,    // sType
-                               DE_NULL,                                                                                                // pNext
-                               0u,                                                                                                             // flags
-                               VK_SHADER_STAGE_FRAGMENT_BIT,                                                   // stage
-                               *fragShaderModule,                                                                              // module
-                               "main",                                                                                                 // pName
-                               &emptyShaderSpecParams,                                                                 // pSpecializationInfo
-                       };
-                       shaderStageParams.push_back(fragmentShaderStageParams);
+                       const std::vector<VkViewport>                                   viewports                               (1, makeViewport(renderSize));
+                       const std::vector<VkRect2D>                                             scissors                                (1, makeRect2D(renderSize));
 
-                       const VkPipelineDepthStencilStateCreateInfo     depthStencilParams =
-                       {
-                               VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,     // sType
-                               DE_NULL,                                                                                                        // pNext
-                               0u,                                                                                                                     // flags
-                               DE_FALSE,                                                                                                       // depthTestEnable
-                               DE_FALSE,                                                                                                       // depthWriteEnable
-                               VK_COMPARE_OP_ALWAYS,                                                                           // depthCompareOp
-                               DE_FALSE,                                                                                                       // depthBoundsTestEnable
-                               DE_FALSE,                                                                                                       // stencilTestEnable
-                               {
-                                       VK_STENCIL_OP_KEEP,                                                                             // failOp
-                                       VK_STENCIL_OP_KEEP,                                                                             // passOp
-                                       VK_STENCIL_OP_KEEP,                                                                             // depthFailOp
-                                       VK_COMPARE_OP_ALWAYS,                                                                   // compareOp
-                                       0u,                                                                                                             // compareMask
-                                       0u,                                                                                                             // writeMask
-                                       0u,                                                                                                             // reference
-                               },                                                                                                                      // front
-                               {
-                                       VK_STENCIL_OP_KEEP,                                                                             // failOp
-                                       VK_STENCIL_OP_KEEP,                                                                             // passOp
-                                       VK_STENCIL_OP_KEEP,                                                                             // depthFailOp
-                                       VK_COMPARE_OP_ALWAYS,                                                                   // compareOp
-                                       0u,                                                                                                             // compareMask
-                                       0u,                                                                                                             // writeMask
-                                       0u,                                                                                                             // reference
-                               },                                                                                                                      // back;
-                               0.0f,                                                                                                           // minDepthBounds;
-                               1.0f,                                                                                                           // maxDepthBounds;
-                       };
-                       const VkViewport        viewport0 =
-                       {
-                               0.0f,                                                                                                           // x
-                               0.0f,                                                                                                           // y
-                               (float)renderSize.x(),                                                                          // width
-                               (float)renderSize.y(),                                                                          // height
-                               0.0f,                                                                                                           // minDepth
-                               1.0f,                                                                                                           // maxDepth
-                       };
-                       const VkRect2D          scissor0 =
-                       {
-                               {
-                                       0u,                                                                                                             // x
-                                       0u,                                                                                                             // y
-                               },                                                                                                                      // offset
-                               {
-                                       renderSize.x(),                                                                                 // width
-                                       renderSize.y(),                                                                                 // height
-                               },                                                                                                                      // extent;
-                       };
-                       const VkPipelineViewportStateCreateInfo         viewportParams =
-                       {
-                               VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,          // sType
-                               DE_NULL,                                                                                                        // pNext
-                               0u,                                                                                                                     // flags
-                               1u,                                                                                                                     // viewportCount
-                               &viewport0,                                                                                                     // pViewports
-                               1u,                                                                                                                     // scissorCount
-                               &scissor0                                                                                                       // pScissors
-                       };
-                       const VkSampleMask                                                      sampleMask = ~0u;
-                       const VkPipelineMultisampleStateCreateInfo      multisampleParams =
-                       {
-                               VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,       // sType
-                               DE_NULL,                                                                                                        // pNext
-                               0u,                                                                                                                     // flags
-                               VK_SAMPLE_COUNT_1_BIT,                                                                          // rasterizationSamples
-                               VK_FALSE,                                                                                                       // sampleShadingEnable
-                               0.0f,                                                                                                           // minSampleShading
-                               &sampleMask,                                                                                            // sampleMask
-                               VK_FALSE,                                                                                                       // alphaToCoverageEnable
-                               VK_FALSE,                                                                                                       // alphaToOneEnable
-                       };
-                       const VkPipelineRasterizationStateCreateInfo    rasterParams =
+                       const VkPipelineRasterizationStateCreateInfo    rasterParams                    =
                        {
                                VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,                     // sType
                                DE_NULL,                                                                                                                        // pNext
@@ -1287,93 +1022,25 @@ tcu::TestStatus DeviceGroupTestInstance::iterate (void)
                                0.0f,                                                                                                                           // depthBiasSlopeFactor
                                1.0f,                                                                                                                           // lineWidth
                        };
-                       const VkPipelineInputAssemblyStateCreateInfo    inputAssemblyParams =
-                       {
-                               VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,    // sType
-                               DE_NULL,                                                                                                                // pNext
-                               0u,                                                                                                                             // flags
-                               m_drawTessellatedSphere ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,       // topology
-                               DE_FALSE,                                                                                                               // primitiveRestartEnable
-                       };
-                       const VkVertexInputBindingDescription           vertexBinding0 =
-                       {
-                               0u,                                                                                                             // binding
-                               (deUint32)sizeof(tcu::Vec4),                                                    // stride
-                               VK_VERTEX_INPUT_RATE_VERTEX,                                                    // inputRate
-                       };
-                       const VkVertexInputAttributeDescription         vertexAttrib0 =
-                       {
-                               0u,                                                                                                             // location
-                               0u,                                                                                                             // binding
-                               VK_FORMAT_R32G32B32A32_SFLOAT,                                                  // format
-                               0u,                                                                                                             // offset
-                       };
-                       const VkPipelineVertexInputStateCreateInfo      vertexInputStateParams =
-                       {
-                               VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,      // sType
-                               DE_NULL,                                                                                                        // pNext
-                               0u,                                                                                                                     // flags
-                               1u,                                                                                                                     // vertexBindingDescriptionCount
-                               &vertexBinding0,                                                                                        // pVertexBindingDescriptions
-                               1u,                                                                                                                     // vertexAttributeDescriptionCount
-                               &vertexAttrib0,                                                                                         // pVertexAttributeDescriptions
-                       };
-                       const VkPipelineColorBlendAttachmentState       attBlendParams =
-                       {
-                               VK_FALSE,                                                                                                       // blendEnable
-                               VK_BLEND_FACTOR_ONE,                                                                            // srcColorBlendFactor
-                               VK_BLEND_FACTOR_ZERO,                                                                           // dstColorBlendFactor
-                               VK_BLEND_OP_ADD,                                                                                        // colorBlendOp
-                               VK_BLEND_FACTOR_ONE,                                                                            // srcAlphaBlendFactor
-                               VK_BLEND_FACTOR_ZERO,                                                                           // dstAlphaBlendFactor
-                               VK_BLEND_OP_ADD,                                                                                        // alphaBlendOp
-                               (VK_COLOR_COMPONENT_R_BIT |
-                                VK_COLOR_COMPONENT_G_BIT |
-                                VK_COLOR_COMPONENT_B_BIT |
-                                VK_COLOR_COMPONENT_A_BIT),                                                                     // colorWriteMask
-                       };
-                       const VkPipelineColorBlendStateCreateInfo       blendParams =
-                       {
-                               VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,       // sType
-                               DE_NULL,                                                                                                        // pNext
-                               0u,                                                                                                                     // flags
-                               DE_FALSE,                                                                                                       // logicOpEnable
-                               VK_LOGIC_OP_COPY,                                                                                       // logicOp
-                               1u,                                                                                                                     // attachmentCount
-                               &attBlendParams,                                                                                        // pAttachments
-                               { 0.0f, 0.0f, 0.0f, 0.0f },                                                                     // blendConstants[4]
-                       };
 
-                       const VkPipelineTessellationStateCreateInfo tessState =
-                       {
-                               VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,      // sType
-                               DE_NULL,                                                                                                        // pNext
-                               0u,                                                                                                                     // flags
-                               3u,                                                                                                                     // patchControlPoints
-                       };
-                       const VkGraphicsPipelineCreateInfo              pipelineParams =
-                       {
-                               VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,                // sType
-                               DE_NULL,                                                                                                // pNext
-                               0u,                                                                                                             // flags
-                               deUint32(shaderStageParams.size()),                                             // stageCount
-                               shaderStageParams.data(),                                                               // pStages
-                               &vertexInputStateParams,                                                                // pVertexInputState
-                               &inputAssemblyParams,                                                                   // pInputAssemblyState
-                               m_drawTessellatedSphere ? &tessState : DE_NULL,                 // pTessellationState
-                               &viewportParams,                                                                                // pViewportState
-                               &rasterParams,                                                                                  // pRasterizationState
-                               &multisampleParams,                                                                             // pMultisampleState
-                               &depthStencilParams,                                                                    // pDepthStencilState
-                               &blendParams,                                                                                   // pColorBlendState
-                               (const VkPipelineDynamicStateCreateInfo*)DE_NULL,               // pDynamicState
-                               *pipelineLayout,                                                                                // layout
-                               *renderPass,                                                                                    // renderPass
-                               0u,                                                                                                             // subpass
-                               DE_NULL,                                                                                                // basePipelineHandle
-                               0u,                                                                                                             // basePipelineIndex
-                       };
-                       pipeline = createGraphicsPipeline(vk, *m_deviceGroup, DE_NULL, &pipelineParams);
+                       const VkPrimitiveTopology                                               topology                                = m_drawTessellatedSphere ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+
+                       pipeline = makeGraphicsPipeline(vk,                                                                                                             // const DeviceInterface&                        vk
+                                                                                       *m_deviceGroup,                                                                                 // const VkDevice                                device
+                                                                                       *pipelineLayout,                                                                                // const VkPipelineLayout                        pipelineLayout
+                                                                                       *vertShaderModule,                                                                              // const VkShaderModule                          vertexShaderModule
+                                                                                       m_drawTessellatedSphere ? *tcssShaderModule : DE_NULL,  // const VkShaderModule                          tessellationControlModule,
+                                                                                       m_drawTessellatedSphere ? *tessShaderModule : DE_NULL,  // const VkShaderModule                          tessellationEvalModule,
+                                                                                       DE_NULL,                                                                                                // const VkShaderModule                          geometryShaderModule
+                                                                                       *fragShaderModule,                                                                              // const VkShaderModule                          fragmentShaderModule
+                                                                                       *renderPass,                                                                                    // const VkRenderPass                            renderPass
+                                                                                       viewports,                                                                                              // const std::vector<VkViewport>&                viewports
+                                                                                       scissors,                                                                                               // const std::vector<VkRect2D>&                  scissors
+                                                                                       topology,                                                                                               // const VkPrimitiveTopology                     topology
+                                                                                       0u,                                                                                                             // const deUint32                                subpass
+                                                                                       3u,                                                                                                             // const deUint32                                patchControlPoints
+                                                                                       DE_NULL,                                                                                                // const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
+                                                                                       &rasterParams);                                                                                 // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
                }
 
                // Create Framebuffer
@@ -1439,25 +1106,9 @@ tcu::TestStatus DeviceGroupTestInstance::iterate (void)
                        cmdBuffer = allocateCommandBuffer(vk, *m_deviceGroup, &cmdBufParams);
                }
 
-               // Begin recording
-               VkCommandBufferBeginInfo                                cmdBufBeginParams =
+               // Do a layout transition for renderImage
                {
-                       VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,                    // sType
-                       DE_NULL,                                                                                                // pNext
-                       VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,                    // flags
-                       (const VkCommandBufferInheritanceInfo*)DE_NULL,
-               };
-               VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufBeginParams));
-
-               // Prepare render target for rendering
-               {
-                       const VkMemoryBarrier           vertFlushBarrier =
-                       {
-                               VK_STRUCTURE_TYPE_MEMORY_BARRIER,                       // sType
-                               DE_NULL,                                                                        // pNext
-                               VK_ACCESS_HOST_WRITE_BIT,                                       // srcAccessMask
-                               VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT,            // dstAccessMask
-                       };
+                       beginCommandBuffer(vk, *cmdBuffer);
                        const VkImageMemoryBarrier      colorAttBarrier =
                        {
                                VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,         // sType
@@ -1478,9 +1129,79 @@ tcu::TestStatus DeviceGroupTestInstance::iterate (void)
                                        1u,                                                                             // layerCount
                                }                                                                                       // subresourceRange
                        };
-                       vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, (VkDependencyFlags)0, 1, &vertFlushBarrier, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &colorAttBarrier);
+                       vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &colorAttBarrier);
+
+                       endCommandBuffer(vk, *cmdBuffer);
+                       const deUint32 deviceMask = (1 << firstDeviceID) | (1 << secondDeviceID);
+                       SubmitBufferAndWaitForIdle(vk, cmdBuffer.get(), deviceMask);
                }
 
+               // Bind renderImage across devices for SFR
+               if ((m_testMode & TEST_MODE_SFR) && (m_physicalDeviceCount > 1))
+               {
+                       if (m_usePeerFetch && !isPeerFetchAllowed(memoryTypeNdx, firstDeviceID, secondDeviceID))
+                               TCU_THROW(NotSupportedError, "Peer texture reads is not supported.");
+
+                       // Check if peer memory can be used as source of a copy command in case of SFR bindings, always allowed in case of 1 device
+                       VkPeerMemoryFeatureFlags                                peerMemFeatures;
+                       const VkPhysicalDeviceMemoryProperties  deviceMemProps = getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_physicalDevices[secondDeviceID]);
+                       vk.getDeviceGroupPeerMemoryFeatures(*m_deviceGroup, deviceMemProps.memoryTypes[memoryTypeNdx].heapIndex, firstDeviceID, secondDeviceID, &peerMemFeatures);
+                       isPeerMemAsCopySrcAllowed = (peerMemFeatures & VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT);
+
+                       VkRect2D zeroRect = {
+                               {
+                                       0,      //      VkOffset2D.x
+                                       0,      //      VkOffset2D.x
+                               },
+                               {
+                                       0,      //      VkExtent2D.x
+                                       0,      //      VkExtent2D.x
+                               }
+                       };
+                       vector<VkRect2D> sfrRects;
+                       for (deUint32 i = 0; i < m_physicalDeviceCount*m_physicalDeviceCount; i++)
+                               sfrRects.push_back(zeroRect);
+
+                       if (m_physicalDeviceCount == 1u)
+                       {
+                               sfrRects[0].extent.width        = (deInt32)renderSize.x();
+                               sfrRects[0].extent.height       = (deInt32)renderSize.y();
+                       }
+                       else
+                       {
+                               // Split into 2 vertical halves
+                               sfrRects[firstDeviceID * m_physicalDeviceCount + firstDeviceID].extent.width    = (deInt32)renderSize.x() / 2;
+                               sfrRects[firstDeviceID * m_physicalDeviceCount + firstDeviceID].extent.height   = (deInt32)renderSize.y();
+                               sfrRects[firstDeviceID * m_physicalDeviceCount + secondDeviceID]                                = sfrRects[firstDeviceID * m_physicalDeviceCount + firstDeviceID];
+                               sfrRects[firstDeviceID * m_physicalDeviceCount + secondDeviceID].offset.x               = (deInt32)renderSize.x() / 2;
+                               sfrRects[secondDeviceID * m_physicalDeviceCount + firstDeviceID]                                = sfrRects[firstDeviceID * m_physicalDeviceCount + firstDeviceID];
+                               sfrRects[secondDeviceID * m_physicalDeviceCount + secondDeviceID]                               = sfrRects[firstDeviceID * m_physicalDeviceCount + secondDeviceID];
+                       }
+
+                       VkBindImageMemoryDeviceGroupInfo        devGroupBindInfo =
+                       {
+                               VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO,          // sType
+                               DE_NULL,                                                                                                        // pNext
+                               0u,                                                                                                                     // deviceIndexCount
+                               DE_NULL,                                                                                                        // pDeviceIndices
+                               m_physicalDeviceCount*m_physicalDeviceCount,                            // SFRRectCount
+                               &sfrRects[0],                                                                                           // pSFRRects
+                       };
+
+                       VkBindImageMemoryInfo                           bindInfo =
+                       {
+                               VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO,                                       // sType
+                               &devGroupBindInfo,                                                                                      // pNext
+                               *renderImage,                                                                                           // image
+                               imageMemory.get(),                                                                                      // memory
+                               0u,                                                                                                                     // memoryOffset
+                       };
+                       VK_CHECK(vk.bindImageMemory2(*m_deviceGroup, 1, &bindInfo));
+               }
+
+               // Begin recording
+               beginCommandBuffer(vk, *cmdBuffer);
+
                // Update buffers
                {
                        const VkBufferMemoryBarrier             stagingVertexBufferUpdateBarrier =
@@ -1685,7 +1406,7 @@ tcu::TestStatus DeviceGroupTestInstance::iterate (void)
                        vk.cmdSetDeviceMask(*cmdBuffer, ((1 << firstDeviceID) | (1 << secondDeviceID)));
                        vk.cmdDrawIndexed(*cmdBuffer, numIndices, 1u, 0, 0, 0);
                }
-               vk.cmdEndRenderPass(*cmdBuffer);
+               endRenderPass(vk, *cmdBuffer);
 
                // Change image layout for copy
                {
@@ -1711,14 +1432,12 @@ tcu::TestStatus DeviceGroupTestInstance::iterate (void)
                        vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &renderFinishBarrier);
                }
 
-               VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
+               endCommandBuffer(vk, *cmdBuffer);
 
                // Submit & wait for completion
                {
                        const deUint32 deviceMask = (1 << firstDeviceID) | (1 << secondDeviceID);
-                       deviceGroupSubmitInfo.commandBufferCount = 1;
-                       deviceGroupSubmitInfo.pCommandBufferDeviceMasks = &deviceMask;
-                       SubmitBufferAndWaitForIdle(vk, cmdBuffer.get(), deviceGroupSubmitInfo);
+                       SubmitBufferAndWaitForIdle(vk, cmdBuffer.get(), deviceMask);
                }
 
                // Copy image from secondDeviceID in case of AFR and SFR(only if Peer memory as copy source is not allowed)
@@ -1793,14 +1512,13 @@ tcu::TestStatus DeviceGroupTestInstance::iterate (void)
                                                }
                                        };
 
-                                       VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufBeginParams));
+                                       beginCommandBuffer(vk, *cmdBuffer);
                                        vk.cmdSetDeviceMask(*cmdBuffer, 1 << firstDeviceID);
                                        vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1u, &preCopyBarrier);
-                                       VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
+                                       endCommandBuffer(vk, *cmdBuffer);
 
                                        const deUint32 deviceMask = 1 << firstDeviceID;
-                                       deviceGroupSubmitInfo.pCommandBufferDeviceMasks = &deviceMask;
-                                       SubmitBufferAndWaitForIdle(vk, cmdBuffer.get(), deviceGroupSubmitInfo);
+                                       SubmitBufferAndWaitForIdle(vk, cmdBuffer.get(), deviceMask);
                                }
 
                                // Copy Image from secondDeviceID to firstDeviceID
@@ -1834,14 +1552,13 @@ tcu::TestStatus DeviceGroupTestInstance::iterate (void)
                                                }
                                        };
 
-                                       VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufBeginParams));
+                                       beginCommandBuffer(vk, *cmdBuffer);
                                        vk.cmdSetDeviceMask(*cmdBuffer, 1 << secondDeviceID);
                                        vk.cmdCopyImage(*cmdBuffer, *renderImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *peerImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &imageCopy);
-                                       VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
+                                       endCommandBuffer(vk, *cmdBuffer);
 
                                        const deUint32 deviceMask = 1 << secondDeviceID;
-                                       deviceGroupSubmitInfo.pCommandBufferDeviceMasks = &deviceMask;
-                                       SubmitBufferAndWaitForIdle(vk, cmdBuffer.get(), deviceGroupSubmitInfo);
+                                       SubmitBufferAndWaitForIdle(vk, cmdBuffer.get(), deviceMask);
                                }
 
                                // Change layout back on firstDeviceID
@@ -1866,14 +1583,13 @@ tcu::TestStatus DeviceGroupTestInstance::iterate (void)
                                                }
                                        };
 
-                                       VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufBeginParams));
+                                       beginCommandBuffer(vk, *cmdBuffer);
                                        vk.cmdSetDeviceMask(*cmdBuffer, 1 << firstDeviceID);
                                        vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1u, &postCopyBarrier);
-                                       VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
+                                       endCommandBuffer(vk, *cmdBuffer);
 
                                        const deUint32 deviceMask = 1 << firstDeviceID;
-                                       deviceGroupSubmitInfo.pCommandBufferDeviceMasks = &deviceMask;
-                                       SubmitBufferAndWaitForIdle(vk, cmdBuffer.get(), deviceGroupSubmitInfo);
+                                       SubmitBufferAndWaitForIdle(vk, cmdBuffer.get(), deviceMask);
                                }
                        }
                }
@@ -1896,7 +1612,7 @@ tcu::TestStatus DeviceGroupTestInstance::iterate (void)
                        const UniquePtr<Allocation>     readImageBufferMemory(memAlloc.allocate(getBufferMemoryRequirements(vk, *m_deviceGroup, *readImageBuffer), MemoryRequirement::HostVisible));
                        VK_CHECK(vk.bindBufferMemory(*m_deviceGroup, *readImageBuffer, readImageBufferMemory->getMemory(), readImageBufferMemory->getOffset()));
 
-                       VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufBeginParams));
+                       beginCommandBuffer(vk, *cmdBuffer);
 
                        // Copy image to buffer
                        {
@@ -1936,13 +1652,12 @@ tcu::TestStatus DeviceGroupTestInstance::iterate (void)
                                };
                                vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &copyFinishBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
                        }
-                       VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
+                       endCommandBuffer(vk, *cmdBuffer);
 
                        // Submit & wait for completion
                        {
                                const deUint32 deviceMask = 1 << firstDeviceID;
-                               deviceGroupSubmitInfo.pCommandBufferDeviceMasks = &deviceMask;
-                               SubmitBufferAndWaitForIdle(vk, cmdBuffer.get(), deviceGroupSubmitInfo);
+                               SubmitBufferAndWaitForIdle(vk, cmdBuffer.get(), deviceMask);
                        }
 
                        // Read results and check against reference image