[PATCH v2] wined3d: Avoid ending the renderpass when issuing a query.

Jan Sikorski jsikorski at codeweavers.com
Mon Jun 28 10:52:41 CDT 2021


Allocate a fresh query index that does not need to be reset.
Reset query pools at creation and when the render pass is ended.

Signed-off-by: Jan Sikorski <jsikorski at codeweavers.com>
---
v2:
 - changed list beheading to LIST_FOR_EACH_ENTRY_SAFE
 - naming (dirty -> completed)
 - added an explanatory comment
 - whitespace fix
---
 dlls/wined3d/context_vk.c      | 19 +++++++++++--
 dlls/wined3d/query.c           | 50 ++++++++++++++++++++++++++--------
 dlls/wined3d/wined3d_private.h |  6 +++-
 3 files changed, 60 insertions(+), 15 deletions(-)

diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c
index 43b806a19b5..87fcb868197 100644
--- a/dlls/wined3d/context_vk.c
+++ b/dlls/wined3d/context_vk.c
@@ -1282,12 +1282,12 @@ VkRenderPass wined3d_context_vk_get_render_pass(struct wined3d_context_vk *conte
 
 void wined3d_context_vk_end_current_render_pass(struct wined3d_context_vk *context_vk)
 {
+    VkCommandBuffer vk_command_buffer = context_vk->current_command_buffer.vk_command_buffer;
     const struct wined3d_vk_info *vk_info = context_vk->vk_info;
-    VkCommandBuffer vk_command_buffer;
+    struct wined3d_query_pool_vk *pool_vk, *pool_vk_next;
 
     if (context_vk->vk_render_pass)
     {
-        vk_command_buffer = context_vk->current_command_buffer.vk_command_buffer;
         VK_CALL(vkCmdEndRenderPass(vk_command_buffer));
         context_vk->vk_render_pass = VK_NULL_HANDLE;
         VK_CALL(vkCmdPipelineBarrier(vk_command_buffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
@@ -1300,6 +1300,14 @@ void wined3d_context_vk_end_current_render_pass(struct wined3d_context_vk *conte
                 context_vk->vk_framebuffer, context_vk->current_command_buffer.id);
         context_vk->vk_framebuffer = VK_NULL_HANDLE;
     }
+
+    LIST_FOR_EACH_ENTRY_SAFE(pool_vk, pool_vk_next, &context_vk->completed_query_pools,
+            struct wined3d_query_pool_vk, completed_entry)
+    {
+        list_remove(&pool_vk->completed_entry);
+        list_init(&pool_vk->completed_entry);
+        wined3d_query_pool_vk_reset(pool_vk, context_vk, vk_command_buffer);
+    }
 }
 
 static void wined3d_context_vk_destroy_render_pass(struct wine_rb_entry *entry, void *ctx)
@@ -1330,6 +1338,7 @@ static void wined3d_context_vk_destroy_query_pools(struct wined3d_context_vk *co
 bool wined3d_context_vk_allocate_query(struct wined3d_context_vk *context_vk,
         enum wined3d_query_type type, struct wined3d_query_pool_idx_vk *pool_idx)
 {
+    const struct wined3d_vk_info *vk_info = context_vk->vk_info;
     struct wined3d_query_pool_vk *pool_vk, *entry;
     struct list *free_pools;
     size_t idx;
@@ -1376,6 +1385,10 @@ bool wined3d_context_vk_allocate_query(struct wined3d_context_vk *context_vk,
         return false;
     }
 
+    wined3d_context_vk_end_current_render_pass(context_vk);
+    VK_CALL(vkCmdResetQueryPool(wined3d_context_vk_get_command_buffer(context_vk),
+            pool_vk->vk_query_pool, 0, WINED3D_QUERY_POOL_SIZE));
+
     if (!wined3d_query_pool_vk_allocate_query(pool_vk, &idx))
     {
         wined3d_query_pool_vk_cleanup(pool_vk, context_vk);
@@ -1449,7 +1462,6 @@ void wined3d_context_vk_remove_pending_queries(struct wined3d_context_vk *contex
         {
             if (p->query_vk != query_vk && !wined3d_query_vk_accumulate_data(p->query_vk, context_vk, &p->pool_idx))
                 continue;
-            wined3d_query_pool_vk_free_query(p->pool_idx.pool_vk, p->pool_idx.idx);
             --p->query_vk->pending_count;
         }
 
@@ -3390,6 +3402,7 @@ HRESULT wined3d_context_vk_init(struct wined3d_context_vk *context_vk, struct wi
     wined3d_context_vk_init_graphics_pipeline_key(context_vk);
 
     list_init(&context_vk->active_queries);
+    list_init(&context_vk->completed_query_pools);
     list_init(&context_vk->free_occlusion_query_pools);
     list_init(&context_vk->free_timestamp_query_pools);
     list_init(&context_vk->free_pipeline_statistics_query_pools);
diff --git a/dlls/wined3d/query.c b/dlls/wined3d/query.c
index 81f5ba7d0d7..1e082f8ffae 100644
--- a/dlls/wined3d/query.c
+++ b/dlls/wined3d/query.c
@@ -1348,12 +1348,15 @@ HRESULT wined3d_query_gl_create(struct wined3d_device *device, enum wined3d_quer
     }
 }
 
-void wined3d_query_pool_vk_free_query(struct wined3d_query_pool_vk *pool_vk, size_t idx)
+static void wined3d_query_pool_vk_mark_complete(struct wined3d_query_pool_vk *pool_vk, size_t idx,
+        struct wined3d_context_vk *context_vk)
 {
-    wined3d_bitmap_clear(pool_vk->allocated, idx);
-
-    if (list_empty(&pool_vk->entry))
-        list_add_tail(pool_vk->free_list, &pool_vk->entry);
+    /* Don't reset completed queries right away, as vkCmdResetQueryPool() needs to happen
+     * outside of a render pass. Queue the query to be reset in wined3d_query_pool_vk_reset()
+     * instead, which is called when the render pass ends. */
+    wined3d_bitmap_set(pool_vk->completed, idx);
+    if (list_empty(&pool_vk->completed_entry))
+        list_add_tail(&context_vk->completed_query_pools, &pool_vk->completed_entry);
 }
 
 bool wined3d_query_pool_vk_allocate_query(struct wined3d_query_pool_vk *pool_vk, size_t *idx)
@@ -1372,6 +1375,29 @@ void wined3d_query_pool_vk_cleanup(struct wined3d_query_pool_vk *pool_vk, struct
 
     VK_CALL(vkDestroyQueryPool(device_vk->vk_device, pool_vk->vk_query_pool, NULL));
     list_remove(&pool_vk->entry);
+    list_remove(&pool_vk->completed_entry);
+}
+
+void wined3d_query_pool_vk_reset(struct wined3d_query_pool_vk *pool_vk, struct wined3d_context_vk *context_vk,
+        VkCommandBuffer vk_command_buffer)
+{
+    const struct wined3d_vk_info *vk_info = context_vk->vk_info;
+    unsigned int start = 0, idx;
+    struct wined3d_range range;
+
+    for (;;)
+    {
+        if (!wined3d_bitmap_get_range(pool_vk->completed, WINED3D_QUERY_POOL_SIZE, start, &range))
+            break;
+
+        VK_CALL(vkCmdResetQueryPool(vk_command_buffer, pool_vk->vk_query_pool, range.offset, range.size));
+        start = range.offset + range.size;
+        for (idx = range.offset; idx < start; ++idx)
+            wined3d_bitmap_clear(pool_vk->allocated, idx);
+    }
+    memset(pool_vk->completed, 0, sizeof(pool_vk->completed));
+    if (list_empty(&pool_vk->entry))
+        list_add_tail(pool_vk->free_list, &pool_vk->entry);
 }
 
 bool wined3d_query_pool_vk_init(struct wined3d_query_pool_vk *pool_vk,
@@ -1383,6 +1409,7 @@ bool wined3d_query_pool_vk_init(struct wined3d_query_pool_vk *pool_vk,
     VkResult vr;
 
     list_init(&pool_vk->entry);
+    list_init(&pool_vk->completed_entry);
     pool_vk->free_list = free_pools;
 
     pool_info.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO;
@@ -1468,6 +1495,8 @@ bool wined3d_query_vk_accumulate_data(struct wined3d_query_vk *query_vk,
     if (vr == VK_NOT_READY)
         return false;
 
+    wined3d_query_pool_vk_mark_complete(pool_idx->pool_vk, pool_idx->idx, context_vk);
+
     result = (void *)query_vk->q.data;
     switch (query_vk->q.type)
     {
@@ -1519,8 +1548,7 @@ static void wined3d_query_vk_begin(struct wined3d_query_vk *query_vk,
     struct wined3d_query_pool_vk *pool_vk;
     size_t idx;
 
-    if (!query_vk->pool_idx.pool_vk
-            && !wined3d_context_vk_allocate_query(context_vk, query_vk->q.type, &query_vk->pool_idx))
+    if (!wined3d_context_vk_allocate_query(context_vk, query_vk->q.type, &query_vk->pool_idx))
     {
         ERR("Failed to allocate new query.\n");
         return;
@@ -1528,7 +1556,6 @@ static void wined3d_query_vk_begin(struct wined3d_query_vk *query_vk,
     pool_vk = query_vk->pool_idx.pool_vk;
     idx = query_vk->pool_idx.idx;
 
-    VK_CALL(vkCmdResetQueryPool(vk_command_buffer, pool_vk->vk_query_pool, idx, 1));
     if (query_vk->q.type >= WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM1
             && query_vk->q.type <= WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM3)
         VK_CALL(vkCmdBeginQueryIndexedEXT(vk_command_buffer, pool_vk->vk_query_pool, idx,
@@ -1599,6 +1626,7 @@ static BOOL wined3d_query_vk_poll(struct wined3d_query *query, uint32_t flags)
     if (query_vk->pool_idx.pool_vk && !wined3d_query_vk_accumulate_data(query_vk, context_vk, &query_vk->pool_idx))
         goto unavailable;
 
+    query_vk->pool_idx.pool_vk = NULL;
     context_release(&context_vk->c);
 
     return TRUE;
@@ -1622,7 +1650,6 @@ static BOOL wined3d_query_vk_issue(struct wined3d_query *query, uint32_t flags)
     {
         context_vk = wined3d_context_vk(context_acquire(&device_vk->d, NULL, 0));
 
-        wined3d_context_vk_end_current_render_pass(context_vk);
         list_remove(&query_vk->entry);
         if (query_vk->pending_count)
             wined3d_context_vk_remove_pending_queries(context_vk, query_vk);
@@ -1633,6 +1660,9 @@ static BOOL wined3d_query_vk_issue(struct wined3d_query *query, uint32_t flags)
             wined3d_query_vk_end(query_vk, context_vk, vk_command_buffer);
             list_remove(&query_vk->entry);
         }
+        if (query_vk->pool_idx.pool_vk)
+            wined3d_query_pool_vk_mark_complete(query_vk->pool_idx.pool_vk,
+                    query_vk->pool_idx.idx, context_vk);
         wined3d_query_vk_begin(query_vk, context_vk, vk_command_buffer);
         list_add_head(&context_vk->active_queries, &query_vk->entry);
         query_vk->started = true;
@@ -1669,8 +1699,6 @@ static void wined3d_query_vk_destroy(struct wined3d_query *query)
         wined3d_context_vk_remove_pending_queries(context_vk, query_vk);
         context_release(&context_vk->c);
     }
-    if (query_vk->pool_idx.pool_vk)
-        wined3d_query_pool_vk_free_query(query_vk->pool_idx.pool_vk, query_vk->pool_idx.idx);
     heap_free(query_vk);
 }
 
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 84dad38f0c9..58fbc69ca7c 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2023,16 +2023,19 @@ struct wined3d_pipeline_statistics_query
 struct wined3d_query_pool_vk
 {
     struct list entry;
+    struct list completed_entry;
 
     struct list *free_list;
     VkQueryPool vk_query_pool;
     uint32_t allocated[WINED3D_BITMAP_SIZE(WINED3D_QUERY_POOL_SIZE)];
+    uint32_t completed[WINED3D_BITMAP_SIZE(WINED3D_QUERY_POOL_SIZE)];
 };
 
 bool wined3d_query_pool_vk_allocate_query(struct wined3d_query_pool_vk *pool_vk, size_t *idx) DECLSPEC_HIDDEN;
 void wined3d_query_pool_vk_cleanup(struct wined3d_query_pool_vk *pool_vk,
         struct wined3d_context_vk *context_vk) DECLSPEC_HIDDEN;
-void wined3d_query_pool_vk_free_query(struct wined3d_query_pool_vk *pool_vk, size_t idx) DECLSPEC_HIDDEN;
+void wined3d_query_pool_vk_reset(struct wined3d_query_pool_vk *pool_vk, struct wined3d_context_vk *context_vk,
+        VkCommandBuffer vk_command_buffer) DECLSPEC_HIDDEN;
 bool wined3d_query_pool_vk_init(struct wined3d_query_pool_vk *pool_vk, struct wined3d_context_vk *context_vk,
         enum wined3d_query_type type, struct list *free_pools) DECLSPEC_HIDDEN;
 
@@ -2574,6 +2577,7 @@ struct wined3d_context_vk
 
     struct list active_queries;
     struct wined3d_pending_queries_vk pending_queries;
+    struct list completed_query_pools;
     struct list free_occlusion_query_pools;
     struct list free_timestamp_query_pools;
     struct list free_pipeline_statistics_query_pools;
-- 
2.30.2




More information about the wine-devel mailing list