etnaviv: allow 0 back stencil valuemask on new cores

Older cores have a hardware bug where the stencil test misbehaves when
the valuemask is 0 in the back stencil. The workaround is to effectively
switch to single sided stencil and hope for the best. This seems to be
okay for most actual use-cases and tests, as a 0 valuemask is quite rare.

However, as 0 is a valid value for the mask the workaround breaks some
edge cases. Newer cores don't seem to require the workaround and operate
correctly with all stencil valuemasks, so drop the workaround for them.

I don't know which feature bit tells us about the bugfix. I made an
educated guess by checking behavior on multiple GPUs: GC880r5106 and
GC2000r5108 need the workaround, GC3000r5450, GC7000r6204 and GC600r4653
work fine without it. By comparing the set BugFixes feature bits between
the cores and the fact that BugFixes15 already fixes some PE issues, I
think this one is the most likely candidate.

Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Reviewed-by: Christian Gmeiner <cgmeiner@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/35704>
This commit is contained in:
Lucas Stach
2025-06-23 23:45:28 +02:00
committed by Marge Bot
parent 2dc5db625b
commit 41b08a2040
4 changed files with 17 additions and 3 deletions
+2 -1
View File
@@ -532,7 +532,8 @@ etna_emit_state(struct etna_context *ctx)
}
if (unlikely(dirty & (ETNA_DIRTY_STENCIL_REF | ETNA_DIRTY_RASTERIZER | ETNA_DIRTY_ZSA))) {
uint32_t val = etna_zsa_state(ctx->zsa)->PE_STENCIL_CONFIG_EXT;
if (!ctx->zsa->stencil[1].enabled && ctx->zsa->stencil[0].valuemask)
if (!ctx->zsa->stencil[1].enabled &&
(screen->specs.correct_stencil_valuemask || ctx->zsa->stencil[0].valuemask))
val |= ctx->stencil_ref.PE_STENCIL_CONFIG_EXT[!ccw];
else
val |= ctx->stencil_ref.PE_STENCIL_CONFIG_EXT[ccw];
@@ -89,6 +89,8 @@ struct etna_specs {
unsigned tex_astc : 1;
/* has BLT engine instead of RS */
unsigned use_blt : 1;
/* has correct stencil 0 valuemask */
unsigned correct_stencil_valuemask : 1;
/* number of bits per TS tile */
unsigned bits_per_tile;
/* clear value for TS (dependent on bits_per_tile) */
@@ -829,6 +829,9 @@ etna_get_specs(struct etna_screen *screen)
screen->specs.v4_compression =
VIV_FEATURE(screen, ETNA_FEATURE_V4_COMPRESSION);
/* XXX: The feature bit gating the bugfix is an educated guess */
screen->specs.correct_stencil_valuemask = VIV_FEATURE(screen, ETNA_FEATURE_PE_DITHER_FIX);
if (screen->info->halti >= 5) {
/* GC7000 - this core must load shaders from memory. */
screen->specs.vs_offset = 0;
+10 -2
View File
@@ -100,8 +100,16 @@ etna_zsa_state_create(struct pipe_context *pctx,
VIVS_PE_ALPHA_OP_ALPHA_REF(float_to_ubyte(so->alpha_ref_value));
for (unsigned i = 0; i < 2; i++) {
const struct pipe_stencil_state *stencil_front = (so->stencil[1].enabled && so->stencil[1].valuemask) ? &so->stencil[i] : &so->stencil[0];
const struct pipe_stencil_state *stencil_back = (so->stencil[1].enabled && so->stencil[1].valuemask) ? &so->stencil[!i] : &so->stencil[0];
const struct pipe_stencil_state *stencil_front, *stencil_back;
if (so->stencil[1].enabled &&
(screen->specs.correct_stencil_valuemask || so->stencil[1].valuemask)) {
stencil_front = &so->stencil[i];
stencil_back = &so->stencil[!i];
} else {
stencil_front = stencil_back = &so->stencil[0];
}
cs->PE_STENCIL_OP[i] =
VIVS_PE_STENCIL_OP_FUNC_FRONT(stencil_front->func) |
VIVS_PE_STENCIL_OP_FUNC_BACK(stencil_back->func) |