Commit 8e0ab736 authored by Jan Sikorski's avatar Jan Sikorski Committed by Alexandre Julliard

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: 's avatarJan Sikorski <jsikorski@codeweavers.com> Signed-off-by: 's avatarHenri Verbeet <hverbeet@codeweavers.com> Signed-off-by: 's avatarAlexandre Julliard <julliard@winehq.org>
parent 1a7a50a1
......@@ -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;
......
......@@ -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)
{
......
......@@ -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,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment