[PATCH 3/3] wined3d: Implement event queries using Vulkan events.
Jan Sikorski
jsikorski at codeweavers.com
Mon Nov 22 06:46:19 CST 2021
Signed-off-by: Jan Sikorski <jsikorski at codeweavers.com>
---
dlls/wined3d/context_vk.c | 30 +++++++++++
dlls/wined3d/query.c | 91 ++++++++++++++++------------------
dlls/wined3d/wined3d_private.h | 5 ++
3 files changed, 79 insertions(+), 47 deletions(-)
diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c
index dce78e1bc43..fe940d08c5f 100644
--- a/dlls/wined3d/context_vk.c
+++ b/dlls/wined3d/context_vk.c
@@ -930,6 +930,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);
@@ -1083,6 +1108,11 @@ static void wined3d_context_vk_cleanup_resources(struct wined3d_context_vk *cont
TRACE("Destroyed sampler 0x%s.\n", wine_dbgstr_longlong(o->u.vk_sampler));
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 6cfa5d73da0..c2a5b8a5d2d 100644
--- a/dlls/wined3d/query.c
+++ b/dlls/wined3d/query.c
@@ -1808,6 +1808,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);
@@ -1820,70 +1822,65 @@ static const struct wined3d_query_ops wined3d_query_vk_ops =
.query_destroy = wined3d_query_vk_destroy,
};
-static void wined3d_query_event_vk_poll_cs(void *object)
-{
- struct wined3d_poll_callback_data *data = object;
- struct wined3d_query *query = data->query;
- struct wined3d_context_vk *context_vk;
- struct wined3d_query_vk *query_vk;
- uint32_t flags = data->flags;
- BOOL *signalled;
-
- query_vk = wined3d_query_vk(query);
- 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);
- data->result = *signalled = FALSE;
- return;
- }
-
- 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);
-
- data->result = *signalled;
-}
-
static BOOL wined3d_query_event_vk_poll(struct wined3d_query *query, uint32_t flags)
{
- struct wined3d_cs *cs = query->device->cs;
- struct wined3d_poll_callback_data data;
-
- data.query = query;
- data.flags = flags;
-
- wined3d_cs_run_priority_callback(cs, wined3d_query_event_vk_poll_cs, &data);
+ struct wined3d_device_vk *device_vk = wined3d_device_vk(query->device);
+ struct wined3d_query_vk *query_vk = wined3d_query_vk(query);
+ const struct wined3d_vk_info *vk_info = &device_vk->vk_info;
- return data.result;
+ return *(BOOL *)query->data = VK_CALL(vkGetEventStatus(device_vk->vk_device, query_vk->vk_event))
+ == VK_EVENT_SET;
}
static void 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;
+ }
+ }
+
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);
}
}
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 7185893e894..b7a675ffa9b 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2102,6 +2102,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;
};
@@ -2428,6 +2429,7 @@ enum wined3d_retired_object_type_vk
WINED3D_RETIRED_BUFFER_VIEW_VK,
WINED3D_RETIRED_IMAGE_VIEW_VK,
WINED3D_RETIRED_SAMPLER_VK,
+ WINED3D_RETIRED_EVENT_VK,
};
struct wined3d_retired_object_vk
@@ -2450,6 +2452,7 @@ struct wined3d_retired_object_vk
VkBufferView vk_buffer_view;
VkImageView vk_image_view;
VkSampler vk_sampler;
+ VkEvent vk_event;
} u;
uint64_t command_buffer_id;
};
@@ -2682,6 +2685,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,
--
2.32.0
More information about the wine-devel
mailing list