Mesa (master): zink: make timeline semaphores per-screen

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri Apr 9 13:40:39 UTC 2021


Module: Mesa
Branch: master
Commit: fa36a16c68489c7a8a7223c39fb0078f7d745bcb
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=fa36a16c68489c7a8a7223c39fb0078f7d745bcb

Author: Mike Blumenkrantz <michael.blumenkrantz at gmail.com>
Date:   Thu Apr  8 10:52:55 2021 -0400

zink: make timeline semaphores per-screen

I misread the spec, and it turns out timeline ids can't be reused across
semaphores. This is obvious in retrospect, but what can be done?

Reviewed-by: Erik Faye-Lund <erik.faye-lund at collabora.com>
Tested-by: Erik Faye-Lund <erik.faye-lund at collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10115>

---

 src/gallium/drivers/zink/zink_batch.c   | 34 ++++++---------------------------
 src/gallium/drivers/zink/zink_batch.h   |  2 --
 src/gallium/drivers/zink/zink_context.c |  6 +-----
 src/gallium/drivers/zink/zink_screen.c  | 30 +++++++++++++++++++++++++++++
 src/gallium/drivers/zink/zink_screen.h  |  6 ++++++
 5 files changed, 43 insertions(+), 35 deletions(-)

diff --git a/src/gallium/drivers/zink/zink_batch.c b/src/gallium/drivers/zink/zink_batch.c
index 45cac57fa39..e0a8decda94 100644
--- a/src/gallium/drivers/zink/zink_batch.c
+++ b/src/gallium/drivers/zink/zink_batch.c
@@ -154,8 +154,6 @@ create_batch_state(struct zink_context *ctx)
    struct zink_screen *screen = zink_screen(ctx->base.screen);
    struct zink_batch_state *bs = rzalloc(NULL, struct zink_batch_state);
    bs->have_timelines = ctx->have_timelines;
-   if (ctx->have_timelines)
-      bs->sem = ctx->batch.sem;
    VkCommandPoolCreateInfo cpci = {};
    cpci.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
    cpci.queueFamilyIndex = screen->gfx_queue;
@@ -252,20 +250,6 @@ get_batch_state(struct zink_context *ctx, struct zink_batch *batch)
    return bs;
 }
 
