From 7da87aaae7039cbdc132f8f563a2603c5e3c73a1 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. --- 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 0fea46e9..15593c67 100644 --- a/README.md +++ b/README.md @@ -142,6 +142,7 @@ information on what to include when reporting a bug. window (#1499) - [Win32] Bugfix: Disabled cursor mode interfered with some non-client actions - [Cocoa] Added support for `VK_EXT_metal_surface` (#1619) + - [Cocoa] Added locating the Vulkan loader at runtime in an application bundle - [Cocoa] Removed dependency on the CoreVideo framework - [Cocoa] Bugfix: `glfwSetWindowSize` used a bottom-left anchor point (#1553) - [Cocoa] Bugfix: Window remained on screen after destruction until event poll diff --git a/src/cocoa_init.m b/src/cocoa_init.m index 7e75299a..cbc9462f 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 e9cd5843..9a979af2 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 0bbcb83d..b5340520 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