Signed-off-by: Henri Verbeet hverbeet@codeweavers.com --- dlls/wined3d/adapter_vk.c | 7 ++-- dlls/wined3d/context_vk.c | 6 ++++ dlls/wined3d/query.c | 66 +++++++++++++++++++++++++++++++++- dlls/wined3d/wined3d_private.h | 2 ++ 4 files changed, 78 insertions(+), 3 deletions(-)
diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c index 84eda1e551b..3cccda3b2c6 100644 --- a/dlls/wined3d/adapter_vk.c +++ b/dlls/wined3d/adapter_vk.c @@ -292,7 +292,7 @@ static void adapter_vk_destroy(struct wined3d_adapter *adapter) }
static HRESULT wined3d_select_vulkan_queue_family(const struct wined3d_adapter_vk *adapter_vk, - uint32_t *queue_family_index) + uint32_t *queue_family_index, uint32_t *timestamp_bits) { VkPhysicalDevice physical_device = adapter_vk->physical_device; const struct wined3d_vk_info *vk_info = &adapter_vk->vk_info; @@ -311,6 +311,7 @@ static HRESULT wined3d_select_vulkan_queue_family(const struct wined3d_adapter_v if (queue_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) { *queue_family_index = i; + *timestamp_bits = queue_properties[i].timestampValidBits; heap_free(queue_properties); return WINED3D_OK; } @@ -496,13 +497,14 @@ static HRESULT adapter_vk_create_device(struct wined3d *wined3d, const struct wi VkPhysicalDevice physical_device; VkDeviceCreateInfo device_info; uint32_t queue_family_index; + uint32_t timestamp_bits; VkResult vr; HRESULT hr;
if (!(device_vk = heap_alloc_zero(sizeof(*device_vk)))) return E_OUTOFMEMORY;
- if (FAILED(hr = wined3d_select_vulkan_queue_family(adapter_vk, &queue_family_index))) + if (FAILED(hr = wined3d_select_vulkan_queue_family(adapter_vk, &queue_family_index, ×tamp_bits))) goto fail;
physical_device = adapter_vk->physical_device; @@ -564,6 +566,7 @@ static HRESULT adapter_vk_create_device(struct wined3d *wined3d, const struct wi device_vk->vk_device = vk_device; VK_CALL(vkGetDeviceQueue(vk_device, queue_family_index, 0, &device_vk->vk_queue)); device_vk->vk_queue_family_index = queue_family_index; + device_vk->timestamp_bits = timestamp_bits;
device_vk->vk_info = *vk_info; #define LOAD_DEVICE_PFN(name) \ diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c index 2964eb30cc4..af29ef7e7a7 100644 --- a/dlls/wined3d/context_vk.c +++ b/dlls/wined3d/context_vk.c @@ -1227,6 +1227,10 @@ bool wined3d_context_vk_allocate_query(struct wined3d_context_vk *context_vk, free_pools = &context_vk->free_occlusion_query_pools; break;
+ case WINED3D_QUERY_TYPE_TIMESTAMP: + free_pools = &context_vk->free_timestamp_query_pools; + break; + default: FIXME("Unhandled query type %#x.\n", type); return false; @@ -1286,6 +1290,7 @@ void wined3d_context_vk_cleanup(struct wined3d_context_vk *context_vk) VK_CALL(vkDestroyCommandPool(device_vk->vk_device, context_vk->vk_command_pool, NULL)); wined3d_context_vk_cleanup_resources(context_vk); wined3d_context_vk_destroy_query_pools(context_vk, &context_vk->free_occlusion_query_pools); + wined3d_context_vk_destroy_query_pools(context_vk, &context_vk->free_timestamp_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); @@ -3057,6 +3062,7 @@ HRESULT wined3d_context_vk_init(struct wined3d_context_vk *context_vk, struct wi
list_init(&context_vk->active_queries); list_init(&context_vk->free_occlusion_query_pools); + list_init(&context_vk->free_timestamp_query_pools);
wine_rb_init(&context_vk->render_passes, wined3d_render_pass_vk_compare); wine_rb_init(&context_vk->pipeline_layouts, wined3d_pipeline_layout_vk_compare); diff --git a/dlls/wined3d/query.c b/dlls/wined3d/query.c index b72ffd633c5..3b6f442f4a7 100644 --- a/dlls/wined3d/query.c +++ b/dlls/wined3d/query.c @@ -1403,6 +1403,11 @@ bool wined3d_query_pool_vk_init(struct wined3d_query_pool_vk *pool_vk, pool_info.pipelineStatistics = 0; break;
+ case WINED3D_QUERY_TYPE_TIMESTAMP: + pool_info.queryType = VK_QUERY_TYPE_TIMESTAMP; + pool_info.pipelineStatistics = 0; + break; + default: FIXME("Unhandled query type %#x.\n", type); return false; @@ -1428,6 +1433,7 @@ bool wined3d_query_vk_accumulate_data(struct wined3d_query_vk *query_vk, union { uint64_t occlusion; + uint64_t timestamp; } tmp, *result;
if ((vr = VK_CALL(vkGetQueryPoolResults(device_vk->vk_device, pool_idx->pool_vk->vk_query_pool, @@ -1447,6 +1453,10 @@ bool wined3d_query_vk_accumulate_data(struct wined3d_query_vk *query_vk, result->occlusion += tmp.occlusion; break;
+ case WINED3D_QUERY_TYPE_TIMESTAMP: + result->timestamp = tmp.timestamp; + break; + default: FIXME("Unhandled query type %#x.\n", query_vk->q.type); return false; @@ -1607,9 +1617,53 @@ static const struct wined3d_query_ops wined3d_query_vk_ops = .query_destroy = wined3d_query_vk_destroy, };
+static BOOL 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); + const struct wined3d_vk_info *vk_info; + struct wined3d_context_vk *context_vk; + VkCommandBuffer command_buffer; + + TRACE("query %p, flags %#x.\n", query, flags); + + if (flags & WINED3DISSUE_BEGIN) + TRACE("Ignoring WINED3DISSUE_BEGIN.\n"); + + if (flags & WINED3DISSUE_END) + { + context_vk = wined3d_context_vk(context_acquire(&device_vk->d, NULL, 0)); + vk_info = context_vk->vk_info; + + wined3d_context_vk_end_current_render_pass(context_vk); + command_buffer = wined3d_context_vk_get_command_buffer(context_vk); + if (!query_vk->pool_idx.pool_vk) + wined3d_context_vk_allocate_query(context_vk, query_vk->q.type, &query_vk->pool_idx); + VK_CALL(vkCmdResetQueryPool(command_buffer, query_vk->pool_idx.pool_vk->vk_query_pool, + query_vk->pool_idx.idx, 1)); + 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 = +{ + .query_poll = wined3d_query_vk_poll, + .query_issue = wined3d_query_timestamp_vk_issue, + .query_destroy = wined3d_query_vk_destroy, +}; + 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) { + const struct wined3d_query_ops *ops = &wined3d_query_vk_ops; struct wined3d_query_vk *query_vk; unsigned int data_size;
@@ -1622,6 +1676,16 @@ HRESULT wined3d_query_vk_create(struct wined3d_device *device, enum wined3d_quer data_size = sizeof(uint64_t); break;
+ case WINED3D_QUERY_TYPE_TIMESTAMP: + if (!wined3d_device_vk(device)->timestamp_bits) + { + WARN("Timestamp queries not supported.\n"); + return WINED3DERR_NOTAVAILABLE; + } + ops = &wined3d_query_timestamp_vk_ops; + data_size = sizeof(uint64_t); + break; + default: FIXME("Unhandled query type %#x.\n", type); return WINED3DERR_NOTAVAILABLE; @@ -1630,7 +1694,7 @@ HRESULT wined3d_query_vk_create(struct wined3d_device *device, enum wined3d_quer if (!(query_vk = heap_alloc_zero(sizeof(*query_vk) + data_size))) return E_OUTOFMEMORY;
- wined3d_query_init(&query_vk->q, device, type, query_vk + 1, data_size, &wined3d_query_vk_ops, parent, parent_ops); + wined3d_query_init(&query_vk->q, device, type, query_vk + 1, data_size, ops, parent, parent_ops); list_init(&query_vk->entry); if (type == WINED3D_QUERY_TYPE_OCCLUSION) query_vk->control_flags = VK_QUERY_CONTROL_PRECISE_BIT; diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 5c92eecbf3e..9f8c212fbf3 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -2495,6 +2495,7 @@ struct wined3d_context_vk struct list active_queries; struct wined3d_pending_queries_vk pending_queries; struct list free_occlusion_query_pools; + struct list free_timestamp_query_pools;
struct wined3d_retired_objects_vk retired; struct wine_rb_tree render_passes; @@ -3857,6 +3858,7 @@ struct wined3d_device_vk VkDevice vk_device; VkQueue vk_queue; uint32_t vk_queue_family_index; + uint32_t timestamp_bits;
struct wined3d_vk_info vk_info;