From ba171ded1d8bb9beb3d2a2b59f545aa1227472a0 Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Mon, 7 Mar 2022 22:01:08 -0800 Subject: [PATCH] iris: Add pre-draw flushing for stream output targets When stream output is active, we need to let the cache tracker know about any SO buffers, which we access via IRIS_DOMAIN_OTHER_WRITE. In particular, we may have written to those buffers via another mechanism, such as BLORP buffer copies. In that case, previous writes happened via IRIS_DOMAIN_RENDER_WRITE, in which case we'd need to flush both the render cache and the tile cache to make that data globally- observable before we begin writing via streamout, which is incoherent with the earlier mechanism. Fixes misrendering in Ryujinx. Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/6085 Fixes: d8cb76211c5 ("iris: Fix MOCS for buffer copies") Reviewed-by: Francisco Jerez Part-of: (cherry picked from commit 9c8874b9ab3705f6474c1b02de0700ab356ffb18) --- .pick_status.json | 2 +- src/gallium/drivers/iris/iris_resolve.c | 11 +++++++++++ src/gallium/drivers/iris/iris_resource.c | 3 +++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/.pick_status.json b/.pick_status.json index 90dabe86f23..d42ad017eee 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -2276,7 +2276,7 @@ "description": "iris: Add pre-draw flushing for stream output targets", "nominated": true, "nomination_type": 1, - "resolution": 0, + "resolution": 1, "because_sha": "d8cb76211c5d264d705dbd3c02b5fc61637d5a56" }, { diff --git a/src/gallium/drivers/iris/iris_resolve.c b/src/gallium/drivers/iris/iris_resolve.c index 50fc9a94dfe..d1857157ec7 100644 --- a/src/gallium/drivers/iris/iris_resolve.c +++ b/src/gallium/drivers/iris/iris_resolve.c @@ -413,6 +413,17 @@ iris_predraw_flush_buffers(struct iris_context *ice, if (ice->state.stage_dirty & (IRIS_STAGE_DIRTY_BINDINGS_VS << stage)) flush_ssbos(batch, shs); + + if (ice->state.streamout_active && + (ice->state.dirty & IRIS_DIRTY_SO_BUFFERS)) { + for (int i = 0; i < 4; i++) { + struct iris_stream_output_target *tgt = (void *)ice->state.so_target[i]; + if (tgt) { + struct iris_bo *bo = iris_resource_bo(tgt->base.buffer); + iris_emit_buffer_barrier_for(batch, bo, IRIS_DOMAIN_OTHER_WRITE); + } + } + } } static void diff --git a/src/gallium/drivers/iris/iris_resource.c b/src/gallium/drivers/iris/iris_resource.c index d963e6e42aa..4a420ba7b26 100644 --- a/src/gallium/drivers/iris/iris_resource.c +++ b/src/gallium/drivers/iris/iris_resource.c @@ -2547,6 +2547,9 @@ iris_dirty_for_history(struct iris_context *ice, if (res->bind_history & PIPE_BIND_VERTEX_BUFFER) dirty |= IRIS_DIRTY_VERTEX_BUFFER_FLUSHES; + if (ice->state.streamout_active && (res->bind_history & PIPE_BIND_STREAM_OUTPUT)) + dirty |= IRIS_DIRTY_SO_BUFFERS; + ice->state.dirty |= dirty; ice->state.stage_dirty |= stage_dirty; }