Mesa (master): v3dv: enable early Z/S clears

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Thu Jan 21 13:24:03 UTC 2021


Module: Mesa
Branch: master
Commit: 9c97cc37b0b03bc7a714a48569abd69c0177c7e1
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=9c97cc37b0b03bc7a714a48569abd69c0177c7e1

Author: Iago Toral Quiroga <itoral at igalia.com>
Date:   Wed Jan 20 10:31:01 2021 +0100

v3dv: enable early Z/S clears

This is an optimization that should make Z/S clears faster. To enable
this we can't have any Z/S loads or stores in the job. Also, it seems
that enabling early Z/S clearing is independent of whether early Z/S
testing is enabled.

Reviewed-by: Alejandro Piñeiro <apinheiro at igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8589>

---

 src/broadcom/vulkan/v3dv_cmd_buffer.c | 60 +++++++++++++++++++++++++++++++++--
 src/broadcom/vulkan/v3dv_private.h    |  3 ++
 2 files changed, 61 insertions(+), 2 deletions(-)

diff --git a/src/broadcom/vulkan/v3dv_cmd_buffer.c b/src/broadcom/vulkan/v3dv_cmd_buffer.c
index 627bdd302a8..face9d8e489 100644
--- a/src/broadcom/vulkan/v3dv_cmd_buffer.c
+++ b/src/broadcom/vulkan/v3dv_cmd_buffer.c
@@ -1809,11 +1809,14 @@ cmd_buffer_render_pass_emit_stores(struct v3dv_cmd_buffer *cmd_buffer,
        * So if we have to emit a clear of depth or stencil we don't use
        * the per-buffer store clear bit, even if we need to store the buffers,
        * instead we always have to use the Clear Tile Buffers Z/S bit.
+       * If we have configured the job to do early Z/S clearing, then we
+       * don't want to emit any Clear Tile Buffers command at all here.
        *
        * Note that GFXH-1689 is not reproduced in the simulator, where
        * using the clear buffer bit in depth/stencil stores works fine.
        */
-      use_global_zs_clear = needs_depth_clear || needs_stencil_clear;
+      use_global_zs_clear = !state->job->early_zs_clear &&
+                            (needs_depth_clear || needs_stencil_clear);
       if (needs_depth_store || needs_stencil_store) {
          const uint32_t zs_buffer =
             v3dv_zs_buffer(needs_depth_store, needs_stencil_store);
@@ -2016,7 +2019,7 @@ cmd_buffer_emit_render_pass_layer_rcl(struct v3dv_cmd_buffer *cmd_buffer,
       }
       if (i == 0 && cmd_buffer->state.tile_aligned_render_area) {
          cl_emit(rcl, CLEAR_TILE_BUFFERS, clear) {
-            clear.clear_z_stencil_buffer = true;
+            clear.clear_z_stencil_buffer = !job->early_zs_clear;
             clear.clear_all_render_targets = true;
          }
       }
@@ -2125,6 +2128,7 @@ cmd_buffer_emit_render_pass_rcl(struct v3dv_cmd_buffer *cmd_buffer)
     * Z_STENCIL_CLEAR_VALUES must be last. The ones in between are optional
     * updates to the previous HW state.
     */
+   bool do_early_zs_clear = false;
    const uint32_t ds_attachment_idx = subpass->ds_attachment.attachment;
    cl_emit(rcl, TILE_RENDERING_MODE_CFG_COMMON, config) {
       config.image_width_pixels = framebuffer->width;
@@ -2156,11 +2160,63 @@ cmd_buffer_emit_render_pass_rcl(struct v3dv_cmd_buffer *cmd_buffer)
                                 needs_depth_load,
                                 &config.early_z_disable,
                                 &config.early_z_test_and_update_direction);
+
+         /* Early-Z/S clear can be enabled if the job is clearing and not
+          * storing (or loading) depth. If a stencil aspect is also present
+          * we have the same requirements for it, however, in this case we
+          * can accept stencil loadOp DONT_CARE as well, so instead of
+          * checking that stencil is cleared we check that is not loaded.
+          *
+          * Early-Z/S clearing is independent of Early Z/S testing, so it is
+          * possible to enable one but not the other so long as their
+          * respective requirements are met.
+          */
+         bool needs_depth_clear =
+            check_needs_clear(state,
+                              ds_aspects & VK_IMAGE_ASPECT_DEPTH_BIT,
+                              ds_attachment->first_subpass,
+                              ds_attachment->desc.loadOp,
+                              subpass->do_depth_clear_with_draw);
+
+         /* Sanity check: can't be loading and clearing */
+         assert(!needs_depth_clear || !needs_depth_load);
+
+         bool needs_depth_store =
+            check_needs_store(state,
+                              ds_aspects & VK_IMAGE_ASPECT_DEPTH_BIT,
+                              ds_attachment->last_subpass,
+                              ds_attachment->desc.storeOp);
+
+         do_early_zs_clear = needs_depth_clear && !needs_depth_store;
+         if (do_early_zs_clear &&
+             vk_format_has_stencil(ds_attachment->desc.format)) {
+            bool needs_stencil_load =
+               check_needs_load(state,
+                                ds_aspects & VK_IMAGE_ASPECT_STENCIL_BIT,
+                                ds_attachment->first_subpass,
+                                ds_attachment->desc.stencilLoadOp);
+
+            bool needs_stencil_store =
+               check_needs_store(state,
+                                 ds_aspects & VK_IMAGE_ASPECT_STENCIL_BIT,
+                                 ds_attachment->last_subpass,
+                                 ds_attachment->desc.stencilStoreOp);
+
+            do_early_zs_clear = !needs_stencil_load && !needs_stencil_store;
+         }
+
+         config.early_depth_stencil_clear = do_early_zs_clear;
       } else {
          config.early_z_disable = true;
       }
    }
 
+   /* If we enabled early Z/S clear, then we can't emit any "Clear Tile Buffers"
+    * commands with the Z/S bit set, so keep track of whether we enabled this
+    * in the job so we can skip these later.
+    */
+   job->early_zs_clear = do_early_zs_clear;
+
    for (uint32_t i = 0; i < subpass->color_count; i++) {
       uint32_t attachment_idx = subpass->color_attachments[i].attachment;
       if (attachment_idx == VK_ATTACHMENT_UNUSED)
diff --git a/src/broadcom/vulkan/v3dv_private.h b/src/broadcom/vulkan/v3dv_private.h
index e9f7e27e152..fb13753b7f3 100644
--- a/src/broadcom/vulkan/v3dv_private.h
+++ b/src/broadcom/vulkan/v3dv_private.h
@@ -896,6 +896,9 @@ struct v3dv_job {
    enum v3dv_ez_state ez_state;
    enum v3dv_ez_state first_ez_state;
 
+   /* If this job has been configured to use early Z/S clear */
+   bool early_zs_clear;
+
    /* Number of draw calls recorded into the job */
    uint32_t draw_count;
 



More information about the mesa-commit mailing list