This part introduces support for Vulkan swapchains to the Wayland driver:
* Implement several Vulkan functions typically called to get info before swapchain creation. * Implement swapchain creation/destruction * Implement getting swapchain images.
I stopped short of adding presentation support since the MR would grow too big (stay tuned for part 10.3).
Thanks!
From: Alexandros Frantzis alexandros.frantzis@collabora.com
Passthrough implementations with three additions:
1. Try to emulate vkGetPhysicalDeviceSurfaceCapabilities2KHR with vkGetPhysicalDeviceSurfaceCapabilitiesKHR if needed. 3. Set the capabilities' image extent values to match what the Vulkan Win32 WSI typically provides. --- dlls/winewayland.drv/vulkan.c | 101 +++++++++++++++++++++++++++++++++- 1 file changed, 100 insertions(+), 1 deletion(-)
diff --git a/dlls/winewayland.drv/vulkan.c b/dlls/winewayland.drv/vulkan.c index be7f048f9d3..c729db4d1d3 100644 --- a/dlls/winewayland.drv/vulkan.c +++ b/dlls/winewayland.drv/vulkan.c @@ -58,6 +58,8 @@ static void (*pvkDestroySurfaceKHR)(VkInstance, VkSurfaceKHR, const VkAllocation static VkResult (*pvkEnumerateInstanceExtensionProperties)(const char *, uint32_t *, VkExtensionProperties *); static void * (*pvkGetDeviceProcAddr)(VkDevice, const char *); static void * (*pvkGetInstanceProcAddr)(VkInstance, const char *); +static VkResult (*pvkGetPhysicalDeviceSurfaceCapabilities2KHR)(VkPhysicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR *, VkSurfaceCapabilities2KHR *); +static VkResult (*pvkGetPhysicalDeviceSurfaceCapabilitiesKHR)(VkPhysicalDevice, VkSurfaceKHR, VkSurfaceCapabilitiesKHR *);
static void *vulkan_handle; static const struct vulkan_funcs vulkan_funcs; @@ -73,11 +75,16 @@ static struct wine_vk_surface *wine_vk_surface_from_handle(VkSurfaceKHR handle) return (struct wine_vk_surface *)(uintptr_t)handle; }
+static HWND wine_vk_surface_get_hwnd(struct wine_vk_surface *wine_vk_surface) +{ + return wl_surface_get_user_data(wine_vk_surface->client->wl_surface); +} + static void wine_vk_surface_destroy(struct wine_vk_surface *wine_vk_surface) { if (wine_vk_surface->client) { - HWND hwnd = wl_surface_get_user_data(wine_vk_surface->client->wl_surface); + HWND hwnd = wine_vk_surface_get_hwnd(wine_vk_surface); struct wayland_surface *wayland_surface = wayland_surface_lock_hwnd(hwnd);
if (wayland_client_surface_release(wine_vk_surface->client) && @@ -143,6 +150,37 @@ static const char *wine_vk_native_fn_name(const char *name) return name; }
+/* Update the capabilities to match what the Win32 WSI would provide. */ +static VkResult wine_vk_surface_update_caps(struct wine_vk_surface *wine_vk_surface, + VkSurfaceCapabilitiesKHR *caps) +{ + struct wayland_surface *wayland_surface; + int client_width, client_height; + HWND hwnd = wine_vk_surface_get_hwnd(wine_vk_surface); + + if (!(wayland_surface = wayland_surface_lock_hwnd(hwnd))) + return VK_ERROR_SURFACE_LOST_KHR; + + client_width = wayland_surface->window.client_rect.right - + wayland_surface->window.client_rect.left; + client_height = wayland_surface->window.client_rect.bottom - + wayland_surface->window.client_rect.top; + + pthread_mutex_unlock(&wayland_surface->mutex); + + caps->minImageExtent.width = client_width; + caps->minImageExtent.height = client_height; + caps->maxImageExtent.width = client_width; + caps->maxImageExtent.height = client_height; + caps->currentExtent.width = client_width; + caps->currentExtent.height = client_height; + + TRACE("hwnd=%p extent=%dx%d\n", hwnd, + caps->currentExtent.width, caps->currentExtent.height); + + return VK_SUCCESS; +} + static VkResult wayland_vkCreateInstance(const VkInstanceCreateInfo *create_info, const VkAllocationCallbacks *allocator, VkInstance *instance) @@ -343,6 +381,61 @@ static void *wayland_vkGetInstanceProcAddr(VkInstance instance, const char *name return pvkGetInstanceProcAddr(instance, name); }
+static VkResult wayland_vkGetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice phys_dev, + const VkPhysicalDeviceSurfaceInfo2KHR *surface_info, + VkSurfaceCapabilities2KHR *capabilities) +{ + struct wine_vk_surface *wine_vk_surface = wine_vk_surface_from_handle(surface_info->surface); + VkPhysicalDeviceSurfaceInfo2KHR surface_info_host; + VkResult res; + + TRACE("%p, %p, %p\n", phys_dev, surface_info, capabilities); + + surface_info_host = *surface_info; + surface_info_host.surface = wine_vk_surface->native; + + if (pvkGetPhysicalDeviceSurfaceCapabilities2KHR) + { + res = pvkGetPhysicalDeviceSurfaceCapabilities2KHR(phys_dev, &surface_info_host, + capabilities); + goto out; + } + + /* Until the loader version exporting this function is common, emulate it + * using the older non-2 version. */ + if (surface_info->pNext || capabilities->pNext) + { + FIXME("Emulating vkGetPhysicalDeviceSurfaceCapabilities2KHR with " + "vkGetPhysicalDeviceSurfaceCapabilitiesKHR, pNext is ignored.\n"); + } + + res = pvkGetPhysicalDeviceSurfaceCapabilitiesKHR(phys_dev, surface_info_host.surface, + &capabilities->surfaceCapabilities); + +out: + if (res == VK_SUCCESS) + res = wine_vk_surface_update_caps(wine_vk_surface, &capabilities->surfaceCapabilities); + + return res; +} + +static VkResult wayland_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice phys_dev, + VkSurfaceKHR surface, + VkSurfaceCapabilitiesKHR *capabilities) +{ + struct wine_vk_surface *wine_vk_surface = wine_vk_surface_from_handle(surface); + VkResult res; + + TRACE("%p, 0x%s, %p\n", phys_dev, wine_dbgstr_longlong(surface), capabilities); + + res = pvkGetPhysicalDeviceSurfaceCapabilitiesKHR(phys_dev, wine_vk_surface->native, + capabilities); + if (res == VK_SUCCESS) + res = wine_vk_surface_update_caps(wine_vk_surface, capabilities); + + return res; +} + static VkSurfaceKHR wayland_wine_get_native_surface(VkSurfaceKHR surface) { return wine_vk_surface_from_handle(surface)->native; @@ -357,6 +450,7 @@ static void wine_vk_init(void) }
#define LOAD_FUNCPTR(f) if (!(p##f = dlsym(vulkan_handle, #f))) goto fail +#define LOAD_OPTIONAL_FUNCPTR(f) p##f = dlsym(vulkan_handle, #f) LOAD_FUNCPTR(vkCreateInstance); LOAD_FUNCPTR(vkCreateWaylandSurfaceKHR); LOAD_FUNCPTR(vkDestroyInstance); @@ -364,7 +458,10 @@ static void wine_vk_init(void) LOAD_FUNCPTR(vkEnumerateInstanceExtensionProperties); LOAD_FUNCPTR(vkGetDeviceProcAddr); LOAD_FUNCPTR(vkGetInstanceProcAddr); + LOAD_OPTIONAL_FUNCPTR(vkGetPhysicalDeviceSurfaceCapabilities2KHR); + LOAD_FUNCPTR(vkGetPhysicalDeviceSurfaceCapabilitiesKHR); #undef LOAD_FUNCPTR +#undef LOAD_OPTIONAL_FUNCPTR
return;
@@ -382,6 +479,8 @@ static const struct vulkan_funcs vulkan_funcs = .p_vkEnumerateInstanceExtensionProperties = wayland_vkEnumerateInstanceExtensionProperties, .p_vkGetDeviceProcAddr = wayland_vkGetDeviceProcAddr, .p_vkGetInstanceProcAddr = wayland_vkGetInstanceProcAddr, + .p_vkGetPhysicalDeviceSurfaceCapabilities2KHR = wayland_vkGetPhysicalDeviceSurfaceCapabilities2KHR, + .p_vkGetPhysicalDeviceSurfaceCapabilitiesKHR = wayland_vkGetPhysicalDeviceSurfaceCapabilitiesKHR, .p_wine_get_native_surface = wayland_wine_get_native_surface, };
From: Alexandros Frantzis alexandros.frantzis@collabora.com
Passthrough implementations with two additions:
1. Checking for invalidated VkSurfaceKHR. 2. Try to emulate vkGetPhysicalDeviceSurfaceFormats2KHR with vkGetPhysicalDeviceSurfaceFormatsKHR if needed. --- dlls/winewayland.drv/vulkan.c | 89 +++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+)
diff --git a/dlls/winewayland.drv/vulkan.c b/dlls/winewayland.drv/vulkan.c index c729db4d1d3..0a827c69cce 100644 --- a/dlls/winewayland.drv/vulkan.c +++ b/dlls/winewayland.drv/vulkan.c @@ -60,6 +60,8 @@ static void * (*pvkGetDeviceProcAddr)(VkDevice, const char *); static void * (*pvkGetInstanceProcAddr)(VkInstance, const char *); static VkResult (*pvkGetPhysicalDeviceSurfaceCapabilities2KHR)(VkPhysicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR *, VkSurfaceCapabilities2KHR *); static VkResult (*pvkGetPhysicalDeviceSurfaceCapabilitiesKHR)(VkPhysicalDevice, VkSurfaceKHR, VkSurfaceCapabilitiesKHR *); +static VkResult (*pvkGetPhysicalDeviceSurfaceFormats2KHR)(VkPhysicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR *, uint32_t *, VkSurfaceFormat2KHR *); +static VkResult (*pvkGetPhysicalDeviceSurfaceFormatsKHR)(VkPhysicalDevice, VkSurfaceKHR, uint32_t *, VkSurfaceFormatKHR *);
static void *vulkan_handle; static const struct vulkan_funcs vulkan_funcs; @@ -99,6 +101,20 @@ static void wine_vk_surface_destroy(struct wine_vk_surface *wine_vk_surface) free(wine_vk_surface); }
+static BOOL wine_vk_surface_is_valid(struct wine_vk_surface *wine_vk_surface) +{ + HWND hwnd = wine_vk_surface_get_hwnd(wine_vk_surface); + struct wayland_surface *wayland_surface; + + if ((wayland_surface = wayland_surface_lock_hwnd(hwnd))) + { + pthread_mutex_unlock(&wayland_surface->mutex); + return TRUE; + } + + return FALSE; +} + /* Helper function for converting between win32 and Wayland compatible VkInstanceCreateInfo. * Caller is responsible for allocation and cleanup of 'dst'. */ static VkResult wine_vk_instance_convert_create_info(const VkInstanceCreateInfo *src, @@ -436,6 +452,75 @@ static VkResult wayland_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevi return res; }
+static VkResult wayland_vkGetPhysicalDeviceSurfaceFormats2KHR(VkPhysicalDevice phys_dev, + const VkPhysicalDeviceSurfaceInfo2KHR *surface_info, + uint32_t *count, + VkSurfaceFormat2KHR *formats) +{ + struct wine_vk_surface *wine_vk_surface = wine_vk_surface_from_handle(surface_info->surface); + VkPhysicalDeviceSurfaceInfo2KHR surface_info_host; + VkSurfaceFormatKHR *formats_host; + uint32_t i; + VkResult result; + + TRACE("%p, %p, %p, %p\n", phys_dev, surface_info, count, formats); + + if (!wine_vk_surface_is_valid(wine_vk_surface)) + return VK_ERROR_SURFACE_LOST_KHR; + + surface_info_host = *surface_info; + surface_info_host.surface = wine_vk_surface->native; + + if (pvkGetPhysicalDeviceSurfaceFormats2KHR) + { + return pvkGetPhysicalDeviceSurfaceFormats2KHR(phys_dev, surface_info, + count, formats); + } + + /* Until the loader version exporting this function is common, emulate it + * using the older non-2 version. */ + if (surface_info->pNext) + { + FIXME("Emulating vkGetPhysicalDeviceSurfaceFormats2KHR with " + "vkGetPhysicalDeviceSurfaceFormatsKHR, pNext is ignored.\n"); + } + + if (!formats) + { + return pvkGetPhysicalDeviceSurfaceFormatsKHR(phys_dev, surface_info_host.surface, + count, NULL); + } + + formats_host = calloc(*count, sizeof(*formats_host)); + if (!formats_host) return VK_ERROR_OUT_OF_HOST_MEMORY; + result = pvkGetPhysicalDeviceSurfaceFormatsKHR(phys_dev, surface_info_host.surface, + count, formats_host); + if (result == VK_SUCCESS || result == VK_INCOMPLETE) + { + for (i = 0; i < *count; i++) + formats[i].surfaceFormat = formats_host[i]; + } + + free(formats_host); + return result; +} + +static VkResult wayland_vkGetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice phys_dev, + VkSurfaceKHR surface, + uint32_t *count, + VkSurfaceFormatKHR *formats) +{ + struct wine_vk_surface *wine_vk_surface = wine_vk_surface_from_handle(surface); + + TRACE("%p, 0x%s, %p, %p\n", phys_dev, wine_dbgstr_longlong(surface), count, formats); + + if (!wine_vk_surface_is_valid(wine_vk_surface)) + return VK_ERROR_SURFACE_LOST_KHR; + + return pvkGetPhysicalDeviceSurfaceFormatsKHR(phys_dev, wine_vk_surface->native, + count, formats); +} + static VkSurfaceKHR wayland_wine_get_native_surface(VkSurfaceKHR surface) { return wine_vk_surface_from_handle(surface)->native; @@ -460,6 +545,8 @@ static void wine_vk_init(void) LOAD_FUNCPTR(vkGetInstanceProcAddr); LOAD_OPTIONAL_FUNCPTR(vkGetPhysicalDeviceSurfaceCapabilities2KHR); LOAD_FUNCPTR(vkGetPhysicalDeviceSurfaceCapabilitiesKHR); + LOAD_OPTIONAL_FUNCPTR(vkGetPhysicalDeviceSurfaceFormats2KHR); + LOAD_FUNCPTR(vkGetPhysicalDeviceSurfaceFormatsKHR); #undef LOAD_FUNCPTR #undef LOAD_OPTIONAL_FUNCPTR
@@ -481,6 +568,8 @@ static const struct vulkan_funcs vulkan_funcs = .p_vkGetInstanceProcAddr = wayland_vkGetInstanceProcAddr, .p_vkGetPhysicalDeviceSurfaceCapabilities2KHR = wayland_vkGetPhysicalDeviceSurfaceCapabilities2KHR, .p_vkGetPhysicalDeviceSurfaceCapabilitiesKHR = wayland_vkGetPhysicalDeviceSurfaceCapabilitiesKHR, + .p_vkGetPhysicalDeviceSurfaceFormats2KHR = wayland_vkGetPhysicalDeviceSurfaceFormats2KHR, + .p_vkGetPhysicalDeviceSurfaceFormatsKHR = wayland_vkGetPhysicalDeviceSurfaceFormatsKHR, .p_wine_get_native_surface = wayland_wine_get_native_surface, };
From: Alexandros Frantzis alexandros.frantzis@collabora.com
This is a simple passthrough implementation to the native Vulkan driver, with the addition of a VkSurfaceKHR invalidation check. --- dlls/winewayland.drv/vulkan.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+)
diff --git a/dlls/winewayland.drv/vulkan.c b/dlls/winewayland.drv/vulkan.c index 0a827c69cce..2d30f83c62e 100644 --- a/dlls/winewayland.drv/vulkan.c +++ b/dlls/winewayland.drv/vulkan.c @@ -62,6 +62,7 @@ static VkResult (*pvkGetPhysicalDeviceSurfaceCapabilities2KHR)(VkPhysicalDevice, static VkResult (*pvkGetPhysicalDeviceSurfaceCapabilitiesKHR)(VkPhysicalDevice, VkSurfaceKHR, VkSurfaceCapabilitiesKHR *); static VkResult (*pvkGetPhysicalDeviceSurfaceFormats2KHR)(VkPhysicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR *, uint32_t *, VkSurfaceFormat2KHR *); static VkResult (*pvkGetPhysicalDeviceSurfaceFormatsKHR)(VkPhysicalDevice, VkSurfaceKHR, uint32_t *, VkSurfaceFormatKHR *); +static VkResult (*pvkGetPhysicalDeviceSurfacePresentModesKHR)(VkPhysicalDevice, VkSurfaceKHR, uint32_t *, VkPresentModeKHR *);
static void *vulkan_handle; static const struct vulkan_funcs vulkan_funcs; @@ -521,6 +522,22 @@ static VkResult wayland_vkGetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice ph count, formats); }
+static VkResult wayland_vkGetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice phys_dev, + VkSurfaceKHR surface, + uint32_t *count, + VkPresentModeKHR *modes) +{ + struct wine_vk_surface *wine_vk_surface = wine_vk_surface_from_handle(surface); + + TRACE("%p, 0x%s, %p, %p\n", phys_dev, wine_dbgstr_longlong(surface), count, modes); + + if (!wine_vk_surface_is_valid(wine_vk_surface)) + return VK_ERROR_SURFACE_LOST_KHR; + + return pvkGetPhysicalDeviceSurfacePresentModesKHR(phys_dev, wine_vk_surface->native, + count, modes); +} + static VkSurfaceKHR wayland_wine_get_native_surface(VkSurfaceKHR surface) { return wine_vk_surface_from_handle(surface)->native; @@ -547,6 +564,7 @@ static void wine_vk_init(void) LOAD_FUNCPTR(vkGetPhysicalDeviceSurfaceCapabilitiesKHR); LOAD_OPTIONAL_FUNCPTR(vkGetPhysicalDeviceSurfaceFormats2KHR); LOAD_FUNCPTR(vkGetPhysicalDeviceSurfaceFormatsKHR); + LOAD_FUNCPTR(vkGetPhysicalDeviceSurfacePresentModesKHR); #undef LOAD_FUNCPTR #undef LOAD_OPTIONAL_FUNCPTR
@@ -570,6 +588,7 @@ static const struct vulkan_funcs vulkan_funcs = .p_vkGetPhysicalDeviceSurfaceCapabilitiesKHR = wayland_vkGetPhysicalDeviceSurfaceCapabilitiesKHR, .p_vkGetPhysicalDeviceSurfaceFormats2KHR = wayland_vkGetPhysicalDeviceSurfaceFormats2KHR, .p_vkGetPhysicalDeviceSurfaceFormatsKHR = wayland_vkGetPhysicalDeviceSurfaceFormatsKHR, + .p_vkGetPhysicalDeviceSurfacePresentModesKHR = wayland_vkGetPhysicalDeviceSurfacePresentModesKHR, .p_wine_get_native_surface = wayland_wine_get_native_surface, };
From: Alexandros Frantzis alexandros.frantzis@collabora.com
This is a simple passthrough implementation to the native Vulkan driver, with the addition of a VkSurfaceKHR invalidation check. --- dlls/winewayland.drv/vulkan.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+)
diff --git a/dlls/winewayland.drv/vulkan.c b/dlls/winewayland.drv/vulkan.c index 2d30f83c62e..2d4c5f0f042 100644 --- a/dlls/winewayland.drv/vulkan.c +++ b/dlls/winewayland.drv/vulkan.c @@ -63,6 +63,7 @@ static VkResult (*pvkGetPhysicalDeviceSurfaceCapabilitiesKHR)(VkPhysicalDevice, static VkResult (*pvkGetPhysicalDeviceSurfaceFormats2KHR)(VkPhysicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR *, uint32_t *, VkSurfaceFormat2KHR *); static VkResult (*pvkGetPhysicalDeviceSurfaceFormatsKHR)(VkPhysicalDevice, VkSurfaceKHR, uint32_t *, VkSurfaceFormatKHR *); static VkResult (*pvkGetPhysicalDeviceSurfacePresentModesKHR)(VkPhysicalDevice, VkSurfaceKHR, uint32_t *, VkPresentModeKHR *); +static VkResult (*pvkGetPhysicalDeviceSurfaceSupportKHR)(VkPhysicalDevice, uint32_t, VkSurfaceKHR, VkBool32 *);
static void *vulkan_handle; static const struct vulkan_funcs vulkan_funcs; @@ -538,6 +539,22 @@ static VkResult wayland_vkGetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevi count, modes); }
+static VkResult wayland_vkGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice phys_dev, + uint32_t index, + VkSurfaceKHR surface, + VkBool32 *supported) +{ + struct wine_vk_surface *wine_vk_surface = wine_vk_surface_from_handle(surface); + + TRACE("%p, %u, 0x%s, %p\n", phys_dev, index, wine_dbgstr_longlong(surface), supported); + + if (!wine_vk_surface_is_valid(wine_vk_surface)) + return VK_ERROR_SURFACE_LOST_KHR; + + return pvkGetPhysicalDeviceSurfaceSupportKHR(phys_dev, index, wine_vk_surface->native, + supported); +} + static VkSurfaceKHR wayland_wine_get_native_surface(VkSurfaceKHR surface) { return wine_vk_surface_from_handle(surface)->native; @@ -565,6 +582,7 @@ static void wine_vk_init(void) LOAD_OPTIONAL_FUNCPTR(vkGetPhysicalDeviceSurfaceFormats2KHR); LOAD_FUNCPTR(vkGetPhysicalDeviceSurfaceFormatsKHR); LOAD_FUNCPTR(vkGetPhysicalDeviceSurfacePresentModesKHR); + LOAD_FUNCPTR(vkGetPhysicalDeviceSurfaceSupportKHR); #undef LOAD_FUNCPTR #undef LOAD_OPTIONAL_FUNCPTR
@@ -589,6 +607,7 @@ static const struct vulkan_funcs vulkan_funcs = .p_vkGetPhysicalDeviceSurfaceFormats2KHR = wayland_vkGetPhysicalDeviceSurfaceFormats2KHR, .p_vkGetPhysicalDeviceSurfaceFormatsKHR = wayland_vkGetPhysicalDeviceSurfaceFormatsKHR, .p_vkGetPhysicalDeviceSurfacePresentModesKHR = wayland_vkGetPhysicalDeviceSurfacePresentModesKHR, + .p_vkGetPhysicalDeviceSurfaceSupportKHR = wayland_vkGetPhysicalDeviceSurfaceSupportKHR, .p_wine_get_native_surface = wayland_wine_get_native_surface, };
From: Alexandros Frantzis alexandros.frantzis@collabora.com
This is a simple passthrough implementation to the corresponding Vulkan Wayland extension. --- dlls/winewayland.drv/vulkan.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
diff --git a/dlls/winewayland.drv/vulkan.c b/dlls/winewayland.drv/vulkan.c index 2d4c5f0f042..acccee1f122 100644 --- a/dlls/winewayland.drv/vulkan.c +++ b/dlls/winewayland.drv/vulkan.c @@ -64,6 +64,7 @@ static VkResult (*pvkGetPhysicalDeviceSurfaceFormats2KHR)(VkPhysicalDevice, cons static VkResult (*pvkGetPhysicalDeviceSurfaceFormatsKHR)(VkPhysicalDevice, VkSurfaceKHR, uint32_t *, VkSurfaceFormatKHR *); static VkResult (*pvkGetPhysicalDeviceSurfacePresentModesKHR)(VkPhysicalDevice, VkSurfaceKHR, uint32_t *, VkPresentModeKHR *); static VkResult (*pvkGetPhysicalDeviceSurfaceSupportKHR)(VkPhysicalDevice, uint32_t, VkSurfaceKHR, VkBool32 *); +static VkBool32 (*pvkGetPhysicalDeviceWaylandPresentationSupportKHR)(VkPhysicalDevice, uint32_t, struct wl_display *);
static void *vulkan_handle; static const struct vulkan_funcs vulkan_funcs; @@ -164,6 +165,8 @@ static const char *wine_vk_native_fn_name(const char *name) { if (!strcmp(name, "vkCreateWin32SurfaceKHR")) return "vkCreateWaylandSurfaceKHR"; + if (!strcmp(name, "vkGetPhysicalDeviceWin32PresentationSupportKHR")) + return "vkGetPhysicalDeviceWaylandPresentationSupportKHR";
return name; } @@ -555,6 +558,15 @@ static VkResult wayland_vkGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice ph supported); }
+static VkBool32 wayland_vkGetPhysicalDeviceWin32PresentationSupportKHR(VkPhysicalDevice phys_dev, + uint32_t index) +{ + TRACE("%p %u\n", phys_dev, index); + + return pvkGetPhysicalDeviceWaylandPresentationSupportKHR(phys_dev, index, + process_wayland.wl_display); +} + static VkSurfaceKHR wayland_wine_get_native_surface(VkSurfaceKHR surface) { return wine_vk_surface_from_handle(surface)->native; @@ -583,6 +595,7 @@ static void wine_vk_init(void) LOAD_FUNCPTR(vkGetPhysicalDeviceSurfaceFormatsKHR); LOAD_FUNCPTR(vkGetPhysicalDeviceSurfacePresentModesKHR); LOAD_FUNCPTR(vkGetPhysicalDeviceSurfaceSupportKHR); + LOAD_FUNCPTR(vkGetPhysicalDeviceWaylandPresentationSupportKHR); #undef LOAD_FUNCPTR #undef LOAD_OPTIONAL_FUNCPTR
@@ -608,6 +621,7 @@ static const struct vulkan_funcs vulkan_funcs = .p_vkGetPhysicalDeviceSurfaceFormatsKHR = wayland_vkGetPhysicalDeviceSurfaceFormatsKHR, .p_vkGetPhysicalDeviceSurfacePresentModesKHR = wayland_vkGetPhysicalDeviceSurfacePresentModesKHR, .p_vkGetPhysicalDeviceSurfaceSupportKHR = wayland_vkGetPhysicalDeviceSurfaceSupportKHR, + .p_vkGetPhysicalDeviceWin32PresentationSupportKHR = wayland_vkGetPhysicalDeviceWin32PresentationSupportKHR, .p_wine_get_native_surface = wayland_wine_get_native_surface, };
From: Alexandros Frantzis alexandros.frantzis@collabora.com
--- dlls/winewayland.drv/vulkan.c | 46 +++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+)
diff --git a/dlls/winewayland.drv/vulkan.c b/dlls/winewayland.drv/vulkan.c index acccee1f122..d9f43387ed2 100644 --- a/dlls/winewayland.drv/vulkan.c +++ b/dlls/winewayland.drv/vulkan.c @@ -52,6 +52,7 @@ typedef struct VkWaylandSurfaceCreateInfoKHR } VkWaylandSurfaceCreateInfoKHR;
static VkResult (*pvkCreateInstance)(const VkInstanceCreateInfo *, const VkAllocationCallbacks *, VkInstance *); +static VkResult (*pvkCreateSwapchainKHR)(VkDevice, const VkSwapchainCreateInfoKHR *, const VkAllocationCallbacks *, VkSwapchainKHR *); static VkResult (*pvkCreateWaylandSurfaceKHR)(VkInstance, const VkWaylandSurfaceCreateInfoKHR *, const VkAllocationCallbacks *, VkSurfaceKHR *); static void (*pvkDestroyInstance)(VkInstance, const VkAllocationCallbacks *); static void (*pvkDestroySurfaceKHR)(VkInstance, VkSurfaceKHR, const VkAllocationCallbacks *); @@ -230,6 +231,49 @@ static VkResult wayland_vkCreateInstance(const VkInstanceCreateInfo *create_info return res; }
+static VkResult wayland_vkCreateSwapchainKHR(VkDevice device, + const VkSwapchainCreateInfoKHR *create_info, + const VkAllocationCallbacks *allocator, + VkSwapchainKHR *swapchain) +{ + VkResult res; + VkSwapchainCreateInfoKHR create_info_host; + struct wine_vk_surface *wine_vk_surface; + + TRACE("%p %p %p %p\n", device, create_info, allocator, swapchain); + + if (allocator) + FIXME("Support for allocation callbacks not implemented yet\n"); + + wine_vk_surface = wine_vk_surface_from_handle(create_info->surface); + if (!wine_vk_surface_is_valid(wine_vk_surface)) + return VK_ERROR_SURFACE_LOST_KHR; + + create_info_host = *create_info; + create_info_host.surface = wine_vk_surface->native; + + /* Some apps do not properly handle a 0x0 image extent in capabilities, + * and erroneously try to create a swapchain with it, so use the minimum + * 1x1 to accommodate them. */ + if (create_info_host.imageExtent.width == 0 || + create_info_host.imageExtent.height == 0) + { + create_info_host.imageExtent.width = 1; + create_info_host.imageExtent.height = 1; + } + + res = pvkCreateSwapchainKHR(device, &create_info_host, NULL /* allocator */, + swapchain); + if (res != VK_SUCCESS) + { + ERR("Failed to create vulkan wayland swapchain, res=%d\n", res); + return res; + } + + TRACE("Created swapchain=0x%s\n", wine_dbgstr_longlong(*swapchain)); + return res; +} + static VkResult wayland_vkCreateWin32SurfaceKHR(VkInstance instance, const VkWin32SurfaceCreateInfoKHR *create_info, const VkAllocationCallbacks *allocator, @@ -583,6 +627,7 @@ static void wine_vk_init(void) #define LOAD_FUNCPTR(f) if (!(p##f = dlsym(vulkan_handle, #f))) goto fail #define LOAD_OPTIONAL_FUNCPTR(f) p##f = dlsym(vulkan_handle, #f) LOAD_FUNCPTR(vkCreateInstance); + LOAD_FUNCPTR(vkCreateSwapchainKHR); LOAD_FUNCPTR(vkCreateWaylandSurfaceKHR); LOAD_FUNCPTR(vkDestroyInstance); LOAD_FUNCPTR(vkDestroySurfaceKHR); @@ -609,6 +654,7 @@ fail: static const struct vulkan_funcs vulkan_funcs = { .p_vkCreateInstance = wayland_vkCreateInstance, + .p_vkCreateSwapchainKHR = wayland_vkCreateSwapchainKHR, .p_vkCreateWin32SurfaceKHR = wayland_vkCreateWin32SurfaceKHR, .p_vkDestroyInstance = wayland_vkDestroyInstance, .p_vkDestroySurfaceKHR = wayland_vkDestroySurfaceKHR,
From: Alexandros Frantzis alexandros.frantzis@collabora.com
--- dlls/winewayland.drv/vulkan.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
diff --git a/dlls/winewayland.drv/vulkan.c b/dlls/winewayland.drv/vulkan.c index d9f43387ed2..4065419ada4 100644 --- a/dlls/winewayland.drv/vulkan.c +++ b/dlls/winewayland.drv/vulkan.c @@ -56,6 +56,7 @@ static VkResult (*pvkCreateSwapchainKHR)(VkDevice, const VkSwapchainCreateInfoKH static VkResult (*pvkCreateWaylandSurfaceKHR)(VkInstance, const VkWaylandSurfaceCreateInfoKHR *, const VkAllocationCallbacks *, VkSurfaceKHR *); static void (*pvkDestroyInstance)(VkInstance, const VkAllocationCallbacks *); static void (*pvkDestroySurfaceKHR)(VkInstance, VkSurfaceKHR, const VkAllocationCallbacks *); +static void (*pvkDestroySwapchainKHR)(VkDevice, VkSwapchainKHR, const VkAllocationCallbacks *); static VkResult (*pvkEnumerateInstanceExtensionProperties)(const char *, uint32_t *, VkExtensionProperties *); static void * (*pvkGetDeviceProcAddr)(VkDevice, const char *); static void * (*pvkGetInstanceProcAddr)(VkInstance, const char *); @@ -370,6 +371,18 @@ static void wayland_vkDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surfac wine_vk_surface_destroy(wine_vk_surface); }
+static void wayland_vkDestroySwapchainKHR(VkDevice device, + VkSwapchainKHR swapchain, + const VkAllocationCallbacks *allocator) +{ + TRACE("%p, 0x%s %p\n", device, wine_dbgstr_longlong(swapchain), allocator); + + if (allocator) + FIXME("Support for allocation callbacks not implemented yet\n"); + + pvkDestroySwapchainKHR(device, swapchain, NULL /* allocator */); +} + static VkResult wayland_vkEnumerateInstanceExtensionProperties(const char *layer_name, uint32_t *count, VkExtensionProperties* properties) @@ -631,6 +644,7 @@ static void wine_vk_init(void) LOAD_FUNCPTR(vkCreateWaylandSurfaceKHR); LOAD_FUNCPTR(vkDestroyInstance); LOAD_FUNCPTR(vkDestroySurfaceKHR); + LOAD_FUNCPTR(vkDestroySwapchainKHR); LOAD_FUNCPTR(vkEnumerateInstanceExtensionProperties); LOAD_FUNCPTR(vkGetDeviceProcAddr); LOAD_FUNCPTR(vkGetInstanceProcAddr); @@ -658,6 +672,7 @@ static const struct vulkan_funcs vulkan_funcs = .p_vkCreateWin32SurfaceKHR = wayland_vkCreateWin32SurfaceKHR, .p_vkDestroyInstance = wayland_vkDestroyInstance, .p_vkDestroySurfaceKHR = wayland_vkDestroySurfaceKHR, + .p_vkDestroySwapchainKHR = wayland_vkDestroySwapchainKHR, .p_vkEnumerateInstanceExtensionProperties = wayland_vkEnumerateInstanceExtensionProperties, .p_vkGetDeviceProcAddr = wayland_vkGetDeviceProcAddr, .p_vkGetInstanceProcAddr = wayland_vkGetInstanceProcAddr,
From: Alexandros Frantzis alexandros.frantzis@collabora.com
This is a simple passthrough implementation to the native Vulkan driver. --- dlls/winewayland.drv/vulkan.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/dlls/winewayland.drv/vulkan.c b/dlls/winewayland.drv/vulkan.c index 4065419ada4..edfef08cc3a 100644 --- a/dlls/winewayland.drv/vulkan.c +++ b/dlls/winewayland.drv/vulkan.c @@ -67,6 +67,7 @@ static VkResult (*pvkGetPhysicalDeviceSurfaceFormatsKHR)(VkPhysicalDevice, VkSur static VkResult (*pvkGetPhysicalDeviceSurfacePresentModesKHR)(VkPhysicalDevice, VkSurfaceKHR, uint32_t *, VkPresentModeKHR *); static VkResult (*pvkGetPhysicalDeviceSurfaceSupportKHR)(VkPhysicalDevice, uint32_t, VkSurfaceKHR, VkBool32 *); static VkBool32 (*pvkGetPhysicalDeviceWaylandPresentationSupportKHR)(VkPhysicalDevice, uint32_t, struct wl_display *); +static VkResult (*pvkGetSwapchainImagesKHR)(VkDevice, VkSwapchainKHR, uint32_t *, VkImage *);
static void *vulkan_handle; static const struct vulkan_funcs vulkan_funcs; @@ -624,6 +625,14 @@ static VkBool32 wayland_vkGetPhysicalDeviceWin32PresentationSupportKHR(VkPhysica process_wayland.wl_display); }
+static VkResult wayland_vkGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, + uint32_t *count, VkImage *images) +{ + TRACE("%p, 0x%s %p %p\n", device, wine_dbgstr_longlong(swapchain), count, images); + + return pvkGetSwapchainImagesKHR(device, swapchain, count, images); +} + static VkSurfaceKHR wayland_wine_get_native_surface(VkSurfaceKHR surface) { return wine_vk_surface_from_handle(surface)->native; @@ -655,6 +664,7 @@ static void wine_vk_init(void) LOAD_FUNCPTR(vkGetPhysicalDeviceSurfacePresentModesKHR); LOAD_FUNCPTR(vkGetPhysicalDeviceSurfaceSupportKHR); LOAD_FUNCPTR(vkGetPhysicalDeviceWaylandPresentationSupportKHR); + LOAD_FUNCPTR(vkGetSwapchainImagesKHR); #undef LOAD_FUNCPTR #undef LOAD_OPTIONAL_FUNCPTR
@@ -683,6 +693,7 @@ static const struct vulkan_funcs vulkan_funcs = .p_vkGetPhysicalDeviceSurfacePresentModesKHR = wayland_vkGetPhysicalDeviceSurfacePresentModesKHR, .p_vkGetPhysicalDeviceSurfaceSupportKHR = wayland_vkGetPhysicalDeviceSurfaceSupportKHR, .p_vkGetPhysicalDeviceWin32PresentationSupportKHR = wayland_vkGetPhysicalDeviceWin32PresentationSupportKHR, + .p_vkGetSwapchainImagesKHR = wayland_vkGetSwapchainImagesKHR, .p_wine_get_native_surface = wayland_wine_get_native_surface, };
Rémi Bernon (@rbernon) commented about dlls/winewayland.drv/vulkan.c:
- VkSurfaceFormatKHR *formats_host;
- uint32_t i;
- VkResult result;
- TRACE("%p, %p, %p, %p\n", phys_dev, surface_info, count, formats);
- if (!wine_vk_surface_is_valid(wine_vk_surface))
return VK_ERROR_SURFACE_LOST_KHR;
- surface_info_host = *surface_info;
- surface_info_host.surface = wine_vk_surface->native;
- if (pvkGetPhysicalDeviceSurfaceFormats2KHR)
- {
return pvkGetPhysicalDeviceSurfaceFormats2KHR(phys_dev, surface_info,
count, formats);
```suggestion:-1+0 return pvkGetPhysicalDeviceSurfaceFormats2KHR(phys_dev, &surface_info_host, count, formats); ```
I'd also reorder the commits to follow the usual d3d call sequence, and more gradually progress in the d3d11 tests for instance. I did that and pushed to https://gitlab.winehq.org/rbernon/wine/-/commits/tmp-4456 with the fix above.