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@chromium.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7342>
This commit is contained in:
Rob Clark
2020-10-28 09:51:15 -07:00
committed by Marge Bot
parent 20a813b0eb
commit 290f827928
6 changed files with 44 additions and 18 deletions
@@ -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 *
@@ -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);
@@ -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
@@ -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);
}
@@ -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
@@ -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: */