Mesa (master): etnaviv: rework ZSA into a derived state

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri Nov 6 09:21:39 UTC 2020


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

Author: Lucas Stach <l.stach at pengutronix.de>
Date:   Sun Nov  1 16:53:19 2020 +0100

etnaviv: rework ZSA into a derived state

The ZSA state is not fully self contained, as other states (mostly
shader using discard or writing depth information) have an influence
on whether we can use early Z test/write.

Rework the ZSA state into a derived state that gets updated whenever
a new ZSA or SHADER state is bound. This way we can automatically
enable/disable early Z as needed.

Signed-off-by: Lucas Stach <l.stach at pengutronix.de>
Reviewed-by: Christian Gmeiner <christian.gmeiner at gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7396>

---

 src/gallium/drivers/etnaviv/etnaviv_emit.c     |  3 +-
 src/gallium/drivers/etnaviv/etnaviv_internal.h |  3 +-
 src/gallium/drivers/etnaviv/etnaviv_shader.c   |  4 +-
 src/gallium/drivers/etnaviv/etnaviv_state.c    | 69 ++++++++++++++++++++++++++
 src/gallium/drivers/etnaviv/etnaviv_zsa.c      | 34 +++----------
 src/gallium/drivers/etnaviv/etnaviv_zsa.h      |  4 ++
 6 files changed, 84 insertions(+), 33 deletions(-)

