[Mesa-dev] [PATCH 7/8] radv: add implicit external subpass dependencies

Fredrik Höglund fredrik at kde.org
Tue Jun 26 21:49:35 UTC 2018


Cc: <mesa-stable at lists.freedesktop.org>
Signed-off-by: Fredrik Höglund <fredrik at kde.org>
---
 src/amd/vulkan/radv_pass.c    | 107 +++++++++++++++++++++++++++++++---
 src/amd/vulkan/radv_private.h |   8 ++-
 2 files changed, 105 insertions(+), 10 deletions(-)

diff --git a/src/amd/vulkan/radv_pass.c b/src/amd/vulkan/radv_pass.c
index 17dafaca071..5bdaa7fd554 100644
--- a/src/amd/vulkan/radv_pass.c
+++ b/src/amd/vulkan/radv_pass.c
@@ -91,6 +91,8 @@ VkResult radv_CreateRenderPass(
 		att->final_layout =  pCreateInfo->pAttachments[i].finalLayout;
 		// att->store_op = pCreateInfo->pAttachments[i].storeOp;
 		// att->stencil_store_op = pCreateInfo->pAttachments[i].stencilStoreOp;
+		att->first_subpass = UINT32_MAX;
+		att->last_subpass = UINT32_MAX;
 	}
 
 	VkAttachmentReference *p = (void *) pass + subpass_attachments_offset;
@@ -109,10 +111,14 @@ VkResult radv_CreateRenderPass(
 			p += desc->inputAttachmentCount;
 
 			for (uint32_t j = 0; j < desc->inputAttachmentCount; j++) {
+				uint32_t a = desc->pInputAttachments[j].attachment;
 				subpass->input_attachments[j]
 					= desc->pInputAttachments[j];
-				if (desc->pInputAttachments[j].attachment != VK_ATTACHMENT_UNUSED)
-					pass->attachments[desc->pInputAttachments[j].attachment].view_mask |= subpass->view_mask;
+				if (a != VK_ATTACHMENT_UNUSED) {
+					pass->attachments[a].view_mask |= subpass->view_mask;
+					pass->attachments[a].first_subpass = MIN2(pass->attachments[a].first_subpass, i);
+					pass->attachments[a].last_subpass = i;
+				}
 			}
 		}
 
