From df63f188e83a3c041d93ee272d593bfd2679be82 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Wed, 10 Apr 2024 15:38:58 +0200 Subject: [PATCH] etnaviv: fix separate depth/stencil clears TS only tracks the clear state on a per-tile basis, so for a combined depth/stencil buffer there is no way to fast-clear the one without also affecting the other. Fall back to a regular clear when the clear_bits tell us that not all channels of the buffer are to be cleared and make sure to flush/invalidate any pending TS state when we do so. Signed-off-by: Lucas Stach Reviewed-by: Christian Gmeiner Part-of: --- src/gallium/drivers/etnaviv/etnaviv_rs.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/gallium/drivers/etnaviv/etnaviv_rs.c b/src/gallium/drivers/etnaviv/etnaviv_rs.c index 5e11bd95ee0..2aeda88b227 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_rs.c +++ b/src/gallium/drivers/etnaviv/etnaviv_rs.c @@ -398,13 +398,8 @@ etna_blit_clear_zs_rs(struct pipe_context *pctx, struct pipe_surface *dst, new_clear_bits |= clear_bits_depth; if (buffers & PIPE_CLEAR_STENCIL) new_clear_bits |= clear_bits_stencil; - /* FIXME: when tile status is enabled, this becomes more complex as - * we may separately clear the depth from the stencil. In this case, - * we want to resolve the surface, and avoid using the tile status. - * We may be better off recording the pending clear operation, - * delaying the actual clear to the first use. This way, we can merge - * consecutive clears together. */ - if (surf->level->ts_size) { /* TS: use precompiled clear command */ + + if (surf->level->ts_size && new_clear_bits == 0xffff) { /* Set new clear depth value */ ctx->framebuffer.TS_DEPTH_CLEAR_VALUE = new_clear_value; if (VIV_FEATURE(ctx->screen, chipMinorFeatures1, AUTO_DISABLE)) { @@ -417,12 +412,19 @@ etna_blit_clear_zs_rs(struct pipe_context *pctx, struct pipe_surface *dst, etna_resource_level_ts_mark_valid(surf->level); ctx->dirty |= ETNA_DIRTY_TS | ETNA_DIRTY_DERIVE_TS; } else { + /* If the level has valid TS state we need to flush it, as the regular + * clear will not update the state and we must therefore invalidate it. */ + etna_copy_resource(pctx, surf->base.texture, surf->base.texture, + surf->base.u.tex.level, surf->base.u.tex.level); + if (unlikely(new_clear_value != surf->level->clear_value)) { /* Queue normal RS clear for non-TS surfaces */ /* If clear depth value changed, re-generate stored command */ etna_rs_gen_clear_surface(ctx, surf, new_clear_value); } /* Update the channels to be cleared */ etna_modify_rs_clearbits(&surf->clear_command, new_clear_bits); + + etna_resource_level_ts_mark_invalid(surf->level); } etna_submit_rs_state(ctx, &surf->clear_command);