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 <l.stach@pengutronix.de>
Reviewed-by: Christian Gmeiner <cgmeiner@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32956>
This commit is contained in:
Lucas Stach
2024-10-28 20:42:46 +01:00
committed by Marge Bot
parent d74f569035
commit 4bed508122
4 changed files with 24 additions and 9 deletions
@@ -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;
}
@@ -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
+17 -8
View File
@@ -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
+2
View File
@@ -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