Fix Renderpass storeOp synchronization hazards
authorJeremy Gebben <jeremyg@lunarg.com>
Thu, 10 Dec 2020 20:20:09 +0000 (13:20 -0700)
committerAlexander Galazin <Alexander.Galazin@arm.com>
Fri, 18 Dec 2020 08:12:16 +0000 (08:12 +0000)
Several multisample test groups create Renderpasses where the
first subpass writes to a color attachment, followed by N
subpasses that use the same attachment as an input attachment.

The spec says: "The store operation for each sample in an attachment
happens-after any recorded command which accesses the sample in
the last subpass where the attachment is used."

To avoid SYNC-HAZARD-WRITE-RACING-WRITE or SYNC-HAZARD-WRITE-RACING-READ
errors, the Nth subpass must depend on all prior subpasses.

VK-GL-CTS Issue: 2700

Affects Tests:
dEQP-VK.pipeline.multisample.min_sample_shading.*
dEQP-VK.pipeline.multisample_shader_builtin.*
dEQP-VK.renderpass.suballocation.multisample.*
dEQP-VK.renderpass2.suballocation.multisample.*

Components: Vulkan

Change-Id: I48c1ad2c1f05010ac31e45c513e1d4920216fe52

external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleBaseResolveAndPerSampleFetch.cpp
external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleTests.cpp
external/vulkancts/modules/vulkan/renderpass/vktRenderPassMultisampleTests.cpp

index 453fa03abf861830c12b468ded565f4a2dce400f..012844a849e03fa114d6378c1f05b5aa597d601f 100644 (file)
@@ -258,7 +258,7 @@ tcu::TestStatus MSInstanceBaseResolveAndPerSampleFetch::iterate (void)
        }
 
        std::vector<VkSubpassDescription> subpasses(1u + numSamples);
-       std::vector<VkSubpassDependency>  subpassDependencies(numSamples);
+       std::vector<VkSubpassDependency>  subpassDependencies;
 
        const VkSubpassDescription firstSubpassDesc =
        {
@@ -305,7 +305,23 @@ tcu::TestStatus MSInstanceBaseResolveAndPerSampleFetch::iterate (void)
                        0u,                                                                                             // VkDependencyFlags       dependencyFlags;
                };
 
-               subpassDependencies[sampleNdx] = subpassDependency;
+               subpassDependencies.push_back(subpassDependency);
+       }
+       // now handle the very last sample pass, which must synchronize with all prior subpasses
+       for (deUint32 sampleNdx = 0u; sampleNdx < (numSamples - 1); ++sampleNdx)
+       {
+               const VkSubpassDependency subpassDependency =
+               {
+                       1u + sampleNdx,                                                                 // uint32_t                                     srcSubpass;
+                       numSamples,                                                                             // uint32_t                                     dstSubpass;
+                       VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,  // VkPipelineStageFlags         srcStageMask;
+                       VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,                  // VkPipelineStageFlags         dstStageMask;
+                       VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,                   // VkAccessFlags                        srcAccessMask;
+                       VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,                    // VkAccessFlags                        dstAccessMask;
+                       0u,                                                                                             // VkDependencyFlags            dependencyFlags;
+               };
+
+               subpassDependencies.push_back(subpassDependency);
        }
 
        const VkRenderPassCreateInfo renderPassInfo =
index 3db404ca32ecf129d8bce6c78cca0c6673fc8e57..73d0fa7a1f87b4f16afa1bbbffdef7a02cf0d987 100644 (file)
@@ -2977,6 +2977,21 @@ void MultisampleRenderer::initialize (Context&                                                                   context,
                                        };
                                        subpassDependencies.push_back(copySampleSubpassDependency);
                                }
+                               // the very last sample pass must synchronize with all prior subpasses
+                               for (size_t i = 0; i < (m_perSampleImages.size() - 1); ++i)
+                               {
+                                       const VkSubpassDependency storeSubpassDependency =
+                                       {
+                                               1u + static_cast<deUint32>(i),                                          // deUint32                                                     srcSubpass
+                                               static_cast<deUint32>(m_perSampleImages.size()),    // deUint32                                                 dstSubpass
+                                               VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,          // VkPipelineStageFlags                         srcStageMask
+                                               VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,                          // VkPipelineStageFlags                         dstStageMask
+                                               VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,                           // VkAccessFlags                                        srcAccessMask
+                                               VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,                            // VkAccessFlags                                        dstAccessMask
+                                               0u,                                                                                                     // VkDependencyFlags                            dependencyFlags
+                                       };
+                                       subpassDependencies.push_back(storeSubpassDependency);
+                               }
                        }
                }
 
index 28dd49c9617be11fc63f5d023f8cea2056913fdb..a150ea89312c13deee5ebdc2d9ea528f3ae5ec47 100644 (file)
@@ -716,6 +716,25 @@ Move<VkRenderPass> createRenderPass (const DeviceInterface&        vkd,
                                dependencies.push_back(dependency);
                        }
                };
+               // the last subpass must synchronize with all prior subpasses
+               for (deUint32 splitSubpassIndex = 0; splitSubpassIndex < (splitSubpassCount - 1); splitSubpassIndex++)
+               {
+                               const SubpassDep        dependency                                                                                                                              //  VkSubpassDependency                                                 ||  VkSubpassDependency2KHR
+                               (
+                                                                                                                                                                                                                       //                                                                                              ||      VkStructureType                 sType;
+                                       DE_NULL,                                                                                                                                                                //                                                                                              ||      const void*                             pNext;
+                                       splitSubpassIndex + 1,                                                                                                                                  //  deUint32                            srcSubpass;                     ||      deUint32                                srcSubpass;
+                                       splitSubpassCount,                                                                                                                                              //  deUint32                            dstSubpass;                     ||      deUint32                                dstSubpass;
+                                       VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT
+                                       | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,                                                                                    //  VkPipelineStageFlags        srcStageMask;           ||      VkPipelineStageFlags    srcStageMask;
+                                       VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,                                                                                                  //  VkPipelineStageFlags        dstStageMask;           ||      VkPipelineStageFlags    dstStageMask;
+                                       VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,    //  VkAccessFlags                       srcAccessMask;          ||      VkAccessFlags                   srcAccessMask;
+                                       VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,                                                                                                    //  VkAccessFlags                       dstAccessMask;          ||      VkAccessFlags                   dstAccessMask;
+                                       VK_DEPENDENCY_BY_REGION_BIT,                                                                                                                    //  VkDependencyFlags           dependencyFlags;        ||      VkDependencyFlags               dependencyFlags;
+                                       0u                                                                                                                                                                              //                                                                                              ||      deInt32                                 viewOffset;
+                               );
+                               dependencies.push_back(dependency);
+               }
                const RenderPassCreateInfo      renderPassCreator                                               //  VkRenderPassCreateInfo                                                                              ||  VkRenderPassCreateInfo2KHR
                (
                                                                                                                                                        //  VkStructureType                                     sType;                                          ||  VkStructureType                                             sType;