From f3d2fade82c168a7ffffa4bd7bf22585c45c711b Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Sat, 1 May 2021 11:32:10 -0700 Subject: [PATCH] freedreno: Fix TC last_fence optimization Grabbing the fence value in fd_fence_repopulate() without waiting on fd_submit_fence::ready doesn't work with async flushes, since we are waiting for the first flush to complete (ie. we don't have the kernel- side fence value yet). Just simplify it and make the "repopulated" fence delagate to the original fence. Fixes: e9a9ac6f77f ("freedreno/drm: Async submit support") Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/4726 Signed-off-by: Rob Clark Part-of: --- .../drivers/freedreno/freedreno_fence.c | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/src/gallium/drivers/freedreno/freedreno_fence.c b/src/gallium/drivers/freedreno/freedreno_fence.c index 5279efe155a..d85809317dd 100644 --- a/src/gallium/drivers/freedreno/freedreno_fence.c +++ b/src/gallium/drivers/freedreno/freedreno_fence.c @@ -59,14 +59,6 @@ fence_flush(struct pipe_context *pctx, struct pipe_fence_handle *fence, } } - /* If after the pre-created unflushed fence is flushed, we end up - * re-populated to a previous last_fence, then *that* is the one - * whose submit_fence.ready we want to wait on: - */ - if (fence->last_fence) { - return fence_flush(pctx, fence->last_fence, timeout); - } - util_queue_fence_wait(&fence->submit_fence.ready); /* We've already waited for batch to be flushed and fence->batch @@ -89,14 +81,15 @@ fence_flush(struct pipe_context *pctx, struct pipe_fence_handle *fence, void fd_fence_repopulate(struct pipe_fence_handle *fence, struct pipe_fence_handle *last_fence) { + if (last_fence->last_fence) + fd_fence_repopulate(fence, last_fence->last_fence); + /* The fence we are re-populating must not be an fd-fence (but last_fince * might have been) */ assert(!fence->submit_fence.use_fence_fd); assert(!last_fence->batch); - fence->submit_fence.fence = last_fence->submit_fence.fence; - fd_fence_ref(&fence->last_fence, last_fence); /* We have nothing to flush, so nothing will clear the batch reference @@ -140,9 +133,16 @@ bool fd_fence_finish(struct pipe_screen *pscreen, struct pipe_context *pctx, struct pipe_fence_handle *fence, uint64_t timeout) { + /* Note: for TC deferred fence, pctx->flush() may not have been called + * yet, so always do fence_flush() *first* before delegating to + * fence->last_fence + */ if (!fence_flush(pctx, fence, timeout)) return false; + if (fence->last_fence) + return fd_fence_finish(pscreen, pctx, fence->last_fence, timeout); + if (fence->last_fence) fence = fence->last_fence; @@ -220,6 +220,11 @@ fd_fence_server_sync(struct pipe_context *pctx, struct pipe_fence_handle *fence) */ fence_flush(pctx, fence, 0); + if (fence->last_fence) { + fd_fence_server_sync(pctx, fence->last_fence); + return; + } + /* if not an external fence, then nothing more to do without preemption: */ if (!fence->submit_fence.use_fence_fd) return; @@ -243,6 +248,9 @@ fd_fence_server_signal(struct pipe_context *pctx, int fd_fence_get_fd(struct pipe_screen *pscreen, struct pipe_fence_handle *fence) { + /* We don't expect deferred flush to be combined with fence-fd: */ + assert(!fence->last_fence); + assert(fence->submit_fence.use_fence_fd); /* NOTE: in the deferred fence case, the pctx we want is the threaded-ctx