[PATCH 1/2] wined3d: Track queries started inside/outside of a render pass separately.

Jan Sikorski jsikorski at codeweavers.com
Wed Jul 28 06:42:13 CDT 2021


Signed-off-by: Jan Sikorski <jsikorski at codeweavers.com>
---
 dlls/wined3d/context_vk.c      | 28 +++++++++++++--
 dlls/wined3d/query.c           | 64 ++++++++++++++++++++++++++--------
 dlls/wined3d/wined3d_private.h |  7 +++-
 3 files changed, 81 insertions(+), 18 deletions(-)

diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c
index 4b1bea38370..c718f3facd5 100644
--- a/dlls/wined3d/context_vk.c
+++ b/dlls/wined3d/context_vk.c
@@ -1285,13 +1285,26 @@ void wined3d_context_vk_end_current_render_pass(struct wined3d_context_vk *conte
     VkCommandBuffer vk_command_buffer = context_vk->current_command_buffer.vk_command_buffer;
     const struct wined3d_vk_info *vk_info = context_vk->vk_info;
     struct wined3d_query_pool_vk *pool_vk, *pool_vk_next;
+    struct wined3d_query_vk *query_vk;
 
     if (context_vk->vk_render_pass)
     {
+        LIST_FOR_EACH_ENTRY(query_vk, &context_vk->render_pass_queries, struct wined3d_query_vk, entry)
+            wined3d_query_vk_suspend(query_vk, context_vk);
+
         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,
                 VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, NULL, 0, NULL, 0, NULL));
+
+        LIST_FOR_EACH_ENTRY(query_vk, &context_vk->render_pass_queries, struct wined3d_query_vk, entry)
+        {
+            if (!wined3d_context_vk_allocate_query(context_vk, query_vk->q.type, &query_vk->pool_idx))
+            {
+                ERR("Failed to allocate new query.\n");
+                break;
+            }
+        }
     }
 
     if (context_vk->vk_framebuffer)
