From 0fb813526e3b3be6cf8a866b084db044ccd0e103 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Fri, 18 Nov 2022 12:24:58 +0100 Subject: [PATCH] etnaviv: fix tile status interaction with write mappings This fixes a longstanding bug in the interaction between TS and a write mapping. The write does not update TS regardless of the way the update is done. Update via etna_copy_resource would just set the target ts_valid to false without actually writing back any dirty TS to the resource. Writes via the CPU would update the resource, but keep ts_valid at true even if the tile status may now not match the actually written tiles of the resource anymore. Fix this by writing back a dirty TS to the target resource if needed before updating the level with the write data. Always invalidate TS, even when the update is done by the CPU. Cc: mesa-stable Signed-off-by: Lucas Stach Reviewed-by: Christian Gmeiner Part-of: --- src/gallium/drivers/etnaviv/etnaviv_clear_blit.c | 1 + src/gallium/drivers/etnaviv/etnaviv_transfer.c | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/gallium/drivers/etnaviv/etnaviv_clear_blit.c b/src/gallium/drivers/etnaviv/etnaviv_clear_blit.c index bef5a9d4367..7a6591ea463 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_clear_blit.c +++ b/src/gallium/drivers/etnaviv/etnaviv_clear_blit.c @@ -230,6 +230,7 @@ etna_copy_resource_box(struct pipe_context *pctx, struct pipe_resource *dst, { assert(src->format == dst->format); assert(src->array_size == dst->array_size); + assert(!etna_resource_needs_flush(etna_resource(dst))); struct pipe_blit_info blit = {}; blit.mask = util_format_get_mask(dst->format); diff --git a/src/gallium/drivers/etnaviv/etnaviv_transfer.c b/src/gallium/drivers/etnaviv/etnaviv_transfer.c index 82d23ac6392..e24d22892ff 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_transfer.c +++ b/src/gallium/drivers/etnaviv/etnaviv_transfer.c @@ -124,10 +124,17 @@ etna_transfer_unmap(struct pipe_context *pctx, struct pipe_transfer *ptrans) etna_bo_cpu_fini(etna_resource(trans->rsc)->bo); if (ptrans->usage & PIPE_MAP_WRITE) { + if (etna_resource_needs_flush(rsc)) { + if (ptrans->usage & PIPE_MAP_DISCARD_WHOLE_RESOURCE) + rsc->flush_seqno = rsc->seqno; + else + etna_copy_resource(pctx, &rsc->base, &rsc->base, 0, rsc->base.last_level); + } + if (trans->rsc) { /* We have a temporary resource due to either tile status or * tiling format. Write back the updated buffer contents. - * FIXME: we need to invalidate the tile status. */ + */ etna_copy_resource_box(pctx, ptrans->resource, trans->rsc, ptrans->level, &ptrans->box); } else if (trans->staging) { /* map buffer object */ @@ -156,6 +163,7 @@ etna_transfer_unmap(struct pipe_context *pctx, struct pipe_transfer *ptrans) FREE(trans->staging); } + rsc->levels[ptrans->level].ts_valid = false; rsc->seqno++; if (rsc->base.bind & PIPE_BIND_SAMPLER_VIEW) {