Mesa (main): v3dv: track first and last subpass that use a view index

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Tue Jul 27 07:45:58 UTC 2021


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

Author: Iago Toral Quiroga <itoral at igalia.com>
Date:   Fri Jul 23 12:21:38 2021 +0200

v3dv: track first and last subpass that use a view index

When multiview is enabled, we no longer care about when a particular
attachment is first or last used in a render pass, since not all views
in the attachment will meet that criteria. Instead, we need to track
each individual view (layer) in each attachment and emit our stores,
loads and clears accordingly.

Reviewed-by: Alejandro Piñeiro <apinheiro at igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12034>

---

 src/broadcom/vulkan/v3dv_limits.h      |  2 +
 src/broadcom/vulkan/v3dv_pass.c        | 28 ++++++++++---
 src/broadcom/vulkan/v3dv_private.h     | 12 ++++++
 src/broadcom/vulkan/v3dvx_cmd_buffer.c | 73 ++++++++++++++++++++++++----------
 4 files changed, 89 insertions(+), 26 deletions(-)

diff --git a/src/broadcom/vulkan/v3dv_limits.h b/src/broadcom/vulkan/v3dv_limits.h
index aff7305e5ce..aaab1ce03ac 100644
--- a/src/broadcom/vulkan/v3dv_limits.h
+++ b/src/broadcom/vulkan/v3dv_limits.h
@@ -53,6 +53,8 @@
 
 #define MAX_RENDER_TARGETS 4
 
+#define MAX_MULTIVIEW_VIEW_COUNT 16
+
 /* These are tunable parameters in the HW design, but all the V3D
  * implementations agree.
  */
