etnaviv: rs: fix slow/fast clear transitions

When a slow/fast/slow clear sequence is executed on a surface, the second
slow clear will not regenerate the clear command if the clear value of the
fast clear is the same as the one used for the second slow clear, as the
current stored surface clear value is the same as the new clear value.
The command generated on the first slow clear however may have used a
different clear value, which is now submitted unchanged to the hardware on
the second slow clear.

Fix this by only generating the clear command if there is no valid one
already. If we already have a valid clear command simply update the fill
value in that command with the new clear value. This has some marginal
overhead, but has been chosen over the alternative of adding more state by
remembering the last slow clear value.

Cc: mesa-stable
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/34029>
(cherry picked from commit fb0f9e6352)
This commit is contained in:
Lucas Stach 2025-03-12 16:22:07 +01:00 committed by Eric Engestrom
parent 249613cd92
commit 3d600b2c0e
2 changed files with 21 additions and 10 deletions

View file

@ -944,7 +944,7 @@
"description": "etnaviv: rs: fix slow/fast clear transitions",
"nominated": true,
"nomination_type": 1,
"resolution": 0,
"resolution": 1,
"main_sha": null,
"because_sha": null,
"notes": null

View file

@ -192,6 +192,15 @@ etna_modify_rs_clearbits(struct compiled_rs_state *cs, uint32_t clear_bits)
cs->RS_CLEAR_CONTROL |= VIVS_RS_CLEAR_CONTROL_BITS(clear_bits);
}
static void
etna_modify_rs_fill_value(struct compiled_rs_state *cs, uint64_t clear_value)
{
cs->RS_FILL_VALUE[0] = clear_value;
cs->RS_FILL_VALUE[1] = clear_value >> 32;
cs->RS_FILL_VALUE[2] = clear_value;
cs->RS_FILL_VALUE[3] = clear_value >> 32;
}
#define EMIT_STATE(state_name, src_value) \
etna_coalsence_emit(stream, &coalesce, VIVS_##state_name, src_value)
@ -365,11 +374,12 @@ etna_blit_clear_color_rs(struct pipe_context *pctx, unsigned idx,
etna_resource_level_mark_unflushed(surf->level);
ctx->dirty |= ETNA_DIRTY_TS;
} else { /* Queue normal RS clear for non-TS surfaces */
/* If clear color changed or no valid command yet (re-)generate
* stored command */
if (unlikely(new_clear_value != surf->level->clear_value ||
!surf->clear_command.valid))
/* If no valid command yet generate stored command, otherwise simply
* update the clear value. */
if (unlikely(!surf->clear_command.valid))
etna_rs_gen_clear_surface(ctx, surf, new_clear_value);
else
etna_modify_rs_fill_value(&surf->clear_command, new_clear_value);
etna_submit_rs_state(ctx, &surf->clear_command);
etna_resource_level_ts_mark_invalid(surf->level);
@ -433,12 +443,13 @@ etna_blit_clear_zs_rs(struct pipe_context *pctx, struct pipe_surface *dst,
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 ||
!surf->clear_command.valid)) {
/* If clear depth/stencil value changed or no valid command yet
* (re)-generate stored command */
/* If no valid command yet generate stored command, otherwise simply
* update clear value. */
if (unlikely(!surf->clear_command.valid))
etna_rs_gen_clear_surface(ctx, surf, new_clear_value);
}
else
etna_modify_rs_fill_value(&surf->clear_command, new_clear_value);
/* Update the channels to be cleared */
etna_modify_rs_clearbits(&surf->clear_command, new_clear_bits);