Mesa (master): freedreno: handle batch flush in resource tracking

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Thu Jun 25 01:55:19 UTC 2020


Module: Mesa
Branch: master
Commit: 7c008c293d7b220eec0c98cefb794cab95ee344e
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=7c008c293d7b220eec0c98cefb794cab95ee344e

Author: Rob Clark <robdclark at chromium.org>
Date:   Wed Jun 24 11:28:32 2020 -0700

freedreno: handle batch flush in resource tracking

In rare cases, we can get into situations where the tracking of read/
written resources triggers a flush of the current batch.

To handle that, (1) take a reference to the current batch, so it doesn't
disappear under us, and (2) check after resource tracking whether the
current batch was flushed.  If it is, we have to re-do the resource
tracking, but since we have a fresh batch, it should not get flushed the
second time around.

Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/3160
Signed-off-by: Rob Clark <robdclark at chromium.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5634>

---

 src/gallium/drivers/freedreno/freedreno_draw.c | 34 +++++++++++++++++++++++---
 1 file changed, 30 insertions(+), 4 deletions(-)

diff --git a/src/gallium/drivers/freedreno/freedreno_draw.c b/src/gallium/drivers/freedreno/freedreno_draw.c
index da79a81d521..a5dae976607 100644
--- a/src/gallium/drivers/freedreno/freedreno_draw.c
+++ b/src/gallium/drivers/freedreno/freedreno_draw.c
@@ -213,8 +213,6 @@ static void
 fd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
 {
 	struct fd_context *ctx = fd_context(pctx);
-	struct fd_batch *batch = fd_context_batch(ctx);
-	struct pipe_framebuffer_state *pfb = &batch->framebuffer;
 
 	/* for debugging problems with indirect draw, it is convenient
 	 * to be able to emulate it, to determine if game is feeding us
@@ -260,6 +258,9 @@ fd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
 		}
 	}
 
+	struct fd_batch *batch = NULL;
+	fd_batch_reference(&batch, fd_context_batch(ctx));
+
 	if (ctx->in_discard_blit) {
 		fd_batch_reset(batch);
 		fd_context_all_dirty(ctx);
@@ -267,6 +268,16 @@ fd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
 
 	batch_draw_tracking(batch, info);
 
+	if (unlikely(ctx->batch != batch)) {
+		/* The current batch was flushed in batch_draw_tracking()
+		 * so start anew.  We know this won't happen a second time
+		 * since we are dealing with a fresh batch:
+		 */
+		fd_batch_reference(&batch, fd_context_batch(ctx));
+		batch_draw_tracking(batch, info);
+		assert(ctx->batch == batch);
+	}
+
 	batch->blit = ctx->in_discard_blit;
 	batch->back_blit = ctx->in_shadow;
 	batch->num_draws++;
@@ -299,6 +310,7 @@ fd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
 	 */
 	fd_fence_ref(&ctx->last_fence, NULL);
 
+	struct pipe_framebuffer_state *pfb = &batch->framebuffer;
 	DBG("%p: %ux%u num_draws=%u (%s/%s)", batch,
 		pfb->width, pfb->height, batch->num_draws,
 		util_format_short_name(pipe_surface_format(pfb->cbufs[0])),
@@ -316,6 +328,7 @@ fd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
 		fd_context_all_dirty(ctx);
 
 	fd_batch_check_size(batch);
+	fd_batch_reference(&batch, NULL);
 
 	if (info == &new_info)
 		pipe_resource_reference(&indexbuf, NULL);
@@ -377,13 +390,14 @@ fd_clear(struct pipe_context *pctx, unsigned buffers,
 		unsigned stencil)
 {
 	struct fd_context *ctx = fd_context(pctx);
-	struct fd_batch *batch = fd_context_batch(ctx);
-	struct pipe_framebuffer_state *pfb = &batch->framebuffer;
 
 	/* TODO: push down the region versions into the tiles */
 	if (!fd_render_condition_check(pctx))
 		return;
 
+	struct fd_batch *batch = NULL;
+	fd_batch_reference(&batch, fd_context_batch(ctx));
+
 	if (ctx->in_discard_blit) {
 		fd_batch_reset(batch);
 		fd_context_all_dirty(ctx);
@@ -391,12 +405,23 @@ fd_clear(struct pipe_context *pctx, unsigned buffers,
 
 	batch_clear_tracking(batch, buffers);
 
+	if (unlikely(ctx->batch != batch)) {
+		/* The current batch was flushed in batch_clear_tracking()
+		 * so start anew.  We know this won't happen a second time
+		 * since we are dealing with a fresh batch:
+		 */
+		fd_batch_reference(&batch, fd_context_batch(ctx));
+		batch_clear_tracking(batch, buffers);
+		assert(ctx->batch == batch);
+	}
+
 	/* Clearing last_fence must come after the batch dependency tracking
 	 * (resource_read()/resource_written()), as that can trigger a flush,
 	 * re-populating last_fence
 	 */
 	fd_fence_ref(&ctx->last_fence, NULL);
 
+	struct pipe_framebuffer_state *pfb = &batch->framebuffer;
 	DBG("%p: %x %ux%u depth=%f, stencil=%u (%s/%s)", batch, buffers,
 		pfb->width, pfb->height, depth, stencil,
 		util_format_short_name(pipe_surface_format(pfb->cbufs[0])),
@@ -423,6 +448,7 @@ fd_clear(struct pipe_context *pctx, unsigned buffers,
 	}
 
 	fd_batch_check_size(batch);
+	fd_batch_reference(&batch, NULL);
 }
 
 static void



More information about the mesa-commit mailing list