zink: flush active queries on destroy and free query object
authorMike Blumenkrantz <michael.blumenkrantz@gmail.com>
Wed, 20 May 2020 13:45:39 +0000 (09:45 -0400)
committerMarge Bot <eric+marge@anholt.net>
Fri, 22 May 2020 13:24:10 +0000 (13:24 +0000)
queries with a valid active_list pointer are likely to still be active,
and vk spec requires them to have completed prior to being destroyed

this isn't completely accurate, as it's currently possible for queries
to remain in the active list while not actually being active, but it
resolves driver crashes that can occur from destroying a stilll-running
query pool object

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

src/gallium/drivers/zink/zink_query.c

index 344ed785be63de9d9df57308247569582bd8902d..3f8c640ae6550b712e743142122719bc5ad17fa8 100644 (file)
@@ -76,6 +76,20 @@ zink_create_query(struct pipe_context *pctx,
    return (struct pipe_query *)query;
 }
 
+/* TODO: rework this to be less hammer-ish using deferred destroy */
+static void
+wait_query(struct pipe_context *pctx, struct zink_query *query)
+{
+   struct pipe_fence_handle *fence = NULL;
+
+   pctx->flush(pctx, &fence, PIPE_FLUSH_HINT_FINISH);
+   if (fence) {
+      pctx->screen->fence_finish(pctx->screen, NULL, fence,
+                                 PIPE_TIMEOUT_INFINITE);
+      pctx->screen->fence_reference(pctx->screen, &fence, NULL);
+   }
+}
+
 static void
 zink_destroy_query(struct pipe_context *pctx,
                    struct pipe_query *q)
@@ -83,7 +97,12 @@ zink_destroy_query(struct pipe_context *pctx,
    struct zink_screen *screen = zink_screen(pctx->screen);
    struct zink_query *query = (struct zink_query *)q;
 
+   if (!list_is_empty(&query->active_list)) {
+      wait_query(pctx, query);
+   }
+
    vkDestroyQueryPool(screen->dev, query->query_pool, NULL);
+   FREE(query);
 }
 
 static void
@@ -165,13 +184,7 @@ zink_get_query_result(struct pipe_context *pctx,
    VkQueryResultFlagBits flags = 0;
 
    if (wait) {
-      struct pipe_fence_handle *fence = NULL;
-      pctx->flush(pctx, &fence, PIPE_FLUSH_HINT_FINISH);
-      if (fence) {
-         pctx->screen->fence_finish(pctx->screen, NULL, fence,
-                                    PIPE_TIMEOUT_INFINITE);
-         pctx->screen->fence_reference(pctx->screen, &fence, NULL);
-      }
+      wait_query(pctx, query);
       flags |= VK_QUERY_RESULT_WAIT_BIT;
    } else
       pctx->flush(pctx, NULL, 0);