[PATCH vkd3d 2/2] vkd3d: Use multiple command queues if available.

Conor McCarthy cmccarthy at codeweavers.com
Thu Dec 12 06:31:12 CST 2019


Signed-off-by: Conor McCarthy <cmccarthy at codeweavers.com>
---
 libs/vkd3d/command.c       | 24 +++++++----
 libs/vkd3d/device.c        | 84 ++++++++++++++++++++++++--------------
 libs/vkd3d/vkd3d_private.h | 16 ++++++--
 3 files changed, 83 insertions(+), 41 deletions(-)

diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c
index 8a7ff66..6b0d9e0 100644
--- a/libs/vkd3d/command.c
+++ b/libs/vkd3d/command.c
@@ -22,7 +22,8 @@
 static HRESULT d3d12_fence_signal(struct d3d12_fence *fence, uint64_t value, VkFence vk_fence);
 
 HRESULT vkd3d_queue_create(struct d3d12_device *device,
-        uint32_t family_index, const VkQueueFamilyProperties *properties, struct vkd3d_queue **queue)
+        uint32_t family_index, const VkQueueFamilyProperties *properties,
+        struct vkd3d_queue_array *queue_array, uint32_t queue_index)
 {
     const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
     struct vkd3d_queue *object;
@@ -51,11 +52,11 @@ HRESULT vkd3d_queue_create(struct d3d12_device *device,
 
     memset(object->old_vk_semaphores, 0, sizeof(object->old_vk_semaphores));
 
-    VK_CALL(vkGetDeviceQueue(device->vk_device, family_index, 0, &object->vk_queue));
+    VK_CALL(vkGetDeviceQueue(device->vk_device, family_index, queue_index, &object->vk_queue));
 
     TRACE("Created queue %p for queue family index %u.\n", object, family_index);
 
-    *queue = object;
+    queue_array->queues[queue_index] = object;
 
     return S_OK;
 }
@@ -1683,17 +1684,26 @@ static struct d3d12_command_allocator *unsafe_impl_from_ID3D12CommandAllocator(I
     return impl_from_ID3D12CommandAllocator(iface);
 }
 
+static struct vkd3d_queue *d3d12_device_get_next_vkd3d_queue(struct vkd3d_queue_array *queue_array)
+{
+    LONG i = (InterlockedIncrement(queue_array->index_ptr) - 1) % VKD3D_MAX_QUEUE_CREATE_COUNT;
+    struct vkd3d_queue *queue = queue_array->queues[i];
+    if (queue)
+        return queue;
+    return queue_array->queues[0];
+}
+
 struct vkd3d_queue *d3d12_device_get_vkd3d_queue(struct d3d12_device *device,
         D3D12_COMMAND_LIST_TYPE type)
 {
     switch (type)
     {
         case D3D12_COMMAND_LIST_TYPE_DIRECT:
-            return device->direct_queue;
+            return d3d12_device_get_next_vkd3d_queue(&device->direct_queues);
         case D3D12_COMMAND_LIST_TYPE_COMPUTE:
-            return device->compute_queue;
+            return d3d12_device_get_next_vkd3d_queue(&device->compute_queues);
         case D3D12_COMMAND_LIST_TYPE_COPY:
-            return device->copy_queue;
+            return d3d12_device_get_next_vkd3d_queue(&device->copy_queues);
         default:
             FIXME("Unhandled command list type %#x.\n", type);
             return NULL;
@@ -1713,7 +1723,7 @@ static HRESULT d3d12_command_allocator_init(struct d3d12_command_allocator *allo
         return hr;
 
     if (!(queue = d3d12_device_get_vkd3d_queue(device, type)))
-        queue = device->direct_queue;
+        queue = device->direct_queues.queues[0];
 
     allocator->ID3D12CommandAllocator_iface.lpVtbl = &d3d12_command_allocator_vtbl;
     allocator->refcount = 1;
diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c
index ad32ff2..ff5dad1 100644
--- a/libs/vkd3d/device.c
+++ b/libs/vkd3d/device.c
@@ -1538,17 +1538,48 @@ struct vkd3d_device_queue_info
 
 static void d3d12_device_destroy_vkd3d_queues(struct d3d12_device *device)
 {
-    if (device->direct_queue)
-        vkd3d_queue_destroy(device->direct_queue, device);
-    if (device->compute_queue && device->compute_queue != device->direct_queue)
-        vkd3d_queue_destroy(device->compute_queue, device);
-    if (device->copy_queue && device->copy_queue != device->direct_queue
-            && device->copy_queue != device->compute_queue)
-        vkd3d_queue_destroy(device->copy_queue, device);
+    struct vkd3d_queue_array *direct_queues = &device->direct_queues;
+    struct vkd3d_queue_array *compute_queues = &device->compute_queues;
+    struct vkd3d_queue_array *copy_queues = &device->copy_queues;
+    size_t i;
 
-    device->direct_queue = NULL;
-    device->compute_queue = NULL;
-    device->copy_queue = NULL;
+    for (i = 0; i < ARRAY_SIZE(direct_queues->queues); ++i)
+    {
+        if (direct_queues->queues[i])
+            vkd3d_queue_destroy(direct_queues->queues[i], device);
+        if (compute_queues->queues[i] && compute_queues->queues[i] != direct_queues->queues[i])
+            vkd3d_queue_destroy(compute_queues->queues[i], device);
+        if (copy_queues->queues[i] && copy_queues->queues[i] != direct_queues->queues[i]
+                && copy_queues->queues[i] != compute_queues->queues[i])
+            vkd3d_queue_destroy(copy_queues->queues[i], device);
+        direct_queues->queues[i] = NULL;
+        compute_queues->queues[i] = NULL;
+        copy_queues->queues[i] = NULL;
+    }
+}
+
+static HRESULT d3d12_device_create_family_queues(struct d3d12_device *device,
+        const struct vkd3d_device_queue_info *queue_info, enum vkd3d_queue_family family,
+        struct vkd3d_queue_array *queue_array)
+{
+    uint32_t family_index = queue_info->family_index[family];
+    uint32_t i, count;
+    HRESULT hr;
+
+    queue_array->index_ptr = &queue_array->index;
+
+    count = min(queue_info->vk_properties[family].queueCount, VKD3D_MAX_QUEUE_CREATE_COUNT);
+
+    for (i = 0; i < count; ++i)
+    {
+        if (FAILED(hr = vkd3d_queue_create(device, family_index,
+                &queue_info->vk_properties[family], queue_array, i)))
+            return hr;
+    }
+
+    device->queue_family_indices[device->queue_family_count++] = family_index;
+
+    return S_OK;
 }
 
 static HRESULT d3d12_device_create_vkd3d_queues(struct d3d12_device *device,
@@ -1559,35 +1590,27 @@ static HRESULT d3d12_device_create_vkd3d_queues(struct d3d12_device *device,
     uint32_t direct_family_index = queue_info->family_index[VKD3D_QUEUE_FAMILY_DIRECT];
     HRESULT hr;
 
-    device->direct_queue = NULL;
-    device->compute_queue = NULL;
-    device->copy_queue = NULL;
+    memset(&device->direct_queues, 0, sizeof(device->direct_queues));
+    memset(&device->compute_queues, 0, sizeof(device->compute_queues));
+    memset(&device->copy_queues, 0, sizeof(device->copy_queues));
 
     device->queue_family_count = 0;
     memset(device->queue_family_indices, 0, sizeof(device->queue_family_indices));
 
-    if (SUCCEEDED((hr = vkd3d_queue_create(device, direct_family_index,
-            &queue_info->vk_properties[VKD3D_QUEUE_FAMILY_DIRECT], &device->direct_queue))))
-        device->queue_family_indices[device->queue_family_count++] = direct_family_index;
-    else
+    if (FAILED(hr = d3d12_device_create_family_queues(device, queue_info, VKD3D_QUEUE_FAMILY_DIRECT, &device->direct_queues)))
         goto out_destroy_queues;
 
+    /* A binary copy points index_ptr to the index in the source object, which is the desired behaviour. */
     if (compute_family_index == direct_family_index)
-        device->compute_queue = device->direct_queue;
-    else if (SUCCEEDED(hr = vkd3d_queue_create(device, compute_family_index,
-            &queue_info->vk_properties[VKD3D_QUEUE_FAMILY_COMPUTE], &device->compute_queue)))
-        device->queue_family_indices[device->queue_family_count++] = compute_family_index;
-    else
+        memcpy(&device->compute_queues, &device->direct_queues, sizeof(device->compute_queues));
+    else if (FAILED(hr = d3d12_device_create_family_queues(device, queue_info, VKD3D_QUEUE_FAMILY_COMPUTE, &device->compute_queues)))
         goto out_destroy_queues;
 
     if (transfer_family_index == direct_family_index)
-        device->copy_queue = device->direct_queue;
+        memcpy(&device->copy_queues, &device->direct_queues, sizeof(device->copy_queues));
     else if (transfer_family_index == compute_family_index)
-        device->copy_queue = device->compute_queue;
-    else if (SUCCEEDED(hr = vkd3d_queue_create(device, transfer_family_index,
-            &queue_info->vk_properties[VKD3D_QUEUE_FAMILY_TRANSFER], &device->copy_queue)))
-        device->queue_family_indices[device->queue_family_count++] = transfer_family_index;
-    else
+        memcpy(&device->copy_queues, &device->compute_queues, sizeof(device->copy_queues));
+    else if (FAILED(hr = d3d12_device_create_family_queues(device, queue_info, VKD3D_QUEUE_FAMILY_TRANSFER, &device->copy_queues)))
         goto out_destroy_queues;
 
     return S_OK;
@@ -1597,7 +1620,8 @@ out_destroy_queues:
     return hr;
 }
 
-static float queue_priorities[] = {1.0f};
+static float queue_priorities[] = {1.0f, 1.0f, 1.0f, 1.0f};
+STATIC_ASSERT(ARRAY_SIZE(queue_priorities) == VKD3D_MAX_QUEUE_CREATE_COUNT);
 
 static HRESULT vkd3d_select_queues(const struct vkd3d_instance *vkd3d_instance,
         VkPhysicalDevice physical_device, struct vkd3d_device_queue_info *info)
@@ -1647,7 +1671,7 @@ static HRESULT vkd3d_select_queues(const struct vkd3d_instance *vkd3d_instance,
         queue_info->pNext = NULL;
         queue_info->flags = 0;
         queue_info->queueFamilyIndex = i;
-        queue_info->queueCount = 1; /* FIXME: Use multiple queues. */
+        queue_info->queueCount = min(queue_properties[i].queueCount, VKD3D_MAX_QUEUE_CREATE_COUNT);
         queue_info->pQueuePriorities = queue_priorities;
     }
 
diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h
index 0c031d2..382b5ca 100644
--- a/libs/vkd3d/vkd3d_private.h
+++ b/libs/vkd3d/vkd3d_private.h
@@ -50,6 +50,7 @@
 
 #define VKD3D_MAX_COMPATIBLE_FORMAT_COUNT 6u
 #define VKD3D_MAX_QUEUE_FAMILY_COUNT      3u
+#define VKD3D_MAX_QUEUE_CREATE_COUNT      4u
 #define VKD3D_MAX_SHADER_EXTENSIONS       1u
 #define VKD3D_MAX_SHADER_STAGES           5u
 #define VKD3D_MAX_VK_SYNC_OBJECTS         4u
@@ -1003,10 +1004,17 @@ struct vkd3d_queue
     VkSemaphore old_vk_semaphores[VKD3D_MAX_VK_SYNC_OBJECTS];
 };
 
+struct vkd3d_queue_array
+{
+    struct vkd3d_queue *queues[VKD3D_MAX_QUEUE_CREATE_COUNT];
+    LONG *index_ptr;
+    LONG index;
+};
+
 VkQueue vkd3d_queue_acquire(struct vkd3d_queue *queue) DECLSPEC_HIDDEN;
 HRESULT vkd3d_queue_create(struct d3d12_device *device,
         uint32_t family_index, const VkQueueFamilyProperties *properties,
-        struct vkd3d_queue **queue) DECLSPEC_HIDDEN;
+        struct vkd3d_queue_array *queue_array, uint32_t queue_index) DECLSPEC_HIDDEN;
 void vkd3d_queue_destroy(struct vkd3d_queue *queue, struct d3d12_device *device) DECLSPEC_HIDDEN;
 void vkd3d_queue_release(struct vkd3d_queue *queue) DECLSPEC_HIDDEN;
 
@@ -1134,9 +1142,9 @@ struct d3d12_device
 
     struct vkd3d_vulkan_info vk_info;
 
-    struct vkd3d_queue *direct_queue;
-    struct vkd3d_queue *compute_queue;
-    struct vkd3d_queue *copy_queue;
+    struct vkd3d_queue_array direct_queues;
+    struct vkd3d_queue_array compute_queues;
+    struct vkd3d_queue_array copy_queues;
     uint32_t queue_family_indices[VKD3D_MAX_QUEUE_FAMILY_COUNT];
     unsigned int queue_family_count;
 
-- 
2.24.0




More information about the wine-devel mailing list