-static void
-init_semaphore(struct zink_context *ctx, struct zink_batch *batch)
-{
-   struct zink_screen *screen = zink_screen(ctx->base.screen);
-   VkSemaphoreCreateInfo sci = {};
-   VkSemaphoreTypeCreateInfo tci = {};
-   sci.pNext = &tci;
-   sci.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
-   tci.sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO;
-   tci.semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE;
-   if (vkCreateSemaphore(screen->dev, &sci, NULL, &batch->sem) != VK_SUCCESS)
-      ctx->have_timelines = false;
-}
-
 void
 zink_reset_batch(struct zink_context *ctx, struct zink_batch *batch)
 {
@@ -273,18 +257,12 @@ zink_reset_batch(struct zink_context *ctx, struct zink_batch *batch)
    bool fresh = !batch->state;
 
    if (ctx->have_timelines) {
-      bool do_reset = false;
-      if (screen->last_finished > ctx->curr_batch && ctx->curr_batch == 1) {
-         do_reset = true;
-         /* semaphore signal values can never decrease,
-          * so we need a new semaphore anytime we overflow
-          */
-         if (ctx->batch.prev_sem)
-            vkDestroySemaphore(screen->dev, ctx->batch.prev_sem, NULL);
-         ctx->batch.prev_sem = ctx->batch.sem;
+      if (fresh || (screen->last_finished > ctx->curr_batch && ctx->curr_batch == 1)) {
+         if (!zink_screen_init_semaphore(screen)) {
+            debug_printf("timeline init failed, things are about to go dramatically wrong.");
+            ctx->have_timelines = false;
+         }
       }
-      if (fresh || do_reset)
-         init_semaphore(ctx, batch);
    }
 
    batch->state = get_batch_state(ctx, batch);
@@ -351,7 +329,7 @@ submit_queue(void *data, int thread_index)
       tsi.signalSemaphoreValueCount = 1;
       tsi.pSignalSemaphoreValues = &batch_id;
       si.signalSemaphoreCount = 1;
-      si.pSignalSemaphores = &bs->sem;
+      si.pSignalSemaphores = &zink_screen(bs->ctx->base.screen)->sem;
    }
 
    struct wsi_memory_signal_submit_info mem_signal = {
diff --git a/src/gallium/drivers/zink/zink_batch.h b/src/gallium/drivers/zink/zink_batch.h
index d0d49676673..6c1c2fd2bee 100644
--- a/src/gallium/drivers/zink/zink_batch.h
+++ b/src/gallium/drivers/zink/zink_batch.h
@@ -89,8 +89,6 @@ struct zink_batch {
    uint32_t last_batch_id;
    VkQueue queue; //gfx+compute
    VkQueue thread_queue; //gfx+compute
-   VkSemaphore sem;
-   VkSemaphore prev_sem;
    struct util_queue flush_queue; //TODO: move to wsi
 
    bool has_work;
diff --git a/src/gallium/drivers/zink/zink_context.c b/src/gallium/drivers/zink/zink_context.c
index 8f27200076c..68c997debeb 100644
--- a/src/gallium/drivers/zink/zink_context.c
+++ b/src/gallium/drivers/zink/zink_context.c
@@ -301,10 +301,6 @@ zink_context_destroy(struct pipe_context *pctx)
 
    pipe_resource_reference(&ctx->dummy_vertex_buffer, NULL);
    pipe_resource_reference(&ctx->dummy_xfb_buffer, NULL);
-   if (ctx->batch.sem)
-      vkDestroySemaphore(screen->dev, ctx->batch.sem, NULL);
-   if (ctx->batch.prev_sem)
-      vkDestroySemaphore(screen->dev, ctx->batch.prev_sem, NULL);
 
    if (ctx->tc)
       util_queue_destroy(&ctx->batch.flush_queue);
@@ -2028,7 +2024,7 @@ timeline_wait(struct zink_context *ctx, uint32_t batch_id, uint64_t timeout)
    wi.sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO;
    wi.semaphoreCount = 1;
    /* handle batch_id overflow */
-   wi.pSemaphores = batch_id > ctx->curr_batch ? &ctx->batch.prev_sem : &ctx->batch.sem;
+   wi.pSemaphores = batch_id > ctx->curr_batch ? &screen->prev_sem : &screen->sem;
    uint64_t batch_id64 = batch_id;
    wi.pValues = &batch_id64;
    bool success = false;
diff --git a/src/gallium/drivers/zink/zink_screen.c b/src/gallium/drivers/zink/zink_screen.c
index db639d56af5..d0d55f5d396 100644
--- a/src/gallium/drivers/zink/zink_screen.c
+++ b/src/gallium/drivers/zink/zink_screen.c
@@ -956,6 +956,12 @@ zink_destroy_screen(struct pipe_screen *pscreen)
    simple_mtx_destroy(&screen->mem_cache_mtx);
    vkDestroyPipelineCache(screen->dev, screen->pipeline_cache, NULL);
 
+   if (screen->sem)
+      vkDestroySemaphore(screen->dev, screen->sem, NULL);
+   if (screen->prev_sem)
+      vkDestroySemaphore(screen->dev, screen->prev_sem, NULL);
+
+
    vkDestroyDevice(screen->dev, NULL);
    vkDestroyInstance(screen->instance, NULL);
 
@@ -1325,6 +1331,30 @@ populate_format_props(struct zink_screen *screen)
    }
 }
 
+bool
+zink_screen_init_semaphore(struct zink_screen *screen)
+{
+   VkSemaphoreCreateInfo sci = {};
+   VkSemaphoreTypeCreateInfo tci = {};
+   VkSemaphore sem;
+   sci.pNext = &tci;
+   sci.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
+   tci.sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO;
+   tci.semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE;
+
+   if (vkCreateSemaphore(screen->dev, &sci, NULL, &sem) == VK_SUCCESS) {
+      /* semaphore signal values can never decrease,
+       * so we need a new semaphore anytime we overflow
+       */
+      if (screen->prev_sem)
+         vkDestroySemaphore(screen->dev, screen->prev_sem, NULL);
+      screen->sem = sem;
+      return true;
+   }
+   screen->info.have_KHR_timeline_semaphore = false;
+   return false;
+}
+
 static uint32_t
 zink_get_loader_version(void)
 {
diff --git a/src/gallium/drivers/zink/zink_screen.h b/src/gallium/drivers/zink/zink_screen.h
index 2e667a9d312..4a2e88d968c 100644
--- a/src/gallium/drivers/zink/zink_screen.h
+++ b/src/gallium/drivers/zink/zink_screen.h
@@ -54,6 +54,8 @@ struct zink_screen {
    bool threaded;
    uint32_t curr_batch; //the current batch id
    uint32_t last_finished; //this is racy but ultimately doesn't matter
+   VkSemaphore sem;
+   VkSemaphore prev_sem;
 
    bool device_lost;
    struct sw_winsys *winsys;
@@ -191,6 +193,10 @@ zink_screen_check_last_finished(struct zink_screen *screen, uint32_t batch_id)
    return screen->last_finished >= batch_id;
 }
 
+bool
+zink_screen_init_semaphore(struct zink_screen *screen);
+
+
 static inline struct zink_screen *
 zink_screen(struct pipe_screen *pipe)
 {



More information about the mesa-commit mailing list