From 4bed508122b20b750f71883f2225e14b9bb15102 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Mon, 28 Oct 2024 20:42:46 +0100 Subject: [PATCH] etnaviv: track TS flushed status as bool TS can be valid and flushed at the same time when no compression is used. This state is beneficial if we needed to flush TS to the base surface (filling cleared tiles) for any reason, but still use TS state to accelerate read requests into PE or TX caches. The current seqno based tracking of the TS flush state has a major drawback with the following sequence of events: 1. fast clear surface (TS is now valid) 2. flush TS (base surface tiles filled, TS still valid, flush seqno == surface seqno) 3. render to surface (surface seqno increased) 4. flush resource Step 4 will now execute a full TS flush as the flush and surface seqnos are different after rendering and TS is still valid, wasting memory bandwidth to fill already filled tiled that are still marked as clear in the TS state. If the TS has been flushed already, step 4 should be a no-op. Switch from the seqno based tracking to tracking the flush state itself, marking the TS state un-/flushed as needed. With this boolean tracking of the flush state step4 above will correctly see that the TS has already been flushed since the last fast clear and skip the tile fill blit. Signed-off-by: Lucas Stach Reviewed-by: Christian Gmeiner Part-of: --- src/gallium/drivers/etnaviv/etnaviv_blt.c | 2 ++ .../drivers/etnaviv/etnaviv_resource.c | 4 ++- .../drivers/etnaviv/etnaviv_resource.h | 25 +++++++++++++------ src/gallium/drivers/etnaviv/etnaviv_rs.c | 2 ++ 4 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/gallium/drivers/etnaviv/etnaviv_blt.c b/src/gallium/drivers/etnaviv/etnaviv_blt.c index af9cf11d534..31ed591d50f 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_blt.c +++ b/src/gallium/drivers/etnaviv/etnaviv_blt.c @@ -280,6 +280,7 @@ etna_blit_clear_color_blt(struct pipe_context *pctx, unsigned idx, surf->level->ts_meta->v0.clear_value = new_clear_value; etna_resource_level_ts_mark_valid(surf->level); + etna_resource_level_mark_unflushed(surf->level); ctx->dirty |= ETNA_DIRTY_TS | ETNA_DIRTY_DERIVE_TS; } @@ -362,6 +363,7 @@ etna_blit_clear_zs_blt(struct pipe_context *pctx, struct pipe_surface *dst, if (surf->level->ts_size) { ctx->framebuffer.TS_DEPTH_CLEAR_VALUE = surf->level->clear_value; etna_resource_level_ts_mark_valid(surf->level); + etna_resource_level_mark_unflushed(surf->level); ctx->dirty |= ETNA_DIRTY_TS | ETNA_DIRTY_DERIVE_TS; } diff --git a/src/gallium/drivers/etnaviv/etnaviv_resource.c b/src/gallium/drivers/etnaviv/etnaviv_resource.c index 563b1603a1f..f309b73d714 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_resource.c +++ b/src/gallium/drivers/etnaviv/etnaviv_resource.c @@ -568,8 +568,10 @@ etna_resource_changed(struct pipe_screen *pscreen, struct pipe_resource *prsc) { struct etna_resource *rsc = etna_resource(prsc); - for (int level = 0; level <= prsc->last_level; level++) + for (int level = 0; level <= prsc->last_level; level++) { etna_resource_level_mark_changed(&rsc->levels[level]); + etna_resource_level_mark_unflushed(&rsc->levels[level]); + } } static void diff --git a/src/gallium/drivers/etnaviv/etnaviv_resource.h b/src/gallium/drivers/etnaviv/etnaviv_resource.h index df1b1c42032..6c159e2d723 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_resource.h +++ b/src/gallium/drivers/etnaviv/etnaviv_resource.h @@ -51,9 +51,9 @@ struct etna_ts_sw_meta { uint32_t comp_format; uint64_t clear_value; uint32_t seqno; - uint32_t flush_seqno; uint8_t valid; - uint8_t pad[3]; + uint8_t flushed; + uint8_t pad[6]; } v0; }; @@ -71,6 +71,7 @@ struct etna_resource_level { uint32_t ts_size; uint64_t clear_value; /* clear value of resource level (mainly for TS) */ bool ts_valid; + bool ts_flushed; uint8_t ts_mode; int8_t ts_compress_fmt; /* COLOR_COMPRESSION_FORMAT_* (-1 = disable) */ @@ -81,7 +82,6 @@ struct etna_resource_level { struct util_dynarray *patch_offsets; uint32_t seqno; - uint32_t flush_seqno; }; /* returns TRUE if a is newer than b */ @@ -133,7 +133,7 @@ etna_resource_level_ts_mark_invalid(struct etna_resource_level *lvl) lvl->ts_valid = false; } -/* returns TRUE if a is older than b */ +/* returns TRUE if lvl has valid, unflushed TS data */ static inline bool etna_resource_level_needs_flush(struct etna_resource_level *lvl) { @@ -141,18 +141,27 @@ etna_resource_level_needs_flush(struct etna_resource_level *lvl) return false; if (unlikely(lvl->ts_meta)) - return ((int)(lvl->ts_meta->v0.seqno - lvl->ts_meta->v0.flush_seqno) > 0); + return !lvl->ts_meta->v0.flushed; else - return ((int)(lvl->seqno - lvl->flush_seqno) > 0); + return !lvl->ts_flushed; } static inline void etna_resource_level_mark_flushed(struct etna_resource_level *lvl) { if (unlikely(lvl->ts_meta)) - lvl->ts_meta->v0.flush_seqno = lvl->ts_meta->v0.seqno; + lvl->ts_meta->v0.flushed = 1; else - lvl->flush_seqno = lvl->seqno; + lvl->ts_flushed = true; +} + +static inline void +etna_resource_level_mark_unflushed(struct etna_resource_level *lvl) +{ + if (unlikely(lvl->ts_meta)) + lvl->ts_meta->v0.flushed = 0; + else + lvl->ts_flushed = false; } static inline void diff --git a/src/gallium/drivers/etnaviv/etnaviv_rs.c b/src/gallium/drivers/etnaviv/etnaviv_rs.c index 26b02566dff..06c1a4887bf 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_rs.c +++ b/src/gallium/drivers/etnaviv/etnaviv_rs.c @@ -362,6 +362,7 @@ etna_blit_clear_color_rs(struct pipe_context *pctx, unsigned idx, etna_submit_rs_state(ctx, &surf->ts_clear_command); etna_resource_level_ts_mark_valid(surf->level); + 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 @@ -424,6 +425,7 @@ etna_blit_clear_zs_rs(struct pipe_context *pctx, struct pipe_surface *dst, etna_submit_rs_state(ctx, &surf->ts_clear_command); etna_resource_level_ts_mark_valid(surf->level); + etna_resource_level_mark_unflushed(surf->level); ctx->dirty |= ETNA_DIRTY_TS; } else { /* Queue normal RS clear for non-TS surfaces */ /* If the level has valid TS state we need to flush it, as the regular