Mesa (main): zink: improve tc fence disambiguation
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Tue Jun 22 21:08:01 UTC 2021
Module: Mesa
Branch: main
Commit: 982a2dfbd4a45cfed50e4f7f77702eb27b4f866f
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=982a2dfbd4a45cfed50e4f7f77702eb27b4f866f
Author: Mike Blumenkrantz <michael.blumenkrantz at gmail.com>
Date: Fri May 7 08:39:27 2021 -0400
zink: improve tc fence disambiguation
instead of storing separate batch_id values onto the tc fence for matching:
* use a fence pointer on the main context to indicate the current deferred fence
* add a monotonic counter to each batch state which double-increments on each use,
thereby enabling direct determination by the tc fence as to whether this is the same
batch state it was created with
Acked-by: Dave Airlie <airlied at redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/11437>
---
src/gallium/drivers/zink/zink_batch.c | 2 ++
src/gallium/drivers/zink/zink_batch.h | 3 +++
src/gallium/drivers/zink/zink_context.c | 11 ++++++++---
src/gallium/drivers/zink/zink_context.h | 1 +
src/gallium/drivers/zink/zink_fence.c | 26 +++++++++++++++-----------
src/gallium/drivers/zink/zink_fence.h | 5 ++---
6 files changed, 31 insertions(+), 17 deletions(-)
diff --git a/src/gallium/drivers/zink/zink_batch.c b/src/gallium/drivers/zink/zink_batch.c
index b890c4df7c3..deb17fc868c 100644
--- a/src/gallium/drivers/zink/zink_batch.c
+++ b/src/gallium/drivers/zink/zink_batch.c
@@ -93,6 +93,7 @@ zink_reset_batch_state(struct zink_context *ctx, struct zink_batch_state *bs)
bs->has_barriers = false;
if (bs->fence.batch_id)
zink_screen_update_last_finished(screen, bs->fence.batch_id);
+ bs->submit_count++;
bs->fence.batch_id = 0;
bs->draw_count = bs->compute_count = 0;
}
@@ -353,6 +354,7 @@ submit_queue(void *data, void *gdata, int thread_index)
debug_printf("ZINK: vkQueueSubmit() failed\n");
bs->is_device_lost = true;
}
+ bs->submit_count++;
p_atomic_set(&bs->fence.submitted, true);
}
diff --git a/src/gallium/drivers/zink/zink_batch.h b/src/gallium/drivers/zink/zink_batch.h
index 9b4057e3199..ebba92c0f3b 100644
--- a/src/gallium/drivers/zink/zink_batch.h
+++ b/src/gallium/drivers/zink/zink_batch.h
@@ -86,6 +86,9 @@ struct zink_batch_state {
VkDeviceSize resource_size;
+ /* this is a monotonic int used to disambiguate internal fences from their tc fence references */
+ unsigned submit_count;
+
bool is_device_lost;
bool have_timelines;
bool has_barriers;
diff --git a/src/gallium/drivers/zink/zink_context.c b/src/gallium/drivers/zink/zink_context.c
index 087df64418b..377cfd0cc14 100644
--- a/src/gallium/drivers/zink/zink_context.c
+++ b/src/gallium/drivers/zink/zink_context.c
@@ -1796,6 +1796,7 @@ flush_batch(struct zink_context *ctx, bool sync)
zink_begin_render_pass(ctx, batch);
zink_end_render_pass(ctx, batch);
zink_end_batch(ctx, batch);
+ ctx->deferred_fence = NULL;
if (sync)
sync_flush(ctx, ctx->batch.state);
@@ -2388,6 +2389,7 @@ zink_flush(struct pipe_context *pctx,
struct zink_batch *batch = &ctx->batch;
struct zink_fence *fence = NULL;
struct zink_screen *screen = zink_screen(ctx->base.screen);
+ unsigned submit_count = 0;
/* triggering clears will force has_work */
if (!deferred && ctx->clears_enabled)
@@ -2410,6 +2412,7 @@ zink_flush(struct pipe_context *pctx,
tc_driver_internal_flush_notify(ctx->tc);
} else {
fence = &batch->state->fence;
+ submit_count = batch->state->submit_count;
if (deferred && !(flags & PIPE_FLUSH_FENCE_FD) && pfence)
deferred_fence = true;
else
@@ -2429,15 +2432,17 @@ zink_flush(struct pipe_context *pctx,
*pfence = (struct pipe_fence_handle *)mfence;
}
- zink_batch_state_reference(screen, NULL, zink_batch_state(fence));
+ struct zink_batch_state *bs = zink_batch_state(fence);
+ zink_batch_state_reference(screen, NULL, bs);
mfence->fence = fence;
if (fence)
- mfence->batch_id = fence->batch_id;
+ mfence->submit_count = submit_count;
if (deferred_fence) {
assert(fence);
mfence->deferred_ctx = pctx;
- mfence->deferred_id = fence->batch_id;
+ assert(!ctx->deferred_fence || ctx->deferred_fence == fence);
+ ctx->deferred_fence = fence;
}
if (!fence || flags & TC_FLUSH_ASYNC) {
diff --git a/src/gallium/drivers/zink/zink_context.h b/src/gallium/drivers/zink/zink_context.h
index 57a72e0b6c4..fb5e08faac8 100644
--- a/src/gallium/drivers/zink/zink_context.h
+++ b/src/gallium/drivers/zink/zink_context.h
@@ -147,6 +147,7 @@ struct zink_context {
uint32_t curr_batch; //the current batch id
struct zink_batch batch;
simple_mtx_t batch_mtx;
+ struct zink_fence *deferred_fence;
struct zink_fence *last_fence; //the last command buffer submitted
struct hash_table batch_states; //submitted batch states
struct util_dynarray free_batch_states; //unused batch states
diff --git a/src/gallium/drivers/zink/zink_fence.c b/src/gallium/drivers/zink/zink_fence.c
index aeddfae8e31..338ffcdf217 100644
--- a/src/gallium/drivers/zink/zink_fence.c
+++ b/src/gallium/drivers/zink/zink_fence.c
@@ -175,30 +175,34 @@ zink_fence_finish(struct zink_screen *screen, struct pipe_context *pctx, struct
return true;
if (pctx && mfence->deferred_ctx == pctx) {
- if (mfence->deferred_id == ctx->curr_batch) {
+ if (mfence->fence == ctx->deferred_fence) {
zink_context(pctx)->batch.has_work = true;
/* this must be the current batch */
pctx->flush(pctx, NULL, !timeout_ns ? PIPE_FLUSH_ASYNC : 0);
if (!timeout_ns)
return false;
}
- /* this batch is known to have finished */
- if (mfence->deferred_id <= screen->last_finished)
- return true;
}
/* need to ensure the tc mfence has been flushed before we wait */
bool tc_finish = tc_fence_finish(ctx, mfence, &timeout_ns);
- struct zink_fence *fence = mfence->fence;
- if (!tc_finish || (fence && !fence->submitted))
- return zink_screen_check_last_finished(screen, mfence->batch_id) ? true :
- (fence ? p_atomic_read(&fence->completed) : false);
-
+ /* the submit thread hasn't finished yet */
+ if (!tc_finish)
+ return false;
/* this was an invalid flush, just return completed */
if (!mfence->fence)
return true;
- /* if the zink fence has a different batch id then it must have completed and been recycled already */
- if (mfence->fence->batch_id != mfence->batch_id)
+
+ struct zink_fence *fence = mfence->fence;
+
+ unsigned submit_diff = zink_batch_state(mfence->fence)->submit_count - mfence->submit_count;
+ /* this batch is known to have finished because it has been submitted more than 1 time
+ * since the tc fence last saw it
+ */
+ if (submit_diff > 1)
+ return true;
+
+ if (fence->submitted && zink_screen_check_last_finished(screen, fence->batch_id))
return true;
return zink_vkfence_wait(screen, fence, timeout_ns);
diff --git a/src/gallium/drivers/zink/zink_fence.h b/src/gallium/drivers/zink/zink_fence.h
index 5c7fa4d4562..876788e141e 100644
--- a/src/gallium/drivers/zink/zink_fence.h
+++ b/src/gallium/drivers/zink/zink_fence.h
@@ -41,10 +41,9 @@ struct tc_unflushed_batch_token;
struct zink_tc_fence {
struct pipe_reference reference;
- uint32_t deferred_id;
- struct tc_unflushed_batch_token *tc_token;
+ uint32_t submit_count;
struct util_queue_fence ready;
- uint32_t batch_id;
+ struct tc_unflushed_batch_token *tc_token;
struct pipe_context *deferred_ctx;
struct zink_fence *fence;
};
More information about the mesa-commit
mailing list