@@ -1561,6 +1574,12 @@ VkCommandBuffer wined3d_context_vk_get_command_buffer(struct wined3d_context_vk
     wined3d_context_vk_accumulate_pending_queries(context_vk);
     LIST_FOR_EACH_ENTRY(query_vk, &context_vk->active_queries, struct wined3d_query_vk, entry)
     {
+        if (!wined3d_context_vk_allocate_query(context_vk, query_vk->q.type, &query_vk->pool_idx))
+        {
+            ERR("Failed to allocate new query.\n");
+            break;
+        }
+
         wined3d_query_vk_resume(query_vk, context_vk);
     }
 
@@ -1594,12 +1613,11 @@ void wined3d_context_vk_submit_command_buffer(struct wined3d_context_vk *context
     TRACE("Submitting command buffer %p with id 0x%s.\n",
             buffer->vk_command_buffer, wine_dbgstr_longlong(buffer->id));
 
+    wined3d_context_vk_end_current_render_pass(context_vk);
+
     LIST_FOR_EACH_ENTRY(query_vk, &context_vk->active_queries, struct wined3d_query_vk, entry)
-    {
         wined3d_query_vk_suspend(query_vk, context_vk);
-    }
 
-    wined3d_context_vk_end_current_render_pass(context_vk);
     context_vk->graphics.vk_pipeline = VK_NULL_HANDLE;
     context_vk->update_compute_pipeline = 1;
     context_vk->update_stream_output = 1;
@@ -2323,6 +2341,7 @@ static bool wined3d_context_vk_begin_render_pass(struct wined3d_context_vk *cont
     struct wined3d_rendertarget_view_vk *rtv_vk;
     struct wined3d_rendertarget_view *view;
     const VkPhysicalDeviceLimits *limits;
+    struct wined3d_query_vk *query_vk;
     VkRenderPassBeginInfo begin_info;
     unsigned int attachment_count, i;
     VkFramebufferCreateInfo fb_desc;
@@ -2409,6 +2428,8 @@ static bool wined3d_context_vk_begin_render_pass(struct wined3d_context_vk *cont
     begin_info.pClearValues = NULL;
     VK_CALL(vkCmdBeginRenderPass(vk_command_buffer, &begin_info, VK_SUBPASS_CONTENTS_INLINE));
 
+    LIST_FOR_EACH_ENTRY(query_vk, &context_vk->render_pass_queries, struct wined3d_query_vk, entry)
+        wined3d_query_vk_resume(query_vk, context_vk);
     return true;
 }
 
@@ -3460,6 +3481,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->render_pass_queries);
     list_init(&context_vk->active_queries);
     list_init(&context_vk->completed_query_pools);
     list_init(&context_vk->free_occlusion_query_pools);
diff --git a/dlls/wined3d/query.c b/dlls/wined3d/query.c
index 1e082f8ffae..4628cb98cdc 100644
--- a/dlls/wined3d/query.c
+++ b/dlls/wined3d/query.c
@@ -1548,11 +1548,6 @@ static void wined3d_query_vk_begin(struct wined3d_query_vk *query_vk,
     struct wined3d_query_pool_vk *pool_vk;
     size_t 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;
-    }
     pool_vk = query_vk->pool_idx.pool_vk;
     idx = query_vk->pool_idx.idx;
 
@@ -1588,6 +1583,7 @@ void wined3d_query_vk_resume(struct wined3d_query_vk *query_vk, struct wined3d_c
     VkCommandBuffer vk_command_buffer = context_vk->current_command_buffer.vk_command_buffer;
 
     wined3d_query_vk_begin(query_vk, context_vk, vk_command_buffer);
+    query_vk->flags |= WINED3D_QUERY_VK_FLAG_ACTIVE;
 }
 
 void wined3d_query_vk_suspend(struct wined3d_query_vk *query_vk, struct wined3d_context_vk *context_vk)
@@ -1597,6 +1593,7 @@ void wined3d_query_vk_suspend(struct wined3d_query_vk *query_vk, struct wined3d_
     wined3d_query_vk_end(query_vk, context_vk, vk_command_buffer);
     wined3d_context_vk_add_pending_query(context_vk, query_vk);
     query_vk->pool_idx.pool_vk = NULL;
+    query_vk->flags &= ~WINED3D_QUERY_VK_FLAG_ACTIVE;
 }
 
 static BOOL wined3d_query_vk_poll(struct wined3d_query *query, uint32_t flags)
@@ -1655,30 +1652,69 @@ static BOOL wined3d_query_vk_issue(struct wined3d_query *query, uint32_t flags)
             wined3d_context_vk_remove_pending_queries(context_vk, query_vk);
         memset((void *)query->data, 0, query->data_size);
         vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk);
-        if (query_vk->started)
+        if (query_vk->flags & WINED3D_QUERY_VK_FLAG_STARTED)
         {
-            wined3d_query_vk_end(query_vk, context_vk, vk_command_buffer);
+            if (query_vk->flags & WINED3D_QUERY_VK_FLAG_ACTIVE)
+                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;
 
+        if (!wined3d_context_vk_allocate_query(context_vk, query_vk->q.type, &query_vk->pool_idx))
+        {
+            ERR("Failed to allocate new query.\n");
+            return false;
+        }
+
+        /* A query need to either begin and end inside a single render pass,
+         * or begin and end ouside of a render pass. Occlusion queries, if issued
+         * ouside of a render pass, are queued up and only begun when a render
+         * pass is started, to avoid interrupting it when the query ends. */
+        if (context_vk->vk_render_pass)
+        {
+            wined3d_query_vk_begin(query_vk, context_vk, vk_command_buffer);
+            list_add_head(&context_vk->render_pass_queries, &query_vk->entry);
+            query_vk->flags |= WINED3D_QUERY_VK_FLAG_ACTIVE | WINED3D_QUERY_VK_FLAG_RENDER_PASS;
+        }
+        else if (query->type == WINED3D_QUERY_TYPE_OCCLUSION)
+        {
+            list_add_head(&context_vk->render_pass_queries, &query_vk->entry);
+            query_vk->flags |= WINED3D_QUERY_VK_FLAG_RENDER_PASS;
+        }
+        else
+        {
+            wined3d_query_vk_begin(query_vk, context_vk, vk_command_buffer);
+            list_add_head(&context_vk->active_queries, &query_vk->entry);
+            query_vk->flags |= WINED3D_QUERY_VK_FLAG_ACTIVE;
+        }
+
+        query_vk->flags |= WINED3D_QUERY_VK_FLAG_STARTED;
         context_release(&context_vk->c);
     }
-    if (flags & WINED3DISSUE_END && query_vk->started)
+    if (flags & WINED3DISSUE_END && query_vk->flags & WINED3D_QUERY_VK_FLAG_STARTED)
     {
         context_vk = wined3d_context_vk(context_acquire(&device_vk->d, NULL, 0));
 
         /* If the query was already ended because the command buffer was
-         * flushed, we don't need to end it here. */
-        if ((vk_command_buffer = context_vk->current_command_buffer.vk_command_buffer))
+         * flushed or the render pass ended, we don't need to end it here. */
+        if (query_vk->flags & WINED3D_QUERY_VK_FLAG_ACTIVE)
+        {
+            vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk);
+            if (!(query_vk->flags & WINED3D_QUERY_VK_FLAG_RENDER_PASS))
+                wined3d_context_vk_end_current_render_pass(context_vk);
             wined3d_query_vk_end(query_vk, context_vk, vk_command_buffer);
+        }
+        else if (query_vk->pool_idx.pool_vk)
+        {
+            /* It was queued, but never activated. */
+            wined3d_query_pool_vk_mark_complete(query_vk->pool_idx.pool_vk,
+                    query_vk->pool_idx.idx, context_vk);
+            query_vk->pool_idx.pool_vk = NULL;
+        }
         list_remove(&query_vk->entry);
-        query_vk->started = false;
+        query_vk->flags = 0;
         poll = true;
 
         context_release(&context_vk->c);
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index a2048fc6ea6..86eae149306 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2050,13 +2050,17 @@ struct wined3d_query_pool_idx_vk
     size_t idx;
 };
 
+#define WINED3D_QUERY_VK_FLAG_ACTIVE       0x00000001
+#define WINED3D_QUERY_VK_FLAG_STARTED      0x00000002
+#define WINED3D_QUERY_VK_FLAG_RENDER_PASS  0x00000004
+
 struct wined3d_query_vk
 {
     struct wined3d_query q;
 
     struct list entry;
     struct wined3d_query_pool_idx_vk pool_idx;
-    bool started;
+    uint8_t flags;
     uint64_t command_buffer_id;
     uint32_t control_flags;
     size_t pending_count;
@@ -2580,6 +2584,7 @@ struct wined3d_context_vk
     VkDeviceSize vk_so_offsets[WINED3D_MAX_STREAM_OUTPUT_BUFFERS];
     struct wined3d_bo_vk vk_so_counter_bo;
 
+    struct list render_pass_queries;
     struct list active_queries;
     struct wined3d_pending_queries_vk pending_queries;
     struct list completed_query_pools;
-- 
2.30.2




More information about the wine-devel mailing list