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@redhat.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/11437>
This commit is contained in:
committed by
Marge Bot
parent
618784732a
commit
982a2dfbd4
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user