From e5bbf8be36659ec700f416bbf5fc57d92127bfac Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Fri, 10 Mar 2017 17:29:24 -0800 Subject: [PATCH] anv/pass: Record required pipe flushes Reviewed-by: Nanley Chery --- src/intel/vulkan/anv_pass.c | 88 ++++++++++++++++++++++++++++++++++ src/intel/vulkan/anv_private.h | 2 + 2 files changed, 90 insertions(+) diff --git a/src/intel/vulkan/anv_pass.c b/src/intel/vulkan/anv_pass.c index 15c42758f00..dcd9aafc645 100644 --- a/src/intel/vulkan/anv_pass.c +++ b/src/intel/vulkan/anv_pass.c @@ -45,11 +45,13 @@ VkResult anv_CreateRenderPass( struct anv_render_pass *pass; struct anv_subpass *subpasses; struct anv_render_pass_attachment *attachments; + enum anv_pipe_bits *subpass_flushes; ANV_MULTIALLOC(ma); anv_multialloc_add(&ma, &pass, 1); anv_multialloc_add(&ma, &subpasses, pCreateInfo->subpassCount); anv_multialloc_add(&ma, &attachments, pCreateInfo->attachmentCount); + anv_multialloc_add(&ma, &subpass_flushes, pCreateInfo->subpassCount + 1); VkAttachmentReference *subpass_attachments; uint32_t subpass_attachment_count = 0; @@ -74,6 +76,7 @@ VkResult anv_CreateRenderPass( pass->attachment_count = pCreateInfo->attachmentCount; pass->subpass_count = pCreateInfo->subpassCount; pass->attachments = attachments; + pass->subpass_flushes = subpass_flushes; for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) { struct anv_render_pass_attachment *att = &pass->attachments[i]; @@ -90,6 +93,7 @@ VkResult anv_CreateRenderPass( subpass_usages += pass->subpass_count; } + bool has_color = false, has_depth = false, has_input = false; for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) { const VkSubpassDescription *desc = &pCreateInfo->pSubpasses[i]; struct anv_subpass *subpass = &pass->subpasses[i]; @@ -107,6 +111,7 @@ VkResult anv_CreateRenderPass( uint32_t a = desc->pInputAttachments[j].attachment; subpass->input_attachments[j] = desc->pInputAttachments[j]; if (a != VK_ATTACHMENT_UNUSED) { + has_input = true; pass->attachments[a].usage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; pass->attachments[a].subpass_usage[i] |= ANV_SUBPASS_USAGE_INPUT; pass->attachments[a].last_subpass_idx = i; @@ -126,6 +131,7 @@ VkResult anv_CreateRenderPass( uint32_t a = desc->pColorAttachments[j].attachment; subpass->color_attachments[j] = desc->pColorAttachments[j]; if (a != VK_ATTACHMENT_UNUSED) { + has_color = true; pass->attachments[a].usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; pass->attachments[a].subpass_usage[i] |= ANV_SUBPASS_USAGE_DRAW; pass->attachments[a].last_subpass_idx = i; @@ -162,6 +168,7 @@ VkResult anv_CreateRenderPass( *subpass_attachments++ = subpass->depth_stencil_attachment = *desc->pDepthStencilAttachment; if (a != VK_ATTACHMENT_UNUSED) { + has_depth = true; pass->attachments[a].usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; pass->attachments[a].subpass_usage[i] |= ANV_SUBPASS_USAGE_DRAW; @@ -173,6 +180,87 @@ VkResult anv_CreateRenderPass( } } + for (uint32_t i = 0; i < pCreateInfo->dependencyCount; i++) { + const VkSubpassDependency *dep = &pCreateInfo->pDependencies[i]; + if (dep->dstSubpass == VK_SUBPASS_EXTERNAL) { + pass->subpass_flushes[pass->subpass_count] |= + anv_pipe_invalidate_bits_for_access_flags(dep->dstAccessMask); + } else { + assert(dep->dstSubpass < pass->subpass_count); + pass->subpass_flushes[dep->dstSubpass] |= + anv_pipe_invalidate_bits_for_access_flags(dep->dstAccessMask); + } + + if (dep->srcSubpass == VK_SUBPASS_EXTERNAL) { + pass->subpass_flushes[0] |= + anv_pipe_flush_bits_for_access_flags(dep->srcAccessMask); + } else { + assert(dep->srcSubpass < pass->subpass_count); + pass->subpass_flushes[dep->srcSubpass + 1] |= + anv_pipe_flush_bits_for_access_flags(dep->srcAccessMask); + } + } + + /* 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; + * }; + * + * We could implement this by walking over all of the attachments and + * subpasses and checking to see if any of them don't have an external + * dependency. Or, we could just be lazy and add a couple extra flushes. + * We choose to be lazy. + */ + if (has_input) { + pass->subpass_flushes[0] |= + ANV_PIPE_TEXTURE_CACHE_INVALIDATE_BIT; + } + if (has_color) { + pass->subpass_flushes[pass->subpass_count] |= + ANV_PIPE_RENDER_TARGET_CACHE_FLUSH_BIT; + } + if (has_depth) { + pass->subpass_flushes[pass->subpass_count] |= + ANV_PIPE_DEPTH_CACHE_FLUSH_BIT; + } + *pRenderPass = anv_render_pass_to_handle(pass); return VK_SUCCESS; diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h index 217c86c2929..7d079000b0c 100644 --- a/src/intel/vulkan/anv_private.h +++ b/src/intel/vulkan/anv_private.h @@ -2181,6 +2181,8 @@ struct anv_render_pass { uint32_t attachment_count; uint32_t subpass_count; VkAttachmentReference * subpass_attachments; + /* An array of subpass_count+1 flushes, one per subpass boundary */ + enum anv_pipe_bits * subpass_flushes; struct anv_render_pass_attachment * attachments; struct anv_subpass subpasses[0]; }; -- 2.30.2