[PATCH] winevulkan: Fix queue creation with mixed queue flags.
Georg Lehmann
dadschoorse at gmail.com
Wed Mar 31 13:11:34 CDT 2021
The Vulkan spec says:
The queueFamilyIndex member of each element of pQueueCreateInfos must be unique
within pQueueCreateInfos, except that two members can share the same
queueFamilyIndex if one is a protected-capable queue and one is not a
protected-capable queue.
Signed-off-by: Georg Lehmann <dadschoorse at gmail.com>
---
dlls/winevulkan/vulkan.c | 83 ++++++++++++++++++--------------
dlls/winevulkan/vulkan_private.h | 6 ++-
2 files changed, 51 insertions(+), 38 deletions(-)
diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c
index b2045295718..0beb09329d2 100644
--- a/dlls/winevulkan/vulkan.c
+++ b/dlls/winevulkan/vulkan.c
@@ -323,25 +323,21 @@ static void wine_vk_free_command_buffers(struct VkDevice_T *device,
}
}
-static struct VkQueue_T *wine_vk_device_alloc_queues(struct VkDevice_T *device,
- uint32_t family_index, uint32_t queue_count, VkDeviceQueueCreateFlags flags)
+static void wine_vk_device_get_queues(struct VkDevice_T *device,
+ uint32_t family_index, uint32_t queue_count, VkDeviceQueueCreateFlags flags,
+ struct VkQueue_T* queues)
{
VkDeviceQueueInfo2 queue_info;
- struct VkQueue_T *queues;
unsigned int i;
- if (!(queues = heap_calloc(queue_count, sizeof(*queues))))
- {
- ERR("Failed to allocate memory for queues\n");
- return NULL;
- }
-
for (i = 0; i < queue_count; i++)
{
struct VkQueue_T *queue = &queues[i];
queue->base.loader_magic = VULKAN_ICD_MAGIC_VALUE;
queue->device = device;
+ queue->family_index = family_index;
+ queue->queue_index = i;
queue->flags = flags;
/* The Vulkan spec says:
@@ -365,8 +361,6 @@ static struct VkQueue_T *wine_vk_device_alloc_queues(struct VkDevice_T *device,
WINE_VK_ADD_DISPATCHABLE_MAPPING(device->phys_dev->instance, queue, queue->queue);
}
-
- return queues;
}
static void wine_vk_device_free_create_info(VkDeviceCreateInfo *create_info)
@@ -438,17 +432,18 @@ static VkResult wine_vk_device_convert_create_info(const VkDeviceCreateInfo *src
*/
static void wine_vk_device_free(struct VkDevice_T *device)
{
+ struct VkQueue_T *queue;
if (!device)
return;
if (device->queues)
{
unsigned int i;
- for (i = 0; i < device->max_queue_families; i++)
+ for (i = 0; i < device->queue_count; i++)
{
- if (device->queues[i] && device->queues[i]->queue)
- WINE_VK_REMOVE_HANDLE_MAPPING(device->phys_dev->instance, device->queues[i]);
- heap_free(device->queues[i]);
+ queue = &device->queues[i];
+ if (queue && queue->queue)
+ WINE_VK_REMOVE_HANDLE_MAPPING(device->phys_dev->instance, queue);
}
heap_free(device->queues);
device->queues = NULL;
@@ -764,7 +759,7 @@ VkResult WINAPI wine_vkCreateDevice(VkPhysicalDevice phys_dev,
const VkAllocationCallbacks *allocator, VkDevice *device)
{
VkDeviceCreateInfo create_info_host;
- uint32_t max_queue_families;
+ struct VkQueue_T *next_queue;
struct VkDevice_T *object;
unsigned int i;
VkResult res;
@@ -819,17 +814,18 @@ VkResult WINAPI wine_vkCreateDevice(VkPhysicalDevice phys_dev,
/* We need to cache all queues within the device as each requires wrapping since queues are
* dispatchable objects.
*/
- phys_dev->instance->funcs.p_vkGetPhysicalDeviceQueueFamilyProperties(phys_dev->phys_dev,
- &max_queue_families, NULL);
- object->max_queue_families = max_queue_families;
- TRACE("Max queue families: %u.\n", object->max_queue_families);
+ for (i = 0; i < create_info_host.queueCreateInfoCount; i++)
+ {
+ object->queue_count += create_info_host.pQueueCreateInfos[i].queueCount;
+ }
- if (!(object->queues = heap_calloc(max_queue_families, sizeof(*object->queues))))
+ if (!(object->queues = heap_calloc(object->queue_count, sizeof(*object->queues))))
{
res = VK_ERROR_OUT_OF_HOST_MEMORY;
goto fail;
}
+ next_queue = object->queues;
for (i = 0; i < create_info_host.queueCreateInfoCount; i++)
{
uint32_t flags = create_info_host.pQueueCreateInfos[i].flags;
@@ -838,12 +834,8 @@ VkResult WINAPI wine_vkCreateDevice(VkPhysicalDevice phys_dev,
TRACE("Queue family index %u, queue count %u.\n", family_index, queue_count);
- if (!(object->queues[family_index] = wine_vk_device_alloc_queues(object, family_index, queue_count, flags)))
- {
- ERR("Failed to allocate memory for queues.\n");
- res = VK_ERROR_OUT_OF_HOST_MEMORY;
- goto fail;
- }
+ wine_vk_device_get_queues(object, family_index, queue_count, flags, next_queue);
+ next_queue += queue_count;
}
object->quirks = phys_dev->instance->quirks;
@@ -1173,17 +1165,42 @@ PFN_vkVoidFunction WINAPI wine_vkGetDeviceProcAddr(VkDevice device, const char *
return NULL;
}
+static VkQueue wine_vk_device_find_queue(VkDevice device, const VkDeviceQueueInfo2 *info)
+{
+ struct VkQueue_T* queue;
+ uint32_t i;
+
+ for (i = 0; i < device->queue_count; i++)
+ {
+ queue = &device->queues[i];
+ if (queue->family_index == info->queueFamilyIndex
+ && queue->queue_index == info->queueIndex
+ && queue->flags == info->flags)
+ {
+ return queue;
+ }
+ }
+
+ return VK_NULL_HANDLE;
+}
+
void WINAPI wine_vkGetDeviceQueue(VkDevice device, uint32_t family_index,
uint32_t queue_index, VkQueue *queue)
{
+ VkDeviceQueueInfo2 queue_info;
TRACE("%p, %u, %u, %p\n", device, family_index, queue_index, queue);
- *queue = &device->queues[family_index][queue_index];
+ queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2;
+ queue_info.pNext = NULL;
+ queue_info.flags = 0;
+ queue_info.queueFamilyIndex = family_index;
+ queue_info.queueIndex = queue_index;
+
+ *queue = wine_vk_device_find_queue(device, &queue_info);
}
void WINAPI wine_vkGetDeviceQueue2(VkDevice device, const VkDeviceQueueInfo2 *info, VkQueue *queue)
{
- struct VkQueue_T *matching_queue;
const VkBaseInStructure *chain;
TRACE("%p, %p, %p\n", device, info, queue);
@@ -1191,13 +1208,7 @@ void WINAPI wine_vkGetDeviceQueue2(VkDevice device, const VkDeviceQueueInfo2 *in
if ((chain = info->pNext))
FIXME("Ignoring a linked structure of type %u.\n", chain->sType);
- matching_queue = &device->queues[info->queueFamilyIndex][info->queueIndex];
- if (matching_queue->flags != info->flags)
- {
- WARN("No matching flags were specified %#x, %#x.\n", matching_queue->flags, info->flags);
- matching_queue = VK_NULL_HANDLE;
- }
- *queue = matching_queue;
+ *queue = wine_vk_device_find_queue(device, info);
}
PFN_vkVoidFunction WINAPI wine_vkGetInstanceProcAddr(VkInstance instance, const char *name)
diff --git a/dlls/winevulkan/vulkan_private.h b/dlls/winevulkan/vulkan_private.h
index 322d27079ea..2b4d155ca9b 100644
--- a/dlls/winevulkan/vulkan_private.h
+++ b/dlls/winevulkan/vulkan_private.h
@@ -87,8 +87,8 @@ struct VkDevice_T
struct VkPhysicalDevice_T *phys_dev; /* parent */
VkDevice device; /* native device */
- struct VkQueue_T **queues;
- uint32_t max_queue_families;
+ struct VkQueue_T* queues;
+ uint32_t queue_count;
unsigned int quirks;
@@ -153,6 +153,8 @@ struct VkQueue_T
struct VkDevice_T *device; /* parent */
VkQueue queue; /* native queue */
+ uint32_t family_index;
+ uint32_t queue_index;
VkDeviceQueueCreateFlags flags;
struct wine_vk_mapping mapping;
--
2.31.1
More information about the wine-devel
mailing list