mfplat: Read queue subscriber within the critical section.
[wine/zf.git] / dlls / winex11.drv / vulkan.c
blob139faf6b407cb5e227ad6485a4f91d0bae9ef526
1 /* X11DRV Vulkan 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
20 /* NOTE: If making changes here, consider whether they should be reflected in
21 * the other drivers. */
23 #include "config.h"
24 #include "wine/port.h"
26 #include <stdarg.h>
27 #include <stdio.h>
29 #include "windef.h"
30 #include "winbase.h"
32 #include "wine/debug.h"
33 #include "wine/heap.h"
34 #include "x11drv.h"
36 #define VK_NO_PROTOTYPES
37 #define WINE_VK_HOST
39 #include "wine/vulkan.h"
40 #include "wine/vulkan_driver.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(vulkan);
44 #ifdef SONAME_LIBVULKAN
45 WINE_DECLARE_DEBUG_CHANNEL(fps);
47 static CRITICAL_SECTION context_section;
48 static CRITICAL_SECTION_DEBUG critsect_debug =
50 0, 0, &context_section,
51 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
52 0, 0, { (DWORD_PTR)(__FILE__ ": context_section") }
54 static CRITICAL_SECTION context_section = { &critsect_debug, -1, 0, 0, 0, 0 };
56 static XContext vulkan_hwnd_context;
58 #define VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR 1000004000
60 struct wine_vk_surface
62 LONG ref;
63 Window window;
64 VkSurfaceKHR surface; /* native surface */
67 typedef struct VkXlibSurfaceCreateInfoKHR
69 VkStructureType sType;
70 const void *pNext;
71 VkXlibSurfaceCreateFlagsKHR flags;
72 Display *dpy;
73 Window window;
74 } VkXlibSurfaceCreateInfoKHR;
76 static VkResult (*pvkCreateInstance)(const VkInstanceCreateInfo *, const VkAllocationCallbacks *, VkInstance *);
77 static VkResult (*pvkCreateSwapchainKHR)(VkDevice, const VkSwapchainCreateInfoKHR *, const VkAllocationCallbacks *, VkSwapchainKHR *);
78 static VkResult (*pvkCreateXlibSurfaceKHR)(VkInstance, const VkXlibSurfaceCreateInfoKHR *, 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 VkResult (*pvkGetDeviceGroupSurfacePresentModesKHR)(VkDevice, VkSurfaceKHR, VkDeviceGroupPresentModeFlagsKHR *);
84 static void * (*pvkGetDeviceProcAddr)(VkDevice, const char *);
85 static void * (*pvkGetInstanceProcAddr)(VkInstance, const char *);
86 static VkResult (*pvkGetPhysicalDevicePresentRectanglesKHR)(VkPhysicalDevice, VkSurfaceKHR, uint32_t *, VkRect2D *);
87 static VkResult (*pvkGetPhysicalDeviceSurfaceCapabilities2KHR)(VkPhysicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR *, VkSurfaceCapabilities2KHR *);
88 static VkResult (*pvkGetPhysicalDeviceSurfaceCapabilitiesKHR)(VkPhysicalDevice, VkSurfaceKHR, VkSurfaceCapabilitiesKHR *);
89 static VkResult (*pvkGetPhysicalDeviceSurfaceFormats2KHR)(VkPhysicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR *, uint32_t *, VkSurfaceFormat2KHR *);
90 static VkResult (*pvkGetPhysicalDeviceSurfaceFormatsKHR)(VkPhysicalDevice, VkSurfaceKHR, uint32_t *, VkSurfaceFormatKHR *);
91 static VkResult (*pvkGetPhysicalDeviceSurfacePresentModesKHR)(VkPhysicalDevice, VkSurfaceKHR, uint32_t *, VkPresentModeKHR *);
92 static VkResult (*pvkGetPhysicalDeviceSurfaceSupportKHR)(VkPhysicalDevice, uint32_t, VkSurfaceKHR, VkBool32 *);
93 static VkBool32 (*pvkGetPhysicalDeviceXlibPresentationSupportKHR)(VkPhysicalDevice, uint32_t, Display *, VisualID);
94 static VkResult (*pvkGetSwapchainImagesKHR)(VkDevice, VkSwapchainKHR, uint32_t *, VkImage *);
95 static VkResult (*pvkQueuePresentKHR)(VkQueue, const VkPresentInfoKHR *);
97 static void *X11DRV_get_vk_device_proc_addr(const char *name);
98 static void *X11DRV_get_vk_instance_proc_addr(VkInstance instance, const char *name);
100 static inline struct wine_vk_surface *surface_from_handle(VkSurfaceKHR handle)
102 return (struct wine_vk_surface *)(uintptr_t)handle;
105 static void *vulkan_handle;
107 static BOOL WINAPI wine_vk_init(INIT_ONCE *once, void *param, void **context)
109 if (!(vulkan_handle = dlopen(SONAME_LIBVULKAN, RTLD_NOW)))
111 ERR("Failed to load %s.\n", SONAME_LIBVULKAN);
112 return TRUE;
115 #define LOAD_FUNCPTR(f) if (!(p##f = dlsym(vulkan_handle, #f))) goto fail
116 #define LOAD_OPTIONAL_FUNCPTR(f) p##f = dlsym(vulkan_handle, #f)
117 LOAD_FUNCPTR(vkCreateInstance);
118 LOAD_FUNCPTR(vkCreateSwapchainKHR);
119 LOAD_FUNCPTR(vkCreateXlibSurfaceKHR);
120 LOAD_FUNCPTR(vkDestroyInstance);
121 LOAD_FUNCPTR(vkDestroySurfaceKHR);
122 LOAD_FUNCPTR(vkDestroySwapchainKHR);
123 LOAD_FUNCPTR(vkEnumerateInstanceExtensionProperties);
124 LOAD_FUNCPTR(vkGetDeviceProcAddr);
125 LOAD_FUNCPTR(vkGetInstanceProcAddr);
126 LOAD_OPTIONAL_FUNCPTR(vkGetPhysicalDeviceSurfaceCapabilities2KHR);
127 LOAD_FUNCPTR(vkGetPhysicalDeviceSurfaceCapabilitiesKHR);
128 LOAD_OPTIONAL_FUNCPTR(vkGetPhysicalDeviceSurfaceFormats2KHR);
129 LOAD_FUNCPTR(vkGetPhysicalDeviceSurfaceFormatsKHR);
130 LOAD_FUNCPTR(vkGetPhysicalDeviceSurfacePresentModesKHR);
131 LOAD_FUNCPTR(vkGetPhysicalDeviceSurfaceSupportKHR);
132 LOAD_FUNCPTR(vkGetPhysicalDeviceXlibPresentationSupportKHR);
133 LOAD_FUNCPTR(vkGetSwapchainImagesKHR);
134 LOAD_FUNCPTR(vkQueuePresentKHR);
135 LOAD_OPTIONAL_FUNCPTR(vkGetDeviceGroupSurfacePresentModesKHR);
136 LOAD_OPTIONAL_FUNCPTR(vkGetPhysicalDevicePresentRectanglesKHR);
137 #undef LOAD_FUNCPTR
138 #undef LOAD_OPTIONAL_FUNCPTR
140 vulkan_hwnd_context = XUniqueContext();
142 return TRUE;
144 fail:
145 dlclose(vulkan_handle);
146 vulkan_handle = NULL;
147 return TRUE;
150 /* Helper function for converting between win32 and X11 compatible VkInstanceCreateInfo.
151 * Caller is responsible for allocation and cleanup of 'dst'.
153 static VkResult wine_vk_instance_convert_create_info(const VkInstanceCreateInfo *src,
154 VkInstanceCreateInfo *dst)
156 unsigned int i;
157 const char **enabled_extensions = NULL;
159 dst->sType = src->sType;
160 dst->flags = src->flags;
161 dst->pApplicationInfo = src->pApplicationInfo;
162 dst->pNext = src->pNext;
163 dst->enabledLayerCount = 0;
164 dst->ppEnabledLayerNames = NULL;
165 dst->enabledExtensionCount = 0;
166 dst->ppEnabledExtensionNames = NULL;
168 if (src->enabledExtensionCount > 0)
170 enabled_extensions = heap_calloc(src->enabledExtensionCount, sizeof(*src->ppEnabledExtensionNames));
171 if (!enabled_extensions)
173 ERR("Failed to allocate memory for enabled extensions\n");
174 return VK_ERROR_OUT_OF_HOST_MEMORY;
177 for (i = 0; i < src->enabledExtensionCount; i++)
179 /* Substitute extension with X11 ones else copy. Long-term, when we
180 * support more extensions, we should store these in a list.
182 if (!strcmp(src->ppEnabledExtensionNames[i], "VK_KHR_win32_surface"))
184 enabled_extensions[i] = "VK_KHR_xlib_surface";
186 else
188 enabled_extensions[i] = src->ppEnabledExtensionNames[i];
191 dst->ppEnabledExtensionNames = enabled_extensions;
192 dst->enabledExtensionCount = src->enabledExtensionCount;
195 return VK_SUCCESS;
198 static struct wine_vk_surface *wine_vk_surface_grab(struct wine_vk_surface *surface)
200 InterlockedIncrement(&surface->ref);
201 return surface;
204 static void wine_vk_surface_release(struct wine_vk_surface *surface)
206 if (InterlockedDecrement(&surface->ref))
207 return;
209 if (surface->window)
210 XDestroyWindow(gdi_display, surface->window);
212 heap_free(surface);
215 void wine_vk_surface_destroy(HWND hwnd)
217 struct wine_vk_surface *surface;
218 EnterCriticalSection(&context_section);
219 if (!XFindContext(gdi_display, (XID)hwnd, vulkan_hwnd_context, (char **)&surface))
221 wine_vk_surface_release(surface);
223 XDeleteContext(gdi_display, (XID)hwnd, vulkan_hwnd_context);
224 LeaveCriticalSection(&context_section);
227 static VkResult X11DRV_vkCreateInstance(const VkInstanceCreateInfo *create_info,
228 const VkAllocationCallbacks *allocator, VkInstance *instance)
230 VkInstanceCreateInfo create_info_host;
231 VkResult res;
232 TRACE("create_info %p, allocator %p, instance %p\n", create_info, allocator, instance);
234 if (allocator)
235 FIXME("Support for allocation callbacks not implemented yet\n");
237 /* Perform a second pass on converting VkInstanceCreateInfo. Winevulkan
238 * performed a first pass in which it handles everything except for WSI
239 * functionality such as VK_KHR_win32_surface. Handle this now.
241 res = wine_vk_instance_convert_create_info(create_info, &create_info_host);
242 if (res != VK_SUCCESS)
244 ERR("Failed to convert instance create info, res=%d\n", res);
245 return res;
248 res = pvkCreateInstance(&create_info_host, NULL /* allocator */, instance);
250 heap_free((void *)create_info_host.ppEnabledExtensionNames);
251 return res;
254 static VkResult X11DRV_vkCreateSwapchainKHR(VkDevice device,
255 const VkSwapchainCreateInfoKHR *create_info,
256 const VkAllocationCallbacks *allocator, VkSwapchainKHR *swapchain)
258 VkSwapchainCreateInfoKHR create_info_host;
259 TRACE("%p %p %p %p\n", device, create_info, allocator, swapchain);
261 if (allocator)
262 FIXME("Support for allocation callbacks not implemented yet\n");
264 create_info_host = *create_info;
265 create_info_host.surface = surface_from_handle(create_info->surface)->surface;
267 return pvkCreateSwapchainKHR(device, &create_info_host, NULL /* allocator */, swapchain);
270 static VkResult X11DRV_vkCreateWin32SurfaceKHR(VkInstance instance,
271 const VkWin32SurfaceCreateInfoKHR *create_info,
272 const VkAllocationCallbacks *allocator, VkSurfaceKHR *surface)
274 VkResult res;
275 VkXlibSurfaceCreateInfoKHR create_info_host;
276 struct wine_vk_surface *x11_surface, *prev;
278 TRACE("%p %p %p %p\n", instance, create_info, allocator, surface);
280 if (allocator)
281 FIXME("Support for allocation callbacks not implemented yet\n");
283 /* TODO: support child window rendering. */
284 if (GetAncestor(create_info->hwnd, GA_PARENT) != GetDesktopWindow())
286 FIXME("Application requires child window rendering, which is not implemented yet!\n");
287 return VK_ERROR_INCOMPATIBLE_DRIVER;
290 x11_surface = heap_alloc_zero(sizeof(*x11_surface));
291 if (!x11_surface)
292 return VK_ERROR_OUT_OF_HOST_MEMORY;
294 x11_surface->ref = 1;
296 x11_surface->window = create_client_window(create_info->hwnd, &default_visual);
297 if (!x11_surface->window)
299 ERR("Failed to allocate client window for hwnd=%p\n", create_info->hwnd);
301 /* VK_KHR_win32_surface only allows out of host and device memory as errors. */
302 res = VK_ERROR_OUT_OF_HOST_MEMORY;
303 goto err;
306 create_info_host.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
307 create_info_host.pNext = NULL;
308 create_info_host.flags = 0; /* reserved */
309 create_info_host.dpy = gdi_display;
310 create_info_host.window = x11_surface->window;
312 res = pvkCreateXlibSurfaceKHR(instance, &create_info_host, NULL /* allocator */, &x11_surface->surface);
313 if (res != VK_SUCCESS)
315 ERR("Failed to create Xlib surface, res=%d\n", res);
316 goto err;
319 EnterCriticalSection(&context_section);
320 if (!XFindContext(gdi_display, (XID)create_info->hwnd, vulkan_hwnd_context, (char **)&prev))
322 wine_vk_surface_release(prev);
324 XSaveContext(gdi_display, (XID)create_info->hwnd, vulkan_hwnd_context, (char *)wine_vk_surface_grab(x11_surface));
325 LeaveCriticalSection(&context_section);
327 *surface = (uintptr_t)x11_surface;
329 TRACE("Created surface=0x%s\n", wine_dbgstr_longlong(*surface));
330 return VK_SUCCESS;
332 err:
333 wine_vk_surface_release(x11_surface);
334 return res;
337 static void X11DRV_vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks *allocator)
339 TRACE("%p %p\n", instance, allocator);
341 if (allocator)
342 FIXME("Support for allocation callbacks not implemented yet\n");
344 pvkDestroyInstance(instance, NULL /* allocator */);
347 static void X11DRV_vkDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface,
348 const VkAllocationCallbacks *allocator)
350 struct wine_vk_surface *x11_surface = surface_from_handle(surface);
352 TRACE("%p 0x%s %p\n", instance, wine_dbgstr_longlong(surface), allocator);
354 if (allocator)
355 FIXME("Support for allocation callbacks not implemented yet\n");
357 /* vkDestroySurfaceKHR must handle VK_NULL_HANDLE (0) for surface. */
358 if (x11_surface)
360 pvkDestroySurfaceKHR(instance, x11_surface->surface, NULL /* allocator */);
362 wine_vk_surface_release(x11_surface);
366 static void X11DRV_vkDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain,
367 const VkAllocationCallbacks *allocator)
369 TRACE("%p, 0x%s %p\n", device, wine_dbgstr_longlong(swapchain), allocator);
371 if (allocator)
372 FIXME("Support for allocation callbacks not implemented yet\n");
374 pvkDestroySwapchainKHR(device, swapchain, NULL /* allocator */);
377 static VkResult X11DRV_vkEnumerateInstanceExtensionProperties(const char *layer_name,
378 uint32_t *count, VkExtensionProperties* properties)
380 unsigned int i;
381 VkResult res;
383 TRACE("layer_name %s, count %p, properties %p\n", debugstr_a(layer_name), count, properties);
385 /* This shouldn't get called with layer_name set, the ICD loader prevents it. */
386 if (layer_name)
388 ERR("Layer enumeration not supported from ICD.\n");
389 return VK_ERROR_LAYER_NOT_PRESENT;
392 /* We will return the same number of instance extensions reported by the host back to
393 * winevulkan. Along the way we may replace xlib extensions with their win32 equivalents.
394 * Winevulkan will perform more detailed filtering as it knows whether it has thunks
395 * for a particular extension.
397 res = pvkEnumerateInstanceExtensionProperties(layer_name, count, properties);
398 if (!properties || res < 0)
399 return res;
401 for (i = 0; i < *count; i++)
403 /* For now the only x11 extension we need to fixup. Long-term we may need an array. */
404 if (!strcmp(properties[i].extensionName, "VK_KHR_xlib_surface"))
406 TRACE("Substituting VK_KHR_xlib_surface for VK_KHR_win32_surface\n");
408 snprintf(properties[i].extensionName, sizeof(properties[i].extensionName),
409 VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
410 properties[i].specVersion = VK_KHR_WIN32_SURFACE_SPEC_VERSION;
414 TRACE("Returning %u extensions.\n", *count);
415 return res;
418 static VkResult X11DRV_vkGetDeviceGroupSurfacePresentModesKHR(VkDevice device,
419 VkSurfaceKHR surface, VkDeviceGroupPresentModeFlagsKHR *flags)
421 struct wine_vk_surface *x11_surface = surface_from_handle(surface);
423 TRACE("%p, 0x%s, %p\n", device, wine_dbgstr_longlong(surface), flags);
425 return pvkGetDeviceGroupSurfacePresentModesKHR(device, x11_surface->surface, flags);
428 static void *X11DRV_vkGetDeviceProcAddr(VkDevice device, const char *name)
430 void *proc_addr;
432 TRACE("%p, %s\n", device, debugstr_a(name));
434 if ((proc_addr = X11DRV_get_vk_device_proc_addr(name)))
435 return proc_addr;
437 return pvkGetDeviceProcAddr(device, name);
440 static void *X11DRV_vkGetInstanceProcAddr(VkInstance instance, const char *name)
442 void *proc_addr;
444 TRACE("%p, %s\n", instance, debugstr_a(name));
446 if ((proc_addr = X11DRV_get_vk_instance_proc_addr(instance, name)))
447 return proc_addr;
449 return pvkGetInstanceProcAddr(instance, name);
452 static VkResult X11DRV_vkGetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice phys_dev,
453 VkSurfaceKHR surface, uint32_t *count, VkRect2D *rects)
455 struct wine_vk_surface *x11_surface = surface_from_handle(surface);
457 TRACE("%p, 0x%s, %p, %p\n", phys_dev, wine_dbgstr_longlong(surface), count, rects);
459 return pvkGetPhysicalDevicePresentRectanglesKHR(phys_dev, x11_surface->surface, count, rects);
462 static VkResult X11DRV_vkGetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice phys_dev,
463 const VkPhysicalDeviceSurfaceInfo2KHR *surface_info, VkSurfaceCapabilities2KHR *capabilities)
465 VkPhysicalDeviceSurfaceInfo2KHR surface_info_host;
466 TRACE("%p, %p, %p\n", phys_dev, surface_info, capabilities);
468 surface_info_host = *surface_info;
469 surface_info_host.surface = surface_from_handle(surface_info->surface)->surface;
471 if (pvkGetPhysicalDeviceSurfaceCapabilities2KHR)
472 return pvkGetPhysicalDeviceSurfaceCapabilities2KHR(phys_dev, &surface_info_host, capabilities);
474 /* Until the loader version exporting this function is common, emulate it using the older non-2 version. */
475 if (surface_info->pNext || capabilities->pNext)
476 FIXME("Emulating vkGetPhysicalDeviceSurfaceCapabilities2KHR with vkGetPhysicalDeviceSurfaceCapabilitiesKHR, pNext is ignored.\n");
478 return pvkGetPhysicalDeviceSurfaceCapabilitiesKHR(phys_dev, surface_info_host.surface, &capabilities->surfaceCapabilities);
481 static VkResult X11DRV_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice phys_dev,
482 VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR *capabilities)
484 struct wine_vk_surface *x11_surface = surface_from_handle(surface);
486 TRACE("%p, 0x%s, %p\n", phys_dev, wine_dbgstr_longlong(surface), capabilities);
488 return pvkGetPhysicalDeviceSurfaceCapabilitiesKHR(phys_dev, x11_surface->surface, capabilities);
491 static VkResult X11DRV_vkGetPhysicalDeviceSurfaceFormats2KHR(VkPhysicalDevice phys_dev,
492 const VkPhysicalDeviceSurfaceInfo2KHR *surface_info, uint32_t *count, VkSurfaceFormat2KHR *formats)
494 VkPhysicalDeviceSurfaceInfo2KHR surface_info_host = *surface_info;
495 VkSurfaceFormatKHR *formats_host;
496 uint32_t i;
497 VkResult result;
498 TRACE("%p, %p, %p, %p\n", phys_dev, surface_info, count, formats);
500 surface_info_host = *surface_info;
501 surface_info_host.surface = surface_from_handle(surface_info->surface)->surface;
503 if (pvkGetPhysicalDeviceSurfaceFormats2KHR)
504 return pvkGetPhysicalDeviceSurfaceFormats2KHR(phys_dev, &surface_info_host, count, formats);
506 /* Until the loader version exporting this function is common, emulate it using the older non-2 version. */
507 if (surface_info->pNext)
508 FIXME("Emulating vkGetPhysicalDeviceSurfaceFormats2KHR with vkGetPhysicalDeviceSurfaceFormatsKHR, pNext is ignored.\n");
510 if (!formats)
511 return pvkGetPhysicalDeviceSurfaceFormatsKHR(phys_dev, surface_info_host.surface, count, NULL);
513 formats_host = heap_calloc(*count, sizeof(*formats_host));
514 if (!formats_host) return VK_ERROR_OUT_OF_HOST_MEMORY;
515 result = pvkGetPhysicalDeviceSurfaceFormatsKHR(phys_dev, surface_info_host.surface, count, formats_host);
516 if (result == VK_SUCCESS || result == VK_INCOMPLETE)
518 for (i = 0; i < *count; i++)
519 formats[i].surfaceFormat = formats_host[i];
522 heap_free(formats_host);
523 return result;
526 static VkResult X11DRV_vkGetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice phys_dev,
527 VkSurfaceKHR surface, uint32_t *count, VkSurfaceFormatKHR *formats)
529 struct wine_vk_surface *x11_surface = surface_from_handle(surface);
531 TRACE("%p, 0x%s, %p, %p\n", phys_dev, wine_dbgstr_longlong(surface), count, formats);
533 return pvkGetPhysicalDeviceSurfaceFormatsKHR(phys_dev, x11_surface->surface, count, formats);
536 static VkResult X11DRV_vkGetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice phys_dev,
537 VkSurfaceKHR surface, uint32_t *count, VkPresentModeKHR *modes)
539 struct wine_vk_surface *x11_surface = surface_from_handle(surface);
541 TRACE("%p, 0x%s, %p, %p\n", phys_dev, wine_dbgstr_longlong(surface), count, modes);
543 return pvkGetPhysicalDeviceSurfacePresentModesKHR(phys_dev, x11_surface->surface, count, modes);
546 static VkResult X11DRV_vkGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice phys_dev,
547 uint32_t index, VkSurfaceKHR surface, VkBool32 *supported)
549 struct wine_vk_surface *x11_surface = surface_from_handle(surface);
551 TRACE("%p, %u, 0x%s, %p\n", phys_dev, index, wine_dbgstr_longlong(surface), supported);
553 return pvkGetPhysicalDeviceSurfaceSupportKHR(phys_dev, index, x11_surface->surface, supported);
556 static VkBool32 X11DRV_vkGetPhysicalDeviceWin32PresentationSupportKHR(VkPhysicalDevice phys_dev,
557 uint32_t index)
559 TRACE("%p %u\n", phys_dev, index);
561 return pvkGetPhysicalDeviceXlibPresentationSupportKHR(phys_dev, index, gdi_display,
562 default_visual.visual->visualid);
565 static VkResult X11DRV_vkGetSwapchainImagesKHR(VkDevice device,
566 VkSwapchainKHR swapchain, uint32_t *count, VkImage *images)
568 TRACE("%p, 0x%s %p %p\n", device, wine_dbgstr_longlong(swapchain), count, images);
569 return pvkGetSwapchainImagesKHR(device, swapchain, count, images);
572 static VkResult X11DRV_vkQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *present_info)
574 VkResult res;
576 TRACE("%p, %p\n", queue, present_info);
578 res = pvkQueuePresentKHR(queue, present_info);
580 if (TRACE_ON(fps))
582 static unsigned long frames, frames_total;
583 static long prev_time, start_time;
584 DWORD time;
586 time = GetTickCount();
587 frames++;
588 frames_total++;
589 if (time - prev_time > 1500)
591 TRACE_(fps)("%p @ approx %.2ffps, total %.2ffps\n",
592 queue, 1000.0 * frames / (time - prev_time),
593 1000.0 * frames_total / (time - start_time));
594 prev_time = time;
595 frames = 0;
596 if (!start_time)
597 start_time = time;
601 return res;
604 static VkSurfaceKHR X11DRV_wine_get_native_surface(VkSurfaceKHR surface)
606 struct wine_vk_surface *x11_surface = surface_from_handle(surface);
608 TRACE("0x%s\n", wine_dbgstr_longlong(surface));
610 return x11_surface->surface;
613 static const struct vulkan_funcs vulkan_funcs =
615 X11DRV_vkCreateInstance,
616 X11DRV_vkCreateSwapchainKHR,
617 X11DRV_vkCreateWin32SurfaceKHR,
618 X11DRV_vkDestroyInstance,
619 X11DRV_vkDestroySurfaceKHR,
620 X11DRV_vkDestroySwapchainKHR,
621 X11DRV_vkEnumerateInstanceExtensionProperties,
622 X11DRV_vkGetDeviceGroupSurfacePresentModesKHR,
623 X11DRV_vkGetDeviceProcAddr,
624 X11DRV_vkGetInstanceProcAddr,
625 X11DRV_vkGetPhysicalDevicePresentRectanglesKHR,
626 X11DRV_vkGetPhysicalDeviceSurfaceCapabilities2KHR,
627 X11DRV_vkGetPhysicalDeviceSurfaceCapabilitiesKHR,
628 X11DRV_vkGetPhysicalDeviceSurfaceFormats2KHR,
629 X11DRV_vkGetPhysicalDeviceSurfaceFormatsKHR,
630 X11DRV_vkGetPhysicalDeviceSurfacePresentModesKHR,
631 X11DRV_vkGetPhysicalDeviceSurfaceSupportKHR,
632 X11DRV_vkGetPhysicalDeviceWin32PresentationSupportKHR,
633 X11DRV_vkGetSwapchainImagesKHR,
634 X11DRV_vkQueuePresentKHR,
636 X11DRV_wine_get_native_surface,
639 static void *X11DRV_get_vk_device_proc_addr(const char *name)
641 return get_vulkan_driver_device_proc_addr(&vulkan_funcs, name);
644 static void *X11DRV_get_vk_instance_proc_addr(VkInstance instance, const char *name)
646 return get_vulkan_driver_instance_proc_addr(&vulkan_funcs, instance, name);
649 const struct vulkan_funcs *get_vulkan_driver(UINT version)
651 static INIT_ONCE init_once = INIT_ONCE_STATIC_INIT;
653 if (version != WINE_VULKAN_DRIVER_VERSION)
655 ERR("version mismatch, vulkan wants %u but driver has %u\n", version, WINE_VULKAN_DRIVER_VERSION);
656 return NULL;
659 InitOnceExecuteOnce(&init_once, wine_vk_init, NULL, NULL);
660 if (vulkan_handle)
661 return &vulkan_funcs;
663 return NULL;
666 #else /* No vulkan */
668 const struct vulkan_funcs *get_vulkan_driver(UINT version)
670 ERR("Wine was built without Vulkan support.\n");
671 return NULL;
674 void wine_vk_surface_destroy(HWND hwnd)
678 #endif /* SONAME_LIBVULKAN */