Mesa (master): broadcom/vc5: Fix EZ disabling and allow using GT/GE direction as well.

Eric Anholt anholt at kemper.freedesktop.org
Tue Mar 27 00:49:26 UTC 2018


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

Author: Eric Anholt <eric at anholt.net>
Date:   Fri Mar 23 16:18:02 2018 -0700

broadcom/vc5: Fix EZ disabling and allow using GT/GE direction as well.

Once we've disabled EZ for some draws, we need to not use EZ on future
draws.  Implementing that made implementing the GT/GE direction trivial.

Fixes KHR-GLES3.shaders.fragdepth.compare.no_write on V3D 4.1 simulation.

---

 src/gallium/drivers/vc5/vc5_context.h | 20 +++++++++++++--
 src/gallium/drivers/vc5/vc5_draw.c    | 47 ++++++++++++++++++++++++++++++++---
 src/gallium/drivers/vc5/vc5_emit.c    |  9 ++++---
 src/gallium/drivers/vc5/vc5_rcl.c     | 16 +++++++++++-
 src/gallium/drivers/vc5/vc5_state.c   | 40 ++++++++++++++++++++---------
 5 files changed, 111 insertions(+), 21 deletions(-)

diff --git a/src/gallium/drivers/vc5/vc5_context.h b/src/gallium/drivers/vc5/vc5_context.h
index f6ed91c27a..f61c37ba92 100644
--- a/src/gallium/drivers/vc5/vc5_context.h
+++ b/src/gallium/drivers/vc5/vc5_context.h
@@ -199,6 +199,13 @@ struct vc5_job_key {
         struct pipe_surface *zsbuf;
 };
 
+enum vc5_ez_state {
+        VC5_EZ_UNDECIDED = 0,
+        VC5_EZ_GT_GE,
+        VC5_EZ_LT_LE,
+        VC5_EZ_DISABLED,
+};
+
 /**
  * A complete bin/render job.
  *
@@ -300,7 +307,16 @@ struct vc5_job {
          */
         bool tf_enabled;
 
