From: Rémi Bernon <rbernon(a)codeweavers.com> So that VulkanInit is only called when surface related functions are needed, breaking the re-entry when we call d3dkmt vulkan functions from update_display_cache, which is called when graphics drivers are loaded. --- dlls/win32u/vulkan.c | 73 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 64 insertions(+), 9 deletions(-) diff --git a/dlls/win32u/vulkan.c b/dlls/win32u/vulkan.c index 59b9364065e..5b128afe3cb 100644 --- a/dlls/win32u/vulkan.c +++ b/dlls/win32u/vulkan.c @@ -213,22 +213,14 @@ static const struct vulkan_driver_funcs nulldrv_funcs = .p_get_host_surface_extension = nulldrv_get_host_surface_extension, }; -static void vulkan_init(void) +static void vulkan_driver_init(void) { UINT status; - if (!(vulkan_handle = dlopen( SONAME_LIBVULKAN, RTLD_NOW ))) - { - ERR( "Failed to load %s\n", SONAME_LIBVULKAN ); - return; - } - if ((status = user_driver->pVulkanInit( WINE_VULKAN_DRIVER_VERSION, vulkan_handle, &driver_funcs )) && status != STATUS_NOT_IMPLEMENTED) { ERR( "Failed to initialize the driver vulkan functions, status %#x\n", status ); - dlclose( vulkan_handle ); - vulkan_handle = NULL; return; } @@ -239,6 +231,65 @@ static void vulkan_init(void) vulkan_funcs.p_vkGetPhysicalDeviceWin32PresentationSupportKHR = driver_funcs->p_vkGetPhysicalDeviceWin32PresentationSupportKHR; vulkan_funcs.p_get_host_surface_extension = driver_funcs->p_get_host_surface_extension; } +} + +static void vulkan_driver_load(void) +{ + static pthread_once_t init_once = PTHREAD_ONCE_INIT; + pthread_once( &init_once, vulkan_driver_init ); +} + +static VkResult lazydrv_vulkan_surface_create( HWND hwnd, VkInstance instance, VkSurfaceKHR *surface, void **private ) +{ + vulkan_driver_load(); + return driver_funcs->p_vulkan_surface_create( hwnd, instance, surface, private ); +} + +static void lazydrv_vulkan_surface_destroy( HWND hwnd, void *private ) +{ + vulkan_driver_load(); + return driver_funcs->p_vulkan_surface_destroy( hwnd, private ); +} + +static void lazydrv_vulkan_surface_detach( HWND hwnd, void *private ) +{ + vulkan_driver_load(); + return driver_funcs->p_vulkan_surface_detach( hwnd, private ); +} + +static void lazydrv_vulkan_surface_presented( HWND hwnd, VkResult result ) +{ + vulkan_driver_load(); + return driver_funcs->p_vulkan_surface_presented( hwnd, result ); +} + +static VkBool32 lazydrv_vkGetPhysicalDeviceWin32PresentationSupportKHR( VkPhysicalDevice device, uint32_t queue ) +{ + vulkan_driver_load(); + return driver_funcs->p_vkGetPhysicalDeviceWin32PresentationSupportKHR( device, queue ); +} + +static const char *lazydrv_get_host_surface_extension(void) +{ + vulkan_driver_load(); + return driver_funcs->p_get_host_surface_extension(); +} + +static const struct vulkan_driver_funcs lazydrv_funcs = +{ + .p_vulkan_surface_create = lazydrv_vulkan_surface_create, + .p_vulkan_surface_destroy = lazydrv_vulkan_surface_destroy, + .p_vulkan_surface_detach = lazydrv_vulkan_surface_detach, + .p_vulkan_surface_presented = lazydrv_vulkan_surface_presented, +}; + +static void vulkan_init(void) +{ + if (!(vulkan_handle = dlopen( SONAME_LIBVULKAN, RTLD_NOW ))) + { + ERR( "Failed to load %s\n", SONAME_LIBVULKAN ); + return; + } #define LOAD_FUNCPTR( f ) \ if (!(p_##f = dlsym( vulkan_handle, #f ))) \ @@ -254,6 +305,10 @@ static void vulkan_init(void) LOAD_FUNCPTR( vkGetDeviceProcAddr ); LOAD_FUNCPTR( vkGetInstanceProcAddr ); #undef LOAD_FUNCPTR + + driver_funcs = &lazydrv_funcs; + vulkan_funcs.p_vkGetPhysicalDeviceWin32PresentationSupportKHR = lazydrv_vkGetPhysicalDeviceWin32PresentationSupportKHR; + vulkan_funcs.p_get_host_surface_extension = lazydrv_get_host_surface_extension; } void vulkan_detach_surfaces( struct list *surfaces ) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/5616