Signed-off-by: Jan Sikorski jsikorski@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,