From 9510af0f603f2c9843e6f8f1e882e99c925e3149 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Thu, 21 Sep 2023 14:27:44 -0700 Subject: [PATCH] freedreno/fence: Hold a strong ref to batch We don't want a unflushed fence to outlive it's batch, otherwise we run into trouble when it comes time to wait on the fence. For ex: 1. Create a fence before framebuffer state is set, with the PIPE_FLUSH_DEFERRED flags. This creates a new batch, to which the ctx holds the only reference (unless the fence also holds a ref) 2. set_framebuffer_state() creates a new batch and drops the ctx->batch reference. 3. Later something tries to wait on the fence Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/8621 Signed-off-by: Rob Clark Part-of: --- src/gallium/drivers/freedreno/freedreno_fence.c | 4 ++-- src/gallium/drivers/freedreno/freedreno_fence.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/gallium/drivers/freedreno/freedreno_fence.c b/src/gallium/drivers/freedreno/freedreno_fence.c index 7d748e460d6..e7677009f79 100644 --- a/src/gallium/drivers/freedreno/freedreno_fence.c +++ b/src/gallium/drivers/freedreno/freedreno_fence.c @@ -289,10 +289,10 @@ fd_pipe_fence_set_batch(struct pipe_fence_handle *fence, struct fd_batch *batch) { if (batch) { assert(!fence->batch); - fence->batch = batch; + fd_batch_reference(&fence->batch, batch); fd_batch_needs_flush(batch); } else { - fence->batch = NULL; + fd_batch_reference(&fence->batch, NULL); /* When the batch is dis-associated with the fence, we can signal TC * that the fence is flushed diff --git a/src/gallium/drivers/freedreno/freedreno_fence.h b/src/gallium/drivers/freedreno/freedreno_fence.h index 30d568ac82c..2bd4c581c7b 100644 --- a/src/gallium/drivers/freedreno/freedreno_fence.h +++ b/src/gallium/drivers/freedreno/freedreno_fence.h @@ -44,13 +44,13 @@ struct pipe_fence_handle { */ struct pipe_fence_handle *last_fence; - /* fence holds a weak reference to the batch until the batch is flushed, to + /* fence holds a reference to the batch until the batch is flushed, to * accommodate PIPE_FLUSH_DEFERRED. When the batch is actually flushed, it * is cleared (before the batch reference is dropped). If we need to wait * on a fence, and the batch is not NULL, we need to flush it. * * Note that with u_threaded_context async flushes, if a fence is requested - * by the frontend, the fence is initially created without a weak reference + * by the frontend, the fence is initially created without a reference * to the batch, which is filled in later when fd_context_flush() is called * from the driver thread. In this case tc_token will be non-null, in * which case threaded_context_flush() should be called in fd_fence_finish()