From 2e6fd24b7c50e68d679319f19d7a70a218fe2a5c 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: (cherry picked from commit 0fb813526e3b3be6cf8a866b084db044ccd0e103) --- .pick_status.json | 2 +- src/gallium/drivers/etnaviv/etnaviv_clear_blit.c | 1 + src/gallium/drivers/etnaviv/etnaviv_transfer.c | 10 +++++++++- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/.pick_status.json b/.pick_status.json index 771cee562d9..977143adc56 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -2335,7 +2335,7 @@ "description": "etnaviv: fix tile status interaction with write mappings", "nominated": true, "nomination_type": 0, - "resolution": 0, + "resolution": 1, "main_sha": null, "because_sha": null }, diff --git a/src/gallium/drivers/etnaviv/etnaviv_clear_blit.c b/src/gallium/drivers/etnaviv/etnaviv_clear_blit.c index 113f9cf53b7..03aa2f842fb 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 d85196a3811..03116bb52c6 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) {