etnaviv: switch to late Z when linear PE is used
authorLucas Stach <l.stach@pengutronix.de>
Fri, 11 Nov 2022 16:20:41 +0000 (17:20 +0100)
committerMarge Bot <emma+marge@anholt.net>
Tue, 15 Nov 2022 09:51:56 +0000 (09:51 +0000)
In linear PE mode the early and late depth stage do not only disagree
about the cache layout, but they seem to fundamentally disagree about
the buffer layout. When Z was written via the late stage, early tests
always show spurious zfails, even if they are not in the same draw
call. Cache flushing and pipe stalls don't help in that case.

The only option to get reliable Z tests with linear render targets is
to move all Z handling into the PE stage. Even when early Z writes
are possible, we don't know if any other draw to the same surface
needs late Z handling, so we must never use the early stage.

Fixes: 53445284a427 ("etnaviv: add linear PE support")
Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/19686>

src/gallium/drivers/etnaviv/etnaviv_state.c

index 794e682..6b17ad9 100644 (file)
@@ -718,12 +718,26 @@ etna_update_zsa(struct etna_context *ctx)
    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 early_z_allowed = !VIV_FEATURE(screen, chipFeatures, NO_EARLY_Z);
    bool late_z_write = false, early_z_write = false,
         late_z_test = false, early_z_test = false;
 
+   /* Linear PE breaks the combination of early test with late write, as it
+    * seems RA and PE disagree about the buffer layout in this mode. Fall back
+    * to late Z always even though early Z write might be possible, as we don't
+    * know if any other draws to the same surface require late Z write.
+    */
+   if (ctx->framebuffer_s.nr_cbufs > 0) {
+      struct etna_surface *cbuf = etna_surface(ctx->framebuffer_s.cbufs[0]);
+      struct etna_resource *res = etna_resource(cbuf->base.texture);
+
+      if (res->layout == ETNA_LAYOUT_LINEAR)
+         early_z_allowed = false;
+   }
+
    if (zsa->z_write_enabled) {
       if (VIV_FEATURE(screen, chipMinorFeatures5, RA_WRITE_DEPTH) &&
-          !VIV_FEATURE(screen, chipFeatures, NO_EARLY_Z) &&
+          early_z_allowed &&
           !zsa->stencil_enabled &&
           !zsa_state->alpha_enabled &&
           !shader_state->writes_z &&
@@ -734,7 +748,7 @@ etna_update_zsa(struct etna_context *ctx)
    }
 
    if (zsa->z_test_enabled) {
-      if (!VIV_FEATURE(screen, chipFeatures, NO_EARLY_Z) &&
+      if (early_z_allowed &&
           !zsa->stencil_modified &&
           !shader_state->writes_z)
          early_z_test = true;
@@ -742,20 +756,6 @@ etna_update_zsa(struct etna_context *ctx)
          late_z_test = true;
    }
 
-   /* Linear PE breaks the combination of early test with late write, as it
-    * seems RA and PE disagree about the cache layout in this mode. Switch to
-    * late test to work around this issue.
-    */
-   if (ctx->framebuffer_s.nr_cbufs > 0) {
-      struct etna_surface *cbuf = etna_surface(ctx->framebuffer_s.cbufs[0]);
-      struct etna_resource *res = etna_resource(cbuf->base.texture);
-
-      if (res->layout == ETNA_LAYOUT_LINEAR && early_z_test && late_z_write) {
-         early_z_test = false;
-         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) |