Jan Sikorski : wined3d: Implement event queries using Vulkan events.

Alexandre Julliard julliard at winehq.org
Mon Mar 7 16:04:56 CST 2022


Module: wine
Branch: master
Commit: 8e0ab7363d84d615e0a6ec93ce07b569a13a1eee
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=8e0ab7363d84d615e0a6ec93ce07b569a13a1eee

Author: Jan Sikorski <jsikorski at codeweavers.com>
Date:   Fri Mar  4 18:12:59 2022 +0100

wined3d: Implement event queries using Vulkan events.

This makes event results available sooner, i.e. after they are executed
by the GPU, and also moves the polling from CS to application's thread.

Signed-off-by: Jan Sikorski <jsikorski at codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/wined3d/context_vk.c      | 30 ++++++++++++++++
 dlls/wined3d/query.c           | 79 +++++++++++++++++++++++++-----------------
 dlls/wined3d/wined3d_private.h |  5 +++
 3 files changed, 83 insertions(+), 31 deletions(-)

diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c
index dcb94eb7c1a..436973fe76f 100644
--- a/dlls/wined3d/context_vk.c
+++ b/dlls/wined3d/context_vk.c
@@ -973,6 +973,31 @@ void wined3d_context_vk_destroy_vk_sampler(struct wined3d_context_vk *context_vk
     o->command_buffer_id = command_buffer_id;
 }
 
