Mesa (master): freedreno: Make fd_context_batch() return a reference

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Tue Nov 10 18:27:28 UTC 2020


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

Author: Rob Clark <robdclark at chromium.org>
Date:   Wed Oct 28 09:51:15 2020 -0700

freedreno: Make fd_context_batch() return a reference

This protects better against another context triggering a batch flush
and unref while the first context is doing resource tracking.

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

---

 src/gallium/drivers/freedreno/a4xx/fd4_query.c     |  1 +
 .../drivers/freedreno/freedreno_batch_cache.c      |  2 ++
 src/gallium/drivers/freedreno/freedreno_context.c  | 36 ++++++++++++++++------
 src/gallium/drivers/freedreno/freedreno_draw.c     | 12 ++++----
 .../drivers/freedreno/freedreno_query_acc.c        |  7 +++--
 src/gallium/drivers/freedreno/freedreno_query_hw.c |  4 +++
 6 files changed, 44 insertions(+), 18 deletions(-)

diff --git a/src/gallium/drivers/freedreno/a4xx/fd4_query.c b/src/gallium/drivers/freedreno/a4xx/fd4_query.c
index 465e4b3c03c..73a5af1268c 100644
--- a/src/gallium/drivers/freedreno/a4xx/fd4_query.c
+++ b/src/gallium/drivers/freedreno/a4xx/fd4_query.c
@@ -119,6 +119,7 @@ time_elapsed_enable(struct fd_context *ctx, struct fd_ringbuffer *ring)
 	fd_wfi(batch, ring);
 	OUT_PKT0(ring, REG_A4XX_CP_PERFCTR_CP_SEL_0, 1);
 	OUT_RING(ring, CP_ALWAYS_COUNT);
+	fd_batch_reference(&batch, NULL);
 }
 
 static struct fd_hw_sample *
diff --git a/src/gallium/drivers/freedreno/freedreno_batch_cache.c b/src/gallium/drivers/freedreno/freedreno_batch_cache.c
index 0d0064c6ce7..4f918932e27 100644
--- a/src/gallium/drivers/freedreno/freedreno_batch_cache.c
+++ b/src/gallium/drivers/freedreno/freedreno_batch_cache.c
@@ -159,6 +159,8 @@ bc_flush(struct fd_batch_cache *cache, struct fd_context *ctx, bool deferred)
 			}
 		}
 
+		fd_batch_reference_locked(&current_batch, NULL);
+
 		fd_screen_unlock(ctx->screen);
 	} else {
 		fd_screen_unlock(ctx->screen);
diff --git a/src/gallium/drivers/freedreno/freedreno_context.c b/src/gallium/drivers/freedreno/freedreno_context.c
index 0d3c5e6c15e..9393965e22a 100644
--- a/src/gallium/drivers/freedreno/freedreno_context.c
+++ b/src/gallium/drivers/freedreno/freedreno_context.c
@@ -51,10 +51,14 @@ fd_context_flush(struct pipe_context *pctx, struct pipe_fence_handle **fencep,
 {
 	struct fd_context *ctx = fd_context(pctx);
 	struct pipe_fence_handle *fence = NULL;
-	// TODO we want to lookup batch if it exists, but not create one if not.
-	struct fd_batch *batch = fd_context_batch(ctx);
+	struct fd_batch *batch = NULL;
 
-	DBG("%p: flush: flags=%x", ctx->batch, flags);
+	/* We want to lookup current batch if it exists, but not create a new
+	 * one if not (unless we need a fence)
+	 */
+	fd_batch_reference(&batch, ctx->batch);
+
+	DBG("%p: flush: flags=%x", batch, flags);
 
 	/* In some sequence of events, we can end up with a last_fence that is
 	 * not an "fd" fence, which results in eglDupNativeFenceFDANDROID()
@@ -73,7 +77,9 @@ fd_context_flush(struct pipe_context *pctx, struct pipe_fence_handle **fencep,
 		goto out;
 	}
 
-	if (!batch) {
+	if (fencep && !batch) {
+		batch = fd_context_batch(ctx);
+	} else if (!batch) {
 		fd_bc_dump(ctx->screen, "%p: NULL batch, remaining:\n", ctx);
 		return;
 	}
@@ -105,6 +111,8 @@ out:
 
 	fd_fence_ref(&fence, NULL);
 
+	fd_batch_reference(&batch, NULL);
+
 	if (flags & PIPE_FLUSH_END_OF_FRAME)
 		fd_log_eof(ctx);
 }
@@ -232,18 +240,26 @@ fd_context_switch_to(struct fd_context *ctx, struct fd_batch *batch)
 	}
 }
 
+/**
+ * Return a reference to the current batch, caller must unref.
+ */
 struct fd_batch *
 fd_context_batch(struct fd_context *ctx)
 {
-	if (unlikely(!ctx->batch)) {
-		struct fd_batch *batch =
-			fd_batch_from_fb(&ctx->screen->batch_cache, ctx, &ctx->framebuffer);
+	struct fd_batch *batch = NULL;
+
+	fd_batch_reference(&batch, ctx->batch);
+
+	if (unlikely(!batch)) {
+		batch = fd_batch_from_fb(&ctx->screen->batch_cache, ctx, &ctx->framebuffer);
 		util_copy_framebuffer_state(&batch->framebuffer, &ctx->framebuffer);
-		ctx->batch = batch;
+		fd_batch_reference(&ctx->batch, batch);
 		fd_context_all_dirty(ctx);
 	}
-	fd_context_switch_to(ctx, ctx->batch);
-	return ctx->batch;
+
+	fd_context_switch_to(ctx, batch);
+
+	return batch;
 }
 
 void
diff --git a/src/gallium/drivers/freedreno/freedreno_draw.c b/src/gallium/drivers/freedreno/freedreno_draw.c
index 6e492e7461f..5db8391b55f 100644
--- a/src/gallium/drivers/freedreno/freedreno_draw.c
+++ b/src/gallium/drivers/freedreno/freedreno_draw.c
@@ -259,8 +259,7 @@ 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));
+	struct fd_batch *batch = fd_context_batch(ctx);
 
 	if (ctx->in_discard_blit) {
 		fd_batch_reset(batch);
@@ -274,7 +273,8 @@ fd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
 		 * 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));
+		fd_batch_reference(&batch, NULL);
+		batch = fd_context_batch(ctx);
 		batch_draw_tracking(batch, info);
 		assert(ctx->batch == batch);
 	}
