Mesa (main): vulkan/render_pass: Add a better helper for render pass inheritance

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri Jun 24 23:08:44 UTC 2022


Module: Mesa
Branch: main
Commit: 3a204d5cf370116a427361410a449dde002bc143
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=3a204d5cf370116a427361410a449dde002bc143

Author: Jason Ekstrand <jason.ekstrand at collabora.com>
Date:   Tue May 31 15:53:51 2022 -0500

vulkan/render_pass: Add a better helper for render pass inheritance

Instead of making drivers dive into the render pass and framebuffer
themselves, provide a helper that constructs a VkRenderingInfo for a
render pass resume that they can use instead.  This should reduce code
duplication between driver implementations of BeginRendering and
BeginCommandBuffer.

Reviewed-by: Samuel Pitoiset <samuel.pitoiset at gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/16953>

---

 src/vulkan/runtime/vk_render_pass.c | 120 ++++++++++++++++++++++++++++++++++++
 src/vulkan/runtime/vk_render_pass.h |  40 +++++++++++-
 2 files changed, 158 insertions(+), 2 deletions(-)

diff --git a/src/vulkan/runtime/vk_render_pass.c b/src/vulkan/runtime/vk_render_pass.c
index 6780baf75de..91f2a055d1e 100644
--- a/src/vulkan/runtime/vk_render_pass.c
+++ b/src/vulkan/runtime/vk_render_pass.c
@@ -820,6 +820,126 @@ vk_get_command_buffer_inheritance_rendering_info(
                                COMMAND_BUFFER_INHERITANCE_RENDERING_INFO);
 }
 
