Commit 7101af57 authored by Henri Verbeet's avatar Henri Verbeet Committed by Alexandre Julliard

wined3d: Implement timestamp queries for the Vulkan adapter.

parent 8cb3d29c
...@@ -292,7 +292,7 @@ static void adapter_vk_destroy(struct wined3d_adapter *adapter) ...@@ -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, 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; VkPhysicalDevice physical_device = adapter_vk->physical_device;
const struct wined3d_vk_info *vk_info = &adapter_vk->vk_info; 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 ...@@ -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) if (queue_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
{ {
*queue_family_index = i; *queue_family_index = i;
*timestamp_bits = queue_properties[i].timestampValidBits;
heap_free(queue_properties); heap_free(queue_properties);
return WINED3D_OK; return WINED3D_OK;
} }
...@@ -496,13 +497,14 @@ static HRESULT adapter_vk_create_device(struct wined3d *wined3d, const struct wi ...@@ -496,13 +497,14 @@ static HRESULT adapter_vk_create_device(struct wined3d *wined3d, const struct wi
VkPhysicalDevice physical_device; VkPhysicalDevice physical_device;
VkDeviceCreateInfo device_info; VkDeviceCreateInfo device_info;
uint32_t queue_family_index; uint32_t queue_family_index;
uint32_t timestamp_bits;
VkResult vr; VkResult vr;
HRESULT hr; HRESULT hr;
if (!(device_vk = heap_alloc_zero(sizeof(*device_vk)))) if (!(device_vk = heap_alloc_zero(sizeof(*device_vk))))
return E_OUTOFMEMORY; 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, &timestamp_bits)))
goto fail; goto fail;
physical_device = adapter_vk->physical_device; physical_device = adapter_vk->physical_device;
...@@ -564,6 +566,7 @@ static HRESULT adapter_vk_create_device(struct wined3d *wined3d, const struct wi ...@@ -564,6 +566,7 @@ static HRESULT adapter_vk_create_device(struct wined3d *wined3d, const struct wi
device_vk->vk_device = vk_device; device_vk->vk_device = vk_device;
VK_CALL(vkGetDeviceQueue(vk_device, queue_family_index, 0, &device_vk->vk_queue)); VK_CALL(vkGetDeviceQueue(vk_device, queue_family_index, 0, &device_vk->vk_queue));
device_vk->vk_queue_family_index = queue_family_index; device_vk->vk_queue_family_index = queue_family_index;
device_vk->timestamp_bits = timestamp_bits;
device_vk->vk_info = *vk_info; device_vk->vk_info = *vk_info;
#define LOAD_DEVICE_PFN(name) \ #define LOAD_DEVICE_PFN(name) \
......
...@@ -1227,6 +1227,10 @@ bool wined3d_context_vk_allocate_query(struct wined3d_context_vk *context_vk, ...@@ -1227,6 +1227,10 @@ bool wined3d_context_vk_allocate_query(struct wined3d_context_vk *context_vk,
free_pools = &context_vk->free_occlusion_query_pools; free_pools = &context_vk->free_occlusion_query_pools;
break; break;
case WINED3D_QUERY_TYPE_TIMESTAMP:
free_pools = &context_vk->free_timestamp_query_pools;
break;
default: default:
FIXME("Unhandled query type %#x.\n", type); FIXME("Unhandled query type %#x.\n", type);
return false; return false;
...@@ -1286,6 +1290,7 @@ void wined3d_context_vk_cleanup(struct wined3d_context_vk *context_vk) ...@@ -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)); VK_CALL(vkDestroyCommandPool(device_vk->vk_device, context_vk->vk_command_pool, NULL));
wined3d_context_vk_cleanup_resources(context_vk); 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_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); 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->pending_queries.queries);
heap_free(context_vk->submitted.buffers); heap_free(context_vk->submitted.buffers);
...@@ -3057,6 +3062,7 @@ HRESULT wined3d_context_vk_init(struct wined3d_context_vk *context_vk, struct wi ...@@ -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->active_queries);
list_init(&context_vk->free_occlusion_query_pools); 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->render_passes, wined3d_render_pass_vk_compare);
wine_rb_init(&context_vk->pipeline_layouts, wined3d_pipeline_layout_vk_compare); wine_rb_init(&context_vk->pipeline_layouts, wined3d_pipeline_layout_vk_compare);
......
...@@ -1403,6 +1403,11 @@ bool wined3d_query_pool_vk_init(struct wined3d_query_pool_vk *pool_vk, ...@@ -1403,6 +1403,11 @@ bool wined3d_query_pool_vk_init(struct wined3d_query_pool_vk *pool_vk,
pool_info.pipelineStatistics = 0; pool_info.pipelineStatistics = 0;
break; break;
case WINED3D_QUERY_TYPE_TIMESTAMP:
pool_info.queryType = VK_QUERY_TYPE_TIMESTAMP;
pool_info.pipelineStatistics = 0;
break;
default: default:
FIXME("Unhandled query type %#x.\n", type); FIXME("Unhandled query type %#x.\n", type);
return false; return false;
...@@ -1428,6 +1433,7 @@ bool wined3d_query_vk_accumulate_data(struct wined3d_query_vk *query_vk, ...@@ -1428,6 +1433,7 @@ bool wined3d_query_vk_accumulate_data(struct wined3d_query_vk *query_vk,
union union
{ {
uint64_t occlusion; uint64_t occlusion;
uint64_t timestamp;
} tmp, *result; } tmp, *result;
if ((vr = VK_CALL(vkGetQueryPoolResults(device_vk->vk_device, pool_idx->pool_vk->vk_query_pool, 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, ...@@ -1447,6 +1453,10 @@ bool wined3d_query_vk_accumulate_data(struct wined3d_query_vk *query_vk,
result->occlusion += tmp.occlusion; result->occlusion += tmp.occlusion;
break; break;
case WINED3D_QUERY_TYPE_TIMESTAMP:
result->timestamp = tmp.timestamp;
break;
default: default:
FIXME("Unhandled query type %#x.\n", query_vk->q.type); FIXME("Unhandled query type %#x.\n", query_vk->q.type);
return false; return false;
...@@ -1607,9 +1617,53 @@ static const struct wined3d_query_ops wined3d_query_vk_ops = ...@@ -1607,9 +1617,53 @@ static const struct wined3d_query_ops wined3d_query_vk_ops =
.query_destroy = wined3d_query_vk_destroy, .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, 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) 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; struct wined3d_query_vk *query_vk;
unsigned int data_size; unsigned int data_size;
...@@ -1622,6 +1676,16 @@ HRESULT wined3d_query_vk_create(struct wined3d_device *device, enum wined3d_quer ...@@ -1622,6 +1676,16 @@ HRESULT wined3d_query_vk_create(struct wined3d_device *device, enum wined3d_quer
data_size = sizeof(uint64_t); data_size = sizeof(uint64_t);
break; 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: default:
FIXME("Unhandled query type %#x.\n", type); FIXME("Unhandled query type %#x.\n", type);
return WINED3DERR_NOTAVAILABLE; return WINED3DERR_NOTAVAILABLE;
...@@ -1630,7 +1694,7 @@ HRESULT wined3d_query_vk_create(struct wined3d_device *device, enum wined3d_quer ...@@ -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))) if (!(query_vk = heap_alloc_zero(sizeof(*query_vk) + data_size)))
return E_OUTOFMEMORY; 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); list_init(&query_vk->entry);
if (type == WINED3D_QUERY_TYPE_OCCLUSION) if (type == WINED3D_QUERY_TYPE_OCCLUSION)
query_vk->control_flags = VK_QUERY_CONTROL_PRECISE_BIT; query_vk->control_flags = VK_QUERY_CONTROL_PRECISE_BIT;
......
...@@ -2495,6 +2495,7 @@ struct wined3d_context_vk ...@@ -2495,6 +2495,7 @@ struct wined3d_context_vk
struct list active_queries; struct list active_queries;
struct wined3d_pending_queries_vk pending_queries; struct wined3d_pending_queries_vk pending_queries;
struct list free_occlusion_query_pools; struct list free_occlusion_query_pools;
struct list free_timestamp_query_pools;
struct wined3d_retired_objects_vk retired; struct wined3d_retired_objects_vk retired;
struct wine_rb_tree render_passes; struct wine_rb_tree render_passes;
...@@ -3857,6 +3858,7 @@ struct wined3d_device_vk ...@@ -3857,6 +3858,7 @@ struct wined3d_device_vk
VkDevice vk_device; VkDevice vk_device;
VkQueue vk_queue; VkQueue vk_queue;
uint32_t vk_queue_family_index; uint32_t vk_queue_family_index;
uint32_t timestamp_bits;
struct wined3d_vk_info vk_info; struct wined3d_vk_info vk_info;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment