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 #if defined(USE_STRUCT_CONVERSION)
126 const VkDebugUtilsMessengerCallbackDataEXT_host
*callback_data
,
128 const VkDebugUtilsMessengerCallbackDataEXT
*callback_data
,
132 struct VkDebugUtilsMessengerCallbackDataEXT wine_callback_data
;
133 VkDebugUtilsObjectNameInfoEXT
*object_name_infos
;
134 struct wine_debug_utils_messenger
*object
;
138 TRACE("%i, %u, %p, %p\n", severity
, message_types
, callback_data
, user_data
);
142 if (!object
->instance
->instance
)
144 /* instance wasn't yet created, this is a message from the native loader */
148 wine_callback_data
= *((VkDebugUtilsMessengerCallbackDataEXT
*) callback_data
);
150 object_name_infos
= RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY
,
151 wine_callback_data
.objectCount
* sizeof(*object_name_infos
));
153 for (i
= 0; i
< wine_callback_data
.objectCount
; i
++)
155 object_name_infos
[i
].sType
= callback_data
->pObjects
[i
].sType
;
156 object_name_infos
[i
].pNext
= callback_data
->pObjects
[i
].pNext
;
157 object_name_infos
[i
].objectType
= callback_data
->pObjects
[i
].objectType
;
158 object_name_infos
[i
].pObjectName
= callback_data
->pObjects
[i
].pObjectName
;
160 if (wine_vk_is_type_wrapped(callback_data
->pObjects
[i
].objectType
))
162 object_name_infos
[i
].objectHandle
= wine_vk_get_wrapper(object
->instance
, callback_data
->pObjects
[i
].objectHandle
);
163 if (!object_name_infos
[i
].objectHandle
)
165 WARN("handle conversion failed 0x%s\n", wine_dbgstr_longlong(callback_data
->pObjects
[i
].objectHandle
));
166 RtlFreeHeap(GetProcessHeap(), 0, object_name_infos
);
172 object_name_infos
[i
].objectHandle
= callback_data
->pObjects
[i
].objectHandle
;
176 wine_callback_data
.pObjects
= object_name_infos
;
178 /* applications should always return VK_FALSE */
179 result
= object
->user_callback(severity
, message_types
, &wine_callback_data
, object
->user_data
);
181 RtlFreeHeap(GetProcessHeap(), 0, object_name_infos
);
186 static VkBool32
debug_report_callback_conversion(VkDebugReportFlagsEXT flags
, VkDebugReportObjectTypeEXT object_type
,
187 uint64_t object_handle
, size_t location
, int32_t code
, const char *layer_prefix
, const char *message
, void *user_data
)
189 struct wine_debug_report_callback
*object
;
191 TRACE("%#x, %#x, 0x%s, 0x%s, %d, %p, %p, %p\n", flags
, object_type
, wine_dbgstr_longlong(object_handle
),
192 wine_dbgstr_longlong(location
), code
, layer_prefix
, message
, user_data
);
196 if (!object
->instance
->instance
)
198 /* instance wasn't yet created, this is a message from the native loader */
202 object_handle
= wine_vk_get_wrapper(object
->instance
, object_handle
);
204 object_type
= VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT
;
206 return object
->user_callback(
207 flags
, object_type
, object_handle
, location
, code
, layer_prefix
, message
, object
->user_data
);
210 static void wine_vk_physical_device_free(struct VkPhysicalDevice_T
*phys_dev
)
215 WINE_VK_REMOVE_HANDLE_MAPPING(phys_dev
->instance
, phys_dev
);
216 free(phys_dev
->extensions
);
220 static struct VkPhysicalDevice_T
*wine_vk_physical_device_alloc(struct VkInstance_T
*instance
,
221 VkPhysicalDevice phys_dev
)
223 struct VkPhysicalDevice_T
*object
;
224 uint32_t num_host_properties
, num_properties
= 0;
225 VkExtensionProperties
*host_properties
= NULL
;
229 if (!(object
= calloc(1, sizeof(*object
))))
232 object
->base
.loader_magic
= VULKAN_ICD_MAGIC_VALUE
;
233 object
->instance
= instance
;
234 object
->phys_dev
= phys_dev
;
236 WINE_VK_ADD_DISPATCHABLE_MAPPING(instance
, object
, phys_dev
);
238 res
= instance
->funcs
.p_vkEnumerateDeviceExtensionProperties(phys_dev
,
239 NULL
, &num_host_properties
, NULL
);
240 if (res
!= VK_SUCCESS
)
242 ERR("Failed to enumerate device extensions, res=%d\n", res
);
246 host_properties
= calloc(num_host_properties
, sizeof(*host_properties
));
247 if (!host_properties
)
249 ERR("Failed to allocate memory for device properties!\n");
253 res
= instance
->funcs
.p_vkEnumerateDeviceExtensionProperties(phys_dev
,
254 NULL
, &num_host_properties
, host_properties
);
255 if (res
!= VK_SUCCESS
)
257 ERR("Failed to enumerate device extensions, res=%d\n", res
);
261 /* Count list of extensions for which we have an implementation.
262 * TODO: perform translation for platform specific extensions.
264 for (i
= 0; i
< num_host_properties
; i
++)
266 if (wine_vk_device_extension_supported(host_properties
[i
].extensionName
))
268 TRACE("Enabling extension '%s' for physical device %p\n", host_properties
[i
].extensionName
, object
);
273 TRACE("Skipping extension '%s', no implementation found in winevulkan.\n", host_properties
[i
].extensionName
);
277 TRACE("Host supported extensions %u, Wine supported extensions %u\n", num_host_properties
, num_properties
);
279 if (!(object
->extensions
= calloc(num_properties
, sizeof(*object
->extensions
))))
281 ERR("Failed to allocate memory for device extensions!\n");
285 for (i
= 0, j
= 0; i
< num_host_properties
; i
++)
287 if (wine_vk_device_extension_supported(host_properties
[i
].extensionName
))
289 object
->extensions
[j
] = host_properties
[i
];
293 object
->extension_count
= num_properties
;
295 free(host_properties
);
299 wine_vk_physical_device_free(object
);
300 free(host_properties
);
304 static void wine_vk_free_command_buffers(struct VkDevice_T
*device
,
305 struct wine_cmd_pool
*pool
, uint32_t count
, const VkCommandBuffer
*buffers
)
309 for (i
= 0; i
< count
; i
++)
314 device
->funcs
.p_vkFreeCommandBuffers(device
->device
, pool
->command_pool
, 1, &buffers
[i
]->command_buffer
);
315 list_remove(&buffers
[i
]->pool_link
);
316 WINE_VK_REMOVE_HANDLE_MAPPING(device
->phys_dev
->instance
, buffers
[i
]);
321 static void wine_vk_device_get_queues(struct VkDevice_T
*device
,
322 uint32_t family_index
, uint32_t queue_count
, VkDeviceQueueCreateFlags flags
,
323 struct VkQueue_T
* queues
)
325 VkDeviceQueueInfo2 queue_info
;
328 for (i
= 0; i
< queue_count
; i
++)
330 struct VkQueue_T
*queue
= &queues
[i
];
332 queue
->base
.loader_magic
= VULKAN_ICD_MAGIC_VALUE
;
333 queue
->device
= device
;
334 queue
->family_index
= family_index
;
335 queue
->queue_index
= i
;
336 queue
->flags
= flags
;
338 /* The Vulkan spec says:
340 * "vkGetDeviceQueue must only be used to get queues that were created
341 * with the flags parameter of VkDeviceQueueCreateInfo set to zero."
343 if (flags
&& device
->funcs
.p_vkGetDeviceQueue2
)
345 queue_info
.sType
= VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2
;
346 queue_info
.pNext
= NULL
;
347 queue_info
.flags
= flags
;
348 queue_info
.queueFamilyIndex
= family_index
;
349 queue_info
.queueIndex
= i
;
350 device
->funcs
.p_vkGetDeviceQueue2(device
->device
, &queue_info
, &queue
->queue
);
354 device
->funcs
.p_vkGetDeviceQueue(device
->device
, family_index
, i
, &queue
->queue
);
357 WINE_VK_ADD_DISPATCHABLE_MAPPING(device
->phys_dev
->instance
, queue
, queue
->queue
);
361 static void wine_vk_device_free_create_info(VkDeviceCreateInfo
*create_info
)
363 VkDeviceGroupDeviceCreateInfo
*group_info
;
365 if ((group_info
= wine_vk_find_struct(create_info
, DEVICE_GROUP_DEVICE_CREATE_INFO
)))
367 free((void *)group_info
->pPhysicalDevices
);
370 free_VkDeviceCreateInfo_struct_chain(create_info
);
373 static VkResult
wine_vk_device_convert_create_info(const VkDeviceCreateInfo
*src
,
374 VkDeviceCreateInfo
*dst
)
376 VkDeviceGroupDeviceCreateInfo
*group_info
;
382 if ((res
= convert_VkDeviceCreateInfo_struct_chain(src
->pNext
, dst
)) < 0)
384 WARN("Failed to convert VkDeviceCreateInfo pNext chain, res=%d.\n", res
);
388 /* FIXME: convert_VkDeviceCreateInfo_struct_chain() should unwrap handles for us. */
389 if ((group_info
= wine_vk_find_struct(dst
, DEVICE_GROUP_DEVICE_CREATE_INFO
)))
391 VkPhysicalDevice
*physical_devices
;
393 if (!(physical_devices
= calloc(group_info
->physicalDeviceCount
, sizeof(*physical_devices
))))
395 free_VkDeviceCreateInfo_struct_chain(dst
);
396 return VK_ERROR_OUT_OF_HOST_MEMORY
;
398 for (i
= 0; i
< group_info
->physicalDeviceCount
; ++i
)
400 physical_devices
[i
] = group_info
->pPhysicalDevices
[i
]->phys_dev
;
402 group_info
->pPhysicalDevices
= physical_devices
;
405 /* Should be filtered out by loader as ICDs don't support layers. */
406 dst
->enabledLayerCount
= 0;
407 dst
->ppEnabledLayerNames
= NULL
;
409 TRACE("Enabled %u extensions.\n", dst
->enabledExtensionCount
);
410 for (i
= 0; i
< dst
->enabledExtensionCount
; i
++)
412 const char *extension_name
= dst
->ppEnabledExtensionNames
[i
];
413 TRACE("Extension %u: %s.\n", i
, debugstr_a(extension_name
));
414 if (!wine_vk_device_extension_supported(extension_name
))
416 WARN("Extension %s is not supported.\n", debugstr_a(extension_name
));
417 wine_vk_device_free_create_info(dst
);
418 return VK_ERROR_EXTENSION_NOT_PRESENT
;
425 /* Helper function used for freeing a device structure. This function supports full
426 * and partial object cleanups and can thus be used for vkCreateDevice failures.
428 static void wine_vk_device_free(struct VkDevice_T
*device
)
430 struct VkQueue_T
*queue
;
438 for (i
= 0; i
< device
->queue_count
; i
++)
440 queue
= &device
->queues
[i
];
441 if (queue
&& queue
->queue
)
442 WINE_VK_REMOVE_HANDLE_MAPPING(device
->phys_dev
->instance
, queue
);
444 free(device
->queues
);
445 device
->queues
= NULL
;
448 if (device
->device
&& device
->funcs
.p_vkDestroyDevice
)
450 WINE_VK_REMOVE_HANDLE_MAPPING(device
->phys_dev
->instance
, device
);
451 device
->funcs
.p_vkDestroyDevice(device
->device
, NULL
/* pAllocator */);
457 NTSTATUS CDECL
__wine_init_unix_lib(HMODULE module
, DWORD reason
, const void *driver
, void *ptr_out
)
459 if (reason
!= DLL_PROCESS_ATTACH
) return STATUS_SUCCESS
;
462 p_vkEnumerateInstanceVersion
= vk_funcs
->p_vkGetInstanceProcAddr(NULL
, "vkEnumerateInstanceVersion");
463 *(const struct unix_funcs
**)ptr_out
= &loader_funcs
;
464 return STATUS_SUCCESS
;
467 /* Helper function for converting between win32 and host compatible VkInstanceCreateInfo.
468 * This function takes care of extensions handled at winevulkan layer, a Wine graphics
469 * driver is responsible for handling e.g. surface extensions.
471 static VkResult
wine_vk_instance_convert_create_info(const VkInstanceCreateInfo
*src
,
472 VkInstanceCreateInfo
*dst
, struct VkInstance_T
*object
)
474 VkDebugUtilsMessengerCreateInfoEXT
*debug_utils_messenger
;
475 VkDebugReportCallbackCreateInfoEXT
*debug_report_callback
;
476 VkBaseInStructure
*header
;
482 if ((res
= convert_VkInstanceCreateInfo_struct_chain(src
->pNext
, dst
)) < 0)
484 WARN("Failed to convert VkInstanceCreateInfo pNext chain, res=%d.\n", res
);
488 object
->utils_messenger_count
= wine_vk_count_struct(dst
, DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT
);
489 object
->utils_messengers
= calloc(object
->utils_messenger_count
, sizeof(*object
->utils_messengers
));
490 header
= (VkBaseInStructure
*) dst
;
491 for (i
= 0; i
< object
->utils_messenger_count
; i
++)
493 header
= wine_vk_find_struct(header
->pNext
, DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT
);
494 debug_utils_messenger
= (VkDebugUtilsMessengerCreateInfoEXT
*) header
;
496 object
->utils_messengers
[i
].instance
= object
;
497 object
->utils_messengers
[i
].debug_messenger
= VK_NULL_HANDLE
;
498 object
->utils_messengers
[i
].user_callback
= debug_utils_messenger
->pfnUserCallback
;
499 object
->utils_messengers
[i
].user_data
= debug_utils_messenger
->pUserData
;
501 /* convert_VkInstanceCreateInfo_struct_chain already copied the chain,
502 * so we can modify it in-place.
504 debug_utils_messenger
->pfnUserCallback
= (void *) &debug_utils_callback_conversion
;
505 debug_utils_messenger
->pUserData
= &object
->utils_messengers
[i
];
508 debug_report_callback
= wine_vk_find_struct(header
->pNext
, DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT
);
509 if (debug_report_callback
)
511 object
->default_callback
.instance
= object
;
512 object
->default_callback
.debug_callback
= VK_NULL_HANDLE
;
513 object
->default_callback
.user_callback
= debug_report_callback
->pfnCallback
;
514 object
->default_callback
.user_data
= debug_report_callback
->pUserData
;
516 debug_report_callback
->pfnCallback
= (void *) &debug_report_callback_conversion
;
517 debug_report_callback
->pUserData
= &object
->default_callback
;
520 /* ICDs don't support any layers, so nothing to copy. Modern versions of the loader
521 * filter this data out as well.
523 if (object
->quirks
& WINEVULKAN_QUIRK_IGNORE_EXPLICIT_LAYERS
) {
524 dst
->enabledLayerCount
= 0;
525 dst
->ppEnabledLayerNames
= NULL
;
526 WARN("Ignoring explicit layers!\n");
527 } else if (dst
->enabledLayerCount
) {
528 FIXME("Loading explicit layers is not supported by winevulkan!\n");
529 return VK_ERROR_LAYER_NOT_PRESENT
;
532 TRACE("Enabled %u instance extensions.\n", dst
->enabledExtensionCount
);
533 for (i
= 0; i
< dst
->enabledExtensionCount
; i
++)
535 const char *extension_name
= dst
->ppEnabledExtensionNames
[i
];
536 TRACE("Extension %u: %s.\n", i
, debugstr_a(extension_name
));
537 if (!wine_vk_instance_extension_supported(extension_name
))
539 WARN("Extension %s is not supported.\n", debugstr_a(extension_name
));
540 free_VkInstanceCreateInfo_struct_chain(dst
);
541 return VK_ERROR_EXTENSION_NOT_PRESENT
;
543 if (!strcmp(extension_name
, "VK_EXT_debug_utils") || !strcmp(extension_name
, "VK_EXT_debug_report"))
545 object
->enable_wrapper_list
= VK_TRUE
;
552 /* Helper function which stores wrapped physical devices in the instance object. */
553 static VkResult
wine_vk_instance_load_physical_devices(struct VkInstance_T
*instance
)
555 VkPhysicalDevice
*tmp_phys_devs
;
556 uint32_t phys_dev_count
;
560 res
= instance
->funcs
.p_vkEnumeratePhysicalDevices(instance
->instance
, &phys_dev_count
, NULL
);
561 if (res
!= VK_SUCCESS
)
563 ERR("Failed to enumerate physical devices, res=%d\n", res
);
569 if (!(tmp_phys_devs
= calloc(phys_dev_count
, sizeof(*tmp_phys_devs
))))
570 return VK_ERROR_OUT_OF_HOST_MEMORY
;
572 res
= instance
->funcs
.p_vkEnumeratePhysicalDevices(instance
->instance
, &phys_dev_count
, tmp_phys_devs
);
573 if (res
!= VK_SUCCESS
)
579 instance
->phys_devs
= calloc(phys_dev_count
, sizeof(*instance
->phys_devs
));
580 if (!instance
->phys_devs
)
583 return VK_ERROR_OUT_OF_HOST_MEMORY
;
586 /* Wrap each native physical device handle into a dispatchable object for the ICD loader. */
587 for (i
= 0; i
< phys_dev_count
; i
++)
589 struct VkPhysicalDevice_T
*phys_dev
= wine_vk_physical_device_alloc(instance
, tmp_phys_devs
[i
]);
592 ERR("Unable to allocate memory for physical device!\n");
594 return VK_ERROR_OUT_OF_HOST_MEMORY
;
597 instance
->phys_devs
[i
] = phys_dev
;
598 instance
->phys_dev_count
= i
+ 1;
600 instance
->phys_dev_count
= phys_dev_count
;
606 static struct VkPhysicalDevice_T
*wine_vk_instance_wrap_physical_device(struct VkInstance_T
*instance
,
607 VkPhysicalDevice physical_device
)
611 for (i
= 0; i
< instance
->phys_dev_count
; ++i
)
613 struct VkPhysicalDevice_T
*current
= instance
->phys_devs
[i
];
614 if (current
->phys_dev
== physical_device
)
618 ERR("Unrecognized physical device %p.\n", physical_device
);
622 /* Helper function used for freeing an instance structure. This function supports full
623 * and partial object cleanups and can thus be used for vkCreateInstance failures.
625 static void wine_vk_instance_free(struct VkInstance_T
*instance
)
630 if (instance
->phys_devs
)
634 for (i
= 0; i
< instance
->phys_dev_count
; i
++)
636 wine_vk_physical_device_free(instance
->phys_devs
[i
]);
638 free(instance
->phys_devs
);
641 if (instance
->instance
)
643 vk_funcs
->p_vkDestroyInstance(instance
->instance
, NULL
/* allocator */);
644 WINE_VK_REMOVE_HANDLE_MAPPING(instance
, instance
);
647 pthread_rwlock_destroy(&instance
->wrapper_lock
);
648 free(instance
->utils_messengers
);
653 VkResult WINAPI
wine_vkAllocateCommandBuffers(VkDevice device
,
654 const VkCommandBufferAllocateInfo
*allocate_info
, VkCommandBuffer
*buffers
)
656 struct wine_cmd_pool
*pool
;
657 VkResult res
= VK_SUCCESS
;
660 TRACE("%p, %p, %p\n", device
, allocate_info
, buffers
);
662 pool
= wine_cmd_pool_from_handle(allocate_info
->commandPool
);
664 memset(buffers
, 0, allocate_info
->commandBufferCount
* sizeof(*buffers
));
666 for (i
= 0; i
< allocate_info
->commandBufferCount
; i
++)
668 #if defined(USE_STRUCT_CONVERSION)
669 VkCommandBufferAllocateInfo_host allocate_info_host
;
671 VkCommandBufferAllocateInfo allocate_info_host
;
673 /* TODO: future extensions (none yet) may require pNext conversion. */
674 allocate_info_host
.pNext
= allocate_info
->pNext
;
675 allocate_info_host
.sType
= allocate_info
->sType
;
676 allocate_info_host
.commandPool
= pool
->command_pool
;
677 allocate_info_host
.level
= allocate_info
->level
;
678 allocate_info_host
.commandBufferCount
= 1;
680 TRACE("Allocating command buffer %u from pool 0x%s.\n",
681 i
, wine_dbgstr_longlong(allocate_info_host
.commandPool
));
683 if (!(buffers
[i
] = calloc(1, sizeof(**buffers
))))
685 res
= VK_ERROR_OUT_OF_HOST_MEMORY
;
689 buffers
[i
]->base
.loader_magic
= VULKAN_ICD_MAGIC_VALUE
;
690 buffers
[i
]->device
= device
;
691 list_add_tail(&pool
->command_buffers
, &buffers
[i
]->pool_link
);
692 res
= device
->funcs
.p_vkAllocateCommandBuffers(device
->device
,
693 &allocate_info_host
, &buffers
[i
]->command_buffer
);
694 WINE_VK_ADD_DISPATCHABLE_MAPPING(device
->phys_dev
->instance
, buffers
[i
], buffers
[i
]->command_buffer
);
695 if (res
!= VK_SUCCESS
)
697 ERR("Failed to allocate command buffer, res=%d.\n", res
);
698 buffers
[i
]->command_buffer
= VK_NULL_HANDLE
;
703 if (res
!= VK_SUCCESS
)
705 wine_vk_free_command_buffers(device
, pool
, i
+ 1, buffers
);
706 memset(buffers
, 0, allocate_info
->commandBufferCount
* sizeof(*buffers
));
712 void WINAPI
wine_vkCmdExecuteCommands(VkCommandBuffer buffer
, uint32_t count
,
713 const VkCommandBuffer
*buffers
)
715 VkCommandBuffer
*tmp_buffers
;
718 TRACE("%p %u %p\n", buffer
, count
, buffers
);
720 if (!buffers
|| !count
)
723 /* Unfortunately we need a temporary buffer as our command buffers are wrapped.
724 * This call is called often and if a performance concern, we may want to use
725 * alloca as we shouldn't need much memory and it needs to be cleaned up after
728 if (!(tmp_buffers
= malloc(count
* sizeof(*tmp_buffers
))))
730 ERR("Failed to allocate memory for temporary command buffers\n");
734 for (i
= 0; i
< count
; i
++)
735 tmp_buffers
[i
] = buffers
[i
]->command_buffer
;
737 buffer
->device
->funcs
.p_vkCmdExecuteCommands(buffer
->command_buffer
, count
, tmp_buffers
);
742 VkResult WINAPI
wine_vkCreateDevice(VkPhysicalDevice phys_dev
,
743 const VkDeviceCreateInfo
*create_info
,
744 const VkAllocationCallbacks
*allocator
, VkDevice
*device
)
746 VkDeviceCreateInfo create_info_host
;
747 struct VkQueue_T
*next_queue
;
748 struct VkDevice_T
*object
;
752 TRACE("%p, %p, %p, %p\n", phys_dev
, create_info
, allocator
, device
);
755 FIXME("Support for allocation callbacks not implemented yet\n");
757 if (TRACE_ON(vulkan
))
759 VkPhysicalDeviceProperties properties
;
761 wine_vkGetPhysicalDeviceProperties(phys_dev
, &properties
);
763 TRACE("Device name: %s.\n", debugstr_a(properties
.deviceName
));
764 TRACE("Vendor ID: %#x, Device ID: %#x.\n", properties
.vendorID
, properties
.deviceID
);
765 TRACE("Driver version: %#x.\n", properties
.driverVersion
);
768 if (!(object
= calloc(1, sizeof(*object
))))
769 return VK_ERROR_OUT_OF_HOST_MEMORY
;
771 object
->base
.base
.loader_magic
= VULKAN_ICD_MAGIC_VALUE
;
772 object
->phys_dev
= phys_dev
;
774 res
= wine_vk_device_convert_create_info(create_info
, &create_info_host
);
775 if (res
!= VK_SUCCESS
)
778 res
= phys_dev
->instance
->funcs
.p_vkCreateDevice(phys_dev
->phys_dev
,
779 &create_info_host
, NULL
/* allocator */, &object
->device
);
780 wine_vk_device_free_create_info(&create_info_host
);
781 WINE_VK_ADD_DISPATCHABLE_MAPPING(phys_dev
->instance
, object
, object
->device
);
782 if (res
!= VK_SUCCESS
)
784 WARN("Failed to create device, res=%d.\n", res
);
788 /* Just load all function pointers we are aware off. The loader takes care of filtering.
789 * We use vkGetDeviceProcAddr as opposed to vkGetInstanceProcAddr for efficiency reasons
790 * as functions pass through fewer dispatch tables within the loader.
792 #define USE_VK_FUNC(name) \
793 object->funcs.p_##name = (void *)vk_funcs->p_vkGetDeviceProcAddr(object->device, #name); \
794 if (object->funcs.p_##name == NULL) \
795 TRACE("Not found '%s'.\n", #name);
796 ALL_VK_DEVICE_FUNCS()
799 /* We need to cache all queues within the device as each requires wrapping since queues are
800 * dispatchable objects.
802 for (i
= 0; i
< create_info_host
.queueCreateInfoCount
; i
++)
804 object
->queue_count
+= create_info_host
.pQueueCreateInfos
[i
].queueCount
;
807 if (!(object
->queues
= calloc(object
->queue_count
, sizeof(*object
->queues
))))
809 res
= VK_ERROR_OUT_OF_HOST_MEMORY
;
813 next_queue
= object
->queues
;
814 for (i
= 0; i
< create_info_host
.queueCreateInfoCount
; i
++)
816 uint32_t flags
= create_info_host
.pQueueCreateInfos
[i
].flags
;
817 uint32_t family_index
= create_info_host
.pQueueCreateInfos
[i
].queueFamilyIndex
;
818 uint32_t queue_count
= create_info_host
.pQueueCreateInfos
[i
].queueCount
;
820 TRACE("Queue family index %u, queue count %u.\n", family_index
, queue_count
);
822 wine_vk_device_get_queues(object
, family_index
, queue_count
, flags
, next_queue
);
823 next_queue
+= queue_count
;
826 object
->base
.quirks
= phys_dev
->instance
->quirks
;
829 TRACE("Created device %p (native device %p).\n", object
, object
->device
);
833 wine_vk_device_free(object
);
837 VkResult WINAPI
wine_vkCreateInstance(const VkInstanceCreateInfo
*create_info
,
838 const VkAllocationCallbacks
*allocator
, VkInstance
*instance
)
840 VkInstanceCreateInfo create_info_host
;
841 const VkApplicationInfo
*app_info
;
842 struct VkInstance_T
*object
;
846 FIXME("Support for allocation callbacks not implemented yet\n");
848 if (!(object
= calloc(1, sizeof(*object
))))
850 ERR("Failed to allocate memory for instance\n");
851 return VK_ERROR_OUT_OF_HOST_MEMORY
;
853 object
->base
.loader_magic
= VULKAN_ICD_MAGIC_VALUE
;
854 list_init(&object
->wrappers
);
855 pthread_rwlock_init(&object
->wrapper_lock
, NULL
);
857 res
= wine_vk_instance_convert_create_info(create_info
, &create_info_host
, object
);
858 if (res
!= VK_SUCCESS
)
860 wine_vk_instance_free(object
);
864 res
= vk_funcs
->p_vkCreateInstance(&create_info_host
, NULL
/* allocator */, &object
->instance
);
865 free_VkInstanceCreateInfo_struct_chain(&create_info_host
);
866 if (res
!= VK_SUCCESS
)
868 ERR("Failed to create instance, res=%d\n", res
);
869 wine_vk_instance_free(object
);
873 WINE_VK_ADD_DISPATCHABLE_MAPPING(object
, object
, object
->instance
);
875 /* Load all instance functions we are aware of. Note the loader takes care
876 * of any filtering for extensions which were not requested, but which the
879 #define USE_VK_FUNC(name) \
880 object->funcs.p_##name = (void *)vk_funcs->p_vkGetInstanceProcAddr(object->instance, #name);
881 ALL_VK_INSTANCE_FUNCS()
884 /* Cache physical devices for vkEnumeratePhysicalDevices within the instance as
885 * each vkPhysicalDevice is a dispatchable object, which means we need to wrap
886 * the native physical devices and present those to the application.
887 * Cleanup happens as part of wine_vkDestroyInstance.
889 res
= wine_vk_instance_load_physical_devices(object
);
890 if (res
!= VK_SUCCESS
)
892 ERR("Failed to load physical devices, res=%d\n", res
);
893 wine_vk_instance_free(object
);
897 if ((app_info
= create_info
->pApplicationInfo
))
899 TRACE("Application name %s, application version %#x.\n",
900 debugstr_a(app_info
->pApplicationName
), app_info
->applicationVersion
);
901 TRACE("Engine name %s, engine version %#x.\n", debugstr_a(app_info
->pEngineName
),
902 app_info
->engineVersion
);
903 TRACE("API version %#x.\n", app_info
->apiVersion
);
905 if (app_info
->pEngineName
&& !strcmp(app_info
->pEngineName
, "idTech"))
906 object
->quirks
|= WINEVULKAN_QUIRK_GET_DEVICE_PROC_ADDR
;
909 object
->quirks
|= WINEVULKAN_QUIRK_ADJUST_MAX_IMAGE_COUNT
;
912 TRACE("Created instance %p (native instance %p).\n", object
, object
->instance
);
916 void WINAPI
wine_vkDestroyDevice(VkDevice device
, const VkAllocationCallbacks
*allocator
)
918 TRACE("%p %p\n", device
, allocator
);
921 FIXME("Support for allocation callbacks not implemented yet\n");
923 wine_vk_device_free(device
);
926 void WINAPI
wine_vkDestroyInstance(VkInstance instance
, const VkAllocationCallbacks
*allocator
)
928 TRACE("%p, %p\n", instance
, allocator
);
931 FIXME("Support allocation allocators\n");
933 wine_vk_instance_free(instance
);
936 VkResult WINAPI
wine_vkEnumerateDeviceExtensionProperties(VkPhysicalDevice phys_dev
,
937 const char *layer_name
, uint32_t *count
, VkExtensionProperties
*properties
)
939 TRACE("%p, %p, %p, %p\n", phys_dev
, layer_name
, count
, properties
);
941 /* This shouldn't get called with layer_name set, the ICD loader prevents it. */
944 ERR("Layer enumeration not supported from ICD.\n");
945 return VK_ERROR_LAYER_NOT_PRESENT
;
950 *count
= phys_dev
->extension_count
;
954 *count
= min(*count
, phys_dev
->extension_count
);
955 memcpy(properties
, phys_dev
->extensions
, *count
* sizeof(*properties
));
957 TRACE("Returning %u extensions.\n", *count
);
958 return *count
< phys_dev
->extension_count
? VK_INCOMPLETE
: VK_SUCCESS
;
961 VkResult WINAPI
wine_vkEnumerateInstanceExtensionProperties(const char *layer_name
,
962 uint32_t *count
, VkExtensionProperties
*properties
)
964 uint32_t num_properties
= 0, num_host_properties
;
965 VkExtensionProperties
*host_properties
;
969 res
= vk_funcs
->p_vkEnumerateInstanceExtensionProperties(NULL
, &num_host_properties
, NULL
);
970 if (res
!= VK_SUCCESS
)
973 if (!(host_properties
= calloc(num_host_properties
, sizeof(*host_properties
))))
974 return VK_ERROR_OUT_OF_HOST_MEMORY
;
976 res
= vk_funcs
->p_vkEnumerateInstanceExtensionProperties(NULL
, &num_host_properties
, host_properties
);
977 if (res
!= VK_SUCCESS
)
979 ERR("Failed to retrieve host properties, res=%d.\n", res
);
980 free(host_properties
);
984 /* The Wine graphics driver provides us with all extensions supported by the host side
985 * including extension fixup (e.g. VK_KHR_xlib_surface -> VK_KHR_win32_surface). It is
986 * up to us here to filter the list down to extensions for which we have thunks.
988 for (i
= 0; i
< num_host_properties
; i
++)
990 if (wine_vk_instance_extension_supported(host_properties
[i
].extensionName
))
993 TRACE("Instance extension '%s' is not supported.\n", host_properties
[i
].extensionName
);
998 TRACE("Returning %u extensions.\n", num_properties
);
999 *count
= num_properties
;
1000 free(host_properties
);
1004 for (i
= 0, j
= 0; i
< num_host_properties
&& j
< *count
; i
++)
1006 if (wine_vk_instance_extension_supported(host_properties
[i
].extensionName
))
1008 TRACE("Enabling extension '%s'.\n", host_properties
[i
].extensionName
);
1009 properties
[j
++] = host_properties
[i
];
1012 *count
= min(*count
, num_properties
);
1014 free(host_properties
);
1015 return *count
< num_properties
? VK_INCOMPLETE
: VK_SUCCESS
;
1018 VkResult WINAPI
wine_vkEnumerateDeviceLayerProperties(VkPhysicalDevice phys_dev
, uint32_t *count
, VkLayerProperties
*properties
)
1020 TRACE("%p, %p, %p\n", phys_dev
, count
, properties
);
1026 VkResult WINAPI
wine_vkEnumerateInstanceVersion(uint32_t *version
)
1030 if (p_vkEnumerateInstanceVersion
)
1032 res
= p_vkEnumerateInstanceVersion(version
);
1036 *version
= VK_API_VERSION_1_0
;
1040 TRACE("API version %u.%u.%u.\n",
1041 VK_VERSION_MAJOR(*version
), VK_VERSION_MINOR(*version
), VK_VERSION_PATCH(*version
));
1042 *version
= min(WINE_VK_VERSION
, *version
);
1046 VkResult WINAPI
wine_vkEnumeratePhysicalDevices(VkInstance instance
, uint32_t *count
,
1047 VkPhysicalDevice
*devices
)
1051 TRACE("%p %p %p\n", instance
, count
, devices
);
1055 *count
= instance
->phys_dev_count
;
1059 *count
= min(*count
, instance
->phys_dev_count
);
1060 for (i
= 0; i
< *count
; i
++)
1062 devices
[i
] = instance
->phys_devs
[i
];
1065 TRACE("Returning %u devices.\n", *count
);
1066 return *count
< instance
->phys_dev_count
? VK_INCOMPLETE
: VK_SUCCESS
;
1069 void WINAPI
wine_vkFreeCommandBuffers(VkDevice device
, VkCommandPool pool_handle
,
1070 uint32_t count
, const VkCommandBuffer
*buffers
)
1072 struct wine_cmd_pool
*pool
= wine_cmd_pool_from_handle(pool_handle
);
1074 TRACE("%p, 0x%s, %u, %p\n", device
, wine_dbgstr_longlong(pool_handle
), count
, buffers
);
1076 wine_vk_free_command_buffers(device
, pool
, count
, buffers
);
1079 static VkQueue
wine_vk_device_find_queue(VkDevice device
, const VkDeviceQueueInfo2
*info
)
1081 struct VkQueue_T
* queue
;
1084 for (i
= 0; i
< device
->queue_count
; i
++)
1086 queue
= &device
->queues
[i
];
1087 if (queue
->family_index
== info
->queueFamilyIndex
1088 && queue
->queue_index
== info
->queueIndex
1089 && queue
->flags
== info
->flags
)
1095 return VK_NULL_HANDLE
;
1098 void WINAPI
wine_vkGetDeviceQueue(VkDevice device
, uint32_t family_index
,
1099 uint32_t queue_index
, VkQueue
*queue
)
1101 VkDeviceQueueInfo2 queue_info
;
1102 TRACE("%p, %u, %u, %p\n", device
, family_index
, queue_index
, queue
);
1104 queue_info
.sType
= VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2
;
1105 queue_info
.pNext
= NULL
;
1106 queue_info
.flags
= 0;
1107 queue_info
.queueFamilyIndex
= family_index
;
1108 queue_info
.queueIndex
= queue_index
;
1110 *queue
= wine_vk_device_find_queue(device
, &queue_info
);
1113 void WINAPI
wine_vkGetDeviceQueue2(VkDevice device
, const VkDeviceQueueInfo2
*info
, VkQueue
*queue
)
1115 const VkBaseInStructure
*chain
;
1117 TRACE("%p, %p, %p\n", device
, info
, queue
);
1119 if ((chain
= info
->pNext
))
1120 FIXME("Ignoring a linked structure of type %u.\n", chain
->sType
);
1122 *queue
= wine_vk_device_find_queue(device
, info
);
1125 VkResult WINAPI
wine_vkQueueSubmit(VkQueue queue
, uint32_t count
,
1126 const VkSubmitInfo
*submits
, VkFence fence
)
1128 VkSubmitInfo
*submits_host
;
1130 VkCommandBuffer
*command_buffers
;
1131 unsigned int i
, j
, num_command_buffers
;
1133 TRACE("%p %u %p 0x%s\n", queue
, count
, submits
, wine_dbgstr_longlong(fence
));
1137 return queue
->device
->funcs
.p_vkQueueSubmit(queue
->queue
, 0, NULL
, fence
);
1140 submits_host
= calloc(count
, sizeof(*submits_host
));
1143 ERR("Unable to allocate memory for submit buffers!\n");
1144 return VK_ERROR_OUT_OF_HOST_MEMORY
;
1147 for (i
= 0; i
< count
; i
++)
1149 memcpy(&submits_host
[i
], &submits
[i
], sizeof(*submits_host
));
1151 num_command_buffers
= submits
[i
].commandBufferCount
;
1152 command_buffers
= calloc(num_command_buffers
, sizeof(*command_buffers
));
1153 if (!command_buffers
)
1155 ERR("Unable to allocate memory for command buffers!\n");
1156 res
= VK_ERROR_OUT_OF_HOST_MEMORY
;
1160 for (j
= 0; j
< num_command_buffers
; j
++)
1162 command_buffers
[j
] = submits
[i
].pCommandBuffers
[j
]->command_buffer
;
1164 submits_host
[i
].pCommandBuffers
= command_buffers
;
1167 res
= queue
->device
->funcs
.p_vkQueueSubmit(queue
->queue
, count
, submits_host
, fence
);
1170 for (i
= 0; i
< count
; i
++)
1172 free((void *)submits_host
[i
].pCommandBuffers
);
1176 TRACE("Returning %d\n", res
);
1180 VkResult WINAPI
wine_vkCreateCommandPool(VkDevice device
, const VkCommandPoolCreateInfo
*info
,
1181 const VkAllocationCallbacks
*allocator
, VkCommandPool
*command_pool
)
1183 struct wine_cmd_pool
*object
;
1186 TRACE("%p, %p, %p, %p\n", device
, info
, allocator
, command_pool
);
1189 FIXME("Support for allocation callbacks not implemented yet\n");
1191 if (!(object
= calloc(1, sizeof(*object
))))
1192 return VK_ERROR_OUT_OF_HOST_MEMORY
;
1194 list_init(&object
->command_buffers
);
1196 res
= device
->funcs
.p_vkCreateCommandPool(device
->device
, info
, NULL
, &object
->command_pool
);
1198 if (res
== VK_SUCCESS
)
1200 WINE_VK_ADD_NON_DISPATCHABLE_MAPPING(device
->phys_dev
->instance
, object
, object
->command_pool
);
1201 *command_pool
= wine_cmd_pool_to_handle(object
);
1211 void WINAPI
wine_vkDestroyCommandPool(VkDevice device
, VkCommandPool handle
,
1212 const VkAllocationCallbacks
*allocator
)
1214 struct wine_cmd_pool
*pool
= wine_cmd_pool_from_handle(handle
);
1215 struct VkCommandBuffer_T
*buffer
, *cursor
;
1217 TRACE("%p, 0x%s, %p\n", device
, wine_dbgstr_longlong(handle
), allocator
);
1223 FIXME("Support for allocation callbacks not implemented yet\n");
1225 /* The Vulkan spec says:
1227 * "When a pool is destroyed, all command buffers allocated from the pool are freed."
1229 LIST_FOR_EACH_ENTRY_SAFE(buffer
, cursor
, &pool
->command_buffers
, struct VkCommandBuffer_T
, pool_link
)
1231 WINE_VK_REMOVE_HANDLE_MAPPING(device
->phys_dev
->instance
, buffer
);
1235 WINE_VK_REMOVE_HANDLE_MAPPING(device
->phys_dev
->instance
, pool
);
1237 device
->funcs
.p_vkDestroyCommandPool(device
->device
, pool
->command_pool
, NULL
);
1241 static VkResult
wine_vk_enumerate_physical_device_groups(struct VkInstance_T
*instance
,
1242 VkResult (*p_vkEnumeratePhysicalDeviceGroups
)(VkInstance
, uint32_t *, VkPhysicalDeviceGroupProperties
*),
1243 uint32_t *count
, VkPhysicalDeviceGroupProperties
*properties
)
1248 res
= p_vkEnumeratePhysicalDeviceGroups(instance
->instance
, count
, properties
);
1249 if (res
< 0 || !properties
)
1252 for (i
= 0; i
< *count
; ++i
)
1254 VkPhysicalDeviceGroupProperties
*current
= &properties
[i
];
1255 for (j
= 0; j
< current
->physicalDeviceCount
; ++j
)
1257 VkPhysicalDevice dev
= current
->physicalDevices
[j
];
1258 if (!(current
->physicalDevices
[j
] = wine_vk_instance_wrap_physical_device(instance
, dev
)))
1259 return VK_ERROR_INITIALIZATION_FAILED
;
1266 VkResult WINAPI
wine_vkEnumeratePhysicalDeviceGroups(VkInstance instance
,
1267 uint32_t *count
, VkPhysicalDeviceGroupProperties
*properties
)
1269 TRACE("%p, %p, %p\n", instance
, count
, properties
);
1270 return wine_vk_enumerate_physical_device_groups(instance
,
1271 instance
->funcs
.p_vkEnumeratePhysicalDeviceGroups
, count
, properties
);
1274 VkResult WINAPI
wine_vkEnumeratePhysicalDeviceGroupsKHR(VkInstance instance
,
1275 uint32_t *count
, VkPhysicalDeviceGroupProperties
*properties
)
1277 TRACE("%p, %p, %p\n", instance
, count
, properties
);
1278 return wine_vk_enumerate_physical_device_groups(instance
,
1279 instance
->funcs
.p_vkEnumeratePhysicalDeviceGroupsKHR
, count
, properties
);
1282 void WINAPI
wine_vkGetPhysicalDeviceExternalFenceProperties(VkPhysicalDevice phys_dev
,
1283 const VkPhysicalDeviceExternalFenceInfo
*fence_info
, VkExternalFenceProperties
*properties
)
1285 TRACE("%p, %p, %p\n", phys_dev
, fence_info
, properties
);
1286 properties
->exportFromImportedHandleTypes
= 0;
1287 properties
->compatibleHandleTypes
= 0;
1288 properties
->externalFenceFeatures
= 0;
1291 void WINAPI
wine_vkGetPhysicalDeviceExternalFencePropertiesKHR(VkPhysicalDevice phys_dev
,
1292 const VkPhysicalDeviceExternalFenceInfo
*fence_info
, VkExternalFenceProperties
*properties
)
1294 TRACE("%p, %p, %p\n", phys_dev
, fence_info
, properties
);
1295 properties
->exportFromImportedHandleTypes
= 0;
1296 properties
->compatibleHandleTypes
= 0;
1297 properties
->externalFenceFeatures
= 0;
1300 void WINAPI
wine_vkGetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice phys_dev
,
1301 const VkPhysicalDeviceExternalBufferInfo
*buffer_info
, VkExternalBufferProperties
*properties
)
1303 TRACE("%p, %p, %p\n", phys_dev
, buffer_info
, properties
);
1304 memset(&properties
->externalMemoryProperties
, 0, sizeof(properties
->externalMemoryProperties
));
1307 void WINAPI
wine_vkGetPhysicalDeviceExternalBufferPropertiesKHR(VkPhysicalDevice phys_dev
,
1308 const VkPhysicalDeviceExternalBufferInfo
*buffer_info
, VkExternalBufferProperties
*properties
)
1310 TRACE("%p, %p, %p\n", phys_dev
, buffer_info
, properties
);
1311 memset(&properties
->externalMemoryProperties
, 0, sizeof(properties
->externalMemoryProperties
));
1314 VkResult WINAPI
wine_vkGetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice phys_dev
,
1315 const VkPhysicalDeviceImageFormatInfo2
*format_info
, VkImageFormatProperties2
*properties
)
1317 VkExternalImageFormatProperties
*external_image_properties
;
1320 TRACE("%p, %p, %p\n", phys_dev
, format_info
, properties
);
1322 res
= thunk_vkGetPhysicalDeviceImageFormatProperties2(phys_dev
, format_info
, properties
);
1324 if ((external_image_properties
= wine_vk_find_struct(properties
, EXTERNAL_IMAGE_FORMAT_PROPERTIES
)))
1326 VkExternalMemoryProperties
*p
= &external_image_properties
->externalMemoryProperties
;
1327 p
->externalMemoryFeatures
= 0;
1328 p
->exportFromImportedHandleTypes
= 0;
1329 p
->compatibleHandleTypes
= 0;
1335 VkResult WINAPI
wine_vkGetPhysicalDeviceImageFormatProperties2KHR(VkPhysicalDevice phys_dev
,
1336 const VkPhysicalDeviceImageFormatInfo2
*format_info
, VkImageFormatProperties2
*properties
)
1338 VkExternalImageFormatProperties
*external_image_properties
;
1341 TRACE("%p, %p, %p\n", phys_dev
, format_info
, properties
);
1343 res
= thunk_vkGetPhysicalDeviceImageFormatProperties2KHR(phys_dev
, format_info
, properties
);
1345 if ((external_image_properties
= wine_vk_find_struct(properties
, EXTERNAL_IMAGE_FORMAT_PROPERTIES
)))
1347 VkExternalMemoryProperties
*p
= &external_image_properties
->externalMemoryProperties
;
1348 p
->externalMemoryFeatures
= 0;
1349 p
->exportFromImportedHandleTypes
= 0;
1350 p
->compatibleHandleTypes
= 0;
1356 /* From ntdll/unix/sync.c */
1357 #define NANOSECONDS_IN_A_SECOND 1000000000
1358 #define TICKSPERSEC 10000000
1360 static inline VkTimeDomainEXT
get_performance_counter_time_domain(void)
1362 #if !defined(__APPLE__) && defined(HAVE_CLOCK_GETTIME)
1363 # ifdef CLOCK_MONOTONIC_RAW
1364 return VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT
;
1366 return VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT
;
1369 FIXME("No mapping for VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT on this platform.\n");
1370 return VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT
;
1374 static VkTimeDomainEXT
map_to_host_time_domain(VkTimeDomainEXT domain
)
1376 /* Matches ntdll/unix/sync.c's performance counter implementation. */
1377 if (domain
== VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT
)
1378 return get_performance_counter_time_domain();
1383 static inline uint64_t convert_monotonic_timestamp(uint64_t value
)
1385 return value
/ (NANOSECONDS_IN_A_SECOND
/ TICKSPERSEC
);
1388 static inline uint64_t convert_timestamp(VkTimeDomainEXT host_domain
, VkTimeDomainEXT target_domain
, uint64_t value
)
1390 if (host_domain
== target_domain
)
1393 /* Convert between MONOTONIC time in ns -> QueryPerformanceCounter */
1394 if ((host_domain
== VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT
|| host_domain
== VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT
)
1395 && target_domain
== VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT
)
1396 return convert_monotonic_timestamp(value
);
1398 FIXME("Couldn't translate between host domain %d and target domain %d\n", host_domain
, target_domain
);
1402 VkResult WINAPI
wine_vkGetCalibratedTimestampsEXT(VkDevice device
,
1403 uint32_t timestamp_count
, const VkCalibratedTimestampInfoEXT
*timestamp_infos
,
1404 uint64_t *timestamps
, uint64_t *max_deviation
)
1406 VkCalibratedTimestampInfoEXT
* host_timestamp_infos
;
1409 TRACE("%p, %u, %p, %p, %p\n", device
, timestamp_count
, timestamp_infos
, timestamps
, max_deviation
);
1411 if (!(host_timestamp_infos
= malloc(sizeof(VkCalibratedTimestampInfoEXT
) * timestamp_count
)))
1412 return VK_ERROR_OUT_OF_HOST_MEMORY
;
1414 for (i
= 0; i
< timestamp_count
; i
++)
1416 host_timestamp_infos
[i
].sType
= timestamp_infos
[i
].sType
;
1417 host_timestamp_infos
[i
].pNext
= timestamp_infos
[i
].pNext
;
1418 host_timestamp_infos
[i
].timeDomain
= map_to_host_time_domain(timestamp_infos
[i
].timeDomain
);
1421 res
= device
->funcs
.p_vkGetCalibratedTimestampsEXT(device
->device
, timestamp_count
, host_timestamp_infos
, timestamps
, max_deviation
);
1422 if (res
!= VK_SUCCESS
)
1425 for (i
= 0; i
< timestamp_count
; i
++)
1426 timestamps
[i
] = convert_timestamp(host_timestamp_infos
[i
].timeDomain
, timestamp_infos
[i
].timeDomain
, timestamps
[i
]);
1428 free(host_timestamp_infos
);
1433 VkResult WINAPI
wine_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT(VkPhysicalDevice phys_dev
,
1434 uint32_t *time_domain_count
, VkTimeDomainEXT
*time_domains
)
1436 BOOL supports_device
= FALSE
, supports_monotonic
= FALSE
, supports_monotonic_raw
= FALSE
;
1437 const VkTimeDomainEXT performance_counter_domain
= get_performance_counter_time_domain();
1438 VkTimeDomainEXT
*host_time_domains
;
1439 uint32_t host_time_domain_count
;
1440 VkTimeDomainEXT out_time_domains
[2];
1441 uint32_t out_time_domain_count
;
1445 TRACE("%p, %p, %p\n", phys_dev
, time_domain_count
, time_domains
);
1447 /* Find out the time domains supported on the host */
1448 res
= phys_dev
->instance
->funcs
.p_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT(phys_dev
->phys_dev
, &host_time_domain_count
, NULL
);
1449 if (res
!= VK_SUCCESS
)
1452 if (!(host_time_domains
= malloc(sizeof(VkTimeDomainEXT
) * host_time_domain_count
)))
1453 return VK_ERROR_OUT_OF_HOST_MEMORY
;
1455 res
= phys_dev
->instance
->funcs
.p_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT(phys_dev
->phys_dev
, &host_time_domain_count
, host_time_domains
);
1456 if (res
!= VK_SUCCESS
)
1458 free(host_time_domains
);
1462 for (i
= 0; i
< host_time_domain_count
; i
++)
1464 if (host_time_domains
[i
] == VK_TIME_DOMAIN_DEVICE_EXT
)
1465 supports_device
= TRUE
;
1466 else if (host_time_domains
[i
] == VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT
)
1467 supports_monotonic
= TRUE
;
1468 else if (host_time_domains
[i
] == VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT
)
1469 supports_monotonic_raw
= TRUE
;
1471 FIXME("Unknown time domain %d\n", host_time_domains
[i
]);
1474 free(host_time_domains
);
1476 out_time_domain_count
= 0;
1478 /* Map our monotonic times -> QPC */
1479 if (supports_monotonic_raw
&& performance_counter_domain
== VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT
)
1480 out_time_domains
[out_time_domain_count
++] = VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT
;
1481 else if (supports_monotonic
&& performance_counter_domain
== VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT
)
1482 out_time_domains
[out_time_domain_count
++] = VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT
;
1484 FIXME("VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT not supported on this platform.\n");
1486 /* Forward the device domain time */
1487 if (supports_device
)
1488 out_time_domains
[out_time_domain_count
++] = VK_TIME_DOMAIN_DEVICE_EXT
;
1490 /* Send the count/domains back to the app */
1493 *time_domain_count
= out_time_domain_count
;
1497 for (i
= 0; i
< min(*time_domain_count
, out_time_domain_count
); i
++)
1498 time_domains
[i
] = out_time_domains
[i
];
1500 res
= *time_domain_count
< out_time_domain_count
? VK_INCOMPLETE
: VK_SUCCESS
;
1501 *time_domain_count
= out_time_domain_count
;
1505 void WINAPI
wine_vkGetPhysicalDeviceExternalSemaphoreProperties(VkPhysicalDevice phys_dev
,
1506 const VkPhysicalDeviceExternalSemaphoreInfo
*semaphore_info
, VkExternalSemaphoreProperties
*properties
)
1508 TRACE("%p, %p, %p\n", phys_dev
, semaphore_info
, properties
);
1509 properties
->exportFromImportedHandleTypes
= 0;
1510 properties
->compatibleHandleTypes
= 0;
1511 properties
->externalSemaphoreFeatures
= 0;
1514 void WINAPI
wine_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR(VkPhysicalDevice phys_dev
,
1515 const VkPhysicalDeviceExternalSemaphoreInfo
*semaphore_info
, VkExternalSemaphoreProperties
*properties
)
1517 TRACE("%p, %p, %p\n", phys_dev
, semaphore_info
, properties
);
1518 properties
->exportFromImportedHandleTypes
= 0;
1519 properties
->compatibleHandleTypes
= 0;
1520 properties
->externalSemaphoreFeatures
= 0;
1523 VkResult WINAPI
wine_vkSetPrivateDataEXT(VkDevice device
, VkObjectType object_type
, uint64_t object_handle
,
1524 VkPrivateDataSlotEXT private_data_slot
, uint64_t data
)
1526 TRACE("%p, %#x, 0x%s, 0x%s, 0x%s\n", device
, object_type
, wine_dbgstr_longlong(object_handle
),
1527 wine_dbgstr_longlong(private_data_slot
), wine_dbgstr_longlong(data
));
1529 object_handle
= wine_vk_unwrap_handle(object_type
, object_handle
);
1530 return device
->funcs
.p_vkSetPrivateDataEXT(device
->device
, object_type
, object_handle
, private_data_slot
, data
);
1533 void WINAPI
wine_vkGetPrivateDataEXT(VkDevice device
, VkObjectType object_type
, uint64_t object_handle
,
1534 VkPrivateDataSlotEXT private_data_slot
, uint64_t *data
)
1536 TRACE("%p, %#x, 0x%s, 0x%s, %p\n", device
, object_type
, wine_dbgstr_longlong(object_handle
),
1537 wine_dbgstr_longlong(private_data_slot
), data
);
1539 object_handle
= wine_vk_unwrap_handle(object_type
, object_handle
);
1540 device
->funcs
.p_vkGetPrivateDataEXT(device
->device
, object_type
, object_handle
, private_data_slot
, data
);
1543 VkResult WINAPI
wine_vkCreateSwapchainKHR(VkDevice device
, const VkSwapchainCreateInfoKHR
*create_info
,
1544 const VkAllocationCallbacks
*allocator
, VkSwapchainKHR
*swapchain
)
1546 VkSwapchainCreateInfoKHR native_info
;
1548 TRACE("%p, %p, %p, %p\n", device
, create_info
, allocator
, swapchain
);
1550 native_info
= *create_info
;
1551 native_info
.surface
= wine_surface_from_handle(create_info
->surface
)->driver_surface
;
1553 return thunk_vkCreateSwapchainKHR(device
, &native_info
, allocator
, swapchain
);
1556 VkResult WINAPI
wine_vkCreateWin32SurfaceKHR(VkInstance instance
,
1557 const VkWin32SurfaceCreateInfoKHR
*createInfo
, const VkAllocationCallbacks
*allocator
, VkSurfaceKHR
*surface
)
1559 struct wine_surface
*object
;
1562 TRACE("%p, %p, %p, %p\n", instance
, createInfo
, allocator
, surface
);
1565 FIXME("Support for allocation callbacks not implemented yet\n");
1567 object
= calloc(1, sizeof(*object
));
1570 return VK_ERROR_OUT_OF_HOST_MEMORY
;
1572 res
= instance
->funcs
.p_vkCreateWin32SurfaceKHR(instance
->instance
, createInfo
, NULL
, &object
->driver_surface
);
1574 if (res
!= VK_SUCCESS
)
1580 object
->surface
= vk_funcs
->p_wine_get_native_surface(object
->driver_surface
);
1582 WINE_VK_ADD_NON_DISPATCHABLE_MAPPING(instance
, object
, object
->surface
);
1584 *surface
= wine_surface_to_handle(object
);
1589 void WINAPI
wine_vkDestroySurfaceKHR(VkInstance instance
, VkSurfaceKHR surface
, const VkAllocationCallbacks
*allocator
)
1591 struct wine_surface
*object
= wine_surface_from_handle(surface
);
1593 TRACE("%p, 0x%s, %p\n", instance
, wine_dbgstr_longlong(surface
), allocator
);
1598 instance
->funcs
.p_vkDestroySurfaceKHR(instance
->instance
, object
->driver_surface
, NULL
);
1600 WINE_VK_REMOVE_HANDLE_MAPPING(instance
, object
);
1604 VkResult WINAPI
wine_vkGetPhysicalDeviceSurfaceFormats2KHR(VkPhysicalDevice phys_dev
,
1605 const VkPhysicalDeviceSurfaceInfo2KHR
*surface_info
, uint32_t *formats_count
, VkSurfaceFormat2KHR
*formats
)
1607 VkPhysicalDeviceSurfaceInfo2KHR native_info
;
1609 TRACE("%p, %p, %p, %p\n", phys_dev
, surface_info
, formats_count
, formats
);
1611 native_info
= *surface_info
;
1612 native_info
.surface
= wine_surface_from_handle(surface_info
->surface
)->driver_surface
;
1614 return thunk_vkGetPhysicalDeviceSurfaceFormats2KHR(phys_dev
, &native_info
, formats_count
, formats
);
1617 static inline void adjust_max_image_count(VkPhysicalDevice phys_dev
, VkSurfaceCapabilitiesKHR
* capabilities
)
1619 /* Many Windows games, for example Strange Brigade, No Man's Sky, Path of Exile
1620 * and World War Z, do not expect that maxImageCount can be set to 0.
1621 * A value of 0 means that there is no limit on the number of images.
1622 * Nvidia reports 8 on Windows, AMD 16.
1623 * https://vulkan.gpuinfo.org/displayreport.php?id=9122#surface
1624 * https://vulkan.gpuinfo.org/displayreport.php?id=9121#surface
1626 if ((phys_dev
->instance
->quirks
& WINEVULKAN_QUIRK_ADJUST_MAX_IMAGE_COUNT
) && !capabilities
->maxImageCount
)
1628 capabilities
->maxImageCount
= max(capabilities
->minImageCount
, 16);
1632 VkResult WINAPI
wine_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice phys_dev
,
1633 VkSurfaceKHR surface
, VkSurfaceCapabilitiesKHR
*capabilities
)
1637 TRACE("%p, 0x%s, %p\n", phys_dev
, wine_dbgstr_longlong(surface
), capabilities
);
1639 res
= thunk_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(phys_dev
, surface
, capabilities
);
1641 if (res
== VK_SUCCESS
)
1642 adjust_max_image_count(phys_dev
, capabilities
);
1647 VkResult WINAPI
wine_vkGetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice phys_dev
,
1648 const VkPhysicalDeviceSurfaceInfo2KHR
*surface_info
, VkSurfaceCapabilities2KHR
*capabilities
)
1650 VkPhysicalDeviceSurfaceInfo2KHR native_info
;
1653 TRACE("%p, %p, %p\n", phys_dev
, surface_info
, capabilities
);
1655 native_info
= *surface_info
;
1656 native_info
.surface
= wine_surface_from_handle(surface_info
->surface
)->driver_surface
;
1658 res
= thunk_vkGetPhysicalDeviceSurfaceCapabilities2KHR(phys_dev
, &native_info
, capabilities
);
1660 if (res
== VK_SUCCESS
)
1661 adjust_max_image_count(phys_dev
, &capabilities
->surfaceCapabilities
);
1666 VkResult WINAPI
wine_vkCreateDebugUtilsMessengerEXT(VkInstance instance
, const VkDebugUtilsMessengerCreateInfoEXT
*create_info
,
1667 const VkAllocationCallbacks
*allocator
, VkDebugUtilsMessengerEXT
*messenger
)
1669 VkDebugUtilsMessengerCreateInfoEXT wine_create_info
;
1670 struct wine_debug_utils_messenger
*object
;
1673 TRACE("%p, %p, %p, %p\n", instance
, create_info
, allocator
, messenger
);
1676 FIXME("Support for allocation callbacks not implemented yet\n");
1678 if (!(object
= calloc(1, sizeof(*object
))))
1679 return VK_ERROR_OUT_OF_HOST_MEMORY
;
1681 object
->instance
= instance
;
1682 object
->user_callback
= create_info
->pfnUserCallback
;
1683 object
->user_data
= create_info
->pUserData
;
1685 wine_create_info
= *create_info
;
1687 wine_create_info
.pfnUserCallback
= (void *) &debug_utils_callback_conversion
;
1688 wine_create_info
.pUserData
= object
;
1690 res
= instance
->funcs
.p_vkCreateDebugUtilsMessengerEXT(instance
->instance
, &wine_create_info
, NULL
, &object
->debug_messenger
);
1692 if (res
!= VK_SUCCESS
)
1698 WINE_VK_ADD_NON_DISPATCHABLE_MAPPING(instance
, object
, object
->debug_messenger
);
1699 *messenger
= wine_debug_utils_messenger_to_handle(object
);
1704 void WINAPI
wine_vkDestroyDebugUtilsMessengerEXT(
1705 VkInstance instance
, VkDebugUtilsMessengerEXT messenger
, const VkAllocationCallbacks
*allocator
)
1707 struct wine_debug_utils_messenger
*object
;
1709 TRACE("%p, 0x%s, %p\n", instance
, wine_dbgstr_longlong(messenger
), allocator
);
1711 object
= wine_debug_utils_messenger_from_handle(messenger
);
1716 instance
->funcs
.p_vkDestroyDebugUtilsMessengerEXT(instance
->instance
, object
->debug_messenger
, NULL
);
1717 WINE_VK_REMOVE_HANDLE_MAPPING(instance
, object
);
1722 void WINAPI
wine_vkSubmitDebugUtilsMessageEXT(VkInstance instance
, VkDebugUtilsMessageSeverityFlagBitsEXT severity
,
1723 VkDebugUtilsMessageTypeFlagsEXT types
, const VkDebugUtilsMessengerCallbackDataEXT
*callback_data
)
1725 VkDebugUtilsMessengerCallbackDataEXT native_callback_data
;
1726 VkDebugUtilsObjectNameInfoEXT
*object_names
;
1729 TRACE("%p, %#x, %#x, %p\n", instance
, severity
, types
, callback_data
);
1731 native_callback_data
= *callback_data
;
1732 object_names
= calloc(callback_data
->objectCount
, sizeof(*object_names
));
1733 memcpy(object_names
, callback_data
->pObjects
, callback_data
->objectCount
* sizeof(*object_names
));
1734 native_callback_data
.pObjects
= object_names
;
1736 for (i
= 0; i
< callback_data
->objectCount
; i
++)
1738 object_names
[i
].objectHandle
=
1739 wine_vk_unwrap_handle(callback_data
->pObjects
[i
].objectType
, callback_data
->pObjects
[i
].objectHandle
);
1742 thunk_vkSubmitDebugUtilsMessageEXT(instance
, severity
, types
, &native_callback_data
);
1747 VkResult WINAPI
wine_vkSetDebugUtilsObjectTagEXT(VkDevice device
, const VkDebugUtilsObjectTagInfoEXT
*tag_info
)
1749 VkDebugUtilsObjectTagInfoEXT wine_tag_info
;
1751 TRACE("%p, %p\n", device
, tag_info
);
1753 wine_tag_info
= *tag_info
;
1754 wine_tag_info
.objectHandle
= wine_vk_unwrap_handle(tag_info
->objectType
, tag_info
->objectHandle
);
1756 return thunk_vkSetDebugUtilsObjectTagEXT(device
, &wine_tag_info
);
1759 VkResult WINAPI
wine_vkSetDebugUtilsObjectNameEXT(VkDevice device
, const VkDebugUtilsObjectNameInfoEXT
*name_info
)
1761 VkDebugUtilsObjectNameInfoEXT wine_name_info
;
1763 TRACE("%p, %p\n", device
, name_info
);
1765 wine_name_info
= *name_info
;
1766 wine_name_info
.objectHandle
= wine_vk_unwrap_handle(name_info
->objectType
, name_info
->objectHandle
);
1768 return thunk_vkSetDebugUtilsObjectNameEXT(device
, &wine_name_info
);
1771 VkResult WINAPI
wine_vkCreateDebugReportCallbackEXT(VkInstance instance
, const VkDebugReportCallbackCreateInfoEXT
*create_info
,
1772 const VkAllocationCallbacks
*allocator
, VkDebugReportCallbackEXT
*callback
)
1774 VkDebugReportCallbackCreateInfoEXT wine_create_info
;
1775 struct wine_debug_report_callback
*object
;
1778 TRACE("%p, %p, %p, %p\n", instance
, create_info
, allocator
, callback
);
1781 FIXME("Support for allocation callbacks not implemented yet\n");
1783 if (!(object
= calloc(1, sizeof(*object
))))
1784 return VK_ERROR_OUT_OF_HOST_MEMORY
;
1786 object
->instance
= instance
;
1787 object
->user_callback
= create_info
->pfnCallback
;
1788 object
->user_data
= create_info
->pUserData
;
1790 wine_create_info
= *create_info
;
1792 wine_create_info
.pfnCallback
= (void *) debug_report_callback_conversion
;
1793 wine_create_info
.pUserData
= object
;
1795 res
= instance
->funcs
.p_vkCreateDebugReportCallbackEXT(instance
->instance
, &wine_create_info
, NULL
, &object
->debug_callback
);
1797 if (res
!= VK_SUCCESS
)
1803 WINE_VK_ADD_NON_DISPATCHABLE_MAPPING(instance
, object
, object
->debug_callback
);
1804 *callback
= wine_debug_report_callback_to_handle(object
);
1809 void WINAPI
wine_vkDestroyDebugReportCallbackEXT(
1810 VkInstance instance
, VkDebugReportCallbackEXT callback
, const VkAllocationCallbacks
*allocator
)
1812 struct wine_debug_report_callback
*object
;
1814 TRACE("%p, 0x%s, %p\n", instance
, wine_dbgstr_longlong(callback
), allocator
);
1816 object
= wine_debug_report_callback_from_handle(callback
);
1821 instance
->funcs
.p_vkDestroyDebugReportCallbackEXT(instance
->instance
, object
->debug_callback
, NULL
);
1823 WINE_VK_REMOVE_HANDLE_MAPPING(instance
, object
);
1828 void WINAPI
wine_vkDebugReportMessageEXT(VkInstance instance
, VkDebugReportFlagsEXT flags
, VkDebugReportObjectTypeEXT object_type
,
1829 uint64_t object
, size_t location
, int32_t code
, const char *layer_prefix
, const char *message
)
1831 TRACE("%p, %#x, %#x, 0x%s, 0x%s, %d, %p, %p\n", instance
, flags
, object_type
, wine_dbgstr_longlong(object
),
1832 wine_dbgstr_longlong(location
), code
, layer_prefix
, message
);
1834 object
= wine_vk_unwrap_handle(object_type
, object
);
1836 instance
->funcs
.p_vkDebugReportMessageEXT(
1837 instance
->instance
, flags
, object_type
, object
, location
, code
, layer_prefix
, message
);
1840 VkResult WINAPI
wine_vkDebugMarkerSetObjectTagEXT(VkDevice device
, const VkDebugMarkerObjectTagInfoEXT
*tag_info
)
1842 VkDebugMarkerObjectTagInfoEXT wine_tag_info
;
1844 TRACE("%p, %p\n", device
, tag_info
);
1846 wine_tag_info
= *tag_info
;
1847 wine_tag_info
.object
= wine_vk_unwrap_handle(tag_info
->objectType
, tag_info
->object
);
1849 return thunk_vkDebugMarkerSetObjectTagEXT(device
, &wine_tag_info
);
1852 VkResult WINAPI
wine_vkDebugMarkerSetObjectNameEXT(VkDevice device
, const VkDebugMarkerObjectNameInfoEXT
*name_info
)
1854 VkDebugMarkerObjectNameInfoEXT wine_name_info
;
1856 TRACE("%p, %p\n", device
, name_info
);
1858 wine_name_info
= *name_info
;
1859 wine_name_info
.object
= wine_vk_unwrap_handle(name_info
->objectType
, name_info
->object
);
1861 return thunk_vkDebugMarkerSetObjectNameEXT(device
, &wine_name_info
);