From e60de085473174e5a6b5a1e33e39006e62f5c786 Mon Sep 17 00:00:00 2001 From: Samuel Pitoiset Date: Thu, 9 Jan 2020 10:55:54 +0100 Subject: [PATCH] radv: handle missing implicit subpass dependencies When a subpass doesn't declare an explicit dependency from/to VK_SUBPASS_EXTERNAL, Vulkan says there is an implicit dependency. Signed-off-by: Samuel Pitoiset Reviewed-by: Bas Nieuwenhuizen Tested-by: Marge Bot Part-of: --- src/amd/vulkan/radv_pass.c | 112 +++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) diff --git a/src/amd/vulkan/radv_pass.c b/src/amd/vulkan/radv_pass.c index 4c3cab6855f..89343d8a0d9 100644 --- a/src/amd/vulkan/radv_pass.c +++ b/src/amd/vulkan/radv_pass.c @@ -59,6 +59,90 @@ radv_render_pass_add_subpass_dep(struct radv_render_pass *pass, } } +static void +radv_render_pass_add_implicit_deps(struct radv_render_pass *pass, + bool has_ingoing_dep, bool has_outgoing_dep) +{ + /* From the Vulkan 1.0.39 spec: + * + * If there is no subpass dependency from VK_SUBPASS_EXTERNAL to the + * first subpass that uses an attachment, then an implicit subpass + * dependency exists from VK_SUBPASS_EXTERNAL to the first subpass it is + * used in. The subpass dependency operates as if defined with the + * following parameters: + * + * VkSubpassDependency implicitDependency = { + * .srcSubpass = VK_SUBPASS_EXTERNAL; + * .dstSubpass = firstSubpass; // First subpass attachment is used in + * .srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + * .dstStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; + * .srcAccessMask = 0; + * .dstAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_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; + * .dependencyFlags = 0; + * }; + * + * Similarly, if there is no subpass dependency from the last subpass + * that uses an attachment to VK_SUBPASS_EXTERNAL, then an implicit + * subpass dependency exists from the last subpass it is used in to + * VK_SUBPASS_EXTERNAL. The subpass dependency operates as if defined + * with the following parameters: + * + * VkSubpassDependency implicitDependency = { + * .srcSubpass = lastSubpass; // Last subpass attachment is used in + * .dstSubpass = VK_SUBPASS_EXTERNAL; + * .srcStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; + * .dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; + * .srcAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_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; + * .dstAccessMask = 0; + * .dependencyFlags = 0; + * }; + */ + + if (!has_ingoing_dep) { + const VkSubpassDependency2KHR implicit_ingoing_dep = { + .srcSubpass = VK_SUBPASS_EXTERNAL, + .dstSubpass = 0, + .srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + .dstStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + .srcAccessMask = 0, + .dstAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_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, + .dependencyFlags = 0, + }; + + radv_render_pass_add_subpass_dep(pass, &implicit_ingoing_dep); + } + + if (!has_outgoing_dep) { + const VkSubpassDependency2KHR implicit_outgoing_dep = { + .srcSubpass = 0, + .dstSubpass = VK_SUBPASS_EXTERNAL, + .srcStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + .dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + .srcAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_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, + .dstAccessMask = 0, + .dependencyFlags = 0, + }; + + radv_render_pass_add_subpass_dep(pass, &implicit_outgoing_dep); + } +} + static void radv_render_pass_compile(struct radv_render_pass *pass) { @@ -314,6 +398,9 @@ VkResult radv_CreateRenderPass( } } + bool has_ingoing_dep = false; + bool has_outgoing_dep = false; + for (unsigned i = 0; i < pCreateInfo->dependencyCount; ++i) { /* Convert to a Dependency2 */ struct VkSubpassDependency2 dep2 = { @@ -326,8 +413,19 @@ VkResult radv_CreateRenderPass( .dependencyFlags = pCreateInfo->pDependencies[i].dependencyFlags, }; radv_render_pass_add_subpass_dep(pass, &dep2); + + /* Determine if the subpass has explicit dependencies from/to + * VK_SUBPASS_EXTERNAL. + */ + if (pCreateInfo->pDependencies[i].srcSubpass == VK_SUBPASS_EXTERNAL) + has_ingoing_dep = true; + if (pCreateInfo->pDependencies[i].dstSubpass == VK_SUBPASS_EXTERNAL) + has_outgoing_dep = true; } + radv_render_pass_add_implicit_deps(pass, + has_ingoing_dep, has_outgoing_dep); + radv_render_pass_compile(pass); *pRenderPass = radv_render_pass_to_handle(pass); @@ -511,11 +609,25 @@ VkResult radv_CreateRenderPass2( } } + bool has_ingoing_dep = false; + bool has_outgoing_dep = false; + for (unsigned i = 0; i < pCreateInfo->dependencyCount; ++i) { radv_render_pass_add_subpass_dep(pass, &pCreateInfo->pDependencies[i]); + + /* Determine if the subpass has explicit dependencies from/to + * VK_SUBPASS_EXTERNAL. + */ + if (pCreateInfo->pDependencies[i].srcSubpass == VK_SUBPASS_EXTERNAL) + has_ingoing_dep = true; + if (pCreateInfo->pDependencies[i].dstSubpass == VK_SUBPASS_EXTERNAL) + has_outgoing_dep = true; } + radv_render_pass_add_implicit_deps(pass, + has_ingoing_dep, has_outgoing_dep); + radv_render_pass_compile(pass); *pRenderPass = radv_render_pass_to_handle(pass); -- 2.30.2