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 0fea46e9e3..15593c67c3 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 7e75299ace..cbc9462ff5 100644 --- a/src/cocoa_init.m +++ b/src/cocoa_init.m @@ -463,6 +463,32 @@ - (void)applicationDidHide:(NSNotification *)notification @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 e9cd584334..9a979af219 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 0bbcb83d57..b5340520b1 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