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
30 #define WIN32_NO_STATUS
37 #include "vulkan_private.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(vulkan
);
41 #define wine_vk_find_struct(s, t) wine_vk_find_struct_((void *)s, VK_STRUCTURE_TYPE_##t)
42 static void *wine_vk_find_struct_(void *s
, VkStructureType t
)
44 VkBaseOutStructure
*header
;
46 for (header
= s
; header
; header
= header
->pNext
)
48 if (header
->sType
== t
)
55 #define wine_vk_count_struct(s, t) wine_vk_count_struct_((void *)s, VK_STRUCTURE_TYPE_##t)
56 static uint32_t wine_vk_count_struct_(void *s
, VkStructureType t
)
58 const VkBaseInStructure
*header
;
61 for (header
= s
; header
; header
= header
->pNext
)
63 if (header
->sType
== t
)
70 static const struct vulkan_funcs
*vk_funcs
;
71 static VkResult (*p_vkEnumerateInstanceVersion
)(uint32_t *version
);
73 void WINAPI
wine_vkGetPhysicalDeviceProperties(VkPhysicalDevice physical_device
,
74 VkPhysicalDeviceProperties
*properties
);
76 #define WINE_VK_ADD_DISPATCHABLE_MAPPING(instance, object, native_handle) \
77 wine_vk_add_handle_mapping((instance), (uint64_t) (uintptr_t) (object), (uint64_t) (uintptr_t) (native_handle), &(object)->mapping)
78 #define WINE_VK_ADD_NON_DISPATCHABLE_MAPPING(instance, object, native_handle) \
79 wine_vk_add_handle_mapping((instance), (uint64_t) (uintptr_t) (object), (uint64_t) (native_handle), &(object)->mapping)
80 static void wine_vk_add_handle_mapping(struct VkInstance_T
*instance
, uint64_t wrapped_handle
,
81 uint64_t native_handle
, struct wine_vk_mapping
*mapping
)
83 if (instance
->enable_wrapper_list
)
85 mapping
->native_handle
= native_handle
;
86 mapping
->wine_wrapped_handle
= wrapped_handle
;
87 pthread_rwlock_wrlock(&instance
->wrapper_lock
);
88 list_add_tail(&instance
->wrappers
, &mapping
->link
);
89 pthread_rwlock_unlock(&instance
->wrapper_lock
);
93 #define WINE_VK_REMOVE_HANDLE_MAPPING(instance, object) \
94 wine_vk_remove_handle_mapping((instance), &(object)->mapping)
95 static void wine_vk_remove_handle_mapping(struct VkInstance_T
*instance
, struct wine_vk_mapping
*mapping
)
97 if (instance
->enable_wrapper_list
)
99 pthread_rwlock_wrlock(&instance
->wrapper_lock
);
100 list_remove(&mapping
->link
);
101 pthread_rwlock_unlock(&instance
->wrapper_lock
);
105 static uint64_t wine_vk_get_wrapper(struct VkInstance_T
*instance
, uint64_t native_handle
)
107 struct wine_vk_mapping
*mapping
;
110 pthread_rwlock_rdlock(&instance
->wrapper_lock
);
111 LIST_FOR_EACH_ENTRY(mapping
, &instance
->wrappers
, struct wine_vk_mapping
, link
)
113 if (mapping
->native_handle
== native_handle
)
115 result
= mapping
->wine_wrapped_handle
;
119 pthread_rwlock_unlock(&instance
->wrapper_lock
);
123 static VkBool32
debug_utils_callback_conversion(VkDebugUtilsMessageSeverityFlagBitsEXT severity
,
124 VkDebugUtilsMessageTypeFlagsEXT message_types
,
125 const VkDebugUtilsMessengerCallbackDataEXT_host
*callback_data
,
128 struct VkDebugUtilsMessengerCallbackDataEXT wine_callback_data
;
129 VkDebugUtilsObjectNameInfoEXT
*object_name_infos
;
130 struct wine_debug_utils_messenger
*object
;
134 TRACE("%i, %u, %p, %p\n", severity
, message_types
, callback_data
, user_data
);
138 if (!object
->instance
->instance
)
140 /* instance wasn't yet created, this is a message from the native loader */
144 wine_callback_data
= *((VkDebugUtilsMessengerCallbackDataEXT
*) callback_data
);
146 object_name_infos
= RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY
,
147 wine_callback_data
.objectCount
* sizeof(*object_name_infos
));
149 for (i
= 0; i
< wine_callback_data
.objectCount
; i
++)
151 object_name_infos
[i
].sType
= callback_data
->pObjects
[i
].sType
;
152 object_name_infos
[i
].pNext
= callback_data
->pObjects
[i
].pNext
;
153 object_name_infos
[i
].objectType
= callback_data
->pObjects
[i
].objectType
;
154 object_name_infos
[i
].pObjectName
= callback_data
->pObjects
[i
].pObjectName
;
156 if (wine_vk_is_type_wrapped(callback_data
->pObjects
[i
].objectType
))
158 object_name_infos
[i
].objectHandle
= wine_vk_get_wrapper(object
->instance
, callback_data
->pObjects
[i
].objectHandle
);
159 if (!object_name_infos
[i
].objectHandle
)
161 WARN("handle conversion failed 0x%s\n", wine_dbgstr_longlong(callback_data
->pObjects
[i
].objectHandle
));
162 RtlFreeHeap(GetProcessHeap(), 0, object_name_infos
);
168 object_name_infos
[i
].objectHandle
= callback_data
->pObjects
[i
].objectHandle
;
172 wine_callback_data
.pObjects
= object_name_infos
;
174 /* applications should always return VK_FALSE */
175 result
= object
->user_callback(severity
, message_types
, &wine_callback_data
, object
->user_data
);
177 RtlFreeHeap(GetProcessHeap(), 0, object_name_infos
);
182 static VkBool32
debug_report_callback_conversion(VkDebugReportFlagsEXT flags
, VkDebugReportObjectTypeEXT object_type
,
183 uint64_t object_handle
, size_t location
, int32_t code
, const char *layer_prefix
, const char *message
, void *user_data
)
185 struct wine_debug_report_callback
*object
;
187 TRACE("%#x, %#x, 0x%s, 0x%s, %d, %p, %p, %p\n", flags
, object_type
, wine_dbgstr_longlong(object_handle
),
188 wine_dbgstr_longlong(location
), code
, layer_prefix
, message
, user_data
);
192 if (!object
->instance
->instance
)
194 /* instance wasn't yet created, this is a message from the native loader */
198 object_handle
= wine_vk_get_wrapper(object
->instance
, object_handle
);
200 object_type
= VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT
;
202 return object
->user_callback(
203 flags
, object_type
, object_handle
, location
, code
, layer_prefix
, message
, object
->user_data
);
206 static void wine_vk_physical_device_free(struct VkPhysicalDevice_T
*phys_dev
)
211 WINE_VK_REMOVE_HANDLE_MAPPING(phys_dev
->instance
, phys_dev
);
212 free(phys_dev
->extensions
);
216 static struct VkPhysicalDevice_T
*wine_vk_physical_device_alloc(struct VkInstance_T
*instance
,
217 VkPhysicalDevice phys_dev
)
219 struct VkPhysicalDevice_T
*object
;
220 uint32_t num_host_properties
, num_properties
= 0;
221 VkExtensionProperties
*host_properties
= NULL
;
225 if (!(object
= calloc(1, sizeof(*object
))))
228 object
->base
.loader_magic
= VULKAN_ICD_MAGIC_VALUE
;
229 object
->instance
= instance
;
230 object
->phys_dev
= phys_dev
;
232 WINE_VK_ADD_DISPATCHABLE_MAPPING(instance
, object
, phys_dev
);
234 res
= instance
->funcs
.p_vkEnumerateDeviceExtensionProperties(phys_dev
,
235 NULL
, &num_host_properties
, NULL
);
236 if (res
!= VK_SUCCESS
)
238 ERR("Failed to enumerate device extensions, res=%d\n", res
);
242 host_properties
= calloc(num_host_properties
, sizeof(*host_properties
));
243 if (!host_properties
)
245 ERR("Failed to allocate memory for device properties!\n");
249 res
= instance
->funcs
.p_vkEnumerateDeviceExtensionProperties(phys_dev
,
250 NULL
, &num_host_properties
, host_properties
);
251 if (res
!= VK_SUCCESS
)
253 ERR("Failed to enumerate device extensions, res=%d\n", res
);
257 /* Count list of extensions for which we have an implementation.
258 * TODO: perform translation for platform specific extensions.
260 for (i
= 0; i
< num_host_properties
; i
++)
262 if (wine_vk_device_extension_supported(host_properties
[i
].extensionName
))
264 TRACE("Enabling extension '%s' for physical device %p\n", host_properties
[i
].extensionName
, object
);
269 TRACE("Skipping extension '%s', no implementation found in winevulkan.\n", host_properties
[i
].extensionName
);
273 TRACE("Host supported extensions %u, Wine supported extensions %u\n", num_host_properties
, num_properties
);
275 if (!(object
->extensions
= calloc(num_properties
, sizeof(*object
->extensions
))))
277 ERR("Failed to allocate memory for device extensions!\n");
281 for (i
= 0, j
= 0; i
< num_host_properties
; i
++)
283 if (wine_vk_device_extension_supported(host_properties
[i
].extensionName
))
285 object
->extensions
[j
] = host_properties
[i
];
289 object
->extension_count
= num_properties
;
291 free(host_properties
);
295 wine_vk_physical_device_free(object
);
296 free(host_properties
);
300 static void wine_vk_free_command_buffers(struct VkDevice_T
*device
,
301 struct wine_cmd_pool
*pool
, uint32_t count
, const VkCommandBuffer
*buffers
)
305 for (i
= 0; i
< count
; i
++)
310 device
->funcs
.p_vkFreeCommandBuffers(device
->device
, pool
->command_pool
, 1, &buffers
[i
]->command_buffer
);
311 list_remove(&buffers
[i
]->pool_link
);
312 WINE_VK_REMOVE_HANDLE_MAPPING(device
->phys_dev
->instance
, buffers
[i
]);
317 static void wine_vk_device_get_queues(struct VkDevice_T
*device
,
318 uint32_t family_index
, uint32_t queue_count
, VkDeviceQueueCreateFlags flags
,
319 struct VkQueue_T
* queues
)
321 VkDeviceQueueInfo2 queue_info
;
324 for (i
= 0; i
< queue_count
; i
++)
326 struct VkQueue_T
*queue
= &queues
[i
];
328 queue
->base
.loader_magic
= VULKAN_ICD_MAGIC_VALUE
;
329 queue
->device
= device
;
330 queue
->family_index
= family_index
;
331 queue
->queue_index
= i
;
332 queue
->flags
= flags
;
334 /* The Vulkan spec says:
336 * "vkGetDeviceQueue must only be used to get queues that were created
337 * with the flags parameter of VkDeviceQueueCreateInfo set to zero."
339 if (flags
&& device
->funcs
.p_vkGetDeviceQueue2
)
341 queue_info
.sType
= VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2
;
342 queue_info
.pNext
= NULL
;
343 queue_info
.flags
= flags
;
344 queue_info
.queueFamilyIndex
= family_index
;
345 queue_info
.queueIndex
= i
;
346 device
->funcs
.p_vkGetDeviceQueue2(device
->device
, &queue_info
, &queue
->queue
);
350 device
->funcs
.p_vkGetDeviceQueue(device
->device
, family_index
, i
, &queue
->queue
);
353 WINE_VK_ADD_DISPATCHABLE_MAPPING(device
->phys_dev
->instance
, queue
, queue
->queue
);
357 static void wine_vk_device_free_create_info(VkDeviceCreateInfo
*create_info
)
359 free_VkDeviceCreateInfo_struct_chain(create_info
);
362 static VkResult
wine_vk_device_convert_create_info(const VkDeviceCreateInfo
*src
,
363 VkDeviceCreateInfo
*dst
)
370 if ((res
= convert_VkDeviceCreateInfo_struct_chain(src
->pNext
, dst
)) < 0)
372 WARN("Failed to convert VkDeviceCreateInfo pNext chain, res=%d.\n", res
);
376 /* Should be filtered out by loader as ICDs don't support layers. */
377 dst
->enabledLayerCount
= 0;
378 dst
->ppEnabledLayerNames
= NULL
;
380 TRACE("Enabled %u extensions.\n", dst
->enabledExtensionCount
);
381 for (i
= 0; i
< dst
->enabledExtensionCount
; i
++)
383 const char *extension_name
= dst
->ppEnabledExtensionNames
[i
];
384 TRACE("Extension %u: %s.\n", i
, debugstr_a(extension_name
));
385 if (!wine_vk_device_extension_supported(extension_name
))
387 WARN("Extension %s is not supported.\n", debugstr_a(extension_name
));
388 wine_vk_device_free_create_info(dst
);
389 return VK_ERROR_EXTENSION_NOT_PRESENT
;
396 /* Helper function used for freeing a device structure. This function supports full
397 * and partial object cleanups and can thus be used for vkCreateDevice failures.
399 static void wine_vk_device_free(struct VkDevice_T
*device
)
401 struct VkQueue_T
*queue
;
409 for (i
= 0; i
< device
->queue_count
; i
++)
411 queue
= &device
->queues
[i
];
412 if (queue
&& queue
->queue
)
413 WINE_VK_REMOVE_HANDLE_MAPPING(device
->phys_dev
->instance
, queue
);
415 free(device
->queues
);
416 device
->queues
= NULL
;
419 if (device
->device
&& device
->funcs
.p_vkDestroyDevice
)
421 WINE_VK_REMOVE_HANDLE_MAPPING(device
->phys_dev
->instance
, device
);
422 device
->funcs
.p_vkDestroyDevice(device
->device
, NULL
/* pAllocator */);
428 NTSTATUS CDECL
__wine_init_unix_lib(HMODULE module
, DWORD reason
, const void *driver
, void *ptr_out
)
430 if (reason
!= DLL_PROCESS_ATTACH
) return STATUS_SUCCESS
;
433 p_vkEnumerateInstanceVersion
= vk_funcs
->p_vkGetInstanceProcAddr(NULL
, "vkEnumerateInstanceVersion");
434 *(const struct unix_funcs
**)ptr_out
= &loader_funcs
;
435 return STATUS_SUCCESS
;
438 /* Helper function for converting between win32 and host compatible VkInstanceCreateInfo.
439 * This function takes care of extensions handled at winevulkan layer, a Wine graphics
440 * driver is responsible for handling e.g. surface extensions.
442 static VkResult
wine_vk_instance_convert_create_info(const VkInstanceCreateInfo
*src
,
443 VkInstanceCreateInfo
*dst
, struct VkInstance_T
*object
)
445 VkDebugUtilsMessengerCreateInfoEXT
*debug_utils_messenger
;
446 VkDebugReportCallbackCreateInfoEXT
*debug_report_callback
;
447 VkBaseInStructure
*header
;
453 if ((res
= convert_VkInstanceCreateInfo_struct_chain(src
->pNext
, dst
)) < 0)
455 WARN("Failed to convert VkInstanceCreateInfo pNext chain, res=%d.\n", res
);
459 object
->utils_messenger_count
= wine_vk_count_struct(dst
, DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT
);
460 object
->utils_messengers
= calloc(object
->utils_messenger_count
, sizeof(*object
->utils_messengers
));
461 header
= (VkBaseInStructure
*) dst
;
462 for (i
= 0; i
< object
->utils_messenger_count
; i
++)
464 header
= wine_vk_find_struct(header
->pNext
, DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT
);
465 debug_utils_messenger
= (VkDebugUtilsMessengerCreateInfoEXT
*) header
;
467 object
->utils_messengers
[i
].instance
= object
;
468 object
->utils_messengers
[i
].debug_messenger
= VK_NULL_HANDLE
;
469 object
->utils_messengers
[i
].user_callback
= debug_utils_messenger
->pfnUserCallback
;
470 object
->utils_messengers
[i
].user_data
= debug_utils_messenger
->pUserData
;
472 /* convert_VkInstanceCreateInfo_struct_chain already copied the chain,
473 * so we can modify it in-place.
475 debug_utils_messenger
->pfnUserCallback
= (void *) &debug_utils_callback_conversion
;
476 debug_utils_messenger
->pUserData
= &object
->utils_messengers
[i
];
479 debug_report_callback
= wine_vk_find_struct(header
->pNext
, DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT
);
480 if (debug_report_callback
)
482 object
->default_callback
.instance
= object
;
483 object
->default_callback
.debug_callback
= VK_NULL_HANDLE
;
484 object
->default_callback
.user_callback
= debug_report_callback
->pfnCallback
;
485 object
->default_callback
.user_data
= debug_report_callback
->pUserData
;
487 debug_report_callback
->pfnCallback
= (void *) &debug_report_callback_conversion
;
488 debug_report_callback
->pUserData
= &object
->default_callback
;
491 /* ICDs don't support any layers, so nothing to copy. Modern versions of the loader
492 * filter this data out as well.
494 if (object
->quirks
& WINEVULKAN_QUIRK_IGNORE_EXPLICIT_LAYERS
) {
495 dst
->enabledLayerCount
= 0;
496 dst
->ppEnabledLayerNames
= NULL
;
497 WARN("Ignoring explicit layers!\n");
498 } else if (dst
->enabledLayerCount
) {
499 FIXME("Loading explicit layers is not supported by winevulkan!\n");
500 return VK_ERROR_LAYER_NOT_PRESENT
;
503 TRACE("Enabled %u instance extensions.\n", dst
->enabledExtensionCount
);
504 for (i
= 0; i
< dst
->enabledExtensionCount
; i
++)
506 const char *extension_name
= dst
->ppEnabledExtensionNames
[i
];
507 TRACE("Extension %u: %s.\n", i
, debugstr_a(extension_name
));
508 if (!wine_vk_instance_extension_supported(extension_name
))
510 WARN("Extension %s is not supported.\n", debugstr_a(extension_name
));
511 free_VkInstanceCreateInfo_struct_chain(dst
);
512 return VK_ERROR_EXTENSION_NOT_PRESENT
;
514 if (!strcmp(extension_name
, "VK_EXT_debug_utils") || !strcmp(extension_name
, "VK_EXT_debug_report"))
516 object
->enable_wrapper_list
= VK_TRUE
;
523 /* Helper function which stores wrapped physical devices in the instance object. */
524 static VkResult
wine_vk_instance_load_physical_devices(struct VkInstance_T
*instance
)
526 VkPhysicalDevice
*tmp_phys_devs
;
527 uint32_t phys_dev_count
;
531 res
= instance
->funcs
.p_vkEnumeratePhysicalDevices(instance
->instance
, &phys_dev_count
, NULL
);
532 if (res
!= VK_SUCCESS
)
534 ERR("Failed to enumerate physical devices, res=%d\n", res
);
540 if (!(tmp_phys_devs
= calloc(phys_dev_count
, sizeof(*tmp_phys_devs
))))
541 return VK_ERROR_OUT_OF_HOST_MEMORY
;
543 res
= instance
->funcs
.p_vkEnumeratePhysicalDevices(instance
->instance
, &phys_dev_count
, tmp_phys_devs
);
544 if (res
!= VK_SUCCESS
)
550 instance
->phys_devs
= calloc(phys_dev_count
, sizeof(*instance
->phys_devs
));
551 if (!instance
->phys_devs
)
554 return VK_ERROR_OUT_OF_HOST_MEMORY
;
557 /* Wrap each native physical device handle into a dispatchable object for the ICD loader. */
558 for (i
= 0; i
< phys_dev_count
; i
++)
560 struct VkPhysicalDevice_T
*phys_dev
= wine_vk_physical_device_alloc(instance
, tmp_phys_devs
[i
]);
563 ERR("Unable to allocate memory for physical device!\n");
565 return VK_ERROR_OUT_OF_HOST_MEMORY
;
568 instance
->phys_devs
[i
] = phys_dev
;
569 instance
->phys_dev_count
= i
+ 1;
571 instance
->phys_dev_count
= phys_dev_count
;
577 static struct VkPhysicalDevice_T
*wine_vk_instance_wrap_physical_device(struct VkInstance_T
*instance
,
578 VkPhysicalDevice physical_device
)
582 for (i
= 0; i
< instance
->phys_dev_count
; ++i
)
584 struct VkPhysicalDevice_T
*current
= instance
->phys_devs
[i
];
585 if (current
->phys_dev
== physical_device
)
589 ERR("Unrecognized physical device %p.\n", physical_device
);
593 /* Helper function used for freeing an instance structure. This function supports full
594 * and partial object cleanups and can thus be used for vkCreateInstance failures.
596 static void wine_vk_instance_free(struct VkInstance_T
*instance
)
601 if (instance
->phys_devs
)
605 for (i
= 0; i
< instance
->phys_dev_count
; i
++)
607 wine_vk_physical_device_free(instance
->phys_devs
[i
]);
609 free(instance
->phys_devs
);
612 if (instance
->instance
)
614 vk_funcs
->p_vkDestroyInstance(instance
->instance
, NULL
/* allocator */);
615 WINE_VK_REMOVE_HANDLE_MAPPING(instance
, instance
);
618 pthread_rwlock_destroy(&instance
->wrapper_lock
);
619 free(instance
->utils_messengers
);
624 VkResult WINAPI
wine_vkAllocateCommandBuffers(VkDevice device
,
625 const VkCommandBufferAllocateInfo
*allocate_info
, VkCommandBuffer
*buffers
)
627 struct wine_cmd_pool
*pool
;
628 VkResult res
= VK_SUCCESS
;
631 TRACE("%p, %p, %p\n", device
, allocate_info
, buffers
);
633 pool
= wine_cmd_pool_from_handle(allocate_info
->commandPool
);
635 memset(buffers
, 0, allocate_info
->commandBufferCount
* sizeof(*buffers
));
637 for (i
= 0; i
< allocate_info
->commandBufferCount
; i
++)
639 VkCommandBufferAllocateInfo_host allocate_info_host
;
641 /* TODO: future extensions (none yet) may require pNext conversion. */
642 allocate_info_host
.pNext
= allocate_info
->pNext
;
643 allocate_info_host
.sType
= allocate_info
->sType
;
644 allocate_info_host
.commandPool
= pool
->command_pool
;
645 allocate_info_host
.level
= allocate_info
->level
;
646 allocate_info_host
.commandBufferCount
= 1;
648 TRACE("Allocating command buffer %u from pool 0x%s.\n",
649 i
, wine_dbgstr_longlong(allocate_info_host
.commandPool
));
651 if (!(buffers
[i
] = calloc(1, sizeof(**buffers
))))
653 res
= VK_ERROR_OUT_OF_HOST_MEMORY
;
657 buffers
[i
]->base
.loader_magic
= VULKAN_ICD_MAGIC_VALUE
;
658 buffers
[i
]->device
= device
;
659 list_add_tail(&pool
->command_buffers
, &buffers
[i
]->pool_link
);
660 res
= device
->funcs
.p_vkAllocateCommandBuffers(device
->device
,
661 &allocate_info_host
, &buffers
[i
]->command_buffer
);
662 WINE_VK_ADD_DISPATCHABLE_MAPPING(device
->phys_dev
->instance
, buffers
[i
], buffers
[i
]->command_buffer
);
663 if (res
!= VK_SUCCESS
)
665 ERR("Failed to allocate command buffer, res=%d.\n", res
);
666 buffers
[i
]->command_buffer
= VK_NULL_HANDLE
;
671 if (res
!= VK_SUCCESS
)
673 wine_vk_free_command_buffers(device
, pool
, i
+ 1, buffers
);
674 memset(buffers
, 0, allocate_info
->commandBufferCount
* sizeof(*buffers
));
680 VkResult WINAPI
wine_vkCreateDevice(VkPhysicalDevice phys_dev
,
681 const VkDeviceCreateInfo
*create_info
,
682 const VkAllocationCallbacks
*allocator
, VkDevice
*device
)
684 VkDeviceCreateInfo create_info_host
;
685 struct VkQueue_T
*next_queue
;
686 struct VkDevice_T
*object
;
690 TRACE("%p, %p, %p, %p\n", phys_dev
, create_info
, allocator
, device
);
693 FIXME("Support for allocation callbacks not implemented yet\n");
695 if (TRACE_ON(vulkan
))
697 VkPhysicalDeviceProperties properties
;
699 wine_vkGetPhysicalDeviceProperties(phys_dev
, &properties
);
701 TRACE("Device name: %s.\n", debugstr_a(properties
.deviceName
));
702 TRACE("Vendor ID: %#x, Device ID: %#x.\n", properties
.vendorID
, properties
.deviceID
);
703 TRACE("Driver version: %#x.\n", properties
.driverVersion
);
706 if (!(object
= calloc(1, sizeof(*object
))))
707 return VK_ERROR_OUT_OF_HOST_MEMORY
;
709 object
->base
.base
.loader_magic
= VULKAN_ICD_MAGIC_VALUE
;
710 object
->phys_dev
= phys_dev
;
712 res
= wine_vk_device_convert_create_info(create_info
, &create_info_host
);
713 if (res
!= VK_SUCCESS
)
716 res
= phys_dev
->instance
->funcs
.p_vkCreateDevice(phys_dev
->phys_dev
,
717 &create_info_host
, NULL
/* allocator */, &object
->device
);
718 wine_vk_device_free_create_info(&create_info_host
);
719 WINE_VK_ADD_DISPATCHABLE_MAPPING(phys_dev
->instance
, object
, object
->device
);
720 if (res
!= VK_SUCCESS
)
722 WARN("Failed to create device, res=%d.\n", res
);
726 /* Just load all function pointers we are aware off. The loader takes care of filtering.
727 * We use vkGetDeviceProcAddr as opposed to vkGetInstanceProcAddr for efficiency reasons
728 * as functions pass through fewer dispatch tables within the loader.
730 #define USE_VK_FUNC(name) \
731 object->funcs.p_##name = (void *)vk_funcs->p_vkGetDeviceProcAddr(object->device, #name); \
732 if (object->funcs.p_##name == NULL) \
733 TRACE("Not found '%s'.\n", #name);
734 ALL_VK_DEVICE_FUNCS()
737 /* We need to cache all queues within the device as each requires wrapping since queues are
738 * dispatchable objects.
740 for (i
= 0; i
< create_info_host
.queueCreateInfoCount
; i
++)
742 object
->queue_count
+= create_info_host
.pQueueCreateInfos
[i
].queueCount
;
745 if (!(object
->queues
= calloc(object
->queue_count
, sizeof(*object
->queues
))))
747 res
= VK_ERROR_OUT_OF_HOST_MEMORY
;
751 next_queue
= object
->queues
;
752 for (i
= 0; i
< create_info_host
.queueCreateInfoCount
; i
++)
754 uint32_t flags
= create_info_host
.pQueueCreateInfos
[i
].flags
;
755 uint32_t family_index
= create_info_host
.pQueueCreateInfos
[i
].queueFamilyIndex
;
756 uint32_t queue_count
= create_info_host
.pQueueCreateInfos
[i
].queueCount
;
758 TRACE("Queue family index %u, queue count %u.\n", family_index
, queue_count
);
760 wine_vk_device_get_queues(object
, family_index
, queue_count
, flags
, next_queue
);
761 next_queue
+= queue_count
;
764 object
->base
.quirks
= phys_dev
->instance
->quirks
;
767 TRACE("Created device %p (native device %p).\n", object
, object
->device
);
771 wine_vk_device_free(object
);
775 VkResult WINAPI
wine_vkCreateInstance(const VkInstanceCreateInfo
*create_info
,
776 const VkAllocationCallbacks
*allocator
, VkInstance
*instance
)
778 VkInstanceCreateInfo create_info_host
;
779 const VkApplicationInfo
*app_info
;
780 struct VkInstance_T
*object
;
784 FIXME("Support for allocation callbacks not implemented yet\n");
786 if (!(object
= calloc(1, sizeof(*object
))))
788 ERR("Failed to allocate memory for instance\n");
789 return VK_ERROR_OUT_OF_HOST_MEMORY
;
791 object
->base
.loader_magic
= VULKAN_ICD_MAGIC_VALUE
;
792 list_init(&object
->wrappers
);
793 pthread_rwlock_init(&object
->wrapper_lock
, NULL
);
795 res
= wine_vk_instance_convert_create_info(create_info
, &create_info_host
, object
);
796 if (res
!= VK_SUCCESS
)
798 wine_vk_instance_free(object
);
802 res
= vk_funcs
->p_vkCreateInstance(&create_info_host
, NULL
/* allocator */, &object
->instance
);
803 free_VkInstanceCreateInfo_struct_chain(&create_info_host
);
804 if (res
!= VK_SUCCESS
)
806 ERR("Failed to create instance, res=%d\n", res
);
807 wine_vk_instance_free(object
);
811 WINE_VK_ADD_DISPATCHABLE_MAPPING(object
, object
, object
->instance
);
813 /* Load all instance functions we are aware of. Note the loader takes care
814 * of any filtering for extensions which were not requested, but which the
817 #define USE_VK_FUNC(name) \
818 object->funcs.p_##name = (void *)vk_funcs->p_vkGetInstanceProcAddr(object->instance, #name);
819 ALL_VK_INSTANCE_FUNCS()
822 /* Cache physical devices for vkEnumeratePhysicalDevices within the instance as
823 * each vkPhysicalDevice is a dispatchable object, which means we need to wrap
824 * the native physical devices and present those to the application.
825 * Cleanup happens as part of wine_vkDestroyInstance.
827 res
= wine_vk_instance_load_physical_devices(object
);
828 if (res
!= VK_SUCCESS
)
830 ERR("Failed to load physical devices, res=%d\n", res
);
831 wine_vk_instance_free(object
);
835 if ((app_info
= create_info
->pApplicationInfo
))
837 TRACE("Application name %s, application version %#x.\n",
838 debugstr_a(app_info
->pApplicationName
), app_info
->applicationVersion
);
839 TRACE("Engine name %s, engine version %#x.\n", debugstr_a(app_info
->pEngineName
),
840 app_info
->engineVersion
);
841 TRACE("API version %#x.\n", app_info
->apiVersion
);
843 if (app_info
->pEngineName
&& !strcmp(app_info
->pEngineName
, "idTech"))
844 object
->quirks
|= WINEVULKAN_QUIRK_GET_DEVICE_PROC_ADDR
;
847 object
->quirks
|= WINEVULKAN_QUIRK_ADJUST_MAX_IMAGE_COUNT
;
850 TRACE("Created instance %p (native instance %p).\n", object
, object
->instance
);
854 void WINAPI
wine_vkDestroyDevice(VkDevice device
, const VkAllocationCallbacks
*allocator
)
856 TRACE("%p %p\n", device
, allocator
);
859 FIXME("Support for allocation callbacks not implemented yet\n");
861 wine_vk_device_free(device
);
864 void WINAPI
wine_vkDestroyInstance(VkInstance instance
, const VkAllocationCallbacks
*allocator
)
866 TRACE("%p, %p\n", instance
, allocator
);
869 FIXME("Support allocation allocators\n");
871 wine_vk_instance_free(instance
);
874 VkResult WINAPI
wine_vkEnumerateDeviceExtensionProperties(VkPhysicalDevice phys_dev
,
875 const char *layer_name
, uint32_t *count
, VkExtensionProperties
*properties
)
877 TRACE("%p, %p, %p, %p\n", phys_dev
, layer_name
, count
, properties
);
879 /* This shouldn't get called with layer_name set, the ICD loader prevents it. */
882 ERR("Layer enumeration not supported from ICD.\n");
883 return VK_ERROR_LAYER_NOT_PRESENT
;
888 *count
= phys_dev
->extension_count
;
892 *count
= min(*count
, phys_dev
->extension_count
);
893 memcpy(properties
, phys_dev
->extensions
, *count
* sizeof(*properties
));
895 TRACE("Returning %u extensions.\n", *count
);
896 return *count
< phys_dev
->extension_count
? VK_INCOMPLETE
: VK_SUCCESS
;
899 VkResult WINAPI
wine_vkEnumerateInstanceExtensionProperties(const char *layer_name
,
900 uint32_t *count
, VkExtensionProperties
*properties
)
902 uint32_t num_properties
= 0, num_host_properties
;
903 VkExtensionProperties
*host_properties
;
907 res
= vk_funcs
->p_vkEnumerateInstanceExtensionProperties(NULL
, &num_host_properties
, NULL
);
908 if (res
!= VK_SUCCESS
)
911 if (!(host_properties
= calloc(num_host_properties
, sizeof(*host_properties
))))
912 return VK_ERROR_OUT_OF_HOST_MEMORY
;
914 res
= vk_funcs
->p_vkEnumerateInstanceExtensionProperties(NULL
, &num_host_properties
, host_properties
);
915 if (res
!= VK_SUCCESS
)
917 ERR("Failed to retrieve host properties, res=%d.\n", res
);
918 free(host_properties
);
922 /* The Wine graphics driver provides us with all extensions supported by the host side
923 * including extension fixup (e.g. VK_KHR_xlib_surface -> VK_KHR_win32_surface). It is
924 * up to us here to filter the list down to extensions for which we have thunks.
926 for (i
= 0; i
< num_host_properties
; i
++)
928 if (wine_vk_instance_extension_supported(host_properties
[i
].extensionName
))
931 TRACE("Instance extension '%s' is not supported.\n", host_properties
[i
].extensionName
);
936 TRACE("Returning %u extensions.\n", num_properties
);
937 *count
= num_properties
;
938 free(host_properties
);
942 for (i
= 0, j
= 0; i
< num_host_properties
&& j
< *count
; i
++)
944 if (wine_vk_instance_extension_supported(host_properties
[i
].extensionName
))
946 TRACE("Enabling extension '%s'.\n", host_properties
[i
].extensionName
);
947 properties
[j
++] = host_properties
[i
];
950 *count
= min(*count
, num_properties
);
952 free(host_properties
);
953 return *count
< num_properties
? VK_INCOMPLETE
: VK_SUCCESS
;
956 VkResult WINAPI
wine_vkEnumerateDeviceLayerProperties(VkPhysicalDevice phys_dev
, uint32_t *count
, VkLayerProperties
*properties
)
958 TRACE("%p, %p, %p\n", phys_dev
, count
, properties
);
964 VkResult WINAPI
wine_vkEnumerateInstanceVersion(uint32_t *version
)
968 if (p_vkEnumerateInstanceVersion
)
970 res
= p_vkEnumerateInstanceVersion(version
);
974 *version
= VK_API_VERSION_1_0
;
978 TRACE("API version %u.%u.%u.\n",
979 VK_VERSION_MAJOR(*version
), VK_VERSION_MINOR(*version
), VK_VERSION_PATCH(*version
));
980 *version
= min(WINE_VK_VERSION
, *version
);
984 VkResult WINAPI
wine_vkEnumeratePhysicalDevices(VkInstance instance
, uint32_t *count
,
985 VkPhysicalDevice
*devices
)
989 TRACE("%p %p %p\n", instance
, count
, devices
);
993 *count
= instance
->phys_dev_count
;
997 *count
= min(*count
, instance
->phys_dev_count
);
998 for (i
= 0; i
< *count
; i
++)
1000 devices
[i
] = instance
->phys_devs
[i
];
1003 TRACE("Returning %u devices.\n", *count
);
1004 return *count
< instance
->phys_dev_count
? VK_INCOMPLETE
: VK_SUCCESS
;
1007 void WINAPI
wine_vkFreeCommandBuffers(VkDevice device
, VkCommandPool pool_handle
,
1008 uint32_t count
, const VkCommandBuffer
*buffers
)
1010 struct wine_cmd_pool
*pool
= wine_cmd_pool_from_handle(pool_handle
);
1012 TRACE("%p, 0x%s, %u, %p\n", device
, wine_dbgstr_longlong(pool_handle
), count
, buffers
);
1014 wine_vk_free_command_buffers(device
, pool
, count
, buffers
);
1017 static VkQueue
wine_vk_device_find_queue(VkDevice device
, const VkDeviceQueueInfo2
*info
)
1019 struct VkQueue_T
* queue
;
1022 for (i
= 0; i
< device
->queue_count
; i
++)
1024 queue
= &device
->queues
[i
];
1025 if (queue
->family_index
== info
->queueFamilyIndex
1026 && queue
->queue_index
== info
->queueIndex
1027 && queue
->flags
== info
->flags
)
1033 return VK_NULL_HANDLE
;
1036 void WINAPI
wine_vkGetDeviceQueue(VkDevice device
, uint32_t family_index
,
1037 uint32_t queue_index
, VkQueue
*queue
)
1039 VkDeviceQueueInfo2 queue_info
;
1040 TRACE("%p, %u, %u, %p\n", device
, family_index
, queue_index
, queue
);
1042 queue_info
.sType
= VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2
;
1043 queue_info
.pNext
= NULL
;
1044 queue_info
.flags
= 0;
1045 queue_info
.queueFamilyIndex
= family_index
;
1046 queue_info
.queueIndex
= queue_index
;
1048 *queue
= wine_vk_device_find_queue(device
, &queue_info
);
1051 void WINAPI
wine_vkGetDeviceQueue2(VkDevice device
, const VkDeviceQueueInfo2
*info
, VkQueue
*queue
)
1053 const VkBaseInStructure
*chain
;
1055 TRACE("%p, %p, %p\n", device
, info
, queue
);
1057 if ((chain
= info
->pNext
))
1058 FIXME("Ignoring a linked structure of type %u.\n", chain
->sType
);
1060 *queue
= wine_vk_device_find_queue(device
, info
);
1063 VkResult WINAPI
wine_vkCreateCommandPool(VkDevice device
, const VkCommandPoolCreateInfo
*info
,
1064 const VkAllocationCallbacks
*allocator
, VkCommandPool
*command_pool
)
1066 struct wine_cmd_pool
*object
;
1069 TRACE("%p, %p, %p, %p\n", device
, info
, allocator
, command_pool
);
1072 FIXME("Support for allocation callbacks not implemented yet\n");
1074 if (!(object
= calloc(1, sizeof(*object
))))
1075 return VK_ERROR_OUT_OF_HOST_MEMORY
;
1077 list_init(&object
->command_buffers
);
1079 res
= device
->funcs
.p_vkCreateCommandPool(device
->device
, info
, NULL
, &object
->command_pool
);
1081 if (res
== VK_SUCCESS
)
1083 WINE_VK_ADD_NON_DISPATCHABLE_MAPPING(device
->phys_dev
->instance
, object
, object
->command_pool
);
1084 *command_pool
= wine_cmd_pool_to_handle(object
);
1094 void WINAPI
wine_vkDestroyCommandPool(VkDevice device
, VkCommandPool handle
,
1095 const VkAllocationCallbacks
*allocator
)
1097 struct wine_cmd_pool
*pool
= wine_cmd_pool_from_handle(handle
);
1098 struct VkCommandBuffer_T
*buffer
, *cursor
;
1100 TRACE("%p, 0x%s, %p\n", device
, wine_dbgstr_longlong(handle
), allocator
);
1106 FIXME("Support for allocation callbacks not implemented yet\n");
1108 /* The Vulkan spec says:
1110 * "When a pool is destroyed, all command buffers allocated from the pool are freed."
1112 LIST_FOR_EACH_ENTRY_SAFE(buffer
, cursor
, &pool
->command_buffers
, struct VkCommandBuffer_T
, pool_link
)
1114 WINE_VK_REMOVE_HANDLE_MAPPING(device
->phys_dev
->instance
, buffer
);
1118 WINE_VK_REMOVE_HANDLE_MAPPING(device
->phys_dev
->instance
, pool
);
1120 device
->funcs
.p_vkDestroyCommandPool(device
->device
, pool
->command_pool
, NULL
);
1124 static VkResult
wine_vk_enumerate_physical_device_groups(struct VkInstance_T
*instance
,
1125 VkResult (*p_vkEnumeratePhysicalDeviceGroups
)(VkInstance
, uint32_t *, VkPhysicalDeviceGroupProperties
*),
1126 uint32_t *count
, VkPhysicalDeviceGroupProperties
*properties
)
1131 res
= p_vkEnumeratePhysicalDeviceGroups(instance
->instance
, count
, properties
);
1132 if (res
< 0 || !properties
)
1135 for (i
= 0; i
< *count
; ++i
)
1137 VkPhysicalDeviceGroupProperties
*current
= &properties
[i
];
1138 for (j
= 0; j
< current
->physicalDeviceCount
; ++j
)
1140 VkPhysicalDevice dev
= current
->physicalDevices
[j
];
1141 if (!(current
->physicalDevices
[j
] = wine_vk_instance_wrap_physical_device(instance
, dev
)))
1142 return VK_ERROR_INITIALIZATION_FAILED
;
1149 VkResult WINAPI
wine_vkEnumeratePhysicalDeviceGroups(VkInstance instance
,
1150 uint32_t *count
, VkPhysicalDeviceGroupProperties
*properties
)
1152 TRACE("%p, %p, %p\n", instance
, count
, properties
);
1153 return wine_vk_enumerate_physical_device_groups(instance
,
1154 instance
->funcs
.p_vkEnumeratePhysicalDeviceGroups
, count
, properties
);
1157 VkResult WINAPI
wine_vkEnumeratePhysicalDeviceGroupsKHR(VkInstance instance
,
1158 uint32_t *count
, VkPhysicalDeviceGroupProperties
*properties
)
1160 TRACE("%p, %p, %p\n", instance
, count
, properties
);
1161 return wine_vk_enumerate_physical_device_groups(instance
,
1162 instance
->funcs
.p_vkEnumeratePhysicalDeviceGroupsKHR
, count
, properties
);
1165 void WINAPI
wine_vkGetPhysicalDeviceExternalFenceProperties(VkPhysicalDevice phys_dev
,
1166 const VkPhysicalDeviceExternalFenceInfo
*fence_info
, VkExternalFenceProperties
*properties
)
1168 TRACE("%p, %p, %p\n", phys_dev
, fence_info
, properties
);
1169 properties
->exportFromImportedHandleTypes
= 0;
1170 properties
->compatibleHandleTypes
= 0;
1171 properties
->externalFenceFeatures
= 0;
1174 void WINAPI
wine_vkGetPhysicalDeviceExternalFencePropertiesKHR(VkPhysicalDevice phys_dev
,
1175 const VkPhysicalDeviceExternalFenceInfo
*fence_info
, VkExternalFenceProperties
*properties
)
1177 TRACE("%p, %p, %p\n", phys_dev
, fence_info
, properties
);
1178 properties
->exportFromImportedHandleTypes
= 0;
1179 properties
->compatibleHandleTypes
= 0;
1180 properties
->externalFenceFeatures
= 0;
1183 void WINAPI
wine_vkGetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice phys_dev
,
1184 const VkPhysicalDeviceExternalBufferInfo
*buffer_info
, VkExternalBufferProperties
*properties
)
1186 TRACE("%p, %p, %p\n", phys_dev
, buffer_info
, properties
);
1187 memset(&properties
->externalMemoryProperties
, 0, sizeof(properties
->externalMemoryProperties
));
1190 void WINAPI
wine_vkGetPhysicalDeviceExternalBufferPropertiesKHR(VkPhysicalDevice phys_dev
,
1191 const VkPhysicalDeviceExternalBufferInfo
*buffer_info
, VkExternalBufferProperties
*properties
)
1193 TRACE("%p, %p, %p\n", phys_dev
, buffer_info
, properties
);
1194 memset(&properties
->externalMemoryProperties
, 0, sizeof(properties
->externalMemoryProperties
));
1197 VkResult WINAPI
wine_vkGetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice phys_dev
,
1198 const VkPhysicalDeviceImageFormatInfo2
*format_info
, VkImageFormatProperties2
*properties
)
1200 VkExternalImageFormatProperties
*external_image_properties
;
1203 TRACE("%p, %p, %p\n", phys_dev
, format_info
, properties
);
1205 res
= thunk_vkGetPhysicalDeviceImageFormatProperties2(phys_dev
, format_info
, properties
);
1207 if ((external_image_properties
= wine_vk_find_struct(properties
, EXTERNAL_IMAGE_FORMAT_PROPERTIES
)))
1209 VkExternalMemoryProperties
*p
= &external_image_properties
->externalMemoryProperties
;
1210 p
->externalMemoryFeatures
= 0;
1211 p
->exportFromImportedHandleTypes
= 0;
1212 p
->compatibleHandleTypes
= 0;
1218 VkResult WINAPI
wine_vkGetPhysicalDeviceImageFormatProperties2KHR(VkPhysicalDevice phys_dev
,
1219 const VkPhysicalDeviceImageFormatInfo2
*format_info
, VkImageFormatProperties2
*properties
)
1221 VkExternalImageFormatProperties
*external_image_properties
;
1224 TRACE("%p, %p, %p\n", phys_dev
, format_info
, properties
);
1226 res
= thunk_vkGetPhysicalDeviceImageFormatProperties2KHR(phys_dev
, format_info
, properties
);
1228 if ((external_image_properties
= wine_vk_find_struct(properties
, EXTERNAL_IMAGE_FORMAT_PROPERTIES
)))
1230 VkExternalMemoryProperties
*p
= &external_image_properties
->externalMemoryProperties
;
1231 p
->externalMemoryFeatures
= 0;
1232 p
->exportFromImportedHandleTypes
= 0;
1233 p
->compatibleHandleTypes
= 0;
1239 /* From ntdll/unix/sync.c */
1240 #define NANOSECONDS_IN_A_SECOND 1000000000
1241 #define TICKSPERSEC 10000000
1243 static inline VkTimeDomainEXT
get_performance_counter_time_domain(void)
1245 #if !defined(__APPLE__) && defined(HAVE_CLOCK_GETTIME)
1246 # ifdef CLOCK_MONOTONIC_RAW
1247 return VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT
;
1249 return VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT
;
1252 FIXME("No mapping for VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT on this platform.\n");
1253 return VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT
;
1257 static VkTimeDomainEXT
map_to_host_time_domain(VkTimeDomainEXT domain
)
1259 /* Matches ntdll/unix/sync.c's performance counter implementation. */
1260 if (domain
== VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT
)
1261 return get_performance_counter_time_domain();
1266 static inline uint64_t convert_monotonic_timestamp(uint64_t value
)
1268 return value
/ (NANOSECONDS_IN_A_SECOND
/ TICKSPERSEC
);
1271 static inline uint64_t convert_timestamp(VkTimeDomainEXT host_domain
, VkTimeDomainEXT target_domain
, uint64_t value
)
1273 if (host_domain
== target_domain
)
1276 /* Convert between MONOTONIC time in ns -> QueryPerformanceCounter */
1277 if ((host_domain
== VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT
|| host_domain
== VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT
)
1278 && target_domain
== VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT
)
1279 return convert_monotonic_timestamp(value
);
1281 FIXME("Couldn't translate between host domain %d and target domain %d\n", host_domain
, target_domain
);
1285 VkResult WINAPI
wine_vkGetCalibratedTimestampsEXT(VkDevice device
,
1286 uint32_t timestamp_count
, const VkCalibratedTimestampInfoEXT
*timestamp_infos
,
1287 uint64_t *timestamps
, uint64_t *max_deviation
)
1289 VkCalibratedTimestampInfoEXT
* host_timestamp_infos
;
1292 TRACE("%p, %u, %p, %p, %p\n", device
, timestamp_count
, timestamp_infos
, timestamps
, max_deviation
);
1294 if (!(host_timestamp_infos
= malloc(sizeof(VkCalibratedTimestampInfoEXT
) * timestamp_count
)))
1295 return VK_ERROR_OUT_OF_HOST_MEMORY
;
1297 for (i
= 0; i
< timestamp_count
; i
++)
1299 host_timestamp_infos
[i
].sType
= timestamp_infos
[i
].sType
;
1300 host_timestamp_infos
[i
].pNext
= timestamp_infos
[i
].pNext
;
1301 host_timestamp_infos
[i
].timeDomain
= map_to_host_time_domain(timestamp_infos
[i
].timeDomain
);
1304 res
= device
->funcs
.p_vkGetCalibratedTimestampsEXT(device
->device
, timestamp_count
, host_timestamp_infos
, timestamps
, max_deviation
);
1305 if (res
!= VK_SUCCESS
)
1308 for (i
= 0; i
< timestamp_count
; i
++)
1309 timestamps
[i
] = convert_timestamp(host_timestamp_infos
[i
].timeDomain
, timestamp_infos
[i
].timeDomain
, timestamps
[i
]);
1311 free(host_timestamp_infos
);
1316 VkResult WINAPI
wine_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT(VkPhysicalDevice phys_dev
,
1317 uint32_t *time_domain_count
, VkTimeDomainEXT
*time_domains
)
1319 BOOL supports_device
= FALSE
, supports_monotonic
= FALSE
, supports_monotonic_raw
= FALSE
;
1320 const VkTimeDomainEXT performance_counter_domain
= get_performance_counter_time_domain();
1321 VkTimeDomainEXT
*host_time_domains
;
1322 uint32_t host_time_domain_count
;
1323 VkTimeDomainEXT out_time_domains
[2];
1324 uint32_t out_time_domain_count
;
1328 TRACE("%p, %p, %p\n", phys_dev
, time_domain_count
, time_domains
);
1330 /* Find out the time domains supported on the host */
1331 res
= phys_dev
->instance
->funcs
.p_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT(phys_dev
->phys_dev
, &host_time_domain_count
, NULL
);
1332 if (res
!= VK_SUCCESS
)
1335 if (!(host_time_domains
= malloc(sizeof(VkTimeDomainEXT
) * host_time_domain_count
)))
1336 return VK_ERROR_OUT_OF_HOST_MEMORY
;
1338 res
= phys_dev
->instance
->funcs
.p_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT(phys_dev
->phys_dev
, &host_time_domain_count
, host_time_domains
);
1339 if (res
!= VK_SUCCESS
)
1341 free(host_time_domains
);
1345 for (i
= 0; i
< host_time_domain_count
; i
++)
1347 if (host_time_domains
[i
] == VK_TIME_DOMAIN_DEVICE_EXT
)
1348 supports_device
= TRUE
;
1349 else if (host_time_domains
[i
] == VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT
)
1350 supports_monotonic
= TRUE
;
1351 else if (host_time_domains
[i
] == VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT
)
1352 supports_monotonic_raw
= TRUE
;
1354 FIXME("Unknown time domain %d\n", host_time_domains
[i
]);
1357 free(host_time_domains
);
1359 out_time_domain_count
= 0;
1361 /* Map our monotonic times -> QPC */
1362 if (supports_monotonic_raw
&& performance_counter_domain
== VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT
)
1363 out_time_domains
[out_time_domain_count
++] = VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT
;
1364 else if (supports_monotonic
&& performance_counter_domain
== VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT
)
1365 out_time_domains
[out_time_domain_count
++] = VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT
;
1367 FIXME("VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT not supported on this platform.\n");
1369 /* Forward the device domain time */
1370 if (supports_device
)
1371 out_time_domains
[out_time_domain_count
++] = VK_TIME_DOMAIN_DEVICE_EXT
;
1373 /* Send the count/domains back to the app */
1376 *time_domain_count
= out_time_domain_count
;
1380 for (i
= 0; i
< min(*time_domain_count
, out_time_domain_count
); i
++)
1381 time_domains
[i
] = out_time_domains
[i
];
1383 res
= *time_domain_count
< out_time_domain_count
? VK_INCOMPLETE
: VK_SUCCESS
;
1384 *time_domain_count
= out_time_domain_count
;
1388 void WINAPI
wine_vkGetPhysicalDeviceExternalSemaphoreProperties(VkPhysicalDevice phys_dev
,
1389 const VkPhysicalDeviceExternalSemaphoreInfo
*semaphore_info
, VkExternalSemaphoreProperties
*properties
)
1391 TRACE("%p, %p, %p\n", phys_dev
, semaphore_info
, properties
);
1392 properties
->exportFromImportedHandleTypes
= 0;
1393 properties
->compatibleHandleTypes
= 0;
1394 properties
->externalSemaphoreFeatures
= 0;
1397 void WINAPI
wine_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR(VkPhysicalDevice phys_dev
,
1398 const VkPhysicalDeviceExternalSemaphoreInfo
*semaphore_info
, VkExternalSemaphoreProperties
*properties
)
1400 TRACE("%p, %p, %p\n", phys_dev
, semaphore_info
, properties
);
1401 properties
->exportFromImportedHandleTypes
= 0;
1402 properties
->compatibleHandleTypes
= 0;
1403 properties
->externalSemaphoreFeatures
= 0;
1406 VkResult WINAPI
wine_vkSetPrivateDataEXT(VkDevice device
, VkObjectType object_type
, uint64_t object_handle
,
1407 VkPrivateDataSlotEXT private_data_slot
, uint64_t data
)
1409 TRACE("%p, %#x, 0x%s, 0x%s, 0x%s\n", device
, object_type
, wine_dbgstr_longlong(object_handle
),
1410 wine_dbgstr_longlong(private_data_slot
), wine_dbgstr_longlong(data
));
1412 object_handle
= wine_vk_unwrap_handle(object_type
, object_handle
);
1413 return device
->funcs
.p_vkSetPrivateDataEXT(device
->device
, object_type
, object_handle
, private_data_slot
, data
);
1416 void WINAPI
wine_vkGetPrivateDataEXT(VkDevice device
, VkObjectType object_type
, uint64_t object_handle
,
1417 VkPrivateDataSlotEXT private_data_slot
, uint64_t *data
)
1419 TRACE("%p, %#x, 0x%s, 0x%s, %p\n", device
, object_type
, wine_dbgstr_longlong(object_handle
),
1420 wine_dbgstr_longlong(private_data_slot
), data
);
1422 object_handle
= wine_vk_unwrap_handle(object_type
, object_handle
);
1423 device
->funcs
.p_vkGetPrivateDataEXT(device
->device
, object_type
, object_handle
, private_data_slot
, data
);
1426 VkResult WINAPI
wine_vkCreateWin32SurfaceKHR(VkInstance instance
,
1427 const VkWin32SurfaceCreateInfoKHR
*createInfo
, const VkAllocationCallbacks
*allocator
, VkSurfaceKHR
*surface
)
1429 struct wine_surface
*object
;
1432 TRACE("%p, %p, %p, %p\n", instance
, createInfo
, allocator
, surface
);
1435 FIXME("Support for allocation callbacks not implemented yet\n");
1437 object
= calloc(1, sizeof(*object
));
1440 return VK_ERROR_OUT_OF_HOST_MEMORY
;
1442 res
= instance
->funcs
.p_vkCreateWin32SurfaceKHR(instance
->instance
, createInfo
, NULL
, &object
->driver_surface
);
1444 if (res
!= VK_SUCCESS
)
1450 object
->surface
= vk_funcs
->p_wine_get_native_surface(object
->driver_surface
);
1452 WINE_VK_ADD_NON_DISPATCHABLE_MAPPING(instance
, object
, object
->surface
);
1454 *surface
= wine_surface_to_handle(object
);
1459 void WINAPI
wine_vkDestroySurfaceKHR(VkInstance instance
, VkSurfaceKHR surface
, const VkAllocationCallbacks
*allocator
)
1461 struct wine_surface
*object
= wine_surface_from_handle(surface
);
1463 TRACE("%p, 0x%s, %p\n", instance
, wine_dbgstr_longlong(surface
), allocator
);
1468 instance
->funcs
.p_vkDestroySurfaceKHR(instance
->instance
, object
->driver_surface
, NULL
);
1470 WINE_VK_REMOVE_HANDLE_MAPPING(instance
, object
);
1474 static inline void adjust_max_image_count(VkPhysicalDevice phys_dev
, VkSurfaceCapabilitiesKHR
* capabilities
)
1476 /* Many Windows games, for example Strange Brigade, No Man's Sky, Path of Exile
1477 * and World War Z, do not expect that maxImageCount can be set to 0.
1478 * A value of 0 means that there is no limit on the number of images.
1479 * Nvidia reports 8 on Windows, AMD 16.
1480 * https://vulkan.gpuinfo.org/displayreport.php?id=9122#surface
1481 * https://vulkan.gpuinfo.org/displayreport.php?id=9121#surface
1483 if ((phys_dev
->instance
->quirks
& WINEVULKAN_QUIRK_ADJUST_MAX_IMAGE_COUNT
) && !capabilities
->maxImageCount
)
1485 capabilities
->maxImageCount
= max(capabilities
->minImageCount
, 16);
1489 VkResult WINAPI
wine_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice phys_dev
,
1490 VkSurfaceKHR surface
, VkSurfaceCapabilitiesKHR
*capabilities
)
1494 TRACE("%p, 0x%s, %p\n", phys_dev
, wine_dbgstr_longlong(surface
), capabilities
);
1496 res
= thunk_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(phys_dev
, surface
, capabilities
);
1498 if (res
== VK_SUCCESS
)
1499 adjust_max_image_count(phys_dev
, capabilities
);
1504 VkResult WINAPI
wine_vkGetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice phys_dev
,
1505 const VkPhysicalDeviceSurfaceInfo2KHR
*surface_info
, VkSurfaceCapabilities2KHR
*capabilities
)
1509 TRACE("%p, %p, %p\n", phys_dev
, surface_info
, capabilities
);
1511 res
= thunk_vkGetPhysicalDeviceSurfaceCapabilities2KHR(phys_dev
, surface_info
, capabilities
);
1513 if (res
== VK_SUCCESS
)
1514 adjust_max_image_count(phys_dev
, &capabilities
->surfaceCapabilities
);
1519 VkResult WINAPI
wine_vkCreateDebugUtilsMessengerEXT(VkInstance instance
, const VkDebugUtilsMessengerCreateInfoEXT
*create_info
,
1520 const VkAllocationCallbacks
*allocator
, VkDebugUtilsMessengerEXT
*messenger
)
1522 VkDebugUtilsMessengerCreateInfoEXT wine_create_info
;
1523 struct wine_debug_utils_messenger
*object
;
1526 TRACE("%p, %p, %p, %p\n", instance
, create_info
, allocator
, messenger
);
1529 FIXME("Support for allocation callbacks not implemented yet\n");
1531 if (!(object
= calloc(1, sizeof(*object
))))
1532 return VK_ERROR_OUT_OF_HOST_MEMORY
;
1534 object
->instance
= instance
;
1535 object
->user_callback
= create_info
->pfnUserCallback
;
1536 object
->user_data
= create_info
->pUserData
;
1538 wine_create_info
= *create_info
;
1540 wine_create_info
.pfnUserCallback
= (void *) &debug_utils_callback_conversion
;
1541 wine_create_info
.pUserData
= object
;
1543 res
= instance
->funcs
.p_vkCreateDebugUtilsMessengerEXT(instance
->instance
, &wine_create_info
, NULL
, &object
->debug_messenger
);
1545 if (res
!= VK_SUCCESS
)
1551 WINE_VK_ADD_NON_DISPATCHABLE_MAPPING(instance
, object
, object
->debug_messenger
);
1552 *messenger
= wine_debug_utils_messenger_to_handle(object
);
1557 void WINAPI
wine_vkDestroyDebugUtilsMessengerEXT(
1558 VkInstance instance
, VkDebugUtilsMessengerEXT messenger
, const VkAllocationCallbacks
*allocator
)
1560 struct wine_debug_utils_messenger
*object
;
1562 TRACE("%p, 0x%s, %p\n", instance
, wine_dbgstr_longlong(messenger
), allocator
);
1564 object
= wine_debug_utils_messenger_from_handle(messenger
);
1569 instance
->funcs
.p_vkDestroyDebugUtilsMessengerEXT(instance
->instance
, object
->debug_messenger
, NULL
);
1570 WINE_VK_REMOVE_HANDLE_MAPPING(instance
, object
);
1575 void WINAPI
wine_vkSubmitDebugUtilsMessageEXT(VkInstance instance
, VkDebugUtilsMessageSeverityFlagBitsEXT severity
,
1576 VkDebugUtilsMessageTypeFlagsEXT types
, const VkDebugUtilsMessengerCallbackDataEXT
*callback_data
)
1578 VkDebugUtilsMessengerCallbackDataEXT native_callback_data
;
1579 VkDebugUtilsObjectNameInfoEXT
*object_names
;
1582 TRACE("%p, %#x, %#x, %p\n", instance
, severity
, types
, callback_data
);
1584 native_callback_data
= *callback_data
;
1585 object_names
= calloc(callback_data
->objectCount
, sizeof(*object_names
));
1586 memcpy(object_names
, callback_data
->pObjects
, callback_data
->objectCount
* sizeof(*object_names
));
1587 native_callback_data
.pObjects
= object_names
;
1589 for (i
= 0; i
< callback_data
->objectCount
; i
++)
1591 object_names
[i
].objectHandle
=
1592 wine_vk_unwrap_handle(callback_data
->pObjects
[i
].objectType
, callback_data
->pObjects
[i
].objectHandle
);
1595 thunk_vkSubmitDebugUtilsMessageEXT(instance
, severity
, types
, &native_callback_data
);
1600 VkResult WINAPI
wine_vkSetDebugUtilsObjectTagEXT(VkDevice device
, const VkDebugUtilsObjectTagInfoEXT
*tag_info
)
1602 VkDebugUtilsObjectTagInfoEXT wine_tag_info
;
1604 TRACE("%p, %p\n", device
, tag_info
);
1606 wine_tag_info
= *tag_info
;
1607 wine_tag_info
.objectHandle
= wine_vk_unwrap_handle(tag_info
->objectType
, tag_info
->objectHandle
);
1609 return thunk_vkSetDebugUtilsObjectTagEXT(device
, &wine_tag_info
);
1612 VkResult WINAPI
wine_vkSetDebugUtilsObjectNameEXT(VkDevice device
, const VkDebugUtilsObjectNameInfoEXT
*name_info
)
1614 VkDebugUtilsObjectNameInfoEXT wine_name_info
;
1616 TRACE("%p, %p\n", device
, name_info
);
1618 wine_name_info
= *name_info
;
1619 wine_name_info
.objectHandle
= wine_vk_unwrap_handle(name_info
->objectType
, name_info
->objectHandle
);
1621 return thunk_vkSetDebugUtilsObjectNameEXT(device
, &wine_name_info
);
1624 VkResult WINAPI
wine_vkCreateDebugReportCallbackEXT(VkInstance instance
, const VkDebugReportCallbackCreateInfoEXT
*create_info
,
1625 const VkAllocationCallbacks
*allocator
, VkDebugReportCallbackEXT
*callback
)
1627 VkDebugReportCallbackCreateInfoEXT wine_create_info
;
1628 struct wine_debug_report_callback
*object
;
1631 TRACE("%p, %p, %p, %p\n", instance
, create_info
, allocator
, callback
);
1634 FIXME("Support for allocation callbacks not implemented yet\n");
1636 if (!(object
= calloc(1, sizeof(*object
))))
1637 return VK_ERROR_OUT_OF_HOST_MEMORY
;
1639 object
->instance
= instance
;
1640 object
->user_callback
= create_info
->pfnCallback
;
1641 object
->user_data
= create_info
->pUserData
;
1643 wine_create_info
= *create_info
;
1645 wine_create_info
.pfnCallback
= (void *) debug_report_callback_conversion
;
1646 wine_create_info
.pUserData
= object
;
1648 res
= instance
->funcs
.p_vkCreateDebugReportCallbackEXT(instance
->instance
, &wine_create_info
, NULL
, &object
->debug_callback
);
1650 if (res
!= VK_SUCCESS
)
1656 WINE_VK_ADD_NON_DISPATCHABLE_MAPPING(instance
, object
, object
->debug_callback
);
1657 *callback
= wine_debug_report_callback_to_handle(object
);
1662 void WINAPI
wine_vkDestroyDebugReportCallbackEXT(
1663 VkInstance instance
, VkDebugReportCallbackEXT callback
, const VkAllocationCallbacks
*allocator
)
1665 struct wine_debug_report_callback
*object
;
1667 TRACE("%p, 0x%s, %p\n", instance
, wine_dbgstr_longlong(callback
), allocator
);
1669 object
= wine_debug_report_callback_from_handle(callback
);
1674 instance
->funcs
.p_vkDestroyDebugReportCallbackEXT(instance
->instance
, object
->debug_callback
, NULL
);
1676 WINE_VK_REMOVE_HANDLE_MAPPING(instance
, object
);
1681 void WINAPI
wine_vkDebugReportMessageEXT(VkInstance instance
, VkDebugReportFlagsEXT flags
, VkDebugReportObjectTypeEXT object_type
,
1682 uint64_t object
, size_t location
, int32_t code
, const char *layer_prefix
, const char *message
)
1684 TRACE("%p, %#x, %#x, 0x%s, 0x%s, %d, %p, %p\n", instance
, flags
, object_type
, wine_dbgstr_longlong(object
),
1685 wine_dbgstr_longlong(location
), code
, layer_prefix
, message
);
1687 object
= wine_vk_unwrap_handle(object_type
, object
);
1689 instance
->funcs
.p_vkDebugReportMessageEXT(
1690 instance
->instance
, flags
, object_type
, object
, location
, code
, layer_prefix
, message
);
1693 VkResult WINAPI
wine_vkDebugMarkerSetObjectTagEXT(VkDevice device
, const VkDebugMarkerObjectTagInfoEXT
*tag_info
)
1695 VkDebugMarkerObjectTagInfoEXT wine_tag_info
;
1697 TRACE("%p, %p\n", device
, tag_info
);
1699 wine_tag_info
= *tag_info
;
1700 wine_tag_info
.object
= wine_vk_unwrap_handle(tag_info
->objectType
, tag_info
->object
);
1702 return thunk_vkDebugMarkerSetObjectTagEXT(device
, &wine_tag_info
);
1705 VkResult WINAPI
wine_vkDebugMarkerSetObjectNameEXT(VkDevice device
, const VkDebugMarkerObjectNameInfoEXT
*name_info
)
1707 VkDebugMarkerObjectNameInfoEXT wine_name_info
;
1709 TRACE("%p, %p\n", device
, name_info
);
1711 wine_name_info
= *name_info
;
1712 wine_name_info
.object
= wine_vk_unwrap_handle(name_info
->objectType
, name_info
->object
);
1714 return thunk_vkDebugMarkerSetObjectNameEXT(device
, &wine_name_info
);