zink: track last completed batch id to optimize checking states
authorMike Blumenkrantz <michael.blumenkrantz@gmail.com>
Tue, 29 Dec 2020 17:10:08 +0000 (12:10 -0500)
committerMarge Bot <eric+marge@anholt.net>
Thu, 1 Apr 2021 13:25:51 +0000 (13:25 +0000)
Acked-by: Erik Faye-Lund <erik.faye-lund@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/9963>

src/gallium/drivers/zink/zink_batch.c
src/gallium/drivers/zink/zink_context.c
src/gallium/drivers/zink/zink_fence.c
src/gallium/drivers/zink/zink_screen.h

index 9a399e1..6e01b91 100644 (file)
@@ -97,6 +97,7 @@ zink_reset_batch_state(struct zink_context *ctx, struct zink_batch_state *bs)
     * before the state is reused
     */
    bs->fence.submitted = false;
+   zink_screen_update_last_finished(screen, bs->fence.batch_id);
    bs->fence.batch_id = 0;
 }
 
index 4d40a05..ba78cf3 100644 (file)
@@ -2042,6 +2042,8 @@ zink_check_batch_completion(struct zink_context *ctx, uint32_t batch_id)
       /* not submitted yet */
       return false;
 
+   if (zink_screen_check_last_finished(zink_screen(ctx->base.screen), batch_id))
+      return true;
    struct zink_fence *fence;
 
    simple_mtx_lock(&ctx->batch_mtx);
index 4f5a097..515edf4 100644 (file)
@@ -156,6 +156,7 @@ zink_vkfence_wait(struct zink_screen *screen, struct zink_fence *fence, uint64_t
    if (success) {
       p_atomic_set(&fence->completed, true);
       zink_fence_clear_resources(screen, fence);
+      zink_screen_update_last_finished(screen, fence->batch_id);
    }
    return success;
 }
index d867740..d44415a 100644 (file)
@@ -53,6 +53,7 @@ struct zink_screen {
    struct pipe_screen base;
    bool threaded;
    uint32_t curr_batch; //the current batch id
+   uint32_t last_finished; //this is racy but ultimately doesn't matter
 
    struct sw_winsys *winsys;
 
@@ -148,6 +149,41 @@ struct zink_screen {
    } null_descriptor_hashes;
 };
 
+
+/* update last_finished to account for batch_id wrapping */
+static inline void
+zink_screen_update_last_finished(struct zink_screen *screen, uint32_t batch_id)
+{
+   /* last_finished may have wrapped */
+   if (screen->last_finished < UINT_MAX / 2) {
+      /* last_finished has wrapped, batch_id has not */
+      if (batch_id > UINT_MAX / 2)
+         return;
+   } else if (batch_id < UINT_MAX / 2) {
+      /* batch_id has wrapped, last_finished has not */
+      screen->last_finished = batch_id;
+      return;
+   }
+   /* neither have wrapped */
+   screen->last_finished = MAX2(batch_id, screen->last_finished);
+}
+
+/* check a batch_id against last_finished while accounting for wrapping */
+static inline bool
+zink_screen_check_last_finished(struct zink_screen *screen, uint32_t batch_id)
+{
+   /* last_finished may have wrapped */
+   if (screen->last_finished < UINT_MAX / 2) {
+      /* last_finished has wrapped, batch_id has not */
+      if (batch_id > UINT_MAX / 2)
+         return true;
+   } else if (batch_id < UINT_MAX / 2) {
+      /* batch_id has wrapped, last_finished has not */
+      return false;
+   }
+   return screen->last_finished >= batch_id;
+}
+
 static inline struct zink_screen *
 zink_screen(struct pipe_screen *pipe)
 {