+void wined3d_context_vk_destroy_vk_event(struct wined3d_context_vk *context_vk,
+        VkEvent vk_event, uint64_t command_buffer_id)
+{
+    struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
+    const struct wined3d_vk_info *vk_info = context_vk->vk_info;
+    struct wined3d_retired_object_vk *o;
+
+    if (context_vk->completed_command_buffer_id > command_buffer_id)
+    {
+        VK_CALL(vkDestroyEvent(device_vk->vk_device, vk_event, NULL));
+        TRACE("Destroyed event 0x%s.\n", wine_dbgstr_longlong(vk_event));
+        return;
+    }
+
+    if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
+    {
+        ERR("Leaking event 0x%s.\n", wine_dbgstr_longlong(vk_event));
+        return;
+    }
+
+    o->type = WINED3D_RETIRED_EVENT_VK;
+    o->u.vk_event = vk_event;
+    o->command_buffer_id = command_buffer_id;
+}
+
 void wined3d_context_vk_destroy_image(struct wined3d_context_vk *context_vk, struct wined3d_image_vk *image)
 {
     wined3d_context_vk_destroy_vk_image(context_vk, image->vk_image, image->command_buffer_id);
@@ -1134,6 +1159,11 @@ static void wined3d_context_vk_cleanup_resources(struct wined3d_context_vk *cont
                 TRACE("Freed query range %u+%u in pool %p.\n", o->u.queries.start, o->u.queries.count, o->u.queries.pool_vk);
                 break;
 
+            case WINED3D_RETIRED_EVENT_VK:
+                VK_CALL(vkDestroyEvent(device_vk->vk_device, o->u.vk_event, NULL));
+                TRACE("Destroyed event 0x%s.\n", wine_dbgstr_longlong(o->u.vk_event));
+                break;
+
             default:
                 ERR("Unhandled object type %#x.\n", o->type);
                 break;
diff --git a/dlls/wined3d/query.c b/dlls/wined3d/query.c
index 3a4a518fcfb..4b94cb8daea 100644
--- a/dlls/wined3d/query.c
+++ b/dlls/wined3d/query.c
@@ -1742,6 +1742,8 @@ static void wined3d_query_vk_destroy(struct wined3d_query *query)
     wined3d_query_vk_remove_pending_queries(context_vk, query_vk);
     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);
+    if (query_vk->vk_event)
+        wined3d_context_vk_destroy_vk_event(context_vk, query_vk->vk_event, query_vk->command_buffer_id);
     context_release(&context_vk->c);
     heap_free(query_vk->pending);
     heap_free(query_vk);
@@ -1756,50 +1758,67 @@ static const struct wined3d_query_ops wined3d_query_vk_ops =
 
 static BOOL wined3d_query_event_vk_poll(struct wined3d_query *query, uint32_t flags)
 {
+    struct wined3d_device_vk *device_vk = wined3d_device_vk(query->device);
     struct wined3d_query_vk *query_vk = wined3d_query_vk(query);
-    struct wined3d_context_vk *context_vk;
-    BOOL *signalled;
-
-    context_vk = wined3d_context_vk(context_acquire(query->device, NULL, 0));
-
-    signalled = (BOOL *)query->data;
-    if (flags & WINED3DGETDATA_FLUSH)
-        wined3d_context_vk_submit_command_buffer(context_vk, 0, NULL, NULL, 0, NULL);
-    if (query_vk->command_buffer_id == context_vk->current_command_buffer.id)
-    {
-        context_release(&context_vk->c);
-        return *signalled = FALSE;
-    }
-
-    if (query_vk->command_buffer_id > context_vk->completed_command_buffer_id)
-        wined3d_context_vk_poll_command_buffers(context_vk);
-    *signalled = context_vk->completed_command_buffer_id >= query_vk->command_buffer_id;
-
-    context_release(&context_vk->c);
+    const struct wined3d_vk_info *vk_info = &device_vk->vk_info;
+    BOOL signalled;
 
-    return *signalled;
+    signalled = VK_CALL(vkGetEventStatus(device_vk->vk_device, query_vk->vk_event))
+            == VK_EVENT_SET;
+    if (!signalled && (flags & WINED3DGETDATA_FLUSH) && !query->device->cs->queries_flushed)
+        query->device->cs->c.ops->flush(&query->device->cs->c);
+    return *(BOOL *)query->data = signalled;
 }
 
 static BOOL wined3d_query_event_vk_issue(struct wined3d_query *query, uint32_t flags)
 {
     struct wined3d_device_vk *device_vk = wined3d_device_vk(query->device);
+    const struct wined3d_vk_info *vk_info = &device_vk->vk_info;
     struct wined3d_query_vk *query_vk = wined3d_query_vk(query);
     struct wined3d_context_vk *context_vk;
+    VkEventCreateInfo create_info;
+    VkResult vr;
 
     TRACE("query %p, flags %#x.\n", query, flags);
 
     if (flags & WINED3DISSUE_END)
     {
         context_vk = wined3d_context_vk(context_acquire(&device_vk->d, NULL, 0));
+        wined3d_context_vk_end_current_render_pass(context_vk);
+
+        if (query_vk->vk_event)
+        {
+            if (query_vk->command_buffer_id > context_vk->completed_command_buffer_id)
+            {
+                /* Cannot reuse this event, as it may still get signalled by previous usage. */
+                /* Throw it away and create a new one, but if that happens a lot we may want to pool instead. */
+                wined3d_context_vk_destroy_vk_event(context_vk, query_vk->vk_event, query_vk->command_buffer_id);
+                query_vk->vk_event = VK_NULL_HANDLE;
+            }
+            else
+            {
+                VK_CALL(vkResetEvent(device_vk->vk_device, query_vk->vk_event));
+            }
+        }
+
+        if (!query_vk->vk_event)
+        {
+            create_info.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO;
+            create_info.pNext = NULL;
+            create_info.flags = 0;
+
+            vr = VK_CALL(vkCreateEvent(device_vk->vk_device, &create_info, NULL, &query_vk->vk_event));
+            if (vr != VK_SUCCESS)
+            {
+                ERR("Failed to create Vulkan event, vr %s\n", wined3d_debug_vkresult(vr));
+                context_release(&context_vk->c);
+                return FALSE;
+            }
+        }
+
         wined3d_context_vk_reference_query(context_vk, query_vk);
-        /* Because we don't actually submit any commands to the command buffer
-         * for event queries, the context's current command buffer may still
-         * be empty, and we should wait on the preceding command buffer
-         * instead. That's not merely an optimisation; if the command buffer
-         * referenced by the query is still empty by the time the application
-         * waits for it, that wait will never complete. */
-        if (!context_vk->current_command_buffer.vk_command_buffer)
-            --query_vk->command_buffer_id;
+        VK_CALL(vkCmdSetEvent(wined3d_context_vk_get_command_buffer(context_vk), query_vk->vk_event,
+                VK_PIPELINE_STAGE_ALL_COMMANDS_BIT));
         context_release(&context_vk->c);
 
         return TRUE;
@@ -1937,9 +1956,7 @@ HRESULT wined3d_query_vk_create(struct wined3d_device *device, enum wined3d_quer
     data = query_vk + 1;
 
     wined3d_query_init(&query_vk->q, device, type, data, data_size, ops, parent, parent_ops);
-
-    if (type != WINED3D_QUERY_TYPE_EVENT)
-        query_vk->q.poll_in_cs = false;
+    query_vk->q.poll_in_cs = false;
 
     switch (type)
     {
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index a9e42e0cb16..58ef6764f2d 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2086,6 +2086,7 @@ struct wined3d_query_vk
     uint8_t flags;
     uint64_t command_buffer_id;
     uint32_t control_flags;
+    VkEvent vk_event;
     SIZE_T pending_count, pending_size;
     struct wined3d_query_pool_idx_vk *pending;
 };
@@ -2414,6 +2415,7 @@ enum wined3d_retired_object_type_vk
     WINED3D_RETIRED_IMAGE_VIEW_VK,
     WINED3D_RETIRED_SAMPLER_VK,
     WINED3D_RETIRED_QUERY_POOL_VK,
+    WINED3D_RETIRED_EVENT_VK,
 };
 
 struct wined3d_retired_object_vk
@@ -2436,6 +2438,7 @@ struct wined3d_retired_object_vk
         VkBufferView vk_buffer_view;
         VkImageView vk_image_view;
         VkSampler vk_sampler;
+        VkEvent vk_event;
         struct
         {
             struct wined3d_query_pool_vk *pool_vk;
@@ -2659,6 +2662,8 @@ void wined3d_context_vk_destroy_vk_memory(struct wined3d_context_vk *context_vk,
         VkDeviceMemory vk_memory, uint64_t command_buffer_id) DECLSPEC_HIDDEN;
 void wined3d_context_vk_destroy_vk_sampler(struct wined3d_context_vk *context_vk,
         VkSampler vk_sampler, uint64_t command_buffer_id) DECLSPEC_HIDDEN;
+void wined3d_context_vk_destroy_vk_event(struct wined3d_context_vk *context_vk,
+        VkEvent vk_event, uint64_t command_buffer_id) DECLSPEC_HIDDEN;
 void wined3d_context_vk_end_current_render_pass(struct wined3d_context_vk *context_vk) DECLSPEC_HIDDEN;
 VkCommandBuffer wined3d_context_vk_get_command_buffer(struct wined3d_context_vk *context_vk) DECLSPEC_HIDDEN;
 struct wined3d_pipeline_layout_vk *wined3d_context_vk_get_pipeline_layout(struct wined3d_context_vk *context_vk,




More information about the wine-cvs mailing list