From 3d600b2c0ec2effeaadcb047e9508dd63c1e7d17 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Wed, 12 Mar 2025 16:22:07 +0100 Subject: [PATCH] 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 Reviewed-by: Christian Gmeiner Part-of: (cherry picked from commit fb0f9e6352251576f5aff76166b40ddb76c366ad) --- .pick_status.json | 2 +- src/gallium/drivers/etnaviv/etnaviv_rs.c | 29 ++++++++++++++++-------- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/.pick_status.json b/.pick_status.json index 55690a2a610..5abcbb91654 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -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 diff --git a/src/gallium/drivers/etnaviv/etnaviv_rs.c b/src/gallium/drivers/etnaviv/etnaviv_rs.c index 06c1a4887bf..6177de8e5ea 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_rs.c +++ b/src/gallium/drivers/etnaviv/etnaviv_rs.c @@ -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);