diff --git a/src/gallium/drivers/etnaviv/etnaviv_emit.c b/src/gallium/drivers/etnaviv/etnaviv_emit.c
index db9a484fc06..934a739121c 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_emit.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_emit.c
@@ -431,8 +431,7 @@ etna_emit_state(struct etna_context *ctx)
    }
    if (unlikely(dirty & (ETNA_DIRTY_ZSA | ETNA_DIRTY_FRAMEBUFFER | ETNA_DIRTY_SHADER))) {
       /*01400*/ EMIT_STATE(PE_DEPTH_CONFIG, (etna_zsa_state(ctx->zsa)->PE_DEPTH_CONFIG |
-                                             ctx->framebuffer.PE_DEPTH_CONFIG) &
-                                            ctx->shader_state.PE_DEPTH_CONFIG);
+                                             ctx->framebuffer.PE_DEPTH_CONFIG));
    }
    if (unlikely(dirty & (ETNA_DIRTY_VIEWPORT))) {
       /*01404*/ EMIT_STATE(PE_DEPTH_NEAR, ctx->viewport.PE_DEPTH_NEAR);
diff --git a/src/gallium/drivers/etnaviv/etnaviv_internal.h b/src/gallium/drivers/etnaviv/etnaviv_internal.h
index dc5f3f2b902..36ddb3bc1ec 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_internal.h
+++ b/src/gallium/drivers/etnaviv/etnaviv_internal.h
@@ -245,7 +245,6 @@ struct compiled_shader_state {
    uint32_t PS_TEMP_REGISTER_CONTROL;
    uint32_t PS_TEMP_REGISTER_CONTROL_MSAA; /* Adds a temporary if needed to make space for extra input */
    uint32_t PS_START_PC;
-   uint32_t PE_DEPTH_CONFIG;
    uint32_t GL_VARYING_TOTAL_COMPONENTS;
    uint32_t GL_VARYING_NUM_COMPONENTS[2];
    uint32_t GL_VARYING_COMPONENT_USE[2];
@@ -257,6 +256,8 @@ struct compiled_shader_state {
    uint32_t *PS_INST_MEM;
    struct etna_reloc PS_INST_ADDR;
    struct etna_reloc VS_INST_ADDR;
+   unsigned writes_z:1;
+   unsigned uses_discard:1;
 };
 
 /* Helpers to assist creating and setting bitarrays (eg, for varyings).
diff --git a/src/gallium/drivers/etnaviv/etnaviv_shader.c b/src/gallium/drivers/etnaviv/etnaviv_shader.c
index 3f28e4db3ce..e890b34061d 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_shader.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_shader.c
@@ -251,8 +251,8 @@ etna_link_shaders(struct etna_context *ctx, struct compiled_shader_state *cs,
       VIVS_GL_HALTI5_SH_SPECIALS_PS_PCOORD_IN((link.pcoord_varying_comp_ofs != -1) ?
                                               link.pcoord_varying_comp_ofs : 0x7f);
 
-   /* mask out early Z bit when frag depth is written */
-   cs->PE_DEPTH_CONFIG = ~COND(fs->ps_depth_out_reg >= 0, VIVS_PE_DEPTH_CONFIG_EARLY_Z);
+   cs->writes_z = fs->ps_depth_out_reg >= 0;
+   cs->uses_discard = fs->uses_discard;
 
    /* reference instruction memory */
    cs->vs_inst_mem_size = vs->code_size;
diff --git a/src/gallium/drivers/etnaviv/etnaviv_state.c b/src/gallium/drivers/etnaviv/etnaviv_state.c
index e25d78ddb3a..1b4a7040b50 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_state.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_state.c
@@ -39,6 +39,7 @@
 #include "etnaviv_surface.h"
 #include "etnaviv_translate.h"
 #include "etnaviv_util.h"
+#include "etnaviv_zsa.h"
 #include "util/u_framebuffer.h"
 #include "util/u_helpers.h"
 #include "util/u_inlines.h"
@@ -675,6 +676,71 @@ etna_update_clipping(struct etna_context *ctx)
    return true;
 }
 
+static bool
+etna_update_zsa(struct etna_context *ctx)
+{
+   struct compiled_shader_state *shader_state = &ctx->shader_state;
+   struct pipe_depth_stencil_alpha_state *zsa_state = ctx->zsa;
+   struct etna_zsa_state *zsa = etna_zsa_state(zsa_state);
+   struct etna_screen *screen = ctx->screen;
+   uint32_t new_pe_depth, new_ra_depth;
+   bool late_z_write = false, early_z_write = false,
+        late_z_test = false, early_z_test = false;
+
+   if (zsa->z_write_enabled) {
+      if (VIV_FEATURE(screen, chipMinorFeatures5, RA_WRITE_DEPTH) &&
+          !VIV_FEATURE(screen, chipFeatures, NO_EARLY_Z) &&
+          !zsa->stencil_enabled &&
+          !zsa_state->alpha.enabled &&
+          !shader_state->writes_z &&
+          !shader_state->uses_discard)
+         early_z_write = true;
+      else
+         late_z_write = true;
+   }
+
+   if (zsa->z_test_enabled) {
+      if (!VIV_FEATURE(screen, chipFeatures, NO_EARLY_Z) &&
+          !zsa->stencil_modified &&
+          !shader_state->writes_z)
+         early_z_test = true;
+      else
+         late_z_test = true;
+   }
+
+   new_pe_depth = VIVS_PE_DEPTH_CONFIG_DEPTH_FUNC(zsa->z_test_enabled ?
+                     /* compare funcs have 1 to 1 mapping */
+                     zsa_state->depth.func : PIPE_FUNC_ALWAYS) |
+                  COND(zsa->z_write_enabled, VIVS_PE_DEPTH_CONFIG_WRITE_ENABLE) |
+                  COND(early_z_test, VIVS_PE_DEPTH_CONFIG_EARLY_Z) |
+                  COND(!late_z_write && !late_z_test && !zsa->stencil_enabled,
+                       VIVS_PE_DEPTH_CONFIG_DISABLE_ZS);
+
+   /* blob sets this to 0x40000031 on GC7000, seems to make no difference,
+    * but keep it in mind if depth behaves strangely. */
+   new_ra_depth = 0x0000030 |
+                  COND(early_z_test, VIVS_RA_EARLY_DEPTH_TEST_ENABLE);
+
+   if (VIV_FEATURE(screen, chipMinorFeatures5, RA_WRITE_DEPTH)) {
+      if (!early_z_write)
+         new_ra_depth |= VIVS_RA_EARLY_DEPTH_WRITE_DISABLE;
+      /* The new early hierarchical test seems to only work properly if depth
+       * is also written from the early stage.
+       */
+      if (late_z_test || (early_z_test && late_z_write))
+         new_ra_depth |= VIVS_RA_EARLY_DEPTH_HDEPTH_DISABLE;
+   }
+
+   if (new_pe_depth != zsa->PE_DEPTH_CONFIG ||
+       new_ra_depth != zsa->RA_DEPTH_CONFIG)
+      ctx->dirty |= ETNA_DIRTY_ZSA;
+
+   zsa->PE_DEPTH_CONFIG = new_pe_depth;
+   zsa->RA_DEPTH_CONFIG = new_ra_depth;
+
+   return true;
+}
+
 struct etna_state_updater {
    bool (*update)(struct etna_context *ctx);
    uint32_t dirty;
@@ -699,6 +765,9 @@ static const struct etna_state_updater etna_state_updates[] = {
    {
       etna_update_clipping, ETNA_DIRTY_SCISSOR | ETNA_DIRTY_FRAMEBUFFER |
                             ETNA_DIRTY_RASTERIZER | ETNA_DIRTY_VIEWPORT,
+   },
+   {
+      etna_update_zsa, ETNA_DIRTY_ZSA | ETNA_DIRTY_SHADER,
    }
 };
 
diff --git a/src/gallium/drivers/etnaviv/etnaviv_zsa.c b/src/gallium/drivers/etnaviv/etnaviv_zsa.c
index 2f9f2cb13c1..66d0c290c9f 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_zsa.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_zsa.c
@@ -47,11 +47,10 @@ etna_zsa_state_create(struct pipe_context *pctx,
 
    cs->base = *so;
 
+   cs->z_test_enabled = so->depth.enabled && so->depth.func != PIPE_FUNC_ALWAYS;
+   cs->z_write_enabled = so->depth.enabled && so->depth.writemask;
+
    /* XXX does stencil[0] / stencil[1] order depend on rs->front_ccw? */
-   bool early_z = !VIV_FEATURE(ctx->screen, chipFeatures, NO_EARLY_Z);
-   bool disable_zs =
-      (!so->depth.enabled || so->depth.func == PIPE_FUNC_ALWAYS) &&
-      !so->depth.writemask;
 
 /* Set operations to KEEP if write mask is 0.
  * When we don't do this, the depth buffer is written for the entire primitive
@@ -73,27 +72,21 @@ etna_zsa_state_create(struct pipe_context *pctx,
    if (so->stencil[0].enabled) {
       if (so->stencil[0].func != PIPE_FUNC_ALWAYS ||
           (so->stencil[1].enabled && so->stencil[1].func != PIPE_FUNC_ALWAYS))
-         disable_zs = false;
+         cs->stencil_enabled = 1;
 
       if (so->stencil[0].fail_op != PIPE_STENCIL_OP_KEEP ||
           so->stencil[0].zfail_op != PIPE_STENCIL_OP_KEEP ||
           so->stencil[0].zpass_op != PIPE_STENCIL_OP_KEEP) {
-         disable_zs = early_z = false;
+         cs->stencil_modified = 1;
       } else if (so->stencil[1].enabled) {
          if (so->stencil[1].fail_op != PIPE_STENCIL_OP_KEEP ||
              so->stencil[1].zfail_op != PIPE_STENCIL_OP_KEEP ||
              so->stencil[1].zpass_op != PIPE_STENCIL_OP_KEEP) {
-            disable_zs = early_z = false;
+            cs->stencil_modified = 1;
          }
       }
    }
 
-   /* Disable early z reject when no depth test is enabled.
-    * This avoids having to sample depth even though we know it's going to
-    * succeed. */
-   if (so->depth.enabled == false || so->depth.func == PIPE_FUNC_ALWAYS)
-      early_z = false;
-
    /* calculate extra_reference value */
    uint32_t extra_reference = 0;
 
@@ -103,15 +96,6 @@ etna_zsa_state_create(struct pipe_context *pctx,
    cs->PE_STENCIL_CONFIG_EXT =
       VIVS_PE_STENCIL_CONFIG_EXT_EXTRA_ALPHA_REF(extra_reference);
 
-   /* compare funcs have 1 to 1 mapping */
-   cs->PE_DEPTH_CONFIG =
-      VIVS_PE_DEPTH_CONFIG_DEPTH_FUNC(so->depth.enabled ? so->depth.func
-                                                        : PIPE_FUNC_ALWAYS) |
-      COND(so->depth.writemask, VIVS_PE_DEPTH_CONFIG_WRITE_ENABLE) |
-      COND(early_z, VIVS_PE_DEPTH_CONFIG_EARLY_Z) |
-      /* this bit changed meaning with HALTI5: */
-      COND((disable_zs && screen->specs.halti < 5) || ((early_z || disable_zs) && VIV_FEATURE(screen, chipMinorFeatures5, RA_WRITE_DEPTH)), VIVS_PE_DEPTH_CONFIG_DISABLE_ZS);
-
    cs->PE_ALPHA_OP =
       COND(so->alpha.enabled, VIVS_PE_ALPHA_OP_ALPHA_TEST) |
       VIVS_PE_ALPHA_OP_ALPHA_FUNC(so->alpha.func) |
@@ -138,12 +122,6 @@ etna_zsa_state_create(struct pipe_context *pctx,
          VIVS_PE_STENCIL_CONFIG_EXT2_WRITE_MASK_BACK(stencil_back->writemask);
    }
 
-   /* blob sets this to 0x40000031 on GC7000, seems to make no difference,
-    * but keep it in mind if depth behaves strangely. */
-   cs->RA_DEPTH_CONFIG = 0x00000031;
-   if (VIV_FEATURE(screen, chipMinorFeatures5, RA_WRITE_DEPTH) && !disable_zs && !early_z)
-      cs->RA_DEPTH_CONFIG |= 0x11000000;
-
    /* XXX does alpha/stencil test affect PE_COLOR_FORMAT_OVERWRITE? */
    return cs;
 }
diff --git a/src/gallium/drivers/etnaviv/etnaviv_zsa.h b/src/gallium/drivers/etnaviv/etnaviv_zsa.h
index dfa1b572a30..e423474ad10 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_zsa.h
+++ b/src/gallium/drivers/etnaviv/etnaviv_zsa.h
@@ -40,6 +40,10 @@ struct etna_zsa_state {
    uint32_t PE_STENCIL_CONFIG_EXT;
    uint32_t PE_STENCIL_CONFIG_EXT2[2];
    uint32_t RA_DEPTH_CONFIG;
+   unsigned z_test_enabled:1;
+   unsigned z_write_enabled:1;
+   unsigned stencil_enabled:1;
+   unsigned stencil_modified:1;
 
 };
 



More information about the mesa-commit mailing list