[PATCH 4/5] wined3d: Implement timestamp queries for the Vulkan adapter.

Henri Verbeet hverbeet at codeweavers.com
Tue May 26 11:10:12 CDT 2020


Signed-off-by: Henri Verbeet <hverbeet at 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, &timestamp_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;
 
-- 
2.20.1




More information about the wine-devel mailing list