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. */
24 #include "wine/port.h"
32 #include "wine/debug.h"
33 #include "wine/heap.h"
36 #define VK_NO_PROTOTYPES
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 static struct list surface_list
= LIST_INIT( surface_list
);
62 struct wine_vk_surface
67 VkSurfaceKHR surface
; /* native surface */
72 typedef struct VkXlibSurfaceCreateInfoKHR
74 VkStructureType sType
;
76 VkXlibSurfaceCreateFlagsKHR flags
;
79 } VkXlibSurfaceCreateInfoKHR
;
81 static VkResult (*pvkCreateInstance
)(const VkInstanceCreateInfo
*, const VkAllocationCallbacks
*, VkInstance
*);
82 static VkResult (*pvkCreateSwapchainKHR
)(VkDevice
, const VkSwapchainCreateInfoKHR
*, const VkAllocationCallbacks
*, VkSwapchainKHR
*);
83 static VkResult (*pvkCreateXlibSurfaceKHR
)(VkInstance
, const VkXlibSurfaceCreateInfoKHR
*, const VkAllocationCallbacks
*, VkSurfaceKHR
*);
84 static void (*pvkDestroyInstance
)(VkInstance
, const VkAllocationCallbacks
*);
85 static void (*pvkDestroySurfaceKHR
)(VkInstance
, VkSurfaceKHR
, const VkAllocationCallbacks
*);
86 static void (*pvkDestroySwapchainKHR
)(VkDevice
, VkSwapchainKHR
, const VkAllocationCallbacks
*);
87 static VkResult (*pvkEnumerateInstanceExtensionProperties
)(const char *, uint32_t *, VkExtensionProperties
*);
88 static VkResult (*pvkGetDeviceGroupSurfacePresentModesKHR
)(VkDevice
, VkSurfaceKHR
, VkDeviceGroupPresentModeFlagsKHR
*);
89 static void * (*pvkGetDeviceProcAddr
)(VkDevice
, const char *);
90 static void * (*pvkGetInstanceProcAddr
)(VkInstance
, const char *);
91 static VkResult (*pvkGetPhysicalDevicePresentRectanglesKHR
)(VkPhysicalDevice
, VkSurfaceKHR
, uint32_t *, VkRect2D
*);
92 static VkResult (*pvkGetPhysicalDeviceSurfaceCapabilities2KHR
)(VkPhysicalDevice
, const VkPhysicalDeviceSurfaceInfo2KHR
*, VkSurfaceCapabilities2KHR
*);
93 static VkResult (*pvkGetPhysicalDeviceSurfaceCapabilitiesKHR
)(VkPhysicalDevice
, VkSurfaceKHR
, VkSurfaceCapabilitiesKHR
*);
94 static VkResult (*pvkGetPhysicalDeviceSurfaceFormats2KHR
)(VkPhysicalDevice
, const VkPhysicalDeviceSurfaceInfo2KHR
*, uint32_t *, VkSurfaceFormat2KHR
*);
95 static VkResult (*pvkGetPhysicalDeviceSurfaceFormatsKHR
)(VkPhysicalDevice
, VkSurfaceKHR
, uint32_t *, VkSurfaceFormatKHR
*);
96 static VkResult (*pvkGetPhysicalDeviceSurfacePresentModesKHR
)(VkPhysicalDevice
, VkSurfaceKHR
, uint32_t *, VkPresentModeKHR
*);
97 static VkResult (*pvkGetPhysicalDeviceSurfaceSupportKHR
)(VkPhysicalDevice
, uint32_t, VkSurfaceKHR
, VkBool32
*);
98 static VkBool32 (*pvkGetPhysicalDeviceXlibPresentationSupportKHR
)(VkPhysicalDevice
, uint32_t, Display
*, VisualID
);
99 static VkResult (*pvkGetSwapchainImagesKHR
)(VkDevice
, VkSwapchainKHR
, uint32_t *, VkImage
*);
100 static VkResult (*pvkQueuePresentKHR
)(VkQueue
, const VkPresentInfoKHR
*);
102 static void *X11DRV_get_vk_device_proc_addr(const char *name
);
103 static void *X11DRV_get_vk_instance_proc_addr(VkInstance instance
, const char *name
);
105 static inline struct wine_vk_surface
*surface_from_handle(VkSurfaceKHR handle
)
107 return (struct wine_vk_surface
*)(uintptr_t)handle
;
110 static void *vulkan_handle
;
112 static BOOL WINAPI
wine_vk_init(INIT_ONCE
*once
, void *param
, void **context
)
114 if (!(vulkan_handle
= dlopen(SONAME_LIBVULKAN
, RTLD_NOW
)))
116 ERR("Failed to load %s.\n", SONAME_LIBVULKAN
);
120 #define LOAD_FUNCPTR(f) if (!(p##f = dlsym(vulkan_handle, #f))) goto fail
121 #define LOAD_OPTIONAL_FUNCPTR(f) p##f = dlsym(vulkan_handle, #f)
122 LOAD_FUNCPTR(vkCreateInstance
);
123 LOAD_FUNCPTR(vkCreateSwapchainKHR
);
124 LOAD_FUNCPTR(vkCreateXlibSurfaceKHR
);
125 LOAD_FUNCPTR(vkDestroyInstance
);
126 LOAD_FUNCPTR(vkDestroySurfaceKHR
);
127 LOAD_FUNCPTR(vkDestroySwapchainKHR
);
128 LOAD_FUNCPTR(vkEnumerateInstanceExtensionProperties
);
129 LOAD_FUNCPTR(vkGetDeviceProcAddr
);
130 LOAD_FUNCPTR(vkGetInstanceProcAddr
);
131 LOAD_OPTIONAL_FUNCPTR(vkGetPhysicalDeviceSurfaceCapabilities2KHR
);
132 LOAD_FUNCPTR(vkGetPhysicalDeviceSurfaceCapabilitiesKHR
);
133 LOAD_OPTIONAL_FUNCPTR(vkGetPhysicalDeviceSurfaceFormats2KHR
);
134 LOAD_FUNCPTR(vkGetPhysicalDeviceSurfaceFormatsKHR
);
135 LOAD_FUNCPTR(vkGetPhysicalDeviceSurfacePresentModesKHR
);
136 LOAD_FUNCPTR(vkGetPhysicalDeviceSurfaceSupportKHR
);
137 LOAD_FUNCPTR(vkGetPhysicalDeviceXlibPresentationSupportKHR
);
138 LOAD_FUNCPTR(vkGetSwapchainImagesKHR
);
139 LOAD_FUNCPTR(vkQueuePresentKHR
);
140 LOAD_OPTIONAL_FUNCPTR(vkGetDeviceGroupSurfacePresentModesKHR
);
141 LOAD_OPTIONAL_FUNCPTR(vkGetPhysicalDevicePresentRectanglesKHR
);
143 #undef LOAD_OPTIONAL_FUNCPTR
145 vulkan_hwnd_context
= XUniqueContext();
150 dlclose(vulkan_handle
);
151 vulkan_handle
= NULL
;
155 /* Helper function for converting between win32 and X11 compatible VkInstanceCreateInfo.
156 * Caller is responsible for allocation and cleanup of 'dst'.
158 static VkResult
wine_vk_instance_convert_create_info(const VkInstanceCreateInfo
*src
,
159 VkInstanceCreateInfo
*dst
)
162 const char **enabled_extensions
= NULL
;
164 dst
->sType
= src
->sType
;
165 dst
->flags
= src
->flags
;
166 dst
->pApplicationInfo
= src
->pApplicationInfo
;
167 dst
->pNext
= src
->pNext
;
168 dst
->enabledLayerCount
= 0;
169 dst
->ppEnabledLayerNames
= NULL
;
170 dst
->enabledExtensionCount
= 0;
171 dst
->ppEnabledExtensionNames
= NULL
;
173 if (src
->enabledExtensionCount
> 0)
175 enabled_extensions
= heap_calloc(src
->enabledExtensionCount
, sizeof(*src
->ppEnabledExtensionNames
));
176 if (!enabled_extensions
)
178 ERR("Failed to allocate memory for enabled extensions\n");
179 return VK_ERROR_OUT_OF_HOST_MEMORY
;
182 for (i
= 0; i
< src
->enabledExtensionCount
; i
++)
184 /* Substitute extension with X11 ones else copy. Long-term, when we
185 * support more extensions, we should store these in a list.
187 if (!strcmp(src
->ppEnabledExtensionNames
[i
], "VK_KHR_win32_surface"))
189 enabled_extensions
[i
] = "VK_KHR_xlib_surface";
193 enabled_extensions
[i
] = src
->ppEnabledExtensionNames
[i
];
196 dst
->ppEnabledExtensionNames
= enabled_extensions
;
197 dst
->enabledExtensionCount
= src
->enabledExtensionCount
;
203 static struct wine_vk_surface
*wine_vk_surface_grab(struct wine_vk_surface
*surface
)
205 InterlockedIncrement(&surface
->ref
);
209 static void wine_vk_surface_release(struct wine_vk_surface
*surface
)
211 if (InterlockedDecrement(&surface
->ref
))
214 EnterCriticalSection(&context_section
);
215 list_remove(&surface
->entry
);
216 LeaveCriticalSection(&context_section
);
219 XDestroyWindow(gdi_display
, surface
->window
);
224 void wine_vk_surface_destroy(HWND hwnd
)
226 struct wine_vk_surface
*surface
;
227 EnterCriticalSection(&context_section
);
228 if (!XFindContext(gdi_display
, (XID
)hwnd
, vulkan_hwnd_context
, (char **)&surface
))
230 surface
->hwnd_thread_id
= 0;
231 surface
->hwnd
= NULL
;
232 wine_vk_surface_release(surface
);
234 XDeleteContext(gdi_display
, (XID
)hwnd
, vulkan_hwnd_context
);
235 LeaveCriticalSection(&context_section
);
238 void vulkan_thread_detach(void)
240 struct wine_vk_surface
*surface
, *next
;
241 DWORD thread_id
= GetCurrentThreadId();
243 EnterCriticalSection(&context_section
);
244 LIST_FOR_EACH_ENTRY_SAFE(surface
, next
, &surface_list
, struct wine_vk_surface
, entry
)
246 if (surface
->hwnd_thread_id
!= thread_id
)
249 TRACE("Detaching surface %p, hwnd %p.\n", surface
, surface
->hwnd
);
250 XReparentWindow(gdi_display
, surface
->window
, get_dummy_parent(), 0, 0);
251 XSync(gdi_display
, False
);
252 wine_vk_surface_destroy(surface
->hwnd
);
254 LeaveCriticalSection(&context_section
);
257 static VkResult
X11DRV_vkCreateInstance(const VkInstanceCreateInfo
*create_info
,
258 const VkAllocationCallbacks
*allocator
, VkInstance
*instance
)
260 VkInstanceCreateInfo create_info_host
;
262 TRACE("create_info %p, allocator %p, instance %p\n", create_info
, allocator
, instance
);
265 FIXME("Support for allocation callbacks not implemented yet\n");
267 /* Perform a second pass on converting VkInstanceCreateInfo. Winevulkan
268 * performed a first pass in which it handles everything except for WSI
269 * functionality such as VK_KHR_win32_surface. Handle this now.
271 res
= wine_vk_instance_convert_create_info(create_info
, &create_info_host
);
272 if (res
!= VK_SUCCESS
)
274 ERR("Failed to convert instance create info, res=%d\n", res
);
278 res
= pvkCreateInstance(&create_info_host
, NULL
/* allocator */, instance
);
280 heap_free((void *)create_info_host
.ppEnabledExtensionNames
);
284 static VkResult
X11DRV_vkCreateSwapchainKHR(VkDevice device
,
285 const VkSwapchainCreateInfoKHR
*create_info
,
286 const VkAllocationCallbacks
*allocator
, VkSwapchainKHR
*swapchain
)
288 struct wine_vk_surface
*x11_surface
= surface_from_handle(create_info
->surface
);
289 VkSwapchainCreateInfoKHR create_info_host
;
290 TRACE("%p %p %p %p\n", device
, create_info
, allocator
, swapchain
);
293 FIXME("Support for allocation callbacks not implemented yet\n");
295 if (!x11_surface
->hwnd
)
296 return VK_ERROR_SURFACE_LOST_KHR
;
298 create_info_host
= *create_info
;
299 create_info_host
.surface
= x11_surface
->surface
;
301 return pvkCreateSwapchainKHR(device
, &create_info_host
, NULL
/* allocator */, swapchain
);
304 static VkResult
X11DRV_vkCreateWin32SurfaceKHR(VkInstance instance
,
305 const VkWin32SurfaceCreateInfoKHR
*create_info
,
306 const VkAllocationCallbacks
*allocator
, VkSurfaceKHR
*surface
)
309 VkXlibSurfaceCreateInfoKHR create_info_host
;
310 struct wine_vk_surface
*x11_surface
;
312 TRACE("%p %p %p %p\n", instance
, create_info
, allocator
, surface
);
315 FIXME("Support for allocation callbacks not implemented yet\n");
317 /* TODO: support child window rendering. */
318 if (create_info
->hwnd
&& GetAncestor(create_info
->hwnd
, GA_PARENT
) != GetDesktopWindow())
320 FIXME("Application requires child window rendering, which is not implemented yet!\n");
321 return VK_ERROR_INCOMPATIBLE_DRIVER
;
324 x11_surface
= heap_alloc_zero(sizeof(*x11_surface
));
326 return VK_ERROR_OUT_OF_HOST_MEMORY
;
328 x11_surface
->ref
= 1;
329 x11_surface
->hwnd
= create_info
->hwnd
;
330 if (x11_surface
->hwnd
)
332 x11_surface
->window
= create_client_window(create_info
->hwnd
, &default_visual
);
333 x11_surface
->hwnd_thread_id
= GetWindowThreadProcessId(x11_surface
->hwnd
, NULL
);
337 x11_surface
->window
= create_dummy_client_window();
340 if (!x11_surface
->window
)
342 ERR("Failed to allocate client window for hwnd=%p\n", create_info
->hwnd
);
344 /* VK_KHR_win32_surface only allows out of host and device memory as errors. */
345 res
= VK_ERROR_OUT_OF_HOST_MEMORY
;
349 create_info_host
.sType
= VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR
;
350 create_info_host
.pNext
= NULL
;
351 create_info_host
.flags
= 0; /* reserved */
352 create_info_host
.dpy
= gdi_display
;
353 create_info_host
.window
= x11_surface
->window
;
355 res
= pvkCreateXlibSurfaceKHR(instance
, &create_info_host
, NULL
/* allocator */, &x11_surface
->surface
);
356 if (res
!= VK_SUCCESS
)
358 ERR("Failed to create Xlib surface, res=%d\n", res
);
362 EnterCriticalSection(&context_section
);
363 if (x11_surface
->hwnd
)
365 wine_vk_surface_destroy( x11_surface
->hwnd
);
366 XSaveContext(gdi_display
, (XID
)create_info
->hwnd
, vulkan_hwnd_context
, (char *)wine_vk_surface_grab(x11_surface
));
368 list_add_tail(&surface_list
, &x11_surface
->entry
);
369 LeaveCriticalSection(&context_section
);
371 *surface
= (uintptr_t)x11_surface
;
373 TRACE("Created surface=0x%s\n", wine_dbgstr_longlong(*surface
));
377 wine_vk_surface_release(x11_surface
);
381 static void X11DRV_vkDestroyInstance(VkInstance instance
, const VkAllocationCallbacks
*allocator
)
383 TRACE("%p %p\n", instance
, allocator
);
386 FIXME("Support for allocation callbacks not implemented yet\n");
388 pvkDestroyInstance(instance
, NULL
/* allocator */);
391 static void X11DRV_vkDestroySurfaceKHR(VkInstance instance
, VkSurfaceKHR surface
,
392 const VkAllocationCallbacks
*allocator
)
394 struct wine_vk_surface
*x11_surface
= surface_from_handle(surface
);
396 TRACE("%p 0x%s %p\n", instance
, wine_dbgstr_longlong(surface
), allocator
);
399 FIXME("Support for allocation callbacks not implemented yet\n");
401 /* vkDestroySurfaceKHR must handle VK_NULL_HANDLE (0) for surface. */
404 pvkDestroySurfaceKHR(instance
, x11_surface
->surface
, NULL
/* allocator */);
406 wine_vk_surface_release(x11_surface
);
410 static void X11DRV_vkDestroySwapchainKHR(VkDevice device
, VkSwapchainKHR swapchain
,
411 const VkAllocationCallbacks
*allocator
)
413 TRACE("%p, 0x%s %p\n", device
, wine_dbgstr_longlong(swapchain
), allocator
);
416 FIXME("Support for allocation callbacks not implemented yet\n");
418 pvkDestroySwapchainKHR(device
, swapchain
, NULL
/* allocator */);
421 static VkResult
X11DRV_vkEnumerateInstanceExtensionProperties(const char *layer_name
,
422 uint32_t *count
, VkExtensionProperties
* properties
)
427 TRACE("layer_name %s, count %p, properties %p\n", debugstr_a(layer_name
), count
, properties
);
429 /* This shouldn't get called with layer_name set, the ICD loader prevents it. */
432 ERR("Layer enumeration not supported from ICD.\n");
433 return VK_ERROR_LAYER_NOT_PRESENT
;
436 /* We will return the same number of instance extensions reported by the host back to
437 * winevulkan. Along the way we may replace xlib extensions with their win32 equivalents.
438 * Winevulkan will perform more detailed filtering as it knows whether it has thunks
439 * for a particular extension.
441 res
= pvkEnumerateInstanceExtensionProperties(layer_name
, count
, properties
);
442 if (!properties
|| res
< 0)
445 for (i
= 0; i
< *count
; i
++)
447 /* For now the only x11 extension we need to fixup. Long-term we may need an array. */
448 if (!strcmp(properties
[i
].extensionName
, "VK_KHR_xlib_surface"))
450 TRACE("Substituting VK_KHR_xlib_surface for VK_KHR_win32_surface\n");
452 snprintf(properties
[i
].extensionName
, sizeof(properties
[i
].extensionName
),
453 VK_KHR_WIN32_SURFACE_EXTENSION_NAME
);
454 properties
[i
].specVersion
= VK_KHR_WIN32_SURFACE_SPEC_VERSION
;
458 TRACE("Returning %u extensions.\n", *count
);
462 static VkResult
X11DRV_vkGetDeviceGroupSurfacePresentModesKHR(VkDevice device
,
463 VkSurfaceKHR surface
, VkDeviceGroupPresentModeFlagsKHR
*flags
)
465 struct wine_vk_surface
*x11_surface
= surface_from_handle(surface
);
467 TRACE("%p, 0x%s, %p\n", device
, wine_dbgstr_longlong(surface
), flags
);
469 return pvkGetDeviceGroupSurfacePresentModesKHR(device
, x11_surface
->surface
, flags
);
472 static const char *wine_vk_native_fn_name(const char *name
)
474 if (!strcmp(name
, "vkCreateWin32SurfaceKHR"))
475 return "vkCreateXlibSurfaceKHR";
476 if (!strcmp(name
, "vkGetPhysicalDeviceWin32PresentationSupportKHR"))
477 return "vkGetPhysicalDeviceXlibPresentationSupportKHR";
482 static void *X11DRV_vkGetDeviceProcAddr(VkDevice device
, const char *name
)
486 TRACE("%p, %s\n", device
, debugstr_a(name
));
488 if (!pvkGetDeviceProcAddr(device
, wine_vk_native_fn_name(name
)))
491 if ((proc_addr
= X11DRV_get_vk_device_proc_addr(name
)))
494 return pvkGetDeviceProcAddr(device
, name
);
497 static void *X11DRV_vkGetInstanceProcAddr(VkInstance instance
, const char *name
)
501 TRACE("%p, %s\n", instance
, debugstr_a(name
));
503 if (!pvkGetInstanceProcAddr(instance
, wine_vk_native_fn_name(name
)))
506 if ((proc_addr
= X11DRV_get_vk_instance_proc_addr(instance
, name
)))
509 return pvkGetInstanceProcAddr(instance
, name
);
512 static VkResult
X11DRV_vkGetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice phys_dev
,
513 VkSurfaceKHR surface
, uint32_t *count
, VkRect2D
*rects
)
515 struct wine_vk_surface
*x11_surface
= surface_from_handle(surface
);
517 TRACE("%p, 0x%s, %p, %p\n", phys_dev
, wine_dbgstr_longlong(surface
), count
, rects
);
519 if (!x11_surface
->hwnd
)
522 return VK_ERROR_SURFACE_LOST_KHR
;
528 return pvkGetPhysicalDevicePresentRectanglesKHR(phys_dev
, x11_surface
->surface
, count
, rects
);
531 static VkResult
X11DRV_vkGetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice phys_dev
,
532 const VkPhysicalDeviceSurfaceInfo2KHR
*surface_info
, VkSurfaceCapabilities2KHR
*capabilities
)
534 VkPhysicalDeviceSurfaceInfo2KHR surface_info_host
;
535 TRACE("%p, %p, %p\n", phys_dev
, surface_info
, capabilities
);
537 surface_info_host
= *surface_info
;
538 surface_info_host
.surface
= surface_from_handle(surface_info
->surface
)->surface
;
540 if (pvkGetPhysicalDeviceSurfaceCapabilities2KHR
)
541 return pvkGetPhysicalDeviceSurfaceCapabilities2KHR(phys_dev
, &surface_info_host
, capabilities
);
543 /* Until the loader version exporting this function is common, emulate it using the older non-2 version. */
544 if (surface_info
->pNext
|| capabilities
->pNext
)
545 FIXME("Emulating vkGetPhysicalDeviceSurfaceCapabilities2KHR with vkGetPhysicalDeviceSurfaceCapabilitiesKHR, pNext is ignored.\n");
547 return pvkGetPhysicalDeviceSurfaceCapabilitiesKHR(phys_dev
, surface_info_host
.surface
, &capabilities
->surfaceCapabilities
);
550 static VkResult
X11DRV_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice phys_dev
,
551 VkSurfaceKHR surface
, VkSurfaceCapabilitiesKHR
*capabilities
)
553 struct wine_vk_surface
*x11_surface
= surface_from_handle(surface
);
555 TRACE("%p, 0x%s, %p\n", phys_dev
, wine_dbgstr_longlong(surface
), capabilities
);
557 if (!x11_surface
->hwnd
)
558 return VK_ERROR_SURFACE_LOST_KHR
;
560 return pvkGetPhysicalDeviceSurfaceCapabilitiesKHR(phys_dev
, x11_surface
->surface
, capabilities
);
563 static VkResult
X11DRV_vkGetPhysicalDeviceSurfaceFormats2KHR(VkPhysicalDevice phys_dev
,
564 const VkPhysicalDeviceSurfaceInfo2KHR
*surface_info
, uint32_t *count
, VkSurfaceFormat2KHR
*formats
)
566 VkPhysicalDeviceSurfaceInfo2KHR surface_info_host
= *surface_info
;
567 VkSurfaceFormatKHR
*formats_host
;
570 TRACE("%p, %p, %p, %p\n", phys_dev
, surface_info
, count
, formats
);
572 surface_info_host
= *surface_info
;
573 surface_info_host
.surface
= surface_from_handle(surface_info
->surface
)->surface
;
575 if (pvkGetPhysicalDeviceSurfaceFormats2KHR
)
576 return pvkGetPhysicalDeviceSurfaceFormats2KHR(phys_dev
, &surface_info_host
, count
, formats
);
578 /* Until the loader version exporting this function is common, emulate it using the older non-2 version. */
579 if (surface_info
->pNext
)
580 FIXME("Emulating vkGetPhysicalDeviceSurfaceFormats2KHR with vkGetPhysicalDeviceSurfaceFormatsKHR, pNext is ignored.\n");
583 return pvkGetPhysicalDeviceSurfaceFormatsKHR(phys_dev
, surface_info_host
.surface
, count
, NULL
);
585 formats_host
= heap_calloc(*count
, sizeof(*formats_host
));
586 if (!formats_host
) return VK_ERROR_OUT_OF_HOST_MEMORY
;
587 result
= pvkGetPhysicalDeviceSurfaceFormatsKHR(phys_dev
, surface_info_host
.surface
, count
, formats_host
);
588 if (result
== VK_SUCCESS
|| result
== VK_INCOMPLETE
)
590 for (i
= 0; i
< *count
; i
++)
591 formats
[i
].surfaceFormat
= formats_host
[i
];
594 heap_free(formats_host
);
598 static VkResult
X11DRV_vkGetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice phys_dev
,
599 VkSurfaceKHR surface
, uint32_t *count
, VkSurfaceFormatKHR
*formats
)
601 struct wine_vk_surface
*x11_surface
= surface_from_handle(surface
);
603 TRACE("%p, 0x%s, %p, %p\n", phys_dev
, wine_dbgstr_longlong(surface
), count
, formats
);
605 return pvkGetPhysicalDeviceSurfaceFormatsKHR(phys_dev
, x11_surface
->surface
, count
, formats
);
608 static VkResult
X11DRV_vkGetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice phys_dev
,
609 VkSurfaceKHR surface
, uint32_t *count
, VkPresentModeKHR
*modes
)
611 struct wine_vk_surface
*x11_surface
= surface_from_handle(surface
);
613 TRACE("%p, 0x%s, %p, %p\n", phys_dev
, wine_dbgstr_longlong(surface
), count
, modes
);
615 return pvkGetPhysicalDeviceSurfacePresentModesKHR(phys_dev
, x11_surface
->surface
, count
, modes
);
618 static VkResult
X11DRV_vkGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice phys_dev
,
619 uint32_t index
, VkSurfaceKHR surface
, VkBool32
*supported
)
621 struct wine_vk_surface
*x11_surface
= surface_from_handle(surface
);
623 TRACE("%p, %u, 0x%s, %p\n", phys_dev
, index
, wine_dbgstr_longlong(surface
), supported
);
625 return pvkGetPhysicalDeviceSurfaceSupportKHR(phys_dev
, index
, x11_surface
->surface
, supported
);
628 static VkBool32
X11DRV_vkGetPhysicalDeviceWin32PresentationSupportKHR(VkPhysicalDevice phys_dev
,
631 TRACE("%p %u\n", phys_dev
, index
);
633 return pvkGetPhysicalDeviceXlibPresentationSupportKHR(phys_dev
, index
, gdi_display
,
634 default_visual
.visual
->visualid
);
637 static VkResult
X11DRV_vkGetSwapchainImagesKHR(VkDevice device
,
638 VkSwapchainKHR swapchain
, uint32_t *count
, VkImage
*images
)
640 TRACE("%p, 0x%s %p %p\n", device
, wine_dbgstr_longlong(swapchain
), count
, images
);
641 return pvkGetSwapchainImagesKHR(device
, swapchain
, count
, images
);
644 static VkResult
X11DRV_vkQueuePresentKHR(VkQueue queue
, const VkPresentInfoKHR
*present_info
)
648 TRACE("%p, %p\n", queue
, present_info
);
650 res
= pvkQueuePresentKHR(queue
, present_info
);
654 static unsigned long frames
, frames_total
;
655 static long prev_time
, start_time
;
658 time
= GetTickCount();
661 if (time
- prev_time
> 1500)
663 TRACE_(fps
)("%p @ approx %.2ffps, total %.2ffps\n",
664 queue
, 1000.0 * frames
/ (time
- prev_time
),
665 1000.0 * frames_total
/ (time
- start_time
));
676 static VkSurfaceKHR
X11DRV_wine_get_native_surface(VkSurfaceKHR surface
)
678 struct wine_vk_surface
*x11_surface
= surface_from_handle(surface
);
680 TRACE("0x%s\n", wine_dbgstr_longlong(surface
));
682 return x11_surface
->surface
;
685 static const struct vulkan_funcs vulkan_funcs
=
687 X11DRV_vkCreateInstance
,
688 X11DRV_vkCreateSwapchainKHR
,
689 X11DRV_vkCreateWin32SurfaceKHR
,
690 X11DRV_vkDestroyInstance
,
691 X11DRV_vkDestroySurfaceKHR
,
692 X11DRV_vkDestroySwapchainKHR
,
693 X11DRV_vkEnumerateInstanceExtensionProperties
,
694 X11DRV_vkGetDeviceGroupSurfacePresentModesKHR
,
695 X11DRV_vkGetDeviceProcAddr
,
696 X11DRV_vkGetInstanceProcAddr
,
697 X11DRV_vkGetPhysicalDevicePresentRectanglesKHR
,
698 X11DRV_vkGetPhysicalDeviceSurfaceCapabilities2KHR
,
699 X11DRV_vkGetPhysicalDeviceSurfaceCapabilitiesKHR
,
700 X11DRV_vkGetPhysicalDeviceSurfaceFormats2KHR
,
701 X11DRV_vkGetPhysicalDeviceSurfaceFormatsKHR
,
702 X11DRV_vkGetPhysicalDeviceSurfacePresentModesKHR
,
703 X11DRV_vkGetPhysicalDeviceSurfaceSupportKHR
,
704 X11DRV_vkGetPhysicalDeviceWin32PresentationSupportKHR
,
705 X11DRV_vkGetSwapchainImagesKHR
,
706 X11DRV_vkQueuePresentKHR
,
708 X11DRV_wine_get_native_surface
,
711 static void *X11DRV_get_vk_device_proc_addr(const char *name
)
713 return get_vulkan_driver_device_proc_addr(&vulkan_funcs
, name
);
716 static void *X11DRV_get_vk_instance_proc_addr(VkInstance instance
, const char *name
)
718 return get_vulkan_driver_instance_proc_addr(&vulkan_funcs
, instance
, name
);
721 const struct vulkan_funcs
*get_vulkan_driver(UINT version
)
723 static INIT_ONCE init_once
= INIT_ONCE_STATIC_INIT
;
725 if (version
!= WINE_VULKAN_DRIVER_VERSION
)
727 ERR("version mismatch, vulkan wants %u but driver has %u\n", version
, WINE_VULKAN_DRIVER_VERSION
);
731 InitOnceExecuteOnce(&init_once
, wine_vk_init
, NULL
, NULL
);
733 return &vulkan_funcs
;
738 #else /* No vulkan */
740 const struct vulkan_funcs
*get_vulkan_driver(UINT version
)
742 ERR("Wine was built without Vulkan support.\n");
746 void wine_vk_surface_destroy(HWND hwnd
)
750 void vulkan_thread_detach(void)
754 #endif /* SONAME_LIBVULKAN */