[Mesa-dev] [PATCH 04/14] anv/cmd_buffer: Move the color portion of clear_subpass into begin_subpass

Jason Ekstrand jason at jlekstrand.net
Mon Feb 5 22:34:53 UTC 2018


This doesn't really change much now but it will give us more/better
control over clears in the future.  The one interesting functional
change here is that we are now re-emitting 3DSTATE_DEPTH_BUFFERS and
friends for each clear.  However, this only happens at begin_subpass
time so it shouldn't be substantially more expensive.
---
 src/intel/vulkan/anv_blorp.c       | 124 ++++++++++---------------------------
 src/intel/vulkan/anv_private.h     |   8 +++
 src/intel/vulkan/genX_cmd_buffer.c |  54 +++++++++++++++-
 3 files changed, 94 insertions(+), 92 deletions(-)

diff --git a/src/intel/vulkan/anv_blorp.c b/src/intel/vulkan/anv_blorp.c
index d38b343..fd32227 100644
--- a/src/intel/vulkan/anv_blorp.c
+++ b/src/intel/vulkan/anv_blorp.c
@@ -1142,17 +1142,6 @@ subpass_needs_clear(const struct anv_cmd_buffer *cmd_buffer)
    const struct anv_cmd_state *cmd_state = &cmd_buffer->state;
    uint32_t ds = cmd_state->subpass->depth_stencil_attachment.attachment;
 
-   for (uint32_t i = 0; i < cmd_state->subpass->color_count; ++i) {
-      uint32_t a = cmd_state->subpass->color_attachments[i].attachment;
-      if (a == VK_ATTACHMENT_UNUSED)
-         continue;
-
-      assert(a < cmd_state->pass->attachment_count);
-      if (cmd_state->attachments[a].pending_clear_aspects) {
-         return true;
-      }
-   }
-
    if (ds != VK_ATTACHMENT_UNUSED) {
       assert(ds < cmd_state->pass->attachment_count);
       if (cmd_state->attachments[ds].pending_clear_aspects)
@@ -1186,86 +1175,6 @@ anv_cmd_buffer_clear_subpass(struct anv_cmd_buffer *cmd_buffer)
    };
 
    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;
