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
= 0;
46 #define wine_vk_count_struct(s, t) wine_vk_count_struct_((void *)s, VK_STRUCTURE_TYPE_##t)
47 static uint32_t wine_vk_count_struct_(void *s
, VkStructureType t
)
49 const VkBaseInStructure
*header
;
52 for (header
= s
; header
; header
= header
->pNext
)
54 if (header
->sType
== t
)
61 static const struct vulkan_funcs
*vk_funcs
;
63 #define WINE_VK_ADD_DISPATCHABLE_MAPPING(instance, client_handle, native_handle, object) \
64 wine_vk_add_handle_mapping((instance), (uintptr_t)(client_handle), (uintptr_t)(native_handle), &(object)->mapping)
65 #define WINE_VK_ADD_NON_DISPATCHABLE_MAPPING(instance, client_handle, native_handle, object) \
66 wine_vk_add_handle_mapping((instance), (uintptr_t)(client_handle), (native_handle), &(object)->mapping)
67 static void wine_vk_add_handle_mapping(struct wine_instance
*instance
, uint64_t wrapped_handle
,
68 uint64_t native_handle
, struct wine_vk_mapping
*mapping
)
70 if (instance
->enable_wrapper_list
)
72 mapping
->native_handle
= native_handle
;
73 mapping
->wine_wrapped_handle
= wrapped_handle
;
74 pthread_rwlock_wrlock(&instance
->wrapper_lock
);
75 list_add_tail(&instance
->wrappers
, &mapping
->link
);
76 pthread_rwlock_unlock(&instance
->wrapper_lock
);
80 #define WINE_VK_REMOVE_HANDLE_MAPPING(instance, object) \
81 wine_vk_remove_handle_mapping((instance), &(object)->mapping)
82 static void wine_vk_remove_handle_mapping(struct wine_instance
*instance
, struct wine_vk_mapping
*mapping
)
84 if (instance
->enable_wrapper_list
)
86 pthread_rwlock_wrlock(&instance
->wrapper_lock
);
87 list_remove(&mapping
->link
);
88 pthread_rwlock_unlock(&instance
->wrapper_lock
);
92 static uint64_t wine_vk_get_wrapper(struct wine_instance
*instance
, uint64_t native_handle
)
94 struct wine_vk_mapping
*mapping
;
97 pthread_rwlock_rdlock(&instance
->wrapper_lock
);
98 LIST_FOR_EACH_ENTRY(mapping
, &instance
->wrappers
, struct wine_vk_mapping
, link
)
100 if (mapping
->native_handle
== native_handle
)
102 result
= mapping
->wine_wrapped_handle
;
106 pthread_rwlock_unlock(&instance
->wrapper_lock
);
110 static VkBool32
debug_utils_callback_conversion(VkDebugUtilsMessageSeverityFlagBitsEXT severity
,
111 VkDebugUtilsMessageTypeFlagsEXT message_types
,
112 const VkDebugUtilsMessengerCallbackDataEXT
*callback_data
,
115 struct wine_vk_debug_utils_params params
;
116 VkDebugUtilsObjectNameInfoEXT
*object_name_infos
;
117 struct wine_debug_utils_messenger
*object
;
123 TRACE("%i, %u, %p, %p\n", severity
, message_types
, callback_data
, user_data
);
127 if (!object
->instance
->instance
)
129 /* instance wasn't yet created, this is a message from the native loader */
133 /* FIXME: we should pack all referenced structs instead of passing pointers */
134 params
.user_callback
= object
->user_callback
;
135 params
.user_data
= object
->user_data
;
136 params
.severity
= severity
;
137 params
.message_types
= message_types
;
138 params
.data
= *((VkDebugUtilsMessengerCallbackDataEXT
*) callback_data
);
140 object_name_infos
= calloc(params
.data
.objectCount
, sizeof(*object_name_infos
));
142 for (i
= 0; i
< params
.data
.objectCount
; i
++)
144 object_name_infos
[i
].sType
= callback_data
->pObjects
[i
].sType
;
145 object_name_infos
[i
].pNext
= callback_data
->pObjects
[i
].pNext
;
146 object_name_infos
[i
].objectType
= callback_data
->pObjects
[i
].objectType
;
147 object_name_infos
[i
].pObjectName
= callback_data
->pObjects
[i
].pObjectName
;
149 if (wine_vk_is_type_wrapped(callback_data
->pObjects
[i
].objectType
))
151 object_name_infos
[i
].objectHandle
= wine_vk_get_wrapper(object
->instance
, callback_data
->pObjects
[i
].objectHandle
);
152 if (!object_name_infos
[i
].objectHandle
)
154 WARN("handle conversion failed 0x%s\n", wine_dbgstr_longlong(callback_data
->pObjects
[i
].objectHandle
));
155 free(object_name_infos
);
161 object_name_infos
[i
].objectHandle
= callback_data
->pObjects
[i
].objectHandle
;
165 params
.data
.pObjects
= object_name_infos
;
167 /* applications should always return VK_FALSE */
168 result
= KeUserModeCallback( NtUserCallVulkanDebugUtilsCallback
, ¶ms
, sizeof(params
),
169 &ret_ptr
, &ret_len
);
171 free(object_name_infos
);
176 static VkBool32
debug_report_callback_conversion(VkDebugReportFlagsEXT flags
, VkDebugReportObjectTypeEXT object_type
,
177 uint64_t object_handle
, size_t location
, int32_t code
, const char *layer_prefix
, const char *message
, void *user_data
)
179 struct wine_vk_debug_report_params params
;
180 struct wine_debug_report_callback
*object
;
184 TRACE("%#x, %#x, 0x%s, 0x%s, %d, %p, %p, %p\n", flags
, object_type
, wine_dbgstr_longlong(object_handle
),
185 wine_dbgstr_longlong(location
), code
, layer_prefix
, message
, user_data
);
189 if (!object
->instance
->instance
)
191 /* instance wasn't yet created, this is a message from the native loader */
195 /* FIXME: we should pack all referenced structs instead of passing pointers */
196 params
.user_callback
= object
->user_callback
;
197 params
.user_data
= object
->user_data
;
198 params
.flags
= flags
;
199 params
.object_type
= object_type
;
200 params
.location
= location
;
202 params
.layer_prefix
= layer_prefix
;
203 params
.message
= message
;
205 params
.object_handle
= wine_vk_get_wrapper(object
->instance
, object_handle
);
206 if (!params
.object_handle
)
207 params
.object_type
= VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT
;
209 return KeUserModeCallback( NtUserCallVulkanDebugReportCallback
, ¶ms
, sizeof(params
),
210 &ret_ptr
, &ret_len
);
213 static void wine_vk_physical_device_free(struct wine_phys_dev
*phys_dev
)
218 WINE_VK_REMOVE_HANDLE_MAPPING(phys_dev
->instance
, phys_dev
);
219 free(phys_dev
->extensions
);
223 static struct wine_phys_dev
*wine_vk_physical_device_alloc(struct wine_instance
*instance
,
224 VkPhysicalDevice phys_dev
, VkPhysicalDevice handle
)
226 struct wine_phys_dev
*object
;
227 uint32_t num_host_properties
, num_properties
= 0;
228 VkExtensionProperties
*host_properties
= NULL
;
229 BOOL have_external_memory_host
= FALSE
;
233 if (!(object
= calloc(1, sizeof(*object
))))
236 object
->instance
= instance
;
237 object
->handle
= handle
;
238 object
->phys_dev
= phys_dev
;
240 handle
->base
.unix_handle
= (uintptr_t)object
;
241 WINE_VK_ADD_DISPATCHABLE_MAPPING(instance
, handle
, phys_dev
, object
);
243 instance
->funcs
.p_vkGetPhysicalDeviceMemoryProperties(phys_dev
, &object
->memory_properties
);
245 res
= instance
->funcs
.p_vkEnumerateDeviceExtensionProperties(phys_dev
,
246 NULL
, &num_host_properties
, NULL
);
247 if (res
!= VK_SUCCESS
)
249 ERR("Failed to enumerate device extensions, res=%d\n", res
);
253 host_properties
= calloc(num_host_properties
, sizeof(*host_properties
));
254 if (!host_properties
)
256 ERR("Failed to allocate memory for device properties!\n");
260 res
= instance
->funcs
.p_vkEnumerateDeviceExtensionProperties(phys_dev
,
261 NULL
, &num_host_properties
, host_properties
);
262 if (res
!= VK_SUCCESS
)
264 ERR("Failed to enumerate device extensions, res=%d\n", res
);
268 /* Count list of extensions for which we have an implementation.
269 * TODO: perform translation for platform specific extensions.
271 for (i
= 0; i
< num_host_properties
; i
++)
273 if (wine_vk_device_extension_supported(host_properties
[i
].extensionName
))
275 TRACE("Enabling extension '%s' for physical device %p\n", host_properties
[i
].extensionName
, object
);
280 TRACE("Skipping extension '%s', no implementation found in winevulkan.\n", host_properties
[i
].extensionName
);
282 if (!strcmp(host_properties
[i
].extensionName
, "VK_EXT_external_memory_host"))
283 have_external_memory_host
= TRUE
;
286 TRACE("Host supported extensions %u, Wine supported extensions %u\n", num_host_properties
, num_properties
);
288 if (!(object
->extensions
= calloc(num_properties
, sizeof(*object
->extensions
))))
290 ERR("Failed to allocate memory for device extensions!\n");
294 for (i
= 0, j
= 0; i
< num_host_properties
; i
++)
296 if (wine_vk_device_extension_supported(host_properties
[i
].extensionName
))
298 object
->extensions
[j
] = host_properties
[i
];
302 object
->extension_count
= num_properties
;
304 if (use_external_memory() && have_external_memory_host
)
306 VkPhysicalDeviceExternalMemoryHostPropertiesEXT host_mem_props
=
308 .sType
= VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT
,
310 VkPhysicalDeviceProperties2 props
=
312 .sType
= VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2
,
313 .pNext
= &host_mem_props
,
315 instance
->funcs
.p_vkGetPhysicalDeviceProperties2KHR(phys_dev
, &props
);
316 object
->external_memory_align
= host_mem_props
.minImportedHostPointerAlignment
;
317 if (object
->external_memory_align
)
318 TRACE("Using VK_EXT_external_memory_host for memory mapping with alignment: %u\n",
319 object
->external_memory_align
);
322 free(host_properties
);
326 wine_vk_physical_device_free(object
);
327 free(host_properties
);
331 static void wine_vk_free_command_buffers(struct wine_device
*device
,
332 struct wine_cmd_pool
*pool
, uint32_t count
, const VkCommandBuffer
*buffers
)
336 for (i
= 0; i
< count
; i
++)
338 struct wine_cmd_buffer
*buffer
= wine_cmd_buffer_from_handle(buffers
[i
]);
343 device
->funcs
.p_vkFreeCommandBuffers(device
->device
, pool
->command_pool
, 1, &buffer
->command_buffer
);
344 WINE_VK_REMOVE_HANDLE_MAPPING(device
->phys_dev
->instance
, buffer
);
345 buffer
->handle
->base
.unix_handle
= 0;
350 static void wine_vk_device_get_queues(struct wine_device
*device
,
351 uint32_t family_index
, uint32_t queue_count
, VkDeviceQueueCreateFlags flags
,
352 struct wine_queue
*queues
, VkQueue
*handles
)
354 VkDeviceQueueInfo2 queue_info
;
357 for (i
= 0; i
< queue_count
; i
++)
359 struct wine_queue
*queue
= &queues
[i
];
361 queue
->device
= device
;
362 queue
->handle
= (*handles
)++;
363 queue
->family_index
= family_index
;
364 queue
->queue_index
= i
;
365 queue
->flags
= flags
;
367 /* The Vulkan spec says:
369 * "vkGetDeviceQueue must only be used to get queues that were created
370 * with the flags parameter of VkDeviceQueueCreateInfo set to zero."
372 if (flags
&& device
->funcs
.p_vkGetDeviceQueue2
)
374 queue_info
.sType
= VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2
;
375 queue_info
.pNext
= NULL
;
376 queue_info
.flags
= flags
;
377 queue_info
.queueFamilyIndex
= family_index
;
378 queue_info
.queueIndex
= i
;
379 device
->funcs
.p_vkGetDeviceQueue2(device
->device
, &queue_info
, &queue
->queue
);
383 device
->funcs
.p_vkGetDeviceQueue(device
->device
, family_index
, i
, &queue
->queue
);
386 queue
->handle
->base
.unix_handle
= (uintptr_t)queue
;
387 WINE_VK_ADD_DISPATCHABLE_MAPPING(device
->phys_dev
->instance
, queue
->handle
, queue
->queue
, queue
);
391 static VkResult
wine_vk_device_convert_create_info(struct wine_phys_dev
*phys_dev
,
392 struct conversion_context
*ctx
, const VkDeviceCreateInfo
*src
, VkDeviceCreateInfo
*dst
)
398 /* Should be filtered out by loader as ICDs don't support layers. */
399 dst
->enabledLayerCount
= 0;
400 dst
->ppEnabledLayerNames
= NULL
;
402 TRACE("Enabled %u extensions.\n", dst
->enabledExtensionCount
);
403 for (i
= 0; i
< dst
->enabledExtensionCount
; i
++)
405 const char *extension_name
= dst
->ppEnabledExtensionNames
[i
];
406 TRACE("Extension %u: %s.\n", i
, debugstr_a(extension_name
));
407 if (!wine_vk_device_extension_supported(extension_name
))
409 WARN("Extension %s is not supported.\n", debugstr_a(extension_name
));
410 return VK_ERROR_EXTENSION_NOT_PRESENT
;
414 if (phys_dev
->external_memory_align
)
416 const char **new_extensions
;
418 new_extensions
= conversion_context_alloc(ctx
, (dst
->enabledExtensionCount
+ 2) *
419 sizeof(*dst
->ppEnabledExtensionNames
));
420 memcpy(new_extensions
, src
->ppEnabledExtensionNames
,
421 dst
->enabledExtensionCount
* sizeof(*dst
->ppEnabledExtensionNames
));
422 new_extensions
[dst
->enabledExtensionCount
++] = "VK_KHR_external_memory";
423 new_extensions
[dst
->enabledExtensionCount
++] = "VK_EXT_external_memory_host";
424 dst
->ppEnabledExtensionNames
= new_extensions
;
430 /* Helper function used for freeing a device structure. This function supports full
431 * and partial object cleanups and can thus be used for vkCreateDevice failures.
433 static void wine_vk_device_free(struct wine_device
*device
)
435 struct wine_queue
*queue
;
443 for (i
= 0; i
< device
->queue_count
; i
++)
445 queue
= &device
->queues
[i
];
446 if (queue
&& queue
->queue
)
447 WINE_VK_REMOVE_HANDLE_MAPPING(device
->phys_dev
->instance
, queue
);
449 free(device
->queues
);
450 device
->queues
= NULL
;
453 if (device
->device
&& device
->funcs
.p_vkDestroyDevice
)
455 WINE_VK_REMOVE_HANDLE_MAPPING(device
->phys_dev
->instance
, device
);
456 device
->funcs
.p_vkDestroyDevice(device
->device
, NULL
/* pAllocator */);
462 NTSTATUS
init_vulkan(void *args
)
464 vk_funcs
= __wine_get_vulkan_driver(WINE_VULKAN_DRIVER_VERSION
);
467 ERR("Failed to load Wine graphics driver supporting Vulkan.\n");
468 return STATUS_UNSUCCESSFUL
;
473 SYSTEM_BASIC_INFORMATION info
;
475 NtQuerySystemInformation(SystemEmulationBasicInformation
, &info
, sizeof(info
), NULL
);
476 zero_bits
= (ULONG_PTR
)info
.HighestUserAddress
| 0x7fffffff;
479 return STATUS_SUCCESS
;
482 /* Helper function for converting between win32 and host compatible VkInstanceCreateInfo.
483 * This function takes care of extensions handled at winevulkan layer, a Wine graphics
484 * driver is responsible for handling e.g. surface extensions.
486 static VkResult
wine_vk_instance_convert_create_info(struct conversion_context
*ctx
,
487 const VkInstanceCreateInfo
*src
, VkInstanceCreateInfo
*dst
, struct wine_instance
*object
)
489 VkDebugUtilsMessengerCreateInfoEXT
*debug_utils_messenger
;
490 VkDebugReportCallbackCreateInfoEXT
*debug_report_callback
;
491 VkBaseInStructure
*header
;
496 object
->utils_messenger_count
= wine_vk_count_struct(dst
, DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT
);
497 object
->utils_messengers
= calloc(object
->utils_messenger_count
, sizeof(*object
->utils_messengers
));
498 header
= (VkBaseInStructure
*) dst
;
499 for (i
= 0; i
< object
->utils_messenger_count
; i
++)
501 header
= find_next_struct(header
->pNext
, VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT
);
502 debug_utils_messenger
= (VkDebugUtilsMessengerCreateInfoEXT
*) header
;
504 object
->utils_messengers
[i
].instance
= object
;
505 object
->utils_messengers
[i
].debug_messenger
= VK_NULL_HANDLE
;
506 object
->utils_messengers
[i
].user_callback
= debug_utils_messenger
->pfnUserCallback
;
507 object
->utils_messengers
[i
].user_data
= debug_utils_messenger
->pUserData
;
509 /* convert_VkInstanceCreateInfo_* already copied the chain, so we can modify it in-place. */
510 debug_utils_messenger
->pfnUserCallback
= (void *) &debug_utils_callback_conversion
;
511 debug_utils_messenger
->pUserData
= &object
->utils_messengers
[i
];
514 debug_report_callback
= find_next_struct(header
->pNext
,
515 VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT
);
516 if (debug_report_callback
)
518 object
->default_callback
.instance
= object
;
519 object
->default_callback
.debug_callback
= VK_NULL_HANDLE
;
520 object
->default_callback
.user_callback
= debug_report_callback
->pfnCallback
;
521 object
->default_callback
.user_data
= debug_report_callback
->pUserData
;
523 debug_report_callback
->pfnCallback
= (void *) &debug_report_callback_conversion
;
524 debug_report_callback
->pUserData
= &object
->default_callback
;
527 /* ICDs don't support any layers, so nothing to copy. Modern versions of the loader
528 * filter this data out as well.
530 if (object
->quirks
& WINEVULKAN_QUIRK_IGNORE_EXPLICIT_LAYERS
) {
531 dst
->enabledLayerCount
= 0;
532 dst
->ppEnabledLayerNames
= NULL
;
533 WARN("Ignoring explicit layers!\n");
534 } else if (dst
->enabledLayerCount
) {
535 FIXME("Loading explicit layers is not supported by winevulkan!\n");
536 return VK_ERROR_LAYER_NOT_PRESENT
;
539 TRACE("Enabled %u instance extensions.\n", dst
->enabledExtensionCount
);
540 for (i
= 0; i
< dst
->enabledExtensionCount
; i
++)
542 const char *extension_name
= dst
->ppEnabledExtensionNames
[i
];
543 TRACE("Extension %u: %s.\n", i
, debugstr_a(extension_name
));
544 if (!wine_vk_instance_extension_supported(extension_name
))
546 WARN("Extension %s is not supported.\n", debugstr_a(extension_name
));
547 return VK_ERROR_EXTENSION_NOT_PRESENT
;
549 if (!strcmp(extension_name
, "VK_EXT_debug_utils") || !strcmp(extension_name
, "VK_EXT_debug_report"))
551 object
->enable_wrapper_list
= VK_TRUE
;
555 if (use_external_memory())
557 const char **new_extensions
;
559 new_extensions
= conversion_context_alloc(ctx
, (dst
->enabledExtensionCount
+ 2) *
560 sizeof(*dst
->ppEnabledExtensionNames
));
561 memcpy(new_extensions
, src
->ppEnabledExtensionNames
,
562 dst
->enabledExtensionCount
* sizeof(*dst
->ppEnabledExtensionNames
));
563 new_extensions
[dst
->enabledExtensionCount
++] = "VK_KHR_get_physical_device_properties2";
564 new_extensions
[dst
->enabledExtensionCount
++] = "VK_KHR_external_memory_capabilities";
565 dst
->ppEnabledExtensionNames
= new_extensions
;
571 /* Helper function which stores wrapped physical devices in the instance object. */
572 static VkResult
wine_vk_instance_load_physical_devices(struct wine_instance
*instance
)
574 VkPhysicalDevice
*tmp_phys_devs
;
575 uint32_t phys_dev_count
;
579 res
= instance
->funcs
.p_vkEnumeratePhysicalDevices(instance
->instance
, &phys_dev_count
, NULL
);
580 if (res
!= VK_SUCCESS
)
582 ERR("Failed to enumerate physical devices, res=%d\n", res
);
588 if (phys_dev_count
> instance
->handle
->phys_dev_count
)
590 instance
->handle
->phys_dev_count
= phys_dev_count
;
591 return VK_ERROR_OUT_OF_POOL_MEMORY
;
593 instance
->handle
->phys_dev_count
= phys_dev_count
;
595 if (!(tmp_phys_devs
= calloc(phys_dev_count
, sizeof(*tmp_phys_devs
))))
596 return VK_ERROR_OUT_OF_HOST_MEMORY
;
598 res
= instance
->funcs
.p_vkEnumeratePhysicalDevices(instance
->instance
, &phys_dev_count
, tmp_phys_devs
);
599 if (res
!= VK_SUCCESS
)
605 instance
->phys_devs
= calloc(phys_dev_count
, sizeof(*instance
->phys_devs
));
606 if (!instance
->phys_devs
)
609 return VK_ERROR_OUT_OF_HOST_MEMORY
;
612 /* Wrap each native physical device handle into a dispatchable object for the ICD loader. */
613 for (i
= 0; i
< phys_dev_count
; i
++)
615 struct wine_phys_dev
*phys_dev
= wine_vk_physical_device_alloc(instance
, tmp_phys_devs
[i
],
616 &instance
->handle
->phys_devs
[i
]);
619 ERR("Unable to allocate memory for physical device!\n");
621 return VK_ERROR_OUT_OF_HOST_MEMORY
;
624 instance
->phys_devs
[i
] = phys_dev
;
625 instance
->phys_dev_count
= i
+ 1;
627 instance
->phys_dev_count
= phys_dev_count
;
633 static struct wine_phys_dev
*wine_vk_instance_wrap_physical_device(struct wine_instance
*instance
,
634 VkPhysicalDevice physical_device
)
638 for (i
= 0; i
< instance
->phys_dev_count
; ++i
)
640 struct wine_phys_dev
*current
= instance
->phys_devs
[i
];
641 if (current
->phys_dev
== physical_device
)
645 ERR("Unrecognized physical device %p.\n", physical_device
);
649 /* Helper function used for freeing an instance structure. This function supports full
650 * and partial object cleanups and can thus be used for vkCreateInstance failures.
652 static void wine_vk_instance_free(struct wine_instance
*instance
)
657 if (instance
->phys_devs
)
661 for (i
= 0; i
< instance
->phys_dev_count
; i
++)
663 wine_vk_physical_device_free(instance
->phys_devs
[i
]);
665 free(instance
->phys_devs
);
668 if (instance
->instance
)
670 vk_funcs
->p_vkDestroyInstance(instance
->instance
, NULL
/* allocator */);
671 WINE_VK_REMOVE_HANDLE_MAPPING(instance
, instance
);
674 pthread_rwlock_destroy(&instance
->wrapper_lock
);
675 free(instance
->utils_messengers
);
680 VkResult
wine_vkAllocateCommandBuffers(VkDevice handle
, const VkCommandBufferAllocateInfo
*allocate_info
,
681 VkCommandBuffer
*buffers
)
683 struct wine_device
*device
= wine_device_from_handle(handle
);
684 struct wine_cmd_buffer
*buffer
;
685 struct wine_cmd_pool
*pool
;
686 VkResult res
= VK_SUCCESS
;
689 pool
= wine_cmd_pool_from_handle(allocate_info
->commandPool
);
691 for (i
= 0; i
< allocate_info
->commandBufferCount
; i
++)
693 VkCommandBufferAllocateInfo allocate_info_host
;
695 /* TODO: future extensions (none yet) may require pNext conversion. */
696 allocate_info_host
.pNext
= allocate_info
->pNext
;
697 allocate_info_host
.sType
= allocate_info
->sType
;
698 allocate_info_host
.commandPool
= pool
->command_pool
;
699 allocate_info_host
.level
= allocate_info
->level
;
700 allocate_info_host
.commandBufferCount
= 1;
702 TRACE("Allocating command buffer %u from pool 0x%s.\n",
703 i
, wine_dbgstr_longlong(allocate_info_host
.commandPool
));
705 if (!(buffer
= calloc(1, sizeof(*buffer
))))
707 res
= VK_ERROR_OUT_OF_HOST_MEMORY
;
711 buffer
->handle
= buffers
[i
];
712 buffer
->device
= device
;
713 res
= device
->funcs
.p_vkAllocateCommandBuffers(device
->device
,
714 &allocate_info_host
, &buffer
->command_buffer
);
715 buffer
->handle
->base
.unix_handle
= (uintptr_t)buffer
;
716 WINE_VK_ADD_DISPATCHABLE_MAPPING(device
->phys_dev
->instance
, buffer
->handle
,
717 buffer
->command_buffer
, buffer
);
718 if (res
!= VK_SUCCESS
)
720 ERR("Failed to allocate command buffer, res=%d.\n", res
);
721 buffer
->command_buffer
= VK_NULL_HANDLE
;
726 if (res
!= VK_SUCCESS
)
727 wine_vk_free_command_buffers(device
, pool
, i
+ 1, buffers
);
732 VkResult
wine_vkCreateDevice(VkPhysicalDevice phys_dev_handle
, const VkDeviceCreateInfo
*create_info
,
733 const VkAllocationCallbacks
*allocator
, VkDevice
*ret_device
,
736 struct wine_phys_dev
*phys_dev
= wine_phys_dev_from_handle(phys_dev_handle
);
737 VkDevice device_handle
= client_ptr
;
738 VkDeviceCreateInfo create_info_host
;
739 struct VkQueue_T
*queue_handles
;
740 struct wine_queue
*next_queue
;
741 struct conversion_context ctx
;
742 struct wine_device
*object
;
747 FIXME("Support for allocation callbacks not implemented yet\n");
749 if (TRACE_ON(vulkan
))
751 VkPhysicalDeviceProperties properties
;
753 phys_dev
->instance
->funcs
.p_vkGetPhysicalDeviceProperties(phys_dev
->phys_dev
, &properties
);
755 TRACE("Device name: %s.\n", debugstr_a(properties
.deviceName
));
756 TRACE("Vendor ID: %#x, Device ID: %#x.\n", properties
.vendorID
, properties
.deviceID
);
757 TRACE("Driver version: %#x.\n", properties
.driverVersion
);
760 if (!(object
= calloc(1, sizeof(*object
))))
761 return VK_ERROR_OUT_OF_HOST_MEMORY
;
763 object
->phys_dev
= phys_dev
;
765 init_conversion_context(&ctx
);
766 res
= wine_vk_device_convert_create_info(phys_dev
, &ctx
, create_info
, &create_info_host
);
767 if (res
== VK_SUCCESS
)
768 res
= phys_dev
->instance
->funcs
.p_vkCreateDevice(phys_dev
->phys_dev
,
769 &create_info_host
, NULL
/* allocator */, &object
->device
);
770 free_conversion_context(&ctx
);
771 WINE_VK_ADD_DISPATCHABLE_MAPPING(phys_dev
->instance
, device_handle
, object
->device
, object
);
772 if (res
!= VK_SUCCESS
)
774 WARN("Failed to create device, res=%d.\n", res
);
778 /* Just load all function pointers we are aware off. The loader takes care of filtering.
779 * We use vkGetDeviceProcAddr as opposed to vkGetInstanceProcAddr for efficiency reasons
780 * as functions pass through fewer dispatch tables within the loader.
782 #define USE_VK_FUNC(name) \
783 object->funcs.p_##name = (void *)vk_funcs->p_vkGetDeviceProcAddr(object->device, #name); \
784 if (object->funcs.p_##name == NULL) \
785 TRACE("Not found '%s'.\n", #name);
786 ALL_VK_DEVICE_FUNCS()
789 /* We need to cache all queues within the device as each requires wrapping since queues are
790 * dispatchable objects.
792 for (i
= 0; i
< create_info_host
.queueCreateInfoCount
; i
++)
794 object
->queue_count
+= create_info_host
.pQueueCreateInfos
[i
].queueCount
;
797 if (!(object
->queues
= calloc(object
->queue_count
, sizeof(*object
->queues
))))
799 res
= VK_ERROR_OUT_OF_HOST_MEMORY
;
803 next_queue
= object
->queues
;
804 queue_handles
= device_handle
->queues
;
805 for (i
= 0; i
< create_info_host
.queueCreateInfoCount
; i
++)
807 uint32_t flags
= create_info_host
.pQueueCreateInfos
[i
].flags
;
808 uint32_t family_index
= create_info_host
.pQueueCreateInfos
[i
].queueFamilyIndex
;
809 uint32_t queue_count
= create_info_host
.pQueueCreateInfos
[i
].queueCount
;
811 TRACE("Queue family index %u, queue count %u.\n", family_index
, queue_count
);
813 wine_vk_device_get_queues(object
, family_index
, queue_count
, flags
, next_queue
, &queue_handles
);
814 next_queue
+= queue_count
;
817 device_handle
->quirks
= phys_dev
->instance
->quirks
;
818 device_handle
->base
.unix_handle
= (uintptr_t)object
;
819 *ret_device
= device_handle
;
820 TRACE("Created device %p (native device %p).\n", object
, object
->device
);
824 wine_vk_device_free(object
);
828 VkResult
wine_vkCreateInstance(const VkInstanceCreateInfo
*create_info
,
829 const VkAllocationCallbacks
*allocator
, VkInstance
*instance
,
832 VkInstance client_instance
= client_ptr
;
833 VkInstanceCreateInfo create_info_host
;
834 const VkApplicationInfo
*app_info
;
835 struct conversion_context ctx
;
836 struct wine_instance
*object
;
840 FIXME("Support for allocation callbacks not implemented yet\n");
842 if (!(object
= calloc(1, sizeof(*object
))))
844 ERR("Failed to allocate memory for instance\n");
845 return VK_ERROR_OUT_OF_HOST_MEMORY
;
847 list_init(&object
->wrappers
);
848 pthread_rwlock_init(&object
->wrapper_lock
, NULL
);
850 init_conversion_context(&ctx
);
851 res
= wine_vk_instance_convert_create_info(&ctx
, create_info
, &create_info_host
, object
);
852 if (res
== VK_SUCCESS
)
853 res
= vk_funcs
->p_vkCreateInstance(&create_info_host
, NULL
/* allocator */, &object
->instance
);
854 free_conversion_context(&ctx
);
855 if (res
!= VK_SUCCESS
)
857 ERR("Failed to create instance, res=%d\n", res
);
858 wine_vk_instance_free(object
);
862 object
->handle
= client_instance
;
863 WINE_VK_ADD_DISPATCHABLE_MAPPING(object
, object
->handle
, object
->instance
, object
);
865 /* Load all instance functions we are aware of. Note the loader takes care
866 * of any filtering for extensions which were not requested, but which the
869 #define USE_VK_FUNC(name) \
870 object->funcs.p_##name = (void *)vk_funcs->p_vkGetInstanceProcAddr(object->instance, #name);
871 ALL_VK_INSTANCE_FUNCS()
874 /* Cache physical devices for vkEnumeratePhysicalDevices within the instance as
875 * each vkPhysicalDevice is a dispatchable object, which means we need to wrap
876 * the native physical devices and present those to the application.
877 * Cleanup happens as part of wine_vkDestroyInstance.
879 res
= wine_vk_instance_load_physical_devices(object
);
880 if (res
!= VK_SUCCESS
)
882 ERR("Failed to load physical devices, res=%d\n", res
);
883 wine_vk_instance_free(object
);
887 if ((app_info
= create_info
->pApplicationInfo
))
889 TRACE("Application name %s, application version %#x.\n",
890 debugstr_a(app_info
->pApplicationName
), app_info
->applicationVersion
);
891 TRACE("Engine name %s, engine version %#x.\n", debugstr_a(app_info
->pEngineName
),
892 app_info
->engineVersion
);
893 TRACE("API version %#x.\n", app_info
->apiVersion
);
895 if (app_info
->pEngineName
&& !strcmp(app_info
->pEngineName
, "idTech"))
896 object
->quirks
|= WINEVULKAN_QUIRK_GET_DEVICE_PROC_ADDR
;
899 object
->quirks
|= WINEVULKAN_QUIRK_ADJUST_MAX_IMAGE_COUNT
;
901 client_instance
->base
.unix_handle
= (uintptr_t)object
;
902 *instance
= client_instance
;
903 TRACE("Created instance %p (native instance %p).\n", object
, object
->instance
);
907 void wine_vkDestroyDevice(VkDevice handle
, const VkAllocationCallbacks
*allocator
)
909 struct wine_device
*device
= wine_device_from_handle(handle
);
912 FIXME("Support for allocation callbacks not implemented yet\n");
914 wine_vk_device_free(device
);
917 void wine_vkDestroyInstance(VkInstance handle
, const VkAllocationCallbacks
*allocator
)
919 struct wine_instance
*instance
= wine_instance_from_handle(handle
);
922 FIXME("Support allocation allocators\n");
924 wine_vk_instance_free(instance
);
927 VkResult
wine_vkEnumerateDeviceExtensionProperties(VkPhysicalDevice phys_dev_handle
, const char *layer_name
,
928 uint32_t *count
, VkExtensionProperties
*properties
)
930 struct wine_phys_dev
*phys_dev
= wine_phys_dev_from_handle(phys_dev_handle
);
932 /* This shouldn't get called with layer_name set, the ICD loader prevents it. */
935 ERR("Layer enumeration not supported from ICD.\n");
936 return VK_ERROR_LAYER_NOT_PRESENT
;
941 *count
= phys_dev
->extension_count
;
945 *count
= min(*count
, phys_dev
->extension_count
);
946 memcpy(properties
, phys_dev
->extensions
, *count
* sizeof(*properties
));
948 TRACE("Returning %u extensions.\n", *count
);
949 return *count
< phys_dev
->extension_count
? VK_INCOMPLETE
: VK_SUCCESS
;
952 VkResult
wine_vkEnumerateInstanceExtensionProperties(const char *name
, uint32_t *count
,
953 VkExtensionProperties
*properties
)
955 uint32_t num_properties
= 0, num_host_properties
;
956 VkExtensionProperties
*host_properties
;
960 res
= vk_funcs
->p_vkEnumerateInstanceExtensionProperties(NULL
, &num_host_properties
, NULL
);
961 if (res
!= VK_SUCCESS
)
964 if (!(host_properties
= calloc(num_host_properties
, sizeof(*host_properties
))))
965 return VK_ERROR_OUT_OF_HOST_MEMORY
;
967 res
= vk_funcs
->p_vkEnumerateInstanceExtensionProperties(NULL
, &num_host_properties
, host_properties
);
968 if (res
!= VK_SUCCESS
)
970 ERR("Failed to retrieve host properties, res=%d.\n", res
);
971 free(host_properties
);
975 /* The Wine graphics driver provides us with all extensions supported by the host side
976 * including extension fixup (e.g. VK_KHR_xlib_surface -> VK_KHR_win32_surface). It is
977 * up to us here to filter the list down to extensions for which we have thunks.
979 for (i
= 0; i
< num_host_properties
; i
++)
981 if (wine_vk_instance_extension_supported(host_properties
[i
].extensionName
))
984 TRACE("Instance extension '%s' is not supported.\n", host_properties
[i
].extensionName
);
989 TRACE("Returning %u extensions.\n", num_properties
);
990 *count
= num_properties
;
991 free(host_properties
);
995 for (i
= 0, j
= 0; i
< num_host_properties
&& j
< *count
; i
++)
997 if (wine_vk_instance_extension_supported(host_properties
[i
].extensionName
))
999 TRACE("Enabling extension '%s'.\n", host_properties
[i
].extensionName
);
1000 properties
[j
++] = host_properties
[i
];
1003 *count
= min(*count
, num_properties
);
1005 free(host_properties
);
1006 return *count
< num_properties
? VK_INCOMPLETE
: VK_SUCCESS
;
1009 VkResult
wine_vkEnumerateDeviceLayerProperties(VkPhysicalDevice phys_dev
, uint32_t *count
,
1010 VkLayerProperties
*properties
)
1016 VkResult
wine_vkEnumerateInstanceVersion(uint32_t *version
)
1020 static VkResult (*p_vkEnumerateInstanceVersion
)(uint32_t *version
);
1021 if (!p_vkEnumerateInstanceVersion
)
1022 p_vkEnumerateInstanceVersion
= vk_funcs
->p_vkGetInstanceProcAddr(NULL
, "vkEnumerateInstanceVersion");
1024 if (p_vkEnumerateInstanceVersion
)
1026 res
= p_vkEnumerateInstanceVersion(version
);
1030 *version
= VK_API_VERSION_1_0
;
1034 TRACE("API version %u.%u.%u.\n",
1035 VK_VERSION_MAJOR(*version
), VK_VERSION_MINOR(*version
), VK_VERSION_PATCH(*version
));
1036 *version
= min(WINE_VK_VERSION
, *version
);
1040 VkResult
wine_vkEnumeratePhysicalDevices(VkInstance handle
, uint32_t *count
, VkPhysicalDevice
*devices
)
1042 struct wine_instance
*instance
= wine_instance_from_handle(handle
);
1047 *count
= instance
->phys_dev_count
;
1051 *count
= min(*count
, instance
->phys_dev_count
);
1052 for (i
= 0; i
< *count
; i
++)
1054 devices
[i
] = instance
->phys_devs
[i
]->handle
;
1057 TRACE("Returning %u devices.\n", *count
);
1058 return *count
< instance
->phys_dev_count
? VK_INCOMPLETE
: VK_SUCCESS
;
1061 void wine_vkFreeCommandBuffers(VkDevice handle
, VkCommandPool command_pool
, uint32_t count
,
1062 const VkCommandBuffer
*buffers
)
1064 struct wine_device
*device
= wine_device_from_handle(handle
);
1065 struct wine_cmd_pool
*pool
= wine_cmd_pool_from_handle(command_pool
);
1067 wine_vk_free_command_buffers(device
, pool
, count
, buffers
);
1070 static VkQueue
wine_vk_device_find_queue(VkDevice handle
, const VkDeviceQueueInfo2
*info
)
1072 struct wine_device
*device
= wine_device_from_handle(handle
);
1073 struct wine_queue
*queue
;
1076 for (i
= 0; i
< device
->queue_count
; i
++)
1078 queue
= &device
->queues
[i
];
1079 if (queue
->family_index
== info
->queueFamilyIndex
1080 && queue
->queue_index
== info
->queueIndex
1081 && queue
->flags
== info
->flags
)
1083 return queue
->handle
;
1087 return VK_NULL_HANDLE
;
1090 void wine_vkGetDeviceQueue(VkDevice device
, uint32_t family_index
, uint32_t queue_index
, VkQueue
*queue
)
1092 VkDeviceQueueInfo2 queue_info
;
1094 queue_info
.sType
= VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2
;
1095 queue_info
.pNext
= NULL
;
1096 queue_info
.flags
= 0;
1097 queue_info
.queueFamilyIndex
= family_index
;
1098 queue_info
.queueIndex
= queue_index
;
1100 *queue
= wine_vk_device_find_queue(device
, &queue_info
);
1103 void wine_vkGetDeviceQueue2(VkDevice device
, const VkDeviceQueueInfo2
*info
, VkQueue
*queue
)
1105 const VkBaseInStructure
*chain
;
1107 if ((chain
= info
->pNext
))
1108 FIXME("Ignoring a linked structure of type %u.\n", chain
->sType
);
1110 *queue
= wine_vk_device_find_queue(device
, info
);
1113 VkResult
wine_vkCreateCommandPool(VkDevice device_handle
, const VkCommandPoolCreateInfo
*info
,
1114 const VkAllocationCallbacks
*allocator
, VkCommandPool
*command_pool
,
1117 struct wine_device
*device
= wine_device_from_handle(device_handle
);
1118 struct vk_command_pool
*handle
= client_ptr
;
1119 struct wine_cmd_pool
*object
;
1123 FIXME("Support for allocation callbacks not implemented yet\n");
1125 if (!(object
= calloc(1, sizeof(*object
))))
1126 return VK_ERROR_OUT_OF_HOST_MEMORY
;
1128 res
= device
->funcs
.p_vkCreateCommandPool(device
->device
, info
, NULL
, &object
->command_pool
);
1130 if (res
== VK_SUCCESS
)
1132 object
->handle
= (uintptr_t)handle
;
1133 handle
->unix_handle
= (uintptr_t)object
;
1134 WINE_VK_ADD_NON_DISPATCHABLE_MAPPING(device
->phys_dev
->instance
, object
->handle
,
1135 object
->command_pool
, object
);
1136 *command_pool
= object
->handle
;
1146 void wine_vkDestroyCommandPool(VkDevice device_handle
, VkCommandPool handle
,
1147 const VkAllocationCallbacks
*allocator
)
1149 struct wine_device
*device
= wine_device_from_handle(device_handle
);
1150 struct wine_cmd_pool
*pool
= wine_cmd_pool_from_handle(handle
);
1153 FIXME("Support for allocation callbacks not implemented yet\n");
1155 WINE_VK_REMOVE_HANDLE_MAPPING(device
->phys_dev
->instance
, pool
);
1157 device
->funcs
.p_vkDestroyCommandPool(device
->device
, pool
->command_pool
, NULL
);
1161 static VkResult
wine_vk_enumerate_physical_device_groups(struct wine_instance
*instance
,
1162 VkResult (*p_vkEnumeratePhysicalDeviceGroups
)(VkInstance
, uint32_t *, VkPhysicalDeviceGroupProperties
*),
1163 uint32_t *count
, VkPhysicalDeviceGroupProperties
*properties
)
1168 res
= p_vkEnumeratePhysicalDeviceGroups(instance
->instance
, count
, properties
);
1169 if (res
< 0 || !properties
)
1172 for (i
= 0; i
< *count
; ++i
)
1174 VkPhysicalDeviceGroupProperties
*current
= &properties
[i
];
1175 for (j
= 0; j
< current
->physicalDeviceCount
; ++j
)
1177 VkPhysicalDevice dev
= current
->physicalDevices
[j
];
1178 struct wine_phys_dev
*phys_dev
= wine_vk_instance_wrap_physical_device(instance
, dev
);
1180 return VK_ERROR_INITIALIZATION_FAILED
;
1181 current
->physicalDevices
[j
] = phys_dev
->handle
;
1188 VkResult
wine_vkEnumeratePhysicalDeviceGroups(VkInstance handle
, uint32_t *count
,
1189 VkPhysicalDeviceGroupProperties
*properties
)
1191 struct wine_instance
*instance
= wine_instance_from_handle(handle
);
1193 return wine_vk_enumerate_physical_device_groups(instance
,
1194 instance
->funcs
.p_vkEnumeratePhysicalDeviceGroups
, count
, properties
);
1197 VkResult
wine_vkEnumeratePhysicalDeviceGroupsKHR(VkInstance handle
, uint32_t *count
,
1198 VkPhysicalDeviceGroupProperties
*properties
)
1200 struct wine_instance
*instance
= wine_instance_from_handle(handle
);
1202 return wine_vk_enumerate_physical_device_groups(instance
,
1203 instance
->funcs
.p_vkEnumeratePhysicalDeviceGroupsKHR
, count
, properties
);
1206 void wine_vkGetPhysicalDeviceExternalFenceProperties(VkPhysicalDevice phys_dev
,
1207 const VkPhysicalDeviceExternalFenceInfo
*fence_info
,
1208 VkExternalFenceProperties
*properties
)
1210 properties
->exportFromImportedHandleTypes
= 0;
1211 properties
->compatibleHandleTypes
= 0;
1212 properties
->externalFenceFeatures
= 0;
1215 void wine_vkGetPhysicalDeviceExternalFencePropertiesKHR(VkPhysicalDevice phys_dev
,
1216 const VkPhysicalDeviceExternalFenceInfo
*fence_info
,
1217 VkExternalFenceProperties
*properties
)
1219 properties
->exportFromImportedHandleTypes
= 0;
1220 properties
->compatibleHandleTypes
= 0;
1221 properties
->externalFenceFeatures
= 0;
1224 void wine_vkGetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice phys_dev
,
1225 const VkPhysicalDeviceExternalBufferInfo
*buffer_info
,
1226 VkExternalBufferProperties
*properties
)
1228 memset(&properties
->externalMemoryProperties
, 0, sizeof(properties
->externalMemoryProperties
));
1231 void wine_vkGetPhysicalDeviceExternalBufferPropertiesKHR(VkPhysicalDevice phys_dev
,
1232 const VkPhysicalDeviceExternalBufferInfo
*buffer_info
,
1233 VkExternalBufferProperties
*properties
)
1235 memset(&properties
->externalMemoryProperties
, 0, sizeof(properties
->externalMemoryProperties
));
1238 VkResult
wine_vkGetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice phys_dev_handle
,
1239 const VkPhysicalDeviceImageFormatInfo2
*format_info
,
1240 VkImageFormatProperties2
*properties
)
1242 struct wine_phys_dev
*phys_dev
= wine_phys_dev_from_handle(phys_dev_handle
);
1243 VkExternalImageFormatProperties
*external_image_properties
;
1246 res
= phys_dev
->instance
->funcs
.p_vkGetPhysicalDeviceImageFormatProperties2(phys_dev
->phys_dev
,
1247 format_info
, properties
);
1249 if ((external_image_properties
= find_next_struct(properties
,
1250 VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES
)))
1252 VkExternalMemoryProperties
*p
= &external_image_properties
->externalMemoryProperties
;
1253 p
->externalMemoryFeatures
= 0;
1254 p
->exportFromImportedHandleTypes
= 0;
1255 p
->compatibleHandleTypes
= 0;
1261 VkResult
wine_vkGetPhysicalDeviceImageFormatProperties2KHR(VkPhysicalDevice phys_dev_handle
,
1262 const VkPhysicalDeviceImageFormatInfo2
*format_info
,
1263 VkImageFormatProperties2
*properties
)
1265 struct wine_phys_dev
*phys_dev
= wine_phys_dev_from_handle(phys_dev_handle
);
1266 VkExternalImageFormatProperties
*external_image_properties
;
1269 res
= phys_dev
->instance
->funcs
.p_vkGetPhysicalDeviceImageFormatProperties2KHR(phys_dev
->phys_dev
,
1270 format_info
, properties
);
1272 if ((external_image_properties
= find_next_struct(properties
,
1273 VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES
)))
1275 VkExternalMemoryProperties
*p
= &external_image_properties
->externalMemoryProperties
;
1276 p
->externalMemoryFeatures
= 0;
1277 p
->exportFromImportedHandleTypes
= 0;
1278 p
->compatibleHandleTypes
= 0;
1284 /* From ntdll/unix/sync.c */
1285 #define NANOSECONDS_IN_A_SECOND 1000000000
1286 #define TICKSPERSEC 10000000
1288 static inline VkTimeDomainEXT
get_performance_counter_time_domain(void)
1290 #if !defined(__APPLE__) && defined(HAVE_CLOCK_GETTIME)
1291 # ifdef CLOCK_MONOTONIC_RAW
1292 return VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT
;
1294 return VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT
;
1297 FIXME("No mapping for VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT on this platform.\n");
1298 return VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT
;
1302 static VkTimeDomainEXT
map_to_host_time_domain(VkTimeDomainEXT domain
)
1304 /* Matches ntdll/unix/sync.c's performance counter implementation. */
1305 if (domain
== VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT
)
1306 return get_performance_counter_time_domain();
1311 static inline uint64_t convert_monotonic_timestamp(uint64_t value
)
1313 return value
/ (NANOSECONDS_IN_A_SECOND
/ TICKSPERSEC
);
1316 static inline uint64_t convert_timestamp(VkTimeDomainEXT host_domain
, VkTimeDomainEXT target_domain
, uint64_t value
)
1318 if (host_domain
== target_domain
)
1321 /* Convert between MONOTONIC time in ns -> QueryPerformanceCounter */
1322 if ((host_domain
== VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT
|| host_domain
== VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT
)
1323 && target_domain
== VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT
)
1324 return convert_monotonic_timestamp(value
);
1326 FIXME("Couldn't translate between host domain %d and target domain %d\n", host_domain
, target_domain
);
1330 VkResult
wine_vkGetCalibratedTimestampsEXT(VkDevice handle
, uint32_t timestamp_count
,
1331 const VkCalibratedTimestampInfoEXT
*timestamp_infos
,
1332 uint64_t *timestamps
, uint64_t *max_deviation
)
1334 struct wine_device
*device
= wine_device_from_handle(handle
);
1335 VkCalibratedTimestampInfoEXT
* host_timestamp_infos
;
1338 TRACE("%p, %u, %p, %p, %p\n", device
, timestamp_count
, timestamp_infos
, timestamps
, max_deviation
);
1340 if (!(host_timestamp_infos
= malloc(sizeof(VkCalibratedTimestampInfoEXT
) * timestamp_count
)))
1341 return VK_ERROR_OUT_OF_HOST_MEMORY
;
1343 for (i
= 0; i
< timestamp_count
; i
++)
1345 host_timestamp_infos
[i
].sType
= timestamp_infos
[i
].sType
;
1346 host_timestamp_infos
[i
].pNext
= timestamp_infos
[i
].pNext
;
1347 host_timestamp_infos
[i
].timeDomain
= map_to_host_time_domain(timestamp_infos
[i
].timeDomain
);
1350 res
= device
->funcs
.p_vkGetCalibratedTimestampsEXT(device
->device
, timestamp_count
, host_timestamp_infos
, timestamps
, max_deviation
);
1351 if (res
!= VK_SUCCESS
)
1354 for (i
= 0; i
< timestamp_count
; i
++)
1355 timestamps
[i
] = convert_timestamp(host_timestamp_infos
[i
].timeDomain
, timestamp_infos
[i
].timeDomain
, timestamps
[i
]);
1357 free(host_timestamp_infos
);
1362 VkResult
wine_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT(VkPhysicalDevice handle
,
1363 uint32_t *time_domain_count
,
1364 VkTimeDomainEXT
*time_domains
)
1366 struct wine_phys_dev
*phys_dev
= wine_phys_dev_from_handle(handle
);
1367 BOOL supports_device
= FALSE
, supports_monotonic
= FALSE
, supports_monotonic_raw
= FALSE
;
1368 const VkTimeDomainEXT performance_counter_domain
= get_performance_counter_time_domain();
1369 VkTimeDomainEXT
*host_time_domains
;
1370 uint32_t host_time_domain_count
;
1371 VkTimeDomainEXT out_time_domains
[2];
1372 uint32_t out_time_domain_count
;
1376 /* Find out the time domains supported on the host */
1377 res
= phys_dev
->instance
->funcs
.p_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT(phys_dev
->phys_dev
, &host_time_domain_count
, NULL
);
1378 if (res
!= VK_SUCCESS
)
1381 if (!(host_time_domains
= malloc(sizeof(VkTimeDomainEXT
) * host_time_domain_count
)))
1382 return VK_ERROR_OUT_OF_HOST_MEMORY
;
1384 res
= phys_dev
->instance
->funcs
.p_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT(phys_dev
->phys_dev
, &host_time_domain_count
, host_time_domains
);
1385 if (res
!= VK_SUCCESS
)
1387 free(host_time_domains
);
1391 for (i
= 0; i
< host_time_domain_count
; i
++)
1393 if (host_time_domains
[i
] == VK_TIME_DOMAIN_DEVICE_EXT
)
1394 supports_device
= TRUE
;
1395 else if (host_time_domains
[i
] == VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT
)
1396 supports_monotonic
= TRUE
;
1397 else if (host_time_domains
[i
] == VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT
)
1398 supports_monotonic_raw
= TRUE
;
1400 FIXME("Unknown time domain %d\n", host_time_domains
[i
]);
1403 free(host_time_domains
);
1405 out_time_domain_count
= 0;
1407 /* Map our monotonic times -> QPC */
1408 if (supports_monotonic_raw
&& performance_counter_domain
== VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT
)
1409 out_time_domains
[out_time_domain_count
++] = VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT
;
1410 else if (supports_monotonic
&& performance_counter_domain
== VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT
)
1411 out_time_domains
[out_time_domain_count
++] = VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT
;
1413 FIXME("VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT not supported on this platform.\n");
1415 /* Forward the device domain time */
1416 if (supports_device
)
1417 out_time_domains
[out_time_domain_count
++] = VK_TIME_DOMAIN_DEVICE_EXT
;
1419 /* Send the count/domains back to the app */
1422 *time_domain_count
= out_time_domain_count
;
1426 for (i
= 0; i
< min(*time_domain_count
, out_time_domain_count
); i
++)
1427 time_domains
[i
] = out_time_domains
[i
];
1429 res
= *time_domain_count
< out_time_domain_count
? VK_INCOMPLETE
: VK_SUCCESS
;
1430 *time_domain_count
= out_time_domain_count
;
1434 void wine_vkGetPhysicalDeviceExternalSemaphoreProperties(VkPhysicalDevice phys_dev
,
1435 const VkPhysicalDeviceExternalSemaphoreInfo
*info
,
1436 VkExternalSemaphoreProperties
*properties
)
1438 properties
->exportFromImportedHandleTypes
= 0;
1439 properties
->compatibleHandleTypes
= 0;
1440 properties
->externalSemaphoreFeatures
= 0;
1443 void wine_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR(VkPhysicalDevice phys_dev
,
1444 const VkPhysicalDeviceExternalSemaphoreInfo
*info
,
1445 VkExternalSemaphoreProperties
*properties
)
1447 properties
->exportFromImportedHandleTypes
= 0;
1448 properties
->compatibleHandleTypes
= 0;
1449 properties
->externalSemaphoreFeatures
= 0;
1452 VkResult
wine_vkCreateWin32SurfaceKHR(VkInstance handle
, const VkWin32SurfaceCreateInfoKHR
*createInfo
,
1453 const VkAllocationCallbacks
*allocator
, VkSurfaceKHR
*surface
)
1455 struct wine_instance
*instance
= wine_instance_from_handle(handle
);
1456 struct wine_surface
*object
;
1460 FIXME("Support for allocation callbacks not implemented yet\n");
1462 object
= calloc(1, sizeof(*object
));
1465 return VK_ERROR_OUT_OF_HOST_MEMORY
;
1467 res
= instance
->funcs
.p_vkCreateWin32SurfaceKHR(instance
->instance
, createInfo
, NULL
, &object
->driver_surface
);
1469 if (res
!= VK_SUCCESS
)
1475 object
->surface
= vk_funcs
->p_wine_get_native_surface(object
->driver_surface
);
1477 WINE_VK_ADD_NON_DISPATCHABLE_MAPPING(instance
, object
, object
->surface
, object
);
1479 *surface
= wine_surface_to_handle(object
);
1484 void wine_vkDestroySurfaceKHR(VkInstance handle
, VkSurfaceKHR surface
,
1485 const VkAllocationCallbacks
*allocator
)
1487 struct wine_instance
*instance
= wine_instance_from_handle(handle
);
1488 struct wine_surface
*object
= wine_surface_from_handle(surface
);
1493 instance
->funcs
.p_vkDestroySurfaceKHR(instance
->instance
, object
->driver_surface
, NULL
);
1495 WINE_VK_REMOVE_HANDLE_MAPPING(instance
, object
);
1499 VkResult
wine_vkAllocateMemory(VkDevice handle
, const VkMemoryAllocateInfo
*alloc_info
,
1500 const VkAllocationCallbacks
*allocator
, VkDeviceMemory
*ret
)
1502 struct wine_device
*device
= wine_device_from_handle(handle
);
1503 struct wine_device_memory
*memory
;
1504 VkMemoryAllocateInfo info
= *alloc_info
;
1505 VkImportMemoryHostPointerInfoEXT host_pointer_info
;
1507 void *mapping
= NULL
;
1510 /* For host visible memory, we try to use VK_EXT_external_memory_host on wow64
1511 * to ensure that mapped pointer is 32-bit. */
1512 mem_flags
= device
->phys_dev
->memory_properties
.memoryTypes
[alloc_info
->memoryTypeIndex
].propertyFlags
;
1513 if (device
->phys_dev
->external_memory_align
&& (mem_flags
& VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
) &&
1514 !find_next_struct(alloc_info
->pNext
, VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT
))
1516 VkMemoryHostPointerPropertiesEXT props
=
1518 .sType
= VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT
,
1520 uint32_t i
, align
= device
->phys_dev
->external_memory_align
- 1;
1521 SIZE_T alloc_size
= info
.allocationSize
;
1525 FIXME("Using VK_EXT_external_memory_host\n");
1527 if (NtAllocateVirtualMemory(GetCurrentProcess(), &mapping
, zero_bits
, &alloc_size
,
1528 MEM_COMMIT
, PAGE_READWRITE
))
1530 ERR("NtAllocateVirtualMemory failed\n");
1531 return VK_ERROR_OUT_OF_HOST_MEMORY
;
1534 result
= device
->funcs
.p_vkGetMemoryHostPointerPropertiesEXT(device
->device
,
1535 VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT
, mapping
, &props
);
1536 if (result
!= VK_SUCCESS
)
1538 ERR("vkGetMemoryHostPointerPropertiesEXT failed: %d\n", result
);
1542 if (!(props
.memoryTypeBits
& (1u << info
.memoryTypeIndex
)))
1544 /* If requested memory type is not allowed to use external memory,
1545 * try to find a supported compatible type. */
1546 uint32_t mask
= mem_flags
& ~VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
;
1547 for (i
= 0; i
< device
->phys_dev
->memory_properties
.memoryTypeCount
; i
++)
1549 if (!(props
.memoryTypeBits
& (1u << i
)))
1551 if ((device
->phys_dev
->memory_properties
.memoryTypes
[i
].propertyFlags
& mask
) != mask
)
1554 TRACE("Memory type not compatible with host memory, using %u instead\n", i
);
1555 info
.memoryTypeIndex
= i
;
1558 if (i
== device
->phys_dev
->memory_properties
.memoryTypeCount
)
1560 FIXME("Not found compatible memory type\n");
1562 NtFreeVirtualMemory(GetCurrentProcess(), &mapping
, &alloc_size
, MEM_RELEASE
);
1566 if (props
.memoryTypeBits
& (1u << info
.memoryTypeIndex
))
1568 host_pointer_info
.sType
= VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT
;
1569 host_pointer_info
.handleType
= VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT
;
1570 host_pointer_info
.pHostPointer
= mapping
;
1571 host_pointer_info
.pNext
= info
.pNext
;
1572 info
.pNext
= &host_pointer_info
;
1574 info
.allocationSize
= (info
.allocationSize
+ align
) & ~align
;
1578 if (!(memory
= malloc(sizeof(*memory
))))
1579 return VK_ERROR_OUT_OF_HOST_MEMORY
;
1581 result
= device
->funcs
.p_vkAllocateMemory(device
->device
, &info
, NULL
, &memory
->memory
);
1582 if (result
!= VK_SUCCESS
)
1588 memory
->mapping
= mapping
;
1589 *ret
= (VkDeviceMemory
)(uintptr_t)memory
;
1593 void wine_vkFreeMemory(VkDevice handle
, VkDeviceMemory memory_handle
, const VkAllocationCallbacks
*allocator
)
1595 struct wine_device
*device
= wine_device_from_handle(handle
);
1596 struct wine_device_memory
*memory
;
1600 memory
= wine_device_memory_from_handle(memory_handle
);
1602 device
->funcs
.p_vkFreeMemory(device
->device
, memory
->memory
, NULL
);
1604 if (memory
->mapping
)
1606 SIZE_T alloc_size
= 0;
1607 NtFreeVirtualMemory(GetCurrentProcess(), &memory
->mapping
, &alloc_size
, MEM_RELEASE
);
1613 VkResult
wine_vkMapMemory(VkDevice device
, VkDeviceMemory memory
, VkDeviceSize offset
,
1614 VkDeviceSize size
, VkMemoryMapFlags flags
, void **data
)
1616 const VkMemoryMapInfoKHR info
=
1618 .sType
= VK_STRUCTURE_TYPE_MEMORY_MAP_INFO_KHR
,
1625 return wine_vkMapMemory2KHR(device
, &info
, data
);
1628 VkResult
wine_vkMapMemory2KHR(VkDevice handle
, const VkMemoryMapInfoKHR
*map_info
, void **data
)
1630 struct wine_device
*device
= wine_device_from_handle(handle
);
1631 struct wine_device_memory
*memory
= wine_device_memory_from_handle(map_info
->memory
);
1632 VkMemoryMapInfoKHR info
= *map_info
;
1635 info
.memory
= memory
->memory
;
1636 if (memory
->mapping
)
1638 *data
= (char *)memory
->mapping
+ info
.offset
;
1639 TRACE("returning %p\n", *data
);
1643 if (device
->funcs
.p_vkMapMemory2KHR
)
1645 result
= device
->funcs
.p_vkMapMemory2KHR(device
->device
, &info
, data
);
1649 assert(!info
.pNext
);
1650 result
= device
->funcs
.p_vkMapMemory(device
->device
, info
.memory
, info
.offset
,
1651 info
.size
, info
.flags
, data
);
1655 if (NtCurrentTeb()->WowTebOffset
&& result
== VK_SUCCESS
&& (UINT_PTR
)*data
>> 32)
1657 FIXME("returned mapping %p does not fit 32-bit pointer\n", *data
);
1658 device
->funcs
.p_vkUnmapMemory(device
->device
, memory
->memory
);
1660 result
= VK_ERROR_OUT_OF_HOST_MEMORY
;
1667 void wine_vkUnmapMemory(VkDevice device
, VkDeviceMemory memory
)
1669 const VkMemoryUnmapInfoKHR info
=
1671 .sType
= VK_STRUCTURE_TYPE_MEMORY_UNMAP_INFO_KHR
,
1675 wine_vkUnmapMemory2KHR(device
, &info
);
1678 VkResult
wine_vkUnmapMemory2KHR(VkDevice handle
, const VkMemoryUnmapInfoKHR
*unmap_info
)
1680 struct wine_device
*device
= wine_device_from_handle(handle
);
1681 struct wine_device_memory
*memory
= wine_device_memory_from_handle(unmap_info
->memory
);
1682 VkMemoryUnmapInfoKHR info
;
1684 if (memory
->mapping
)
1687 if (!device
->funcs
.p_vkUnmapMemory2KHR
)
1689 assert(!unmap_info
->pNext
);
1690 device
->funcs
.p_vkUnmapMemory(device
->device
, memory
->memory
);
1695 info
.memory
= memory
->memory
;
1696 return device
->funcs
.p_vkUnmapMemory2KHR(device
->device
, &info
);
1699 VkResult
wine_vkCreateBuffer(VkDevice handle
, const VkBufferCreateInfo
*create_info
,
1700 const VkAllocationCallbacks
*allocator
, VkBuffer
*buffer
)
1702 struct wine_device
*device
= wine_device_from_handle(handle
);
1703 VkExternalMemoryBufferCreateInfo external_memory_info
;
1704 VkBufferCreateInfo info
= *create_info
;
1706 if (device
->phys_dev
->external_memory_align
&&
1707 !find_next_struct(info
.pNext
, VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO
))
1709 external_memory_info
.sType
= VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO
;
1710 external_memory_info
.pNext
= info
.pNext
;
1711 external_memory_info
.handleTypes
= VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT
;
1712 info
.pNext
= &external_memory_info
;
1715 return device
->funcs
.p_vkCreateBuffer(device
->device
, &info
, NULL
, buffer
);
1718 VkResult
wine_vkCreateImage(VkDevice handle
, const VkImageCreateInfo
*create_info
,
1719 const VkAllocationCallbacks
*allocator
, VkImage
*image
)
1721 struct wine_device
*device
= wine_device_from_handle(handle
);
1722 VkExternalMemoryImageCreateInfo external_memory_info
;
1723 VkImageCreateInfo info
= *create_info
;
1725 if (device
->phys_dev
->external_memory_align
&&
1726 !find_next_struct(info
.pNext
, VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO
))
1728 external_memory_info
.sType
= VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO
;
1729 external_memory_info
.pNext
= info
.pNext
;
1730 external_memory_info
.handleTypes
= VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT
;
1731 info
.pNext
= &external_memory_info
;
1734 return device
->funcs
.p_vkCreateImage(device
->device
, &info
, NULL
, image
);
1737 static inline void adjust_max_image_count(struct wine_phys_dev
*phys_dev
, VkSurfaceCapabilitiesKHR
* capabilities
)
1739 /* Many Windows games, for example Strange Brigade, No Man's Sky, Path of Exile
1740 * and World War Z, do not expect that maxImageCount can be set to 0.
1741 * A value of 0 means that there is no limit on the number of images.
1742 * Nvidia reports 8 on Windows, AMD 16.
1743 * https://vulkan.gpuinfo.org/displayreport.php?id=9122#surface
1744 * https://vulkan.gpuinfo.org/displayreport.php?id=9121#surface
1746 if ((phys_dev
->instance
->quirks
& WINEVULKAN_QUIRK_ADJUST_MAX_IMAGE_COUNT
) && !capabilities
->maxImageCount
)
1748 capabilities
->maxImageCount
= max(capabilities
->minImageCount
, 16);
1752 VkResult
wine_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice handle
, VkSurfaceKHR surface_handle
,
1753 VkSurfaceCapabilitiesKHR
*capabilities
)
1755 struct wine_phys_dev
*phys_dev
= wine_phys_dev_from_handle(handle
);
1756 struct wine_surface
*surface
= wine_surface_from_handle(surface_handle
);
1759 res
= phys_dev
->instance
->funcs
.p_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(phys_dev
->phys_dev
,
1760 surface
->driver_surface
, capabilities
);
1762 if (res
== VK_SUCCESS
)
1763 adjust_max_image_count(phys_dev
, capabilities
);
1768 VkResult
wine_vkGetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice handle
,
1769 const VkPhysicalDeviceSurfaceInfo2KHR
*surface_info
,
1770 VkSurfaceCapabilities2KHR
*capabilities
)
1772 struct wine_phys_dev
*phys_dev
= wine_phys_dev_from_handle(handle
);
1773 struct wine_surface
*surface
= wine_surface_from_handle(surface_info
->surface
);
1774 VkPhysicalDeviceSurfaceInfo2KHR host_info
;
1777 host_info
.sType
= surface_info
->sType
;
1778 host_info
.pNext
= surface_info
->pNext
;
1779 host_info
.surface
= surface
->driver_surface
;
1780 res
= phys_dev
->instance
->funcs
.p_vkGetPhysicalDeviceSurfaceCapabilities2KHR(phys_dev
->phys_dev
,
1781 &host_info
, capabilities
);
1783 if (res
== VK_SUCCESS
)
1784 adjust_max_image_count(phys_dev
, &capabilities
->surfaceCapabilities
);
1789 VkResult
wine_vkCreateDebugUtilsMessengerEXT(VkInstance handle
,
1790 const VkDebugUtilsMessengerCreateInfoEXT
*create_info
,
1791 const VkAllocationCallbacks
*allocator
,
1792 VkDebugUtilsMessengerEXT
*messenger
)
1794 struct wine_instance
*instance
= wine_instance_from_handle(handle
);
1795 VkDebugUtilsMessengerCreateInfoEXT wine_create_info
;
1796 struct wine_debug_utils_messenger
*object
;
1800 FIXME("Support for allocation callbacks not implemented yet\n");
1802 if (!(object
= calloc(1, sizeof(*object
))))
1803 return VK_ERROR_OUT_OF_HOST_MEMORY
;
1805 object
->instance
= instance
;
1806 object
->user_callback
= create_info
->pfnUserCallback
;
1807 object
->user_data
= create_info
->pUserData
;
1809 wine_create_info
= *create_info
;
1811 wine_create_info
.pfnUserCallback
= (void *) &debug_utils_callback_conversion
;
1812 wine_create_info
.pUserData
= object
;
1814 res
= instance
->funcs
.p_vkCreateDebugUtilsMessengerEXT(instance
->instance
, &wine_create_info
, NULL
, &object
->debug_messenger
);
1816 if (res
!= VK_SUCCESS
)
1822 WINE_VK_ADD_NON_DISPATCHABLE_MAPPING(instance
, object
, object
->debug_messenger
, object
);
1823 *messenger
= wine_debug_utils_messenger_to_handle(object
);
1828 void wine_vkDestroyDebugUtilsMessengerEXT(VkInstance handle
, VkDebugUtilsMessengerEXT messenger
,
1829 const VkAllocationCallbacks
*allocator
)
1831 struct wine_instance
*instance
= wine_instance_from_handle(handle
);
1832 struct wine_debug_utils_messenger
*object
;
1834 object
= wine_debug_utils_messenger_from_handle(messenger
);
1839 instance
->funcs
.p_vkDestroyDebugUtilsMessengerEXT(instance
->instance
, object
->debug_messenger
, NULL
);
1840 WINE_VK_REMOVE_HANDLE_MAPPING(instance
, object
);
1845 VkResult
wine_vkCreateDebugReportCallbackEXT(VkInstance handle
,
1846 const VkDebugReportCallbackCreateInfoEXT
*create_info
,
1847 const VkAllocationCallbacks
*allocator
,
1848 VkDebugReportCallbackEXT
*callback
)
1850 struct wine_instance
*instance
= wine_instance_from_handle(handle
);
1851 VkDebugReportCallbackCreateInfoEXT wine_create_info
;
1852 struct wine_debug_report_callback
*object
;
1856 FIXME("Support for allocation callbacks not implemented yet\n");
1858 if (!(object
= calloc(1, sizeof(*object
))))
1859 return VK_ERROR_OUT_OF_HOST_MEMORY
;
1861 object
->instance
= instance
;
1862 object
->user_callback
= create_info
->pfnCallback
;
1863 object
->user_data
= create_info
->pUserData
;
1865 wine_create_info
= *create_info
;
1867 wine_create_info
.pfnCallback
= (void *) debug_report_callback_conversion
;
1868 wine_create_info
.pUserData
= object
;
1870 res
= instance
->funcs
.p_vkCreateDebugReportCallbackEXT(instance
->instance
, &wine_create_info
, NULL
, &object
->debug_callback
);
1872 if (res
!= VK_SUCCESS
)
1878 WINE_VK_ADD_NON_DISPATCHABLE_MAPPING(instance
, object
, object
->debug_callback
, object
);
1879 *callback
= wine_debug_report_callback_to_handle(object
);
1884 void wine_vkDestroyDebugReportCallbackEXT(VkInstance handle
, VkDebugReportCallbackEXT callback
,
1885 const VkAllocationCallbacks
*allocator
)
1887 struct wine_instance
*instance
= wine_instance_from_handle(handle
);
1888 struct wine_debug_report_callback
*object
;
1890 object
= wine_debug_report_callback_from_handle(callback
);
1895 instance
->funcs
.p_vkDestroyDebugReportCallbackEXT(instance
->instance
, object
->debug_callback
, NULL
);
1897 WINE_VK_REMOVE_HANDLE_MAPPING(instance
, object
);
1902 VkResult
wine_vkCreateDeferredOperationKHR(VkDevice handle
,
1903 const VkAllocationCallbacks
* allocator
,
1904 VkDeferredOperationKHR
* deferredOperation
)
1906 struct wine_device
*device
= wine_device_from_handle(handle
);
1907 struct wine_deferred_operation
*object
;
1911 FIXME("Support for allocation callbacks not implemented yet\n");
1913 if (!(object
= calloc(1, sizeof(*object
))))
1914 return VK_ERROR_OUT_OF_HOST_MEMORY
;
1916 res
= device
->funcs
.p_vkCreateDeferredOperationKHR(device
->device
, NULL
, &object
->deferred_operation
);
1918 if (res
!= VK_SUCCESS
)
1924 init_conversion_context(&object
->ctx
);
1926 WINE_VK_ADD_NON_DISPATCHABLE_MAPPING(device
->phys_dev
->instance
, object
, object
->deferred_operation
, object
);
1927 *deferredOperation
= wine_deferred_operation_to_handle(object
);
1932 void wine_vkDestroyDeferredOperationKHR(VkDevice handle
,
1933 VkDeferredOperationKHR operation
,
1934 const VkAllocationCallbacks
* allocator
)
1936 struct wine_device
*device
= wine_device_from_handle(handle
);
1937 struct wine_deferred_operation
*object
;
1939 object
= wine_deferred_operation_from_handle(operation
);
1944 device
->funcs
.p_vkDestroyDeferredOperationKHR(device
->device
, object
->deferred_operation
, NULL
);
1946 WINE_VK_REMOVE_HANDLE_MAPPING(device
->phys_dev
->instance
, object
);
1948 free_conversion_context(&object
->ctx
);
1954 NTSTATUS
vk_is_available_instance_function(void *arg
)
1956 struct is_available_instance_function_params
*params
= arg
;
1957 struct wine_instance
*instance
= wine_instance_from_handle(params
->instance
);
1958 return !!vk_funcs
->p_vkGetInstanceProcAddr(instance
->instance
, params
->name
);
1961 NTSTATUS
vk_is_available_device_function(void *arg
)
1963 struct is_available_device_function_params
*params
= arg
;
1964 struct wine_device
*device
= wine_device_from_handle(params
->device
);
1965 return !!vk_funcs
->p_vkGetDeviceProcAddr(device
->device
, params
->name
);
1970 NTSTATUS
vk_is_available_instance_function32(void *arg
)
1977 struct wine_instance
*instance
= wine_instance_from_handle(UlongToPtr(params
->instance
));
1978 return !!vk_funcs
->p_vkGetInstanceProcAddr(instance
->instance
, UlongToPtr(params
->name
));
1981 NTSTATUS
vk_is_available_device_function32(void *arg
)
1988 struct wine_device
*device
= wine_device_from_handle(UlongToPtr(params
->device
));
1989 return !!vk_funcs
->p_vkGetDeviceProcAddr(device
->device
, UlongToPtr(params
->name
));