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
28 #include "vulkan_private.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(vulkan
);
34 #define wine_vk_find_struct(s, t) wine_vk_find_struct_((void *)s, VK_STRUCTURE_TYPE_##t)
35 static void *wine_vk_find_struct_(void *s
, VkStructureType t
)
37 VkBaseOutStructure
*header
;
39 for (header
= s
; header
; header
= header
->pNext
)
41 if (header
->sType
== t
)
48 #define wine_vk_count_struct(s, t) wine_vk_count_struct_((void *)s, VK_STRUCTURE_TYPE_##t)
49 static uint32_t wine_vk_count_struct_(void *s
, VkStructureType t
)
51 const VkBaseInStructure
*header
;
54 for (header
= s
; header
; header
= header
->pNext
)
56 if (header
->sType
== t
)
63 static const struct vulkan_funcs
*vk_funcs
;
65 #define WINE_VK_ADD_DISPATCHABLE_MAPPING(instance, object, native_handle) \
66 wine_vk_add_handle_mapping((instance), (uint64_t) (uintptr_t) (object), (uint64_t) (uintptr_t) (native_handle), &(object)->mapping)
67 #define WINE_VK_ADD_NON_DISPATCHABLE_MAPPING(instance, object, native_handle) \
68 wine_vk_add_handle_mapping((instance), (uint64_t) (uintptr_t) (object), (uint64_t) (native_handle), &(object)->mapping)
69 static void wine_vk_add_handle_mapping(struct VkInstance_T
*instance
, uint64_t wrapped_handle
,
70 uint64_t native_handle
, struct wine_vk_mapping
*mapping
)
72 if (instance
->enable_wrapper_list
)
74 mapping
->native_handle
= native_handle
;
75 mapping
->wine_wrapped_handle
= wrapped_handle
;
76 pthread_rwlock_wrlock(&instance
->wrapper_lock
);
77 list_add_tail(&instance
->wrappers
, &mapping
->link
);
78 pthread_rwlock_unlock(&instance
->wrapper_lock
);
82 #define WINE_VK_REMOVE_HANDLE_MAPPING(instance, object) \
83 wine_vk_remove_handle_mapping((instance), &(object)->mapping)
84 static void wine_vk_remove_handle_mapping(struct VkInstance_T
*instance
, struct wine_vk_mapping
*mapping
)
86 if (instance
->enable_wrapper_list
)
88 pthread_rwlock_wrlock(&instance
->wrapper_lock
);
89 list_remove(&mapping
->link
);
90 pthread_rwlock_unlock(&instance
->wrapper_lock
);
94 static uint64_t wine_vk_get_wrapper(struct VkInstance_T
*instance
, uint64_t native_handle
)
96 struct wine_vk_mapping
*mapping
;
99 pthread_rwlock_rdlock(&instance
->wrapper_lock
);
100 LIST_FOR_EACH_ENTRY(mapping
, &instance
->wrappers
, struct wine_vk_mapping
, link
)
102 if (mapping
->native_handle
== native_handle
)
104 result
= mapping
->wine_wrapped_handle
;
108 pthread_rwlock_unlock(&instance
->wrapper_lock
);
112 static VkBool32
debug_utils_callback_conversion(VkDebugUtilsMessageSeverityFlagBitsEXT severity
,
113 VkDebugUtilsMessageTypeFlagsEXT message_types
,
114 const VkDebugUtilsMessengerCallbackDataEXT_host
*callback_data
,
117 struct wine_vk_debug_utils_params params
;
118 VkDebugUtilsObjectNameInfoEXT
*object_name_infos
;
119 struct wine_debug_utils_messenger
*object
;
125 TRACE("%i, %u, %p, %p\n", severity
, message_types
, callback_data
, user_data
);
129 if (!object
->instance
->instance
)
131 /* instance wasn't yet created, this is a message from the native loader */
135 /* FIXME: we should pack all referenced structs instead of passing pointers */
136 params
.user_callback
= object
->user_callback
;
137 params
.user_data
= object
->user_data
;
138 params
.severity
= severity
;
139 params
.message_types
= message_types
;
140 params
.data
= *((VkDebugUtilsMessengerCallbackDataEXT
*) callback_data
);
142 object_name_infos
= calloc(params
.data
.objectCount
, sizeof(*object_name_infos
));
144 for (i
= 0; i
< params
.data
.objectCount
; i
++)
146 object_name_infos
[i
].sType
= callback_data
->pObjects
[i
].sType
;
147 object_name_infos
[i
].pNext
= callback_data
->pObjects
[i
].pNext
;
148 object_name_infos
[i
].objectType
= callback_data
->pObjects
[i
].objectType
;
149 object_name_infos
[i
].pObjectName
= callback_data
->pObjects
[i
].pObjectName
;
151 if (wine_vk_is_type_wrapped(callback_data
->pObjects
[i
].objectType
))
153 object_name_infos
[i
].objectHandle
= wine_vk_get_wrapper(object
->instance
, callback_data
->pObjects
[i
].objectHandle
);
154 if (!object_name_infos
[i
].objectHandle
)
156 WARN("handle conversion failed 0x%s\n", wine_dbgstr_longlong(callback_data
->pObjects
[i
].objectHandle
));
157 free(object_name_infos
);
163 object_name_infos
[i
].objectHandle
= callback_data
->pObjects
[i
].objectHandle
;
167 params
.data
.pObjects
= object_name_infos
;
169 /* applications should always return VK_FALSE */
170 result
= KeUserModeCallback( NtUserCallVulkanDebugUtilsCallback
, ¶ms
, sizeof(params
),
171 &ret_ptr
, &ret_len
);
173 free(object_name_infos
);
178 static VkBool32
debug_report_callback_conversion(VkDebugReportFlagsEXT flags
, VkDebugReportObjectTypeEXT object_type
,
179 uint64_t object_handle
, size_t location
, int32_t code
, const char *layer_prefix
, const char *message
, void *user_data
)
181 struct wine_vk_debug_report_params params
;
182 struct wine_debug_report_callback
*object
;
186 TRACE("%#x, %#x, 0x%s, 0x%s, %d, %p, %p, %p\n", flags
, object_type
, wine_dbgstr_longlong(object_handle
),
187 wine_dbgstr_longlong(location
), code
, layer_prefix
, message
, user_data
);
191 if (!object
->instance
->instance
)
193 /* instance wasn't yet created, this is a message from the native loader */
197 /* FIXME: we should pack all referenced structs instead of passing pointers */
198 params
.user_callback
= object
->user_callback
;
199 params
.user_data
= object
->user_data
;
200 params
.flags
= flags
;
201 params
.object_type
= object_type
;
202 params
.location
= location
;
204 params
.layer_prefix
= layer_prefix
;
205 params
.message
= message
;
207 params
.object_handle
= wine_vk_get_wrapper(object
->instance
, object_handle
);
208 if (!params
.object_handle
)
209 params
.object_type
= VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT
;
211 return KeUserModeCallback( NtUserCallVulkanDebugReportCallback
, ¶ms
, sizeof(params
),
212 &ret_ptr
, &ret_len
);
215 static void wine_vk_physical_device_free(struct VkPhysicalDevice_T
*phys_dev
)
220 WINE_VK_REMOVE_HANDLE_MAPPING(phys_dev
->instance
, phys_dev
);
221 free(phys_dev
->extensions
);
225 static struct VkPhysicalDevice_T
*wine_vk_physical_device_alloc(struct VkInstance_T
*instance
,
226 VkPhysicalDevice phys_dev
)
228 struct VkPhysicalDevice_T
*object
;
229 uint32_t num_host_properties
, num_properties
= 0;
230 VkExtensionProperties
*host_properties
= NULL
;
234 if (!(object
= calloc(1, sizeof(*object
))))
237 object
->base
.loader_magic
= VULKAN_ICD_MAGIC_VALUE
;
238 object
->instance
= instance
;
239 object
->phys_dev
= phys_dev
;
241 WINE_VK_ADD_DISPATCHABLE_MAPPING(instance
, object
, phys_dev
);
243 res
= instance
->funcs
.p_vkEnumerateDeviceExtensionProperties(phys_dev
,
244 NULL
, &num_host_properties
, NULL
);
245 if (res
!= VK_SUCCESS
)
247 ERR("Failed to enumerate device extensions, res=%d\n", res
);
251 host_properties
= calloc(num_host_properties
, sizeof(*host_properties
));
252 if (!host_properties
)
254 ERR("Failed to allocate memory for device properties!\n");
258 res
= instance
->funcs
.p_vkEnumerateDeviceExtensionProperties(phys_dev
,
259 NULL
, &num_host_properties
, host_properties
);
260 if (res
!= VK_SUCCESS
)
262 ERR("Failed to enumerate device extensions, res=%d\n", res
);
266 /* Count list of extensions for which we have an implementation.
267 * TODO: perform translation for platform specific extensions.
269 for (i
= 0; i
< num_host_properties
; i
++)
271 if (wine_vk_device_extension_supported(host_properties
[i
].extensionName
))
273 TRACE("Enabling extension '%s' for physical device %p\n", host_properties
[i
].extensionName
, object
);
278 TRACE("Skipping extension '%s', no implementation found in winevulkan.\n", host_properties
[i
].extensionName
);
282 TRACE("Host supported extensions %u, Wine supported extensions %u\n", num_host_properties
, num_properties
);
284 if (!(object
->extensions
= calloc(num_properties
, sizeof(*object
->extensions
))))
286 ERR("Failed to allocate memory for device extensions!\n");
290 for (i
= 0, j
= 0; i
< num_host_properties
; i
++)
292 if (wine_vk_device_extension_supported(host_properties
[i
].extensionName
))
294 object
->extensions
[j
] = host_properties
[i
];
298 object
->extension_count
= num_properties
;
300 free(host_properties
);
304 wine_vk_physical_device_free(object
);
305 free(host_properties
);
309 static void wine_vk_free_command_buffers(struct VkDevice_T
*device
,
310 struct wine_cmd_pool
*pool
, uint32_t count
, const VkCommandBuffer
*buffers
)
314 for (i
= 0; i
< count
; i
++)
319 device
->funcs
.p_vkFreeCommandBuffers(device
->device
, pool
->command_pool
, 1, &buffers
[i
]->command_buffer
);
320 list_remove(&buffers
[i
]->pool_link
);
321 WINE_VK_REMOVE_HANDLE_MAPPING(device
->phys_dev
->instance
, buffers
[i
]);
326 static void wine_vk_device_get_queues(struct VkDevice_T
*device
,
327 uint32_t family_index
, uint32_t queue_count
, VkDeviceQueueCreateFlags flags
,
328 struct VkQueue_T
* queues
)
330 VkDeviceQueueInfo2 queue_info
;
333 for (i
= 0; i
< queue_count
; i
++)
335 struct VkQueue_T
*queue
= &queues
[i
];
337 queue
->base
.loader_magic
= VULKAN_ICD_MAGIC_VALUE
;
338 queue
->device
= device
;
339 queue
->family_index
= family_index
;
340 queue
->queue_index
= i
;
341 queue
->flags
= flags
;
343 /* The Vulkan spec says:
345 * "vkGetDeviceQueue must only be used to get queues that were created
346 * with the flags parameter of VkDeviceQueueCreateInfo set to zero."
348 if (flags
&& device
->funcs
.p_vkGetDeviceQueue2
)
350 queue_info
.sType
= VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2
;
351 queue_info
.pNext
= NULL
;
352 queue_info
.flags
= flags
;
353 queue_info
.queueFamilyIndex
= family_index
;
354 queue_info
.queueIndex
= i
;
355 device
->funcs
.p_vkGetDeviceQueue2(device
->device
, &queue_info
, &queue
->queue
);
359 device
->funcs
.p_vkGetDeviceQueue(device
->device
, family_index
, i
, &queue
->queue
);
362 WINE_VK_ADD_DISPATCHABLE_MAPPING(device
->phys_dev
->instance
, queue
, queue
->queue
);
366 static void wine_vk_device_free_create_info(VkDeviceCreateInfo
*create_info
)
368 free_VkDeviceCreateInfo_struct_chain(create_info
);
371 static VkResult
wine_vk_device_convert_create_info(const VkDeviceCreateInfo
*src
,
372 VkDeviceCreateInfo
*dst
)
379 if ((res
= convert_VkDeviceCreateInfo_struct_chain(src
->pNext
, dst
)) < 0)
381 WARN("Failed to convert VkDeviceCreateInfo pNext chain, res=%d.\n", res
);
385 /* Should be filtered out by loader as ICDs don't support layers. */
386 dst
->enabledLayerCount
= 0;
387 dst
->ppEnabledLayerNames
= NULL
;
389 TRACE("Enabled %u extensions.\n", dst
->enabledExtensionCount
);
390 for (i
= 0; i
< dst
->enabledExtensionCount
; i
++)
392 const char *extension_name
= dst
->ppEnabledExtensionNames
[i
];
393 TRACE("Extension %u: %s.\n", i
, debugstr_a(extension_name
));
394 if (!wine_vk_device_extension_supported(extension_name
))
396 WARN("Extension %s is not supported.\n", debugstr_a(extension_name
));
397 wine_vk_device_free_create_info(dst
);
398 return VK_ERROR_EXTENSION_NOT_PRESENT
;
405 /* Helper function used for freeing a device structure. This function supports full
406 * and partial object cleanups and can thus be used for vkCreateDevice failures.
408 static void wine_vk_device_free(struct VkDevice_T
*device
)
410 struct VkQueue_T
*queue
;
418 for (i
= 0; i
< device
->queue_count
; i
++)
420 queue
= &device
->queues
[i
];
421 if (queue
&& queue
->queue
)
422 WINE_VK_REMOVE_HANDLE_MAPPING(device
->phys_dev
->instance
, queue
);
424 free(device
->queues
);
425 device
->queues
= NULL
;
428 if (device
->device
&& device
->funcs
.p_vkDestroyDevice
)
430 WINE_VK_REMOVE_HANDLE_MAPPING(device
->phys_dev
->instance
, device
);
431 device
->funcs
.p_vkDestroyDevice(device
->device
, NULL
/* pAllocator */);
437 NTSTATUS
init_vulkan(void *args
)
439 vk_funcs
= *(const struct vulkan_funcs
**)args
;
440 *(const struct unix_funcs
**)args
= &loader_funcs
;
441 return STATUS_SUCCESS
;
444 /* Helper function for converting between win32 and host compatible VkInstanceCreateInfo.
445 * This function takes care of extensions handled at winevulkan layer, a Wine graphics
446 * driver is responsible for handling e.g. surface extensions.
448 static VkResult
wine_vk_instance_convert_create_info(const VkInstanceCreateInfo
*src
,
449 VkInstanceCreateInfo
*dst
, struct VkInstance_T
*object
)
451 VkDebugUtilsMessengerCreateInfoEXT
*debug_utils_messenger
;
452 VkDebugReportCallbackCreateInfoEXT
*debug_report_callback
;
453 VkBaseInStructure
*header
;
459 if ((res
= convert_VkInstanceCreateInfo_struct_chain(src
->pNext
, dst
)) < 0)
461 WARN("Failed to convert VkInstanceCreateInfo pNext chain, res=%d.\n", res
);
465 object
->utils_messenger_count
= wine_vk_count_struct(dst
, DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT
);
466 object
->utils_messengers
= calloc(object
->utils_messenger_count
, sizeof(*object
->utils_messengers
));
467 header
= (VkBaseInStructure
*) dst
;
468 for (i
= 0; i
< object
->utils_messenger_count
; i
++)
470 header
= wine_vk_find_struct(header
->pNext
, DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT
);
471 debug_utils_messenger
= (VkDebugUtilsMessengerCreateInfoEXT
*) header
;
473 object
->utils_messengers
[i
].instance
= object
;
474 object
->utils_messengers
[i
].debug_messenger
= VK_NULL_HANDLE
;
475 object
->utils_messengers
[i
].user_callback
= debug_utils_messenger
->pfnUserCallback
;
476 object
->utils_messengers
[i
].user_data
= debug_utils_messenger
->pUserData
;
478 /* convert_VkInstanceCreateInfo_struct_chain already copied the chain,
479 * so we can modify it in-place.
481 debug_utils_messenger
->pfnUserCallback
= (void *) &debug_utils_callback_conversion
;
482 debug_utils_messenger
->pUserData
= &object
->utils_messengers
[i
];
485 debug_report_callback
= wine_vk_find_struct(header
->pNext
, DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT
);
486 if (debug_report_callback
)
488 object
->default_callback
.instance
= object
;
489 object
->default_callback
.debug_callback
= VK_NULL_HANDLE
;
490 object
->default_callback
.user_callback
= debug_report_callback
->pfnCallback
;
491 object
->default_callback
.user_data
= debug_report_callback
->pUserData
;
493 debug_report_callback
->pfnCallback
= (void *) &debug_report_callback_conversion
;
494 debug_report_callback
->pUserData
= &object
->default_callback
;
497 /* ICDs don't support any layers, so nothing to copy. Modern versions of the loader
498 * filter this data out as well.
500 if (object
->quirks
& WINEVULKAN_QUIRK_IGNORE_EXPLICIT_LAYERS
) {
501 dst
->enabledLayerCount
= 0;
502 dst
->ppEnabledLayerNames
= NULL
;
503 WARN("Ignoring explicit layers!\n");
504 } else if (dst
->enabledLayerCount
) {
505 FIXME("Loading explicit layers is not supported by winevulkan!\n");
506 return VK_ERROR_LAYER_NOT_PRESENT
;
509 TRACE("Enabled %u instance extensions.\n", dst
->enabledExtensionCount
);
510 for (i
= 0; i
< dst
->enabledExtensionCount
; i
++)
512 const char *extension_name
= dst
->ppEnabledExtensionNames
[i
];
513 TRACE("Extension %u: %s.\n", i
, debugstr_a(extension_name
));
514 if (!wine_vk_instance_extension_supported(extension_name
))
516 WARN("Extension %s is not supported.\n", debugstr_a(extension_name
));
517 free_VkInstanceCreateInfo_struct_chain(dst
);
518 return VK_ERROR_EXTENSION_NOT_PRESENT
;
520 if (!strcmp(extension_name
, "VK_EXT_debug_utils") || !strcmp(extension_name
, "VK_EXT_debug_report"))
522 object
->enable_wrapper_list
= VK_TRUE
;
529 /* Helper function which stores wrapped physical devices in the instance object. */
530 static VkResult
wine_vk_instance_load_physical_devices(struct VkInstance_T
*instance
)
532 VkPhysicalDevice
*tmp_phys_devs
;
533 uint32_t phys_dev_count
;
537 res
= instance
->funcs
.p_vkEnumeratePhysicalDevices(instance
->instance
, &phys_dev_count
, NULL
);
538 if (res
!= VK_SUCCESS
)
540 ERR("Failed to enumerate physical devices, res=%d\n", res
);
546 if (!(tmp_phys_devs
= calloc(phys_dev_count
, sizeof(*tmp_phys_devs
))))
547 return VK_ERROR_OUT_OF_HOST_MEMORY
;
549 res
= instance
->funcs
.p_vkEnumeratePhysicalDevices(instance
->instance
, &phys_dev_count
, tmp_phys_devs
);
550 if (res
!= VK_SUCCESS
)
556 instance
->phys_devs
= calloc(phys_dev_count
, sizeof(*instance
->phys_devs
));
557 if (!instance
->phys_devs
)
560 return VK_ERROR_OUT_OF_HOST_MEMORY
;
563 /* Wrap each native physical device handle into a dispatchable object for the ICD loader. */
564 for (i
= 0; i
< phys_dev_count
; i
++)
566 struct VkPhysicalDevice_T
*phys_dev
= wine_vk_physical_device_alloc(instance
, tmp_phys_devs
[i
]);
569 ERR("Unable to allocate memory for physical device!\n");
571 return VK_ERROR_OUT_OF_HOST_MEMORY
;
574 instance
->phys_devs
[i
] = phys_dev
;
575 instance
->phys_dev_count
= i
+ 1;
577 instance
->phys_dev_count
= phys_dev_count
;
583 static struct VkPhysicalDevice_T
*wine_vk_instance_wrap_physical_device(struct VkInstance_T
*instance
,
584 VkPhysicalDevice physical_device
)
588 for (i
= 0; i
< instance
->phys_dev_count
; ++i
)
590 struct VkPhysicalDevice_T
*current
= instance
->phys_devs
[i
];
591 if (current
->phys_dev
== physical_device
)
595 ERR("Unrecognized physical device %p.\n", physical_device
);
599 /* Helper function used for freeing an instance structure. This function supports full
600 * and partial object cleanups and can thus be used for vkCreateInstance failures.
602 static void wine_vk_instance_free(struct VkInstance_T
*instance
)
607 if (instance
->phys_devs
)
611 for (i
= 0; i
< instance
->phys_dev_count
; i
++)
613 wine_vk_physical_device_free(instance
->phys_devs
[i
]);
615 free(instance
->phys_devs
);
618 if (instance
->instance
)
620 vk_funcs
->p_vkDestroyInstance(instance
->instance
, NULL
/* allocator */);
621 WINE_VK_REMOVE_HANDLE_MAPPING(instance
, instance
);
624 pthread_rwlock_destroy(&instance
->wrapper_lock
);
625 free(instance
->utils_messengers
);
630 NTSTATUS
wine_vkAllocateCommandBuffers(void *args
)
632 struct vkAllocateCommandBuffers_params
*params
= args
;
633 VkDevice device
= params
->device
;
634 const VkCommandBufferAllocateInfo
*allocate_info
= params
->pAllocateInfo
;
635 VkCommandBuffer
*buffers
= params
->pCommandBuffers
;
636 struct wine_cmd_pool
*pool
;
637 VkResult res
= VK_SUCCESS
;
640 TRACE("%p, %p, %p\n", device
, allocate_info
, buffers
);
642 pool
= wine_cmd_pool_from_handle(allocate_info
->commandPool
);
644 memset(buffers
, 0, allocate_info
->commandBufferCount
* sizeof(*buffers
));
646 for (i
= 0; i
< allocate_info
->commandBufferCount
; i
++)
648 VkCommandBufferAllocateInfo_host allocate_info_host
;
650 /* TODO: future extensions (none yet) may require pNext conversion. */
651 allocate_info_host
.pNext
= allocate_info
->pNext
;
652 allocate_info_host
.sType
= allocate_info
->sType
;
653 allocate_info_host
.commandPool
= pool
->command_pool
;
654 allocate_info_host
.level
= allocate_info
->level
;
655 allocate_info_host
.commandBufferCount
= 1;
657 TRACE("Allocating command buffer %u from pool 0x%s.\n",
658 i
, wine_dbgstr_longlong(allocate_info_host
.commandPool
));
660 if (!(buffers
[i
] = calloc(1, sizeof(**buffers
))))
662 res
= VK_ERROR_OUT_OF_HOST_MEMORY
;
666 buffers
[i
]->base
.loader_magic
= VULKAN_ICD_MAGIC_VALUE
;
667 buffers
[i
]->device
= device
;
668 list_add_tail(&pool
->command_buffers
, &buffers
[i
]->pool_link
);
669 res
= device
->funcs
.p_vkAllocateCommandBuffers(device
->device
,
670 &allocate_info_host
, &buffers
[i
]->command_buffer
);
671 WINE_VK_ADD_DISPATCHABLE_MAPPING(device
->phys_dev
->instance
, buffers
[i
], buffers
[i
]->command_buffer
);
672 if (res
!= VK_SUCCESS
)
674 ERR("Failed to allocate command buffer, res=%d.\n", res
);
675 buffers
[i
]->command_buffer
= VK_NULL_HANDLE
;
680 if (res
!= VK_SUCCESS
)
682 wine_vk_free_command_buffers(device
, pool
, i
+ 1, buffers
);
683 memset(buffers
, 0, allocate_info
->commandBufferCount
* sizeof(*buffers
));
689 NTSTATUS
wine_vkCreateDevice(void *args
)
691 struct vkCreateDevice_params
*params
= args
;
692 VkPhysicalDevice phys_dev
= params
->physicalDevice
;
693 const VkDeviceCreateInfo
*create_info
= params
->pCreateInfo
;
694 const VkAllocationCallbacks
*allocator
= params
->pAllocator
;
695 VkDevice
*device
= params
->pDevice
;
696 VkDeviceCreateInfo create_info_host
;
697 struct VkQueue_T
*next_queue
;
698 struct VkDevice_T
*object
;
702 TRACE("%p, %p, %p, %p\n", phys_dev
, create_info
, allocator
, device
);
705 FIXME("Support for allocation callbacks not implemented yet\n");
707 if (TRACE_ON(vulkan
))
709 VkPhysicalDeviceProperties_host properties
;
711 phys_dev
->instance
->funcs
.p_vkGetPhysicalDeviceProperties(phys_dev
->phys_dev
, &properties
);
713 TRACE("Device name: %s.\n", debugstr_a(properties
.deviceName
));
714 TRACE("Vendor ID: %#x, Device ID: %#x.\n", properties
.vendorID
, properties
.deviceID
);
715 TRACE("Driver version: %#x.\n", properties
.driverVersion
);
718 if (!(object
= calloc(1, sizeof(*object
))))
719 return VK_ERROR_OUT_OF_HOST_MEMORY
;
721 object
->base
.base
.loader_magic
= VULKAN_ICD_MAGIC_VALUE
;
722 object
->phys_dev
= phys_dev
;
724 res
= wine_vk_device_convert_create_info(create_info
, &create_info_host
);
725 if (res
!= VK_SUCCESS
)
728 res
= phys_dev
->instance
->funcs
.p_vkCreateDevice(phys_dev
->phys_dev
,
729 &create_info_host
, NULL
/* allocator */, &object
->device
);
730 wine_vk_device_free_create_info(&create_info_host
);
731 WINE_VK_ADD_DISPATCHABLE_MAPPING(phys_dev
->instance
, object
, object
->device
);
732 if (res
!= VK_SUCCESS
)
734 WARN("Failed to create device, res=%d.\n", res
);
738 /* Just load all function pointers we are aware off. The loader takes care of filtering.
739 * We use vkGetDeviceProcAddr as opposed to vkGetInstanceProcAddr for efficiency reasons
740 * as functions pass through fewer dispatch tables within the loader.
742 #define USE_VK_FUNC(name) \
743 object->funcs.p_##name = (void *)vk_funcs->p_vkGetDeviceProcAddr(object->device, #name); \
744 if (object->funcs.p_##name == NULL) \
745 TRACE("Not found '%s'.\n", #name);
746 ALL_VK_DEVICE_FUNCS()
749 /* We need to cache all queues within the device as each requires wrapping since queues are
750 * dispatchable objects.
752 for (i
= 0; i
< create_info_host
.queueCreateInfoCount
; i
++)
754 object
->queue_count
+= create_info_host
.pQueueCreateInfos
[i
].queueCount
;
757 if (!(object
->queues
= calloc(object
->queue_count
, sizeof(*object
->queues
))))
759 res
= VK_ERROR_OUT_OF_HOST_MEMORY
;
763 next_queue
= object
->queues
;
764 for (i
= 0; i
< create_info_host
.queueCreateInfoCount
; i
++)
766 uint32_t flags
= create_info_host
.pQueueCreateInfos
[i
].flags
;
767 uint32_t family_index
= create_info_host
.pQueueCreateInfos
[i
].queueFamilyIndex
;
768 uint32_t queue_count
= create_info_host
.pQueueCreateInfos
[i
].queueCount
;
770 TRACE("Queue family index %u, queue count %u.\n", family_index
, queue_count
);
772 wine_vk_device_get_queues(object
, family_index
, queue_count
, flags
, next_queue
);
773 next_queue
+= queue_count
;
776 object
->base
.quirks
= phys_dev
->instance
->quirks
;
779 TRACE("Created device %p (native device %p).\n", object
, object
->device
);
783 wine_vk_device_free(object
);
787 NTSTATUS
wine_vkCreateInstance(void *args
)
789 struct vkCreateInstance_params
*params
= args
;
790 const VkInstanceCreateInfo
*create_info
= params
->pCreateInfo
;
791 const VkAllocationCallbacks
*allocator
= params
->pAllocator
;
792 VkInstance
*instance
= params
->pInstance
;
793 VkInstanceCreateInfo create_info_host
;
794 const VkApplicationInfo
*app_info
;
795 struct VkInstance_T
*object
;
799 FIXME("Support for allocation callbacks not implemented yet\n");
801 if (!(object
= calloc(1, sizeof(*object
))))
803 ERR("Failed to allocate memory for instance\n");
804 return VK_ERROR_OUT_OF_HOST_MEMORY
;
806 object
->base
.loader_magic
= VULKAN_ICD_MAGIC_VALUE
;
807 list_init(&object
->wrappers
);
808 pthread_rwlock_init(&object
->wrapper_lock
, NULL
);
810 res
= wine_vk_instance_convert_create_info(create_info
, &create_info_host
, object
);
811 if (res
!= VK_SUCCESS
)
813 wine_vk_instance_free(object
);
817 res
= vk_funcs
->p_vkCreateInstance(&create_info_host
, NULL
/* allocator */, &object
->instance
);
818 free_VkInstanceCreateInfo_struct_chain(&create_info_host
);
819 if (res
!= VK_SUCCESS
)
821 ERR("Failed to create instance, res=%d\n", res
);
822 wine_vk_instance_free(object
);
826 WINE_VK_ADD_DISPATCHABLE_MAPPING(object
, object
, object
->instance
);
828 /* Load all instance functions we are aware of. Note the loader takes care
829 * of any filtering for extensions which were not requested, but which the
832 #define USE_VK_FUNC(name) \
833 object->funcs.p_##name = (void *)vk_funcs->p_vkGetInstanceProcAddr(object->instance, #name);
834 ALL_VK_INSTANCE_FUNCS()
837 /* Cache physical devices for vkEnumeratePhysicalDevices within the instance as
838 * each vkPhysicalDevice is a dispatchable object, which means we need to wrap
839 * the native physical devices and present those to the application.
840 * Cleanup happens as part of wine_vkDestroyInstance.
842 res
= wine_vk_instance_load_physical_devices(object
);
843 if (res
!= VK_SUCCESS
)
845 ERR("Failed to load physical devices, res=%d\n", res
);
846 wine_vk_instance_free(object
);
850 if ((app_info
= create_info
->pApplicationInfo
))
852 TRACE("Application name %s, application version %#x.\n",
853 debugstr_a(app_info
->pApplicationName
), app_info
->applicationVersion
);
854 TRACE("Engine name %s, engine version %#x.\n", debugstr_a(app_info
->pEngineName
),
855 app_info
->engineVersion
);
856 TRACE("API version %#x.\n", app_info
->apiVersion
);
858 if (app_info
->pEngineName
&& !strcmp(app_info
->pEngineName
, "idTech"))
859 object
->quirks
|= WINEVULKAN_QUIRK_GET_DEVICE_PROC_ADDR
;
862 object
->quirks
|= WINEVULKAN_QUIRK_ADJUST_MAX_IMAGE_COUNT
;
865 TRACE("Created instance %p (native instance %p).\n", object
, object
->instance
);
869 NTSTATUS
wine_vkDestroyDevice(void *args
)
871 struct vkDestroyDevice_params
*params
= args
;
872 VkDevice device
= params
->device
;
873 const VkAllocationCallbacks
*allocator
= params
->pAllocator
;
875 TRACE("%p %p\n", device
, allocator
);
878 FIXME("Support for allocation callbacks not implemented yet\n");
880 wine_vk_device_free(device
);
881 return STATUS_SUCCESS
;
884 NTSTATUS
wine_vkDestroyInstance(void *args
)
886 struct vkDestroyInstance_params
*params
= args
;
887 VkInstance instance
= params
->instance
;
888 const VkAllocationCallbacks
*allocator
= params
->pAllocator
;
890 TRACE("%p, %p\n", instance
, allocator
);
893 FIXME("Support allocation allocators\n");
895 wine_vk_instance_free(instance
);
896 return STATUS_SUCCESS
;
899 NTSTATUS
wine_vkEnumerateDeviceExtensionProperties(void *args
)
901 struct vkEnumerateDeviceExtensionProperties_params
*params
= args
;
902 VkPhysicalDevice phys_dev
= params
->physicalDevice
;
903 const char *layer_name
= params
->pLayerName
;
904 uint32_t *count
= params
->pPropertyCount
;
905 VkExtensionProperties
*properties
= params
->pProperties
;
907 TRACE("%p, %p, %p, %p\n", phys_dev
, layer_name
, count
, properties
);
909 /* This shouldn't get called with layer_name set, the ICD loader prevents it. */
912 ERR("Layer enumeration not supported from ICD.\n");
913 return VK_ERROR_LAYER_NOT_PRESENT
;
918 *count
= phys_dev
->extension_count
;
922 *count
= min(*count
, phys_dev
->extension_count
);
923 memcpy(properties
, phys_dev
->extensions
, *count
* sizeof(*properties
));
925 TRACE("Returning %u extensions.\n", *count
);
926 return *count
< phys_dev
->extension_count
? VK_INCOMPLETE
: VK_SUCCESS
;
929 NTSTATUS
wine_vkEnumerateInstanceExtensionProperties(void *args
)
931 struct vkEnumerateInstanceExtensionProperties_params
*params
= args
;
932 uint32_t *count
= params
->pPropertyCount
;
933 VkExtensionProperties
*properties
= params
->pProperties
;
934 uint32_t num_properties
= 0, num_host_properties
;
935 VkExtensionProperties
*host_properties
;
939 res
= vk_funcs
->p_vkEnumerateInstanceExtensionProperties(NULL
, &num_host_properties
, NULL
);
940 if (res
!= VK_SUCCESS
)
943 if (!(host_properties
= calloc(num_host_properties
, sizeof(*host_properties
))))
944 return VK_ERROR_OUT_OF_HOST_MEMORY
;
946 res
= vk_funcs
->p_vkEnumerateInstanceExtensionProperties(NULL
, &num_host_properties
, host_properties
);
947 if (res
!= VK_SUCCESS
)
949 ERR("Failed to retrieve host properties, res=%d.\n", res
);
950 free(host_properties
);
954 /* The Wine graphics driver provides us with all extensions supported by the host side
955 * including extension fixup (e.g. VK_KHR_xlib_surface -> VK_KHR_win32_surface). It is
956 * up to us here to filter the list down to extensions for which we have thunks.
958 for (i
= 0; i
< num_host_properties
; i
++)
960 if (wine_vk_instance_extension_supported(host_properties
[i
].extensionName
))
963 TRACE("Instance extension '%s' is not supported.\n", host_properties
[i
].extensionName
);
968 TRACE("Returning %u extensions.\n", num_properties
);
969 *count
= num_properties
;
970 free(host_properties
);
974 for (i
= 0, j
= 0; i
< num_host_properties
&& j
< *count
; i
++)
976 if (wine_vk_instance_extension_supported(host_properties
[i
].extensionName
))
978 TRACE("Enabling extension '%s'.\n", host_properties
[i
].extensionName
);
979 properties
[j
++] = host_properties
[i
];
982 *count
= min(*count
, num_properties
);
984 free(host_properties
);
985 return *count
< num_properties
? VK_INCOMPLETE
: VK_SUCCESS
;
988 NTSTATUS
wine_vkEnumerateDeviceLayerProperties(void *args
)
990 struct vkEnumerateDeviceLayerProperties_params
*params
= args
;
991 uint32_t *count
= params
->pPropertyCount
;
993 TRACE("%p, %p, %p\n", params
->physicalDevice
, count
, params
->pProperties
);
999 NTSTATUS
wine_vkEnumerateInstanceVersion(void *args
)
1001 struct vkEnumerateInstanceVersion_params
*params
= args
;
1002 uint32_t *version
= params
->pApiVersion
;
1005 static VkResult (*p_vkEnumerateInstanceVersion
)(uint32_t *version
);
1006 if (!p_vkEnumerateInstanceVersion
)
1007 p_vkEnumerateInstanceVersion
= vk_funcs
->p_vkGetInstanceProcAddr(NULL
, "vkEnumerateInstanceVersion");
1009 if (p_vkEnumerateInstanceVersion
)
1011 res
= p_vkEnumerateInstanceVersion(version
);
1015 *version
= VK_API_VERSION_1_0
;
1019 TRACE("API version %u.%u.%u.\n",
1020 VK_VERSION_MAJOR(*version
), VK_VERSION_MINOR(*version
), VK_VERSION_PATCH(*version
));
1021 *version
= min(WINE_VK_VERSION
, *version
);
1025 NTSTATUS
wine_vkEnumeratePhysicalDevices(void *args
)
1027 struct vkEnumeratePhysicalDevices_params
*params
= args
;
1028 VkInstance instance
= params
->instance
;
1029 uint32_t *count
= params
->pPhysicalDeviceCount
;
1030 VkPhysicalDevice
*devices
= params
->pPhysicalDevices
;
1033 TRACE("%p %p %p\n", instance
, count
, devices
);
1037 *count
= instance
->phys_dev_count
;
1041 *count
= min(*count
, instance
->phys_dev_count
);
1042 for (i
= 0; i
< *count
; i
++)
1044 devices
[i
] = instance
->phys_devs
[i
];
1047 TRACE("Returning %u devices.\n", *count
);
1048 return *count
< instance
->phys_dev_count
? VK_INCOMPLETE
: VK_SUCCESS
;
1051 NTSTATUS
wine_vkFreeCommandBuffers(void *args
)
1053 struct vkFreeCommandBuffers_params
*params
= args
;
1054 VkDevice device
= params
->device
;
1055 struct wine_cmd_pool
*pool
= wine_cmd_pool_from_handle(params
->commandPool
);
1056 uint32_t count
= params
->commandBufferCount
;
1057 const VkCommandBuffer
*buffers
= params
->pCommandBuffers
;
1059 TRACE("%p, 0x%s, %u, %p\n", device
, wine_dbgstr_longlong(params
->commandPool
), count
, buffers
);
1061 wine_vk_free_command_buffers(device
, pool
, count
, buffers
);
1062 return STATUS_SUCCESS
;
1065 static VkQueue
wine_vk_device_find_queue(VkDevice device
, const VkDeviceQueueInfo2
*info
)
1067 struct VkQueue_T
* queue
;
1070 for (i
= 0; i
< device
->queue_count
; i
++)
1072 queue
= &device
->queues
[i
];
1073 if (queue
->family_index
== info
->queueFamilyIndex
1074 && queue
->queue_index
== info
->queueIndex
1075 && queue
->flags
== info
->flags
)
1081 return VK_NULL_HANDLE
;
1084 NTSTATUS
wine_vkGetDeviceQueue(void *args
)
1086 struct vkGetDeviceQueue_params
*params
= args
;
1087 VkDevice device
= params
->device
;
1088 uint32_t family_index
= params
->queueFamilyIndex
;
1089 uint32_t queue_index
= params
->queueIndex
;
1090 VkQueue
*queue
= params
->pQueue
;
1091 VkDeviceQueueInfo2 queue_info
;
1093 TRACE("%p, %u, %u, %p\n", device
, family_index
, queue_index
, queue
);
1095 queue_info
.sType
= VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2
;
1096 queue_info
.pNext
= NULL
;
1097 queue_info
.flags
= 0;
1098 queue_info
.queueFamilyIndex
= family_index
;
1099 queue_info
.queueIndex
= queue_index
;
1101 *queue
= wine_vk_device_find_queue(device
, &queue_info
);
1102 return STATUS_SUCCESS
;
1105 NTSTATUS
wine_vkGetDeviceQueue2(void *args
)
1107 struct vkGetDeviceQueue2_params
*params
= args
;
1108 VkDevice device
= params
->device
;
1109 const VkDeviceQueueInfo2
*info
= params
->pQueueInfo
;
1110 VkQueue
*queue
= params
->pQueue
;
1111 const VkBaseInStructure
*chain
;
1113 TRACE("%p, %p, %p\n", device
, info
, queue
);
1115 if ((chain
= info
->pNext
))
1116 FIXME("Ignoring a linked structure of type %u.\n", chain
->sType
);
1118 *queue
= wine_vk_device_find_queue(device
, info
);
1119 return STATUS_SUCCESS
;
1122 NTSTATUS
wine_vkCreateCommandPool(void *args
)
1124 struct vkCreateCommandPool_params
*params
= args
;
1125 VkDevice device
= params
->device
;
1126 const VkCommandPoolCreateInfo
*info
= params
->pCreateInfo
;
1127 const VkAllocationCallbacks
*allocator
= params
->pAllocator
;
1128 VkCommandPool
*command_pool
= params
->pCommandPool
;
1129 struct wine_cmd_pool
*object
;
1132 TRACE("%p, %p, %p, %p\n", device
, info
, allocator
, command_pool
);
1135 FIXME("Support for allocation callbacks not implemented yet\n");
1137 if (!(object
= calloc(1, sizeof(*object
))))
1138 return VK_ERROR_OUT_OF_HOST_MEMORY
;
1140 list_init(&object
->command_buffers
);
1142 res
= device
->funcs
.p_vkCreateCommandPool(device
->device
, info
, NULL
, &object
->command_pool
);
1144 if (res
== VK_SUCCESS
)
1146 WINE_VK_ADD_NON_DISPATCHABLE_MAPPING(device
->phys_dev
->instance
, object
, object
->command_pool
);
1147 *command_pool
= wine_cmd_pool_to_handle(object
);
1157 NTSTATUS
wine_vkDestroyCommandPool(void *args
)
1159 struct vkDestroyCommandPool_params
*params
= args
;
1160 VkDevice device
= params
->device
;
1161 VkCommandPool handle
= params
->commandPool
;
1162 const VkAllocationCallbacks
*allocator
= params
->pAllocator
;
1163 struct wine_cmd_pool
*pool
= wine_cmd_pool_from_handle(handle
);
1164 struct VkCommandBuffer_T
*buffer
, *cursor
;
1166 TRACE("%p, 0x%s, %p\n", device
, wine_dbgstr_longlong(handle
), allocator
);
1169 return STATUS_SUCCESS
;
1172 FIXME("Support for allocation callbacks not implemented yet\n");
1174 /* The Vulkan spec says:
1176 * "When a pool is destroyed, all command buffers allocated from the pool are freed."
1178 LIST_FOR_EACH_ENTRY_SAFE(buffer
, cursor
, &pool
->command_buffers
, struct VkCommandBuffer_T
, pool_link
)
1180 WINE_VK_REMOVE_HANDLE_MAPPING(device
->phys_dev
->instance
, buffer
);
1184 WINE_VK_REMOVE_HANDLE_MAPPING(device
->phys_dev
->instance
, pool
);
1186 device
->funcs
.p_vkDestroyCommandPool(device
->device
, pool
->command_pool
, NULL
);
1188 return STATUS_SUCCESS
;
1191 static VkResult
wine_vk_enumerate_physical_device_groups(struct VkInstance_T
*instance
,
1192 VkResult (*p_vkEnumeratePhysicalDeviceGroups
)(VkInstance
, uint32_t *, VkPhysicalDeviceGroupProperties
*),
1193 uint32_t *count
, VkPhysicalDeviceGroupProperties
*properties
)
1198 res
= p_vkEnumeratePhysicalDeviceGroups(instance
->instance
, count
, properties
);
1199 if (res
< 0 || !properties
)
1202 for (i
= 0; i
< *count
; ++i
)
1204 VkPhysicalDeviceGroupProperties
*current
= &properties
[i
];
1205 for (j
= 0; j
< current
->physicalDeviceCount
; ++j
)
1207 VkPhysicalDevice dev
= current
->physicalDevices
[j
];
1208 if (!(current
->physicalDevices
[j
] = wine_vk_instance_wrap_physical_device(instance
, dev
)))
1209 return VK_ERROR_INITIALIZATION_FAILED
;
1216 NTSTATUS
wine_vkEnumeratePhysicalDeviceGroups(void *args
)
1218 struct vkEnumeratePhysicalDeviceGroups_params
*params
= args
;
1219 VkInstance instance
= params
->instance
;
1220 uint32_t *count
= params
->pPhysicalDeviceGroupCount
;
1221 VkPhysicalDeviceGroupProperties
*properties
= params
->pPhysicalDeviceGroupProperties
;
1223 TRACE("%p, %p, %p\n", instance
, count
, properties
);
1224 return wine_vk_enumerate_physical_device_groups(instance
,
1225 instance
->funcs
.p_vkEnumeratePhysicalDeviceGroups
, count
, properties
);
1228 NTSTATUS
wine_vkEnumeratePhysicalDeviceGroupsKHR(void *args
)
1230 struct vkEnumeratePhysicalDeviceGroupsKHR_params
*params
= args
;
1231 VkInstance instance
= params
->instance
;
1232 uint32_t *count
= params
->pPhysicalDeviceGroupCount
;
1233 VkPhysicalDeviceGroupProperties
*properties
= params
->pPhysicalDeviceGroupProperties
;
1235 TRACE("%p, %p, %p\n", instance
, count
, properties
);
1236 return wine_vk_enumerate_physical_device_groups(instance
,
1237 instance
->funcs
.p_vkEnumeratePhysicalDeviceGroupsKHR
, count
, properties
);
1240 NTSTATUS
wine_vkGetPhysicalDeviceExternalFenceProperties(void *args
)
1242 struct vkGetPhysicalDeviceExternalFenceProperties_params
*params
= args
;
1243 VkPhysicalDevice phys_dev
= params
->physicalDevice
;
1244 const VkPhysicalDeviceExternalFenceInfo
*fence_info
= params
->pExternalFenceInfo
;
1245 VkExternalFenceProperties
*properties
= params
->pExternalFenceProperties
;
1247 TRACE("%p, %p, %p\n", phys_dev
, fence_info
, properties
);
1248 properties
->exportFromImportedHandleTypes
= 0;
1249 properties
->compatibleHandleTypes
= 0;
1250 properties
->externalFenceFeatures
= 0;
1251 return STATUS_SUCCESS
;
1254 NTSTATUS
wine_vkGetPhysicalDeviceExternalFencePropertiesKHR(void *args
)
1256 struct vkGetPhysicalDeviceExternalFencePropertiesKHR_params
*params
= args
;
1257 VkPhysicalDevice phys_dev
= params
->physicalDevice
;
1258 const VkPhysicalDeviceExternalFenceInfo
*fence_info
= params
->pExternalFenceInfo
;
1259 VkExternalFenceProperties
*properties
= params
->pExternalFenceProperties
;
1261 TRACE("%p, %p, %p\n", phys_dev
, fence_info
, properties
);
1262 properties
->exportFromImportedHandleTypes
= 0;
1263 properties
->compatibleHandleTypes
= 0;
1264 properties
->externalFenceFeatures
= 0;
1265 return STATUS_SUCCESS
;
1268 NTSTATUS
wine_vkGetPhysicalDeviceExternalBufferProperties(void *args
)
1270 struct vkGetPhysicalDeviceExternalBufferProperties_params
*params
= args
;
1271 VkPhysicalDevice phys_dev
= params
->physicalDevice
;
1272 const VkPhysicalDeviceExternalBufferInfo
*buffer_info
= params
->pExternalBufferInfo
;
1273 VkExternalBufferProperties
*properties
= params
->pExternalBufferProperties
;
1275 TRACE("%p, %p, %p\n", phys_dev
, buffer_info
, properties
);
1276 memset(&properties
->externalMemoryProperties
, 0, sizeof(properties
->externalMemoryProperties
));
1277 return STATUS_SUCCESS
;
1280 NTSTATUS
wine_vkGetPhysicalDeviceExternalBufferPropertiesKHR(void *args
)
1282 struct vkGetPhysicalDeviceExternalBufferPropertiesKHR_params
*params
= args
;
1283 VkPhysicalDevice phys_dev
= params
->physicalDevice
;
1284 const VkPhysicalDeviceExternalBufferInfo
*buffer_info
= params
->pExternalBufferInfo
;
1285 VkExternalBufferProperties
*properties
= params
->pExternalBufferProperties
;
1287 TRACE("%p, %p, %p\n", phys_dev
, buffer_info
, properties
);
1288 memset(&properties
->externalMemoryProperties
, 0, sizeof(properties
->externalMemoryProperties
));
1289 return STATUS_SUCCESS
;
1292 NTSTATUS
wine_vkGetPhysicalDeviceImageFormatProperties2(void *args
)
1294 struct vkGetPhysicalDeviceImageFormatProperties2_params
*params
= args
;
1295 VkPhysicalDevice phys_dev
= params
->physicalDevice
;
1296 const VkPhysicalDeviceImageFormatInfo2
*format_info
= params
->pImageFormatInfo
;
1297 VkImageFormatProperties2
*properties
= params
->pImageFormatProperties
;
1298 VkExternalImageFormatProperties
*external_image_properties
;
1301 TRACE("%p, %p, %p\n", phys_dev
, format_info
, properties
);
1303 res
= thunk_vkGetPhysicalDeviceImageFormatProperties2(phys_dev
, format_info
, properties
);
1305 if ((external_image_properties
= wine_vk_find_struct(properties
, EXTERNAL_IMAGE_FORMAT_PROPERTIES
)))
1307 VkExternalMemoryProperties
*p
= &external_image_properties
->externalMemoryProperties
;
1308 p
->externalMemoryFeatures
= 0;
1309 p
->exportFromImportedHandleTypes
= 0;
1310 p
->compatibleHandleTypes
= 0;
1316 NTSTATUS
wine_vkGetPhysicalDeviceImageFormatProperties2KHR(void *args
)
1318 struct vkGetPhysicalDeviceImageFormatProperties2KHR_params
*params
= args
;
1319 VkPhysicalDevice phys_dev
= params
->physicalDevice
;
1320 const VkPhysicalDeviceImageFormatInfo2
*format_info
= params
->pImageFormatInfo
;
1321 VkImageFormatProperties2
*properties
= params
->pImageFormatProperties
;
1322 VkExternalImageFormatProperties
*external_image_properties
;
1325 TRACE("%p, %p, %p\n", phys_dev
, format_info
, properties
);
1327 res
= thunk_vkGetPhysicalDeviceImageFormatProperties2KHR(phys_dev
, format_info
, properties
);
1329 if ((external_image_properties
= wine_vk_find_struct(properties
, EXTERNAL_IMAGE_FORMAT_PROPERTIES
)))
1331 VkExternalMemoryProperties
*p
= &external_image_properties
->externalMemoryProperties
;
1332 p
->externalMemoryFeatures
= 0;
1333 p
->exportFromImportedHandleTypes
= 0;
1334 p
->compatibleHandleTypes
= 0;
1340 /* From ntdll/unix/sync.c */
1341 #define NANOSECONDS_IN_A_SECOND 1000000000
1342 #define TICKSPERSEC 10000000
1344 static inline VkTimeDomainEXT
get_performance_counter_time_domain(void)
1346 #if !defined(__APPLE__) && defined(HAVE_CLOCK_GETTIME)
1347 # ifdef CLOCK_MONOTONIC_RAW
1348 return VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT
;
1350 return VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT
;
1353 FIXME("No mapping for VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT on this platform.\n");
1354 return VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT
;
1358 static VkTimeDomainEXT
map_to_host_time_domain(VkTimeDomainEXT domain
)
1360 /* Matches ntdll/unix/sync.c's performance counter implementation. */
1361 if (domain
== VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT
)
1362 return get_performance_counter_time_domain();
1367 static inline uint64_t convert_monotonic_timestamp(uint64_t value
)
1369 return value
/ (NANOSECONDS_IN_A_SECOND
/ TICKSPERSEC
);
1372 static inline uint64_t convert_timestamp(VkTimeDomainEXT host_domain
, VkTimeDomainEXT target_domain
, uint64_t value
)
1374 if (host_domain
== target_domain
)
1377 /* Convert between MONOTONIC time in ns -> QueryPerformanceCounter */
1378 if ((host_domain
== VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT
|| host_domain
== VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT
)
1379 && target_domain
== VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT
)
1380 return convert_monotonic_timestamp(value
);
1382 FIXME("Couldn't translate between host domain %d and target domain %d\n", host_domain
, target_domain
);
1386 NTSTATUS
wine_vkGetCalibratedTimestampsEXT(void *args
)
1388 struct vkGetCalibratedTimestampsEXT_params
*params
= args
;
1389 VkDevice device
= params
->device
;
1390 uint32_t timestamp_count
= params
->timestampCount
;
1391 const VkCalibratedTimestampInfoEXT
*timestamp_infos
= params
->pTimestampInfos
;
1392 uint64_t *timestamps
= params
->pTimestamps
;
1393 uint64_t *max_deviation
= params
->pMaxDeviation
;
1394 VkCalibratedTimestampInfoEXT
* host_timestamp_infos
;
1397 TRACE("%p, %u, %p, %p, %p\n", device
, timestamp_count
, timestamp_infos
, timestamps
, max_deviation
);
1399 if (!(host_timestamp_infos
= malloc(sizeof(VkCalibratedTimestampInfoEXT
) * timestamp_count
)))
1400 return VK_ERROR_OUT_OF_HOST_MEMORY
;
1402 for (i
= 0; i
< timestamp_count
; i
++)
1404 host_timestamp_infos
[i
].sType
= timestamp_infos
[i
].sType
;
1405 host_timestamp_infos
[i
].pNext
= timestamp_infos
[i
].pNext
;
1406 host_timestamp_infos
[i
].timeDomain
= map_to_host_time_domain(timestamp_infos
[i
].timeDomain
);
1409 res
= device
->funcs
.p_vkGetCalibratedTimestampsEXT(device
->device
, timestamp_count
, host_timestamp_infos
, timestamps
, max_deviation
);
1410 if (res
!= VK_SUCCESS
)
1413 for (i
= 0; i
< timestamp_count
; i
++)
1414 timestamps
[i
] = convert_timestamp(host_timestamp_infos
[i
].timeDomain
, timestamp_infos
[i
].timeDomain
, timestamps
[i
]);
1416 free(host_timestamp_infos
);
1421 NTSTATUS
wine_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT(void *args
)
1423 struct vkGetPhysicalDeviceCalibrateableTimeDomainsEXT_params
*params
= args
;
1424 VkPhysicalDevice phys_dev
= params
->physicalDevice
;
1425 uint32_t *time_domain_count
= params
->pTimeDomainCount
;
1426 VkTimeDomainEXT
*time_domains
= params
->pTimeDomains
;
1427 BOOL supports_device
= FALSE
, supports_monotonic
= FALSE
, supports_monotonic_raw
= FALSE
;
1428 const VkTimeDomainEXT performance_counter_domain
= get_performance_counter_time_domain();
1429 VkTimeDomainEXT
*host_time_domains
;
1430 uint32_t host_time_domain_count
;
1431 VkTimeDomainEXT out_time_domains
[2];
1432 uint32_t out_time_domain_count
;
1436 TRACE("%p, %p, %p\n", phys_dev
, time_domain_count
, time_domains
);
1438 /* Find out the time domains supported on the host */
1439 res
= phys_dev
->instance
->funcs
.p_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT(phys_dev
->phys_dev
, &host_time_domain_count
, NULL
);
1440 if (res
!= VK_SUCCESS
)
1443 if (!(host_time_domains
= malloc(sizeof(VkTimeDomainEXT
) * host_time_domain_count
)))
1444 return VK_ERROR_OUT_OF_HOST_MEMORY
;
1446 res
= phys_dev
->instance
->funcs
.p_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT(phys_dev
->phys_dev
, &host_time_domain_count
, host_time_domains
);
1447 if (res
!= VK_SUCCESS
)
1449 free(host_time_domains
);
1453 for (i
= 0; i
< host_time_domain_count
; i
++)
1455 if (host_time_domains
[i
] == VK_TIME_DOMAIN_DEVICE_EXT
)
1456 supports_device
= TRUE
;
1457 else if (host_time_domains
[i
] == VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT
)
1458 supports_monotonic
= TRUE
;
1459 else if (host_time_domains
[i
] == VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT
)
1460 supports_monotonic_raw
= TRUE
;
1462 FIXME("Unknown time domain %d\n", host_time_domains
[i
]);
1465 free(host_time_domains
);
1467 out_time_domain_count
= 0;
1469 /* Map our monotonic times -> QPC */
1470 if (supports_monotonic_raw
&& performance_counter_domain
== VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT
)
1471 out_time_domains
[out_time_domain_count
++] = VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT
;
1472 else if (supports_monotonic
&& performance_counter_domain
== VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT
)
1473 out_time_domains
[out_time_domain_count
++] = VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT
;
1475 FIXME("VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT not supported on this platform.\n");
1477 /* Forward the device domain time */
1478 if (supports_device
)
1479 out_time_domains
[out_time_domain_count
++] = VK_TIME_DOMAIN_DEVICE_EXT
;
1481 /* Send the count/domains back to the app */
1484 *time_domain_count
= out_time_domain_count
;
1488 for (i
= 0; i
< min(*time_domain_count
, out_time_domain_count
); i
++)
1489 time_domains
[i
] = out_time_domains
[i
];
1491 res
= *time_domain_count
< out_time_domain_count
? VK_INCOMPLETE
: VK_SUCCESS
;
1492 *time_domain_count
= out_time_domain_count
;
1496 NTSTATUS
wine_vkGetPhysicalDeviceExternalSemaphoreProperties(void *args
)
1498 struct vkGetPhysicalDeviceExternalSemaphoreProperties_params
*params
= args
;
1499 VkPhysicalDevice phys_dev
= params
->physicalDevice
;
1500 const VkPhysicalDeviceExternalSemaphoreInfo
*semaphore_info
= params
->pExternalSemaphoreInfo
;
1501 VkExternalSemaphoreProperties
*properties
= params
->pExternalSemaphoreProperties
;
1503 TRACE("%p, %p, %p\n", phys_dev
, semaphore_info
, properties
);
1504 properties
->exportFromImportedHandleTypes
= 0;
1505 properties
->compatibleHandleTypes
= 0;
1506 properties
->externalSemaphoreFeatures
= 0;
1507 return STATUS_SUCCESS
;
1510 NTSTATUS
wine_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR(void *args
)
1512 struct vkGetPhysicalDeviceExternalSemaphorePropertiesKHR_params
*params
= args
;
1513 VkPhysicalDevice phys_dev
= params
->physicalDevice
;
1514 const VkPhysicalDeviceExternalSemaphoreInfo
*semaphore_info
= params
->pExternalSemaphoreInfo
;
1515 VkExternalSemaphoreProperties
*properties
= params
->pExternalSemaphoreProperties
;
1517 TRACE("%p, %p, %p\n", phys_dev
, semaphore_info
, properties
);
1518 properties
->exportFromImportedHandleTypes
= 0;
1519 properties
->compatibleHandleTypes
= 0;
1520 properties
->externalSemaphoreFeatures
= 0;
1521 return STATUS_SUCCESS
;
1524 NTSTATUS
wine_vkCreateWin32SurfaceKHR(void *args
)
1526 struct vkCreateWin32SurfaceKHR_params
*params
= args
;
1527 VkInstance instance
= params
->instance
;
1528 const VkWin32SurfaceCreateInfoKHR
*createInfo
= params
->pCreateInfo
;
1529 const VkAllocationCallbacks
*allocator
= params
->pAllocator
;
1530 VkSurfaceKHR
*surface
= params
->pSurface
;
1531 struct wine_surface
*object
;
1534 TRACE("%p, %p, %p, %p\n", instance
, createInfo
, allocator
, surface
);
1537 FIXME("Support for allocation callbacks not implemented yet\n");
1539 object
= calloc(1, sizeof(*object
));
1542 return VK_ERROR_OUT_OF_HOST_MEMORY
;
1544 res
= instance
->funcs
.p_vkCreateWin32SurfaceKHR(instance
->instance
, createInfo
, NULL
, &object
->driver_surface
);
1546 if (res
!= VK_SUCCESS
)
1552 object
->surface
= vk_funcs
->p_wine_get_native_surface(object
->driver_surface
);
1554 WINE_VK_ADD_NON_DISPATCHABLE_MAPPING(instance
, object
, object
->surface
);
1556 *surface
= wine_surface_to_handle(object
);
1561 NTSTATUS
wine_vkDestroySurfaceKHR(void *args
)
1563 struct vkDestroySurfaceKHR_params
*params
= args
;
1564 VkInstance instance
= params
->instance
;
1565 VkSurfaceKHR surface
= params
->surface
;
1566 const VkAllocationCallbacks
*allocator
= params
->pAllocator
;
1567 struct wine_surface
*object
= wine_surface_from_handle(surface
);
1569 TRACE("%p, 0x%s, %p\n", instance
, wine_dbgstr_longlong(surface
), allocator
);
1572 return STATUS_SUCCESS
;
1574 instance
->funcs
.p_vkDestroySurfaceKHR(instance
->instance
, object
->driver_surface
, NULL
);
1576 WINE_VK_REMOVE_HANDLE_MAPPING(instance
, object
);
1578 return STATUS_SUCCESS
;
1581 static inline void adjust_max_image_count(VkPhysicalDevice phys_dev
, VkSurfaceCapabilitiesKHR
* capabilities
)
1583 /* Many Windows games, for example Strange Brigade, No Man's Sky, Path of Exile
1584 * and World War Z, do not expect that maxImageCount can be set to 0.
1585 * A value of 0 means that there is no limit on the number of images.
1586 * Nvidia reports 8 on Windows, AMD 16.
1587 * https://vulkan.gpuinfo.org/displayreport.php?id=9122#surface
1588 * https://vulkan.gpuinfo.org/displayreport.php?id=9121#surface
1590 if ((phys_dev
->instance
->quirks
& WINEVULKAN_QUIRK_ADJUST_MAX_IMAGE_COUNT
) && !capabilities
->maxImageCount
)
1592 capabilities
->maxImageCount
= max(capabilities
->minImageCount
, 16);
1596 NTSTATUS
wine_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(void *args
)
1598 struct vkGetPhysicalDeviceSurfaceCapabilitiesKHR_params
*params
= args
;
1599 VkPhysicalDevice phys_dev
= params
->physicalDevice
;
1600 VkSurfaceKHR surface
= params
->surface
;
1601 VkSurfaceCapabilitiesKHR
*capabilities
= params
->pSurfaceCapabilities
;
1604 TRACE("%p, 0x%s, %p\n", phys_dev
, wine_dbgstr_longlong(surface
), capabilities
);
1606 res
= thunk_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(phys_dev
, surface
, capabilities
);
1608 if (res
== VK_SUCCESS
)
1609 adjust_max_image_count(phys_dev
, capabilities
);
1614 NTSTATUS
wine_vkGetPhysicalDeviceSurfaceCapabilities2KHR(void *args
)
1616 struct vkGetPhysicalDeviceSurfaceCapabilities2KHR_params
*params
= args
;
1617 VkPhysicalDevice phys_dev
= params
->physicalDevice
;
1618 const VkPhysicalDeviceSurfaceInfo2KHR
*surface_info
= params
->pSurfaceInfo
;
1619 VkSurfaceCapabilities2KHR
*capabilities
= params
->pSurfaceCapabilities
;
1622 TRACE("%p, %p, %p\n", phys_dev
, surface_info
, capabilities
);
1624 res
= thunk_vkGetPhysicalDeviceSurfaceCapabilities2KHR(phys_dev
, surface_info
, capabilities
);
1626 if (res
== VK_SUCCESS
)
1627 adjust_max_image_count(phys_dev
, &capabilities
->surfaceCapabilities
);
1632 NTSTATUS
wine_vkCreateDebugUtilsMessengerEXT(void *args
)
1634 struct vkCreateDebugUtilsMessengerEXT_params
*params
= args
;
1635 VkInstance instance
= params
->instance
;
1636 const VkDebugUtilsMessengerCreateInfoEXT
*create_info
= params
->pCreateInfo
;
1637 const VkAllocationCallbacks
*allocator
= params
->pAllocator
;
1638 VkDebugUtilsMessengerEXT
*messenger
= params
->pMessenger
;
1639 VkDebugUtilsMessengerCreateInfoEXT wine_create_info
;
1640 struct wine_debug_utils_messenger
*object
;
1643 TRACE("%p, %p, %p, %p\n", instance
, create_info
, allocator
, messenger
);
1646 FIXME("Support for allocation callbacks not implemented yet\n");
1648 if (!(object
= calloc(1, sizeof(*object
))))
1649 return VK_ERROR_OUT_OF_HOST_MEMORY
;
1651 object
->instance
= instance
;
1652 object
->user_callback
= create_info
->pfnUserCallback
;
1653 object
->user_data
= create_info
->pUserData
;
1655 wine_create_info
= *create_info
;
1657 wine_create_info
.pfnUserCallback
= (void *) &debug_utils_callback_conversion
;
1658 wine_create_info
.pUserData
= object
;
1660 res
= instance
->funcs
.p_vkCreateDebugUtilsMessengerEXT(instance
->instance
, &wine_create_info
, NULL
, &object
->debug_messenger
);
1662 if (res
!= VK_SUCCESS
)
1668 WINE_VK_ADD_NON_DISPATCHABLE_MAPPING(instance
, object
, object
->debug_messenger
);
1669 *messenger
= wine_debug_utils_messenger_to_handle(object
);
1674 NTSTATUS
wine_vkDestroyDebugUtilsMessengerEXT(void *args
)
1676 struct vkDestroyDebugUtilsMessengerEXT_params
*params
= args
;
1677 VkInstance instance
= params
->instance
;
1678 VkDebugUtilsMessengerEXT messenger
= params
->messenger
;
1679 const VkAllocationCallbacks
*allocator
= params
->pAllocator
;
1680 struct wine_debug_utils_messenger
*object
;
1682 TRACE("%p, 0x%s, %p\n", instance
, wine_dbgstr_longlong(messenger
), allocator
);
1684 object
= wine_debug_utils_messenger_from_handle(messenger
);
1687 return STATUS_SUCCESS
;
1689 instance
->funcs
.p_vkDestroyDebugUtilsMessengerEXT(instance
->instance
, object
->debug_messenger
, NULL
);
1690 WINE_VK_REMOVE_HANDLE_MAPPING(instance
, object
);
1693 return STATUS_SUCCESS
;
1696 NTSTATUS
wine_vkCreateDebugReportCallbackEXT(void *args
)
1698 struct vkCreateDebugReportCallbackEXT_params
*params
= args
;
1699 VkInstance instance
= params
->instance
;
1700 const VkDebugReportCallbackCreateInfoEXT
*create_info
= params
->pCreateInfo
;
1701 const VkAllocationCallbacks
*allocator
= params
->pAllocator
;
1702 VkDebugReportCallbackEXT
*callback
= params
->pCallback
;
1703 VkDebugReportCallbackCreateInfoEXT wine_create_info
;
1704 struct wine_debug_report_callback
*object
;
1707 TRACE("%p, %p, %p, %p\n", instance
, create_info
, allocator
, callback
);
1710 FIXME("Support for allocation callbacks not implemented yet\n");
1712 if (!(object
= calloc(1, sizeof(*object
))))
1713 return VK_ERROR_OUT_OF_HOST_MEMORY
;
1715 object
->instance
= instance
;
1716 object
->user_callback
= create_info
->pfnCallback
;
1717 object
->user_data
= create_info
->pUserData
;
1719 wine_create_info
= *create_info
;
1721 wine_create_info
.pfnCallback
= (void *) debug_report_callback_conversion
;
1722 wine_create_info
.pUserData
= object
;
1724 res
= instance
->funcs
.p_vkCreateDebugReportCallbackEXT(instance
->instance
, &wine_create_info
, NULL
, &object
->debug_callback
);
1726 if (res
!= VK_SUCCESS
)
1732 WINE_VK_ADD_NON_DISPATCHABLE_MAPPING(instance
, object
, object
->debug_callback
);
1733 *callback
= wine_debug_report_callback_to_handle(object
);
1738 NTSTATUS
wine_vkDestroyDebugReportCallbackEXT(void *args
)
1740 struct vkDestroyDebugReportCallbackEXT_params
*params
= args
;
1741 VkInstance instance
= params
->instance
;
1742 VkDebugReportCallbackEXT callback
= params
->callback
;
1743 const VkAllocationCallbacks
*allocator
= params
->pAllocator
;
1744 struct wine_debug_report_callback
*object
;
1746 TRACE("%p, 0x%s, %p\n", instance
, wine_dbgstr_longlong(callback
), allocator
);
1748 object
= wine_debug_report_callback_from_handle(callback
);
1751 return STATUS_SUCCESS
;
1753 instance
->funcs
.p_vkDestroyDebugReportCallbackEXT(instance
->instance
, object
->debug_callback
, NULL
);
1755 WINE_VK_REMOVE_HANDLE_MAPPING(instance
, object
);
1758 return STATUS_SUCCESS
;
1761 static void fixup_pipeline_feedback(VkPipelineCreationFeedback
*feedback
, uint32_t count
)
1763 #if defined(USE_STRUCT_CONVERSION)
1764 struct host_pipeline_feedback
1766 VkPipelineCreationFeedbackFlags flags
;
1771 host_feedback
= (void *) feedback
;
1773 for (i
= count
- 1; i
>= 0; i
--)
1775 memmove(&feedback
[i
].duration
, &host_feedback
[i
].duration
, sizeof(uint64_t));
1776 feedback
[i
].flags
= host_feedback
[i
].flags
;
1781 static void fixup_pipeline_feedback_info(const void *pipeline_info
)
1783 VkPipelineCreationFeedbackCreateInfo
*feedback
;
1785 feedback
= wine_vk_find_struct(pipeline_info
, PIPELINE_CREATION_FEEDBACK_CREATE_INFO
);
1790 fixup_pipeline_feedback(feedback
->pPipelineCreationFeedback
, 1);
1791 fixup_pipeline_feedback(feedback
->pPipelineStageCreationFeedbacks
,
1792 feedback
->pipelineStageCreationFeedbackCount
);
1795 NTSTATUS
wine_vkCreateComputePipelines(void *args
)
1797 struct vkCreateComputePipelines_params
*params
= args
;
1801 TRACE("%p, 0x%s, %u, %p, %p, %p\n", params
->device
, wine_dbgstr_longlong(params
->pipelineCache
),
1802 params
->createInfoCount
, params
->pCreateInfos
, params
->pAllocator
, params
->pPipelines
);
1804 res
= thunk_vkCreateComputePipelines(params
->device
, params
->pipelineCache
,
1805 params
->createInfoCount
, params
->pCreateInfos
, params
->pAllocator
, params
->pPipelines
);
1807 for (i
= 0; i
< params
->createInfoCount
; i
++)
1808 fixup_pipeline_feedback_info(¶ms
->pCreateInfos
[i
]);
1813 NTSTATUS
wine_vkCreateGraphicsPipelines(void *args
)
1815 struct vkCreateGraphicsPipelines_params
*params
= args
;
1819 TRACE("%p, 0x%s, %u, %p, %p, %p\n", params
->device
, wine_dbgstr_longlong(params
->pipelineCache
),
1820 params
->createInfoCount
, params
->pCreateInfos
, params
->pAllocator
, params
->pPipelines
);
1822 res
= thunk_vkCreateGraphicsPipelines(params
->device
, params
->pipelineCache
,
1823 params
->createInfoCount
, params
->pCreateInfos
, params
->pAllocator
, params
->pPipelines
);
1825 for (i
= 0; i
< params
->createInfoCount
; i
++)
1826 fixup_pipeline_feedback_info(¶ms
->pCreateInfos
[i
]);
1831 NTSTATUS
wine_vkCreateRayTracingPipelinesKHR(void *args
)
1833 struct vkCreateRayTracingPipelinesKHR_params
*params
= args
;
1837 TRACE("%p, 0x%s, 0x%s, %u, %p, %p, %p\n", params
->device
,
1838 wine_dbgstr_longlong(params
->deferredOperation
), wine_dbgstr_longlong(params
->pipelineCache
),
1839 params
->createInfoCount
, params
->pCreateInfos
, params
->pAllocator
, params
->pPipelines
);
1841 res
= thunk_vkCreateRayTracingPipelinesKHR(params
->device
, params
->deferredOperation
, params
->pipelineCache
,
1842 params
->createInfoCount
, params
->pCreateInfos
, params
->pAllocator
, params
->pPipelines
);
1844 for (i
= 0; i
< params
->createInfoCount
; i
++)
1845 fixup_pipeline_feedback_info(¶ms
->pCreateInfos
[i
]);
1850 NTSTATUS
wine_vkCreateRayTracingPipelinesNV(void *args
)
1852 struct vkCreateRayTracingPipelinesNV_params
*params
= args
;
1856 TRACE("%p, 0x%s, %u, %p, %p, %p\n", params
->device
, wine_dbgstr_longlong(params
->pipelineCache
),
1857 params
->createInfoCount
, params
->pCreateInfos
, params
->pAllocator
, params
->pPipelines
);
1859 res
= thunk_vkCreateRayTracingPipelinesNV(params
->device
, params
->pipelineCache
,
1860 params
->createInfoCount
, params
->pCreateInfos
, params
->pAllocator
, params
->pPipelines
);
1862 for (i
= 0; i
< params
->createInfoCount
; i
++)
1863 fixup_pipeline_feedback_info(¶ms
->pCreateInfos
[i
]);
1868 BOOL WINAPI
wine_vk_is_available_instance_function(VkInstance instance
, const char *name
)
1870 return !!vk_funcs
->p_vkGetInstanceProcAddr(instance
->instance
, name
);
1873 BOOL WINAPI
wine_vk_is_available_device_function(VkDevice device
, const char *name
)
1875 return !!vk_funcs
->p_vkGetDeviceProcAddr(device
->device
, name
);