1 /* Wine Vulkan ICD implementation
3 * Copyright 2017 Roderick Colenbrander
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 #include "vulkan_private.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(vulkan
);
30 /* For now default to 4 as it felt like a reasonable version feature wise to support.
31 * Don't support the optional vk_icdGetPhysicalDeviceProcAddr introduced in this version
32 * as it is unlikely we will implement physical device extensions, which the loader is not
33 * aware of. Version 5 adds more extensive version checks. Something to tackle later.
35 #define WINE_VULKAN_ICD_VERSION 4
37 /* All Vulkan structures use this structure for the first elements. */
38 struct wine_vk_structure_header
40 VkStructureType sType
;
44 #define wine_vk_find_struct(s, t) wine_vk_find_struct_((void *)s, VK_STRUCTURE_TYPE_##t)
45 static void *wine_vk_find_struct_(void *s
, VkStructureType t
)
47 struct wine_vk_structure_header
*header
;
49 for (header
= s
; header
; header
= header
->pNext
)
51 if (header
->sType
== t
)
58 static void *wine_vk_get_global_proc_addr(const char *name
);
60 static const struct vulkan_funcs
*vk_funcs
;
61 static VkResult (*p_vkEnumerateInstanceVersion
)(uint32_t *version
);
63 static void wine_vk_physical_device_free(struct VkPhysicalDevice_T
*phys_dev
)
68 heap_free(phys_dev
->extensions
);
72 static struct VkPhysicalDevice_T
*wine_vk_physical_device_alloc(struct VkInstance_T
*instance
,
73 VkPhysicalDevice phys_dev
)
75 struct VkPhysicalDevice_T
*object
;
76 uint32_t num_host_properties
, num_properties
= 0;
77 VkExtensionProperties
*host_properties
= NULL
;
81 if (!(object
= heap_alloc_zero(sizeof(*object
))))
84 object
->base
.loader_magic
= VULKAN_ICD_MAGIC_VALUE
;
85 object
->instance
= instance
;
86 object
->phys_dev
= phys_dev
;
88 res
= instance
->funcs
.p_vkEnumerateDeviceExtensionProperties(phys_dev
,
89 NULL
, &num_host_properties
, NULL
);
90 if (res
!= VK_SUCCESS
)
92 ERR("Failed to enumerate device extensions, res=%d\n", res
);
96 host_properties
= heap_calloc(num_host_properties
, sizeof(*host_properties
));
99 ERR("Failed to allocate memory for device properties!\n");
103 res
= instance
->funcs
.p_vkEnumerateDeviceExtensionProperties(phys_dev
,
104 NULL
, &num_host_properties
, host_properties
);
105 if (res
!= VK_SUCCESS
)
107 ERR("Failed to enumerate device extensions, res=%d\n", res
);
111 /* Count list of extensions for which we have an implementation.
112 * TODO: perform translation for platform specific extensions.
114 for (i
= 0; i
< num_host_properties
; i
++)
116 if (wine_vk_device_extension_supported(host_properties
[i
].extensionName
))
118 TRACE("Enabling extension '%s' for physical device %p\n", host_properties
[i
].extensionName
, object
);
123 TRACE("Skipping extension '%s', no implementation found in winevulkan.\n", host_properties
[i
].extensionName
);
127 TRACE("Host supported extensions %u, Wine supported extensions %u\n", num_host_properties
, num_properties
);
129 if (!(object
->extensions
= heap_calloc(num_properties
, sizeof(*object
->extensions
))))
131 ERR("Failed to allocate memory for device extensions!\n");
135 for (i
= 0, j
= 0; i
< num_host_properties
; i
++)
137 if (wine_vk_device_extension_supported(host_properties
[i
].extensionName
))
139 object
->extensions
[j
] = host_properties
[i
];
143 object
->extension_count
= num_properties
;
145 heap_free(host_properties
);
149 wine_vk_physical_device_free(object
);
150 heap_free(host_properties
);
154 /* Helper function to release command buffers. */
155 static void wine_vk_command_buffers_free(struct VkDevice_T
*device
, VkCommandPool pool
,
156 uint32_t count
, const VkCommandBuffer
*buffers
)
160 for (i
= 0; i
< count
; i
++)
165 device
->funcs
.p_vkFreeCommandBuffers(device
->device
, pool
, 1, &buffers
[i
]->command_buffer
);
166 heap_free(buffers
[i
]);
170 /* Helper function to create queues for a given family index. */
171 static struct VkQueue_T
*wine_vk_device_alloc_queues(struct VkDevice_T
*device
,
172 uint32_t family_index
, uint32_t queue_count
, VkDeviceQueueCreateFlags flags
)
174 VkDeviceQueueInfo2 queue_info
;
175 struct VkQueue_T
*queues
;
178 if (!(queues
= heap_calloc(queue_count
, sizeof(*queues
))))
180 ERR("Failed to allocate memory for queues\n");
184 for (i
= 0; i
< queue_count
; i
++)
186 struct VkQueue_T
*queue
= &queues
[i
];
188 queue
->base
.loader_magic
= VULKAN_ICD_MAGIC_VALUE
;
189 queue
->device
= device
;
190 queue
->flags
= flags
;
192 /* The Vulkan spec says:
194 * "vkGetDeviceQueue must only be used to get queues that were created
195 * with the flags parameter of VkDeviceQueueCreateInfo set to zero."
197 if (flags
&& device
->funcs
.p_vkGetDeviceQueue2
)
199 queue_info
.sType
= VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2
;
200 queue_info
.pNext
= NULL
;
201 queue_info
.flags
= flags
;
202 queue_info
.queueFamilyIndex
= family_index
;
203 queue_info
.queueIndex
= i
;
204 device
->funcs
.p_vkGetDeviceQueue2(device
->device
, &queue_info
, &queue
->queue
);
208 device
->funcs
.p_vkGetDeviceQueue(device
->device
, family_index
, i
, &queue
->queue
);
215 static VkDeviceGroupDeviceCreateInfo
*convert_VkDeviceGroupDeviceCreateInfo(const void *src
)
217 const VkDeviceGroupDeviceCreateInfo
*in
= src
;
218 VkDeviceGroupDeviceCreateInfo
*out
;
219 VkPhysicalDevice
*physical_devices
;
222 if (!(out
= heap_alloc(sizeof(*out
))))
226 if (!(physical_devices
= heap_calloc(in
->physicalDeviceCount
, sizeof(*physical_devices
))))
231 for (i
= 0; i
< in
->physicalDeviceCount
; ++i
)
232 physical_devices
[i
] = in
->pPhysicalDevices
[i
]->phys_dev
;
233 out
->pPhysicalDevices
= physical_devices
;
238 static VkResult
wine_vk_device_convert_create_info(const VkDeviceCreateInfo
*src
,
239 VkDeviceCreateInfo
*dst
)
245 /* Application and loader can pass in a chain of extensions through pNext.
246 * We can't blindly pass these through as often these contain callbacks or
247 * they can even be pass structures for loader / ICD internal use.
251 const struct wine_vk_structure_header
*header
;
254 for (header
= src
->pNext
; header
; header
= header
->pNext
)
256 switch (header
->sType
)
258 case VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO
:
259 /* Used for loader to ICD communication. Ignore to not confuse
264 case VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO
:
265 if (!(dst
->pNext
= convert_VkDeviceGroupDeviceCreateInfo(header
)))
266 return VK_ERROR_OUT_OF_HOST_MEMORY
;
270 FIXME("Application requested a linked structure of type %#x.\n", header
->sType
);
275 /* Should be filtered out by loader as ICDs don't support layers. */
276 dst
->enabledLayerCount
= 0;
277 dst
->ppEnabledLayerNames
= NULL
;
279 TRACE("Enabled extensions: %u.\n", dst
->enabledExtensionCount
);
280 for (i
= 0; i
< dst
->enabledExtensionCount
; i
++)
282 TRACE("Extension %u: %s.\n", i
, debugstr_a(dst
->ppEnabledExtensionNames
[i
]));
288 static void wine_vk_device_free_create_info(VkDeviceCreateInfo
*create_info
)
290 VkDeviceGroupDeviceCreateInfo
*group_info
;
292 if ((group_info
= wine_vk_find_struct(create_info
, DEVICE_GROUP_DEVICE_CREATE_INFO
)))
294 heap_free((void *)group_info
->pPhysicalDevices
);
295 heap_free(group_info
);
298 create_info
->pNext
= NULL
;
301 /* Helper function used for freeing a device structure. This function supports full
302 * and partial object cleanups and can thus be used for vkCreateDevice failures.
304 static void wine_vk_device_free(struct VkDevice_T
*device
)
312 for (i
= 0; i
< device
->max_queue_families
; i
++)
314 heap_free(device
->queues
[i
]);
316 heap_free(device
->queues
);
317 device
->queues
= NULL
;
320 if (device
->device
&& device
->funcs
.p_vkDestroyDevice
)
322 device
->funcs
.p_vkDestroyDevice(device
->device
, NULL
/* pAllocator */);
328 static BOOL
wine_vk_init(void)
333 vk_funcs
= __wine_get_vulkan_driver(hdc
, WINE_VULKAN_DRIVER_VERSION
);
337 ERR("Failed to load Wine graphics driver supporting Vulkan.\n");
341 p_vkEnumerateInstanceVersion
= vk_funcs
->p_vkGetInstanceProcAddr(NULL
, "vkEnumerateInstanceVersion");
346 /* Helper function for converting between win32 and host compatible VkInstanceCreateInfo.
347 * This function takes care of extensions handled at winevulkan layer, a Wine graphics
348 * driver is responsible for handling e.g. surface extensions.
350 static void wine_vk_instance_convert_create_info(const VkInstanceCreateInfo
*src
,
351 VkInstanceCreateInfo
*dst
)
357 if (dst
->pApplicationInfo
)
359 const VkApplicationInfo
*app_info
= dst
->pApplicationInfo
;
360 TRACE("Application name %s, application version %#x\n",
361 debugstr_a(app_info
->pApplicationName
), app_info
->applicationVersion
);
362 TRACE("Engine name %s, engine version %#x\n", debugstr_a(app_info
->pEngineName
),
363 app_info
->engineVersion
);
364 TRACE("API version %#x\n", app_info
->apiVersion
);
367 /* Application and loader can pass in a chain of extensions through pNext.
368 * We can't blindly pass these through as often these contain callbacks or
369 * they can even be pass structures for loader / ICD internal use. For now
370 * we ignore everything in pNext chain, but we print FIXMEs.
374 const struct wine_vk_structure_header
*header
;
376 for (header
= src
->pNext
; header
; header
= header
->pNext
)
378 switch (header
->sType
)
380 case VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO
:
381 /* Can be used to register new dispatchable object types
382 * to the loader. We should ignore it as it will confuse the
388 FIXME("Application requested a linked structure of type %#x.\n", header
->sType
);
392 /* For now don't support anything. */
395 /* ICDs don't support any layers, so nothing to copy. Modern versions of the loader
396 * filter this data out as well.
398 dst
->enabledLayerCount
= 0;
399 dst
->ppEnabledLayerNames
= NULL
;
401 TRACE("Enabled extensions: %u\n", dst
->enabledExtensionCount
);
402 for (i
= 0; i
< dst
->enabledExtensionCount
; i
++)
404 TRACE("Extension %u: %s\n", i
, debugstr_a(dst
->ppEnabledExtensionNames
[i
]));
408 /* Helper function which stores wrapped physical devices in the instance object. */
409 static VkResult
wine_vk_instance_load_physical_devices(struct VkInstance_T
*instance
)
411 VkPhysicalDevice
*tmp_phys_devs
;
412 uint32_t phys_dev_count
;
416 res
= instance
->funcs
.p_vkEnumeratePhysicalDevices(instance
->instance
, &phys_dev_count
, NULL
);
417 if (res
!= VK_SUCCESS
)
419 ERR("Failed to enumerate physical devices, res=%d\n", res
);
425 if (!(tmp_phys_devs
= heap_calloc(phys_dev_count
, sizeof(*tmp_phys_devs
))))
426 return VK_ERROR_OUT_OF_HOST_MEMORY
;
428 res
= instance
->funcs
.p_vkEnumeratePhysicalDevices(instance
->instance
, &phys_dev_count
, tmp_phys_devs
);
429 if (res
!= VK_SUCCESS
)
431 heap_free(tmp_phys_devs
);
435 instance
->phys_devs
= heap_calloc(phys_dev_count
, sizeof(*instance
->phys_devs
));
436 if (!instance
->phys_devs
)
438 heap_free(tmp_phys_devs
);
439 return VK_ERROR_OUT_OF_HOST_MEMORY
;
442 /* Wrap each native physical device handle into a dispatchable object for the ICD loader. */
443 for (i
= 0; i
< phys_dev_count
; i
++)
445 struct VkPhysicalDevice_T
*phys_dev
= wine_vk_physical_device_alloc(instance
, tmp_phys_devs
[i
]);
448 ERR("Unable to allocate memory for physical device!\n");
449 heap_free(tmp_phys_devs
);
450 return VK_ERROR_OUT_OF_HOST_MEMORY
;
453 instance
->phys_devs
[i
] = phys_dev
;
454 instance
->phys_dev_count
= i
+ 1;
456 instance
->phys_dev_count
= phys_dev_count
;
458 heap_free(tmp_phys_devs
);
462 static struct VkPhysicalDevice_T
*wine_vk_instance_wrap_physical_device(struct VkInstance_T
*instance
,
463 VkPhysicalDevice physical_device
)
467 for (i
= 0; i
< instance
->phys_dev_count
; ++i
)
469 struct VkPhysicalDevice_T
*current
= instance
->phys_devs
[i
];
470 if (current
->phys_dev
== physical_device
)
474 ERR("Unrecognized physical device %p.\n", physical_device
);
478 /* Helper function used for freeing an instance structure. This function supports full
479 * and partial object cleanups and can thus be used for vkCreateInstance failures.
481 static void wine_vk_instance_free(struct VkInstance_T
*instance
)
486 if (instance
->phys_devs
)
490 for (i
= 0; i
< instance
->phys_dev_count
; i
++)
492 wine_vk_physical_device_free(instance
->phys_devs
[i
]);
494 heap_free(instance
->phys_devs
);
497 if (instance
->instance
)
498 vk_funcs
->p_vkDestroyInstance(instance
->instance
, NULL
/* allocator */);
503 VkResult WINAPI
wine_vkAllocateCommandBuffers(VkDevice device
,
504 const VkCommandBufferAllocateInfo
*allocate_info
, VkCommandBuffer
*buffers
)
506 VkResult res
= VK_SUCCESS
;
509 TRACE("%p %p %p\n", device
, allocate_info
, buffers
);
511 memset(buffers
, 0, allocate_info
->commandBufferCount
* sizeof(*buffers
));
513 for (i
= 0; i
< allocate_info
->commandBufferCount
; i
++)
515 #if defined(USE_STRUCT_CONVERSION)
516 VkCommandBufferAllocateInfo_host allocate_info_host
;
518 VkCommandBufferAllocateInfo allocate_info_host
;
520 /* TODO: future extensions (none yet) may require pNext conversion. */
521 allocate_info_host
.pNext
= allocate_info
->pNext
;
522 allocate_info_host
.sType
= allocate_info
->sType
;
523 allocate_info_host
.commandPool
= allocate_info
->commandPool
;
524 allocate_info_host
.level
= allocate_info
->level
;
525 allocate_info_host
.commandBufferCount
= 1;
527 TRACE("Creating command buffer %u, pool 0x%s, level %#x\n", i
,
528 wine_dbgstr_longlong(allocate_info_host
.commandPool
),
529 allocate_info_host
.level
);
531 if (!(buffers
[i
] = heap_alloc_zero(sizeof(**buffers
))))
533 res
= VK_ERROR_OUT_OF_HOST_MEMORY
;
537 buffers
[i
]->base
.loader_magic
= VULKAN_ICD_MAGIC_VALUE
;
538 buffers
[i
]->device
= device
;
539 res
= device
->funcs
.p_vkAllocateCommandBuffers(device
->device
,
540 &allocate_info_host
, &buffers
[i
]->command_buffer
);
541 if (res
!= VK_SUCCESS
)
543 ERR("Failed to allocate command buffer, res=%d\n", res
);
548 if (res
!= VK_SUCCESS
)
550 wine_vk_command_buffers_free(device
, allocate_info
->commandPool
, i
, buffers
);
551 memset(buffers
, 0, allocate_info
->commandBufferCount
* sizeof(*buffers
));
558 void WINAPI
wine_vkCmdExecuteCommands(VkCommandBuffer buffer
, uint32_t count
,
559 const VkCommandBuffer
*buffers
)
561 VkCommandBuffer
*tmp_buffers
;
564 TRACE("%p %u %p\n", buffer
, count
, buffers
);
566 if (!buffers
|| !count
)
569 /* Unfortunately we need a temporary buffer as our command buffers are wrapped.
570 * This call is called often and if a performance concern, we may want to use
571 * alloca as we shouldn't need much memory and it needs to be cleaned up after
574 if (!(tmp_buffers
= heap_alloc(count
* sizeof(*tmp_buffers
))))
576 ERR("Failed to allocate memory for temporary command buffers\n");
580 for (i
= 0; i
< count
; i
++)
581 tmp_buffers
[i
] = buffers
[i
]->command_buffer
;
583 buffer
->device
->funcs
.p_vkCmdExecuteCommands(buffer
->command_buffer
, count
, tmp_buffers
);
585 heap_free(tmp_buffers
);
588 VkResult WINAPI
wine_vkCreateDevice(VkPhysicalDevice phys_dev
,
589 const VkDeviceCreateInfo
*create_info
,
590 const VkAllocationCallbacks
*allocator
, VkDevice
*device
)
592 VkDeviceCreateInfo create_info_host
;
593 uint32_t max_queue_families
;
594 struct VkDevice_T
*object
;
598 TRACE("%p, %p, %p, %p\n", phys_dev
, create_info
, allocator
, device
);
601 FIXME("Support for allocation callbacks not implemented yet\n");
603 if (!(object
= heap_alloc_zero(sizeof(*object
))))
604 return VK_ERROR_OUT_OF_HOST_MEMORY
;
606 object
->base
.loader_magic
= VULKAN_ICD_MAGIC_VALUE
;
608 res
= wine_vk_device_convert_create_info(create_info
, &create_info_host
);
609 if (res
!= VK_SUCCESS
)
611 ERR("Failed to convert VkDeviceCreateInfo, res=%d.\n", res
);
612 wine_vk_device_free(object
);
616 res
= phys_dev
->instance
->funcs
.p_vkCreateDevice(phys_dev
->phys_dev
,
617 &create_info_host
, NULL
/* allocator */, &object
->device
);
618 wine_vk_device_free_create_info(&create_info_host
);
619 if (res
!= VK_SUCCESS
)
621 ERR("Failed to create device.\n");
622 wine_vk_device_free(object
);
626 /* Just load all function pointers we are aware off. The loader takes care of filtering.
627 * We use vkGetDeviceProcAddr as opposed to vkGetInstanceProcAddr for efficiency reasons
628 * as functions pass through fewer dispatch tables within the loader.
630 #define USE_VK_FUNC(name) \
631 object->funcs.p_##name = (void *)vk_funcs->p_vkGetDeviceProcAddr(object->device, #name); \
632 if (object->funcs.p_##name == NULL) \
633 TRACE("Not found %s\n", #name);
634 ALL_VK_DEVICE_FUNCS()
637 /* We need to cache all queues within the device as each requires wrapping since queues are
638 * dispatchable objects.
640 phys_dev
->instance
->funcs
.p_vkGetPhysicalDeviceQueueFamilyProperties(phys_dev
->phys_dev
,
641 &max_queue_families
, NULL
);
642 object
->max_queue_families
= max_queue_families
;
643 TRACE("Max queue families: %u\n", object
->max_queue_families
);
645 object
->queues
= heap_calloc(max_queue_families
, sizeof(*object
->queues
));
648 wine_vk_device_free(object
);
649 return VK_ERROR_OUT_OF_HOST_MEMORY
;
652 for (i
= 0; i
< create_info_host
.queueCreateInfoCount
; i
++)
654 uint32_t flags
= create_info_host
.pQueueCreateInfos
[i
].flags
;
655 uint32_t family_index
= create_info_host
.pQueueCreateInfos
[i
].queueFamilyIndex
;
656 uint32_t queue_count
= create_info_host
.pQueueCreateInfos
[i
].queueCount
;
658 TRACE("queueFamilyIndex %u, queueCount %u\n", family_index
, queue_count
);
660 object
->queues
[family_index
] = wine_vk_device_alloc_queues(object
, family_index
,
662 if (!object
->queues
[family_index
])
664 ERR("Failed to allocate memory for queues\n");
665 wine_vk_device_free(object
);
666 return VK_ERROR_OUT_OF_HOST_MEMORY
;
670 object
->quirks
= phys_dev
->instance
->quirks
;
673 TRACE("Created device %p (native device %p).\n", object
, object
->device
);
677 VkResult WINAPI
wine_vkCreateInstance(const VkInstanceCreateInfo
*create_info
,
678 const VkAllocationCallbacks
*allocator
, VkInstance
*instance
)
680 VkInstanceCreateInfo create_info_host
;
681 const VkApplicationInfo
*app_info
;
682 struct VkInstance_T
*object
;
685 TRACE("create_info %p, allocator %p, instance %p\n", create_info
, allocator
, instance
);
688 FIXME("Support for allocation callbacks not implemented yet\n");
690 if (!(object
= heap_alloc_zero(sizeof(*object
))))
692 ERR("Failed to allocate memory for instance\n");
693 return VK_ERROR_OUT_OF_HOST_MEMORY
;
695 object
->base
.loader_magic
= VULKAN_ICD_MAGIC_VALUE
;
697 wine_vk_instance_convert_create_info(create_info
, &create_info_host
);
699 res
= vk_funcs
->p_vkCreateInstance(&create_info_host
, NULL
/* allocator */, &object
->instance
);
700 if (res
!= VK_SUCCESS
)
702 ERR("Failed to create instance, res=%d\n", res
);
703 wine_vk_instance_free(object
);
707 /* Load all instance functions we are aware of. Note the loader takes care
708 * of any filtering for extensions which were not requested, but which the
711 #define USE_VK_FUNC(name) \
712 object->funcs.p_##name = (void *)vk_funcs->p_vkGetInstanceProcAddr(object->instance, #name);
713 ALL_VK_INSTANCE_FUNCS()
716 /* Cache physical devices for vkEnumeratePhysicalDevices within the instance as
717 * each vkPhysicalDevice is a dispatchable object, which means we need to wrap
718 * the native physical devices and present those to the application.
719 * Cleanup happens as part of wine_vkDestroyInstance.
721 res
= wine_vk_instance_load_physical_devices(object
);
722 if (res
!= VK_SUCCESS
)
724 ERR("Failed to load physical devices, res=%d\n", res
);
725 wine_vk_instance_free(object
);
729 if ((app_info
= create_info
->pApplicationInfo
) && app_info
->pApplicationName
)
731 if (!strcmp(app_info
->pApplicationName
, "DOOM")
732 || !strcmp(app_info
->pApplicationName
, "Wolfenstein II The New Colossus"))
733 object
->quirks
|= WINEVULKAN_QUIRK_GET_DEVICE_PROC_ADDR
;
737 TRACE("Created instance %p (native instance %p).\n", object
, object
->instance
);
741 void WINAPI
wine_vkDestroyDevice(VkDevice device
, const VkAllocationCallbacks
*allocator
)
743 TRACE("%p %p\n", device
, allocator
);
746 FIXME("Support for allocation callbacks not implemented yet\n");
748 wine_vk_device_free(device
);
751 void WINAPI
wine_vkDestroyInstance(VkInstance instance
, const VkAllocationCallbacks
*allocator
)
753 TRACE("%p, %p\n", instance
, allocator
);
756 FIXME("Support allocation allocators\n");
758 wine_vk_instance_free(instance
);
761 VkResult WINAPI
wine_vkEnumerateDeviceExtensionProperties(VkPhysicalDevice phys_dev
,
762 const char *layer_name
, uint32_t *count
, VkExtensionProperties
*properties
)
764 TRACE("%p, %p, %p, %p\n", phys_dev
, layer_name
, count
, properties
);
766 /* This shouldn't get called with layer_name set, the ICD loader prevents it. */
769 ERR("Layer enumeration not supported from ICD.\n");
770 return VK_ERROR_LAYER_NOT_PRESENT
;
775 *count
= phys_dev
->extension_count
;
779 *count
= min(*count
, phys_dev
->extension_count
);
780 memcpy(properties
, phys_dev
->extensions
, *count
* sizeof(*properties
));
782 TRACE("Returning %u extensions.\n", *count
);
783 return *count
< phys_dev
->extension_count
? VK_INCOMPLETE
: VK_SUCCESS
;
786 VkResult WINAPI
wine_vkEnumerateInstanceExtensionProperties(const char *layer_name
,
787 uint32_t *count
, VkExtensionProperties
*properties
)
789 uint32_t num_properties
= 0, num_host_properties
;
790 VkExtensionProperties
*host_properties
;
794 TRACE("%p, %p, %p\n", layer_name
, count
, properties
);
798 WARN("Layer enumeration not supported from ICD.\n");
799 return VK_ERROR_LAYER_NOT_PRESENT
;
802 res
= vk_funcs
->p_vkEnumerateInstanceExtensionProperties(NULL
, &num_host_properties
, NULL
);
803 if (res
!= VK_SUCCESS
)
806 if (!(host_properties
= heap_calloc(num_host_properties
, sizeof(*host_properties
))))
807 return VK_ERROR_OUT_OF_HOST_MEMORY
;
809 res
= vk_funcs
->p_vkEnumerateInstanceExtensionProperties(NULL
, &num_host_properties
, host_properties
);
810 if (res
!= VK_SUCCESS
)
812 ERR("Failed to retrieve host properties, res=%d.\n", res
);
813 heap_free(host_properties
);
817 /* The Wine graphics driver provides us with all extensions supported by the host side
818 * including extension fixup (e.g. VK_KHR_xlib_surface -> VK_KHR_win32_surface). It is
819 * up to us here to filter the list down to extensions for which we have thunks.
821 for (i
= 0; i
< num_host_properties
; i
++)
823 if (wine_vk_instance_extension_supported(host_properties
[i
].extensionName
))
826 TRACE("Instance extension '%s' is not supported.\n", host_properties
[i
].extensionName
);
831 TRACE("Returning %u extensions.\n", num_properties
);
832 *count
= num_properties
;
833 heap_free(host_properties
);
837 for (i
= 0, j
= 0; i
< num_host_properties
&& j
< *count
; i
++)
839 if (wine_vk_instance_extension_supported(host_properties
[i
].extensionName
))
841 TRACE("Enabling extension '%s'.\n", host_properties
[i
].extensionName
);
842 properties
[j
++] = host_properties
[i
];
845 *count
= min(*count
, num_properties
);
847 heap_free(host_properties
);
848 return *count
< num_properties
? VK_INCOMPLETE
: VK_SUCCESS
;
851 VkResult WINAPI
wine_vkEnumerateInstanceLayerProperties(uint32_t *count
, VkLayerProperties
*properties
)
853 TRACE("%p, %p\n", count
, properties
);
861 return VK_ERROR_LAYER_NOT_PRESENT
;
864 VkResult WINAPI
wine_vkEnumerateInstanceVersion(uint32_t *version
)
868 TRACE("%p\n", version
);
870 if (p_vkEnumerateInstanceVersion
)
872 res
= p_vkEnumerateInstanceVersion(version
);
876 *version
= VK_API_VERSION_1_0
;
880 TRACE("API version %u.%u.%u.\n",
881 VK_VERSION_MAJOR(*version
), VK_VERSION_MINOR(*version
), VK_VERSION_PATCH(*version
));
882 *version
= min(WINE_VK_VERSION
, *version
);
886 VkResult WINAPI
wine_vkEnumeratePhysicalDevices(VkInstance instance
, uint32_t *count
,
887 VkPhysicalDevice
*devices
)
891 TRACE("%p %p %p\n", instance
, count
, devices
);
895 *count
= instance
->phys_dev_count
;
899 *count
= min(*count
, instance
->phys_dev_count
);
900 for (i
= 0; i
< *count
; i
++)
902 devices
[i
] = instance
->phys_devs
[i
];
905 TRACE("Returning %u devices.\n", *count
);
906 return *count
< instance
->phys_dev_count
? VK_INCOMPLETE
: VK_SUCCESS
;
909 void WINAPI
wine_vkFreeCommandBuffers(VkDevice device
, VkCommandPool pool
, uint32_t count
,
910 const VkCommandBuffer
*buffers
)
912 TRACE("%p 0x%s %u %p\n", device
, wine_dbgstr_longlong(pool
), count
, buffers
);
914 wine_vk_command_buffers_free(device
, pool
, count
, buffers
);
917 PFN_vkVoidFunction WINAPI
wine_vkGetDeviceProcAddr(VkDevice device
, const char *name
)
920 TRACE("%p, %s\n", device
, debugstr_a(name
));
922 /* The spec leaves return value undefined for a NULL device, let's just return NULL. */
923 if (!device
|| !name
)
926 /* Per the spec, we are only supposed to return device functions as in functions
927 * for which the first parameter is vkDevice or a child of vkDevice like a
928 * vkCommandBuffer or vkQueue.
929 * Loader takes care of filtering of extensions which are enabled or not.
931 func
= wine_vk_get_device_proc_addr(name
);
935 /* vkGetDeviceProcAddr was intended for loading device and subdevice functions.
936 * idTech 6 titles such as Doom and Wolfenstein II, however use it also for
937 * loading of instance functions. This is undefined behavior as the specification
938 * disallows using any of the returned function pointers outside of device /
939 * subdevice objects. The games don't actually use the function pointers and if they
940 * did, they would crash as VkInstance / VkPhysicalDevice parameters need unwrapping.
941 * Khronos clarified behavior in the Vulkan spec and expects drivers to get updated,
942 * however it would require both driver and game fixes.
943 * https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/issues/2323
944 * https://github.com/KhronosGroup/Vulkan-Docs/issues/655
946 if (device
->quirks
& WINEVULKAN_QUIRK_GET_DEVICE_PROC_ADDR
947 && (func
= wine_vk_get_instance_proc_addr(name
)))
949 WARN("Returning instance function %s.\n", debugstr_a(name
));
953 WARN("Unsupported device function: %s.\n", debugstr_a(name
));
957 void WINAPI
wine_vkGetDeviceQueue(VkDevice device
, uint32_t family_index
,
958 uint32_t queue_index
, VkQueue
*queue
)
960 TRACE("%p, %u, %u, %p\n", device
, family_index
, queue_index
, queue
);
962 *queue
= &device
->queues
[family_index
][queue_index
];
965 void WINAPI
wine_vkGetDeviceQueue2(VkDevice device
, const VkDeviceQueueInfo2
*info
, VkQueue
*queue
)
967 const struct wine_vk_structure_header
*chain
;
968 struct VkQueue_T
*matching_queue
;
970 TRACE("%p, %p, %p\n", device
, info
, queue
);
972 if ((chain
= info
->pNext
))
973 FIXME("Ignoring a linked structure of type %#x.\n", chain
->sType
);
975 matching_queue
= &device
->queues
[info
->queueFamilyIndex
][info
->queueIndex
];
976 if (matching_queue
->flags
!= info
->flags
)
978 WARN("No matching flags were specified %#x, %#x.\n", matching_queue
->flags
, info
->flags
);
979 matching_queue
= VK_NULL_HANDLE
;
981 *queue
= matching_queue
;
984 PFN_vkVoidFunction WINAPI
wine_vkGetInstanceProcAddr(VkInstance instance
, const char *name
)
988 TRACE("%p, %s\n", instance
, debugstr_a(name
));
993 /* vkGetInstanceProcAddr can load most Vulkan functions when an instance is passed in, however
994 * for a NULL instance it can only load global functions.
996 func
= wine_vk_get_global_proc_addr(name
);
1003 WARN("Global function %s not found.\n", debugstr_a(name
));
1007 func
= wine_vk_get_instance_proc_addr(name
);
1008 if (func
) return func
;
1010 /* vkGetInstanceProcAddr also loads any children of instance, so device functions as well. */
1011 func
= wine_vk_get_device_proc_addr(name
);
1012 if (func
) return func
;
1014 WARN("Unsupported device or instance function: %s.\n", debugstr_a(name
));
1018 void * WINAPI
wine_vk_icdGetInstanceProcAddr(VkInstance instance
, const char *name
)
1020 TRACE("%p, %s\n", instance
, debugstr_a(name
));
1022 /* Initial version of the Vulkan ICD spec required vkGetInstanceProcAddr to be
1023 * exported. vk_icdGetInstanceProcAddr was added later to separate ICD calls from
1024 * Vulkan API. One of them in our case should forward to the other, so just forward
1025 * to the older vkGetInstanceProcAddr.
1027 return wine_vkGetInstanceProcAddr(instance
, name
);
1030 VkResult WINAPI
wine_vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t *supported_version
)
1032 uint32_t req_version
;
1034 TRACE("%p\n", supported_version
);
1036 /* The spec is not clear how to handle this. Mesa drivers don't check, but it
1037 * is probably best to not explode. VK_INCOMPLETE seems to be the closest value.
1039 if (!supported_version
)
1040 return VK_INCOMPLETE
;
1042 req_version
= *supported_version
;
1043 *supported_version
= min(req_version
, WINE_VULKAN_ICD_VERSION
);
1044 TRACE("Loader requested ICD version %u, returning %u\n", req_version
, *supported_version
);
1049 VkResult WINAPI
wine_vkQueueSubmit(VkQueue queue
, uint32_t count
,
1050 const VkSubmitInfo
*submits
, VkFence fence
)
1052 VkSubmitInfo
*submits_host
;
1054 VkCommandBuffer
*command_buffers
;
1055 unsigned int i
, j
, num_command_buffers
;
1057 TRACE("%p %u %p 0x%s\n", queue
, count
, submits
, wine_dbgstr_longlong(fence
));
1061 return queue
->device
->funcs
.p_vkQueueSubmit(queue
->queue
, 0, NULL
, fence
);
1064 submits_host
= heap_calloc(count
, sizeof(*submits_host
));
1067 ERR("Unable to allocate memory for submit buffers!\n");
1068 return VK_ERROR_OUT_OF_HOST_MEMORY
;
1071 for (i
= 0; i
< count
; i
++)
1073 memcpy(&submits_host
[i
], &submits
[i
], sizeof(*submits_host
));
1075 num_command_buffers
= submits
[i
].commandBufferCount
;
1076 command_buffers
= heap_calloc(num_command_buffers
, sizeof(*submits_host
));
1077 if (!command_buffers
)
1079 ERR("Unable to allocate memory for comman buffers!\n");
1080 res
= VK_ERROR_OUT_OF_HOST_MEMORY
;
1084 for (j
= 0; j
< num_command_buffers
; j
++)
1086 command_buffers
[j
] = submits
[i
].pCommandBuffers
[j
]->command_buffer
;
1088 submits_host
[i
].pCommandBuffers
= command_buffers
;
1091 res
= queue
->device
->funcs
.p_vkQueueSubmit(queue
->queue
, count
, submits_host
, fence
);
1094 for (i
= 0; i
< count
; i
++)
1096 heap_free((void *)submits_host
[i
].pCommandBuffers
);
1098 heap_free(submits_host
);
1100 TRACE("Returning %d\n", res
);
1104 static VkResult
wine_vk_enumerate_physical_device_groups(struct VkInstance_T
*instance
,
1105 VkResult (*p_vkEnumeratePhysicalDeviceGroups
)(VkInstance
, uint32_t *, VkPhysicalDeviceGroupProperties
*),
1106 uint32_t *count
, VkPhysicalDeviceGroupProperties
*properties
)
1111 res
= p_vkEnumeratePhysicalDeviceGroups(instance
->instance
, count
, properties
);
1112 if (res
< 0 || !properties
)
1115 for (i
= 0; i
< *count
; ++i
)
1117 VkPhysicalDeviceGroupProperties
*current
= &properties
[i
];
1118 for (j
= 0; j
< current
->physicalDeviceCount
; ++j
)
1120 VkPhysicalDevice dev
= current
->physicalDevices
[j
];
1121 if (!(current
->physicalDevices
[j
] = wine_vk_instance_wrap_physical_device(instance
, dev
)))
1122 return VK_ERROR_INITIALIZATION_FAILED
;
1129 VkResult WINAPI
wine_vkEnumeratePhysicalDeviceGroups(VkInstance instance
,
1130 uint32_t *count
, VkPhysicalDeviceGroupProperties
*properties
)
1132 TRACE("%p, %p, %p\n", instance
, count
, properties
);
1133 return wine_vk_enumerate_physical_device_groups(instance
,
1134 instance
->funcs
.p_vkEnumeratePhysicalDeviceGroups
, count
, properties
);
1137 VkResult WINAPI
wine_vkEnumeratePhysicalDeviceGroupsKHR(VkInstance instance
,
1138 uint32_t *count
, VkPhysicalDeviceGroupProperties
*properties
)
1140 TRACE("%p, %p, %p\n", instance
, count
, properties
);
1141 return wine_vk_enumerate_physical_device_groups(instance
,
1142 instance
->funcs
.p_vkEnumeratePhysicalDeviceGroupsKHR
, count
, properties
);
1145 BOOL WINAPI
DllMain(HINSTANCE hinst
, DWORD reason
, void *reserved
)
1147 TRACE("%p, %u, %p\n", hinst
, reason
, reserved
);
1151 case DLL_PROCESS_ATTACH
:
1152 DisableThreadLibraryCalls(hinst
);
1153 return wine_vk_init();
1158 static const struct vulkan_func vk_global_dispatch_table
[] =
1160 {"vkCreateInstance", &wine_vkCreateInstance
},
1161 {"vkEnumerateInstanceExtensionProperties", &wine_vkEnumerateInstanceExtensionProperties
},
1162 {"vkEnumerateInstanceLayerProperties", &wine_vkEnumerateInstanceLayerProperties
},
1163 {"vkEnumerateInstanceVersion", &wine_vkEnumerateInstanceVersion
},
1164 {"vkGetInstanceProcAddr", &wine_vkGetInstanceProcAddr
},
1167 static void *wine_vk_get_global_proc_addr(const char *name
)
1171 for (i
= 0; i
< ARRAY_SIZE(vk_global_dispatch_table
); i
++)
1173 if (strcmp(name
, vk_global_dispatch_table
[i
].name
) == 0)
1175 TRACE("Found name=%s in global table\n", debugstr_a(name
));
1176 return vk_global_dispatch_table
[i
].func
;
1183 * Wrapper around driver vkGetInstanceProcAddr implementation.
1184 * Allows winelib applications to access Vulkan functions with Wine
1185 * additions and native ABI.
1187 void *native_vkGetInstanceProcAddrWINE(VkInstance instance
, const char *name
)
1189 return vk_funcs
->p_vkGetInstanceProcAddr(instance
, name
);