Poll with callbacks from application threads instead.
Signed-off-by: Jan Sikorski jsikorski@codeweavers.com --- dlls/wined3d/cs.c | 73 ++------- dlls/wined3d/query.c | 284 ++++++++++++++++++++++----------- dlls/wined3d/wined3d_private.h | 6 +- 3 files changed, 212 insertions(+), 151 deletions(-)
diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index 9bdd2c8ed98..fff79a6b021 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -2388,44 +2388,26 @@ void wined3d_cs_init_object(struct wined3d_cs *cs, void (*callback)(void *object wined3d_cs_emit_callback(cs, callback, object); }
-static void wined3d_cs_exec_query_issue(struct wined3d_cs *cs, const void *data) +void wined3d_cs_run_priority_callback(struct wined3d_cs *cs, void (*callback)(void *object), void *object) { - const struct wined3d_cs_query_issue *op = data; - struct wined3d_query *query = op->query; - BOOL poll; + struct wined3d_cs_callback *op;
- poll = query->query_ops->query_issue(query, op->flags); + op = wined3d_device_context_require_space(&cs->c, sizeof(*op), WINED3D_CS_QUEUE_MAP); + op->opcode = WINED3D_CS_OP_CALLBACK; + op->callback = callback; + op->object = object;
- if (!cs->thread) - return; + wined3d_device_context_submit(&cs->c, WINED3D_CS_QUEUE_MAP); + wined3d_cs_finish(cs, WINED3D_CS_QUEUE_MAP); +}
- if (poll && list_empty(&query->poll_list_entry)) - { - if (query->buffer_object) - InterlockedIncrement(&query->counter_retrieved); - else - list_add_tail(&cs->query_poll_list, &query->poll_list_entry); - return; - } +static void wined3d_cs_exec_query_issue(struct wined3d_cs *cs, const void *data) +{ + const struct wined3d_cs_query_issue *op = data; + struct wined3d_query *query = op->query;
- /* This can happen if occlusion queries are restarted. This discards the - * old result, since polling it could result in a GL error. */ - if ((op->flags & WINED3DISSUE_BEGIN) && !poll && !list_empty(&query->poll_list_entry)) - { - list_remove(&query->poll_list_entry); - list_init(&query->poll_list_entry); - InterlockedIncrement(&query->counter_retrieved); - return; - } + query->query_ops->query_issue(query, op->flags);
- /* This can happen when an occlusion query is ended without being started, - * in which case we don't want to poll, but still have to counter-balance - * the increment of the main counter. - * - * This can also happen if an event query is re-issued before the first - * fence was reached. In this case the query is already in the list and - * the poll function will check the new fence. We have to counter-balance - * the discarded increment. */ if (op->flags & WINED3DISSUE_END) InterlockedIncrement(&query->counter_retrieved); } @@ -3424,21 +3406,6 @@ static const struct wined3d_device_context_ops wined3d_cs_mt_ops = wined3d_cs_acquire_samplers, };
-static void poll_queries(struct wined3d_cs *cs) -{ - struct wined3d_query *query, *cursor; - - LIST_FOR_EACH_ENTRY_SAFE(query, cursor, &cs->query_poll_list, struct wined3d_query, poll_list_entry) - { - if (!query->query_ops->query_poll(query, 0)) - continue; - - list_remove(&query->poll_list_entry); - list_init(&query->poll_list_entry); - InterlockedIncrement(&query->counter_retrieved); - } -} - static void wined3d_cs_wait_event(struct wined3d_cs *cs) { InterlockedExchange(&cs->waiting_for_event, TRUE); @@ -3478,7 +3445,6 @@ static DWORD WINAPI wined3d_cs_run(void *ctx) struct wined3d_cs *cs = ctx; enum wined3d_cs_op opcode; HMODULE wined3d_module; - unsigned int poll = 0; LONG tail;
TRACE("Started.\n"); @@ -3487,25 +3453,16 @@ static DWORD WINAPI wined3d_cs_run(void *ctx) * thread freeing "cs" before the FreeLibraryAndExitThread() call. */ wined3d_module = cs->wined3d_module;
- list_init(&cs->query_poll_list); cs->thread_id = GetCurrentThreadId(); for (;;) { - if (++poll == WINED3D_CS_QUERY_POLL_INTERVAL) - { - wined3d_cs_command_lock(cs); - poll_queries(cs); - wined3d_cs_command_unlock(cs); - poll = 0; - } - queue = &cs->queue[WINED3D_CS_QUEUE_MAP]; if (wined3d_cs_queue_is_empty(cs, queue)) { queue = &cs->queue[WINED3D_CS_QUEUE_DEFAULT]; if (wined3d_cs_queue_is_empty(cs, queue)) { - if (++spin_count >= WINED3D_CS_SPIN_COUNT && list_empty(&cs->query_poll_list)) + if (++spin_count >= WINED3D_CS_SPIN_COUNT) wined3d_cs_wait_event(cs); continue; } diff --git a/dlls/wined3d/query.c b/dlls/wined3d/query.c index 1b38eb5e311..193f62cd265 100644 --- a/dlls/wined3d/query.c +++ b/dlls/wined3d/query.c @@ -472,23 +472,18 @@ 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 (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; - } - else if (!query->query_ops->query_poll(query, flags)) + if (query->counter_main != query->counter_retrieved + || (query->buffer_object && !wined3d_query_buffer_is_valid(query)) + || !query->query_ops->query_poll(query, flags)) { + 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 (data) memcpy(data, query->data, min(data_size, query->data_size));
@@ -511,20 +506,33 @@ HRESULT CDECL wined3d_query_issue(struct wined3d_query *query, DWORD flags) return WINED3D_OK; }
-static BOOL wined3d_occlusion_query_ops_poll(struct wined3d_query *query, DWORD flags) +struct wined3d_poll_callback_data { - struct wined3d_occlusion_query *oq = wined3d_occlusion_query_from_query(query); + struct wined3d_query *query; + DWORD flags; + BOOL result; +}; + +static void wined3d_occlusion_query_ops_poll_cs(void *object) +{ + struct wined3d_poll_callback_data *data = object; + struct wined3d_query *query = data->query; const struct wined3d_gl_info *gl_info; struct wined3d_context_gl *context_gl; + struct wined3d_occlusion_query *oq; + DWORD flags = data->flags; GLuint available;
TRACE("query %p, flags %#x.\n", query, flags);
+ oq = wined3d_occlusion_query_from_query(query); + if (!(context_gl = wined3d_context_gl_reacquire(oq->context_gl))) { FIXME("%p Wrong thread, returning 1.\n", query); oq->samples = 1; - return TRUE; + data->result = TRUE; + return; } gl_info = context_gl->gl_info;
@@ -540,40 +548,76 @@ static BOOL wined3d_occlusion_query_ops_poll(struct wined3d_query *query, DWORD checkGLcall("poll occlusion query"); context_release(&context_gl->c);
- return available; + data->result = available; }
-static BOOL wined3d_event_query_ops_poll(struct wined3d_query *query, DWORD flags) +static BOOL wined3d_occlusion_query_ops_poll(struct wined3d_query *query, DWORD flags) { - struct wined3d_event_query *event_query = wined3d_event_query_from_query(query); + 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_occlusion_query_ops_poll_cs, &data); + + return data.result; +} + +static void wined3d_event_query_ops_poll_cs(void *object) +{ + struct wined3d_poll_callback_data *data = object; + struct wined3d_query *query = data->query; + struct wined3d_event_query *event_query; enum wined3d_fence_result ret; + DWORD flags = data->flags;
TRACE("query %p, flags %#x.\n", query, flags);
+ event_query = wined3d_event_query_from_query(query); + ret = wined3d_fence_test(&event_query->fence, query->device, flags); switch (ret) { case WINED3D_FENCE_OK: case WINED3D_FENCE_NOT_STARTED: - return event_query->signalled = TRUE; + data->result = event_query->signalled = TRUE; + break;
case WINED3D_FENCE_WAITING: - return event_query->signalled = FALSE; + data->result = event_query->signalled = FALSE; + break;
case WINED3D_FENCE_WRONG_THREAD: FIXME("(%p) Wrong thread, reporting GPU idle.\n", query); - return event_query->signalled = TRUE; + data->result = event_query->signalled = TRUE; + break;
case WINED3D_FENCE_ERROR: ERR("The GL event query failed.\n"); - return event_query->signalled = TRUE; + data->result = event_query->signalled = TRUE; + break;
default: ERR("Unexpected wined3d_event_query_test result %#x.\n", ret); - return event_query->signalled = TRUE; + data->result = event_query->signalled = TRUE; + break; } }
+static BOOL wined3d_event_query_ops_poll(struct wined3d_query *query, DWORD 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_event_query_ops_poll_cs, &data); + + return data.result; +} + void * CDECL wined3d_query_get_parent(const struct wined3d_query *query) { TRACE("query %p.\n", query); @@ -588,7 +632,7 @@ enum wined3d_query_type CDECL wined3d_query_get_type(const struct wined3d_query return query->type; }
-static BOOL wined3d_event_query_ops_issue(struct wined3d_query *query, DWORD flags) +static void wined3d_event_query_ops_issue(struct wined3d_query *query, DWORD flags) { TRACE("query %p, flags %#x.\n", query, flags);
@@ -597,24 +641,20 @@ static BOOL wined3d_event_query_ops_issue(struct wined3d_query *query, DWORD fla struct wined3d_event_query *event_query = wined3d_event_query_from_query(query);
wined3d_fence_issue(&event_query->fence, query->device); - return TRUE; } else if (flags & WINED3DISSUE_BEGIN) { /* Started implicitly at query creation. */ ERR("Event query issued with START flag - what to do?\n"); } - - return FALSE; }
-static BOOL wined3d_occlusion_query_ops_issue(struct wined3d_query *query, DWORD flags) +static void wined3d_occlusion_query_ops_issue(struct wined3d_query *query, DWORD flags) { struct wined3d_occlusion_query *oq = wined3d_occlusion_query_from_query(query); struct wined3d_device *device = query->device; const struct wined3d_gl_info *gl_info; struct wined3d_context_gl *context_gl; - BOOL poll = FALSE;
TRACE("query %p, flags %#x.\n", query, flags);
@@ -668,7 +708,6 @@ static BOOL wined3d_occlusion_query_ops_issue(struct wined3d_query *query, DWORD wined3d_query_buffer_queue_result(context_gl, query, oq->id);
context_release(&context_gl->c); - poll = TRUE; } else { @@ -677,25 +716,29 @@ static BOOL wined3d_occlusion_query_ops_issue(struct wined3d_query *query, DWORD } oq->started = FALSE; } - - return poll; }
-static BOOL wined3d_timestamp_query_ops_poll(struct wined3d_query *query, DWORD flags) +static void wined3d_timestamp_query_ops_poll_cs(void *object) { - struct wined3d_timestamp_query *tq = wined3d_timestamp_query_from_query(query); - const struct wined3d_gl_info *gl_info; + struct wined3d_poll_callback_data *data = object; + struct wined3d_query *query = data->query; struct wined3d_context_gl *context_gl; + const struct wined3d_gl_info *gl_info; + struct wined3d_timestamp_query *tq; + DWORD flags = data->flags; GLuint64 timestamp; GLuint available;
TRACE("query %p, flags %#x.\n", query, flags);
+ tq = wined3d_timestamp_query_from_query(query); + if (!(context_gl = wined3d_context_gl_reacquire(tq->context_gl))) { FIXME("%p Wrong thread, returning 1.\n", query); tq->timestamp = 1; - return TRUE; + data->result = TRUE; + return; } gl_info = context_gl->gl_info;
@@ -712,11 +755,23 @@ static BOOL wined3d_timestamp_query_ops_poll(struct wined3d_query *query, DWORD }
context_release(&context_gl->c); + data->result = available; +} + +static BOOL wined3d_timestamp_query_ops_poll(struct wined3d_query *query, DWORD flags) +{ + struct wined3d_cs *cs = query->device->cs; + struct wined3d_poll_callback_data data;
- return available; + data.query = query; + data.flags = flags; + + wined3d_cs_run_priority_callback(cs, wined3d_timestamp_query_ops_poll_cs, &data); + + return data.result; }
-static BOOL wined3d_timestamp_query_ops_issue(struct wined3d_query *query, DWORD flags) +static void wined3d_timestamp_query_ops_issue(struct wined3d_query *query, DWORD flags) { struct wined3d_timestamp_query *tq = wined3d_timestamp_query_from_query(query); const struct wined3d_gl_info *gl_info; @@ -738,11 +793,7 @@ static BOOL wined3d_timestamp_query_ops_issue(struct wined3d_query *query, DWORD GL_EXTCALL(glQueryCounter(tq->id, GL_TIMESTAMP)); checkGLcall("glQueryCounter()"); context_release(&context_gl->c); - - return TRUE; } - - return FALSE; }
static BOOL wined3d_timestamp_disjoint_query_ops_poll(struct wined3d_query *query, DWORD flags) @@ -752,27 +803,31 @@ static BOOL wined3d_timestamp_disjoint_query_ops_poll(struct wined3d_query *quer return TRUE; }
-static BOOL wined3d_timestamp_disjoint_query_ops_issue(struct wined3d_query *query, DWORD flags) +static void wined3d_timestamp_disjoint_query_ops_issue(struct wined3d_query *query, DWORD flags) { TRACE("query %p, flags %#x.\n", query, flags); - - return FALSE; }
-static BOOL wined3d_so_statistics_query_ops_poll(struct wined3d_query *query, DWORD flags) +static void wined3d_so_statistics_query_ops_poll_cs(void *object) { - struct wined3d_so_statistics_query *pq = wined3d_so_statistics_query_from_query(query); GLuint written_available, generated_available; - const struct wined3d_gl_info *gl_info; + struct wined3d_poll_callback_data *data = object; + struct wined3d_query *query = data->query; + struct wined3d_so_statistics_query *pq; struct wined3d_context_gl *context_gl; + const struct wined3d_gl_info *gl_info; + DWORD flags = data->flags;
TRACE("query %p, flags %#x.\n", query, flags);
+ pq = wined3d_so_statistics_query_from_query(query); + if (!(context_gl = wined3d_context_gl_reacquire(pq->context_gl))) { FIXME("%p Wrong thread, returning 0 primitives.\n", query); memset(&pq->statistics, 0, sizeof(pq->statistics)); - return TRUE; + data->result = TRUE; + return; } gl_info = context_gl->gl_info;
@@ -794,7 +849,20 @@ static BOOL wined3d_so_statistics_query_ops_poll(struct wined3d_query *query, DW checkGLcall("poll SO statistics query"); context_release(&context_gl->c);
- return written_available && generated_available; + data->result = written_available && generated_available; +} + +static BOOL wined3d_so_statistics_query_ops_poll(struct wined3d_query *query, DWORD 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_so_statistics_query_ops_poll_cs, &data); + + return data.result; }
static void wined3d_so_statistics_query_end(struct wined3d_so_statistics_query *query, @@ -815,13 +883,12 @@ static void wined3d_so_statistics_query_end(struct wined3d_so_statistics_query * checkGLcall("end query"); }
-static BOOL wined3d_so_statistics_query_ops_issue(struct wined3d_query *query, DWORD flags) +static void wined3d_so_statistics_query_ops_issue(struct wined3d_query *query, DWORD flags) { struct wined3d_so_statistics_query *pq = wined3d_so_statistics_query_from_query(query); struct wined3d_device *device = query->device; const struct wined3d_gl_info *gl_info; struct wined3d_context_gl *context_gl; - BOOL poll = FALSE;
TRACE("query %p, flags %#x.\n", query, flags);
@@ -878,7 +945,6 @@ static BOOL wined3d_so_statistics_query_ops_issue(struct wined3d_query *query, D wined3d_so_statistics_query_end(pq, context_gl);
context_release(&context_gl->c); - poll = TRUE; } else { @@ -887,25 +953,29 @@ static BOOL wined3d_so_statistics_query_ops_issue(struct wined3d_query *query, D } pq->started = FALSE; } - - return poll; }
-static BOOL wined3d_pipeline_query_ops_poll(struct wined3d_query *query, DWORD flags) +static void wined3d_pipeline_query_ops_poll_cs(void *object) { - struct wined3d_pipeline_statistics_query *pq = wined3d_pipeline_statistics_query_from_query(query); + struct wined3d_pipeline_statistics_query *pq; + struct wined3d_poll_callback_data *data = object; + struct wined3d_query *query = data->query; const struct wined3d_gl_info *gl_info; struct wined3d_context_gl *context_gl; + DWORD flags = data->flags; GLuint available; int i;
TRACE("query %p, flags %#x.\n", query, flags);
+ pq = wined3d_pipeline_statistics_query_from_query(query); + if (!(context_gl = wined3d_context_gl_reacquire(pq->context_gl))) { FIXME("%p Wrong thread.\n", query); memset(&pq->statistics, 0, sizeof(pq->statistics)); - return TRUE; + data->result = TRUE; + return; } gl_info = context_gl->gl_info;
@@ -933,7 +1003,20 @@ static BOOL wined3d_pipeline_query_ops_poll(struct wined3d_query *query, DWORD f
checkGLcall("poll pipeline statistics query"); context_release(&context_gl->c); - return available; + data->result = available; +} + +static BOOL wined3d_pipeline_query_ops_poll(struct wined3d_query *query, DWORD 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_pipeline_query_ops_poll_cs, &data); + + return data.result; }
static void wined3d_pipeline_statistics_query_end(struct wined3d_pipeline_statistics_query *query, @@ -955,13 +1038,12 @@ static void wined3d_pipeline_statistics_query_end(struct wined3d_pipeline_statis checkGLcall("end query"); }
-static BOOL wined3d_pipeline_query_ops_issue(struct wined3d_query *query, DWORD flags) +static void wined3d_pipeline_query_ops_issue(struct wined3d_query *query, DWORD flags) { struct wined3d_pipeline_statistics_query *pq = wined3d_pipeline_statistics_query_from_query(query); struct wined3d_device *device = query->device; const struct wined3d_gl_info *gl_info; struct wined3d_context_gl *context_gl; - BOOL poll = FALSE;
TRACE("query %p, flags %#x.\n", query, flags);
@@ -1014,7 +1096,6 @@ static BOOL wined3d_pipeline_query_ops_issue(struct wined3d_query *query, DWORD { wined3d_pipeline_statistics_query_end(pq, context_gl); context_release(&context_gl->c); - poll = TRUE; } else { @@ -1023,8 +1104,6 @@ static BOOL wined3d_pipeline_query_ops_issue(struct wined3d_query *query, DWORD } pq->started = FALSE; } - - return poll; }
static void wined3d_event_query_ops_destroy(struct wined3d_query *query) @@ -1612,10 +1691,15 @@ void wined3d_query_vk_suspend(struct wined3d_query_vk *query_vk, struct wined3d_ query_vk->flags &= ~WINED3D_QUERY_VK_FLAG_ACTIVE; }
-static BOOL wined3d_query_vk_poll(struct wined3d_query *query, uint32_t flags) +static void wined3d_query_vk_poll_cs(void *object) { - struct wined3d_query_vk *query_vk = wined3d_query_vk(query); + 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; + + query_vk = wined3d_query_vk(query);
context_vk = wined3d_context_vk(context_acquire(query->device, NULL, 0));
@@ -1642,20 +1726,33 @@ static BOOL wined3d_query_vk_poll(struct wined3d_query *query, uint32_t flags) query_vk->pool_idx.pool_vk = NULL; context_release(&context_vk->c);
- return TRUE; + data->result = TRUE; + return;
unavailable: context_release(&context_vk->c); - return FALSE; + data->result = FALSE; }
-static BOOL wined3d_query_vk_issue(struct wined3d_query *query, uint32_t flags) +static BOOL wined3d_query_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_vk_poll_cs, &data); + + return data.result; +} + +static void wined3d_query_vk_issue(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; VkCommandBuffer vk_command_buffer; - bool poll = false;
TRACE("query %p, flags %#x.\n", query, flags);
@@ -1680,7 +1777,7 @@ static BOOL wined3d_query_vk_issue(struct wined3d_query *query, uint32_t flags) 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; + return; }
/* A query needs to either begin and end inside a single render pass, @@ -1730,12 +1827,9 @@ static BOOL wined3d_query_vk_issue(struct wined3d_query *query, uint32_t flags) } list_remove(&query_vk->entry); query_vk->flags = 0; - poll = true;
context_release(&context_vk->c); } - - return poll; }
static void wined3d_query_vk_destroy(struct wined3d_query *query) @@ -1761,12 +1855,16 @@ static const struct wined3d_query_ops wined3d_query_vk_ops = .query_destroy = wined3d_query_vk_destroy, };
-static BOOL wined3d_query_event_vk_poll(struct wined3d_query *query, uint32_t flags) +static void wined3d_query_event_vk_poll_cs(void *object) { - struct wined3d_query_vk *query_vk = wined3d_query_vk(query); + 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; @@ -1775,7 +1873,8 @@ static BOOL wined3d_query_event_vk_poll(struct wined3d_query *query, uint32_t fl if (query_vk->command_buffer_id == context_vk->current_command_buffer.id) { context_release(&context_vk->c); - return *signalled = FALSE; + data->result = *signalled = FALSE; + return; }
if (query_vk->command_buffer_id > context_vk->completed_command_buffer_id) @@ -1784,10 +1883,23 @@ static BOOL wined3d_query_event_vk_poll(struct wined3d_query *query, uint32_t fl
context_release(&context_vk->c);
- return *signalled; + 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); + + return data.result; }
-static BOOL wined3d_query_event_vk_issue(struct wined3d_query *query, uint32_t flags) +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); struct wined3d_query_vk *query_vk = wined3d_query_vk(query); @@ -1808,11 +1920,7 @@ static BOOL wined3d_query_event_vk_issue(struct wined3d_query *query, uint32_t f if (!context_vk->current_command_buffer.vk_command_buffer) --query_vk->command_buffer_id; context_release(&context_vk->c); - - return TRUE; } - - return FALSE; }
static const struct wined3d_query_ops wined3d_query_event_vk_ops = @@ -1822,7 +1930,7 @@ static const struct wined3d_query_ops wined3d_query_event_vk_ops = .query_destroy = wined3d_query_vk_destroy, };
-static BOOL wined3d_query_timestamp_vk_issue(struct wined3d_query *query, uint32_t flags) +static void wined3d_query_timestamp_vk_issue(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); @@ -1846,18 +1954,14 @@ static BOOL wined3d_query_timestamp_vk_issue(struct wined3d_query *query, uint32 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; + return; } VK_CALL(vkCmdWriteTimestamp(command_buffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, query_vk->pool_idx.pool_vk->vk_query_pool, query_vk->pool_idx.idx)); wined3d_context_vk_reference_query(context_vk, query_vk);
context_release(&context_vk->c); - - return TRUE; } - - return FALSE; }
static const struct wined3d_query_ops wined3d_query_timestamp_vk_ops = diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 79b02c2448d..6b885036260 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1952,7 +1952,7 @@ enum wined3d_query_state struct wined3d_query_ops { BOOL (*query_poll)(struct wined3d_query *query, DWORD flags); - BOOL (*query_issue)(struct wined3d_query *query, DWORD flags); + void (*query_issue)(struct wined3d_query *query, DWORD flags); void (*query_destroy)(struct wined3d_query *query); };
@@ -4823,7 +4823,6 @@ enum wined3d_push_constants WINED3D_PUSH_CONSTANTS_PS_B, };
-#define WINED3D_CS_QUERY_POLL_INTERVAL 10u #define WINED3D_CS_QUEUE_SIZE 0x100000u #define WINED3D_CS_SPIN_COUNT 10000000u
@@ -4879,7 +4878,6 @@ struct wined3d_cs struct wined3d_cs_queue queue[WINED3D_CS_QUEUE_COUNT]; size_t data_size, start, end; void *data; - struct list query_poll_list; BOOL queries_flushed;
HANDLE event; @@ -4920,6 +4918,8 @@ void wined3d_cs_emit_set_render_state(struct wined3d_cs *cs, void wined3d_cs_emit_unload_resource(struct wined3d_cs *cs, struct wined3d_resource *resource) DECLSPEC_HIDDEN; void wined3d_cs_init_object(struct wined3d_cs *cs, void (*callback)(void *object), void *object) DECLSPEC_HIDDEN; +void wined3d_cs_run_priority_callback(struct wined3d_cs *cs, void (*callback)(void *object), + void *object) DECLSPEC_HIDDEN;
static inline void wined3d_cs_finish(struct wined3d_cs *cs, enum wined3d_cs_queue_id queue_id) {
Signed-off-by: Jan Sikorski jsikorski@codeweavers.com --- dlls/wined3d/context_vk.c | 64 ----------------- dlls/wined3d/query.c | 121 ++++++++++++--------------------- dlls/wined3d/wined3d_private.h | 12 ++-- 3 files changed, 48 insertions(+), 149 deletions(-)
diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c index ec3554ddc30..dce78e1bc43 100644 --- a/dlls/wined3d/context_vk.c +++ b/dlls/wined3d/context_vk.c @@ -1524,69 +1524,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); @@ -1636,7 +1573,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 193f62cd265..6cfa5d73da0 100644 --- a/dlls/wined3d/query.c +++ b/dlls/wined3d/query.c @@ -1432,26 +1432,12 @@ HRESULT wined3d_query_gl_create(struct wined3d_device *device, enum wined3d_quer static void wined3d_query_pool_vk_mark_complete(struct wined3d_query_pool_vk *pool_vk, size_t idx, struct wined3d_context_vk *context_vk) { - const struct wined3d_vk_info *vk_info = context_vk->vk_info; - - if (vk_info->supported[WINED3D_VK_EXT_HOST_QUERY_RESET]) - { - VK_CALL(vkResetQueryPoolEXT(wined3d_device_vk(context_vk->c.device)->vk_device, - pool_vk->vk_query_pool, idx, 1)); - - wined3d_bitmap_clear(pool_vk->allocated, idx); - if (list_empty(&pool_vk->entry)) - list_add_tail(pool_vk->free_list, &pool_vk->entry); - } - else - { - /* Don't reset completed queries right away, as vkCmdResetQueryPool() needs to happen - * outside of a render pass. Queue the query to be reset in wined3d_query_pool_vk_reset() - * instead, which is called when the render pass ends. */ - wined3d_bitmap_set(pool_vk->completed, idx); - if (list_empty(&pool_vk->completed_entry)) - list_add_tail(&context_vk->completed_query_pools, &pool_vk->completed_entry); - } + /* Don't reset completed queries right away, as vkCmdResetQueryPool() needs to happen + * outside of a render pass. Queue the query to be reset in wined3d_query_pool_vk_reset() + * instead, which is called when the render pass ends. */ + wined3d_bitmap_set(pool_vk->completed, idx); + if (list_empty(&pool_vk->completed_entry)) + list_add_tail(&context_vk->completed_query_pools, &pool_vk->completed_entry); }
bool wined3d_query_pool_vk_allocate_query(struct wined3d_query_pool_vk *pool_vk, size_t *idx) @@ -1565,11 +1551,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 @@ -1590,8 +1575,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) { @@ -1686,65 +1669,48 @@ 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; }
-static void wined3d_query_vk_poll_cs(void *object) +static BOOL wined3d_query_vk_poll(struct wined3d_query *query, uint32_t flags) { - 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; - - query_vk = wined3d_query_vk(query); - - context_vk = wined3d_context_vk(context_acquire(query->device, NULL, 0)); - - 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) - goto unavailable; - - if (query_vk->command_buffer_id > context_vk->completed_command_buffer_id) - wined3d_context_vk_poll_command_buffers(context_vk); - if (query_vk->command_buffer_id > context_vk->completed_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; + struct wined3d_device_vk *device_vk = wined3d_device_vk(query->device); + struct wined3d_query_vk *query_vk = wined3d_query_vk(query); + size_t i;
- /* 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; + memset((void *)query_vk->q.data, 0, query_vk->q.data_size);
- query_vk->pool_idx.pool_vk = NULL; - context_release(&context_vk->c); + if (query_vk->pool_idx.pool_vk && !wined3d_query_vk_accumulate_data(query_vk, device_vk, &query_vk->pool_idx)) + return FALSE;
- data->result = TRUE; - return; + for (i = 0; i < query_vk->pending_count; ++i) + { + if (!wined3d_query_vk_accumulate_data(query_vk, device_vk, &query_vk->pending[i])) + return FALSE; + }
-unavailable: - context_release(&context_vk->c); - data->result = FALSE; + return TRUE; }
-static BOOL wined3d_query_vk_poll(struct wined3d_query *query, uint32_t flags) +static void wined3d_query_vk_remove_pending_queries(struct wined3d_context_vk *context_vk, + struct wined3d_query_vk *query_vk) { - struct wined3d_cs *cs = query->device->cs; - struct wined3d_poll_callback_data data; + size_t i;
- data.query = query; - data.flags = flags; + 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);
- wined3d_cs_run_priority_callback(cs, wined3d_query_vk_poll_cs, &data); - - return data.result; + query_vk->pending_count = 0; }
static void wined3d_query_vk_issue(struct wined3d_query *query, uint32_t flags) @@ -1761,8 +1727,7 @@ static void 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); - memset((void *)query->data, 0, query->data_size); + wined3d_query_vk_remove_pending_queries(context_vk, query_vk); vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk); if (query_vk->flags & WINED3D_QUERY_VK_FLAG_STARTED) { @@ -1839,12 +1804,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 6b885036260..7185893e894 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -2102,7 +2102,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) @@ -2110,7 +2111,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; @@ -2646,9 +2649,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, @@ -2696,8 +2696,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;
On Mon, 22 Nov 2021 at 13:46, Jan Sikorski jsikorski@codeweavers.com wrote:
Signed-off-by: Jan Sikorski jsikorski@codeweavers.com
dlls/wined3d/context_vk.c | 64 ----------------- dlls/wined3d/query.c | 121 ++++++++++++--------------------- dlls/wined3d/wined3d_private.h | 12 ++-- 3 files changed, 48 insertions(+), 149 deletions(-)
Much like the first patch in this series, what were the considerations for writing this patch this way? (As opposed to e.g. copying the scheme currently used by the OpenGL backend.) What are the advantages/disadvantages?
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,
On Mon, 22 Nov 2021 at 13:46, Jan Sikorski jsikorski@codeweavers.com wrote:
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(-)
This may be fine, but it's missing a motivation/commit message.
On Mon, 22 Nov 2021 at 13:46, Jan Sikorski jsikorski@codeweavers.com wrote:
Poll with callbacks from application threads instead.
Signed-off-by: Jan Sikorski jsikorski@codeweavers.com
dlls/wined3d/cs.c | 73 ++------- dlls/wined3d/query.c | 284 ++++++++++++++++++++++----------- dlls/wined3d/wined3d_private.h | 6 +- 3 files changed, 212 insertions(+), 151 deletions(-)
I happen to know the background of this series of patches because of private conversations we've had, but for the benefit of both the commit message and the rest of the mailing list, please assume I don't. Why would we want to do this? What problem does this patch solve?
I also don't think it's ideal to lead with a patch removing the existing mechanism. The way we generally do these kinds of rewrites is to first introduce the new mechanism, then move users of the old mechanism over to the new mechanism, and only remove the old mechanism once it has become unused.
-static void wined3d_cs_exec_query_issue(struct wined3d_cs *cs, const void *data) +void wined3d_cs_run_priority_callback(struct wined3d_cs *cs, void (*callback)(void *object), void *object) {
- const struct wined3d_cs_query_issue *op = data;
- struct wined3d_query *query = op->query;
- BOOL poll;
- struct wined3d_cs_callback *op;
- poll = query->query_ops->query_issue(query, op->flags);
- op = wined3d_device_context_require_space(&cs->c, sizeof(*op), WINED3D_CS_QUEUE_MAP);
- op->opcode = WINED3D_CS_OP_CALLBACK;
- op->callback = callback;
- op->object = object;
- if (!cs->thread)
return;
- wined3d_device_context_submit(&cs->c, WINED3D_CS_QUEUE_MAP);
- wined3d_cs_finish(cs, WINED3D_CS_QUEUE_MAP);
+}
The wined3d_cs_finish() call is effectively going to make polling queries synchronous, at least as far as WINED3D_CS_QUEUE_MAP is concerned. That doesn't seem desirable.
Hi,
On 23 Nov 2021, at 12:46, Henri Verbeet hverbeet@gmail.com wrote:
On Mon, 22 Nov 2021 at 13:46, Jan Sikorski jsikorski@codeweavers.com wrote:
Poll with callbacks from application threads instead.
Signed-off-by: Jan Sikorski jsikorski@codeweavers.com
dlls/wined3d/cs.c | 73 ++------- dlls/wined3d/query.c | 284 ++++++++++++++++++++++----------- dlls/wined3d/wined3d_private.h | 6 +- 3 files changed, 212 insertions(+), 151 deletions(-)
I happen to know the background of this series of patches because of private conversations we've had, but for the benefit of both the commit message and the rest of the mailing list, please assume I don't. Why would we want to do this? What problem does this patch solve?
Right, I guess it could use some explanation.
I also don't think it's ideal to lead with a patch removing the existing mechanism. The way we generally do these kinds of rewrites is to first introduce the new mechanism, then move users of the old mechanism over to the new mechanism, and only remove the old mechanism once it has become unused.
OK, I think this patch could be split into a couple more patches, so that removing the list goes after we can poll using the new way, with only a little intermediate mess.
-static void wined3d_cs_exec_query_issue(struct wined3d_cs *cs, const void *data) +void wined3d_cs_run_priority_callback(struct wined3d_cs *cs, void (*callback)(void *object), void *object) {
- const struct wined3d_cs_query_issue *op = data;
- struct wined3d_query *query = op->query;
- BOOL poll;
- struct wined3d_cs_callback *op;
- poll = query->query_ops->query_issue(query, op->flags);
- op = wined3d_device_context_require_space(&cs->c, sizeof(*op), WINED3D_CS_QUEUE_MAP);
- op->opcode = WINED3D_CS_OP_CALLBACK;
- op->callback = callback;
- op->object = object;
- if (!cs->thread)
return;
- wined3d_device_context_submit(&cs->c, WINED3D_CS_QUEUE_MAP);
- wined3d_cs_finish(cs, WINED3D_CS_QUEUE_MAP);
+}
The wined3d_cs_finish() call is effectively going to make polling queries synchronous, at least as far as WINED3D_CS_QUEUE_MAP is concerned. That doesn't seem desirable.
If we can’t call directly into OpenGL on the application thread reasonably, I’m not sure how much better can this get. Just removing the wined3d_cs_finish() and getting the result asynchronously may actually make it worse, if a game knows the queries should be done by the time it is called, it will probably just busy wait for it by calling GetData() repeatedly. That said, I don’t think it is so bad, because for occlusion queries, which are the bulk I guess, we probably use the buffer method; and other users of WINED3D_CS_QUEUE_MAP are synchronous too, so it shouldn't clog unless there’s more threads involved. It ran well with the couple games I tested, so there’s that too, but supposedly we could hit a pessimistic case where it’s worse.. Do you have a better way in mind?
Thanks, - Jan
On Tue, 23 Nov 2021 at 15:28, Jan Sikorski jsikorski@codeweavers.com wrote:
-static void wined3d_cs_exec_query_issue(struct wined3d_cs *cs, const void *data) +void wined3d_cs_run_priority_callback(struct wined3d_cs *cs, void (*callback)(void *object), void *object) {
- const struct wined3d_cs_query_issue *op = data;
- struct wined3d_query *query = op->query;
- BOOL poll;
- struct wined3d_cs_callback *op;
- poll = query->query_ops->query_issue(query, op->flags);
- op = wined3d_device_context_require_space(&cs->c, sizeof(*op), WINED3D_CS_QUEUE_MAP);
- op->opcode = WINED3D_CS_OP_CALLBACK;
- op->callback = callback;
- op->object = object;
- if (!cs->thread)
return;
- wined3d_device_context_submit(&cs->c, WINED3D_CS_QUEUE_MAP);
- wined3d_cs_finish(cs, WINED3D_CS_QUEUE_MAP);
+}
The wined3d_cs_finish() call is effectively going to make polling queries synchronous, at least as far as WINED3D_CS_QUEUE_MAP is concerned. That doesn't seem desirable.
If we can’t call directly into OpenGL on the application thread reasonably, I’m not sure how much better can this get. Just removing the wined3d_cs_finish() and getting the result asynchronously may actually make it worse, if a game knows the queries should be done by the time it is called, it will probably just busy wait for it by calling GetData() repeatedly. That said, I don’t think it is so bad, because for occlusion queries, which are the bulk I guess, we probably use the buffer method; and other users of WINED3D_CS_QUEUE_MAP are synchronous too, so it shouldn't clog unless there’s more threads involved. It ran well with the couple games I tested, so there’s that too, but supposedly we could hit a pessimistic case where it’s worse.. Do you have a better way in mind?
I guess what it comes down to is whether there's any reason for the wined3d_cs_run_priority_callback() scheme to exist. In the case of Vulkan queries, those would be polled from application threads after this series of patches, so the CS poll list would just be empty, and as far as I'm aware it doesn't add much overhead in that case. As far as I can tell, the wined3d_cs_run_priority_callback() scheme is not a requirement for polling Vulkan queries from application threads. Then, for the GL backend, when we have ARB_query_buffer_object, the OpenGL occlusion query scheme could be extended to other query types if needed. So that mostly leaves OpenGL without ARB_query_buffer_object where the CS poll list would need to be used. If the wined3d_cs_run_priority_callback() scheme is more efficient in those cases, or perhaps equally efficient but less complicated, etc., that's would of course be worth it. On the face of it though, that doesn't appear to be the case? (And the background here is that the CS poll list was introduced as an optimisation over a scheme not entirely unlike the one in this patch, although before the introduction of WINED3D_CS_QUEUE_MAP and ARB_query_buffer_object.)
On 24 Nov 2021, at 15:27, Henri Verbeet hverbeet@gmail.com wrote:
On Tue, 23 Nov 2021 at 15:28, Jan Sikorski jsikorski@codeweavers.com wrote:
-static void wined3d_cs_exec_query_issue(struct wined3d_cs *cs, const void *data) +void wined3d_cs_run_priority_callback(struct wined3d_cs *cs, void (*callback)(void *object), void *object) {
- const struct wined3d_cs_query_issue *op = data;
- struct wined3d_query *query = op->query;
- BOOL poll;
- struct wined3d_cs_callback *op;
- poll = query->query_ops->query_issue(query, op->flags);
- op = wined3d_device_context_require_space(&cs->c, sizeof(*op), WINED3D_CS_QUEUE_MAP);
- op->opcode = WINED3D_CS_OP_CALLBACK;
- op->callback = callback;
- op->object = object;
- if (!cs->thread)
return;
- wined3d_device_context_submit(&cs->c, WINED3D_CS_QUEUE_MAP);
- wined3d_cs_finish(cs, WINED3D_CS_QUEUE_MAP);
+}
The wined3d_cs_finish() call is effectively going to make polling queries synchronous, at least as far as WINED3D_CS_QUEUE_MAP is concerned. That doesn't seem desirable.
If we can’t call directly into OpenGL on the application thread reasonably, I’m not sure how much better can this get. Just removing the wined3d_cs_finish() and getting the result asynchronously may actually make it worse, if a game knows the queries should be done by the time it is called, it will probably just busy wait for it by calling GetData() repeatedly. That said, I don’t think it is so bad, because for occlusion queries, which are the bulk I guess, we probably use the buffer method; and other users of WINED3D_CS_QUEUE_MAP are synchronous too, so it shouldn't clog unless there’s more threads involved. It ran well with the couple games I tested, so there’s that too, but supposedly we could hit a pessimistic case where it’s worse.. Do you have a better way in mind?
I guess what it comes down to is whether there's any reason for the wined3d_cs_run_priority_callback() scheme to exist. In the case of Vulkan queries, those would be polled from application threads after this series of patches, so the CS poll list would just be empty, and as far as I'm aware it doesn't add much overhead in that case. As far as I can tell, the wined3d_cs_run_priority_callback() scheme is not a requirement for polling Vulkan queries from application threads. Then, for the GL backend, when we have ARB_query_buffer_object, the OpenGL occlusion query scheme could be extended to other query types if needed. So that mostly leaves OpenGL without ARB_query_buffer_object where the CS poll list would need to be used. If the wined3d_cs_run_priority_callback() scheme is more efficient in those cases, or perhaps equally efficient but less complicated, etc., that's would of course be worth it. On the face of it though, that doesn't appear to be the case? (And the background here is that the CS poll list was introduced as an optimisation over a scheme not entirely unlike the one in this patch, although before the introduction of WINED3D_CS_QUEUE_MAP and ARB_query_buffer_object.)
Yes, that’s what I figured today too. Whatever ends up happening with the GL queries, it should work for this series.
Thanks, - Jan