[Mesa-dev] [PATCH v2 1/3] anv/blorp: consider multiview and view masks for tracking pending clear aspects

Iago Toral Quiroga itoral at igalia.com
Fri Feb 16 11:54:24 UTC 2018


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.

v2:
  - track pending clear views in the attachment state (Jason)
  - rebased on top of fast-clear rework.

Fixes:
dEQP-VK.multiview.readback_implicit_clear.*
---
 src/intel/vulkan/anv_blorp.c       | 86 ++++++++++++++++++++++++++++++++++++--
 src/intel/vulkan/anv_private.h     |  8 ++++
 src/intel/vulkan/genX_cmd_buffer.c |  2 +
 3 files changed, 92 insertions(+), 4 deletions(-)

diff --git a/src/intel/vulkan/anv_blorp.c b/src/intel/vulkan/anv_blorp.c
index df566773a4..ac3a434c94 100644
--- a/src/intel/vulkan/anv_blorp.c
+++ b/src/intel/vulkan/anv_blorp.c
@@ -963,6 +963,18 @@ binding_table_for_surface_state(struct anv_cmd_buffer *cmd_buffer,
    return VK_SUCCESS;
 }
 
+/**
+ * This ANDs the view mask of the current subpass with the pending clear
+ * views in the attachment to get the mask of views active in the subpass
+ * that still need to be cleared.
+ */
+static inline uint32_t
+get_multiview_subpass_clear_mask(const struct anv_cmd_state *cmd_state,
+                                 const struct anv_attachment_state *att_state)
+{
+   return cmd_state->subpass->view_mask & att_state->pending_clear_views;
+}
+
 static void
 clear_color_attachment(struct anv_cmd_buffer *cmd_buffer,
                        struct blorp_batch *batch,
@@ -1162,13 +1174,25 @@ subpass_needs_clear(const struct anv_cmd_buffer *cmd_buffer)
    return false;
 }
 
+static inline bool
+do_first_layer_clear(const struct anv_cmd_state *cmd_state,
+                     const struct anv_attachment_state *att_state)
+{
+   if (!cmd_state->subpass->view_mask)
+      return true;
+
+   uint32_t pending_clear_mask =
+      get_multiview_subpass_clear_mask(cmd_state, att_state);
+
+   return pending_clear_mask & 1;
+}
+
 void
 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;
 
@@ -1185,6 +1209,8 @@ anv_cmd_buffer_clear_subpass(struct anv_cmd_buffer *cmd_buffer)
       .layerCount = cmd_buffer->state.framebuffer->layers,
    };
 