+const VkRenderingInfo *
+vk_get_command_buffer_inheritance_as_rendering_resume(
+   VkCommandBufferLevel level,
+   const VkCommandBufferBeginInfo *pBeginInfo,
+   void *stack_data)
+{
+   struct vk_gcbiarr_data *data = stack_data;
+
+   /* From the Vulkan 1.3.204 spec:
+    *
+    *    "VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT specifies that a
+    *    secondary command buffer is considered to be entirely inside a render
+    *    pass. If this is a primary command buffer, then this bit is ignored."
+    *
+    * Since we're only concerned with the continue case here, we can ignore
+    * any primary command buffers.
+    */
+   if (level == VK_COMMAND_BUFFER_LEVEL_PRIMARY)
+      return NULL;
+
+   if (!(pBeginInfo->flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT))
+      return NULL;
+
+   const VkCommandBufferInheritanceInfo *inheritance =
+      pBeginInfo->pInheritanceInfo;
+
+   VK_FROM_HANDLE(vk_render_pass, pass, inheritance->renderPass);
+   if (pass == NULL)
+      return NULL;
+
+   assert(inheritance->subpass < pass->subpass_count);
+   const struct vk_subpass *subpass = &pass->subpasses[inheritance->subpass];
+
+   VK_FROM_HANDLE(vk_framebuffer, fb, inheritance->framebuffer);
+   if (fb == NULL || (fb->flags & VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT_KHR))
+      return NULL;
+
+   data->rendering = (VkRenderingInfo) {
+      .sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
+      .flags = VK_RENDERING_RESUMING_BIT,
+      .renderArea = {
+         .offset = { 0, 0 },
+         .extent = { fb->width, fb->height },
+      },
+      .layerCount = fb->layers,
+      .viewMask = pass->is_multiview ? subpass->view_mask : 0,
+   };
+
+   VkRenderingAttachmentInfo *attachments = data->attachments;
+
+   for (unsigned i = 0; i < subpass->color_count; i++) {
+      const struct vk_subpass_attachment *sp_att =
+         &subpass->color_attachments[i];
+      if (sp_att->attachment == VK_ATTACHMENT_UNUSED) {
+         attachments[i] = (VkRenderingAttachmentInfo) {
+            .imageView = VK_NULL_HANDLE,
+         };
+         continue;
+      }
+
+      assert(sp_att->attachment < pass->attachment_count);
+      attachments[i] = (VkRenderingAttachmentInfo) {
+         .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
+         .imageView = fb->attachments[sp_att->attachment],
+         .imageLayout = sp_att->layout,
+         .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
+         .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
+      };
+   }
+   data->rendering.colorAttachmentCount = subpass->color_count;
+   data->rendering.pColorAttachments = attachments;
+   attachments += subpass->color_count;
+
+   if (subpass->depth_stencil_attachment) {
+      const struct vk_subpass_attachment *sp_att =
+         subpass->depth_stencil_attachment;
+      assert(sp_att->attachment < pass->attachment_count);
+
+      VK_FROM_HANDLE(vk_image_view, iview, fb->attachments[sp_att->attachment]);
+      if (iview->image->aspects & VK_IMAGE_ASPECT_DEPTH_BIT) {
+         *attachments = (VkRenderingAttachmentInfo) {
+            .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
+            .imageView = vk_image_view_to_handle(iview),
+            .imageLayout = sp_att->layout,
+            .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
+            .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
+         };
+         data->rendering.pDepthAttachment = attachments++;
+      }
+
+      if (iview->image->aspects & VK_IMAGE_ASPECT_STENCIL_BIT) {
+         *attachments = (VkRenderingAttachmentInfo) {
+            .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
+            .imageView = vk_image_view_to_handle(iview),
+            .imageLayout = sp_att->stencil_layout,
+            .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
+            .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
+         };
+         data->rendering.pStencilAttachment = attachments++;
+      }
+   }
+
+   if (subpass->fragment_shading_rate_attachment) {
+      const struct vk_subpass_attachment *sp_att =
+         subpass->fragment_shading_rate_attachment;
+      assert(sp_att->attachment < pass->attachment_count);
+
+      data->fsr_att = (VkRenderingFragmentShadingRateAttachmentInfoKHR) {
+         .sType = VK_STRUCTURE_TYPE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_INFO_KHR,
+         .imageView = fb->attachments[sp_att->attachment],
+         .imageLayout = sp_att->layout,
+         .shadingRateAttachmentTexelSize =
+            subpass->fragment_shading_rate_attachment_texel_size,
+      };
+      __vk_append_struct(&data->rendering, &data->fsr_att);
+   }
+
+   return &data->rendering;
+}
+
 VKAPI_ATTR void VKAPI_CALL
 vk_common_DestroyRenderPass(VkDevice _device,
                             VkRenderPass renderPass,
diff --git a/src/vulkan/runtime/vk_render_pass.h b/src/vulkan/runtime/vk_render_pass.h
index 8eb99455c93..59b40a25bf5 100644
--- a/src/vulkan/runtime/vk_render_pass.h
+++ b/src/vulkan/runtime/vk_render_pass.h
@@ -305,7 +305,7 @@ VK_DEFINE_NONDISP_HANDLE_CASTS(vk_render_pass, base, VkRenderPass,
 
 /** Returns the VkPipelineRenderingCreateInfo for a graphics pipeline
  *
- * For render-pass-free drivers, this can be used in the implementaiton of
+ * For render-pass-free drivers, this can be used in the implementation of
  * vkCreateGraphicsPipelines to get the VkPipelineRenderingCreateInfo.  If
  * VkGraphicsPipelineCreateInfo::renderPass is not VK_NULL_HANDLE, it will
  * return a representation of the specified subpass as a
@@ -322,7 +322,7 @@ vk_get_pipeline_rendering_create_info(const VkGraphicsPipelineCreateInfo *info);
  * Returns the VkCommandBufferInheritanceRenderingInfo for secondary command
  * buffer execution
  *
- * For render-pass-free drivers, this can be used in the implementaiton of
+ * For render-pass-free drivers, this can be used in the implementation of
  * vkCmdExecuteCommands to get the VkCommandBufferInheritanceRenderingInfo.
  * If VkCommandBufferInheritanceInfo::renderPass is not VK_NULL_HANDLE, it
  * will return a representation of the specified subpass as a
@@ -339,6 +339,42 @@ vk_get_command_buffer_inheritance_rendering_info(
    VkCommandBufferLevel level,
    const VkCommandBufferBeginInfo *pBeginInfo);
 
+struct vk_gcbiarr_data {
+   VkRenderingInfo rendering;
+   VkRenderingFragmentShadingRateAttachmentInfoKHR fsr_att;
+   VkRenderingAttachmentInfo attachments[];
+};
+
+#define VK_GCBIARR_DATA_SIZE(max_color_rts) (\
+   sizeof(struct vk_gcbiarr_data) + \
+   sizeof(VkRenderingAttachmentInfo) * ((max_color_rts) + 2) \
+)
+
+/**
+ * Constructs a VkRenderingInfo for the inheritance rendering info
+ *
+ * For render-pass-free drivers, this can be used in the implementaiton of
+ * vkCmdExecuteCommands to get a VkRenderingInfo representing the subpass and
+ * framebuffer provided via the inheritance info for a command buffer created
+ * with VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT.  The mental model
+ * here is that VkExecuteCommands() implicitly suspends the render pass and
+ * VkBeginCommandBuffer() resumes it.  If a VkRenderingInfo cannot be
+ * constructed due to a missing framebuffer or similar, NULL will be
+ * returned.
+ *
+ * @param[in]  level       The nesting level of this command buffer
+ * @param[in]  pBeginInfo  The pBeginInfo from vkBeginCommandBuffer
+ * @param[out] stack_data  An opaque blob of data which will be overwritten by
+ *                         this function, passed in from the caller to avoid
+ *                         heap allocations.  It must be at least
+ *                         VK_GCBIARR_DATA_SIZE(max_color_rts) bytes.
+ */
+const VkRenderingInfo *
+vk_get_command_buffer_inheritance_as_rendering_resume(
+   VkCommandBufferLevel level,
+   const VkCommandBufferBeginInfo *pBeginInfo,
+   void *stack_data);
+
 #ifdef __cplusplus
 }
 #endif



More information about the mesa-commit mailing list