diff --git a/src/broadcom/vulkan/v3dv_pass.c b/src/broadcom/vulkan/v3dv_pass.c
index 5df93c46fcf..464703e42a4 100644
--- a/src/broadcom/vulkan/v3dv_pass.c
+++ b/src/broadcom/vulkan/v3dv_pass.c
@@ -47,6 +47,12 @@ pass_find_subpass_range_for_attachments(struct v3dv_device *device,
    for (uint32_t i = 0; i < pass->attachment_count; i++) {
       pass->attachments[i].first_subpass = pass->subpass_count - 1;
       pass->attachments[i].last_subpass = 0;
+      if (pass->multiview_enabled) {
+         for (uint32_t j = 0; j < MAX_MULTIVIEW_VIEW_COUNT; j++) {
+            pass->attachments[i].views[j].first_subpass = pass->subpass_count - 1;
+            pass->attachments[i].views[j].last_subpass = 0;
+         }
+      }
    }
 
    for (uint32_t i = 0; i < pass->subpass_count; i++) {
@@ -57,14 +63,26 @@ pass_find_subpass_range_for_attachments(struct v3dv_device *device,
          if (attachment_idx == VK_ATTACHMENT_UNUSED)
             continue;
 
-         if (i < pass->attachments[attachment_idx].first_subpass)
-            pass->attachments[attachment_idx].first_subpass = i;
-         if (i > pass->attachments[attachment_idx].last_subpass)
-            pass->attachments[attachment_idx].last_subpass = i;
+         struct v3dv_render_pass_attachment *att =
+            &pass->attachments[attachment_idx];
+
+         if (i < att->first_subpass)
+            att->first_subpass = i;
+         if (i > att->last_subpass)
+            att->last_subpass = i;
+
+         uint32_t view_mask = subpass->view_mask;
+         while (view_mask) {
+            uint32_t view_index = u_bit_scan(&view_mask);
+            if (i < att->views[view_index].first_subpass)
+               att->views[view_index].first_subpass = i;
+            if (i > att->views[view_index].last_subpass)
+               att->views[view_index].last_subpass = i;
+         }
 
          if (subpass->resolve_attachments &&
              subpass->resolve_attachments[j].attachment != VK_ATTACHMENT_UNUSED) {
-            set_use_tlb_resolve(device, &pass->attachments[attachment_idx]);
+            set_use_tlb_resolve(device, att);
          }
       }
 
diff --git a/src/broadcom/vulkan/v3dv_private.h b/src/broadcom/vulkan/v3dv_private.h
index 14f140b5b3c..650fcec36db 100644
--- a/src/broadcom/vulkan/v3dv_private.h
+++ b/src/broadcom/vulkan/v3dv_private.h
@@ -658,9 +658,21 @@ struct v3dv_subpass {
 
 struct v3dv_render_pass_attachment {
    VkAttachmentDescription desc;
+
    uint32_t first_subpass;
    uint32_t last_subpass;
 
+   /* When multiview is enabled, we no longer care about when a particular
+    * attachment is first or last used in a render pass, since not all views
+    * in the attachment will meet that criteria. Instead, we need to track
+    * each individual view (layer) in each attachment and emit our stores,
+    * loads and clears accordingly.
+    */
+   struct {
+      uint32_t first_subpass;
+      uint32_t last_subpass;
+   } views[MAX_MULTIVIEW_VIEW_COUNT];
+
    /* If this is a multismapled attachment that is going to be resolved,
     * whether we can use the TLB resolve on store.
     */
diff --git a/src/broadcom/vulkan/v3dvx_cmd_buffer.c b/src/broadcom/vulkan/v3dvx_cmd_buffer.c
index 41046100e84..285fa87e6ce 100644
--- a/src/broadcom/vulkan/v3dvx_cmd_buffer.c
+++ b/src/broadcom/vulkan/v3dvx_cmd_buffer.c
@@ -137,7 +137,7 @@ cmd_buffer_render_pass_emit_load(struct v3dv_cmd_buffer *cmd_buffer,
 static bool
 check_needs_load(const struct v3dv_cmd_buffer_state *state,
                  VkImageAspectFlags aspect,
-                 uint32_t att_first_subpass_idx,
+                 uint32_t first_subpass_idx,
                  VkAttachmentLoadOp load_op)
 {
    /* We call this with image->aspects & aspect, so 0 means the aspect we are
@@ -146,10 +146,10 @@ check_needs_load(const struct v3dv_cmd_buffer_state *state,
    if (!aspect)
       return false;
 
-   /* Attachment load operations apply on the first subpass that uses the
-    * attachment, otherwise we always need to load.
+   /* Attachment (or view) load operations apply on the first subpass that
+    * uses the attachment (or view), otherwise we always need to load.
     */
-   if (state->job->first_subpass > att_first_subpass_idx)
+   if (state->job->first_subpass > first_subpass_idx)
       return true;
 
    /* If the job is continuing a subpass started in another job, we always
@@ -188,6 +188,8 @@ cmd_buffer_render_pass_emit_loads(struct v3dv_cmd_buffer *cmd_buffer,
    const struct v3dv_render_pass *pass = state->pass;
    const struct v3dv_subpass *subpass = &pass->subpasses[state->subpass_idx];
 
+  assert(!pass->multiview_enabled || layer < MAX_MULTIVIEW_VIEW_COUNT);
+
    for (uint32_t i = 0; i < subpass->color_count; i++) {
       uint32_t attachment_idx = subpass->color_attachments[i].attachment;
 
@@ -215,9 +217,13 @@ cmd_buffer_render_pass_emit_loads(struct v3dv_cmd_buffer *cmd_buffer,
        * load the tiles so we can preserve the pixels that are outside the
        * render area for any such tiles.
        */
+      uint32_t first_subpass = !pass->multiview_enabled ?
+         attachment->first_subpass :
+         attachment->views[layer].first_subpass;
+
       bool needs_load = check_needs_load(state,
                                          VK_IMAGE_ASPECT_COLOR_BIT,
-                                         attachment->first_subpass,
+                                         first_subpass,
                                          attachment->desc.loadOp);
       if (needs_load) {
          struct v3dv_image_view *iview = framebuffer->attachments[attachment_idx];
@@ -234,16 +240,20 @@ cmd_buffer_render_pass_emit_loads(struct v3dv_cmd_buffer *cmd_buffer,
       const VkImageAspectFlags ds_aspects =
          vk_format_aspects(ds_attachment->desc.format);
 
+      uint32_t ds_first_subpass = !pass->multiview_enabled ?
+         ds_attachment->first_subpass :
+         ds_attachment->views[layer].first_subpass;
+
       const bool needs_depth_load =
          check_needs_load(state,
                           ds_aspects & VK_IMAGE_ASPECT_DEPTH_BIT,
-                          ds_attachment->first_subpass,
+                          ds_first_subpass,
                           ds_attachment->desc.loadOp);
 
       const bool needs_stencil_load =
          check_needs_load(state,
                           ds_aspects & VK_IMAGE_ASPECT_STENCIL_BIT,
-                          ds_attachment->first_subpass,
+                          ds_first_subpass,
                           ds_attachment->desc.stencilLoadOp);
 
       if (needs_depth_load || needs_stencil_load) {
@@ -315,7 +325,7 @@ cmd_buffer_render_pass_emit_store(struct v3dv_cmd_buffer *cmd_buffer,
 static bool
 check_needs_clear(const struct v3dv_cmd_buffer_state *state,
                   VkImageAspectFlags aspect,
-                  uint32_t att_first_subpass_idx,
+                  uint32_t first_subpass_idx,
                   VkAttachmentLoadOp load_op,
                   bool do_clear_with_draw)
 {
@@ -344,9 +354,10 @@ check_needs_clear(const struct v3dv_cmd_buffer_state *state,
       return false;
 
    /* If this job is running in a subpass other than the first subpass in
-    * which this attachment is used then attachment load operations don't apply.
+    * which this attachment (or view) is used then attachment load operations
+    * don't apply.
     */
-   if (state->job->first_subpass != att_first_subpass_idx)
+   if (state->job->first_subpass != first_subpass_idx)
       return false;
 
    /* The attachment load operation must be CLEAR */
@@ -356,7 +367,7 @@ check_needs_clear(const struct v3dv_cmd_buffer_state *state,
 static bool
 check_needs_store(const struct v3dv_cmd_buffer_state *state,
                   VkImageAspectFlags aspect,
-                  uint32_t att_last_subpass_idx,
+                  uint32_t last_subpass_idx,
                   VkAttachmentStoreOp store_op)
 {
    /* We call this with image->aspects & aspect, so 0 means the aspect we are
@@ -365,10 +376,11 @@ check_needs_store(const struct v3dv_cmd_buffer_state *state,
    if (!aspect)
       return false;
 
-   /* Attachment store operations only apply on the last subpass where the
-    * attachment is used, in other subpasses we always need to store.
+   /* Attachment (or view) store operations only apply on the last subpass
+    * where the attachment (or view)  is used, in other subpasses we always
+    * need to store.
     */
-   if (state->subpass_idx < att_last_subpass_idx)
+   if (state->subpass_idx < last_subpass_idx)
       return true;
 
    /* Attachment store operations only apply on the last job we emit on the the
@@ -388,13 +400,16 @@ cmd_buffer_render_pass_emit_stores(struct v3dv_cmd_buffer *cmd_buffer,
                                    uint32_t layer)
 {
    struct v3dv_cmd_buffer_state *state = &cmd_buffer->state;
+   struct v3dv_render_pass *pass = state->pass;
    const struct v3dv_subpass *subpass =
-      &state->pass->subpasses[state->subpass_idx];
+      &pass->subpasses[state->subpass_idx];
 
    bool has_stores = false;
    bool use_global_zs_clear = false;
    bool use_global_rt_clear = false;
 
+   assert(!pass->multiview_enabled || layer < MAX_MULTIVIEW_VIEW_COUNT);
+
    /* FIXME: separate stencil */
    uint32_t ds_attachment_idx = subpass->ds_attachment.attachment;
    if (ds_attachment_idx != VK_ATTACHMENT_UNUSED) {
@@ -419,31 +434,39 @@ cmd_buffer_render_pass_emit_stores(struct v3dv_cmd_buffer *cmd_buffer,
          vk_format_aspects(ds_attachment->desc.format);
 
       /* Only clear once on the first subpass that uses the attachment */
+      uint32_t ds_first_subpass = !state->pass->multiview_enabled ?
+         ds_attachment->first_subpass :
+         ds_attachment->views[layer].first_subpass;
+
       bool needs_depth_clear =
          check_needs_clear(state,
                            aspects & VK_IMAGE_ASPECT_DEPTH_BIT,
-                           ds_attachment->first_subpass,
+                           ds_first_subpass,
                            ds_attachment->desc.loadOp,
                            subpass->do_depth_clear_with_draw);
 
       bool needs_stencil_clear =
          check_needs_clear(state,
                            aspects & VK_IMAGE_ASPECT_STENCIL_BIT,
-                           ds_attachment->first_subpass,
+                           ds_first_subpass,
                            ds_attachment->desc.stencilLoadOp,
                            subpass->do_stencil_clear_with_draw);
 
       /* Skip the last store if it is not required */
+      uint32_t ds_last_subpass = !pass->multiview_enabled ?
+         ds_attachment->last_subpass :
+         ds_attachment->views[layer].last_subpass;
+
       bool needs_depth_store =
          check_needs_store(state,
                            aspects & VK_IMAGE_ASPECT_DEPTH_BIT,
-                           ds_attachment->last_subpass,
+                           ds_last_subpass,
                            ds_attachment->desc.storeOp);
 
       bool needs_stencil_store =
          check_needs_store(state,
                            aspects & VK_IMAGE_ASPECT_STENCIL_BIT,
-                           ds_attachment->last_subpass,
+                           ds_last_subpass,
                            ds_attachment->desc.stencilStoreOp);
 
       /* GFXH-1689: The per-buffer store command's clear buffer bit is broken
@@ -494,18 +517,26 @@ cmd_buffer_render_pass_emit_stores(struct v3dv_cmd_buffer *cmd_buffer,
       assert(state->subpass_idx <= attachment->last_subpass);
 
       /* Only clear once on the first subpass that uses the attachment */
+      uint32_t first_subpass = !pass->multiview_enabled ?
+         attachment->first_subpass :
+         attachment->views[layer].first_subpass;
+
       bool needs_clear =
          check_needs_clear(state,
                            VK_IMAGE_ASPECT_COLOR_BIT,
-                           attachment->first_subpass,
+                           first_subpass,
                            attachment->desc.loadOp,
                            false);
 
       /* Skip the last store if it is not required  */
+      uint32_t last_subpass = !pass->multiview_enabled ?
+         attachment->last_subpass :
+         attachment->views[layer].last_subpass;
+
       bool needs_store =
          check_needs_store(state,
                            VK_IMAGE_ASPECT_COLOR_BIT,
-                           attachment->last_subpass,
+                           last_subpass,
                            attachment->desc.storeOp);
 
       /* If we need to resolve this attachment emit that store first. Notice



More information about the mesa-commit mailing list