[Mesa-dev] [PATCH v3 13/16] anv: Stop resolving CCS implicitly

Nanley Chery nanleychery at gmail.com
Wed Jun 28 21:14:46 UTC 2017


With an earlier patch from this series, resolves are additionally
performed on layout transitions. Remove the now unnecessary implicit
resolves within render passes.

Signed-off-by: Nanley Chery <nanley.g.chery at intel.com>
---
 src/intel/vulkan/anv_blorp.c   | 150 ++---------------------------------------
 src/intel/vulkan/anv_pass.c    |  14 ----
 src/intel/vulkan/anv_private.h |  10 ---
 3 files changed, 5 insertions(+), 169 deletions(-)

diff --git a/src/intel/vulkan/anv_blorp.c b/src/intel/vulkan/anv_blorp.c
index 7ae07808bc..35317ba6be 100644
--- a/src/intel/vulkan/anv_blorp.c
+++ b/src/intel/vulkan/anv_blorp.c
@@ -1496,150 +1496,16 @@ anv_image_ccs_clear(struct anv_cmd_buffer *cmd_buffer,
       ANV_PIPE_RENDER_TARGET_CACHE_FLUSH_BIT | ANV_PIPE_CS_STALL_BIT;
 }
 
-static void
-ccs_resolve_attachment(struct anv_cmd_buffer *cmd_buffer,
-                       uint32_t att)
-{
-   struct anv_framebuffer *fb = cmd_buffer->state.framebuffer;
-   struct anv_attachment_state *att_state =
-      &cmd_buffer->state.attachments[att];
-
-   if (att_state->aux_usage == ISL_AUX_USAGE_NONE ||
-       att_state->aux_usage == ISL_AUX_USAGE_MCS)
-      return; /* Nothing to resolve */
-
-   assert(att_state->aux_usage == ISL_AUX_USAGE_CCS_E ||
-          att_state->aux_usage == ISL_AUX_USAGE_CCS_D);
-
-   struct anv_render_pass *pass = cmd_buffer->state.pass;
-   const uint32_t subpass_idx = anv_get_subpass_id(&cmd_buffer->state);
-
-   /* Scan forward to see what all ways this attachment will be used.
-    * Ideally, we would like to resolve in the same subpass as the last write
-    * of a particular attachment.  That way we only resolve once but it's
-    * still hot in the cache.
-    */
-   bool found_draw = false;
-   enum anv_subpass_usage usage = 0;
-   for (uint32_t s = subpass_idx + 1; s < pass->subpass_count; s++) {
-      usage |= pass->attachments[att].subpass_usage[s];
-
-      if (usage & (ANV_SUBPASS_USAGE_DRAW | ANV_SUBPASS_USAGE_RESOLVE_DST)) {
-         /* We found another subpass that draws to this attachment.  We'll
-          * wait to resolve until then.
-          */
-         found_draw = true;
-         break;
-      }
-   }
-
-   struct anv_image_view *iview = fb->attachments[att];
-   const struct anv_image *image = iview->image;
-   assert(image->aspects == VK_IMAGE_ASPECT_COLOR_BIT);
-
-   enum blorp_fast_clear_op resolve_op = BLORP_FAST_CLEAR_OP_NONE;
-   if (!found_draw) {
-      /* This is the last subpass that writes to this attachment so we need to
-       * resolve here.  Ideally, we would like to only resolve if the storeOp
-       * is set to VK_ATTACHMENT_STORE_OP_STORE.  However, we need to ensure
-       * that the CCS bits are set to "resolved" because there may be copy or
-       * blit operations (which may ignore CCS) between now and the next time
-       * we render and we need to ensure that anything they write will be
-       * respected in the next render.  Unfortunately, the hardware does not
-       * provide us with any sort of "invalidate" pass that sets the CCS to
-       * "resolved" without writing to the render target.
-       */
-      if (iview->image->aux_usage != ISL_AUX_USAGE_CCS_E) {
-         /* The image destination surface doesn't support compression outside
-          * the render pass.  We need a full resolve.
-          */
-         resolve_op = BLORP_FAST_CLEAR_OP_RESOLVE_FULL;
-      } else if (att_state->fast_clear) {
-         /* We don't know what to do with clear colors outside the render
-          * pass.  We need a partial resolve. Only transparent black is
-          * built into the surface state object and thus no resolve is
-          * required for this case.
-          */
-         if (att_state->clear_value.color.uint32[0] ||
-             att_state->clear_value.color.uint32[1] ||
-             att_state->clear_value.color.uint32[2] ||
-             att_state->clear_value.color.uint32[3])
-            resolve_op = BLORP_FAST_CLEAR_OP_RESOLVE_PARTIAL;
-      } else {
-         /* The image "natively" supports all the compression we care about
-          * and we don't need to resolve at all.  If this is the case, we also
-          * don't need to resolve for any of the input attachment cases below.
-          */
-      }
-   } else if (usage & ANV_SUBPASS_USAGE_INPUT) {
-      /* Input attachments are clear-color aware so, at least on Sky Lake, we
-       * can frequently sample from them with no resolves at all.
-       */
-      if (att_state->aux_usage != att_state->input_aux_usage) {
-         assert(att_state->input_aux_usage == ISL_AUX_USAGE_NONE);
-         resolve_op = BLORP_FAST_CLEAR_OP_RESOLVE_FULL;
-      } else if (!att_state->clear_color_is_zero_one) {
-         /* Sky Lake PRM, Vol. 2d, RENDER_SURFACE_STATE::Red Clear Color:
-          *
-          *    "If Number of Multisamples is MULTISAMPLECOUNT_1 AND if this RT
-          *    is fast cleared with non-0/1 clear value, this RT must be
-          *    partially resolved (refer to Partial Resolve operation) before
-          *    binding this surface to Sampler."
-          */
-         resolve_op = BLORP_FAST_CLEAR_OP_RESOLVE_PARTIAL;
-      }
-   }
-
-   if (resolve_op == BLORP_FAST_CLEAR_OP_NONE)
-      return;
-
-   /* From the Sky Lake PRM Vol. 7, "Render Target Resolve":
-    *
-    *    "When performing a render target resolve, PIPE_CONTROL with end of
-    *    pipe sync must be delivered."
-    *
-    * 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.  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;
-
-   const uint32_t aux_layers =
-      anv_image_aux_layers(image, iview->isl.base_level);
-   anv_ccs_resolve(cmd_buffer, att_state->color_rt_state, image,
-                   iview->isl.base_level, MIN2(fb->layers, aux_layers),
-                   resolve_op);
-
-   cmd_buffer->state.pending_pipe_bits |=
-      ANV_PIPE_RENDER_TARGET_CACHE_FLUSH_BIT | ANV_PIPE_CS_STALL_BIT;
-
-   /* Once we've done any sort of resolve, we're no longer fast-cleared */
-   att_state->fast_clear = false;
-   if (att_state->aux_usage == ISL_AUX_USAGE_CCS_D)
-      att_state->aux_usage = ISL_AUX_USAGE_NONE;
-}
-
 void
 anv_cmd_buffer_resolve_subpass(struct anv_cmd_buffer *cmd_buffer)
 {
    struct anv_framebuffer *fb = cmd_buffer->state.framebuffer;
    struct anv_subpass *subpass = cmd_buffer->state.subpass;
 
-
-   for (uint32_t i = 0; i < subpass->color_count; ++i) {
-      const uint32_t att = subpass->color_attachments[i].attachment;
-      if (att == VK_ATTACHMENT_UNUSED)
-         continue;
-
-      assert(att < cmd_buffer->state.pass->attachment_count);
-      ccs_resolve_attachment(cmd_buffer, att);
-   }
-
    if (subpass->has_resolve) {
+      struct blorp_batch batch;
+      blorp_batch_init(&cmd_buffer->device->blorp, &batch, cmd_buffer, 0);
+
       /* We are about to do some MSAA resolves.  We need to flush so that the
        * result of writes to the MSAA color attachments show up in the sampler
        * when we blit to the single-sampled resolve target.
@@ -1676,9 +1542,6 @@ anv_cmd_buffer_resolve_subpass(struct anv_cmd_buffer *cmd_buffer)
 
          assert(src_iview->aspect_mask == dst_iview->aspect_mask);
 
-         struct blorp_batch batch;
-         blorp_batch_init(&cmd_buffer->device->blorp, &batch, cmd_buffer, 0);
-
          resolve_image(&batch, src_iview->image,
                        src_iview->isl.base_level,
                        src_iview->isl.base_array_layer,
@@ -1689,13 +1552,10 @@ anv_cmd_buffer_resolve_subpass(struct anv_cmd_buffer *cmd_buffer)
                        render_area.offset.x, render_area.offset.y,
                        render_area.offset.x, render_area.offset.y,
                        render_area.extent.width, render_area.extent.height);
-
-         blorp_batch_finish(&batch);
-
-         ccs_resolve_attachment(cmd_buffer, dst_att);
       }
-   }
 
+      blorp_batch_finish(&batch);
+   }
 }
 
 void
diff --git a/src/intel/vulkan/anv_pass.c b/src/intel/vulkan/anv_pass.c
index ab0733fc10..a77e52b0c0 100644
--- a/src/intel/vulkan/anv_pass.c
+++ b/src/intel/vulkan/anv_pass.c
@@ -73,10 +73,6 @@ VkResult anv_CreateRenderPass(
    }
    anv_multialloc_add(&ma, &subpass_attachments, subpass_attachment_count);
 
-   enum anv_subpass_usage *subpass_usages;
-   anv_multialloc_add(&ma, &subpass_usages,
-                      pCreateInfo->subpassCount * pCreateInfo->attachmentCount);
-
    if (!anv_multialloc_alloc2(&ma, &device->alloc, pAllocator,
                               VK_SYSTEM_ALLOCATION_SCOPE_OBJECT))
       return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
@@ -102,8 +98,6 @@ VkResult anv_CreateRenderPass(
       att->initial_layout = pCreateInfo->pAttachments[i].initialLayout;
       att->final_layout = pCreateInfo->pAttachments[i].finalLayout;
       att->first_subpass_layout = VK_IMAGE_LAYOUT_UNDEFINED;
-      att->subpass_usage = subpass_usages;
-      subpass_usages += pass->subpass_count;
    }
 
    bool has_color = false, has_depth = false, has_input = false;
@@ -127,7 +121,6 @@ VkResult anv_CreateRenderPass(
             if (a != VK_ATTACHMENT_UNUSED) {
                has_input = true;
                pass->attachments[a].usage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
-               pass->attachments[a].subpass_usage[i] |= ANV_SUBPASS_USAGE_INPUT;
                pass->attachments[a].last_subpass_idx = i;
 
                init_first_subpass_layout(&pass->attachments[a],
@@ -149,7 +142,6 @@ VkResult anv_CreateRenderPass(
             if (a != VK_ATTACHMENT_UNUSED) {
                has_color = true;
                pass->attachments[a].usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
-               pass->attachments[a].subpass_usage[i] |= ANV_SUBPASS_USAGE_DRAW;
                pass->attachments[a].last_subpass_idx = i;
 
                init_first_subpass_layout(&pass->attachments[a],
@@ -172,11 +164,6 @@ VkResult anv_CreateRenderPass(
                pass->attachments[color_att].usage |=
                   VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
                pass->attachments[a].usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
-
-               pass->attachments[color_att].subpass_usage[i] |=
-                  ANV_SUBPASS_USAGE_RESOLVE_SRC;
-               pass->attachments[a].subpass_usage[i] |=
-                  ANV_SUBPASS_USAGE_RESOLVE_DST;
                pass->attachments[a].last_subpass_idx = i;
 
                init_first_subpass_layout(&pass->attachments[a],
@@ -193,7 +180,6 @@ VkResult anv_CreateRenderPass(
             has_depth = true;
             pass->attachments[a].usage |=
                VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
-            pass->attachments[a].subpass_usage[i] |= ANV_SUBPASS_USAGE_DRAW;
             pass->attachments[a].last_subpass_idx = i;
 
             init_first_subpass_layout(&pass->attachments[a],
diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h
index c5a2ba0888..be1623f3c3 100644
--- a/src/intel/vulkan/anv_private.h
+++ b/src/intel/vulkan/anv_private.h
@@ -2318,13 +2318,6 @@ anv_subpass_view_count(const struct anv_subpass *subpass)
    return MAX2(1, _mesa_bitcount(subpass->view_mask));
 }
 
-enum anv_subpass_usage {
-   ANV_SUBPASS_USAGE_DRAW =         (1 << 0),
-   ANV_SUBPASS_USAGE_INPUT =        (1 << 1),
-   ANV_SUBPASS_USAGE_RESOLVE_SRC =  (1 << 2),
-   ANV_SUBPASS_USAGE_RESOLVE_DST =  (1 << 3),
-};
-
 struct anv_render_pass_attachment {
    /* TODO: Consider using VkAttachmentDescription instead of storing each of
     * its members individually.
@@ -2339,9 +2332,6 @@ struct anv_render_pass_attachment {
    VkImageLayout                                final_layout;
    VkImageLayout                                first_subpass_layout;
 
-   /* An array, indexed by subpass id, of how the attachment will be used. */
-   enum anv_subpass_usage *                     subpass_usage;
-
    /* The subpass id in which the attachment will be used last. */
    uint32_t                                     last_subpass_idx;
 };
-- 
2.13.1



More information about the mesa-dev mailing list