-        bool uses_early_z;
+        /**
+         * Current EZ state for drawing. Updated at the start of draw after
+         * we've decided on the shader being rendered.
+         */
+        enum vc5_ez_state ez_state;
+        /**
+         * The first EZ state that was used for drawing with a decided EZ
+         * direction (so either UNDECIDED, GT, or LT).
+         */
+        enum vc5_ez_state first_ez_state;
 
         /**
          * Number of draw calls (not counting full buffer clears) queued in
@@ -429,7 +445,7 @@ struct vc5_rasterizer_state {
 struct vc5_depth_stencil_alpha_state {
         struct pipe_depth_stencil_alpha_state base;
 
-        bool early_z_enable;
+        enum vc5_ez_state ez_state;
 
         /** Uniforms for stencil state.
          *
diff --git a/src/gallium/drivers/vc5/vc5_draw.c b/src/gallium/drivers/vc5/vc5_draw.c
index 7a409c14d4..25f4883be2 100644
--- a/src/gallium/drivers/vc5/vc5_draw.c
+++ b/src/gallium/drivers/vc5/vc5_draw.c
@@ -327,6 +327,49 @@ vc5_tf_statistics_record(struct vc5_context *vc5,
 }
 
 static void
+vc5_update_job_ez(struct vc5_context *vc5, struct vc5_job *job)
+{
+        switch (vc5->zsa->ez_state) {
+        case VC5_EZ_UNDECIDED:
+                /* If the Z/S state didn't pick a direction but didn't
+                 * disable, then go along with the current EZ state.  This
+                 * allows EZ optimization for Z func == EQUAL or NEVER.
+                 */
+                break;
+
+        case VC5_EZ_LT_LE:
+        case VC5_EZ_GT_GE:
+                /* If the Z/S state picked a direction, then it needs to match
+                 * the current direction if we've decided on one.
+                 */
+                if (job->ez_state == VC5_EZ_UNDECIDED)
+                        job->ez_state = vc5->zsa->ez_state;
+                else if (job->ez_state != vc5->zsa->ez_state)
+                        job->ez_state = VC5_EZ_DISABLED;
+                break;
+
+        case VC5_EZ_DISABLED:
+                /* If the current Z/S state 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 = VC5_EZ_DISABLED;
+                break;
+        }
+
+        /* If the FS affects the Z of the pixels, then it may update against
+         * the chosen EZ direction (though we could use
+         * ARB_conservative_depth's hints to avoid this)
+         */
+        if (vc5->prog.fs->prog_data.fs->writes_z) {
+                job->ez_state = VC5_EZ_DISABLED;
+        }
+
+        if (job->first_ez_state == VC5_EZ_UNDECIDED)
+                job->first_ez_state = job->ez_state;
+}
+
+static void
 vc5_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
 {
         struct vc5_context *vc5 = vc5_context(pctx);
@@ -384,6 +427,7 @@ vc5_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
 
         vc5_start_draw(vc5);
         vc5_update_compiled_shaders(vc5, info->mode);
+        vc5_update_job_ez(vc5, job);
 
 #if V3D_VERSION >= 41
         v3d41_emit_state(pctx);
@@ -515,9 +559,6 @@ vc5_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
                 if (vc5->zsa->base.depth.enabled) {
                         job->resolve |= PIPE_CLEAR_DEPTH;
                         rsc->initialized_buffers = PIPE_CLEAR_DEPTH;
-
-                        if (vc5->zsa->early_z_enable)
-                                job->uses_early_z = true;
                 }
 
                 if (vc5->zsa->base.stencil[0].enabled) {
diff --git a/src/gallium/drivers/vc5/vc5_emit.c b/src/gallium/drivers/vc5/vc5_emit.c
index d5bf2824d2..71f508c9ee 100644
--- a/src/gallium/drivers/vc5/vc5_emit.c
+++ b/src/gallium/drivers/vc5/vc5_emit.c
@@ -382,13 +382,16 @@ v3dX(emit_state)(struct pipe_context *pctx)
 
                         config.blend_enable = vc5->blend->rt[0].blend_enable;
 
-                        config.early_z_updates_enable = true;
+                        /* Note: EZ state may update based on the compiled FS,
+                         * along with ZSA
+                         */
+                        config.early_z_updates_enable =
+                                (job->ez_state != VC5_EZ_DISABLED);
                         if (vc5->zsa->base.depth.enabled) {
                                 config.z_updates_enable =
                                         vc5->zsa->base.depth.writemask;
                                 config.early_z_enable =
-                                        (vc5->zsa->early_z_enable &&
-                                         !vc5->prog.fs->prog_data.fs->writes_z);
+                                        config.early_z_updates_enable;
                                 config.depth_test_function =
                                         vc5->zsa->base.depth.func;
                         } else {
diff --git a/src/gallium/drivers/vc5/vc5_rcl.c b/src/gallium/drivers/vc5/vc5_rcl.c
index a5efa32e21..8ff1515f88 100644
--- a/src/gallium/drivers/vc5/vc5_rcl.c
+++ b/src/gallium/drivers/vc5/vc5_rcl.c
@@ -481,7 +481,21 @@ v3dX(emit_rcl)(struct vc5_job *job)
 
                 /* XXX: Early D/S clear */
 
-                config.early_z_disable = !job->uses_early_z;
+                switch (job->first_ez_state) {
+                case VC5_EZ_UNDECIDED:
+                case VC5_EZ_LT_LE:
+                        config.early_z_disable = false;
+                        config.early_z_test_and_update_direction =
+                                EARLY_Z_DIRECTION_LT_LE;
+                        break;
+                case VC5_EZ_GT_GE:
+                        config.early_z_disable = false;
+                        config.early_z_test_and_update_direction =
+                                EARLY_Z_DIRECTION_GT_GE;
+                        break;
+                case VC5_EZ_DISABLED:
+                        config.early_z_disable = true;
+                }
 
                 config.image_width_pixels = job->draw_width;
                 config.image_height_pixels = job->draw_height;
diff --git a/src/gallium/drivers/vc5/vc5_state.c b/src/gallium/drivers/vc5/vc5_state.c
index 75cd948e4a..ba2d748ba9 100644
--- a/src/gallium/drivers/vc5/vc5_state.c
+++ b/src/gallium/drivers/vc5/vc5_state.c
@@ -158,19 +158,35 @@ vc5_create_depth_stencil_alpha_state(struct pipe_context *pctx,
         so->base = *cso;
 
         if (cso->depth.enabled) {
-                /* We only handle early Z in the < direction because otherwise
-                 * we'd have to runtime guess which direction to set in the
-                 * render config.
+                switch (cso->depth.func) {
+                case PIPE_FUNC_LESS:
+                case PIPE_FUNC_LEQUAL:
+                        so->ez_state = VC5_EZ_LT_LE;
+                        break;
+                case PIPE_FUNC_GREATER:
+                case PIPE_FUNC_GEQUAL:
+                        so->ez_state = VC5_EZ_GT_GE;
+                        break;
+                case PIPE_FUNC_NEVER:
+                case PIPE_FUNC_EQUAL:
+                        so->ez_state = VC5_EZ_UNDECIDED;
+                        break;
+                default:
+                        so->ez_state = VC5_EZ_DISABLED;
+                        break;
+                }
+
+                /* If stencil is enabled and it's not a no-op, then it would
+                 * break EZ updates.
                  */
-                so->early_z_enable =
-                        ((cso->depth.func == PIPE_FUNC_LESS ||
-                          cso->depth.func == PIPE_FUNC_LEQUAL) &&
-                         (!cso->stencil[0].enabled ||
-                          (cso->stencil[0].zfail_op == PIPE_STENCIL_OP_KEEP &&
-                           cso->stencil[0].func == PIPE_FUNC_ALWAYS &&
-                           (!cso->stencil[1].enabled ||
-                            (cso->stencil[1].zfail_op == PIPE_STENCIL_OP_KEEP &&
-                             cso->stencil[1].func == PIPE_FUNC_ALWAYS)))));
+                if (cso->stencil[0].enabled &&
+                    (cso->stencil[0].zfail_op != PIPE_STENCIL_OP_KEEP ||
+                     cso->stencil[0].func != PIPE_FUNC_ALWAYS ||
+                     (cso->stencil[1].enabled &&
+                      (cso->stencil[1].zfail_op != PIPE_STENCIL_OP_KEEP &&
+                       cso->stencil[1].func != PIPE_FUNC_ALWAYS)))) {
+                        so->ez_state = VC5_EZ_DISABLED;
+                }
         }
 
         const struct pipe_stencil_state *front = &cso->stencil[0];




More information about the mesa-commit mailing list