zink: only stall during query destroy for xfb queries
authorMike Blumenkrantz <michael.blumenkrantz@gmail.com>
Mon, 25 May 2020 14:55:17 +0000 (10:55 -0400)
committerMarge Bot <eric+marge@anholt.net>
Mon, 13 Jul 2020 20:59:07 +0000 (20:59 +0000)
xfb queries allocate vk buffer objects in the underlying driver which
can be deallocated while an xfb query is in-flight if we attempt to
defer it due to the way that gl xfb is translated to vk, so we need to
continue forcing this behavior in that case

for other query types, we can safely defer here until the current batch has
finished rather than block

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

src/gallium/drivers/zink/zink_query.c

index 1b37f89f74bbfabc4bfb1744932df024cf608ac8..8c4e792eb896c8248b99fce28db6c3cef4cffeae 100644 (file)
@@ -23,8 +23,10 @@ struct zink_query {
    unsigned index;
    bool use_64bit;
    bool precise;
+   bool xfb_running;
 
    bool active; /* query is considered active by vk */
+   bool dead; /* query should be destroyed when its fence finishes */
 
    unsigned fences;
    struct list_head active_list;
@@ -108,6 +110,14 @@ wait_query(struct pipe_context *pctx, struct zink_query *query)
    }
 }
 
+static void
+destroy_query(struct zink_screen *screen, struct zink_query *query)
+{
+   assert(!p_atomic_read(&query->fences));
+   vkDestroyQueryPool(screen->dev, query->query_pool, NULL);
+   FREE(query);
+}
+
 static void
 zink_destroy_query(struct pipe_context *pctx,
                    struct pipe_query *q)
@@ -115,11 +125,14 @@ zink_destroy_query(struct pipe_context *pctx,
    struct zink_screen *screen = zink_screen(pctx->screen);
    struct zink_query *query = (struct zink_query *)q;
 
-   if (p_atomic_read(&query->fences))
-      wait_query(pctx, query);
+   p_atomic_set(&query->dead, true);
+   if (p_atomic_read(&query->fences)) {
+      if (query->xfb_running)
+        wait_query(pctx, query);
+      return;
+   }
 
-   vkDestroyQueryPool(screen->dev, query->query_pool, NULL);
-   FREE(query);
+   destroy_query(screen, query);
 }
 
 void
@@ -127,7 +140,10 @@ zink_prune_queries(struct zink_screen *screen, struct zink_fence *fence)
 {
    set_foreach(fence->active_queries, entry) {
       struct zink_query *query = (void*)entry->key;
-      p_atomic_dec(&query->fences);
+      if (!p_atomic_dec_return(&query->fences)) {
+         if (p_atomic_read(&query->dead))
+            destroy_query(screen, query);
+      }
    }
    _mesa_set_destroy(fence->active_queries, NULL);
    fence->active_queries = NULL;
@@ -140,13 +156,14 @@ begin_query(struct zink_context *ctx, struct zink_batch *batch, struct zink_quer
 
    if (q->precise)
       flags |= VK_QUERY_CONTROL_PRECISE_BIT;
-   if (q->vkqtype == VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT)
+   if (q->vkqtype == VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT) {
       zink_screen(ctx->base.screen)->vk_CmdBeginQueryIndexedEXT(batch->cmdbuf,
                                                                 q->query_pool,
                                                                 q->curr_query,
                                                                 flags,
                                                                 q->index);
-   else
+      q->xfb_running = true;
+   } else
       vkCmdBeginQuery(batch->cmdbuf, q->query_pool, q->curr_query, flags);
    q->active = true;
    if (!batch->active_queries)