Allocate a fresh query index that does not need to be reset. Reset query pools at creation and when the render pass is ended.
Signed-off-by: Jan Sikorski jsikorski@codeweavers.com --- dlls/wined3d/context_vk.c | 19 +++++++++++--- dlls/wined3d/query.c | 47 ++++++++++++++++++++++++++-------- dlls/wined3d/wined3d_private.h | 6 ++++- 3 files changed, 57 insertions(+), 15 deletions(-)
diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c index 43b806a19b5..8b20fd3f779 100644 --- a/dlls/wined3d/context_vk.c +++ b/dlls/wined3d/context_vk.c @@ -1282,12 +1282,11 @@ VkRenderPass wined3d_context_vk_get_render_pass(struct wined3d_context_vk *conte
void wined3d_context_vk_end_current_render_pass(struct wined3d_context_vk *context_vk) { + VkCommandBuffer vk_command_buffer = context_vk->current_command_buffer.vk_command_buffer; const struct wined3d_vk_info *vk_info = context_vk->vk_info; - VkCommandBuffer vk_command_buffer;
if (context_vk->vk_render_pass) { - vk_command_buffer = context_vk->current_command_buffer.vk_command_buffer; VK_CALL(vkCmdEndRenderPass(vk_command_buffer)); context_vk->vk_render_pass = VK_NULL_HANDLE; VK_CALL(vkCmdPipelineBarrier(vk_command_buffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, @@ -1300,6 +1299,15 @@ void wined3d_context_vk_end_current_render_pass(struct wined3d_context_vk *conte context_vk->vk_framebuffer, context_vk->current_command_buffer.id); context_vk->vk_framebuffer = VK_NULL_HANDLE; } + + while (!list_empty(&context_vk->dirty_query_pools)) + { + struct wined3d_query_pool_vk *pool_vk = LIST_ENTRY(list_head(&context_vk->dirty_query_pools), + struct wined3d_query_pool_vk, dirty_entry); + list_remove(&pool_vk->dirty_entry); + list_init(&pool_vk->dirty_entry); + wined3d_query_pool_vk_reset(pool_vk, context_vk, vk_command_buffer); + } }
static void wined3d_context_vk_destroy_render_pass(struct wine_rb_entry *entry, void *ctx) @@ -1330,6 +1338,7 @@ static void wined3d_context_vk_destroy_query_pools(struct wined3d_context_vk *co 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) { + const struct wined3d_vk_info *vk_info = context_vk->vk_info; struct wined3d_query_pool_vk *pool_vk, *entry; struct list *free_pools; size_t idx; @@ -1376,6 +1385,10 @@ bool wined3d_context_vk_allocate_query(struct wined3d_context_vk *context_vk, return false; }
+ wined3d_context_vk_end_current_render_pass(context_vk); + VK_CALL(vkCmdResetQueryPool(wined3d_context_vk_get_command_buffer(context_vk), + pool_vk->vk_query_pool, 0, WINED3D_QUERY_POOL_SIZE)); + if (!wined3d_query_pool_vk_allocate_query(pool_vk, &idx)) { wined3d_query_pool_vk_cleanup(pool_vk, context_vk); @@ -1449,7 +1462,6 @@ void wined3d_context_vk_remove_pending_queries(struct wined3d_context_vk *contex { if (p->query_vk != query_vk && !wined3d_query_vk_accumulate_data(p->query_vk, context_vk, &p->pool_idx)) continue; - wined3d_query_pool_vk_free_query(p->pool_idx.pool_vk, p->pool_idx.idx); --p->query_vk->pending_count; }
@@ -3390,6 +3402,7 @@ HRESULT wined3d_context_vk_init(struct wined3d_context_vk *context_vk, struct wi wined3d_context_vk_init_graphics_pipeline_key(context_vk);
list_init(&context_vk->active_queries); + list_init(&context_vk->dirty_query_pools); list_init(&context_vk->free_occlusion_query_pools); list_init(&context_vk->free_timestamp_query_pools); list_init(&context_vk->free_pipeline_statistics_query_pools); diff --git a/dlls/wined3d/query.c b/dlls/wined3d/query.c index 81f5ba7d0d7..8c135f09c0a 100644 --- a/dlls/wined3d/query.c +++ b/dlls/wined3d/query.c @@ -1348,12 +1348,12 @@ HRESULT wined3d_query_gl_create(struct wined3d_device *device, enum wined3d_quer } }
-void wined3d_query_pool_vk_free_query(struct wined3d_query_pool_vk *pool_vk, size_t idx) +static void wined3d_query_pool_vk_mark_complete(struct wined3d_query_pool_vk *pool_vk, size_t idx, + struct wined3d_context_vk *context_vk) { - wined3d_bitmap_clear(pool_vk->allocated, idx); - - if (list_empty(&pool_vk->entry)) - list_add_tail(pool_vk->free_list, &pool_vk->entry); + wined3d_bitmap_set(pool_vk->completed, idx); + if (list_empty(&pool_vk->dirty_entry)) + list_add_tail(&context_vk->dirty_query_pools, &pool_vk->dirty_entry); }
bool wined3d_query_pool_vk_allocate_query(struct wined3d_query_pool_vk *pool_vk, size_t *idx) @@ -1372,6 +1372,29 @@ void wined3d_query_pool_vk_cleanup(struct wined3d_query_pool_vk *pool_vk, struct
VK_CALL(vkDestroyQueryPool(device_vk->vk_device, pool_vk->vk_query_pool, NULL)); list_remove(&pool_vk->entry); + list_remove(&pool_vk->dirty_entry); +} + +void wined3d_query_pool_vk_reset(struct wined3d_query_pool_vk *pool_vk, struct wined3d_context_vk *context_vk, + VkCommandBuffer vk_command_buffer) +{ + const struct wined3d_vk_info *vk_info = context_vk->vk_info; + unsigned int start = 0, idx; + struct wined3d_range range; + + for (;;) + { + if (!wined3d_bitmap_get_range(pool_vk->completed, WINED3D_QUERY_POOL_SIZE, start, &range)) + break; + + VK_CALL(vkCmdResetQueryPool(vk_command_buffer, pool_vk->vk_query_pool, range.offset, range.size)); + start = range.offset + range.size; + for (idx = range.offset; idx < start; ++idx) + wined3d_bitmap_clear(pool_vk->allocated, idx); + } + memset(pool_vk->completed, 0, sizeof(pool_vk->completed)); + if (list_empty(&pool_vk->entry)) + list_add_tail(pool_vk->free_list, &pool_vk->entry); }
bool wined3d_query_pool_vk_init(struct wined3d_query_pool_vk *pool_vk, @@ -1383,6 +1406,7 @@ bool wined3d_query_pool_vk_init(struct wined3d_query_pool_vk *pool_vk, VkResult vr;
list_init(&pool_vk->entry); + list_init(&pool_vk->dirty_entry); pool_vk->free_list = free_pools;
pool_info.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO; @@ -1468,6 +1492,8 @@ 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) { @@ -1519,8 +1545,7 @@ static void wined3d_query_vk_begin(struct wined3d_query_vk *query_vk, struct wined3d_query_pool_vk *pool_vk; size_t idx;
- if (!query_vk->pool_idx.pool_vk - && !wined3d_context_vk_allocate_query(context_vk, query_vk->q.type, &query_vk->pool_idx)) + if (!wined3d_context_vk_allocate_query(context_vk, query_vk->q.type, &query_vk->pool_idx)) { ERR("Failed to allocate new query.\n"); return; @@ -1528,7 +1553,6 @@ static void wined3d_query_vk_begin(struct wined3d_query_vk *query_vk, pool_vk = query_vk->pool_idx.pool_vk; idx = query_vk->pool_idx.idx;
- VK_CALL(vkCmdResetQueryPool(vk_command_buffer, pool_vk->vk_query_pool, idx, 1)); if (query_vk->q.type >= WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM1 && query_vk->q.type <= WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM3) VK_CALL(vkCmdBeginQueryIndexedEXT(vk_command_buffer, pool_vk->vk_query_pool, idx, @@ -1599,6 +1623,7 @@ static BOOL wined3d_query_vk_poll(struct wined3d_query *query, uint32_t flags) 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; @@ -1622,7 +1647,6 @@ 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));
- wined3d_context_vk_end_current_render_pass(context_vk); list_remove(&query_vk->entry); if (query_vk->pending_count) wined3d_context_vk_remove_pending_queries(context_vk, query_vk); @@ -1633,6 +1657,9 @@ static BOOL wined3d_query_vk_issue(struct wined3d_query *query, uint32_t flags) wined3d_query_vk_end(query_vk, context_vk, vk_command_buffer); list_remove(&query_vk->entry); } + 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); wined3d_query_vk_begin(query_vk, context_vk, vk_command_buffer); list_add_head(&context_vk->active_queries, &query_vk->entry); query_vk->started = true; @@ -1669,8 +1696,6 @@ static void wined3d_query_vk_destroy(struct wined3d_query *query) wined3d_context_vk_remove_pending_queries(context_vk, query_vk); context_release(&context_vk->c); } - if (query_vk->pool_idx.pool_vk) - wined3d_query_pool_vk_free_query(query_vk->pool_idx.pool_vk, query_vk->pool_idx.idx); heap_free(query_vk); }
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 84dad38f0c9..70691df7246 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -2023,16 +2023,19 @@ struct wined3d_pipeline_statistics_query struct wined3d_query_pool_vk { struct list entry; + struct list dirty_entry;
struct list *free_list; VkQueryPool vk_query_pool; uint32_t allocated[WINED3D_BITMAP_SIZE(WINED3D_QUERY_POOL_SIZE)]; + uint32_t completed[WINED3D_BITMAP_SIZE(WINED3D_QUERY_POOL_SIZE)]; };
bool wined3d_query_pool_vk_allocate_query(struct wined3d_query_pool_vk *pool_vk, size_t *idx) DECLSPEC_HIDDEN; void wined3d_query_pool_vk_cleanup(struct wined3d_query_pool_vk *pool_vk, struct wined3d_context_vk *context_vk) DECLSPEC_HIDDEN; -void wined3d_query_pool_vk_free_query(struct wined3d_query_pool_vk *pool_vk, size_t idx) DECLSPEC_HIDDEN; +void wined3d_query_pool_vk_reset(struct wined3d_query_pool_vk *pool_vk, struct wined3d_context_vk *context_vk, + VkCommandBuffer vk_command_buffer) DECLSPEC_HIDDEN; bool wined3d_query_pool_vk_init(struct wined3d_query_pool_vk *pool_vk, struct wined3d_context_vk *context_vk, enum wined3d_query_type type, struct list *free_pools) DECLSPEC_HIDDEN;
@@ -2574,6 +2577,7 @@ struct wined3d_context_vk
struct list active_queries; struct wined3d_pending_queries_vk pending_queries; + struct list dirty_query_pools; struct list free_occlusion_query_pools; struct list free_timestamp_query_pools; struct list free_pipeline_statistics_query_pools;
On Mon, 28 Jun 2021 at 15:38, Jan Sikorski jsikorski@codeweavers.com wrote:
Allocate a fresh query index that does not need to be reset. Reset query pools at creation and when the render pass is ended.
Signed-off-by: Jan Sikorski jsikorski@codeweavers.com
dlls/wined3d/context_vk.c | 19 +++++++++++--- dlls/wined3d/query.c | 47 ++++++++++++++++++++++++++-------- dlls/wined3d/wined3d_private.h | 6 ++++- 3 files changed, 57 insertions(+), 15 deletions(-)
Seems fine, just some nit-picks:
@@ -1300,6 +1299,15 @@ void wined3d_context_vk_end_current_render_pass(struct wined3d_context_vk *conte context_vk->vk_framebuffer, context_vk->current_command_buffer.id); context_vk->vk_framebuffer = VK_NULL_HANDLE; }
- while (!list_empty(&context_vk->dirty_query_pools))
- {
struct wined3d_query_pool_vk *pool_vk = LIST_ENTRY(list_head(&context_vk->dirty_query_pools),
struct wined3d_query_pool_vk, dirty_entry);
list_remove(&pool_vk->dirty_entry);
list_init(&pool_vk->dirty_entry);
wined3d_query_pool_vk_reset(pool_vk, context_vk, vk_command_buffer);
- }
}
We'd normally use LIST_FOR_EACH_ENTRY_SAFE here.
@@ -2023,16 +2023,19 @@ struct wined3d_pipeline_statistics_query struct wined3d_query_pool_vk { struct list entry;
- struct list dirty_entry;
[...]
@@ -2574,6 +2577,7 @@ struct wined3d_context_vk
struct list active_queries; struct wined3d_pending_queries_vk pending_queries;
- struct list dirty_query_pools; struct list free_occlusion_query_pools; struct list free_timestamp_query_pools; struct list free_pipeline_statistics_query_pools;
Perhaps "completed" would be slightly more descriptive (and consistent) than "dirty". It may also be worth adding a small comment explaining why we don't just call vkCmdResetQueryPool() from wined3d_query_vk_begin(), perhaps in wined3d_query_pool_vk_mark_complete() or wined3d_query_pool_vk_reset().