+   bool is_multiview = cmd_state->subpass->view_mask;
+
    struct anv_framebuffer *fb = cmd_buffer->state.framebuffer;
    for (uint32_t i = 0; i < cmd_state->subpass->color_count; ++i) {
       const uint32_t a = cmd_state->subpass->color_attachments[i].attachment;
@@ -1209,7 +1235,7 @@ anv_cmd_buffer_clear_subpass(struct anv_cmd_buffer *cmd_buffer)
       uint32_t base_layer = iview->planes[0].isl.base_array_layer;
       uint32_t layer_count = fb->layers;
 
-      if (att_state->fast_clear) {
+      if (att_state->fast_clear && do_first_layer_clear(cmd_state, att_state)) {
          surf.clear_color = vk_to_isl_color(att_state->clear_value.color);
 
          /* From the Sky Lake PRM Vol. 7, "Render Target Fast Clear":
@@ -1242,12 +1268,48 @@ anv_cmd_buffer_clear_subpass(struct anv_cmd_buffer *cmd_buffer)
                           render_area.offset.y + render_area.extent.height);
          base_layer++;
          layer_count--;
+         if (is_multiview)
+            att_state->pending_clear_views &= ~1;
 
          cmd_buffer->state.pending_pipe_bits |=
             ANV_PIPE_RENDER_TARGET_CACHE_FLUSH_BIT | ANV_PIPE_CS_STALL_BIT;
       }
 
-      if (layer_count > 0) {
+      /* From the VkFramebufferCreateInfo spec:
+       *
+       * "If the render pass uses multiview, then layers must be one and each
+       *  attachment requires a number of layers that is greater than the
+       *  maximum bit index set in the view mask in the subpasses in which it
+       *  is used."
+       *
+       * So if multiview is active we ignore the number of layers in the
+       * framebuffer and instead we honor the view mask from the subpass.
+       */
+      if (is_multiview) {
+         assert(image->n_planes == 1);
+         uint32_t pending_clear_mask =
+            get_multiview_subpass_clear_mask(cmd_state, att_state);
+
+         uint32_t layer_idx;
+         for_each_bit(layer_idx, pending_clear_mask) {
+            uint32_t layer = iview->planes[0].isl.base_array_layer + layer_idx;
+            anv_cmd_buffer_mark_image_written(cmd_buffer, image,
+                                              VK_IMAGE_ASPECT_COLOR_BIT,
+                                              att_state->aux_usage,
+                                              iview->planes[0].isl.base_level,
+                                              layer, 1);
+
+            blorp_clear(&batch, &surf, iview->planes[0].isl.format,
+                        anv_swizzle_for_render(iview->planes[0].isl.swizzle),
+                        iview->planes[0].isl.base_level, layer, 1,
+                        render_area.offset.x, render_area.offset.y,
+                        render_area.offset.x + render_area.extent.width,
+                        render_area.offset.y + render_area.extent.height,
+                        vk_to_isl_color(att_state->clear_value.color), NULL);
+
+            att_state->pending_clear_views &= ~(1 << layer_idx);
+         }
+      } else if (layer_count > 0) {
          assert(image->n_planes == 1);
          anv_cmd_buffer_mark_image_written(cmd_buffer, image,
                                            VK_IMAGE_ASPECT_COLOR_BIT,
@@ -1264,7 +1326,23 @@ anv_cmd_buffer_clear_subpass(struct anv_cmd_buffer *cmd_buffer)
                      vk_to_isl_color(att_state->clear_value.color), NULL);
       }
 
-      att_state->pending_clear_aspects = 0;
+      /* If multiview is enabled, then we are only done clearing when we no
+       * longer have pending layers to clear, or when we have processed the
+       * last subpass that uses this attachment.
+       */
+      if (!is_multiview) {
+         att_state->pending_clear_aspects = 0;
+      } else if (att_state->pending_clear_views == 0) {
+         att_state->pending_clear_aspects = 0;
+      } else {
+         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;
diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h
index d38dd9e422..503d2971fd 100644
--- a/src/intel/vulkan/anv_private.h
+++ b/src/intel/vulkan/anv_private.h
@@ -1682,6 +1682,14 @@ struct anv_attachment_state {
    VkClearValue                                 clear_value;
    bool                                         clear_color_is_zero_one;
    bool                                         clear_color_is_zero;
+
+   /* When multiview is active, attachments with a renderpass clear
+    * operation have their respective layers cleared on the first
+    * subpass that uses them, and only in that subpass. We keep track
+    * of this using a bitfield to indicate which layers of an attachment
+    * have not been cleared yet when multiview is active.
+    */
+   uint32_t                                     pending_clear_views;
 };
 
 /** State tracking for particular pipeline bind point
diff --git a/src/intel/vulkan/genX_cmd_buffer.c b/src/intel/vulkan/genX_cmd_buffer.c
index ce47b8a1cc..0b4ae6fa4c 100644
--- a/src/intel/vulkan/genX_cmd_buffer.c
+++ b/src/intel/vulkan/genX_cmd_buffer.c
@@ -1096,6 +1096,8 @@ genX(cmd_buffer_setup_attachments)(struct anv_cmd_buffer *cmd_buffer,
          if (clear_aspects)
             state->attachments[i].clear_value = begin->pClearValues[i];
 
+         state->attachments[i].pending_clear_views = ~0;
+
          struct anv_image_view *iview = framebuffer->attachments[i];
          anv_assert(iview->vk_format == att->format);
          anv_assert(iview->n_planes == 1);
-- 
2.14.1



More information about the mesa-dev mailing list