From 85172703dbcc851e159d69c91392a952ec17fa7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Thu, 16 Jan 2020 05:09:19 +0100 Subject: [PATCH] Cocoa: Add fully dynamic loading of Vulkan loader If the application is not linked against the Vulkan loader and relies on a third-party loader library or glfwGetInstanceProcAddress, then our call to dlopen will fail without a custom dyld environment variable. This adds a fallback of looking in the directory of the main executable, which matches the bundle structure recommended by the Vulkan SDK, making that finally work out of the box for fully dynamic loading. (cherry picked from commit 7da87aaae7039cbdc132f8f563a2603c5e3c73a1) --- README.md | 1 + src/cocoa_init.m | 26 ++++++++++++++++++++++++++ src/cocoa_platform.h | 2 ++ src/vulkan.c | 2 ++ 4 files changed, 31 insertions(+) diff --git a/README.md b/README.md index 4e49646b..e69bc4bf 100644 --- a/README.md +++ b/README.md @@ -119,6 +119,7 @@ information on what to include when reporting a bug. ## Changelog - [Cocoa] Added support for `VK_EXT_metal_surface` (#1619) + - [Cocoa] Added locating the Vulkan loader at runtime in an application bundle - [X11] Bugfix: `glfwFocusWindow` could terminate on older WMs or without a WM - [X11] Bugfix: Creating an undecorated window could fail with BadMatch (#1620) diff --git a/src/cocoa_init.m b/src/cocoa_init.m index 6dfb6f56..579b6e6c 100644 --- a/src/cocoa_init.m +++ b/src/cocoa_init.m @@ -463,6 +463,32 @@ static GLFWbool initializeTIS(void) @end // GLFWApplicationDelegate +////////////////////////////////////////////////////////////////////////// +////// GLFW internal API ////// +////////////////////////////////////////////////////////////////////////// + +void* _glfwLoadLocalVulkanLoaderNS(void) +{ + CFBundleRef bundle = CFBundleGetMainBundle(); + if (!bundle) + return NULL; + + CFURLRef url = + CFBundleCopyAuxiliaryExecutableURL(bundle, CFSTR("libvulkan.1.dylib")); + if (!url) + return NULL; + + char path[PATH_MAX]; + void* handle = NULL; + + if (CFURLGetFileSystemRepresentation(url, true, (UInt8*) path, sizeof(path) - 1)) + handle = _glfw_dlopen(path); + + CFRelease(url); + return handle; +} + + ////////////////////////////////////////////////////////////////////////// ////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// diff --git a/src/cocoa_platform.h b/src/cocoa_platform.h index 66c4767b..15c21696 100644 --- a/src/cocoa_platform.h +++ b/src/cocoa_platform.h @@ -207,3 +207,5 @@ void _glfwRestoreVideoModeNS(_GLFWmonitor* monitor); float _glfwTransformYNS(float y); +void* _glfwLoadLocalVulkanLoaderNS(void); + diff --git a/src/vulkan.c b/src/vulkan.c index 61b40ea3..22c54e4a 100644 --- a/src/vulkan.c +++ b/src/vulkan.c @@ -57,6 +57,8 @@ GLFWbool _glfwInitVulkan(int mode) _glfw.vk.handle = _glfw_dlopen("vulkan-1.dll"); #elif defined(_GLFW_COCOA) _glfw.vk.handle = _glfw_dlopen("libvulkan.1.dylib"); + if (!_glfw.vk.handle) + _glfw.vk.handle = _glfwLoadLocalVulkanLoaderNS(); #else _glfw.vk.handle = _glfw_dlopen("libvulkan.so.1"); #endif