[Mesa-dev] [PATCH 02/29] anv/blorp: Rework image clear/resolve helpers

Jason Ekstrand jason at jlekstrand.net
Tue Nov 28 03:05:52 UTC 2017


This replaces image_fast_clear and ccs_resolve with two new helpers that
simply perform an isl_aux_op whatever that may be on CCS or MCS.  This
is a bit cleaner as it separates performing the aux operation from which
blorp helper we have to call to do it.
---
 src/intel/vulkan/anv_blorp.c       | 218 ++++++++++++++++++++++---------------
 src/intel/vulkan/anv_private.h     |  23 ++--
 src/intel/vulkan/genX_cmd_buffer.c |  28 +++--
 3 files changed, 165 insertions(+), 104 deletions(-)

diff --git a/src/intel/vulkan/anv_blorp.c b/src/intel/vulkan/anv_blorp.c
index e244468..7c8a673 100644
--- a/src/intel/vulkan/anv_blorp.c
+++ b/src/intel/vulkan/anv_blorp.c
@@ -1439,75 +1439,6 @@ fast_clear_aux_usage(const struct anv_image *image,
 }
 
 void
-anv_image_fast_clear(struct anv_cmd_buffer *cmd_buffer,
-                     const struct anv_image *image,
-                     VkImageAspectFlagBits aspect,
-                     const uint32_t base_level, const uint32_t level_count,
-                     const uint32_t base_layer, uint32_t layer_count)
-{
-   assert(image->type == VK_IMAGE_TYPE_3D || image->extent.depth == 1);
-
-   if (image->type == VK_IMAGE_TYPE_3D) {
-      assert(base_layer == 0);
-      assert(layer_count == anv_minify(image->extent.depth, base_level));
-   }
-
-   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,
-                                fast_clear_aux_usage(image, aspect),
-                                &surf);
-
-   /* 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;
-
-   uint32_t plane = anv_image_aspect_to_plane(image->aspects, aspect);
-   uint32_t width_div = image->format->planes[plane].denominator_scales[0];
-   uint32_t height_div = image->format->planes[plane].denominator_scales[1];
-
-   for (uint32_t l = 0; l < level_count; l++) {
-      const uint32_t level = base_level + l;
-
-      const VkExtent3D extent = {
-         .width = anv_minify(image->extent.width, level),
-         .height = anv_minify(image->extent.height, level),
-         .depth = anv_minify(image->extent.depth, level),
-      };
-
-      if (image->type == VK_IMAGE_TYPE_3D)
-         layer_count = extent.depth;
-
-      assert(level < anv_image_aux_levels(image, aspect));
-      assert(base_layer + layer_count <= anv_image_aux_layers(image, aspect, level));
-      blorp_fast_clear(&batch, &surf, surf.surf->format,
-                       level, base_layer, layer_count,
-                       0, 0,
-                       extent.width / width_div,
-                       extent.height / height_div);
-   }
-
-   cmd_buffer->state.pending_pipe_bits |=
-      ANV_PIPE_RENDER_TARGET_CACHE_FLUSH_BIT | ANV_PIPE_CS_STALL_BIT;
-}
-
-void
 anv_cmd_buffer_resolve_subpass(struct anv_cmd_buffer *cmd_buffer)
 {
    struct anv_framebuffer *fb = cmd_buffer->state.framebuffer;
@@ -1681,36 +1612,153 @@ anv_gen8_hiz_op_resolve(struct anv_cmd_buffer *cmd_buffer,
 }
 
 void
-anv_ccs_resolve(struct anv_cmd_buffer * const cmd_buffer,
-                const struct anv_image * const image,
-                VkImageAspectFlagBits aspect,
-                const uint8_t level,
-                const uint32_t start_layer, const uint32_t layer_count,
-                const enum blorp_fast_clear_op op)
+anv_image_mcs_op(struct anv_cmd_buffer *cmd_buffer,
+                 const struct anv_image *image,
+                 VkImageAspectFlagBits aspect,
+                 uint32_t base_layer, uint32_t layer_count,
+                 enum isl_aux_op mcs_op, bool predicate)
 {
-   assert(cmd_buffer && image);
+   assert(image->aspects == VK_IMAGE_ASPECT_COLOR_BIT);
+   assert(image->samples > 1);
+   assert(base_layer + layer_count <= anv_image_aux_layers(image, aspect, 0));
 
-   uint32_t plane = anv_image_aspect_to_plane(image->aspects, aspect);
+   /* 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,
+                    predicate ? BLORP_BATCH_PREDICATE_ENABLE : 0);
+
+   struct blorp_surf surf;
+   get_blorp_surf_for_anv_image(cmd_buffer->device, image, aspect,
+                                fast_clear_aux_usage(image, aspect),
+                                &surf);
+
+   /* 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;
+
+   switch (mcs_op) {
+   case ISL_AUX_OP_FAST_CLEAR:
+      blorp_fast_clear(&batch, &surf, surf.surf->format,
+                       0, base_layer, layer_count,
+                       0, 0, image->extent.width, image->extent.height);
+      break;
+   case ISL_AUX_OP_FULL_RESOLVE:
+   case ISL_AUX_OP_PARTIAL_RESOLVE:
+   case ISL_AUX_OP_AMBIGUATE:
+   default:
+      unreachable("Unsupported CCS operation");
+   }
+
+   cmd_buffer->state.pending_pipe_bits |=
+      ANV_PIPE_RENDER_TARGET_CACHE_FLUSH_BIT | ANV_PIPE_CS_STALL_BIT;
+
+   blorp_batch_finish(&batch);
+}
 
-   /* The resolved subresource range must have a CCS buffer. */
+static enum blorp_fast_clear_op
+isl_to_blorp_fast_clear_op(enum isl_aux_op isl_op)
+{
+   switch (isl_op) {
+   case ISL_AUX_OP_FAST_CLEAR:      return BLORP_FAST_CLEAR_OP_CLEAR;
+   case ISL_AUX_OP_FULL_RESOLVE:    return BLORP_FAST_CLEAR_OP_RESOLVE_FULL;
+   case ISL_AUX_OP_PARTIAL_RESOLVE: return BLORP_FAST_CLEAR_OP_RESOLVE_PARTIAL;
+   default:
+      unreachable("Unsupported HiZ aux op");
+   }
+}
+
+void
+anv_image_ccs_op(struct anv_cmd_buffer *cmd_buffer,
+                 const struct anv_image *image,
+                 VkImageAspectFlagBits aspect, uint32_t level,
+                 uint32_t base_layer, uint32_t layer_count,
+                 enum isl_aux_op ccs_op, bool predicate)
+{
+   assert(image->aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT_ANV);
+   assert(image->samples == 1);
    assert(level < anv_image_aux_levels(image, aspect));
-   assert(start_layer + layer_count <=
+   assert(base_layer + layer_count <=
           anv_image_aux_layers(image, aspect, level));
-   assert(image->aspects & VK_IMAGE_ASPECT_ANY_COLOR_BIT_ANV && image->samples == 1);
+
+   uint32_t plane = anv_image_aspect_to_plane(image->aspects, aspect);
+   uint32_t width_div = image->format->planes[plane].denominator_scales[0];
+   uint32_t height_div = image->format->planes[plane].denominator_scales[1];
+   uint32_t level_width = anv_minify(image->extent.width, level) / width_div;
+   uint32_t level_height = anv_minify(image->extent.height, level) / height_div;
 
    struct blorp_batch batch;
    blorp_batch_init(&cmd_buffer->device->blorp, &batch, cmd_buffer,
-                    BLORP_BATCH_PREDICATE_ENABLE);
+                    predicate ? BLORP_BATCH_PREDICATE_ENABLE : 0);
 
    struct blorp_surf surf;
    get_blorp_surf_for_anv_image(cmd_buffer->device, image, aspect,
                                 fast_clear_aux_usage(image, aspect),
                                 &surf);
-   surf.clear_color_addr = anv_to_blorp_address(
-      anv_image_get_clear_color_addr(cmd_buffer->device, image, aspect, level));
 
-   blorp_ccs_resolve(&batch, &surf, level, start_layer, layer_count,
-                     image->planes[plane].surface.isl.format, op);
+   if (ccs_op == ISL_AUX_OP_FULL_RESOLVE ||
+       ccs_op == ISL_AUX_OP_PARTIAL_RESOLVE) {
+      /* If we're doing a resolve operation, then we need the indirect clear
+       * color.  The clear and ambiguate operations just stomp the CCS to a
+       * particular value and don't care about format or clear value.
+       */
+      const struct anv_address clear_color_addr =
+         anv_image_get_clear_color_addr(cmd_buffer->device, image,
+                                        aspect, level);
+      surf.clear_color_addr = anv_to_blorp_address(clear_color_addr);
+   }
+
+   /* 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;
+
+   switch (ccs_op) {
+   case ISL_AUX_OP_FAST_CLEAR:
+      blorp_fast_clear(&batch, &surf, surf.surf->format,
+                       level, base_layer, layer_count,
+                       0, 0, level_width, level_height);
+      break;
+   case ISL_AUX_OP_FULL_RESOLVE:
+   case ISL_AUX_OP_PARTIAL_RESOLVE:
+      blorp_ccs_resolve(&batch, &surf, level, base_layer, layer_count,
+                        surf.surf->format, isl_to_blorp_fast_clear_op(ccs_op));
+      break;
+   case ISL_AUX_OP_AMBIGUATE:
+   default:
+      unreachable("Unsupported CCS operation");
+   }
+
+   cmd_buffer->state.pending_pipe_bits |=
+      ANV_PIPE_RENDER_TARGET_CACHE_FLUSH_BIT | ANV_PIPE_CS_STALL_BIT;
 
    blorp_batch_finish(&batch);
 }
diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h
index ca3644d..dc44ab6 100644
--- a/src/intel/vulkan/anv_private.h
+++ b/src/intel/vulkan/anv_private.h
@@ -2533,20 +2533,19 @@ void
 anv_gen8_hiz_op_resolve(struct anv_cmd_buffer *cmd_buffer,
                         const struct anv_image *image,
                         enum blorp_hiz_op op);
-void
-anv_ccs_resolve(struct anv_cmd_buffer * const cmd_buffer,
-                const struct anv_image * const image,
-                VkImageAspectFlagBits aspect,
-                const uint8_t level,
-                const uint32_t start_layer, const uint32_t layer_count,
-                const enum blorp_fast_clear_op op);
 
 void
-anv_image_fast_clear(struct anv_cmd_buffer *cmd_buffer,
-                     const struct anv_image *image,
-                     VkImageAspectFlagBits aspect,
-                     const uint32_t base_level, const uint32_t level_count,
-                     const uint32_t base_layer, uint32_t layer_count);
+anv_image_mcs_op(struct anv_cmd_buffer *cmd_buffer,
+                 const struct anv_image *image,
+                 VkImageAspectFlagBits aspect,
+                 uint32_t base_layer, uint32_t layer_count,
+                 enum isl_aux_op mcs_op, bool predicate);
+void
+anv_image_ccs_op(struct anv_cmd_buffer *cmd_buffer,
+                 const struct anv_image *image,
+                 VkImageAspectFlagBits aspect, uint32_t level,
+                 uint32_t base_layer, uint32_t layer_count,
+                 enum isl_aux_op ccs_op, bool predicate);
 
 void
 anv_image_copy_to_shadow(struct anv_cmd_buffer *cmd_buffer,
diff --git a/src/intel/vulkan/genX_cmd_buffer.c b/src/intel/vulkan/genX_cmd_buffer.c
index ab5590d..2e7a2cc 100644
--- a/src/intel/vulkan/genX_cmd_buffer.c
+++ b/src/intel/vulkan/genX_cmd_buffer.c
@@ -689,9 +689,22 @@ transition_color_buffer(struct anv_cmd_buffer *cmd_buffer,
                           "define an MCS buffer.");
          }
 
-         anv_image_fast_clear(cmd_buffer, image, aspect,
-                              base_level, level_count,
-                              base_layer, layer_count);
+         if (image->samples == 1) {
+            for (uint32_t l = 0; l < level_count; l++) {
+               const uint32_t level = base_level + l;
+               const uint32_t level_layer_count =
+                  MIN2(layer_count, anv_image_aux_layers(image, aspect, level));
+               anv_image_ccs_op(cmd_buffer, image, aspect, level,
+                                base_layer, level_layer_count,
+                                ISL_AUX_OP_FAST_CLEAR, false);
+            }
+         } else {
+            assert(image->samples > 1);
+            assert(base_level == 0 && level_count == 1);
+            anv_image_mcs_op(cmd_buffer, image, aspect,
+                             base_layer, layer_count,
+                             ISL_AUX_OP_FAST_CLEAR, false);
+         }
       }
       /* At this point, some elements of the CCS buffer may have the fast-clear
        * bit-arrangement. As the user writes to a subresource, we need to have
@@ -760,10 +773,11 @@ transition_color_buffer(struct anv_cmd_buffer *cmd_buffer,
 
       genX(load_needs_resolve_predicate)(cmd_buffer, image, aspect, level);
 
-      anv_ccs_resolve(cmd_buffer, image, aspect, level, base_layer, layer_count,
-                      image->planes[plane].aux_usage == ISL_AUX_USAGE_CCS_E ?
-                      BLORP_FAST_CLEAR_OP_RESOLVE_PARTIAL :
-                      BLORP_FAST_CLEAR_OP_RESOLVE_FULL);
+      anv_image_ccs_op(cmd_buffer, image, aspect, level,
+                       base_layer, layer_count,
+                       image->planes[plane].aux_usage == ISL_AUX_USAGE_CCS_E ?
+                       ISL_AUX_OP_PARTIAL_RESOLVE : ISL_AUX_OP_FULL_RESOLVE,
+                       true);
 
       genX(set_image_needs_resolve)(cmd_buffer, image, aspect, level, false);
    }
-- 
2.5.0.400.gff86faf



More information about the mesa-dev mailing list