etnaviv: fix tile status interaction with write mappings
authorLucas Stach <l.stach@pengutronix.de>
Fri, 18 Nov 2022 11:24:58 +0000 (12:24 +0100)
committerMarge Bot <emma+marge@anholt.net>
Tue, 22 Nov 2022 10:01:56 +0000 (10:01 +0000)
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 <l.stach@pengutronix.de>
Reviewed-by: Christian Gmeiner <christian.gmeiner@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/19846>

src/gallium/drivers/etnaviv/etnaviv_clear_blit.c
src/gallium/drivers/etnaviv/etnaviv_transfer.c

index bef5a9d..7a6591e 100644 (file)
@@ -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);
index 82d23ac..e24d228 100644 (file)
@@ -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) {