Mesa (main): v3dv: don't be too aggressive disabling early Z

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Wed Jun 1 06:46:51 UTC 2022


Module: Mesa
Branch: main
Commit: 0f65838933bfee7c189ffbd17fa1d04a005db8c3
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=0f65838933bfee7c189ffbd17fa1d04a005db8c3

Author: Iago Toral Quiroga <itoral at igalia.com>
Date:   Mon May 30 11:28:50 2022 +0200

v3dv: don't be too aggressive disabling early Z

When we have a draw call that is incompatible with EZ we should only
disable EZ for the remaining of the job in the case that both of the
following conditions are met:

1. The cause for the incompatibility is an incompatible depth test
   direction.

2. The pipeline does Z writes.

Otherwise it is enough to disable EZ temporarily only for draw calls
with the incompatible pipeline.

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

---

 src/broadcom/vulkan/v3dv_pipeline.c    | 13 ++++++-
 src/broadcom/vulkan/v3dv_private.h     |  5 +++
 src/broadcom/vulkan/v3dvx_cmd_buffer.c | 64 ++++++++++++++++++++--------------
 3 files changed, 55 insertions(+), 27 deletions(-)

diff --git a/src/broadcom/vulkan/v3dv_pipeline.c b/src/broadcom/vulkan/v3dv_pipeline.c
index 63a8efe984d..0a18d095051 100644
--- a/src/broadcom/vulkan/v3dv_pipeline.c
+++ b/src/broadcom/vulkan/v3dv_pipeline.c
@@ -2882,6 +2882,7 @@ pipeline_set_ez_state(struct v3dv_pipeline *pipeline,
       break;
    default:
       pipeline->ez_state = V3D_EZ_DISABLED;
+      pipeline->incompatible_ez_test = true;
       break;
    }
 
@@ -2891,6 +2892,14 @@ pipeline_set_ez_state(struct v3dv_pipeline *pipeline,
         !stencil_op_is_no_op(&ds_info->back))) {
          pipeline->ez_state = V3D_EZ_DISABLED;
    }
+
+   /* If the FS writes Z, then it may update against the chosen EZ direction */
+   struct v3dv_shader_variant *fs_variant =
+      pipeline->shared_data->variants[BROADCOM_SHADER_FRAGMENT];
+   if (fs_variant && fs_variant->prog_data.fs->writes_z &&
+       !fs_variant->prog_data.fs->writes_z_from_fep) {
+      pipeline->ez_state = V3D_EZ_DISABLED;
+   }
 }
 
 static bool
@@ -3047,7 +3056,6 @@ pipeline_init(struct v3dv_pipeline *pipeline,
                                        rs_info, pv_info, ls_info,
                                        ms_info);
 
-   pipeline_set_ez_state(pipeline, ds_info);
    enable_depth_bias(pipeline, rs_info);
    pipeline_set_sample_mask(pipeline, ms_info);
    pipeline_set_sample_rate_shading(pipeline, ms_info);
@@ -3082,6 +3090,9 @@ pipeline_init(struct v3dv_pipeline *pipeline,
       pipeline->default_attribute_values = NULL;
    }
 
+   /* This must be done after the pipeline has been compiled */
+   pipeline_set_ez_state(pipeline, ds_info);
+
    return result;
 }
 
diff --git a/src/broadcom/vulkan/v3dv_private.h b/src/broadcom/vulkan/v3dv_private.h
index a191e9ed19c..3656db97ac5 100644
--- a/src/broadcom/vulkan/v3dv_private.h
+++ b/src/broadcom/vulkan/v3dv_private.h
@@ -1913,6 +1913,11 @@ struct v3dv_pipeline {
 
    enum v3dv_ez_state ez_state;
 
+   /* If ez_state is V3D_EZ_DISABLED, if the reason for disabling is that the
+    * pipeline selects an incompatible depth test function.
+    */
+   bool incompatible_ez_test;
+
    bool msaa;
    bool sample_rate_shading;
    uint32_t sample_mask;
diff --git a/src/broadcom/vulkan/v3dvx_cmd_buffer.c b/src/broadcom/vulkan/v3dvx_cmd_buffer.c
index 21bf3c4cf9b..ad3e9ba35a9 100644
--- a/src/broadcom/vulkan/v3dvx_cmd_buffer.c
+++ b/src/broadcom/vulkan/v3dvx_cmd_buffer.c
@@ -1400,7 +1400,10 @@ v3dX(cmd_buffer_emit_varyings_state)(struct v3dv_cmd_buffer *cmd_buffer)
    }
 }
 
-static void
+/* Updates job early Z state tracking. Returns False if EZ must be disabled
+ * for the current draw call.
+ */
+static bool
 job_update_ez_state(struct v3dv_job *job,
                     struct v3dv_pipeline *pipeline,
                     struct v3dv_cmd_buffer *cmd_buffer)
