1 /* Mac Driver Vulkan implementation
3 * Copyright 2017 Roderick Colenbrander
4 * Copyright 2018 Andrew Eikum for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 /* NOTE: If making changes here, consider whether they should be reflected in
22 * the other drivers. */
31 #include "wine/debug.h"
32 #include "wine/heap.h"
34 #define VK_NO_PROTOTYPES
37 #include "wine/vulkan.h"
38 #include "wine/vulkan_driver.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(vulkan
);
42 #ifdef SONAME_LIBMOLTENVK
44 WINE_DECLARE_DEBUG_CHANNEL(fps
);
46 typedef VkFlags VkMacOSSurfaceCreateFlagsMVK
;
47 #define VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK 1000123000
49 typedef VkFlags VkMetalSurfaceCreateFlagsEXT
;
50 #define VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT 1000217000
52 struct wine_vk_surface
54 macdrv_metal_device device
;
55 macdrv_metal_view view
;
56 VkSurfaceKHR surface
; /* native surface */
59 typedef struct VkMacOSSurfaceCreateInfoMVK
61 VkStructureType sType
;
63 VkMacOSSurfaceCreateFlagsMVK flags
;
64 const void *pView
; /* NSView */
65 } VkMacOSSurfaceCreateInfoMVK
;
67 typedef struct VkMetalSurfaceCreateInfoEXT
69 VkStructureType sType
;
71 VkMetalSurfaceCreateFlagsEXT flags
;
72 const void *pLayer
; /* CAMetalLayer */
73 } VkMetalSurfaceCreateInfoEXT
;
75 static VkResult (*pvkCreateInstance
)(const VkInstanceCreateInfo
*, const VkAllocationCallbacks
*, VkInstance
*);
76 static VkResult (*pvkCreateSwapchainKHR
)(VkDevice
, const VkSwapchainCreateInfoKHR
*, const VkAllocationCallbacks
*, VkSwapchainKHR
*);
77 static VkResult (*pvkCreateMacOSSurfaceMVK
)(VkInstance
, const VkMacOSSurfaceCreateInfoMVK
*, const VkAllocationCallbacks
*, VkSurfaceKHR
*);
78 static VkResult (*pvkCreateMetalSurfaceEXT
)(VkInstance
, const VkMetalSurfaceCreateInfoEXT
*, const VkAllocationCallbacks
*, VkSurfaceKHR
*);
79 static void (*pvkDestroyInstance
)(VkInstance
, const VkAllocationCallbacks
*);
80 static void (*pvkDestroySurfaceKHR
)(VkInstance
, VkSurfaceKHR
, const VkAllocationCallbacks
*);
81 static void (*pvkDestroySwapchainKHR
)(VkDevice
, VkSwapchainKHR
, const VkAllocationCallbacks
*);
82 static VkResult (*pvkEnumerateInstanceExtensionProperties
)(const char *, uint32_t *, VkExtensionProperties
*);
83 static void * (*pvkGetDeviceProcAddr
)(VkDevice
, const char *);
84 static void * (*pvkGetInstanceProcAddr
)(VkInstance
, const char *);
85 static VkResult (*pvkGetPhysicalDeviceSurfaceCapabilities2KHR
)(VkPhysicalDevice
, const VkPhysicalDeviceSurfaceInfo2KHR
*, VkSurfaceCapabilities2KHR
*);
86 static VkResult (*pvkGetPhysicalDeviceSurfaceCapabilitiesKHR
)(VkPhysicalDevice
, VkSurfaceKHR
, VkSurfaceCapabilitiesKHR
*);
87 static VkResult (*pvkGetPhysicalDeviceSurfaceFormats2KHR
)(VkPhysicalDevice
, const VkPhysicalDeviceSurfaceInfo2KHR
*, uint32_t *, VkSurfaceFormat2KHR
*);
88 static VkResult (*pvkGetPhysicalDeviceSurfaceFormatsKHR
)(VkPhysicalDevice
, VkSurfaceKHR
, uint32_t *, VkSurfaceFormatKHR
*);
89 static VkResult (*pvkGetPhysicalDeviceSurfacePresentModesKHR
)(VkPhysicalDevice
, VkSurfaceKHR
, uint32_t *, VkPresentModeKHR
*);
90 static VkResult (*pvkGetPhysicalDeviceSurfaceSupportKHR
)(VkPhysicalDevice
, uint32_t, VkSurfaceKHR
, VkBool32
*);
91 static VkResult (*pvkGetSwapchainImagesKHR
)(VkDevice
, VkSwapchainKHR
, uint32_t *, VkImage
*);
92 static VkResult (*pvkQueuePresentKHR
)(VkQueue
, const VkPresentInfoKHR
*);
94 static void *macdrv_get_vk_device_proc_addr(const char *name
);
95 static void *macdrv_get_vk_instance_proc_addr(VkInstance instance
, const char *name
);
97 static inline struct wine_vk_surface
*surface_from_handle(VkSurfaceKHR handle
)
99 return (struct wine_vk_surface
*)(uintptr_t)handle
;
102 static void *vulkan_handle
;
104 static BOOL WINAPI
wine_vk_init(INIT_ONCE
*once
, void *param
, void **context
)
106 if (!(vulkan_handle
= dlopen(SONAME_LIBMOLTENVK
, RTLD_NOW
)))
108 ERR("Failed to load %s\n", SONAME_LIBMOLTENVK
);
112 #define LOAD_FUNCPTR(f) if ((p##f = dlsym(vulkan_handle, #f)) == NULL) goto fail;
113 LOAD_FUNCPTR(vkCreateInstance
)
114 LOAD_FUNCPTR(vkCreateSwapchainKHR
)
115 LOAD_FUNCPTR(vkCreateMacOSSurfaceMVK
)
116 LOAD_FUNCPTR(vkCreateMetalSurfaceEXT
)
117 LOAD_FUNCPTR(vkDestroyInstance
)
118 LOAD_FUNCPTR(vkDestroySurfaceKHR
)
119 LOAD_FUNCPTR(vkDestroySwapchainKHR
)
120 LOAD_FUNCPTR(vkEnumerateInstanceExtensionProperties
)
121 LOAD_FUNCPTR(vkGetDeviceProcAddr
)
122 LOAD_FUNCPTR(vkGetInstanceProcAddr
)
123 LOAD_FUNCPTR(vkGetPhysicalDeviceSurfaceCapabilities2KHR
)
124 LOAD_FUNCPTR(vkGetPhysicalDeviceSurfaceCapabilitiesKHR
)
125 LOAD_FUNCPTR(vkGetPhysicalDeviceSurfaceFormats2KHR
)
126 LOAD_FUNCPTR(vkGetPhysicalDeviceSurfaceFormatsKHR
)
127 LOAD_FUNCPTR(vkGetPhysicalDeviceSurfacePresentModesKHR
)
128 LOAD_FUNCPTR(vkGetPhysicalDeviceSurfaceSupportKHR
)
129 LOAD_FUNCPTR(vkGetSwapchainImagesKHR
)
130 LOAD_FUNCPTR(vkQueuePresentKHR
)
136 dlclose(vulkan_handle
);
137 vulkan_handle
= NULL
;
141 /* Helper function for converting between win32 and MoltenVK compatible VkInstanceCreateInfo.
142 * Caller is responsible for allocation and cleanup of 'dst'.
144 static VkResult
wine_vk_instance_convert_create_info(const VkInstanceCreateInfo
*src
,
145 VkInstanceCreateInfo
*dst
)
148 const char **enabled_extensions
= NULL
;
150 dst
->sType
= src
->sType
;
151 dst
->flags
= src
->flags
;
152 dst
->pApplicationInfo
= src
->pApplicationInfo
;
153 dst
->pNext
= src
->pNext
;
154 dst
->enabledLayerCount
= 0;
155 dst
->ppEnabledLayerNames
= NULL
;
156 dst
->enabledExtensionCount
= 0;
157 dst
->ppEnabledExtensionNames
= NULL
;
159 if (src
->enabledExtensionCount
> 0)
161 enabled_extensions
= heap_calloc(src
->enabledExtensionCount
, sizeof(*src
->ppEnabledExtensionNames
));
162 if (!enabled_extensions
)
164 ERR("Failed to allocate memory for enabled extensions\n");
165 return VK_ERROR_OUT_OF_HOST_MEMORY
;
168 for (i
= 0; i
< src
->enabledExtensionCount
; i
++)
170 /* Substitute extension with MoltenVK ones else copy. Long-term, when we
171 * support more extensions, we should store these in a list.
173 if (!strcmp(src
->ppEnabledExtensionNames
[i
], "VK_KHR_win32_surface"))
175 enabled_extensions
[i
] = pvkCreateMetalSurfaceEXT
? "VK_EXT_metal_surface" : "VK_MVK_macos_surface";
179 enabled_extensions
[i
] = src
->ppEnabledExtensionNames
[i
];
182 dst
->ppEnabledExtensionNames
= enabled_extensions
;
183 dst
->enabledExtensionCount
= src
->enabledExtensionCount
;
189 static void wine_vk_surface_destroy(VkInstance instance
, struct wine_vk_surface
*surface
)
191 /* vkDestroySurfaceKHR must handle VK_NULL_HANDLE (0) for surface. */
195 pvkDestroySurfaceKHR(instance
, surface
->surface
, NULL
/* allocator */);
198 macdrv_view_release_metal_view(surface
->view
);
201 macdrv_release_metal_device(surface
->device
);
206 static VkResult
macdrv_vkCreateInstance(const VkInstanceCreateInfo
*create_info
,
207 const VkAllocationCallbacks
*allocator
, VkInstance
*instance
)
209 VkInstanceCreateInfo create_info_host
;
211 TRACE("create_info %p, allocator %p, instance %p\n", create_info
, allocator
, instance
);
214 FIXME("Support for allocation callbacks not implemented yet\n");
216 /* Perform a second pass on converting VkInstanceCreateInfo. Winevulkan
217 * performed a first pass in which it handles everything except for WSI
218 * functionality such as VK_KHR_win32_surface. Handle this now.
220 res
= wine_vk_instance_convert_create_info(create_info
, &create_info_host
);
221 if (res
!= VK_SUCCESS
)
223 ERR("Failed to convert instance create info, res=%d\n", res
);
227 res
= pvkCreateInstance(&create_info_host
, NULL
/* allocator */, instance
);
229 heap_free((void *)create_info_host
.ppEnabledExtensionNames
);
233 static VkResult
macdrv_vkCreateSwapchainKHR(VkDevice device
,
234 const VkSwapchainCreateInfoKHR
*create_info
,
235 const VkAllocationCallbacks
*allocator
, VkSwapchainKHR
*swapchain
)
237 VkSwapchainCreateInfoKHR create_info_host
;
238 TRACE("%p %p %p %p\n", device
, create_info
, allocator
, swapchain
);
241 FIXME("Support for allocation callbacks not implemented yet\n");
243 create_info_host
= *create_info
;
244 create_info_host
.surface
= surface_from_handle(create_info
->surface
)->surface
;
246 return pvkCreateSwapchainKHR(device
, &create_info_host
, NULL
/* allocator */,
250 static VkResult
macdrv_vkCreateWin32SurfaceKHR(VkInstance instance
,
251 const VkWin32SurfaceCreateInfoKHR
*create_info
,
252 const VkAllocationCallbacks
*allocator
, VkSurfaceKHR
*surface
)
255 struct wine_vk_surface
*mac_surface
;
256 struct macdrv_win_data
*data
;
258 TRACE("%p %p %p %p\n", instance
, create_info
, allocator
, surface
);
261 FIXME("Support for allocation callbacks not implemented yet\n");
263 if (!(data
= get_win_data(create_info
->hwnd
)))
265 FIXME("DC for window %p of other process: not implemented\n", create_info
->hwnd
);
266 return VK_ERROR_INCOMPATIBLE_DRIVER
;
269 mac_surface
= heap_alloc_zero(sizeof(*mac_surface
));
272 release_win_data(data
);
273 return VK_ERROR_OUT_OF_HOST_MEMORY
;
276 mac_surface
->device
= macdrv_create_metal_device();
277 if (!mac_surface
->device
)
279 ERR("Failed to allocate Metal device for hwnd=%p\n", create_info
->hwnd
);
280 res
= VK_ERROR_OUT_OF_HOST_MEMORY
;
284 mac_surface
->view
= macdrv_view_create_metal_view(data
->client_cocoa_view
, mac_surface
->device
);
285 if (!mac_surface
->view
)
287 ERR("Failed to allocate Metal view for hwnd=%p\n", create_info
->hwnd
);
289 /* VK_KHR_win32_surface only allows out of host and device memory as errors. */
290 res
= VK_ERROR_OUT_OF_HOST_MEMORY
;
294 if (pvkCreateMetalSurfaceEXT
)
296 VkMetalSurfaceCreateInfoEXT create_info_host
;
297 create_info_host
.sType
= VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT
;
298 create_info_host
.pNext
= NULL
;
299 create_info_host
.flags
= 0; /* reserved */
300 create_info_host
.pLayer
= macdrv_view_get_metal_layer(mac_surface
->view
);
302 res
= pvkCreateMetalSurfaceEXT(instance
, &create_info_host
, NULL
/* allocator */, &mac_surface
->surface
);
306 VkMacOSSurfaceCreateInfoMVK create_info_host
;
307 create_info_host
.sType
= VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK
;
308 create_info_host
.pNext
= NULL
;
309 create_info_host
.flags
= 0; /* reserved */
310 create_info_host
.pView
= macdrv_view_get_metal_layer(mac_surface
->view
);
312 res
= pvkCreateMacOSSurfaceMVK(instance
, &create_info_host
, NULL
/* allocator */, &mac_surface
->surface
);
314 if (res
!= VK_SUCCESS
)
316 ERR("Failed to create MoltenVK surface, res=%d\n", res
);
320 *surface
= (uintptr_t)mac_surface
;
322 release_win_data(data
);
324 TRACE("Created surface=0x%s\n", wine_dbgstr_longlong(*surface
));
328 wine_vk_surface_destroy(instance
, mac_surface
);
329 release_win_data(data
);
333 static void macdrv_vkDestroyInstance(VkInstance instance
, const VkAllocationCallbacks
*allocator
)
335 TRACE("%p %p\n", instance
, allocator
);
338 FIXME("Support for allocation callbacks not implemented yet\n");
340 pvkDestroyInstance(instance
, NULL
/* allocator */);
343 static void macdrv_vkDestroySurfaceKHR(VkInstance instance
, VkSurfaceKHR surface
,
344 const VkAllocationCallbacks
*allocator
)
346 struct wine_vk_surface
*mac_surface
= surface_from_handle(surface
);
348 TRACE("%p 0x%s %p\n", instance
, wine_dbgstr_longlong(surface
), allocator
);
351 FIXME("Support for allocation callbacks not implemented yet\n");
353 wine_vk_surface_destroy(instance
, mac_surface
);
356 static void macdrv_vkDestroySwapchainKHR(VkDevice device
, VkSwapchainKHR swapchain
,
357 const VkAllocationCallbacks
*allocator
)
359 TRACE("%p, 0x%s %p\n", device
, wine_dbgstr_longlong(swapchain
), allocator
);
362 FIXME("Support for allocation callbacks not implemented yet\n");
364 pvkDestroySwapchainKHR(device
, swapchain
, NULL
/* allocator */);
367 static VkResult
macdrv_vkEnumerateInstanceExtensionProperties(const char *layer_name
,
368 uint32_t *count
, VkExtensionProperties
* properties
)
371 BOOL seen_surface
= FALSE
;
374 TRACE("layer_name %s, count %p, properties %p\n", debugstr_a(layer_name
), count
, properties
);
376 /* This shouldn't get called with layer_name set, the ICD loader prevents it. */
379 ERR("Layer enumeration not supported from ICD.\n");
380 return VK_ERROR_LAYER_NOT_PRESENT
;
383 /* We will return at most the same number of instance extensions reported by the host back to
384 * winevulkan. Along the way we may replace MoltenVK extensions with their win32 equivalents,
385 * or remove redundant extensions outright.
386 * Winevulkan will perform more detailed filtering as it knows whether it has thunks
387 * for a particular extension.
389 res
= pvkEnumerateInstanceExtensionProperties(layer_name
, count
, properties
);
390 if (!properties
|| res
< 0)
393 for (i
= 0; i
< *count
; i
++)
395 /* For now the only MoltenVK extensions we need to fixup. Long-term we may need an array. */
396 if (!strcmp(properties
[i
].extensionName
, "VK_MVK_macos_surface") ||
397 !strcmp(properties
[i
].extensionName
, "VK_EXT_metal_surface"))
401 /* If we've already seen a surface extension, just hide this one. */
402 memmove(properties
+ i
, properties
+ i
+ 1, (*count
- i
- 1) * sizeof(*properties
));
407 TRACE("Substituting %s for VK_KHR_win32_surface\n", properties
[i
].extensionName
);
409 snprintf(properties
[i
].extensionName
, sizeof(properties
[i
].extensionName
),
410 VK_KHR_WIN32_SURFACE_EXTENSION_NAME
);
411 properties
[i
].specVersion
= VK_KHR_WIN32_SURFACE_SPEC_VERSION
;
416 TRACE("Returning %u extensions.\n", *count
);
420 static const char *wine_vk_native_fn_name(const char *name
)
422 const char *create_surface_name
=
423 pvkCreateMetalSurfaceEXT
? "vkCreateMetalSurfaceEXT" : "vkCreateMacOSSurfaceMVK";
425 if (!strcmp(name
, "vkCreateWin32SurfaceKHR"))
426 return create_surface_name
;
427 /* We just need something where non-NULL is returned if the correct extension is enabled.
428 * So since there is no native equivalent of this function check for the create
431 if (!strcmp(name
, "vkGetPhysicalDeviceWin32PresentationSupportKHR"))
432 return create_surface_name
;
437 static void *macdrv_vkGetDeviceProcAddr(VkDevice device
, const char *name
)
441 TRACE("%p, %s\n", device
, debugstr_a(name
));
443 if (!pvkGetDeviceProcAddr(device
, wine_vk_native_fn_name(name
)))
446 if ((proc_addr
= macdrv_get_vk_device_proc_addr(name
)))
449 return pvkGetDeviceProcAddr(device
, name
);
452 static void *macdrv_vkGetInstanceProcAddr(VkInstance instance
, const char *name
)
456 TRACE("%p, %s\n", instance
, debugstr_a(name
));
458 if (!pvkGetInstanceProcAddr(instance
, wine_vk_native_fn_name(name
)))
461 if ((proc_addr
= macdrv_get_vk_instance_proc_addr(instance
, name
)))
464 return pvkGetInstanceProcAddr(instance
, name
);
467 static VkResult
macdrv_vkGetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice phys_dev
,
468 const VkPhysicalDeviceSurfaceInfo2KHR
*surface_info
, VkSurfaceCapabilities2KHR
*capabilities
)
470 VkPhysicalDeviceSurfaceInfo2KHR surface_info_host
;
472 TRACE("%p, %p, %p\n", phys_dev
, surface_info
, capabilities
);
474 surface_info_host
= *surface_info
;
475 surface_info_host
.surface
= surface_from_handle(surface_info
->surface
)->surface
;
477 return pvkGetPhysicalDeviceSurfaceCapabilities2KHR(phys_dev
, &surface_info_host
, capabilities
);
480 static VkResult
macdrv_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice phys_dev
,
481 VkSurfaceKHR surface
, VkSurfaceCapabilitiesKHR
*capabilities
)
483 struct wine_vk_surface
*mac_surface
= surface_from_handle(surface
);
485 TRACE("%p, 0x%s, %p\n", phys_dev
, wine_dbgstr_longlong(surface
), capabilities
);
487 return pvkGetPhysicalDeviceSurfaceCapabilitiesKHR(phys_dev
, mac_surface
->surface
,
491 static VkResult
macdrv_vkGetPhysicalDeviceSurfaceFormats2KHR(VkPhysicalDevice phys_dev
,
492 const VkPhysicalDeviceSurfaceInfo2KHR
*surface_info
, uint32_t *count
, VkSurfaceFormat2KHR
*formats
)
494 VkPhysicalDeviceSurfaceInfo2KHR surface_info_host
;
496 TRACE("%p, %p, %p, %p\n", phys_dev
, surface_info
, count
, formats
);
498 surface_info_host
= *surface_info
;
499 surface_info_host
.surface
= surface_from_handle(surface_info
->surface
)->surface
;
501 return pvkGetPhysicalDeviceSurfaceFormats2KHR(phys_dev
, &surface_info_host
, count
, formats
);
504 static VkResult
macdrv_vkGetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice phys_dev
,
505 VkSurfaceKHR surface
, uint32_t *count
, VkSurfaceFormatKHR
*formats
)
507 struct wine_vk_surface
*mac_surface
= surface_from_handle(surface
);
509 TRACE("%p, 0x%s, %p, %p\n", phys_dev
, wine_dbgstr_longlong(surface
), count
, formats
);
511 return pvkGetPhysicalDeviceSurfaceFormatsKHR(phys_dev
, mac_surface
->surface
,
515 static VkResult
macdrv_vkGetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice phys_dev
,
516 VkSurfaceKHR surface
, uint32_t *count
, VkPresentModeKHR
*modes
)
518 struct wine_vk_surface
*mac_surface
= surface_from_handle(surface
);
520 TRACE("%p, 0x%s, %p, %p\n", phys_dev
, wine_dbgstr_longlong(surface
), count
, modes
);
522 return pvkGetPhysicalDeviceSurfacePresentModesKHR(phys_dev
, mac_surface
->surface
, count
,
526 static VkResult
macdrv_vkGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice phys_dev
,
527 uint32_t index
, VkSurfaceKHR surface
, VkBool32
*supported
)
529 struct wine_vk_surface
*mac_surface
= surface_from_handle(surface
);
531 TRACE("%p, %u, 0x%s, %p\n", phys_dev
, index
, wine_dbgstr_longlong(surface
), supported
);
533 return pvkGetPhysicalDeviceSurfaceSupportKHR(phys_dev
, index
, mac_surface
->surface
,
537 static VkBool32
macdrv_vkGetPhysicalDeviceWin32PresentationSupportKHR(VkPhysicalDevice phys_dev
,
540 TRACE("%p %u\n", phys_dev
, index
);
545 static VkResult
macdrv_vkGetSwapchainImagesKHR(VkDevice device
,
546 VkSwapchainKHR swapchain
, uint32_t *count
, VkImage
*images
)
548 TRACE("%p, 0x%s %p %p\n", device
, wine_dbgstr_longlong(swapchain
), count
, images
);
549 return pvkGetSwapchainImagesKHR(device
, swapchain
, count
, images
);
552 static VkResult
macdrv_vkQueuePresentKHR(VkQueue queue
, const VkPresentInfoKHR
*present_info
)
554 TRACE("%p, %p\n", queue
, present_info
);
555 VkResult res
= pvkQueuePresentKHR(queue
, present_info
);
559 static unsigned long frames
, frames_total
;
560 static long prev_time
, start_time
;
563 time
= GetTickCount();
566 if (time
- prev_time
> 1500)
568 TRACE_(fps
)("%p @ approx %.2ffps, total %.2ffps\n",
569 queue
, 1000.0 * frames
/ (time
- prev_time
),
570 1000.0 * frames_total
/ (time
- start_time
));
581 static VkSurfaceKHR
macdrv_wine_get_native_surface(VkSurfaceKHR surface
)
583 struct wine_vk_surface
*mac_surface
= surface_from_handle(surface
);
585 TRACE("0x%s\n", wine_dbgstr_longlong(surface
));
587 return mac_surface
->surface
;
590 static const struct vulkan_funcs vulkan_funcs
=
592 macdrv_vkCreateInstance
,
593 macdrv_vkCreateSwapchainKHR
,
594 macdrv_vkCreateWin32SurfaceKHR
,
595 macdrv_vkDestroyInstance
,
596 macdrv_vkDestroySurfaceKHR
,
597 macdrv_vkDestroySwapchainKHR
,
598 macdrv_vkEnumerateInstanceExtensionProperties
,
600 macdrv_vkGetDeviceProcAddr
,
601 macdrv_vkGetInstanceProcAddr
,
603 macdrv_vkGetPhysicalDeviceSurfaceCapabilities2KHR
,
604 macdrv_vkGetPhysicalDeviceSurfaceCapabilitiesKHR
,
605 macdrv_vkGetPhysicalDeviceSurfaceFormats2KHR
,
606 macdrv_vkGetPhysicalDeviceSurfaceFormatsKHR
,
607 macdrv_vkGetPhysicalDeviceSurfacePresentModesKHR
,
608 macdrv_vkGetPhysicalDeviceSurfaceSupportKHR
,
609 macdrv_vkGetPhysicalDeviceWin32PresentationSupportKHR
,
610 macdrv_vkGetSwapchainImagesKHR
,
611 macdrv_vkQueuePresentKHR
,
613 macdrv_wine_get_native_surface
,
616 static void *macdrv_get_vk_device_proc_addr(const char *name
)
618 return get_vulkan_driver_device_proc_addr(&vulkan_funcs
, name
);
621 static void *macdrv_get_vk_instance_proc_addr(VkInstance instance
, const char *name
)
623 return get_vulkan_driver_instance_proc_addr(&vulkan_funcs
, instance
, name
);
626 static const struct vulkan_funcs
*get_vulkan_driver(UINT version
)
628 static INIT_ONCE init_once
= INIT_ONCE_STATIC_INIT
;
630 if (version
!= WINE_VULKAN_DRIVER_VERSION
)
632 ERR("version mismatch, vulkan wants %u but driver has %u\n", version
, WINE_VULKAN_DRIVER_VERSION
);
636 InitOnceExecuteOnce(&init_once
, wine_vk_init
, NULL
, NULL
);
638 return &vulkan_funcs
;
643 #else /* No vulkan */
645 static const struct vulkan_funcs
*get_vulkan_driver(UINT version
)
647 ERR("Wine was built without Vulkan support.\n");
651 #endif /* SONAME_LIBMOLTENVK */
653 const struct vulkan_funcs
* CDECL
macdrv_wine_get_vulkan_driver(UINT version
)
655 return get_vulkan_driver( version
);