@@ -121,11 +127,14 @@ VkResult radv_CreateRenderPass(
 			p += desc->colorAttachmentCount;
 
 			for (uint32_t j = 0; j < desc->colorAttachmentCount; j++) {
+				uint32_t a = desc->pColorAttachments[j].attachment;
 				subpass->color_attachments[j]
 					= desc->pColorAttachments[j];
-				if (desc->pColorAttachments[j].attachment != VK_ATTACHMENT_UNUSED) {
-					pass->attachments[desc->pColorAttachments[j].attachment].view_mask |= subpass->view_mask;
-					color_sample_count = pCreateInfo->pAttachments[desc->pColorAttachments[j].attachment].samples;
+				if (a != VK_ATTACHMENT_UNUSED) {
+					pass->attachments[a].view_mask |= subpass->view_mask;
+					pass->attachments[a].first_subpass = MIN2(pass->attachments[a].first_subpass, i);
+					pass->attachments[a].last_subpass = i;
+					color_sample_count = pCreateInfo->pAttachments[a].samples;
 				}
 			}
 		}
@@ -141,17 +150,22 @@ VkResult radv_CreateRenderPass(
 					= desc->pResolveAttachments[j];
 				if (a != VK_ATTACHMENT_UNUSED) {
 					subpass->has_resolve = true;
-					pass->attachments[desc->pResolveAttachments[j].attachment].view_mask |= subpass->view_mask;
+					pass->attachments[a].view_mask |= subpass->view_mask;
+					pass->attachments[a].first_subpass = MIN2(pass->attachments[a].first_subpass, i);
+					pass->attachments[a].last_subpass = i;
 				}
 			}
 		}
 
 		if (desc->pDepthStencilAttachment) {
+			uint32_t a = desc->pDepthStencilAttachment->attachment;
 			subpass->depth_stencil_attachment =
 				*desc->pDepthStencilAttachment;
-			if (desc->pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) {
-				pass->attachments[desc->pDepthStencilAttachment->attachment].view_mask |= subpass->view_mask;
-				depth_sample_count = pCreateInfo->pAttachments[desc->pDepthStencilAttachment->attachment].samples;
+			if (a != VK_ATTACHMENT_UNUSED) {
+				pass->attachments[a].view_mask |= subpass->view_mask;
+				pass->attachments[a].first_subpass = MIN2(pass->attachments[a].first_subpass, i);
+				pass->attachments[a].last_subpass = i;
+				depth_sample_count = pCreateInfo->pAttachments[a].samples;
 			}
 		} else {
 			subpass->depth_stencil_attachment.attachment = VK_ATTACHMENT_UNUSED;
@@ -170,15 +184,21 @@ VkResult radv_CreateRenderPass(
 			continue;
 
 		if (src == VK_SUBPASS_EXTERNAL) {
+			assert(dst != VK_SUBPASS_EXTERNAL && dst < pCreateInfo->subpassCount);
+			pass->subpasses[dst].explicit_dependency_from_external = true;
+
 			/* Add all dependencies from external to the first subpass */
 			dst = 0;
 		}
 		if (dst == VK_SUBPASS_EXTERNAL) {
+			assert(src != VK_SUBPASS_EXTERNAL && src < pCreateInfo->subpassCount);
+			pass->subpasses[src].explicit_dependency_to_external = true;
 			if (pCreateInfo->pDependencies[i].dstStageMask != VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT)
 				pass->end_barrier.src_stage_mask |= pCreateInfo->pDependencies[i].srcStageMask;
 			pass->end_barrier.src_access_mask |= pCreateInfo->pDependencies[i].srcAccessMask;
 			pass->end_barrier.dst_access_mask |= pCreateInfo->pDependencies[i].dstAccessMask;
 		} else {
+			assert(dst < pCreateInfo->subpassCount);
 			if (pCreateInfo->pDependencies[i].dstStageMask != VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT)
 				pass->subpasses[dst].start_barrier.src_stage_mask |= pCreateInfo->pDependencies[i].srcStageMask;
 			pass->subpasses[dst].start_barrier.src_access_mask |= pCreateInfo->pDependencies[i].srcAccessMask;
@@ -186,6 +206,75 @@ VkResult radv_CreateRenderPass(
 		}
 	}
 
+	/* The Vulkan specification says:
+	 *
+	 *    "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;
+	 *     };"
+	 */
+	for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) {
+		const uint32_t first_subpass = pass->attachments[i].first_subpass;
+		const uint32_t last_subpass = pass->attachments[i].last_subpass;
+
+		/* Implicit dependency from external */
+		if (first_subpass != UINT32_MAX && !pass->subpasses[first_subpass].explicit_dependency_from_external) {
+			/* We always add the dependency to the first subpass to avoid repeating dependencies */
+			pass->subpasses[0].start_barrier.dst_access_mask |=
+				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;
+		}
+
+		/* Implicit dependency to external */
+		if (last_subpass != UINT32_MAX && !pass->subpasses[last_subpass].explicit_dependency_to_external) {
+			pass->end_barrier.src_access_mask |=
+				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;
+		}
+	}
+
 	*pRenderPass = radv_render_pass_to_handle(pass);
 
 	return VK_SUCCESS;
diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h
index 8627b3c7696..adf259981f1 100644
--- a/src/amd/vulkan/radv_private.h
+++ b/src/amd/vulkan/radv_private.h
@@ -1705,7 +1705,11 @@ struct radv_subpass {
 	VkAttachmentReference                        depth_stencil_attachment;
 
 	/** Subpass has at least one resolve attachment */
-	bool                                         has_resolve;
+	bool                                         has_resolve:1;
+
+	/** Used during renderpass creation */
+	bool                                         explicit_dependency_from_external:1;
+	bool                                         explicit_dependency_to_external:1;
 
 	struct radv_subpass_barrier                  start_barrier;
 
@@ -1721,6 +1725,8 @@ struct radv_render_pass_attachment {
 	VkImageLayout                                initial_layout;
 	VkImageLayout                                final_layout;
 	uint32_t                                     view_mask;
+	uint32_t                                     first_subpass;
+	uint32_t                                     last_subpass;
 };
 
 struct radv_render_pass {
-- 
2.17.0



More information about the mesa-dev mailing list