@@ -1414,9 +1417,15 @@ job_update_ez_state(struct v3dv_job *job,
     */
    if (job->first_ez_state == V3D_EZ_DISABLED) {
       assert(job->ez_state == V3D_EZ_DISABLED);
-      return;
+      return false;
    }
 
+   /* If ez_state is V3D_EZ_DISABLED it means that we have already decided
+    * that EZ must be disabled for the remaining of the frame.
+    */
+   if (job->ez_state == V3D_EZ_DISABLED)
+      return false;
+
    /* This is part of the pre draw call handling, so we should be inside a
     * render pass.
     */
@@ -1436,7 +1445,7 @@ job_update_ez_state(struct v3dv_job *job,
       if (subpass->ds_attachment.attachment == VK_ATTACHMENT_UNUSED) {
          job->first_ez_state = V3D_EZ_DISABLED;
          job->ez_state = V3D_EZ_DISABLED;
-         return;
+         return false;
       }
 
       /* GFXH-1918: the early-z buffer may load incorrect depth values
@@ -1465,7 +1474,7 @@ job_update_ez_state(struct v3dv_job *job,
                        "without framebuffer info disables early-z tests.\n");
             job->first_ez_state = V3D_EZ_DISABLED;
             job->ez_state = V3D_EZ_DISABLED;
-            return;
+            return false;
          }
 
          if (((fb->width % 2) != 0 || (fb->height % 2) != 0)) {
@@ -1473,7 +1482,7 @@ job_update_ez_state(struct v3dv_job *job,
                        "or height disables early-Z tests.\n");
             job->first_ez_state = V3D_EZ_DISABLED;
             job->ez_state = V3D_EZ_DISABLED;
-            return;
+            return false;
          }
       }
    }
@@ -1481,16 +1490,8 @@ job_update_ez_state(struct v3dv_job *job,
    /* Otherwise, we can decide to selectively enable or disable EZ for draw
     * calls using the CFG_BITS packet based on the bound pipeline state.
     */
-
-   /* If the FS writes Z, then it may update against the chosen EZ direction */
-   struct v3dv_shader_variant *fs_variant =
-      pipeline->shared_data->variants[BROADCOM_SHADER_FRAGMENT];
-   if (fs_variant->prog_data.fs->writes_z &&
-       !fs_variant->prog_data.fs->writes_z_from_fep) {
-      job->ez_state = V3D_EZ_DISABLED;
-      return;
-   }
-
+   bool disable_ez = false;
+   bool incompatible_test = false;
    switch (pipeline->ez_state) {
    case V3D_EZ_UNDECIDED:
       /* If the pipeline didn't pick a direction but didn't disable, then go
@@ -1504,24 +1505,35 @@ job_update_ez_state(struct v3dv_job *job,
       /* If the pipeline picked a direction, then it needs to match the current
        * direction if we've decided on one.
        */
-      if (job->ez_state == V3D_EZ_UNDECIDED)
+      if (job->ez_state == V3D_EZ_UNDECIDED) {
          job->ez_state = pipeline->ez_state;
-      else if (job->ez_state != pipeline->ez_state)
-         job->ez_state = V3D_EZ_DISABLED;
+      } else if (job->ez_state != pipeline->ez_state) {
+         disable_ez = true;
+         incompatible_test = true;
+      }
       break;
 
    case V3D_EZ_DISABLED:
-      /* If the pipeline disables EZ because of a bad Z func or stencil
-       * operation, then we can't do any more EZ in this frame.
-       */
-      job->ez_state = V3D_EZ_DISABLED;
+         disable_ez = true;
+         incompatible_test = pipeline->incompatible_ez_test;
       break;
    }
 
-   if (job->first_ez_state == V3D_EZ_UNDECIDED &&
-       job->ez_state != V3D_EZ_DISABLED) {
+   if (job->first_ez_state == V3D_EZ_UNDECIDED && !disable_ez) {
+      assert(job->ez_state != V3D_EZ_DISABLED);
       job->first_ez_state = job->ez_state;
    }
+
+   /* If we had to disable EZ because of an incompatible test direction and
+    * and the pipeline writes depth then we need to disable EZ for the rest of
+    * the frame.
+    */
+   if (incompatible_test && pipeline->z_updates_enable) {
+      assert(disable_ez);
+      job->ez_state = V3D_EZ_DISABLED;
+   }
+
+   return !disable_ez;
 }
 
 void
@@ -1533,13 +1545,13 @@ v3dX(cmd_buffer_emit_configuration_bits)(struct v3dv_cmd_buffer *cmd_buffer)
    struct v3dv_pipeline *pipeline = cmd_buffer->state.gfx.pipeline;
    assert(pipeline);
 
-   job_update_ez_state(job, pipeline, cmd_buffer);
+   bool enable_ez = job_update_ez_state(job, pipeline, cmd_buffer);
 
    v3dv_cl_ensure_space_with_branch(&job->bcl, cl_packet_length(CFG_BITS));
    v3dv_return_if_oom(cmd_buffer, NULL);
 
    cl_emit_with_prepacked(&job->bcl, CFG_BITS, pipeline->cfg_bits, config) {
-      config.early_z_enable = job->ez_state != V3D_EZ_DISABLED;
+      config.early_z_enable = enable_ez;
       config.early_z_updates_enable = config.early_z_enable &&
          pipeline->z_updates_enable;
    }



More information about the mesa-commit mailing list