Its eventual purpose is to allow for skipping the poll list mechanism by calling query_poll() in the application thread. In this patch it is only used for when we don't have a separate CS thread.
Signed-off-by: Jan Sikorski jsikorski@codeweavers.com --- dlls/wined3d/cs.c | 6 +++++- dlls/wined3d/query.c | 21 ++++++++++----------- dlls/wined3d/wined3d_private.h | 1 + 3 files changed, 16 insertions(+), 12 deletions(-)
diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index b150f1ae097..ce297d724f2 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -2312,8 +2312,12 @@ static void wined3d_cs_exec_query_issue(struct wined3d_cs *cs, const void *data)
poll = query->query_ops->query_issue(query, op->flags);
- if (!cs->thread) + if (!query->poll_in_cs) + { + if (op->flags & WINED3DISSUE_END) + InterlockedIncrement(&query->counter_retrieved); return; + }
if (poll && list_empty(&query->poll_list_entry)) { diff --git a/dlls/wined3d/query.c b/dlls/wined3d/query.c index 7b6c2325523..093b412bf18 100644 --- a/dlls/wined3d/query.c +++ b/dlls/wined3d/query.c @@ -143,6 +143,7 @@ static void wined3d_query_init(struct wined3d_query *query, struct wined3d_devic query->data = data; query->data_size = data_size; query->query_ops = query_ops; + query->poll_in_cs = !!device->cs->thread; list_init(&query->poll_list_entry); }
@@ -469,23 +470,21 @@ HRESULT CDECL wined3d_query_get_data(struct wined3d_query *query, return WINED3DERR_INVALIDCALL; }
- if (query->device->cs->thread) + if (query->counter_main != query->counter_retrieved + || (query->buffer_object && !wined3d_query_buffer_is_valid(query))) { - if (query->counter_main != query->counter_retrieved - || (query->buffer_object && !wined3d_query_buffer_is_valid(query))) - { - if (flags & WINED3DGETDATA_FLUSH && !query->device->cs->queries_flushed) - query->device->cs->c.ops->flush(&query->device->cs->c); - return S_FALSE; - } - if (query->buffer_object) - query->data = query->map_ptr; + if (flags & WINED3DGETDATA_FLUSH && !query->device->cs->queries_flushed) + query->device->cs->c.ops->flush(&query->device->cs->c); + return S_FALSE; } - else if (!query->query_ops->query_poll(query, flags)) + else if (!query->poll_in_cs && !query->query_ops->query_poll(query, flags)) { return S_FALSE; }
+ if (query->buffer_object) + query->data = query->map_ptr; + if (data) memcpy(data, query->data, min(data_size, query->data_size));
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index e21c4e6507b..b6f2cf060d4 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1955,6 +1955,7 @@ struct wined3d_query
GLuint buffer_object; UINT64 *map_ptr; + bool poll_in_cs; };
HRESULT wined3d_query_gl_create(struct wined3d_device *device, enum wined3d_query_type type, void *parent,
This is mostly to enable polling queries from the application thread by removing the need to access the shared context.
Signed-off-by: Jan Sikorski jsikorski@codeweavers.com --- dlls/wined3d/context_vk.c | 65 ---------------------------------- dlls/wined3d/query.c | 45 ++++++++++++++++------- dlls/wined3d/wined3d_private.h | 23 ++---------- 3 files changed, 35 insertions(+), 98 deletions(-)
diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c index a3489c23f1d..dcb94eb7c1a 100644 --- a/dlls/wined3d/context_vk.c +++ b/dlls/wined3d/context_vk.c @@ -1577,7 +1577,6 @@ void wined3d_context_vk_cleanup(struct wined3d_context_vk *context_vk) wined3d_context_vk_destroy_query_pools(context_vk, &context_vk->free_pipeline_statistics_query_pools); wined3d_context_vk_destroy_query_pools(context_vk, &context_vk->free_stream_output_statistics_query_pools); wine_rb_destroy(&context_vk->bo_slab_available, wined3d_context_vk_destroy_bo_slab, context_vk); - heap_free(context_vk->pending_queries.queries); heap_free(context_vk->submitted.buffers); heap_free(context_vk->retired.objects);
@@ -1589,69 +1588,6 @@ void wined3d_context_vk_cleanup(struct wined3d_context_vk *context_vk) wined3d_context_cleanup(&context_vk->c); }
-void wined3d_context_vk_remove_pending_queries(struct wined3d_context_vk *context_vk, - struct wined3d_query_vk *query_vk) -{ - struct wined3d_pending_queries_vk *pending = &context_vk->pending_queries; - struct wined3d_pending_query_vk *p; - size_t i; - - pending->free_idx = ~(size_t)0; - for (i = pending->count; i; --i) - { - p = &pending->queries[i - 1]; - - if (p->query_vk) - { - if (p->query_vk != query_vk && !wined3d_query_vk_accumulate_data(p->query_vk, context_vk, &p->pool_idx)) - continue; - --p->query_vk->pending_count; - } - - if (i == pending->count) - { - --pending->count; - continue; - } - - p->query_vk = NULL; - p->pool_idx.pool_vk = NULL; - p->pool_idx.idx = pending->free_idx; - pending->free_idx = i - 1; - } -} - -void wined3d_context_vk_accumulate_pending_queries(struct wined3d_context_vk *context_vk) -{ - wined3d_context_vk_remove_pending_queries(context_vk, NULL); -} - -void wined3d_context_vk_add_pending_query(struct wined3d_context_vk *context_vk, struct wined3d_query_vk *query_vk) -{ - struct wined3d_pending_queries_vk *pending = &context_vk->pending_queries; - struct wined3d_pending_query_vk *p; - - if (pending->free_idx != ~(size_t)0) - { - p = &pending->queries[pending->free_idx]; - pending->free_idx = p->pool_idx.idx; - } - else - { - if (!wined3d_array_reserve((void **)&pending->queries, &pending->size, - pending->count + 1, sizeof(*pending->queries))) - { - ERR("Failed to allocate entry.\n"); - return; - } - p = &pending->queries[pending->count++]; - } - - p->query_vk = query_vk; - p->pool_idx = query_vk->pool_idx; - ++query_vk->pending_count; -} - VkCommandBuffer wined3d_context_vk_get_command_buffer(struct wined3d_context_vk *context_vk) { struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device); @@ -1701,7 +1637,6 @@ VkCommandBuffer wined3d_context_vk_get_command_buffer(struct wined3d_context_vk return buffer->vk_command_buffer = VK_NULL_HANDLE; }
- 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)) diff --git a/dlls/wined3d/query.c b/dlls/wined3d/query.c index 093b412bf18..7309b7a68df 100644 --- a/dlls/wined3d/query.c +++ b/dlls/wined3d/query.c @@ -1598,7 +1598,15 @@ void wined3d_query_vk_suspend(struct wined3d_query_vk *query_vk, struct wined3d_ VkCommandBuffer vk_command_buffer = context_vk->current_command_buffer.vk_command_buffer;
wined3d_query_vk_end(query_vk, context_vk, vk_command_buffer); - wined3d_context_vk_add_pending_query(context_vk, query_vk); + + if (!wined3d_array_reserve((void **)&query_vk->pending, &query_vk->pending_size, + query_vk->pending_count + 1, sizeof(*query_vk->pending))) + { + ERR("Failed to allocate entry.\n"); + return; + } + + query_vk->pending[query_vk->pending_count++] = query_vk->pool_idx; query_vk->pool_idx.pool_vk = NULL; query_vk->flags &= ~WINED3D_QUERY_VK_FLAG_ACTIVE; } @@ -1615,10 +1623,12 @@ static BOOL wined3d_query_vk_poll(struct wined3d_query *query, uint32_t flags) if (query_vk->command_buffer_id == context_vk->current_command_buffer.id) goto unavailable;
- if (query_vk->pending_count) - wined3d_context_vk_accumulate_pending_queries(context_vk); - if (query_vk->pending_count) - goto unavailable; + while (query_vk->pending_count) + { + if (!wined3d_query_vk_accumulate_data(query_vk, context_vk, &query_vk->pending[query_vk->pending_count - 1])) + goto unavailable; + query_vk->pending_count--; + }
/* If the query was suspended, and then ended before it was resumed, * there's no data to accumulate here. */ @@ -1635,6 +1645,17 @@ unavailable: return FALSE; }
+static void wined3d_query_vk_remove_pending_queries(struct wined3d_context_vk *context_vk, + struct wined3d_query_vk *query_vk) +{ + size_t i; + + for (i = 0; i < query_vk->pending_count; ++i) + wined3d_query_pool_vk_mark_complete(query_vk->pending[i].pool_vk, query_vk->pending[i].idx, context_vk); + + query_vk->pending_count = 0; +} + static BOOL wined3d_query_vk_issue(struct wined3d_query *query, uint32_t flags) { struct wined3d_device_vk *device_vk = wined3d_device_vk(query->device); @@ -1650,7 +1671,7 @@ static BOOL wined3d_query_vk_issue(struct wined3d_query *query, uint32_t flags) context_vk = wined3d_context_vk(context_acquire(&device_vk->d, NULL, 0));
if (query_vk->pending_count) - wined3d_context_vk_remove_pending_queries(context_vk, query_vk); + wined3d_query_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->flags & WINED3D_QUERY_VK_FLAG_STARTED) @@ -1732,12 +1753,12 @@ static void wined3d_query_vk_destroy(struct wined3d_query *query)
if (query_vk->flags & WINED3D_QUERY_VK_FLAG_STARTED) list_remove(&query_vk->entry); - if (query_vk->pending_count) - { - context_vk = wined3d_context_vk(context_acquire(query_vk->q.device, NULL, 0)); - wined3d_context_vk_remove_pending_queries(context_vk, query_vk); - context_release(&context_vk->c); - } + context_vk = wined3d_context_vk(context_acquire(query_vk->q.device, NULL, 0)); + 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); + context_release(&context_vk->c); + heap_free(query_vk->pending); heap_free(query_vk); }
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index b6f2cf060d4..d035b89a5e5 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -2086,7 +2086,8 @@ struct wined3d_query_vk uint8_t flags; uint64_t command_buffer_id; uint32_t control_flags; - size_t pending_count; + SIZE_T pending_count, pending_size; + struct wined3d_query_pool_idx_vk *pending; };
static inline struct wined3d_query_vk *wined3d_query_vk(struct wined3d_query *query) @@ -2550,20 +2551,6 @@ struct wined3d_shader_descriptor_writes_vk SIZE_T size, count; };
-struct wined3d_pending_query_vk -{ - struct wined3d_query_vk *query_vk; - struct wined3d_query_pool_idx_vk pool_idx; -}; - -struct wined3d_pending_queries_vk -{ - struct wined3d_pending_query_vk *queries; - SIZE_T free_idx; - SIZE_T size; - SIZE_T count; -}; - struct wined3d_context_vk { struct wined3d_context c; @@ -2619,7 +2606,6 @@ struct wined3d_context_vk
struct list render_pass_queries; struct list active_queries; - struct wined3d_pending_queries_vk pending_queries; struct list completed_query_pools; struct list free_occlusion_query_pools; struct list free_timestamp_query_pools; @@ -2638,9 +2624,6 @@ static inline struct wined3d_context_vk *wined3d_context_vk(struct wined3d_conte return CONTAINING_RECORD(context, struct wined3d_context_vk, c); }
-void wined3d_context_vk_accumulate_pending_queries(struct wined3d_context_vk *context_vk) DECLSPEC_HIDDEN; -void wined3d_context_vk_add_pending_query(struct wined3d_context_vk *context_vk, - struct wined3d_query_vk *query_vk) DECLSPEC_HIDDEN; bool wined3d_context_vk_allocate_query(struct wined3d_context_vk *context_vk, enum wined3d_query_type type, struct wined3d_query_pool_idx_vk *pool_idx) DECLSPEC_HIDDEN; VkDeviceMemory wined3d_context_vk_allocate_vram_chunk_memory(struct wined3d_context_vk *context_vk, @@ -2688,8 +2671,6 @@ void wined3d_context_vk_image_barrier(struct wined3d_context_vk *context_vk, HRESULT wined3d_context_vk_init(struct wined3d_context_vk *context_vk, struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN; void wined3d_context_vk_poll_command_buffers(struct wined3d_context_vk *context_vk) DECLSPEC_HIDDEN; -void wined3d_context_vk_remove_pending_queries(struct wined3d_context_vk *context_vk, - struct wined3d_query_vk *query_vk) DECLSPEC_HIDDEN; void wined3d_context_vk_submit_command_buffer(struct wined3d_context_vk *context_vk, unsigned int wait_semaphore_count, const VkSemaphore *wait_semaphores, const VkPipelineStageFlags *wait_stages, unsigned int signal_semaphore_count, const VkSemaphore *signal_semaphores) DECLSPEC_HIDDEN;
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
We want to avoid using the poll list, for occlusion queries especially, as in some games the number of occlusion queries can reach the hundreds. OpenGL backend already does this by using ARB_QUERY_BUFFER_OBJECT. We could mimic this in Vulkan too using compute shaders to accumulate pending queries, however, unlike with OpenGL, we can also just directly call vkGetQueryPoolResults() from the application's thread. A downside of the approach taken here is that Vulkan queries allocated to a wined3d_query are only released after the query is reused or destroyed. In principle, if this ever becomes a problem, it could be avoided by protecting the query pool with a mutex and releasing queries after reading the results.
Signed-off-by: Jan Sikorski jsikorski@codeweavers.com --- dlls/wined3d/query.c | 40 ++++++++++++---------------------- dlls/wined3d/wined3d_private.h | 4 +++- 2 files changed, 17 insertions(+), 27 deletions(-)
diff --git a/dlls/wined3d/query.c b/dlls/wined3d/query.c index 7309b7a68df..3a4a518fcfb 100644 --- a/dlls/wined3d/query.c +++ b/dlls/wined3d/query.c @@ -1460,11 +1460,10 @@ bool wined3d_query_pool_vk_init(struct wined3d_query_pool_vk *pool_vk, }
bool wined3d_query_vk_accumulate_data(struct wined3d_query_vk *query_vk, - struct wined3d_context_vk *context_vk, const struct wined3d_query_pool_idx_vk *pool_idx) + struct wined3d_device_vk *device_vk, const struct wined3d_query_pool_idx_vk *pool_idx) { - struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device); const struct wined3d_query_data_pipeline_statistics *ps_tmp; - const struct wined3d_vk_info *vk_info = context_vk->vk_info; + const struct wined3d_vk_info *vk_info = &device_vk->vk_info; struct wined3d_query_data_pipeline_statistics *ps_result; VkResult vr; union @@ -1487,9 +1486,6 @@ bool wined3d_query_vk_accumulate_data(struct wined3d_query_vk *query_vk, ERR("Failed to get event status, vr %s\n", wined3d_debug_vkresult(vr)); return false; } - - VK_CALL(vkDestroyEvent(device_vk->vk_device, pool_idx->pool_vk->vk_event, NULL)); - pool_idx->pool_vk->vk_event = VK_NULL_HANDLE; }
if ((vr = VK_CALL(vkGetQueryPoolResults(device_vk->vk_device, pool_idx->pool_vk->vk_query_pool, @@ -1502,8 +1498,6 @@ bool wined3d_query_vk_accumulate_data(struct wined3d_query_vk *query_vk, if (vr == VK_NOT_READY) return false;
- wined3d_query_pool_vk_mark_complete(pool_idx->pool_vk, pool_idx->idx, context_vk); - result = (void *)query_vk->q.data; switch (query_vk->q.type) { @@ -1613,35 +1607,27 @@ void wined3d_query_vk_suspend(struct wined3d_query_vk *query_vk, struct wined3d_
static BOOL wined3d_query_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; + unsigned int i;
- context_vk = wined3d_context_vk(context_acquire(query->device, NULL, 0)); + memset((void *)query->data, 0, query->data_size);
- 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) + if (query_vk->pool_idx.pool_vk && !wined3d_query_vk_accumulate_data(query_vk, device_vk, &query_vk->pool_idx)) goto unavailable;
- while (query_vk->pending_count) + for (i = 0; i < query_vk->pending_count; ++i) { - if (!wined3d_query_vk_accumulate_data(query_vk, context_vk, &query_vk->pending[query_vk->pending_count - 1])) + if (!wined3d_query_vk_accumulate_data(query_vk, device_vk, &query_vk->pending[i])) goto unavailable; - query_vk->pending_count--; }
- /* If the query was suspended, and then ended before it was resumed, - * there's no data to accumulate here. */ - if (query_vk->pool_idx.pool_vk && !wined3d_query_vk_accumulate_data(query_vk, context_vk, &query_vk->pool_idx)) - goto unavailable; - - query_vk->pool_idx.pool_vk = NULL; - context_release(&context_vk->c); - return TRUE;
unavailable: - context_release(&context_vk->c); + if ((flags & WINED3DGETDATA_FLUSH) && !query->device->cs->queries_flushed) + query->device->cs->c.ops->flush(&query->device->cs->c); + return FALSE; }
@@ -1672,7 +1658,6 @@ static BOOL wined3d_query_vk_issue(struct wined3d_query *query, uint32_t flags)
if (query_vk->pending_count) wined3d_query_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->flags & WINED3D_QUERY_VK_FLAG_STARTED) { @@ -1953,6 +1938,9 @@ HRESULT wined3d_query_vk_create(struct wined3d_device *device, enum wined3d_quer
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; + switch (type) { case WINED3D_QUERY_TYPE_OCCLUSION: diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index d035b89a5e5..a9e42e0cb16 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -2095,7 +2095,9 @@ static inline struct wined3d_query_vk *wined3d_query_vk(struct wined3d_query *qu return CONTAINING_RECORD(query, struct wined3d_query_vk, q); }
-bool wined3d_query_vk_accumulate_data(struct wined3d_query_vk *query_vk, struct wined3d_context_vk *context_vk, +struct wined3d_device_vk; + +bool wined3d_query_vk_accumulate_data(struct wined3d_query_vk *query_vk, struct wined3d_device_vk *device_vk, const struct wined3d_query_pool_idx_vk *pool_idx) DECLSPEC_HIDDEN; HRESULT wined3d_query_vk_create(struct wined3d_device *device, enum wined3d_query_type type, void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_query **query) DECLSPEC_HIDDEN;
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
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@codeweavers.com --- I thought event queries may be implicated in some of the hitching, but I haven't measured any concrete improvements. Still, it seems preferable to have this kind of implementation. --- 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,
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com