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:
Mike Blumenkrantz
2021-05-07 08:39:27 -04:00
committed by Marge Bot
parent 618784732a
commit 982a2dfbd4
6 changed files with 31 additions and 17 deletions
+2
View File
@@ -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);
}
+3
View File
@@ -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;
+8 -3
View File
@@ -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) {
+1
View File
@@ -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
+15 -11
View File
@@ -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);
+2 -3
View File
@@ -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;
};