Mesa (main): v3d: disable early-Z on odd frame dimensions

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Wed May 4 08:05:21 UTC 2022


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

Author: Juan A. Suarez Romero <jasuarez at igalia.com>
Date:   Tue Apr 19 16:53:20 2022 +0200

v3d: disable early-Z on odd frame dimensions

The early-Z buffer may load incorrect depth values if the frame has an
od width or height. In this case we need to disable early-Z.

v3:
 - Set job->early_zs_clear only for V3D_VERSION >= 40 (Iago)
 - Check early-Z is disabled if no zsbuf (Iago)

v4:
 - Borrow comments from v3dv around v3d_update_job_ez() (Iago)

Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/3557
Signed-off-by: Juan A. Suarez Romero <jasuarez at igalia.com>
Reviewed-by: Iago Toral Quiroga <itoral at igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/16166>

---

 src/gallium/drivers/v3d/v3d_context.h |  6 +++++
 src/gallium/drivers/v3d/v3dx_draw.c   | 43 +++++++++++++++++++++++++++++++++++
 src/gallium/drivers/v3d/v3dx_rcl.c    | 41 ++++++++++++++++++++-------------
 3 files changed, 74 insertions(+), 16 deletions(-)

diff --git a/src/gallium/drivers/v3d/v3d_context.h b/src/gallium/drivers/v3d/v3d_context.h
index 5bfe53ee6fc..5ba8727add3 100644
--- a/src/gallium/drivers/v3d/v3d_context.h
+++ b/src/gallium/drivers/v3d/v3d_context.h
@@ -470,6 +470,12 @@ struct v3d_job {
          */
         enum v3d_ez_state first_ez_state;
 
+        /**
+         * If we have already decided if we need to disable early Z/S
+         * completely for this job.
+         */
+        bool decided_global_ez_enable;
+
         /**
          * If this job has been configured to use early Z/S clear.
          */
diff --git a/src/gallium/drivers/v3d/v3dx_draw.c b/src/gallium/drivers/v3d/v3dx_draw.c
index 80842b4066b..a3bc11907d7 100644
--- a/src/gallium/drivers/v3d/v3dx_draw.c
+++ b/src/gallium/drivers/v3d/v3dx_draw.c
@@ -852,6 +852,49 @@ v3d_update_primitives_generated_counter(struct v3d_context *v3d,
 static void
 v3d_update_job_ez(struct v3d_context *v3d, struct v3d_job *job)
 {
+        /* If first_ez_state is V3D_EZ_DISABLED it means that we have already
+         * determined that we should disable EZ completely for all draw calls
+         * in this job. This will cause us to disable EZ for the entire job in
+         * the Tile Rendering Mode RCL packet and when we do that we need to
+         * make sure we never emit a draw call in the job with EZ enabled in
+         * the CFG_BITS packet, so ez_state must also be V3D_EZ_DISABLED.
+         */
+        if (job->first_ez_state == V3D_EZ_DISABLED) {
+                assert(job->ez_state == V3D_EZ_DISABLED);
+                return;
+        }
+
+        /* If this is the first time we update EZ state for this job we first
+         * check if there is anything that requires disabling it completely
+         * for the entire job (based on state that is not related to the
+         * current draw call and pipeline state).
+         */
+        if (!job->decided_global_ez_enable) {
+                job->decided_global_ez_enable = true;
+
+                if (!job->zsbuf) {
+                        job->first_ez_state = V3D_EZ_DISABLED;
+                        job->ez_state = V3D_EZ_DISABLED;
+                        return;
+                }
+
+                /* GFXH-1918: the early-Z buffer may load incorrect depth
+                 * values if the frame has odd width or height. Disable early-Z
+                 * in this case.
+                 */
+                bool needs_depth_load = v3d->zsa && job->zsbuf &&
+                        v3d->zsa->base.depth_enabled &&
+                        (PIPE_CLEAR_DEPTH & ~job->clear);
+                if (needs_depth_load &&
+                     ((job->draw_width % 2 != 0) || (job->draw_height % 2 != 0))) {
+                        perf_debug("Loading depth buffer for framebuffer with odd width "
+                                   "or height disables early-Z tests\n");
+                        job->first_ez_state = V3D_EZ_DISABLED;
+                        job->ez_state = V3D_EZ_DISABLED;
+                        return;
+                }
+        }
+
         switch (v3d->zsa->ez_state) {
         case V3D_EZ_UNDECIDED:
                 /* If the Z/S state didn't pick a direction but didn't
diff --git a/src/gallium/drivers/v3d/v3dx_rcl.c b/src/gallium/drivers/v3d/v3dx_rcl.c
index 7c85525bc60..6147d6aef5a 100644
--- a/src/gallium/drivers/v3d/v3dx_rcl.c
+++ b/src/gallium/drivers/v3d/v3dx_rcl.c
@@ -726,6 +726,31 @@ v3dX(emit_rcl)(struct v3d_job *job)
                         struct v3d_surface *surf = v3d_surface(job->zsbuf);
                         config.internal_depth_type = surf->internal_type;
                 }
+#endif /* V3D_VERSION >= 40 */
+
+                if (job->decided_global_ez_enable) {
+                        switch (job->first_ez_state) {
+                        case V3D_EZ_UNDECIDED:
+                        case V3D_EZ_LT_LE:
+                                config.early_z_disable = false;
+                                config.early_z_test_and_update_direction =
+                                        EARLY_Z_DIRECTION_LT_LE;
+                                break;
+                        case V3D_EZ_GT_GE:
+                                config.early_z_disable = false;
+                                config.early_z_test_and_update_direction =
+                                        EARLY_Z_DIRECTION_GT_GE;
+                                break;
+                        case V3D_EZ_DISABLED:
+                                config.early_z_disable = true;
+                        }
+                } else {
+                        assert(job->draw_calls_queued == 0);
+                        config.early_z_disable = true;
+                }
+
+#if V3D_VERSION >= 40
+                assert(job->zsbuf || config.early_z_disable);
 
                 job->early_zs_clear = (job->clear & PIPE_CLEAR_DEPTHSTENCIL) &&
                         !(job->load & PIPE_CLEAR_DEPTHSTENCIL) &&
@@ -734,22 +759,6 @@ v3dX(emit_rcl)(struct v3d_job *job)
                 config.early_depth_stencil_clear = job->early_zs_clear;
 #endif /* V3D_VERSION >= 40 */
 
-                switch (job->first_ez_state) {
-                case V3D_EZ_UNDECIDED:
-                case V3D_EZ_LT_LE:
-                        config.early_z_disable = false;
-                        config.early_z_test_and_update_direction =
-                                EARLY_Z_DIRECTION_LT_LE;
-                        break;
-                case V3D_EZ_GT_GE:
-                        config.early_z_disable = false;
-                        config.early_z_test_and_update_direction =
-                                EARLY_Z_DIRECTION_GT_GE;
-                        break;
-                case V3D_EZ_DISABLED:
-                        config.early_z_disable = true;
-                }
-
                 config.image_width_pixels = job->draw_width;
                 config.image_height_pixels = job->draw_height;
 



More information about the mesa-commit mailing list