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@pengutronix.de>
Reviewed-by: Christian Gmeiner <christian.gmeiner@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7396>
diff --git a/src/gallium/drivers/etnaviv/etnaviv_emit.c b/src/gallium/drivers/etnaviv/etnaviv_emit.c
index db9a484..934a739 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_emit.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_emit.c
@@ -431,8 +431,7 @@
}
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 dc5f3f2..36ddb3b 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_internal.h
+++ b/src/gallium/drivers/etnaviv/etnaviv_internal.h
@@ -245,7 +245,6 @@
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 @@
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 3f28e4d..e890b34 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_shader.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_shader.c
@@ -251,8 +251,8 @@
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 e25d78d..1b4a704 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 @@
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 @@
{
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 2f9f2cb..66d0c29 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_zsa.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_zsa.c
@@ -47,11 +47,10 @@
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 @@
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 @@
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 @@
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 dfa1b57..e423474 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_zsa.h
+++ b/src/gallium/drivers/etnaviv/etnaviv_zsa.h
@@ -40,6 +40,10 @@
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;
};