When multiview is active a subpass clear may only clear a subset of the
attachment layers. Other subpasses in the same render pass may also
clear too and we want to honor those clears as well, however, we need to
ensure that we only clear a layer once, on the first subpass that uses
a particular layer (view) of a given attachment.

This means that when we check if a subpass attachment needs to be cleared
we need to check if all the layers used by that subpass (as indicated by
its view_mask) have already been cleared in previous subpasses or not, in
which case, we must clear any pending layers used by the subpass, and only
those pending.

Fixes work-in-progress CTS tests:
dEQP-VK.multiview.readback_implicit_clear.*
---
 src/intel/vulkan/anv_blorp.c | 56 ++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 52 insertions(+), 4 deletions(-)

diff --git a/src/intel/vulkan/anv_blorp.c b/src/intel/vulkan/anv_blorp.c
index 18fa4a4ae5..0dac20ea80 100644
--- a/src/intel/vulkan/anv_blorp.c
+++ b/src/intel/vulkan/anv_blorp.c
@@ -1110,6 +1110,39 @@ enum subpass_stage {
    SUBPASS_STAGE_RESOLVE,
 };
 
+/**
+ * Goes through all the previous subpasses to the current subpass and collects
+ * information about the layers (views) of the given attachment that have
+ * already been cleared by previous subpasses. The function return the layers
+ * (views), if any, that still need to be cleared when current subpass starts.
+ */
+static uint32_t
+subpass_views_with_pending_clear(const struct anv_cmd_buffer *cmd_buffer,
+                                 const uint32_t att_idx)
+{
+   const struct anv_cmd_state *cmd_state = &cmd_buffer->state;
+   const struct anv_render_pass *pass = cmd_state->pass;
+   const struct anv_subpass *subpass = cmd_state->subpass;
+
+   if (!subpass->view_mask)
+      return 0;
+
+   uint32_t cleared_views = 0;
+   uint32_t subpass_idx = 0;
+   const struct anv_subpass *s = &pass->subpasses[subpass_idx];
+   while (s != subpass) {
+      for (uint32_t i = 0; i < s->color_count; i++) {
+         uint32_t idx = s->color_attachments[i].attachment;
+         if (idx != att_idx)
+            continue;
+         cleared_views |= s->view_mask;
+      }
+      s = &pass->subpasses[++subpass_idx];
+   }
+
+   return subpass->view_mask & (~cleared_views);
+}
+
 static bool
 subpass_needs_clear(const struct anv_cmd_buffer *cmd_buffer)
 {
@@ -1142,7 +1175,6 @@ anv_cmd_buffer_clear_subpass(struct anv_cmd_buffer 
*cmd_buffer)
    const struct anv_cmd_state *cmd_state = &cmd_buffer->state;
    const VkRect2D render_area = cmd_buffer->state.render_area;
 
-
    if (!subpass_needs_clear(cmd_buffer))
       return;
 
@@ -1205,7 +1237,9 @@ anv_cmd_buffer_clear_subpass(struct anv_cmd_buffer 
*cmd_buffer)
          assert(image->n_planes == 1);
          if (cmd_state->subpass->view_mask) {
             uint32_t view_idx;
-            for_each_bit(view_idx, cmd_state->subpass->view_mask) {
+            uint32_t pending_clear_mask =
+               subpass_views_with_pending_clear(cmd_buffer, a);
+            for_each_bit(view_idx, pending_clear_mask) {
                blorp_fast_clear(&batch, &surf, iview->planes[0].isl.format,
                                 iview->planes[0].isl.base_level,
                                 view_idx, 1,
@@ -1227,7 +1261,9 @@ anv_cmd_buffer_clear_subpass(struct anv_cmd_buffer 
*cmd_buffer)
          assert(image->n_planes == 1);
          if (cmd_state->subpass->view_mask) {
             uint32_t view_idx;
-            for_each_bit(view_idx, cmd_state->subpass->view_mask) {
+            uint32_t pending_clear_mask =
+               subpass_views_with_pending_clear(cmd_buffer, a);
+            for_each_bit(view_idx, pending_clear_mask) {
                blorp_clear(&batch, &surf, iview->planes[0].isl.format,
                            
anv_swizzle_for_render(iview->planes[0].isl.swizzle),
                            iview->planes[0].isl.base_level,
@@ -1249,7 +1285,19 @@ anv_cmd_buffer_clear_subpass(struct anv_cmd_buffer 
*cmd_buffer)
          }
       }
 
-      att_state->pending_clear_aspects = 0;
+      if (!cmd_state->subpass->view_mask) {
+         att_state->pending_clear_aspects = 0;
+      } else {
+         /* If multiview is enabled, then we are only done clearing when the
+          * last subpass that uses this attachment has been processed,
+          */
+         uint32_t last_subpass_idx =
+            cmd_state->pass->attachments[a].last_subpass_idx;
+         const struct anv_subpass *last_subpass =
+            &cmd_state->pass->subpasses[last_subpass_idx];
+         if (last_subpass == cmd_state->subpass)
+            att_state->pending_clear_aspects = 0;
+      }
    }
 
    const uint32_t ds = cmd_state->subpass->depth_stencil_attachment.attachment;
-- 
2.11.0

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to