-      if (a == VK_ATTACHMENT_UNUSED)
-         continue;
-
-      assert(a < cmd_state->pass->attachment_count);
-      struct anv_attachment_state *att_state = &cmd_state->attachments[a];
-
-      if (!att_state->pending_clear_aspects)
-         continue;
-
-      assert(att_state->pending_clear_aspects == VK_IMAGE_ASPECT_COLOR_BIT);
-
-      struct anv_image_view *iview = fb->attachments[a];
-      const struct anv_image *image = iview->image;
-      struct blorp_surf surf;
-      get_blorp_surf_for_anv_image(cmd_buffer->device,
-                                   image, VK_IMAGE_ASPECT_COLOR_BIT,
-                                   att_state->aux_usage, &surf);
-
-      uint32_t base_layer = iview->planes[0].isl.base_array_layer;
-      uint32_t layer_count = fb->layers;
-
-      if (att_state->fast_clear) {
-         surf.clear_color = vk_to_isl_color(att_state->clear_value.color);
-
-         /* From the Sky Lake PRM Vol. 7, "Render Target Fast Clear":
-          *
-          *    "After Render target fast clear, pipe-control with color cache
-          *    write-flush must be issued before sending any DRAW commands on
-          *    that render target."
-          *
-          * This comment is a bit cryptic and doesn't really tell you what's
-          * going or what's really needed.  It appears that fast clear ops are
-          * not properly synchronized with other drawing.  This means that we
-          * cannot have a fast clear operation in the pipe at the same time as
-          * other regular drawing operations.  We need to use a PIPE_CONTROL
-          * to ensure that the contents of the previous draw hit the render
-          * target before we resolve and then use a second PIPE_CONTROL after
-          * the resolve to ensure that it is completed before any additional
-          * drawing occurs.
-          */
-         cmd_buffer->state.pending_pipe_bits |=
-            ANV_PIPE_RENDER_TARGET_CACHE_FLUSH_BIT | ANV_PIPE_CS_STALL_BIT;
-
-         /* We only support fast-clears on the first layer */
-         assert(iview->planes[0].isl.base_level == 0);
-         assert(iview->planes[0].isl.base_array_layer == 0);
-
-         assert(image->n_planes == 1);
-         blorp_fast_clear(&batch, &surf, iview->planes[0].isl.format, 0, 0, 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);
-         base_layer++;
-         layer_count--;
-
-         cmd_buffer->state.pending_pipe_bits |=
-            ANV_PIPE_RENDER_TARGET_CACHE_FLUSH_BIT | ANV_PIPE_CS_STALL_BIT;
-      }
-
-      if (layer_count > 0) {
-         assert(image->n_planes == 1);
-         anv_cmd_buffer_mark_image_written(cmd_buffer, image,
-                                           VK_IMAGE_ASPECT_COLOR_BIT,
-                                           att_state->aux_usage,
-                                           iview->planes[0].isl.base_level,
-                                           base_layer, layer_count);
-
-         blorp_clear(&batch, &surf, iview->planes[0].isl.format,
-                     anv_swizzle_for_render(iview->planes[0].isl.swizzle),
-                     iview->planes[0].isl.base_level, base_layer, layer_count,
-                     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_aspects = 0;
-   }
 
    const uint32_t ds = cmd_state->subpass->depth_stencil_attachment.attachment;
    assert(ds == VK_ATTACHMENT_UNUSED || ds < cmd_state->pass->attachment_count);
@@ -1619,6 +1528,39 @@ anv_image_copy_to_shadow(struct anv_cmd_buffer *cmd_buffer,
 }
 
 void
+anv_image_clear_color(struct anv_cmd_buffer *cmd_buffer,
+                      const struct anv_image *image,
+                      VkImageAspectFlagBits aspect,
+                      enum isl_aux_usage aux_usage,
+                      enum isl_format format, struct isl_swizzle swizzle,
+                      uint32_t level, uint32_t base_layer, uint32_t layer_count,
+                      VkRect2D area, union isl_color_value clear_color)
+{
+   assert(image->aspects == VK_IMAGE_ASPECT_COLOR_BIT);
+
+   /* We don't support planar images with multisampling yet */
+   assert(image->n_planes == 1);
+
+   struct blorp_batch batch;
+   blorp_batch_init(&cmd_buffer->device->blorp, &batch, cmd_buffer, 0);
+
+   struct blorp_surf surf;
+   get_blorp_surf_for_anv_image(cmd_buffer->device, image, aspect,
+                                aux_usage, &surf);
+   anv_cmd_buffer_mark_image_written(cmd_buffer, image, aspect, aux_usage,
+                                     level, base_layer, layer_count);
+
+   blorp_clear(&batch, &surf, format, anv_swizzle_for_render(swizzle),
+               level, base_layer, layer_count,
+               area.offset.x, area.offset.y,
+               area.offset.x + area.extent.width,
+               area.offset.y + area.extent.height,
+               clear_color, NULL);
+
+   blorp_batch_finish(&batch);
+}
+
+void
 anv_image_hiz_op(struct anv_cmd_buffer *cmd_buffer,
                  const struct anv_image *image,
                  VkImageAspectFlagBits aspect, uint32_t level,
diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h
index d38dd9e..73004a3 100644
--- a/src/intel/vulkan/anv_private.h
+++ b/src/intel/vulkan/anv_private.h
@@ -2609,6 +2609,14 @@ anv_cmd_buffer_mark_image_written(struct anv_cmd_buffer *cmd_buffer,
                                   uint32_t layer_count);
 
 void
+anv_image_clear_color(struct anv_cmd_buffer *cmd_buffer,
+                      const struct anv_image *image,
+                      VkImageAspectFlagBits aspect,
+                      enum isl_aux_usage aux_usage,
+                      enum isl_format format, struct isl_swizzle swizzle,
+                      uint32_t level, uint32_t base_layer, uint32_t layer_count,
+                      VkRect2D area, union isl_color_value clear_color);
+void
 anv_image_hiz_op(struct anv_cmd_buffer *cmd_buffer,
                  const struct anv_image *image,
                  VkImageAspectFlagBits aspect, uint32_t level,
diff --git a/src/intel/vulkan/genX_cmd_buffer.c b/src/intel/vulkan/genX_cmd_buffer.c
index 519d14f..fcbb2b4 100644
--- a/src/intel/vulkan/genX_cmd_buffer.c
+++ b/src/intel/vulkan/genX_cmd_buffer.c
@@ -3434,7 +3434,9 @@ static void
 cmd_buffer_begin_subpass(struct anv_cmd_buffer *cmd_buffer,
                          uint32_t subpass_id)
 {
-   cmd_buffer->state.subpass = &cmd_buffer->state.pass->subpasses[subpass_id];
+   struct anv_cmd_state *cmd_state = &cmd_buffer->state;
+   struct anv_subpass *subpass = &cmd_state->pass->subpasses[subpass_id];
+   cmd_state->subpass = subpass;
 
    cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_RENDER_TARGETS;
 
@@ -3477,6 +3479,56 @@ cmd_buffer_begin_subpass(struct anv_cmd_buffer *cmd_buffer,
     */
    cmd_buffer_subpass_sync_fast_clear_values(cmd_buffer);
 
+   VkRect2D render_area = cmd_buffer->state.render_area;
+   struct anv_framebuffer *fb = cmd_buffer->state.framebuffer;
+   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;
+
+      assert(a < cmd_state->pass->attachment_count);
+      struct anv_attachment_state *att_state = &cmd_state->attachments[a];
+
+      if (!att_state->pending_clear_aspects)
+         continue;
+
+      assert(att_state->pending_clear_aspects == VK_IMAGE_ASPECT_COLOR_BIT);
+
+      struct anv_image_view *iview = fb->attachments[a];
+      const struct anv_image *image = iview->image;
+
+      /* Multi-planar images are not supported as attachments */
+      assert(image->aspects == VK_IMAGE_ASPECT_COLOR_BIT);
+      assert(image->n_planes == 1);
+
+      uint32_t base_layer = iview->planes[0].isl.base_array_layer;
+      uint32_t layer_count = fb->layers;
+
+      if (att_state->fast_clear) {
+         /* We only support fast-clears on the first layer */
+         assert(iview->planes[0].isl.base_level == 0);
+         assert(iview->planes[0].isl.base_array_layer == 0);
+
+         anv_image_ccs_op(cmd_buffer, image, VK_IMAGE_ASPECT_COLOR_BIT,
+                          0, 0, 1, ISL_AUX_OP_FAST_CLEAR, false);
+         base_layer++;
+         layer_count--;
+      }
+
+      if (layer_count > 0) {
+         assert(image->n_planes == 1);
+         anv_image_clear_color(cmd_buffer, image, VK_IMAGE_ASPECT_COLOR_BIT,
+                               att_state->aux_usage,
+                               iview->planes[0].isl.format,
+                               iview->planes[0].isl.swizzle,
+                               iview->planes[0].isl.base_level,
+                               base_layer, layer_count, render_area,
+                               vk_to_isl_color(att_state->clear_value.color));
+      }
+
+      att_state->pending_clear_aspects = 0;
+   }
+
    cmd_buffer_emit_depth_stencil(cmd_buffer);
 
    anv_cmd_buffer_clear_subpass(cmd_buffer);
-- 
2.5.0.400.gff86faf



More information about the mesa-dev mailing list