@@ -397,8 +397,7 @@ fd_clear(struct pipe_context *pctx, unsigned buffers,
 	if (!fd_render_condition_check(pctx))
 		return;
 
-	struct fd_batch *batch = NULL;
-	fd_batch_reference(&batch, fd_context_batch(ctx));
+	struct fd_batch *batch = fd_context_batch(ctx);
 
 	if (ctx->in_discard_blit) {
 		fd_batch_reset(batch);
@@ -412,7 +411,8 @@ fd_clear(struct pipe_context *pctx, unsigned buffers,
 		 * 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));
+		fd_batch_reference(&batch, NULL);
+		batch = fd_context_batch(ctx);
 		batch_clear_tracking(batch, buffers);
 		assert(ctx->batch == batch);
 	}
diff --git a/src/gallium/drivers/freedreno/freedreno_query_acc.c b/src/gallium/drivers/freedreno/freedreno_query_acc.c
index 888f7763d85..f02e22c4f43 100644
--- a/src/gallium/drivers/freedreno/freedreno_query_acc.c
+++ b/src/gallium/drivers/freedreno/freedreno_query_acc.c
@@ -112,8 +112,11 @@ fd_acc_begin_query(struct fd_context *ctx, struct fd_query *q)
 	/* TIMESTAMP/GPU_FINISHED and don't do normal bracketing at draw time, we
 	 * need to just emit the capture at this moment.
 	 */
-	if (skip_begin_query(q->type))
-		fd_acc_query_resume(aq, fd_context_batch(ctx));
+	if (skip_begin_query(q->type)) {
+		struct fd_batch *batch = fd_context_batch(ctx);
+		fd_acc_query_resume(aq, batch);
+		fd_batch_reference(&batch, NULL);
+	}
 }
 
 static void
diff --git a/src/gallium/drivers/freedreno/freedreno_query_hw.c b/src/gallium/drivers/freedreno/freedreno_query_hw.c
index 5be59613ff5..28d270adb2d 100644
--- a/src/gallium/drivers/freedreno/freedreno_query_hw.c
+++ b/src/gallium/drivers/freedreno/freedreno_query_hw.c
@@ -149,6 +149,8 @@ fd_hw_begin_query(struct fd_context *ctx, struct fd_query *q)
 	/* add to active list: */
 	assert(list_is_empty(&hq->list));
 	list_addtail(&hq->list, &ctx->hw_active_queries);
+
+	fd_batch_reference(&batch, NULL);
 }
 
 static void
@@ -164,6 +166,8 @@ fd_hw_end_query(struct fd_context *ctx, struct fd_query *q)
 
 	/* remove from active list: */
 	list_delinit(&hq->list);
+
+	fd_batch_reference(&batch, NULL);
 }
 
 /* helper to get ptr to specified sample: */



More information about the mesa-commit mailing list