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