wined3d: Track queries started inside/outside of a render pass separately.

Signed-off-by: Jan Sikorski <jsikorski@codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jan Sikorski 2021-07-28 13:42:13 +02:00 committed by Alexandre Julliard
parent 626afcad71
commit ba67dfe8c8
3 changed files with 83 additions and 20 deletions

View file

@ -1285,13 +1285,26 @@ void wined3d_context_vk_end_current_render_pass(struct wined3d_context_vk *conte
VkCommandBuffer vk_command_buffer = context_vk->current_command_buffer.vk_command_buffer;
const struct wined3d_vk_info *vk_info = context_vk->vk_info;
struct wined3d_query_pool_vk *pool_vk, *pool_vk_next;
struct wined3d_query_vk *query_vk;
if (context_vk->vk_render_pass)
{
LIST_FOR_EACH_ENTRY(query_vk, &context_vk->render_pass_queries, struct wined3d_query_vk, entry)
wined3d_query_vk_suspend(query_vk, context_vk);
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,
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, NULL, 0, NULL, 0, NULL));
LIST_FOR_EACH_ENTRY(query_vk, &context_vk->render_pass_queries, struct wined3d_query_vk, entry)
{
if (!wined3d_context_vk_allocate_query(context_vk, query_vk->q.type, &query_vk->pool_idx))
{
ERR("Failed to allocate new query.\n");
break;
}
}
}
if (context_vk->vk_framebuffer)
@ -1561,6 +1574,12 @@ VkCommandBuffer wined3d_context_vk_get_command_buffer(struct wined3d_context_vk
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))
{
ERR("Failed to allocate new query.\n");
break;
}
wined3d_query_vk_resume(query_vk, context_vk);
}
@ -1594,12 +1613,11 @@ void wined3d_context_vk_submit_command_buffer(struct wined3d_context_vk *context
TRACE("Submitting command buffer %p with id 0x%s.\n",
buffer->vk_command_buffer, wine_dbgstr_longlong(buffer->id));
LIST_FOR_EACH_ENTRY(query_vk, &context_vk->active_queries, struct wined3d_query_vk, entry)
{
wined3d_query_vk_suspend(query_vk, context_vk);
}
wined3d_context_vk_end_current_render_pass(context_vk);
LIST_FOR_EACH_ENTRY(query_vk, &context_vk->active_queries, struct wined3d_query_vk, entry)
wined3d_query_vk_suspend(query_vk, context_vk);
context_vk->graphics.vk_pipeline = VK_NULL_HANDLE;
context_vk->update_compute_pipeline = 1;
context_vk->update_stream_output = 1;
@ -2323,6 +2341,7 @@ static bool wined3d_context_vk_begin_render_pass(struct wined3d_context_vk *cont
struct wined3d_rendertarget_view_vk *rtv_vk;
struct wined3d_rendertarget_view *view;
const VkPhysicalDeviceLimits *limits;
struct wined3d_query_vk *query_vk;
VkRenderPassBeginInfo begin_info;
unsigned int attachment_count, i;
VkFramebufferCreateInfo fb_desc;
@ -2409,6 +2428,8 @@ static bool wined3d_context_vk_begin_render_pass(struct wined3d_context_vk *cont
begin_info.pClearValues = NULL;
VK_CALL(vkCmdBeginRenderPass(vk_command_buffer, &begin_info, VK_SUBPASS_CONTENTS_INLINE));
LIST_FOR_EACH_ENTRY(query_vk, &context_vk->render_pass_queries, struct wined3d_query_vk, entry)
wined3d_query_vk_resume(query_vk, context_vk);
return true;
}
@ -3460,6 +3481,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->render_pass_queries);
list_init(&context_vk->active_queries);
list_init(&context_vk->completed_query_pools);
list_init(&context_vk->free_occlusion_query_pools);

View file

@ -1548,11 +1548,6 @@ static void wined3d_query_vk_begin(struct wined3d_query_vk *query_vk,
struct wined3d_query_pool_vk *pool_vk;
size_t 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;
}
pool_vk = query_vk->pool_idx.pool_vk;
idx = query_vk->pool_idx.idx;
@ -1588,6 +1583,7 @@ void wined3d_query_vk_resume(struct wined3d_query_vk *query_vk, struct wined3d_c
VkCommandBuffer vk_command_buffer = context_vk->current_command_buffer.vk_command_buffer;
wined3d_query_vk_begin(query_vk, context_vk, vk_command_buffer);
query_vk->flags |= WINED3D_QUERY_VK_FLAG_ACTIVE;
}
void wined3d_query_vk_suspend(struct wined3d_query_vk *query_vk, struct wined3d_context_vk *context_vk)
@ -1597,6 +1593,7 @@ void wined3d_query_vk_suspend(struct wined3d_query_vk *query_vk, struct wined3d_
wined3d_query_vk_end(query_vk, context_vk, vk_command_buffer);
wined3d_context_vk_add_pending_query(context_vk, query_vk);
query_vk->pool_idx.pool_vk = NULL;
query_vk->flags &= ~WINED3D_QUERY_VK_FLAG_ACTIVE;
}
static BOOL wined3d_query_vk_poll(struct wined3d_query *query, uint32_t flags)
@ -1655,30 +1652,69 @@ static BOOL wined3d_query_vk_issue(struct wined3d_query *query, uint32_t flags)
wined3d_context_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->started)
if (query_vk->flags & WINED3D_QUERY_VK_FLAG_STARTED)
{
wined3d_query_vk_end(query_vk, context_vk, vk_command_buffer);
if (query_vk->flags & WINED3D_QUERY_VK_FLAG_ACTIVE)
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;
if (!wined3d_context_vk_allocate_query(context_vk, query_vk->q.type, &query_vk->pool_idx))
{
ERR("Failed to allocate new query.\n");
return false;
}
/* A query need to either begin and end inside a single render pass,
* or begin and end ouside of a render pass. Occlusion queries, if issued
* ouside of a render pass, are queued up and only begun when a render
* pass is started, to avoid interrupting it when the query ends. */
if (context_vk->vk_render_pass)
{
wined3d_query_vk_begin(query_vk, context_vk, vk_command_buffer);
list_add_head(&context_vk->render_pass_queries, &query_vk->entry);
query_vk->flags |= WINED3D_QUERY_VK_FLAG_ACTIVE | WINED3D_QUERY_VK_FLAG_RENDER_PASS;
}
else if (query->type == WINED3D_QUERY_TYPE_OCCLUSION)
{
list_add_head(&context_vk->render_pass_queries, &query_vk->entry);
query_vk->flags |= WINED3D_QUERY_VK_FLAG_RENDER_PASS;
}
else
{
wined3d_query_vk_begin(query_vk, context_vk, vk_command_buffer);
list_add_head(&context_vk->active_queries, &query_vk->entry);
query_vk->flags |= WINED3D_QUERY_VK_FLAG_ACTIVE;
}
query_vk->flags |= WINED3D_QUERY_VK_FLAG_STARTED;
context_release(&context_vk->c);
}
if (flags & WINED3DISSUE_END && query_vk->started)
if (flags & WINED3DISSUE_END && query_vk->flags & WINED3D_QUERY_VK_FLAG_STARTED)
{
context_vk = wined3d_context_vk(context_acquire(&device_vk->d, NULL, 0));
/* If the query was already ended because the command buffer was
* flushed, we don't need to end it here. */
if ((vk_command_buffer = context_vk->current_command_buffer.vk_command_buffer))
* flushed or the render pass ended, we don't need to end it here. */
if (query_vk->flags & WINED3D_QUERY_VK_FLAG_ACTIVE)
{
vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk);
if (!(query_vk->flags & WINED3D_QUERY_VK_FLAG_RENDER_PASS))
wined3d_context_vk_end_current_render_pass(context_vk);
wined3d_query_vk_end(query_vk, context_vk, vk_command_buffer);
}
else if (query_vk->pool_idx.pool_vk)
{
/* It was queued, but never activated. */
wined3d_query_pool_vk_mark_complete(query_vk->pool_idx.pool_vk,
query_vk->pool_idx.idx, context_vk);
query_vk->pool_idx.pool_vk = NULL;
}
list_remove(&query_vk->entry);
query_vk->started = false;
query_vk->flags = 0;
poll = true;
context_release(&context_vk->c);

View file

@ -2050,13 +2050,17 @@ struct wined3d_query_pool_idx_vk
size_t idx;
};
#define WINED3D_QUERY_VK_FLAG_ACTIVE 0x00000001
#define WINED3D_QUERY_VK_FLAG_STARTED 0x00000002
#define WINED3D_QUERY_VK_FLAG_RENDER_PASS 0x00000004
struct wined3d_query_vk
{
struct wined3d_query q;
struct list entry;
struct wined3d_query_pool_idx_vk pool_idx;
bool started;
uint8_t flags;
uint64_t command_buffer_id;
uint32_t control_flags;
size_t pending_count;
@ -2580,6 +2584,7 @@ struct wined3d_context_vk
VkDeviceSize vk_so_offsets[WINED3D_MAX_STREAM_OUTPUT_BUFFERS];
struct wined3d_bo_vk vk_so_counter_bo;
struct list render_pass_queries;
struct list active_queries;
struct wined3d_pending_queries_vk pending_queries;
struct list completed_query_pools;