Mesa (main): tu: Initial support for dynamic rendering

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Wed Jul 27 20:15:22 UTC 2022


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

Author: Connor Abbott <cwabbott0 at gmail.com>
Date:   Tue Jun 28 10:33:01 2022 +0200

tu: Initial support for dynamic rendering

Support for suspend/resume will be added later. This just sets up
the internal render pass, and adds support to pipeline creation and
secondary inheritance.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17378>

---

 src/freedreno/vulkan/tu_cmd_buffer.c | 147 +++++++++++++++++---
 src/freedreno/vulkan/tu_device.c     |  17 +++
 src/freedreno/vulkan/tu_image.c      |   1 +
 src/freedreno/vulkan/tu_pass.c       | 259 +++++++++++++++++++++++++++++++----
 src/freedreno/vulkan/tu_pipeline.c   | 109 ++++++++++-----
 src/freedreno/vulkan/tu_private.h    |  20 +++
 6 files changed, 477 insertions(+), 76 deletions(-)

diff --git a/src/freedreno/vulkan/tu_cmd_buffer.c b/src/freedreno/vulkan/tu_cmd_buffer.c
index c246d90293b..cd43c8fb53d 100644
--- a/src/freedreno/vulkan/tu_cmd_buffer.c
+++ b/src/freedreno/vulkan/tu_cmd_buffer.c
@@ -269,8 +269,22 @@ tu6_emit_mrt(struct tu_cmd_buffer *cmd,
 
    for (uint32_t i = 0; i < subpass->color_count; ++i) {
       uint32_t a = subpass->color_attachments[i].attachment;
-      if (a == VK_ATTACHMENT_UNUSED)
+      if (a == VK_ATTACHMENT_UNUSED) {
+         /* From the VkPipelineRenderingCreateInfo definition:
+          *
+          *    Valid formats indicate that an attachment can be used - but it
+          *    is still valid to set the attachment to NULL when beginning
+          *    rendering.
+          *
+          * This means that with dynamic rendering, pipelines may write to
+          * some attachments that are UNUSED here. Setting the format to 0
+          * here should prevent them from writing to anything.
+          */
+         tu_cs_emit_pkt4(cs, REG_A6XX_RB_MRT_BUF_INFO(i), 6);
+         for (unsigned i = 0; i < 6; i++)
+            tu_cs_emit(cs, 0);
          continue;
+      }
 
       const struct tu_image_view *iview = cmd->state.attachments[a];
 
@@ -1770,10 +1784,18 @@ tu_BeginCommandBuffer(VkCommandBuffer commandBuffer,
       }
 
       if (pBeginInfo->flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT) {
-         cmd_buffer->state.pass = tu_render_pass_from_handle(pBeginInfo->pInheritanceInfo->renderPass);
-         cmd_buffer->state.subpass =
-            &cmd_buffer->state.pass->subpasses[pBeginInfo->pInheritanceInfo->subpass];
-
+         if (pBeginInfo->pInheritanceInfo->renderPass) {
+            cmd_buffer->state.pass = tu_render_pass_from_handle(pBeginInfo->pInheritanceInfo->renderPass);
+            cmd_buffer->state.subpass =
+               &cmd_buffer->state.pass->subpasses[pBeginInfo->pInheritanceInfo->subpass];
+         } else {
+            const VkCommandBufferInheritanceRenderingInfo *rendering_info =
+               vk_find_struct_const(pBeginInfo->pInheritanceInfo->pNext,
+                                    COMMAND_BUFFER_INHERITANCE_RENDERING_INFO);
+            tu_setup_dynamic_inheritance(cmd_buffer, rendering_info);
+            cmd_buffer->state.pass = &cmd_buffer->dynamic_pass;
+            cmd_buffer->state.subpass = &cmd_buffer->dynamic_subpass;
+         }
          tu_lrz_begin_secondary_cmdbuf(cmd_buffer);
       } else {
          /* When executing in the middle of another command buffer, the CCU
@@ -3590,6 +3612,85 @@ tu_CmdBeginRenderPass2(VkCommandBuffer commandBuffer,
    tu_emit_subpass_begin(cmd);
 }
 
+VKAPI_ATTR void VKAPI_CALL
+tu_CmdBeginRendering(VkCommandBuffer commandBuffer,
+                     const VkRenderingInfo *pRenderingInfo)
+{
+   TU_FROM_HANDLE(tu_cmd_buffer, cmd, commandBuffer);
+   VkClearValue clear_values[2 * (MAX_RTS + 1)];
+
+   tu_setup_dynamic_render_pass(cmd, pRenderingInfo);
+   tu_setup_dynamic_framebuffer(cmd, pRenderingInfo);
+
+   cmd->state.pass = &cmd->dynamic_pass;
+   cmd->state.subpass = &cmd->dynamic_subpass;
+   cmd->state.framebuffer = &cmd->dynamic_framebuffer;
+   cmd->state.render_area = pRenderingInfo->renderArea;
+
+   cmd->state.attachments = cmd->dynamic_attachments;
+
+   cmd->state.draw_cs_writes_to_cond_pred = false;
+
+   for (unsigned i = 0; i < pRenderingInfo->colorAttachmentCount; i++) {
+      uint32_t a = cmd->dynamic_subpass.color_attachments[i].attachment;
+      if (!pRenderingInfo->pColorAttachments[i].imageView)
+         continue;
+
+      TU_FROM_HANDLE(tu_image_view, view,
+                     pRenderingInfo->pColorAttachments[i].imageView);
+      cmd->state.attachments[a] = view;
+      clear_values[a] = pRenderingInfo->pColorAttachments[i].clearValue;
+
+      a = cmd->dynamic_subpass.resolve_attachments[i].attachment;
+      if (a != VK_ATTACHMENT_UNUSED) {
+         TU_FROM_HANDLE(tu_image_view, resolve_view,
+                        pRenderingInfo->pColorAttachments[i].resolveImageView);
+         cmd->state.attachments[a] = resolve_view;
+      }
+   }
+
+   uint32_t a = cmd->dynamic_subpass.depth_stencil_attachment.attachment;
+   if (pRenderingInfo->pDepthAttachment || pRenderingInfo->pStencilAttachment) {
+      const struct VkRenderingAttachmentInfo *common_info =
+         (pRenderingInfo->pDepthAttachment &&
+          pRenderingInfo->pDepthAttachment->imageView != VK_NULL_HANDLE) ?
+         pRenderingInfo->pDepthAttachment :
+         pRenderingInfo->pStencilAttachment;
+      if (common_info && common_info->imageView != VK_NULL_HANDLE) {
+         TU_FROM_HANDLE(tu_image_view, view, common_info->imageView);
+         cmd->state.attachments[a] = view;
+         if (pRenderingInfo->pDepthAttachment) {
+            clear_values[a].depthStencil.depth =
+               pRenderingInfo->pDepthAttachment->clearValue.depthStencil.depth;
+         }
+
+         if (pRenderingInfo->pStencilAttachment) {
+            clear_values[a].depthStencil.stencil =
+               pRenderingInfo->pStencilAttachment->clearValue.depthStencil.stencil;
+         }
+
+         if (cmd->dynamic_subpass.resolve_count >
+             cmd->dynamic_subpass.color_count) {
+            TU_FROM_HANDLE(tu_image_view, resolve_view,
+                           common_info->resolveImageView);
+            a = cmd->dynamic_subpass.resolve_attachments[cmd->dynamic_subpass.color_count].attachment;
+            cmd->state.attachments[a] = resolve_view;
+         }
+      }
+   }
+
+   cmd->state.renderpass_cache.pending_flush_bits =
+      cmd->state.cache.pending_flush_bits;
+   cmd->state.renderpass_cache.flush_bits = 0;
+
+   trace_start_render_pass(&cmd->trace, &cmd->cs);
+
+   cmd->trace_renderpass_start = u_trace_end_iterator(&cmd->trace);
+
+   tu_emit_renderpass_begin(cmd, clear_values);
+   tu_emit_subpass_begin(cmd);
+}
+
 VKAPI_ATTR void VKAPI_CALL
 tu_CmdNextSubpass2(VkCommandBuffer commandBuffer,
                    const VkSubpassBeginInfo *pSubpassBeginInfo,
@@ -4698,12 +4799,9 @@ tu_CmdDispatchIndirect(VkCommandBuffer commandBuffer,
    tu_dispatch(cmd_buffer, &info);
 }
 
-VKAPI_ATTR void VKAPI_CALL
-tu_CmdEndRenderPass2(VkCommandBuffer commandBuffer,
-                     const VkSubpassEndInfo *pSubpassEndInfo)
+static void
+tu_end_rendering(struct tu_cmd_buffer *cmd_buffer)
 {
-   TU_FROM_HANDLE(tu_cmd_buffer, cmd_buffer, commandBuffer);
-
    tu_cs_end(&cmd_buffer->draw_cs);
    tu_cs_end(&cmd_buffer->draw_epilogue_cs);
 
@@ -4731,12 +4829,6 @@ tu_CmdEndRenderPass2(VkCommandBuffer commandBuffer,
    tu_cs_discard_entries(&cmd_buffer->draw_epilogue_cs);
    tu_cs_begin(&cmd_buffer->draw_epilogue_cs);
 
-   cmd_buffer->state.cache.pending_flush_bits |=
-      cmd_buffer->state.renderpass_cache.pending_flush_bits;
-   tu_subpass_barrier(cmd_buffer, &cmd_buffer->state.pass->end_barrier, true);
-
-   vk_free(&cmd_buffer->pool->vk.alloc, cmd_buffer->state.attachments);
-
    cmd_buffer->state.pass = NULL;
    cmd_buffer->state.subpass = NULL;
    cmd_buffer->state.framebuffer = NULL;
@@ -4754,6 +4846,29 @@ tu_CmdEndRenderPass2(VkCommandBuffer commandBuffer,
    cmd_buffer->state.dirty |= TU_CMD_DIRTY_LRZ;
 }
 
+VKAPI_ATTR void VKAPI_CALL
+tu_CmdEndRenderPass2(VkCommandBuffer commandBuffer,
+                     const VkSubpassEndInfo *pSubpassEndInfo)
+{
+   TU_FROM_HANDLE(tu_cmd_buffer, cmd_buffer, commandBuffer);
+
+   tu_end_rendering(cmd_buffer);
+
+   cmd_buffer->state.cache.pending_flush_bits |=
+      cmd_buffer->state.renderpass_cache.pending_flush_bits;
+   tu_subpass_barrier(cmd_buffer, &cmd_buffer->state.pass->end_barrier, true);
+
+   vk_free(&cmd_buffer->pool->vk.alloc, cmd_buffer->state.attachments);
+}
+
+VKAPI_ATTR void VKAPI_CALL
+tu_CmdEndRendering(VkCommandBuffer commandBuffer)
+{
+   TU_FROM_HANDLE(tu_cmd_buffer, cmd_buffer, commandBuffer);
+
+   tu_end_rendering(cmd_buffer);
+}
+
 static void
 tu_barrier(struct tu_cmd_buffer *cmd,
            const VkDependencyInfo *dep_info)
diff --git a/src/freedreno/vulkan/tu_device.c b/src/freedreno/vulkan/tu_device.c
index 4dccc2f033e..1986701c796 100644
--- a/src/freedreno/vulkan/tu_device.c
+++ b/src/freedreno/vulkan/tu_device.c
@@ -2628,6 +2628,23 @@ tu_CreateFramebuffer(VkDevice _device,
    return VK_SUCCESS;
 }
 
+void
+tu_setup_dynamic_framebuffer(struct tu_cmd_buffer *cmd_buffer,
+                             const VkRenderingInfo *pRenderingInfo)
+{
+   struct tu_render_pass *pass = &cmd_buffer->dynamic_pass;
+   struct tu_framebuffer *framebuffer = &cmd_buffer->dynamic_framebuffer;
+
+   framebuffer->attachment_count = pass->attachment_count;
+   framebuffer->width = pRenderingInfo->renderArea.offset.x +
+      pRenderingInfo->renderArea.extent.width;
+   framebuffer->height = pRenderingInfo->renderArea.offset.y +
+      pRenderingInfo->renderArea.extent.height;
+   framebuffer->layers = pRenderingInfo->layerCount;
+
+   tu_framebuffer_tiling_config(framebuffer, cmd_buffer->device, pass);
+}
+
 VKAPI_ATTR void VKAPI_CALL
 tu_DestroyFramebuffer(VkDevice _device,
                       VkFramebuffer _fb,
diff --git a/src/freedreno/vulkan/tu_image.c b/src/freedreno/vulkan/tu_image.c
index bf892ccbdf8..d04b4860ebf 100644
--- a/src/freedreno/vulkan/tu_image.c
+++ b/src/freedreno/vulkan/tu_image.c
@@ -180,6 +180,7 @@ tu_image_view_init(struct tu_image_view *iview,
       vk_find_struct_const(pCreateInfo->pNext, IMAGE_VIEW_MIN_LOD_CREATE_INFO_EXT);
 
    iview->image = image;
+   iview->format = pCreateInfo->format;
 
    const struct fdl_layout *layouts[3];
 
diff --git a/src/freedreno/vulkan/tu_pass.c b/src/freedreno/vulkan/tu_pass.c
index 7eab7ad4a5c..97838d639af 100644
--- a/src/freedreno/vulkan/tu_pass.c
+++ b/src/freedreno/vulkan/tu_pass.c
@@ -523,6 +523,19 @@ static void update_samples(struct tu_subpass *subpass,
    subpass->samples = samples;
 }
 
+static void
+tu_render_pass_cond_config(struct tu_render_pass *pass)
+{
+   for (uint32_t i = 0; i < pass->attachment_count; i++) {
+      struct tu_render_pass_attachment *att = &pass->attachments[i];
+
+      att->cond_load_allowed =
+         (att->load || att->load_stencil) && !att->clear_mask && !att->will_be_resolved;
+      att->cond_store_allowed =
+         (att->store || att->store_stencil) && !att->clear_mask;
+   }
+}
+
 static void
 tu_render_pass_gmem_config(struct tu_render_pass *pass,
                            const struct tu_physical_device *phys_dev)
@@ -626,6 +639,32 @@ tu_render_pass_gmem_config(struct tu_render_pass *pass,
       pass->gmem_pixels = pixels;
 }
 
+static void
+tu_render_pass_bandwidth_config(struct tu_render_pass *pass)
+{
+   for (uint32_t i = 0; i < pass->attachment_count; i++) {
+      const struct tu_render_pass_attachment *att = &pass->attachments[i];
+
+      /* approximate tu_load_gmem_attachment */
+      if (att->load)
+         pass->gmem_bandwidth_per_pixel += att->cpp;
+
+      /* approximate tu_store_gmem_attachment */
+      if (att->store)
+         pass->gmem_bandwidth_per_pixel += att->cpp;
+
+      /* approximate tu_clear_sysmem_attachment */
+      if (att->clear_mask)
+         pass->sysmem_bandwidth_per_pixel += att->cpp;
+
+      /* approximate tu6_emit_sysmem_resolves */
+      if (att->will_be_resolved) {
+         pass->sysmem_bandwidth_per_pixel +=
+            att->cpp + att->cpp / att->samples;
+      }
+   }
+}
+
 static void
 attachment_set_ops(struct tu_device *device,
                    struct tu_render_pass_attachment *att,
@@ -876,36 +915,11 @@ tu_CreateRenderPass2(VkDevice _device,
          att->clear_mask = 0;
          att->load = false;
       }
-
-      att->cond_load_allowed =
-         (att->load || att->load_stencil) && !att->clear_mask && !att->will_be_resolved;
-      att->cond_store_allowed =
-         (att->store || att->store_stencil) && !att->clear_mask;
    }
 
+   tu_render_pass_cond_config(pass);
    tu_render_pass_gmem_config(pass, device->physical_device);
-
-   for (uint32_t i = 0; i < pass->attachment_count; i++) {
-      const struct tu_render_pass_attachment *att = &pass->attachments[i];
-
-      /* approximate tu_load_gmem_attachment */
-      if (att->load)
-         pass->gmem_bandwidth_per_pixel += att->cpp;
-
-      /* approximate tu_store_gmem_attachment */
-      if (att->store)
-         pass->gmem_bandwidth_per_pixel += att->cpp;
-
-      /* approximate tu_clear_sysmem_attachment */
-      if (att->clear_mask)
-         pass->sysmem_bandwidth_per_pixel += att->cpp;
-
-      /* approximate tu6_emit_sysmem_resolves */
-      if (att->will_be_resolved) {
-         pass->sysmem_bandwidth_per_pixel +=
-            att->cpp + att->cpp / att->samples;
-      }
-   }
+   tu_render_pass_bandwidth_config(pass);
 
    for (unsigned i = 0; i < pCreateInfo->dependencyCount; ++i) {
       tu_render_pass_add_subpass_dep(pass, &pCreateInfo->pDependencies[i]);
@@ -933,6 +947,197 @@ tu_DestroyRenderPass(VkDevice _device,
    vk_object_free(&device->vk, pAllocator, pass);
 }
 
+static void
+tu_setup_dynamic_attachment(struct tu_render_pass_attachment *att,
+                            struct tu_image_view *view)
+{
+   att->format = view->format;
+   att->samples = view->image->layout->nr_samples;
+
+   /* for d32s8, cpp is for the depth image, and
+    * att->samples will be used as the cpp for the stencil image
+    */
+   if (att->format == VK_FORMAT_D32_SFLOAT_S8_UINT)
+      att->cpp = 4 * att->samples;
+   else
+      att->cpp = vk_format_get_blocksize(att->format) * att->samples;
+}
+
+void
+tu_setup_dynamic_render_pass(struct tu_cmd_buffer *cmd_buffer,
+                             const VkRenderingInfo *info)
+{
+   struct tu_device *device = cmd_buffer->device;
+   struct tu_render_pass *pass = &cmd_buffer->dynamic_pass;
+   struct tu_subpass *subpass = &cmd_buffer->dynamic_subpass;
+
+   pass->subpass_count = 1;
+   pass->attachments = cmd_buffer->dynamic_rp_attachments;
+
+   subpass->color_count = subpass->resolve_count = info->colorAttachmentCount;
+   subpass->color_attachments = cmd_buffer->dynamic_color_attachments;
+   subpass->resolve_attachments = cmd_buffer->dynamic_resolve_attachments;
+   subpass->feedback_invalidate = false;
+   subpass->feedback_loop_ds = subpass->feedback_loop_color = false;
+   subpass->input_count = 0;
+   subpass->samples = 0;
+   subpass->srgb_cntl = 0;
+   subpass->raster_order_attachment_access = false;
+   subpass->multiview_mask = info->viewMask;
+
+   uint32_t a = 0;
+   for (uint32_t i = 0; i < info->colorAttachmentCount; i++) {
+      struct tu_render_pass_attachment *att = &pass->attachments[a];
+      const VkRenderingAttachmentInfo *att_info = &info->pColorAttachments[i];
+
+      if (att_info->imageView == VK_NULL_HANDLE) {
+         subpass->color_attachments[i].attachment = VK_ATTACHMENT_UNUSED;
+         subpass->resolve_attachments[i].attachment = VK_ATTACHMENT_UNUSED;
+         continue;
+      }
+
+      TU_FROM_HANDLE(tu_image_view, view, att_info->imageView);
+      tu_setup_dynamic_attachment(att, view);
+      att->gmem_offset = 0;
+      att->clear_views = info->viewMask;
+      attachment_set_ops(device, att, att_info->loadOp, 0,
+                         att_info->storeOp, 0);
+      subpass->color_attachments[i].attachment = a++;
+
+      subpass->samples = view->image->layout->nr_samples;
+
+      if (vk_format_is_srgb(view->format))
+         subpass->srgb_cntl |= 1 << i;
+
+      if (att_info->resolveMode != VK_RESOLVE_MODE_NONE) {
+         struct tu_render_pass_attachment *resolve_att = &pass->attachments[a];
+         TU_FROM_HANDLE(tu_image_view, resolve_view, att_info->resolveImageView);
+         tu_setup_dynamic_attachment(resolve_att, resolve_view);
+         resolve_att->gmem_offset = -1;
+         attachment_set_ops(device, resolve_att,
+                            VK_ATTACHMENT_LOAD_OP_DONT_CARE, 0,
+                            VK_ATTACHMENT_STORE_OP_STORE, 0);
+         subpass->resolve_attachments[i].attachment = a++;
+         att->will_be_resolved = true;
+      } else {
+         subpass->resolve_attachments[i].attachment = VK_ATTACHMENT_UNUSED;
+         att->will_be_resolved = false;
+      }
+   }
+
+   if (info->pDepthAttachment || info->pStencilAttachment) {
+      const struct VkRenderingAttachmentInfo *common_info =
+         (info->pDepthAttachment &&
+          info->pDepthAttachment->imageView != VK_NULL_HANDLE) ?
+         info->pDepthAttachment :
+         info->pStencilAttachment;
+
+      if (common_info && common_info->imageView != VK_NULL_HANDLE) {
+         TU_FROM_HANDLE(tu_image_view, view, common_info->imageView);
+
+         struct tu_render_pass_attachment *att = &pass->attachments[a];
+         tu_setup_dynamic_attachment(att, view);
+         att->gmem_offset = 0;
+         att->clear_views = info->viewMask;
+         subpass->depth_stencil_attachment.attachment = a++;
+
+         attachment_set_ops(device, att,
+                            info->pDepthAttachment ? info->pDepthAttachment->loadOp : 0,
+                            info->pStencilAttachment ? info->pStencilAttachment->loadOp : 0,
+                            info->pDepthAttachment ? info->pDepthAttachment->storeOp : 0,
+                            info->pStencilAttachment ? info->pStencilAttachment->storeOp : 0);
+
+         subpass->samples = view->image->layout->nr_samples;
+
+         if (common_info->resolveMode != VK_RESOLVE_MODE_NONE) {
+            unsigned i = subpass->resolve_count++;
+            struct tu_render_pass_attachment *resolve_att = &pass->attachments[a];
+            TU_FROM_HANDLE(tu_image_view, resolve_view,
+                           common_info->resolveImageView);
+            tu_setup_dynamic_attachment(resolve_att, resolve_view);
+            resolve_att->gmem_offset = -1;
+            attachment_set_ops(device, resolve_att,
+                               VK_ATTACHMENT_LOAD_OP_DONT_CARE,
+                               VK_ATTACHMENT_LOAD_OP_DONT_CARE,
+                               VK_ATTACHMENT_STORE_OP_STORE,
+                               VK_ATTACHMENT_STORE_OP_STORE);
+            subpass->resolve_attachments[i].attachment = a++;
+            att->will_be_resolved = true;
+            subpass->resolve_depth_stencil = true;
+         } else {
+            att->will_be_resolved = false;
+         }
+      } else {
+         subpass->depth_stencil_attachment.attachment = VK_ATTACHMENT_UNUSED;
+      }
+   } else {
+      subpass->depth_stencil_attachment.attachment = VK_ATTACHMENT_UNUSED;
+   }
+
+   pass->attachment_count = a;
+
+   tu_render_pass_cond_config(pass);
+   tu_render_pass_gmem_config(pass, device->physical_device);
+   tu_render_pass_bandwidth_config(pass);
+}
+
+void
+tu_setup_dynamic_inheritance(struct tu_cmd_buffer *cmd_buffer,
+                             const VkCommandBufferInheritanceRenderingInfo *info)
+{
+   struct tu_render_pass *pass = &cmd_buffer->dynamic_pass;
+   struct tu_subpass *subpass = &cmd_buffer->dynamic_subpass;
+
+   pass->subpass_count = 1;
+   pass->attachments = cmd_buffer->dynamic_rp_attachments;
+
+   subpass->color_count = info->colorAttachmentCount;
+   subpass->resolve_count = 0;
+   subpass->color_attachments = cmd_buffer->dynamic_color_attachments;
+   subpass->resolve_attachments = NULL;
+   subpass->feedback_invalidate = false;
+   subpass->feedback_loop_ds = subpass->feedback_loop_color = false;
+   subpass->input_count = 0;
+   subpass->samples = 0;
+   subpass->srgb_cntl = 0;
+   subpass->raster_order_attachment_access = false;
+   subpass->multiview_mask = info->viewMask;
+   subpass->samples = info->rasterizationSamples;
+
+   unsigned a = 0;
+   for (unsigned i = 0; i < info->colorAttachmentCount; i++) {
+      struct tu_render_pass_attachment *att = &pass->attachments[a];
+      VkFormat format = info->pColorAttachmentFormats[i];
+
+      if (format == VK_FORMAT_UNDEFINED) {
+         subpass->color_attachments[i].attachment = VK_ATTACHMENT_UNUSED;
+         continue;
+      }
+
+      att->format = format;
+      att->samples = info->rasterizationSamples;
+      subpass->samples = info->rasterizationSamples;
+      subpass->color_attachments[i].attachment = a++;
+
+      /* conservatively assume that the attachment may be conditionally
+       * loaded/stored.
+       */
+      att->cond_load_allowed = att->cond_store_allowed = true;
+   }
+
+   if (info->depthAttachmentFormat != VK_FORMAT_UNDEFINED ||
+       info->stencilAttachmentFormat != VK_FORMAT_UNDEFINED) {
+      struct tu_render_pass_attachment *att = &pass->attachments[a];
+      att->format = info->depthAttachmentFormat != VK_FORMAT_UNDEFINED ?
+         info->depthAttachmentFormat : info->stencilAttachmentFormat;
+      att->samples = info->rasterizationSamples;
+      subpass->depth_stencil_attachment.attachment = a++;
+      att->cond_load_allowed = att->cond_store_allowed = true;
+   } else {
+      subpass->depth_stencil_attachment.attachment = VK_ATTACHMENT_UNUSED;
+   }
+}
+
 VKAPI_ATTR void VKAPI_CALL
 tu_GetRenderAreaGranularity(VkDevice _device,
                             VkRenderPass renderPass,
diff --git a/src/freedreno/vulkan/tu_pipeline.c b/src/freedreno/vulkan/tu_pipeline.c
index bdda536fbb8..90acc12a3f2 100644
--- a/src/freedreno/vulkan/tu_pipeline.c
+++ b/src/freedreno/vulkan/tu_pipeline.c
@@ -3890,24 +3890,85 @@ tu_pipeline_builder_init_graphics(
       }
    }
 
-   const struct tu_render_pass *pass =
-      tu_render_pass_from_handle(create_info->renderPass);
-   const struct tu_subpass *subpass =
-      &pass->subpasses[create_info->subpass];
-
-   builder->subpass_raster_order_attachment_access =
-      subpass->raster_order_attachment_access;
-   builder->subpass_feedback_loop_color = subpass->feedback_loop_color;
-   builder->subpass_feedback_loop_ds = subpass->feedback_loop_ds;
-
-   builder->multiview_mask = subpass->multiview_mask;
-
    builder->rasterizer_discard =
       builder->create_info->pRasterizationState->rasterizerDiscardEnable &&
       !rasterizer_discard_dynamic;
 
-   /* variableMultisampleRate support */
-   builder->emit_msaa_state = (subpass->samples == 0) && !builder->rasterizer_discard;
+   const VkPipelineRenderingCreateInfo *rendering_info =
+      vk_find_struct_const(create_info->pNext, PIPELINE_RENDERING_CREATE_INFO);
+
+   if (rendering_info) {
+      builder->subpass_raster_order_attachment_access = false;
+      builder->subpass_feedback_loop_ds = false;
+      builder->subpass_feedback_loop_color = false;
+
+      builder->multiview_mask = rendering_info->viewMask;
+
+      /* We don't know with dynamic rendering whether the pipeline will be
+       * used in a render pass with none of attachments enabled, so we have to
+       * dynamically emit MSAA state.
+       *
+       * TODO: Move MSAA state to a separate draw state and emit it
+       * dynamically only when the sample count is different from the
+       * subpass's sample count.
+       */
+      builder->emit_msaa_state = !builder->rasterizer_discard;
+
+      if (!builder->rasterizer_discard) {
+         builder->depth_attachment_format =
+            rendering_info->depthAttachmentFormat == VK_FORMAT_UNDEFINED ?
+            rendering_info->stencilAttachmentFormat :
+            rendering_info->depthAttachmentFormat;
+
+         builder->color_attachment_count =
+            rendering_info->colorAttachmentCount;
+
+         for (unsigned i = 0; i < rendering_info->colorAttachmentCount; i++) {
+            builder->color_attachment_formats[i] =
+               rendering_info->pColorAttachmentFormats[i];
+            if (builder->color_attachment_formats[i] != VK_FORMAT_UNDEFINED) {
+               builder->use_color_attachments = true;
+               builder->render_components |= 0xf << (i * 4);
+            }
+         }
+      }
+   } else {
+      const struct tu_render_pass *pass =
+         tu_render_pass_from_handle(create_info->renderPass);
+      const struct tu_subpass *subpass =
+         &pass->subpasses[create_info->subpass];
+
+      builder->subpass_raster_order_attachment_access =
+         subpass->raster_order_attachment_access;
+      builder->subpass_feedback_loop_color = subpass->feedback_loop_color;
+      builder->subpass_feedback_loop_ds = subpass->feedback_loop_ds;
+
+      builder->multiview_mask = subpass->multiview_mask;
+
+      /* variableMultisampleRate support */
+      builder->emit_msaa_state = (subpass->samples == 0) && !builder->rasterizer_discard;
+
+      if (!builder->rasterizer_discard) {
+         const uint32_t a = subpass->depth_stencil_attachment.attachment;
+         builder->depth_attachment_format = (a != VK_ATTACHMENT_UNUSED) ?
+            pass->attachments[a].format : VK_FORMAT_UNDEFINED;
+
+         assert(subpass->color_count == 0 ||
+                !create_info->pColorBlendState ||
+                subpass->color_count == create_info->pColorBlendState->attachmentCount);
+         builder->color_attachment_count = subpass->color_count;
+         for (uint32_t i = 0; i < subpass->color_count; i++) {
+            const uint32_t a = subpass->color_attachments[i].attachment;
+            if (a == VK_ATTACHMENT_UNUSED)
+               continue;
+
+            builder->color_attachment_formats[i] = pass->attachments[a].format;
+            builder->use_color_attachments = true;
+            builder->render_components |= 0xf << (i * 4);
+         }
+      }
+   }
+
 
    if (builder->rasterizer_discard) {
       builder->samples = VK_SAMPLE_COUNT_1_BIT;
@@ -3915,29 +3976,11 @@ tu_pipeline_builder_init_graphics(
       builder->samples = create_info->pMultisampleState->rasterizationSamples;
       builder->alpha_to_coverage = create_info->pMultisampleState->alphaToCoverageEnable;
 
-      const uint32_t a = subpass->depth_stencil_attachment.attachment;
-      builder->depth_attachment_format = (a != VK_ATTACHMENT_UNUSED) ?
-         pass->attachments[a].format : VK_FORMAT_UNDEFINED;
-
-      assert(subpass->color_count == 0 ||
-             !create_info->pColorBlendState ||
-             subpass->color_count == create_info->pColorBlendState->attachmentCount);
-      builder->color_attachment_count = subpass->color_count;
-      for (uint32_t i = 0; i < subpass->color_count; i++) {
-         const uint32_t a = subpass->color_attachments[i].attachment;
-         if (a == VK_ATTACHMENT_UNUSED)
-            continue;
-
-         builder->color_attachment_formats[i] = pass->attachments[a].format;
-         builder->use_color_attachments = true;
-         builder->render_components |= 0xf << (i * 4);
-      }
-
       if (tu_blend_state_is_dual_src(create_info->pColorBlendState)) {
          builder->color_attachment_count++;
          builder->use_dual_src_blend = true;
          /* dual source blending has an extra fs output in the 2nd slot */
-         if (subpass->color_attachments[0].attachment != VK_ATTACHMENT_UNUSED)
+         if (builder->color_attachment_formats[0] != VK_FORMAT_UNDEFINED)
             builder->render_components |= 0xf << 4;
       }
    }
diff --git a/src/freedreno/vulkan/tu_private.h b/src/freedreno/vulkan/tu_private.h
index 7eeef5c0f2f..f835874bcf7 100644
--- a/src/freedreno/vulkan/tu_private.h
+++ b/src/freedreno/vulkan/tu_private.h
@@ -1459,6 +1459,15 @@ struct tu_cmd_buffer
 
    struct tu_descriptor_state descriptors[MAX_BIND_POINTS];
 
+   struct tu_render_pass_attachment dynamic_rp_attachments[2 * (MAX_RTS + 1)];
+   struct tu_subpass_attachment dynamic_color_attachments[MAX_RTS];
+   struct tu_subpass_attachment dynamic_resolve_attachments[MAX_RTS + 1];
+   const struct tu_image_view *dynamic_attachments[2 * (MAX_RTS + 1)];
+
+   struct tu_render_pass dynamic_pass;
+   struct tu_subpass dynamic_subpass;
+   struct tu_framebuffer dynamic_framebuffer;
+
    VkResult record_result;
 
    struct tu_cs cs;
@@ -1492,6 +1501,15 @@ void tu_emit_cache_flush_ccu(struct tu_cmd_buffer *cmd_buffer,
                              struct tu_cs *cs,
                              enum tu_cmd_ccu_state ccu_state);
 
+void tu_setup_dynamic_render_pass(struct tu_cmd_buffer *cmd_buffer,
+                                  const VkRenderingInfo *pRenderingInfo);
+
+void tu_setup_dynamic_inheritance(struct tu_cmd_buffer *cmd_buffer,
+                                  const VkCommandBufferInheritanceRenderingInfo *info);
+
+void tu_setup_dynamic_framebuffer(struct tu_cmd_buffer *cmd_buffer,
+                                  const VkRenderingInfo *pRenderingInfo);
+
 void
 tu6_emit_event_write(struct tu_cmd_buffer *cmd,
                      struct tu_cs *cs,
@@ -1936,6 +1954,8 @@ struct tu_image_view
 
    struct tu_image *image; /**< VkImageViewCreateInfo::image */
 
+   VkFormat format;
+
    struct fdl6_view view;
 
    /* for d32s8 separate depth */



More information about the mesa-commit mailing list