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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user