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
27 #include "vulkan_private.h"
28 #include "wine/vulkan_driver.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(vulkan
);
34 static BOOL
is_wow64(void)
36 return sizeof(void *) == sizeof(UINT64
) && NtCurrentTeb()->WowTebOffset
;
39 static BOOL
use_external_memory(void)
44 static ULONG_PTR
zero_bits(void)
46 return is_wow64() ? 0x7fffffff : 0;
49 #define wine_vk_count_struct(s, t) wine_vk_count_struct_((void *)s, VK_STRUCTURE_TYPE_##t)
50 static uint32_t wine_vk_count_struct_(void *s
, VkStructureType t
)
52 const VkBaseInStructure
*header
;
55 for (header
= s
; header
; header
= header
->pNext
)
57 if (header
->sType
== t
)
64 static const struct vulkan_funcs
*vk_funcs
;
66 #define WINE_VK_ADD_DISPATCHABLE_MAPPING(instance, client_handle, native_handle, object) \
67 wine_vk_add_handle_mapping((instance), (uintptr_t)(client_handle), (uintptr_t)(native_handle), &(object)->mapping)
68 #define WINE_VK_ADD_NON_DISPATCHABLE_MAPPING(instance, client_handle, native_handle, object) \
69 wine_vk_add_handle_mapping((instance), (uintptr_t)(client_handle), (native_handle), &(object)->mapping)
70 static void wine_vk_add_handle_mapping(struct wine_instance
*instance
, uint64_t wrapped_handle
,
71 uint64_t native_handle
, struct wine_vk_mapping
*mapping
)
73 if (instance
->enable_wrapper_list
)
75 mapping
->native_handle
= native_handle
;
76 mapping
->wine_wrapped_handle
= wrapped_handle
;
77 pthread_rwlock_wrlock(&instance
->wrapper_lock
);
78 list_add_tail(&instance
->wrappers
, &mapping
->link
);
79 pthread_rwlock_unlock(&instance
->wrapper_lock
);
83 #define WINE_VK_REMOVE_HANDLE_MAPPING(instance, object) \
84 wine_vk_remove_handle_mapping((instance), &(object)->mapping)
85 static void wine_vk_remove_handle_mapping(struct wine_instance
*instance
, struct wine_vk_mapping
*mapping
)
87 if (instance
->enable_wrapper_list
)
89 pthread_rwlock_wrlock(&instance
->wrapper_lock
);
90 list_remove(&mapping
->link
);
91 pthread_rwlock_unlock(&instance
->wrapper_lock
);
95 static uint64_t wine_vk_get_wrapper(struct wine_instance
*instance
, uint64_t native_handle
)
97 struct wine_vk_mapping
*mapping
;
100 pthread_rwlock_rdlock(&instance
->wrapper_lock
);
101 LIST_FOR_EACH_ENTRY(mapping
, &instance
->wrappers
, struct wine_vk_mapping
, link
)
103 if (mapping
->native_handle
== native_handle
)
105 result
= mapping
->wine_wrapped_handle
;
109 pthread_rwlock_unlock(&instance
->wrapper_lock
);
113 static VkBool32
debug_utils_callback_conversion(VkDebugUtilsMessageSeverityFlagBitsEXT severity
,
114 VkDebugUtilsMessageTypeFlagsEXT message_types
,
115 const VkDebugUtilsMessengerCallbackDataEXT
*callback_data
,
118 struct wine_vk_debug_utils_params params
;
119 VkDebugUtilsObjectNameInfoEXT
*object_name_infos
;
120 struct wine_debug_utils_messenger
*object
;
126 TRACE("%i, %u, %p, %p\n", severity
, message_types
, callback_data
, user_data
);
130 if (!object
->instance
->instance
)
132 /* instance wasn't yet created, this is a message from the native loader */
136 /* FIXME: we should pack all referenced structs instead of passing pointers */
137 params
.user_callback
= object
->user_callback
;
138 params
.user_data
= object
->user_data
;
139 params
.severity
= severity
;
140 params
.message_types
= message_types
;
141 params
.data
= *((VkDebugUtilsMessengerCallbackDataEXT
*) callback_data
);
143 object_name_infos
= calloc(params
.data
.objectCount
, sizeof(*object_name_infos
));
145 for (i
= 0; i
< params
.data
.objectCount
; i
++)
147 object_name_infos
[i
].sType
= callback_data
->pObjects
[i
].sType
;
148 object_name_infos
[i
].pNext
= callback_data
->pObjects
[i
].pNext
;
149 object_name_infos
[i
].objectType
= callback_data
->pObjects
[i
].objectType
;
150 object_name_infos
[i
].pObjectName
= callback_data
->pObjects
[i
].pObjectName
;
152 if (wine_vk_is_type_wrapped(callback_data
->pObjects
[i
].objectType
))
154 object_name_infos
[i
].objectHandle
= wine_vk_get_wrapper(object
->instance
, callback_data
->pObjects
[i
].objectHandle
);
155 if (!object_name_infos
[i
].objectHandle
)
157 WARN("handle conversion failed 0x%s\n", wine_dbgstr_longlong(callback_data
->pObjects
[i
].objectHandle
));
158 free(object_name_infos
);
164 object_name_infos
[i
].objectHandle
= callback_data
->pObjects
[i
].objectHandle
;
168 params
.data
.pObjects
= object_name_infos
;
170 /* applications should always return VK_FALSE */
171 result
= KeUserModeCallback( NtUserCallVulkanDebugUtilsCallback
, ¶ms
, sizeof(params
),
172 &ret_ptr
, &ret_len
);
174 free(object_name_infos
);
179 static VkBool32
debug_report_callback_conversion(VkDebugReportFlagsEXT flags
, VkDebugReportObjectTypeEXT object_type
,
180 uint64_t object_handle
, size_t location
, int32_t code
, const char *layer_prefix
, const char *message
, void *user_data
)
182 struct wine_vk_debug_report_params params
;
183 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 /* FIXME: we should pack all referenced structs instead of passing pointers */
199 params
.user_callback
= object
->user_callback
;
200 params
.user_data
= object
->user_data
;
201 params
.flags
= flags
;
202 params
.object_type
= object_type
;
203 params
.location
= location
;
205 params
.layer_prefix
= layer_prefix
;
206 params
.message
= message
;
208 params
.object_handle
= wine_vk_get_wrapper(object
->instance
, object_handle
);
209 if (!params
.object_handle
)
210 params
.object_type
= VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT
;
212 return KeUserModeCallback( NtUserCallVulkanDebugReportCallback
, ¶ms
, sizeof(params
),
213 &ret_ptr
, &ret_len
);
216 static void wine_vk_physical_device_free(struct wine_phys_dev
*phys_dev
)
221 WINE_VK_REMOVE_HANDLE_MAPPING(phys_dev
->instance
, phys_dev
);
222 free(phys_dev
->extensions
);
226 static struct wine_phys_dev
*wine_vk_physical_device_alloc(struct wine_instance
*instance
,
227 VkPhysicalDevice phys_dev
, VkPhysicalDevice handle
)
229 struct wine_phys_dev
*object
;
230 uint32_t num_host_properties
, num_properties
= 0;
231 VkExtensionProperties
*host_properties
= NULL
;
232 BOOL have_external_memory_host
= FALSE
;
236 if (!(object
= calloc(1, sizeof(*object
))))
239 object
->instance
= instance
;
240 object
->handle
= handle
;
241 object
->phys_dev
= phys_dev
;
243 handle
->base
.unix_handle
= (uintptr_t)object
;
244 WINE_VK_ADD_DISPATCHABLE_MAPPING(instance
, handle
, phys_dev
, object
);
246 instance
->funcs
.p_vkGetPhysicalDeviceMemoryProperties(phys_dev
, &object
->memory_properties
);
248 res
= instance
->funcs
.p_vkEnumerateDeviceExtensionProperties(phys_dev
,
249 NULL
, &num_host_properties
, NULL
);
250 if (res
!= VK_SUCCESS
)
252 ERR("Failed to enumerate device extensions, res=%d\n", res
);
256 host_properties
= calloc(num_host_properties
, sizeof(*host_properties
));
257 if (!host_properties
)
259 ERR("Failed to allocate memory for device properties!\n");
263 res
= instance
->funcs
.p_vkEnumerateDeviceExtensionProperties(phys_dev
,
264 NULL
, &num_host_properties
, host_properties
);
265 if (res
!= VK_SUCCESS
)
267 ERR("Failed to enumerate device extensions, res=%d\n", res
);
271 /* Count list of extensions for which we have an implementation.
272 * TODO: perform translation for platform specific extensions.
274 for (i
= 0; i
< num_host_properties
; i
++)
276 if (wine_vk_device_extension_supported(host_properties
[i
].extensionName
))
278 TRACE("Enabling extension '%s' for physical device %p\n", host_properties
[i
].extensionName
, object
);
283 TRACE("Skipping extension '%s', no implementation found in winevulkan.\n", host_properties
[i
].extensionName
);
285 if (!strcmp(host_properties
[i
].extensionName
, "VK_EXT_external_memory_host"))
286 have_external_memory_host
= TRUE
;
289 TRACE("Host supported extensions %u, Wine supported extensions %u\n", num_host_properties
, num_properties
);
291 if (!(object
->extensions
= calloc(num_properties
, sizeof(*object
->extensions
))))
293 ERR("Failed to allocate memory for device extensions!\n");
297 for (i
= 0, j
= 0; i
< num_host_properties
; i
++)
299 if (wine_vk_device_extension_supported(host_properties
[i
].extensionName
))
301 object
->extensions
[j
] = host_properties
[i
];
305 object
->extension_count
= num_properties
;
307 if (use_external_memory() && have_external_memory_host
)
309 VkPhysicalDeviceExternalMemoryHostPropertiesEXT host_mem_props
=
311 .sType
= VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT
,
313 VkPhysicalDeviceProperties2 props
=
315 .sType
= VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2
,
316 .pNext
= &host_mem_props
,
318 instance
->funcs
.p_vkGetPhysicalDeviceProperties2KHR(phys_dev
, &props
);
319 object
->external_memory_align
= host_mem_props
.minImportedHostPointerAlignment
;
320 if (object
->external_memory_align
)
321 TRACE("Using VK_EXT_external_memory_host for memory mapping with alignment: %u\n",
322 object
->external_memory_align
);
325 free(host_properties
);
329 wine_vk_physical_device_free(object
);
330 free(host_properties
);
334 static void wine_vk_free_command_buffers(struct wine_device
*device
,
335 struct wine_cmd_pool
*pool
, uint32_t count
, const VkCommandBuffer
*buffers
)
339 for (i
= 0; i
< count
; i
++)
341 struct wine_cmd_buffer
*buffer
= wine_cmd_buffer_from_handle(buffers
[i
]);
346 device
->funcs
.p_vkFreeCommandBuffers(device
->device
, pool
->command_pool
, 1, &buffer
->command_buffer
);
347 WINE_VK_REMOVE_HANDLE_MAPPING(device
->phys_dev
->instance
, buffer
);
348 buffer
->handle
->base
.unix_handle
= 0;
353 static void wine_vk_device_get_queues(struct wine_device
*device
,
354 uint32_t family_index
, uint32_t queue_count
, VkDeviceQueueCreateFlags flags
,
355 struct wine_queue
*queues
, VkQueue
*handles
)
357 VkDeviceQueueInfo2 queue_info
;
360 for (i
= 0; i
< queue_count
; i
++)
362 struct wine_queue
*queue
= &queues
[i
];
364 queue
->device
= device
;
365 queue
->handle
= (*handles
)++;
366 queue
->family_index
= family_index
;
367 queue
->queue_index
= i
;
368 queue
->flags
= flags
;
370 /* The Vulkan spec says:
372 * "vkGetDeviceQueue must only be used to get queues that were created
373 * with the flags parameter of VkDeviceQueueCreateInfo set to zero."
375 if (flags
&& device
->funcs
.p_vkGetDeviceQueue2
)
377 queue_info
.sType
= VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2
;
378 queue_info
.pNext
= NULL
;
379 queue_info
.flags
= flags
;
380 queue_info
.queueFamilyIndex
= family_index
;
381 queue_info
.queueIndex
= i
;
382 device
->funcs
.p_vkGetDeviceQueue2(device
->device
, &queue_info
, &queue
->queue
);
386 device
->funcs
.p_vkGetDeviceQueue(device
->device
, family_index
, i
, &queue
->queue
);
389 queue
->handle
->base
.unix_handle
= (uintptr_t)queue
;
390 WINE_VK_ADD_DISPATCHABLE_MAPPING(device
->phys_dev
->instance
, queue
->handle
, queue
->queue
, queue
);
394 static VkResult
wine_vk_device_convert_create_info(struct wine_phys_dev
*phys_dev
,
395 struct conversion_context
*ctx
, const VkDeviceCreateInfo
*src
, VkDeviceCreateInfo
*dst
)
401 /* Should be filtered out by loader as ICDs don't support layers. */
402 dst
->enabledLayerCount
= 0;
403 dst
->ppEnabledLayerNames
= NULL
;
405 TRACE("Enabled %u extensions.\n", dst
->enabledExtensionCount
);
406 for (i
= 0; i
< dst
->enabledExtensionCount
; i
++)
408 const char *extension_name
= dst
->ppEnabledExtensionNames
[i
];
409 TRACE("Extension %u: %s.\n", i
, debugstr_a(extension_name
));
410 if (!wine_vk_device_extension_supported(extension_name
))
412 WARN("Extension %s is not supported.\n", debugstr_a(extension_name
));
413 return VK_ERROR_EXTENSION_NOT_PRESENT
;
417 if (phys_dev
->external_memory_align
)
419 const char **new_extensions
;
421 new_extensions
= conversion_context_alloc(ctx
, (dst
->enabledExtensionCount
+ 2) *
422 sizeof(*dst
->ppEnabledExtensionNames
));
423 memcpy(new_extensions
, src
->ppEnabledExtensionNames
,
424 dst
->enabledExtensionCount
* sizeof(*dst
->ppEnabledExtensionNames
));
425 new_extensions
[dst
->enabledExtensionCount
++] = "VK_KHR_external_memory";
426 new_extensions
[dst
->enabledExtensionCount
++] = "VK_EXT_external_memory_host";
427 dst
->ppEnabledExtensionNames
= new_extensions
;
433 /* Helper function used for freeing a device structure. This function supports full
434 * and partial object cleanups and can thus be used for vkCreateDevice failures.
436 static void wine_vk_device_free(struct wine_device
*device
)
438 struct wine_queue
*queue
;
446 for (i
= 0; i
< device
->queue_count
; i
++)
448 queue
= &device
->queues
[i
];
449 if (queue
&& queue
->queue
)
450 WINE_VK_REMOVE_HANDLE_MAPPING(device
->phys_dev
->instance
, queue
);
452 free(device
->queues
);
453 device
->queues
= NULL
;
456 if (device
->device
&& device
->funcs
.p_vkDestroyDevice
)
458 WINE_VK_REMOVE_HANDLE_MAPPING(device
->phys_dev
->instance
, device
);
459 device
->funcs
.p_vkDestroyDevice(device
->device
, NULL
/* pAllocator */);
465 NTSTATUS
init_vulkan(void *args
)
467 vk_funcs
= __wine_get_vulkan_driver(WINE_VULKAN_DRIVER_VERSION
);
470 ERR("Failed to load Wine graphics driver supporting Vulkan.\n");
471 return STATUS_UNSUCCESSFUL
;
474 return STATUS_SUCCESS
;
477 /* Helper function for converting between win32 and host compatible VkInstanceCreateInfo.
478 * This function takes care of extensions handled at winevulkan layer, a Wine graphics
479 * driver is responsible for handling e.g. surface extensions.
481 static VkResult
wine_vk_instance_convert_create_info(struct conversion_context
*ctx
,
482 const VkInstanceCreateInfo
*src
, VkInstanceCreateInfo
*dst
, struct wine_instance
*object
)
484 VkDebugUtilsMessengerCreateInfoEXT
*debug_utils_messenger
;
485 VkDebugReportCallbackCreateInfoEXT
*debug_report_callback
;
486 VkBaseInStructure
*header
;
491 object
->utils_messenger_count
= wine_vk_count_struct(dst
, DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT
);
492 object
->utils_messengers
= calloc(object
->utils_messenger_count
, sizeof(*object
->utils_messengers
));
493 header
= (VkBaseInStructure
*) dst
;
494 for (i
= 0; i
< object
->utils_messenger_count
; i
++)
496 header
= find_next_struct(header
->pNext
, VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT
);
497 debug_utils_messenger
= (VkDebugUtilsMessengerCreateInfoEXT
*) header
;
499 object
->utils_messengers
[i
].instance
= object
;
500 object
->utils_messengers
[i
].debug_messenger
= VK_NULL_HANDLE
;
501 object
->utils_messengers
[i
].user_callback
= debug_utils_messenger
->pfnUserCallback
;
502 object
->utils_messengers
[i
].user_data
= debug_utils_messenger
->pUserData
;
504 /* convert_VkInstanceCreateInfo_* already copied the chain, so we can modify it in-place. */
505 debug_utils_messenger
->pfnUserCallback
= (void *) &debug_utils_callback_conversion
;
506 debug_utils_messenger
->pUserData
= &object
->utils_messengers
[i
];
509 debug_report_callback
= find_next_struct(header
->pNext
,
510 VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT
);
511 if (debug_report_callback
)
513 object
->default_callback
.instance
= object
;
514 object
->default_callback
.debug_callback
= VK_NULL_HANDLE
;
515 object
->default_callback
.user_callback
= debug_report_callback
->pfnCallback
;
516 object
->default_callback
.user_data
= debug_report_callback
->pUserData
;
518 debug_report_callback
->pfnCallback
= (void *) &debug_report_callback_conversion
;
519 debug_report_callback
->pUserData
= &object
->default_callback
;
522 /* ICDs don't support any layers, so nothing to copy. Modern versions of the loader
523 * filter this data out as well.
525 if (object
->quirks
& WINEVULKAN_QUIRK_IGNORE_EXPLICIT_LAYERS
) {
526 dst
->enabledLayerCount
= 0;
527 dst
->ppEnabledLayerNames
= NULL
;
528 WARN("Ignoring explicit layers!\n");
529 } else if (dst
->enabledLayerCount
) {
530 FIXME("Loading explicit layers is not supported by winevulkan!\n");
531 return VK_ERROR_LAYER_NOT_PRESENT
;
534 TRACE("Enabled %u instance extensions.\n", dst
->enabledExtensionCount
);
535 for (i
= 0; i
< dst
->enabledExtensionCount
; i
++)
537 const char *extension_name
= dst
->ppEnabledExtensionNames
[i
];
538 TRACE("Extension %u: %s.\n", i
, debugstr_a(extension_name
));
539 if (!wine_vk_instance_extension_supported(extension_name
))
541 WARN("Extension %s is not supported.\n", debugstr_a(extension_name
));
542 return VK_ERROR_EXTENSION_NOT_PRESENT
;
544 if (!strcmp(extension_name
, "VK_EXT_debug_utils") || !strcmp(extension_name
, "VK_EXT_debug_report"))
546 object
->enable_wrapper_list
= VK_TRUE
;
550 if (use_external_memory())
552 const char **new_extensions
;
554 new_extensions
= conversion_context_alloc(ctx
, (dst
->enabledExtensionCount
+ 2) *
555 sizeof(*dst
->ppEnabledExtensionNames
));
556 memcpy(new_extensions
, src
->ppEnabledExtensionNames
,
557 dst
->enabledExtensionCount
* sizeof(*dst
->ppEnabledExtensionNames
));
558 new_extensions
[dst
->enabledExtensionCount
++] = "VK_KHR_get_physical_device_properties2";
559 new_extensions
[dst
->enabledExtensionCount
++] = "VK_KHR_external_memory_capabilities";
560 dst
->ppEnabledExtensionNames
= new_extensions
;
566 /* Helper function which stores wrapped physical devices in the instance object. */
567 static VkResult
wine_vk_instance_load_physical_devices(struct wine_instance
*instance
)
569 VkPhysicalDevice
*tmp_phys_devs
;
570 uint32_t phys_dev_count
;
574 res
= instance
->funcs
.p_vkEnumeratePhysicalDevices(instance
->instance
, &phys_dev_count
, NULL
);
575 if (res
!= VK_SUCCESS
)
577 ERR("Failed to enumerate physical devices, res=%d\n", res
);
583 if (phys_dev_count
> instance
->handle
->phys_dev_count
)
585 instance
->handle
->phys_dev_count
= phys_dev_count
;
586 return VK_ERROR_OUT_OF_POOL_MEMORY
;
588 instance
->handle
->phys_dev_count
= phys_dev_count
;
590 if (!(tmp_phys_devs
= calloc(phys_dev_count
, sizeof(*tmp_phys_devs
))))
591 return VK_ERROR_OUT_OF_HOST_MEMORY
;
593 res
= instance
->funcs
.p_vkEnumeratePhysicalDevices(instance
->instance
, &phys_dev_count
, tmp_phys_devs
);
594 if (res
!= VK_SUCCESS
)
600 instance
->phys_devs
= calloc(phys_dev_count
, sizeof(*instance
->phys_devs
));
601 if (!instance
->phys_devs
)
604 return VK_ERROR_OUT_OF_HOST_MEMORY
;
607 /* Wrap each native physical device handle into a dispatchable object for the ICD loader. */
608 for (i
= 0; i
< phys_dev_count
; i
++)
610 struct wine_phys_dev
*phys_dev
= wine_vk_physical_device_alloc(instance
, tmp_phys_devs
[i
],
611 &instance
->handle
->phys_devs
[i
]);
614 ERR("Unable to allocate memory for physical device!\n");
616 return VK_ERROR_OUT_OF_HOST_MEMORY
;
619 instance
->phys_devs
[i
] = phys_dev
;
620 instance
->phys_dev_count
= i
+ 1;
622 instance
->phys_dev_count
= phys_dev_count
;
628 static struct wine_phys_dev
*wine_vk_instance_wrap_physical_device(struct wine_instance
*instance
,
629 VkPhysicalDevice physical_device
)
633 for (i
= 0; i
< instance
->phys_dev_count
; ++i
)
635 struct wine_phys_dev
*current
= instance
->phys_devs
[i
];
636 if (current
->phys_dev
== physical_device
)
640 ERR("Unrecognized physical device %p.\n", physical_device
);
644 /* Helper function used for freeing an instance structure. This function supports full
645 * and partial object cleanups and can thus be used for vkCreateInstance failures.
647 static void wine_vk_instance_free(struct wine_instance
*instance
)
652 if (instance
->phys_devs
)
656 for (i
= 0; i
< instance
->phys_dev_count
; i
++)
658 wine_vk_physical_device_free(instance
->phys_devs
[i
]);
660 free(instance
->phys_devs
);
663 if (instance
->instance
)
665 vk_funcs
->p_vkDestroyInstance(instance
->instance
, NULL
/* allocator */);
666 WINE_VK_REMOVE_HANDLE_MAPPING(instance
, instance
);
669 pthread_rwlock_destroy(&instance
->wrapper_lock
);
670 free(instance
->utils_messengers
);
675 VkResult
wine_vkAllocateCommandBuffers(VkDevice handle
, const VkCommandBufferAllocateInfo
*allocate_info
,
676 VkCommandBuffer
*buffers
)
678 struct wine_device
*device
= wine_device_from_handle(handle
);
679 struct wine_cmd_buffer
*buffer
;
680 struct wine_cmd_pool
*pool
;
681 VkResult res
= VK_SUCCESS
;
684 pool
= wine_cmd_pool_from_handle(allocate_info
->commandPool
);
686 for (i
= 0; i
< allocate_info
->commandBufferCount
; i
++)
688 VkCommandBufferAllocateInfo allocate_info_host
;
690 /* TODO: future extensions (none yet) may require pNext conversion. */
691 allocate_info_host
.pNext
= allocate_info
->pNext
;
692 allocate_info_host
.sType
= allocate_info
->sType
;
693 allocate_info_host
.commandPool
= pool
->command_pool
;
694 allocate_info_host
.level
= allocate_info
->level
;
695 allocate_info_host
.commandBufferCount
= 1;
697 TRACE("Allocating command buffer %u from pool 0x%s.\n",
698 i
, wine_dbgstr_longlong(allocate_info_host
.commandPool
));
700 if (!(buffer
= calloc(1, sizeof(*buffer
))))
702 res
= VK_ERROR_OUT_OF_HOST_MEMORY
;
706 buffer
->handle
= buffers
[i
];
707 buffer
->device
= device
;
708 res
= device
->funcs
.p_vkAllocateCommandBuffers(device
->device
,
709 &allocate_info_host
, &buffer
->command_buffer
);
710 buffer
->handle
->base
.unix_handle
= (uintptr_t)buffer
;
711 WINE_VK_ADD_DISPATCHABLE_MAPPING(device
->phys_dev
->instance
, buffer
->handle
,
712 buffer
->command_buffer
, buffer
);
713 if (res
!= VK_SUCCESS
)
715 ERR("Failed to allocate command buffer, res=%d.\n", res
);
716 buffer
->command_buffer
= VK_NULL_HANDLE
;
721 if (res
!= VK_SUCCESS
)
722 wine_vk_free_command_buffers(device
, pool
, i
+ 1, buffers
);
727 VkResult
wine_vkCreateDevice(VkPhysicalDevice phys_dev_handle
, const VkDeviceCreateInfo
*create_info
,
728 const VkAllocationCallbacks
*allocator
, VkDevice
*ret_device
,
731 struct wine_phys_dev
*phys_dev
= wine_phys_dev_from_handle(phys_dev_handle
);
732 VkDevice device_handle
= client_ptr
;
733 VkDeviceCreateInfo create_info_host
;
734 struct VkQueue_T
*queue_handles
;
735 struct wine_queue
*next_queue
;
736 struct conversion_context ctx
;
737 struct wine_device
*object
;
742 FIXME("Support for allocation callbacks not implemented yet\n");
744 if (TRACE_ON(vulkan
))
746 VkPhysicalDeviceProperties properties
;
748 phys_dev
->instance
->funcs
.p_vkGetPhysicalDeviceProperties(phys_dev
->phys_dev
, &properties
);
750 TRACE("Device name: %s.\n", debugstr_a(properties
.deviceName
));
751 TRACE("Vendor ID: %#x, Device ID: %#x.\n", properties
.vendorID
, properties
.deviceID
);
752 TRACE("Driver version: %#x.\n", properties
.driverVersion
);
755 if (!(object
= calloc(1, sizeof(*object
))))
756 return VK_ERROR_OUT_OF_HOST_MEMORY
;
758 object
->phys_dev
= phys_dev
;
760 init_conversion_context(&ctx
);
761 res
= wine_vk_device_convert_create_info(phys_dev
, &ctx
, create_info
, &create_info_host
);
762 if (res
== VK_SUCCESS
)
763 res
= phys_dev
->instance
->funcs
.p_vkCreateDevice(phys_dev
->phys_dev
,
764 &create_info_host
, NULL
/* allocator */, &object
->device
);
765 free_conversion_context(&ctx
);
766 WINE_VK_ADD_DISPATCHABLE_MAPPING(phys_dev
->instance
, device_handle
, object
->device
, object
);
767 if (res
!= VK_SUCCESS
)
769 WARN("Failed to create device, res=%d.\n", res
);
773 /* Just load all function pointers we are aware off. The loader takes care of filtering.
774 * We use vkGetDeviceProcAddr as opposed to vkGetInstanceProcAddr for efficiency reasons
775 * as functions pass through fewer dispatch tables within the loader.
777 #define USE_VK_FUNC(name) \
778 object->funcs.p_##name = (void *)vk_funcs->p_vkGetDeviceProcAddr(object->device, #name); \
779 if (object->funcs.p_##name == NULL) \
780 TRACE("Not found '%s'.\n", #name);
781 ALL_VK_DEVICE_FUNCS()
784 /* We need to cache all queues within the device as each requires wrapping since queues are
785 * dispatchable objects.
787 for (i
= 0; i
< create_info_host
.queueCreateInfoCount
; i
++)
789 object
->queue_count
+= create_info_host
.pQueueCreateInfos
[i
].queueCount
;
792 if (!(object
->queues
= calloc(object
->queue_count
, sizeof(*object
->queues
))))
794 res
= VK_ERROR_OUT_OF_HOST_MEMORY
;
798 next_queue
= object
->queues
;
799 queue_handles
= device_handle
->queues
;
800 for (i
= 0; i
< create_info_host
.queueCreateInfoCount
; i
++)
802 uint32_t flags
= create_info_host
.pQueueCreateInfos
[i
].flags
;
803 uint32_t family_index
= create_info_host
.pQueueCreateInfos
[i
].queueFamilyIndex
;
804 uint32_t queue_count
= create_info_host
.pQueueCreateInfos
[i
].queueCount
;
806 TRACE("Queue family index %u, queue count %u.\n", family_index
, queue_count
);
808 wine_vk_device_get_queues(object
, family_index
, queue_count
, flags
, next_queue
, &queue_handles
);
809 next_queue
+= queue_count
;
812 device_handle
->quirks
= phys_dev
->instance
->quirks
;
813 device_handle
->base
.unix_handle
= (uintptr_t)object
;
814 *ret_device
= device_handle
;
815 TRACE("Created device %p (native device %p).\n", object
, object
->device
);
819 wine_vk_device_free(object
);
823 VkResult
wine_vkCreateInstance(const VkInstanceCreateInfo
*create_info
,
824 const VkAllocationCallbacks
*allocator
, VkInstance
*instance
,
827 VkInstance client_instance
= client_ptr
;
828 VkInstanceCreateInfo create_info_host
;
829 const VkApplicationInfo
*app_info
;
830 struct conversion_context ctx
;
831 struct wine_instance
*object
;
835 FIXME("Support for allocation callbacks not implemented yet\n");
837 if (!(object
= calloc(1, sizeof(*object
))))
839 ERR("Failed to allocate memory for instance\n");
840 return VK_ERROR_OUT_OF_HOST_MEMORY
;
842 list_init(&object
->wrappers
);
843 pthread_rwlock_init(&object
->wrapper_lock
, NULL
);
845 init_conversion_context(&ctx
);
846 res
= wine_vk_instance_convert_create_info(&ctx
, create_info
, &create_info_host
, object
);
847 if (res
== VK_SUCCESS
)
848 res
= vk_funcs
->p_vkCreateInstance(&create_info_host
, NULL
/* allocator */, &object
->instance
);
849 free_conversion_context(&ctx
);
850 if (res
!= VK_SUCCESS
)
852 ERR("Failed to create instance, res=%d\n", res
);
853 wine_vk_instance_free(object
);
857 object
->handle
= client_instance
;
858 WINE_VK_ADD_DISPATCHABLE_MAPPING(object
, object
->handle
, object
->instance
, object
);
860 /* Load all instance functions we are aware of. Note the loader takes care
861 * of any filtering for extensions which were not requested, but which the
864 #define USE_VK_FUNC(name) \
865 object->funcs.p_##name = (void *)vk_funcs->p_vkGetInstanceProcAddr(object->instance, #name);
866 ALL_VK_INSTANCE_FUNCS()
869 /* Cache physical devices for vkEnumeratePhysicalDevices within the instance as
870 * each vkPhysicalDevice is a dispatchable object, which means we need to wrap
871 * the native physical devices and present those to the application.
872 * Cleanup happens as part of wine_vkDestroyInstance.
874 res
= wine_vk_instance_load_physical_devices(object
);
875 if (res
!= VK_SUCCESS
)
877 ERR("Failed to load physical devices, res=%d\n", res
);
878 wine_vk_instance_free(object
);
882 if ((app_info
= create_info
->pApplicationInfo
))
884 TRACE("Application name %s, application version %#x.\n",
885 debugstr_a(app_info
->pApplicationName
), app_info
->applicationVersion
);
886 TRACE("Engine name %s, engine version %#x.\n", debugstr_a(app_info
->pEngineName
),
887 app_info
->engineVersion
);
888 TRACE("API version %#x.\n", app_info
->apiVersion
);
890 if (app_info
->pEngineName
&& !strcmp(app_info
->pEngineName
, "idTech"))
891 object
->quirks
|= WINEVULKAN_QUIRK_GET_DEVICE_PROC_ADDR
;
894 object
->quirks
|= WINEVULKAN_QUIRK_ADJUST_MAX_IMAGE_COUNT
;
896 client_instance
->base
.unix_handle
= (uintptr_t)object
;
897 *instance
= client_instance
;
898 TRACE("Created instance %p (native instance %p).\n", object
, object
->instance
);
902 void wine_vkDestroyDevice(VkDevice handle
, const VkAllocationCallbacks
*allocator
)
904 struct wine_device
*device
= wine_device_from_handle(handle
);
907 FIXME("Support for allocation callbacks not implemented yet\n");
909 wine_vk_device_free(device
);
912 void wine_vkDestroyInstance(VkInstance handle
, const VkAllocationCallbacks
*allocator
)
914 struct wine_instance
*instance
= wine_instance_from_handle(handle
);
917 FIXME("Support allocation allocators\n");
919 wine_vk_instance_free(instance
);
922 VkResult
wine_vkEnumerateDeviceExtensionProperties(VkPhysicalDevice phys_dev_handle
, const char *layer_name
,
923 uint32_t *count
, VkExtensionProperties
*properties
)
925 struct wine_phys_dev
*phys_dev
= wine_phys_dev_from_handle(phys_dev_handle
);
927 /* This shouldn't get called with layer_name set, the ICD loader prevents it. */
930 ERR("Layer enumeration not supported from ICD.\n");
931 return VK_ERROR_LAYER_NOT_PRESENT
;
936 *count
= phys_dev
->extension_count
;
940 *count
= min(*count
, phys_dev
->extension_count
);
941 memcpy(properties
, phys_dev
->extensions
, *count
* sizeof(*properties
));
943 TRACE("Returning %u extensions.\n", *count
);
944 return *count
< phys_dev
->extension_count
? VK_INCOMPLETE
: VK_SUCCESS
;
947 VkResult
wine_vkEnumerateInstanceExtensionProperties(const char *name
, uint32_t *count
,
948 VkExtensionProperties
*properties
)
950 uint32_t num_properties
= 0, num_host_properties
;
951 VkExtensionProperties
*host_properties
;
955 res
= vk_funcs
->p_vkEnumerateInstanceExtensionProperties(NULL
, &num_host_properties
, NULL
);
956 if (res
!= VK_SUCCESS
)
959 if (!(host_properties
= calloc(num_host_properties
, sizeof(*host_properties
))))
960 return VK_ERROR_OUT_OF_HOST_MEMORY
;
962 res
= vk_funcs
->p_vkEnumerateInstanceExtensionProperties(NULL
, &num_host_properties
, host_properties
);
963 if (res
!= VK_SUCCESS
)
965 ERR("Failed to retrieve host properties, res=%d.\n", res
);
966 free(host_properties
);
970 /* The Wine graphics driver provides us with all extensions supported by the host side
971 * including extension fixup (e.g. VK_KHR_xlib_surface -> VK_KHR_win32_surface). It is
972 * up to us here to filter the list down to extensions for which we have thunks.
974 for (i
= 0; i
< num_host_properties
; i
++)
976 if (wine_vk_instance_extension_supported(host_properties
[i
].extensionName
))
979 TRACE("Instance extension '%s' is not supported.\n", host_properties
[i
].extensionName
);
984 TRACE("Returning %u extensions.\n", num_properties
);
985 *count
= num_properties
;
986 free(host_properties
);
990 for (i
= 0, j
= 0; i
< num_host_properties
&& j
< *count
; i
++)
992 if (wine_vk_instance_extension_supported(host_properties
[i
].extensionName
))
994 TRACE("Enabling extension '%s'.\n", host_properties
[i
].extensionName
);
995 properties
[j
++] = host_properties
[i
];
998 *count
= min(*count
, num_properties
);
1000 free(host_properties
);
1001 return *count
< num_properties
? VK_INCOMPLETE
: VK_SUCCESS
;
1004 VkResult
wine_vkEnumerateDeviceLayerProperties(VkPhysicalDevice phys_dev
, uint32_t *count
,
1005 VkLayerProperties
*properties
)
1011 VkResult
wine_vkEnumerateInstanceVersion(uint32_t *version
)
1015 static VkResult (*p_vkEnumerateInstanceVersion
)(uint32_t *version
);
1016 if (!p_vkEnumerateInstanceVersion
)
1017 p_vkEnumerateInstanceVersion
= vk_funcs
->p_vkGetInstanceProcAddr(NULL
, "vkEnumerateInstanceVersion");
1019 if (p_vkEnumerateInstanceVersion
)
1021 res
= p_vkEnumerateInstanceVersion(version
);
1025 *version
= VK_API_VERSION_1_0
;
1029 TRACE("API version %u.%u.%u.\n",
1030 VK_VERSION_MAJOR(*version
), VK_VERSION_MINOR(*version
), VK_VERSION_PATCH(*version
));
1031 *version
= min(WINE_VK_VERSION
, *version
);
1035 VkResult
wine_vkEnumeratePhysicalDevices(VkInstance handle
, uint32_t *count
, VkPhysicalDevice
*devices
)
1037 struct wine_instance
*instance
= wine_instance_from_handle(handle
);
1042 *count
= instance
->phys_dev_count
;
1046 *count
= min(*count
, instance
->phys_dev_count
);
1047 for (i
= 0; i
< *count
; i
++)
1049 devices
[i
] = instance
->phys_devs
[i
]->handle
;
1052 TRACE("Returning %u devices.\n", *count
);
1053 return *count
< instance
->phys_dev_count
? VK_INCOMPLETE
: VK_SUCCESS
;
1056 void wine_vkFreeCommandBuffers(VkDevice handle
, VkCommandPool command_pool
, uint32_t count
,
1057 const VkCommandBuffer
*buffers
)
1059 struct wine_device
*device
= wine_device_from_handle(handle
);
1060 struct wine_cmd_pool
*pool
= wine_cmd_pool_from_handle(command_pool
);
1062 wine_vk_free_command_buffers(device
, pool
, count
, buffers
);
1065 static VkQueue
wine_vk_device_find_queue(VkDevice handle
, const VkDeviceQueueInfo2
*info
)
1067 struct wine_device
*device
= wine_device_from_handle(handle
);
1068 struct wine_queue
*queue
;
1071 for (i
= 0; i
< device
->queue_count
; i
++)
1073 queue
= &device
->queues
[i
];
1074 if (queue
->family_index
== info
->queueFamilyIndex
1075 && queue
->queue_index
== info
->queueIndex
1076 && queue
->flags
== info
->flags
)
1078 return queue
->handle
;
1082 return VK_NULL_HANDLE
;
1085 void wine_vkGetDeviceQueue(VkDevice device
, uint32_t family_index
, uint32_t queue_index
, VkQueue
*queue
)
1087 VkDeviceQueueInfo2 queue_info
;
1089 queue_info
.sType
= VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2
;
1090 queue_info
.pNext
= NULL
;
1091 queue_info
.flags
= 0;
1092 queue_info
.queueFamilyIndex
= family_index
;
1093 queue_info
.queueIndex
= queue_index
;
1095 *queue
= wine_vk_device_find_queue(device
, &queue_info
);
1098 void wine_vkGetDeviceQueue2(VkDevice device
, const VkDeviceQueueInfo2
*info
, VkQueue
*queue
)
1100 const VkBaseInStructure
*chain
;
1102 if ((chain
= info
->pNext
))
1103 FIXME("Ignoring a linked structure of type %u.\n", chain
->sType
);
1105 *queue
= wine_vk_device_find_queue(device
, info
);
1108 VkResult
wine_vkCreateCommandPool(VkDevice device_handle
, const VkCommandPoolCreateInfo
*info
,
1109 const VkAllocationCallbacks
*allocator
, VkCommandPool
*command_pool
,
1112 struct wine_device
*device
= wine_device_from_handle(device_handle
);
1113 struct vk_command_pool
*handle
= client_ptr
;
1114 struct wine_cmd_pool
*object
;
1118 FIXME("Support for allocation callbacks not implemented yet\n");
1120 if (!(object
= calloc(1, sizeof(*object
))))
1121 return VK_ERROR_OUT_OF_HOST_MEMORY
;
1123 res
= device
->funcs
.p_vkCreateCommandPool(device
->device
, info
, NULL
, &object
->command_pool
);
1125 if (res
== VK_SUCCESS
)
1127 object
->handle
= (uintptr_t)handle
;
1128 handle
->unix_handle
= (uintptr_t)object
;
1129 WINE_VK_ADD_NON_DISPATCHABLE_MAPPING(device
->phys_dev
->instance
, object
->handle
,
1130 object
->command_pool
, object
);
1131 *command_pool
= object
->handle
;
1141 void wine_vkDestroyCommandPool(VkDevice device_handle
, VkCommandPool handle
,
1142 const VkAllocationCallbacks
*allocator
)
1144 struct wine_device
*device
= wine_device_from_handle(device_handle
);
1145 struct wine_cmd_pool
*pool
= wine_cmd_pool_from_handle(handle
);
1148 FIXME("Support for allocation callbacks not implemented yet\n");
1150 WINE_VK_REMOVE_HANDLE_MAPPING(device
->phys_dev
->instance
, pool
);
1152 device
->funcs
.p_vkDestroyCommandPool(device
->device
, pool
->command_pool
, NULL
);
1156 static VkResult
wine_vk_enumerate_physical_device_groups(struct wine_instance
*instance
,
1157 VkResult (*p_vkEnumeratePhysicalDeviceGroups
)(VkInstance
, uint32_t *, VkPhysicalDeviceGroupProperties
*),
1158 uint32_t *count
, VkPhysicalDeviceGroupProperties
*properties
)
1163 res
= p_vkEnumeratePhysicalDeviceGroups(instance
->instance
, count
, properties
);
1164 if (res
< 0 || !properties
)
1167 for (i
= 0; i
< *count
; ++i
)
1169 VkPhysicalDeviceGroupProperties
*current
= &properties
[i
];
1170 for (j
= 0; j
< current
->physicalDeviceCount
; ++j
)
1172 VkPhysicalDevice dev
= current
->physicalDevices
[j
];
1173 struct wine_phys_dev
*phys_dev
= wine_vk_instance_wrap_physical_device(instance
, dev
);
1175 return VK_ERROR_INITIALIZATION_FAILED
;
1176 current
->physicalDevices
[j
] = phys_dev
->handle
;
1183 VkResult
wine_vkEnumeratePhysicalDeviceGroups(VkInstance handle
, uint32_t *count
,
1184 VkPhysicalDeviceGroupProperties
*properties
)
1186 struct wine_instance
*instance
= wine_instance_from_handle(handle
);
1188 return wine_vk_enumerate_physical_device_groups(instance
,
1189 instance
->funcs
.p_vkEnumeratePhysicalDeviceGroups
, count
, properties
);
1192 VkResult
wine_vkEnumeratePhysicalDeviceGroupsKHR(VkInstance handle
, uint32_t *count
,
1193 VkPhysicalDeviceGroupProperties
*properties
)
1195 struct wine_instance
*instance
= wine_instance_from_handle(handle
);
1197 return wine_vk_enumerate_physical_device_groups(instance
,
1198 instance
->funcs
.p_vkEnumeratePhysicalDeviceGroupsKHR
, count
, properties
);
1201 void wine_vkGetPhysicalDeviceExternalFenceProperties(VkPhysicalDevice phys_dev
,
1202 const VkPhysicalDeviceExternalFenceInfo
*fence_info
,
1203 VkExternalFenceProperties
*properties
)
1205 properties
->exportFromImportedHandleTypes
= 0;
1206 properties
->compatibleHandleTypes
= 0;
1207 properties
->externalFenceFeatures
= 0;
1210 void wine_vkGetPhysicalDeviceExternalFencePropertiesKHR(VkPhysicalDevice phys_dev
,
1211 const VkPhysicalDeviceExternalFenceInfo
*fence_info
,
1212 VkExternalFenceProperties
*properties
)
1214 properties
->exportFromImportedHandleTypes
= 0;
1215 properties
->compatibleHandleTypes
= 0;
1216 properties
->externalFenceFeatures
= 0;
1219 void wine_vkGetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice phys_dev
,
1220 const VkPhysicalDeviceExternalBufferInfo
*buffer_info
,
1221 VkExternalBufferProperties
*properties
)
1223 memset(&properties
->externalMemoryProperties
, 0, sizeof(properties
->externalMemoryProperties
));
1226 void wine_vkGetPhysicalDeviceExternalBufferPropertiesKHR(VkPhysicalDevice phys_dev
,
1227 const VkPhysicalDeviceExternalBufferInfo
*buffer_info
,
1228 VkExternalBufferProperties
*properties
)
1230 memset(&properties
->externalMemoryProperties
, 0, sizeof(properties
->externalMemoryProperties
));
1233 VkResult
wine_vkGetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice phys_dev_handle
,
1234 const VkPhysicalDeviceImageFormatInfo2
*format_info
,
1235 VkImageFormatProperties2
*properties
)
1237 struct wine_phys_dev
*phys_dev
= wine_phys_dev_from_handle(phys_dev_handle
);
1238 VkExternalImageFormatProperties
*external_image_properties
;
1241 res
= phys_dev
->instance
->funcs
.p_vkGetPhysicalDeviceImageFormatProperties2(phys_dev
->phys_dev
,
1242 format_info
, properties
);
1244 if ((external_image_properties
= find_next_struct(properties
,
1245 VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES
)))
1247 VkExternalMemoryProperties
*p
= &external_image_properties
->externalMemoryProperties
;
1248 p
->externalMemoryFeatures
= 0;
1249 p
->exportFromImportedHandleTypes
= 0;
1250 p
->compatibleHandleTypes
= 0;
1256 VkResult
wine_vkGetPhysicalDeviceImageFormatProperties2KHR(VkPhysicalDevice phys_dev_handle
,
1257 const VkPhysicalDeviceImageFormatInfo2
*format_info
,
1258 VkImageFormatProperties2
*properties
)
1260 struct wine_phys_dev
*phys_dev
= wine_phys_dev_from_handle(phys_dev_handle
);
1261 VkExternalImageFormatProperties
*external_image_properties
;
1264 res
= phys_dev
->instance
->funcs
.p_vkGetPhysicalDeviceImageFormatProperties2KHR(phys_dev
->phys_dev
,
1265 format_info
, properties
);
1267 if ((external_image_properties
= find_next_struct(properties
,
1268 VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES
)))
1270 VkExternalMemoryProperties
*p
= &external_image_properties
->externalMemoryProperties
;
1271 p
->externalMemoryFeatures
= 0;
1272 p
->exportFromImportedHandleTypes
= 0;
1273 p
->compatibleHandleTypes
= 0;
1279 /* From ntdll/unix/sync.c */
1280 #define NANOSECONDS_IN_A_SECOND 1000000000
1281 #define TICKSPERSEC 10000000
1283 static inline VkTimeDomainEXT
get_performance_counter_time_domain(void)
1285 #if !defined(__APPLE__) && defined(HAVE_CLOCK_GETTIME)
1286 # ifdef CLOCK_MONOTONIC_RAW
1287 return VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT
;
1289 return VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT
;
1292 FIXME("No mapping for VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT on this platform.\n");
1293 return VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT
;
1297 static VkTimeDomainEXT
map_to_host_time_domain(VkTimeDomainEXT domain
)
1299 /* Matches ntdll/unix/sync.c's performance counter implementation. */
1300 if (domain
== VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT
)
1301 return get_performance_counter_time_domain();
1306 static inline uint64_t convert_monotonic_timestamp(uint64_t value
)
1308 return value
/ (NANOSECONDS_IN_A_SECOND
/ TICKSPERSEC
);
1311 static inline uint64_t convert_timestamp(VkTimeDomainEXT host_domain
, VkTimeDomainEXT target_domain
, uint64_t value
)
1313 if (host_domain
== target_domain
)
1316 /* Convert between MONOTONIC time in ns -> QueryPerformanceCounter */
1317 if ((host_domain
== VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT
|| host_domain
== VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT
)
1318 && target_domain
== VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT
)
1319 return convert_monotonic_timestamp(value
);
1321 FIXME("Couldn't translate between host domain %d and target domain %d\n", host_domain
, target_domain
);
1325 VkResult
wine_vkGetCalibratedTimestampsEXT(VkDevice handle
, uint32_t timestamp_count
,
1326 const VkCalibratedTimestampInfoEXT
*timestamp_infos
,
1327 uint64_t *timestamps
, uint64_t *max_deviation
)
1329 struct wine_device
*device
= wine_device_from_handle(handle
);
1330 VkCalibratedTimestampInfoEXT
* host_timestamp_infos
;
1333 TRACE("%p, %u, %p, %p, %p\n", device
, timestamp_count
, timestamp_infos
, timestamps
, max_deviation
);
1335 if (!(host_timestamp_infos
= malloc(sizeof(VkCalibratedTimestampInfoEXT
) * timestamp_count
)))
1336 return VK_ERROR_OUT_OF_HOST_MEMORY
;
1338 for (i
= 0; i
< timestamp_count
; i
++)
1340 host_timestamp_infos
[i
].sType
= timestamp_infos
[i
].sType
;
1341 host_timestamp_infos
[i
].pNext
= timestamp_infos
[i
].pNext
;
1342 host_timestamp_infos
[i
].timeDomain
= map_to_host_time_domain(timestamp_infos
[i
].timeDomain
);
1345 res
= device
->funcs
.p_vkGetCalibratedTimestampsEXT(device
->device
, timestamp_count
, host_timestamp_infos
, timestamps
, max_deviation
);
1346 if (res
!= VK_SUCCESS
)
1349 for (i
= 0; i
< timestamp_count
; i
++)
1350 timestamps
[i
] = convert_timestamp(host_timestamp_infos
[i
].timeDomain
, timestamp_infos
[i
].timeDomain
, timestamps
[i
]);
1352 free(host_timestamp_infos
);
1357 VkResult
wine_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT(VkPhysicalDevice handle
,
1358 uint32_t *time_domain_count
,
1359 VkTimeDomainEXT
*time_domains
)
1361 struct wine_phys_dev
*phys_dev
= wine_phys_dev_from_handle(handle
);
1362 BOOL supports_device
= FALSE
, supports_monotonic
= FALSE
, supports_monotonic_raw
= FALSE
;
1363 const VkTimeDomainEXT performance_counter_domain
= get_performance_counter_time_domain();
1364 VkTimeDomainEXT
*host_time_domains
;
1365 uint32_t host_time_domain_count
;
1366 VkTimeDomainEXT out_time_domains
[2];
1367 uint32_t out_time_domain_count
;
1371 /* Find out the time domains supported on the host */
1372 res
= phys_dev
->instance
->funcs
.p_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT(phys_dev
->phys_dev
, &host_time_domain_count
, NULL
);
1373 if (res
!= VK_SUCCESS
)
1376 if (!(host_time_domains
= malloc(sizeof(VkTimeDomainEXT
) * host_time_domain_count
)))
1377 return VK_ERROR_OUT_OF_HOST_MEMORY
;
1379 res
= phys_dev
->instance
->funcs
.p_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT(phys_dev
->phys_dev
, &host_time_domain_count
, host_time_domains
);
1380 if (res
!= VK_SUCCESS
)
1382 free(host_time_domains
);
1386 for (i
= 0; i
< host_time_domain_count
; i
++)
1388 if (host_time_domains
[i
] == VK_TIME_DOMAIN_DEVICE_EXT
)
1389 supports_device
= TRUE
;
1390 else if (host_time_domains
[i
] == VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT
)
1391 supports_monotonic
= TRUE
;
1392 else if (host_time_domains
[i
] == VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT
)
1393 supports_monotonic_raw
= TRUE
;
1395 FIXME("Unknown time domain %d\n", host_time_domains
[i
]);
1398 free(host_time_domains
);
1400 out_time_domain_count
= 0;
1402 /* Map our monotonic times -> QPC */
1403 if (supports_monotonic_raw
&& performance_counter_domain
== VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT
)
1404 out_time_domains
[out_time_domain_count
++] = VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT
;
1405 else if (supports_monotonic
&& performance_counter_domain
== VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT
)
1406 out_time_domains
[out_time_domain_count
++] = VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT
;
1408 FIXME("VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT not supported on this platform.\n");
1410 /* Forward the device domain time */
1411 if (supports_device
)
1412 out_time_domains
[out_time_domain_count
++] = VK_TIME_DOMAIN_DEVICE_EXT
;
1414 /* Send the count/domains back to the app */
1417 *time_domain_count
= out_time_domain_count
;
1421 for (i
= 0; i
< min(*time_domain_count
, out_time_domain_count
); i
++)
1422 time_domains
[i
] = out_time_domains
[i
];
1424 res
= *time_domain_count
< out_time_domain_count
? VK_INCOMPLETE
: VK_SUCCESS
;
1425 *time_domain_count
= out_time_domain_count
;
1429 void wine_vkGetPhysicalDeviceExternalSemaphoreProperties(VkPhysicalDevice phys_dev
,
1430 const VkPhysicalDeviceExternalSemaphoreInfo
*info
,
1431 VkExternalSemaphoreProperties
*properties
)
1433 properties
->exportFromImportedHandleTypes
= 0;
1434 properties
->compatibleHandleTypes
= 0;
1435 properties
->externalSemaphoreFeatures
= 0;
1438 void wine_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR(VkPhysicalDevice phys_dev
,
1439 const VkPhysicalDeviceExternalSemaphoreInfo
*info
,
1440 VkExternalSemaphoreProperties
*properties
)
1442 properties
->exportFromImportedHandleTypes
= 0;
1443 properties
->compatibleHandleTypes
= 0;
1444 properties
->externalSemaphoreFeatures
= 0;
1447 VkResult
wine_vkCreateWin32SurfaceKHR(VkInstance handle
, const VkWin32SurfaceCreateInfoKHR
*createInfo
,
1448 const VkAllocationCallbacks
*allocator
, VkSurfaceKHR
*surface
)
1450 struct wine_instance
*instance
= wine_instance_from_handle(handle
);
1451 struct wine_surface
*object
;
1455 FIXME("Support for allocation callbacks not implemented yet\n");
1457 object
= calloc(1, sizeof(*object
));
1460 return VK_ERROR_OUT_OF_HOST_MEMORY
;
1462 res
= instance
->funcs
.p_vkCreateWin32SurfaceKHR(instance
->instance
, createInfo
, NULL
, &object
->driver_surface
);
1464 if (res
!= VK_SUCCESS
)
1470 object
->surface
= vk_funcs
->p_wine_get_native_surface(object
->driver_surface
);
1472 WINE_VK_ADD_NON_DISPATCHABLE_MAPPING(instance
, object
, object
->surface
, object
);
1474 *surface
= wine_surface_to_handle(object
);
1479 void wine_vkDestroySurfaceKHR(VkInstance handle
, VkSurfaceKHR surface
,
1480 const VkAllocationCallbacks
*allocator
)
1482 struct wine_instance
*instance
= wine_instance_from_handle(handle
);
1483 struct wine_surface
*object
= wine_surface_from_handle(surface
);
1488 instance
->funcs
.p_vkDestroySurfaceKHR(instance
->instance
, object
->driver_surface
, NULL
);
1490 WINE_VK_REMOVE_HANDLE_MAPPING(instance
, object
);
1494 VkResult
wine_vkAllocateMemory(VkDevice handle
, const VkMemoryAllocateInfo
*alloc_info
,
1495 const VkAllocationCallbacks
*allocator
, VkDeviceMemory
*ret
)
1497 struct wine_device
*device
= wine_device_from_handle(handle
);
1498 struct wine_device_memory
*memory
;
1499 VkMemoryAllocateInfo info
= *alloc_info
;
1500 VkImportMemoryHostPointerInfoEXT host_pointer_info
;
1502 void *mapping
= NULL
;
1505 /* For host visible memory, we try to use VK_EXT_external_memory_host on wow64
1506 * to ensure that mapped pointer is 32-bit. */
1507 mem_flags
= device
->phys_dev
->memory_properties
.memoryTypes
[alloc_info
->memoryTypeIndex
].propertyFlags
;
1508 if (device
->phys_dev
->external_memory_align
&& (mem_flags
& VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
) &&
1509 !find_next_struct(alloc_info
->pNext
, VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT
))
1511 VkMemoryHostPointerPropertiesEXT props
=
1513 .sType
= VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT
,
1515 uint32_t i
, align
= device
->phys_dev
->external_memory_align
- 1;
1516 SIZE_T alloc_size
= info
.allocationSize
;
1520 FIXME("Using VK_EXT_external_memory_host\n");
1522 if (NtAllocateVirtualMemory(GetCurrentProcess(), &mapping
, zero_bits(), &alloc_size
,
1523 MEM_COMMIT
, PAGE_READWRITE
))
1525 ERR("NtAllocateVirtualMemory failed\n");
1526 return VK_ERROR_OUT_OF_HOST_MEMORY
;
1529 result
= device
->funcs
.p_vkGetMemoryHostPointerPropertiesEXT(device
->device
,
1530 VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT
, mapping
, &props
);
1531 if (result
!= VK_SUCCESS
)
1533 ERR("vkGetMemoryHostPointerPropertiesEXT failed: %d\n", result
);
1537 if (!(props
.memoryTypeBits
& (1u << info
.memoryTypeIndex
)))
1539 /* If requested memory type is not allowed to use external memory,
1540 * try to find a supported compatible type. */
1541 uint32_t mask
= mem_flags
& ~VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
;
1542 for (i
= 0; i
< device
->phys_dev
->memory_properties
.memoryTypeCount
; i
++)
1544 if (!(props
.memoryTypeBits
& (1u << i
)))
1546 if ((device
->phys_dev
->memory_properties
.memoryTypes
[i
].propertyFlags
& mask
) != mask
)
1549 TRACE("Memory type not compatible with host memory, using %u instead\n", i
);
1550 info
.memoryTypeIndex
= i
;
1553 if (i
== device
->phys_dev
->memory_properties
.memoryTypeCount
)
1555 FIXME("Not found compatible memory type\n");
1557 NtFreeVirtualMemory(GetCurrentProcess(), &mapping
, &alloc_size
, MEM_RELEASE
);
1561 if (props
.memoryTypeBits
& (1u << info
.memoryTypeIndex
))
1563 host_pointer_info
.sType
= VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT
;
1564 host_pointer_info
.handleType
= VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT
;
1565 host_pointer_info
.pHostPointer
= mapping
;
1566 host_pointer_info
.pNext
= info
.pNext
;
1567 info
.pNext
= &host_pointer_info
;
1569 info
.allocationSize
= (info
.allocationSize
+ align
) & ~align
;
1573 if (!(memory
= malloc(sizeof(*memory
))))
1574 return VK_ERROR_OUT_OF_HOST_MEMORY
;
1576 result
= device
->funcs
.p_vkAllocateMemory(device
->device
, &info
, NULL
, &memory
->memory
);
1577 if (result
!= VK_SUCCESS
)
1583 memory
->mapping
= mapping
;
1584 *ret
= (VkDeviceMemory
)(uintptr_t)memory
;
1588 void wine_vkFreeMemory(VkDevice handle
, VkDeviceMemory memory_handle
, const VkAllocationCallbacks
*allocator
)
1590 struct wine_device
*device
= wine_device_from_handle(handle
);
1591 struct wine_device_memory
*memory
;
1595 memory
= wine_device_memory_from_handle(memory_handle
);
1597 device
->funcs
.p_vkFreeMemory(device
->device
, memory
->memory
, NULL
);
1599 if (memory
->mapping
)
1601 SIZE_T alloc_size
= 0;
1602 NtFreeVirtualMemory(GetCurrentProcess(), &memory
->mapping
, &alloc_size
, MEM_RELEASE
);
1608 VkResult
wine_vkMapMemory(VkDevice device
, VkDeviceMemory memory
, VkDeviceSize offset
,
1609 VkDeviceSize size
, VkMemoryMapFlags flags
, void **data
)
1611 const VkMemoryMapInfoKHR info
=
1613 .sType
= VK_STRUCTURE_TYPE_MEMORY_MAP_INFO_KHR
,
1620 return wine_vkMapMemory2KHR(device
, &info
, data
);
1623 VkResult
wine_vkMapMemory2KHR(VkDevice handle
, const VkMemoryMapInfoKHR
*map_info
, void **data
)
1625 struct wine_device
*device
= wine_device_from_handle(handle
);
1626 struct wine_device_memory
*memory
= wine_device_memory_from_handle(map_info
->memory
);
1627 VkMemoryMapInfoKHR info
= *map_info
;
1630 info
.memory
= memory
->memory
;
1631 if (memory
->mapping
)
1633 *data
= (char *)memory
->mapping
+ info
.offset
;
1634 TRACE("returning %p\n", *data
);
1638 if (device
->funcs
.p_vkMapMemory2KHR
)
1640 result
= device
->funcs
.p_vkMapMemory2KHR(device
->device
, &info
, data
);
1644 assert(!info
.pNext
);
1645 result
= device
->funcs
.p_vkMapMemory(device
->device
, info
.memory
, info
.offset
,
1646 info
.size
, info
.flags
, data
);
1650 if (NtCurrentTeb()->WowTebOffset
&& result
== VK_SUCCESS
&& (UINT_PTR
)*data
>> 32)
1652 FIXME("returned mapping %p does not fit 32-bit pointer\n", *data
);
1653 device
->funcs
.p_vkUnmapMemory(device
->device
, memory
->memory
);
1655 result
= VK_ERROR_OUT_OF_HOST_MEMORY
;
1662 void wine_vkUnmapMemory(VkDevice device
, VkDeviceMemory memory
)
1664 const VkMemoryUnmapInfoKHR info
=
1666 .sType
= VK_STRUCTURE_TYPE_MEMORY_UNMAP_INFO_KHR
,
1670 wine_vkUnmapMemory2KHR(device
, &info
);
1673 VkResult
wine_vkUnmapMemory2KHR(VkDevice handle
, const VkMemoryUnmapInfoKHR
*unmap_info
)
1675 struct wine_device
*device
= wine_device_from_handle(handle
);
1676 struct wine_device_memory
*memory
= wine_device_memory_from_handle(unmap_info
->memory
);
1677 VkMemoryUnmapInfoKHR info
;
1679 if (memory
->mapping
)
1682 if (!device
->funcs
.p_vkUnmapMemory2KHR
)
1684 assert(!unmap_info
->pNext
);
1685 device
->funcs
.p_vkUnmapMemory(device
->device
, memory
->memory
);
1690 info
.memory
= memory
->memory
;
1691 return device
->funcs
.p_vkUnmapMemory2KHR(device
->device
, &info
);
1694 VkResult
wine_vkCreateBuffer(VkDevice handle
, const VkBufferCreateInfo
*create_info
,
1695 const VkAllocationCallbacks
*allocator
, VkBuffer
*buffer
)
1697 struct wine_device
*device
= wine_device_from_handle(handle
);
1698 VkExternalMemoryBufferCreateInfo external_memory_info
;
1699 VkBufferCreateInfo info
= *create_info
;
1701 if (device
->phys_dev
->external_memory_align
&&
1702 !find_next_struct(info
.pNext
, VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO
))
1704 external_memory_info
.sType
= VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO
;
1705 external_memory_info
.pNext
= info
.pNext
;
1706 external_memory_info
.handleTypes
= VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT
;
1707 info
.pNext
= &external_memory_info
;
1710 return device
->funcs
.p_vkCreateBuffer(device
->device
, &info
, NULL
, buffer
);
1713 VkResult
wine_vkCreateImage(VkDevice handle
, const VkImageCreateInfo
*create_info
,
1714 const VkAllocationCallbacks
*allocator
, VkImage
*image
)
1716 struct wine_device
*device
= wine_device_from_handle(handle
);
1717 VkExternalMemoryImageCreateInfo external_memory_info
;
1718 VkImageCreateInfo info
= *create_info
;
1720 if (device
->phys_dev
->external_memory_align
&&
1721 !find_next_struct(info
.pNext
, VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO
))
1723 external_memory_info
.sType
= VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO
;
1724 external_memory_info
.pNext
= info
.pNext
;
1725 external_memory_info
.handleTypes
= VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT
;
1726 info
.pNext
= &external_memory_info
;
1729 return device
->funcs
.p_vkCreateImage(device
->device
, &info
, NULL
, image
);
1732 static inline void adjust_max_image_count(struct wine_phys_dev
*phys_dev
, VkSurfaceCapabilitiesKHR
* capabilities
)
1734 /* Many Windows games, for example Strange Brigade, No Man's Sky, Path of Exile
1735 * and World War Z, do not expect that maxImageCount can be set to 0.
1736 * A value of 0 means that there is no limit on the number of images.
1737 * Nvidia reports 8 on Windows, AMD 16.
1738 * https://vulkan.gpuinfo.org/displayreport.php?id=9122#surface
1739 * https://vulkan.gpuinfo.org/displayreport.php?id=9121#surface
1741 if ((phys_dev
->instance
->quirks
& WINEVULKAN_QUIRK_ADJUST_MAX_IMAGE_COUNT
) && !capabilities
->maxImageCount
)
1743 capabilities
->maxImageCount
= max(capabilities
->minImageCount
, 16);
1747 VkResult
wine_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice handle
, VkSurfaceKHR surface_handle
,
1748 VkSurfaceCapabilitiesKHR
*capabilities
)
1750 struct wine_phys_dev
*phys_dev
= wine_phys_dev_from_handle(handle
);
1751 struct wine_surface
*surface
= wine_surface_from_handle(surface_handle
);
1754 res
= phys_dev
->instance
->funcs
.p_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(phys_dev
->phys_dev
,
1755 surface
->driver_surface
, capabilities
);
1757 if (res
== VK_SUCCESS
)
1758 adjust_max_image_count(phys_dev
, capabilities
);
1763 VkResult
wine_vkGetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice handle
,
1764 const VkPhysicalDeviceSurfaceInfo2KHR
*surface_info
,
1765 VkSurfaceCapabilities2KHR
*capabilities
)
1767 struct wine_phys_dev
*phys_dev
= wine_phys_dev_from_handle(handle
);
1768 struct wine_surface
*surface
= wine_surface_from_handle(surface_info
->surface
);
1769 VkPhysicalDeviceSurfaceInfo2KHR host_info
;
1772 host_info
.sType
= surface_info
->sType
;
1773 host_info
.pNext
= surface_info
->pNext
;
1774 host_info
.surface
= surface
->driver_surface
;
1775 res
= phys_dev
->instance
->funcs
.p_vkGetPhysicalDeviceSurfaceCapabilities2KHR(phys_dev
->phys_dev
,
1776 &host_info
, capabilities
);
1778 if (res
== VK_SUCCESS
)
1779 adjust_max_image_count(phys_dev
, &capabilities
->surfaceCapabilities
);
1784 VkResult
wine_vkCreateDebugUtilsMessengerEXT(VkInstance handle
,
1785 const VkDebugUtilsMessengerCreateInfoEXT
*create_info
,
1786 const VkAllocationCallbacks
*allocator
,
1787 VkDebugUtilsMessengerEXT
*messenger
)
1789 struct wine_instance
*instance
= wine_instance_from_handle(handle
);
1790 VkDebugUtilsMessengerCreateInfoEXT wine_create_info
;
1791 struct wine_debug_utils_messenger
*object
;
1795 FIXME("Support for allocation callbacks not implemented yet\n");
1797 if (!(object
= calloc(1, sizeof(*object
))))
1798 return VK_ERROR_OUT_OF_HOST_MEMORY
;
1800 object
->instance
= instance
;
1801 object
->user_callback
= create_info
->pfnUserCallback
;
1802 object
->user_data
= create_info
->pUserData
;
1804 wine_create_info
= *create_info
;
1806 wine_create_info
.pfnUserCallback
= (void *) &debug_utils_callback_conversion
;
1807 wine_create_info
.pUserData
= object
;
1809 res
= instance
->funcs
.p_vkCreateDebugUtilsMessengerEXT(instance
->instance
, &wine_create_info
, NULL
, &object
->debug_messenger
);
1811 if (res
!= VK_SUCCESS
)
1817 WINE_VK_ADD_NON_DISPATCHABLE_MAPPING(instance
, object
, object
->debug_messenger
, object
);
1818 *messenger
= wine_debug_utils_messenger_to_handle(object
);
1823 void wine_vkDestroyDebugUtilsMessengerEXT(VkInstance handle
, VkDebugUtilsMessengerEXT messenger
,
1824 const VkAllocationCallbacks
*allocator
)
1826 struct wine_instance
*instance
= wine_instance_from_handle(handle
);
1827 struct wine_debug_utils_messenger
*object
;
1829 object
= wine_debug_utils_messenger_from_handle(messenger
);
1834 instance
->funcs
.p_vkDestroyDebugUtilsMessengerEXT(instance
->instance
, object
->debug_messenger
, NULL
);
1835 WINE_VK_REMOVE_HANDLE_MAPPING(instance
, object
);
1840 VkResult
wine_vkCreateDebugReportCallbackEXT(VkInstance handle
,
1841 const VkDebugReportCallbackCreateInfoEXT
*create_info
,
1842 const VkAllocationCallbacks
*allocator
,
1843 VkDebugReportCallbackEXT
*callback
)
1845 struct wine_instance
*instance
= wine_instance_from_handle(handle
);
1846 VkDebugReportCallbackCreateInfoEXT wine_create_info
;
1847 struct wine_debug_report_callback
*object
;
1851 FIXME("Support for allocation callbacks not implemented yet\n");
1853 if (!(object
= calloc(1, sizeof(*object
))))
1854 return VK_ERROR_OUT_OF_HOST_MEMORY
;
1856 object
->instance
= instance
;
1857 object
->user_callback
= create_info
->pfnCallback
;
1858 object
->user_data
= create_info
->pUserData
;
1860 wine_create_info
= *create_info
;
1862 wine_create_info
.pfnCallback
= (void *) debug_report_callback_conversion
;
1863 wine_create_info
.pUserData
= object
;
1865 res
= instance
->funcs
.p_vkCreateDebugReportCallbackEXT(instance
->instance
, &wine_create_info
, NULL
, &object
->debug_callback
);
1867 if (res
!= VK_SUCCESS
)
1873 WINE_VK_ADD_NON_DISPATCHABLE_MAPPING(instance
, object
, object
->debug_callback
, object
);
1874 *callback
= wine_debug_report_callback_to_handle(object
);
1879 void wine_vkDestroyDebugReportCallbackEXT(VkInstance handle
, VkDebugReportCallbackEXT callback
,
1880 const VkAllocationCallbacks
*allocator
)
1882 struct wine_instance
*instance
= wine_instance_from_handle(handle
);
1883 struct wine_debug_report_callback
*object
;
1885 object
= wine_debug_report_callback_from_handle(callback
);
1890 instance
->funcs
.p_vkDestroyDebugReportCallbackEXT(instance
->instance
, object
->debug_callback
, NULL
);
1892 WINE_VK_REMOVE_HANDLE_MAPPING(instance
, object
);
1899 NTSTATUS
vk_is_available_instance_function(void *arg
)
1901 struct is_available_instance_function_params
*params
= arg
;
1902 struct wine_instance
*instance
= wine_instance_from_handle(params
->instance
);
1903 return !!vk_funcs
->p_vkGetInstanceProcAddr(instance
->instance
, params
->name
);
1906 NTSTATUS
vk_is_available_device_function(void *arg
)
1908 struct is_available_device_function_params
*params
= arg
;
1909 struct wine_device
*device
= wine_device_from_handle(params
->device
);
1910 return !!vk_funcs
->p_vkGetDeviceProcAddr(device
->device
, params
->name
);
1915 NTSTATUS
vk_is_available_instance_function32(void *arg
)
1922 struct wine_instance
*instance
= wine_instance_from_handle(UlongToPtr(params
->instance
));
1923 return !!vk_funcs
->p_vkGetInstanceProcAddr(instance
->instance
, UlongToPtr(params
->name
));
1926 NTSTATUS
vk_is_available_device_function32(void *arg
)
1933 struct wine_device
*device
= wine_device_from_handle(UlongToPtr(params
->device
));
1934 return !!vk_funcs
->p_vkGetDeviceProcAddr(device
->device
, UlongToPtr(params
->name
));