From f6901e4a3df2bd9ea560033a1391287ac0a904ea Mon Sep 17 00:00:00 2001 From: Luflosi Date: Fri, 17 Jan 2020 13:14:32 +0100 Subject: [PATCH 1/3] Cocoa: Add support for VK_EXT_metal_surface From upstream: https://github.com/glfw/glfw/commit/c5cb4a253a9c304b136cac01a378567dc46e0320. --- glfw/cocoa_platform.h | 21 ++++++++++++++++++++- glfw/cocoa_window.m | 38 ++++++++++++++++++++++++++++++++++++-- glfw/glfw3.h | 5 +++-- glfw/internal.h | 5 +++++ glfw/vulkan.c | 5 +++++ 5 files changed, 69 insertions(+), 5 deletions(-) diff --git a/glfw/cocoa_platform.h b/glfw/cocoa_platform.h index 32c16292b..f874a8da8 100644 --- a/glfw/cocoa_platform.h +++ b/glfw/cocoa_platform.h @@ -65,13 +65,15 @@ typedef void* CVDisplayLinkRef; #endif -typedef VkFlags VkMacOSSurfaceCreateFlagsMVK; typedef int (* GLFWcocoatextinputfilterfun)(int,int,unsigned int, unsigned long); typedef bool (* GLFWapplicationshouldhandlereopenfun)(int); typedef void (* GLFWapplicationwillfinishlaunchingfun)(void); typedef bool (* GLFWcocoatogglefullscreenfun)(GLFWwindow*); typedef void (* GLFWcocoarenderframefun)(GLFWwindow*); +#if defined(VK_USE_PLATFORM_MACOS_MVK) +typedef VkFlags VkMacOSSurfaceCreateFlagsMVK; + typedef struct VkMacOSSurfaceCreateInfoMVK { VkStructureType sType; @@ -82,6 +84,23 @@ typedef struct VkMacOSSurfaceCreateInfoMVK typedef VkResult (APIENTRY *PFN_vkCreateMacOSSurfaceMVK)(VkInstance,const VkMacOSSurfaceCreateInfoMVK*,const VkAllocationCallbacks*,VkSurfaceKHR*); +#elif defined(VK_USE_PLATFORM_METAL_EXT) +#define VK_EXT_metal_surface 1 +typedef void CAMetalLayer; + +#define VK_EXT_METAL_SURFACE_SPEC_VERSION 1 +#define VK_EXT_METAL_SURFACE_EXTENSION_NAME "VK_EXT_metal_surface" +typedef VkFlags VkMetalSurfaceCreateFlagsEXT; +typedef struct VkMetalSurfaceCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkMetalSurfaceCreateFlagsEXT flags; + const CAMetalLayer* pLayer; +} VkMetalSurfaceCreateInfoEXT; + +typedef VkResult (APIENTRY *PFN_vkCreateMetalSurfaceEXT)(VkInstance, const VkMetalSurfaceCreateInfoEXT*, const VkAllocationCallbacks*, VkSurfaceKHR*); +#endif + #include "posix_thread.h" #include "cocoa_joystick.h" #include "nsgl_context.h" diff --git a/glfw/cocoa_window.m b/glfw/cocoa_window.m index e431995b1..3749abaae 100644 --- a/glfw/cocoa_window.m +++ b/glfw/cocoa_window.m @@ -2079,11 +2079,19 @@ const char* _glfwPlatformGetClipboardString(void) void _glfwPlatformGetRequiredInstanceExtensions(char** extensions) { +#if defined(VK_USE_PLATFORM_MACOS_MVK) if (!_glfw.vk.KHR_surface || !_glfw.vk.MVK_macos_surface) return; extensions[0] = "VK_KHR_surface"; extensions[1] = "VK_MVK_macos_surface"; + +#elif defined(VK_USE_PLATFORM_METAL_EXT) + if (!_glfw.vk.KHR_surface || !_glfw.vk.EXT_metal_surface) + return; + extensions[0] = "VK_KHR_surface"; + extensions[1] = "VK_EXT_metal_surface"; +#endif } int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance UNUSED, @@ -2100,9 +2108,11 @@ VkResult _glfwPlatformCreateWindowSurface(VkInstance instance, { #if MAC_OS_X_VERSION_MAX_ALLOWED >= 101100 VkResult err; - VkMacOSSurfaceCreateInfoMVK sci; - PFN_vkCreateMacOSSurfaceMVK vkCreateMacOSSurfaceMVK; +#if defined(VK_USE_PLATFORM_MACOS_MVK) + VkMacOSSurfaceCreateInfoMVK sci; + + PFN_vkCreateMacOSSurfaceMVK vkCreateMacOSSurfaceMVK; vkCreateMacOSSurfaceMVK = (PFN_vkCreateMacOSSurfaceMVK) vkGetInstanceProcAddr(instance, "vkCreateMacOSSurfaceMVK"); if (!vkCreateMacOSSurfaceMVK) @@ -2112,6 +2122,20 @@ VkResult _glfwPlatformCreateWindowSurface(VkInstance instance, return VK_ERROR_EXTENSION_NOT_PRESENT; } +#elif defined(VK_USE_PLATFORM_METAL_EXT) + VkMetalSurfaceCreateInfoEXT sci; + + PFN_vkCreateMetalSurfaceEXT vkCreateMetalSurfaceEXT; + vkCreateMetalSurfaceEXT = (PFN_vkCreateMetalSurfaceEXT) + vkGetInstanceProcAddr(instance, "vkCreateMetalSurfaceEXT"); + if (!vkCreateMetalSurfaceEXT) + { + _glfwInputError(GLFW_API_UNAVAILABLE, + "Cocoa: Vulkan instance missing VK_EXT_metal_surface extension"); + return VK_ERROR_EXTENSION_NOT_PRESENT; + } +#endif + // HACK: Dynamically load Core Animation to avoid adding an extra // dependency for the majority who don't use MoltenVK NSBundle* bundle = [NSBundle bundleWithPath:@"/System/Library/Frameworks/QuartzCore.framework"]; @@ -2138,10 +2162,20 @@ VkResult _glfwPlatformCreateWindowSurface(VkInstance instance, [window->ns.view setWantsLayer:YES]; memset(&sci, 0, sizeof(sci)); +#if defined(VK_USE_PLATFORM_MACOS_MVK) sci.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK; sci.pView = window->ns.view; err = vkCreateMacOSSurfaceMVK(instance, &sci, allocator, surface); + +#elif defined(VK_USE_PLATFORM_METAL_EXT) + sci.sType = VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT; + sci.pNext = NULL; + sci.flags = 0; + sci.pLayer = window->ns.layer; + + err = vkCreateMetalSurfaceEXT(instance, &sci, allocator, surface); +#endif if (err) { _glfwInputError(GLFW_PLATFORM_ERROR, diff --git a/glfw/glfw3.h b/glfw/glfw3.h index acc9f6844..3822e3754 100644 --- a/glfw/glfw3.h +++ b/glfw/glfw3.h @@ -5566,8 +5566,9 @@ GLFWAPI int glfwVulkanSupported(void); * returned array, as it is an error to specify an extension more than once in * the `VkInstanceCreateInfo` struct. * - * @remark @macos This function currently only supports the - * `VK_MVK_macos_surface` extension from MoltenVK. + * @remark @macos This function currently supports either the + * `VK_MVK_macos_surface` extension from MoltenVK or `VK_EXT_metal_surface` + * extension. * * @pointer_lifetime The returned array is allocated and freed by GLFW. You * should not free it yourself. It is guaranteed to be valid only until the diff --git a/glfw/internal.h b/glfw/internal.h index 17a7b5446..047296443 100644 --- a/glfw/internal.h +++ b/glfw/internal.h @@ -132,6 +132,7 @@ typedef enum VkStructureType VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR = 1000006000, VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR = 1000009000, VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK = 1000123000, + VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT = 1000217000, VK_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF } VkStructureType; @@ -587,7 +588,11 @@ struct _GLFWlibrary #if defined(_GLFW_WIN32) bool KHR_win32_surface; #elif defined(_GLFW_COCOA) + #if defined(VK_USE_PLATFORM_MACOS_MVK) bool MVK_macos_surface; + #elif defined(VK_USE_PLATFORM_METAL_EXT) + bool EXT_metal_surface; + #endif #elif defined(_GLFW_X11) bool KHR_xlib_surface; bool KHR_xcb_surface; diff --git a/glfw/vulkan.c b/glfw/vulkan.c index 421248bc4..7827a0d7c 100644 --- a/glfw/vulkan.c +++ b/glfw/vulkan.c @@ -128,8 +128,13 @@ bool _glfwInitVulkan(int mode) else if (strcmp(ep[i].extensionName, "VK_KHR_win32_surface") == 0) _glfw.vk.KHR_win32_surface = true; #elif defined(_GLFW_COCOA) + #if defined(VK_USE_PLATFORM_MACOS_MVK) else if (strcmp(ep[i].extensionName, "VK_MVK_macos_surface") == 0) _glfw.vk.MVK_macos_surface = true; + #elif defined(VK_USE_PLATFORM_METAL_EXT) + else if (strcmp(ep[i].extensionName, "VK_EXT_metal_surface") == 0) + _glfw.vk.EXT_metal_surface = true; + #endif #elif defined(_GLFW_X11) else if (strcmp(ep[i].extensionName, "VK_KHR_xlib_surface") == 0) _glfw.vk.KHR_xlib_surface = true; From 3581ffe04bc1405825f62bb5d8a1146161593797 Mon Sep 17 00:00:00 2001 From: Luflosi Date: Fri, 17 Jan 2020 14:08:47 +0100 Subject: [PATCH 2/3] Cocoa: Select Vulkan surface extension at runtime From upstream: https://github.com/glfw/glfw/commit/15d91801b7ac3d52779ec7330f2a1c0128fb57df. --- glfw/cocoa_platform.h | 20 +++----- glfw/cocoa_window.m | 104 ++++++++++++++++++++---------------------- glfw/internal.h | 3 -- glfw/vulkan.c | 3 -- 4 files changed, 56 insertions(+), 74 deletions(-) diff --git a/glfw/cocoa_platform.h b/glfw/cocoa_platform.h index f874a8da8..226950a3f 100644 --- a/glfw/cocoa_platform.h +++ b/glfw/cocoa_platform.h @@ -71,8 +71,8 @@ typedef void (* GLFWapplicationwillfinishlaunchingfun)(void); typedef bool (* GLFWcocoatogglefullscreenfun)(GLFWwindow*); typedef void (* GLFWcocoarenderframefun)(GLFWwindow*); -#if defined(VK_USE_PLATFORM_MACOS_MVK) typedef VkFlags VkMacOSSurfaceCreateFlagsMVK; +typedef VkFlags VkMetalSurfaceCreateFlagsEXT; typedef struct VkMacOSSurfaceCreateInfoMVK { @@ -82,24 +82,16 @@ typedef struct VkMacOSSurfaceCreateInfoMVK const void* pView; } VkMacOSSurfaceCreateInfoMVK; -typedef VkResult (APIENTRY *PFN_vkCreateMacOSSurfaceMVK)(VkInstance,const VkMacOSSurfaceCreateInfoMVK*,const VkAllocationCallbacks*,VkSurfaceKHR*); - -#elif defined(VK_USE_PLATFORM_METAL_EXT) -#define VK_EXT_metal_surface 1 -typedef void CAMetalLayer; - -#define VK_EXT_METAL_SURFACE_SPEC_VERSION 1 -#define VK_EXT_METAL_SURFACE_EXTENSION_NAME "VK_EXT_metal_surface" -typedef VkFlags VkMetalSurfaceCreateFlagsEXT; -typedef struct VkMetalSurfaceCreateInfoEXT { +typedef struct VkMetalSurfaceCreateInfoEXT +{ VkStructureType sType; const void* pNext; VkMetalSurfaceCreateFlagsEXT flags; - const CAMetalLayer* pLayer; + const void* pLayer; } VkMetalSurfaceCreateInfoEXT; -typedef VkResult (APIENTRY *PFN_vkCreateMetalSurfaceEXT)(VkInstance, const VkMetalSurfaceCreateInfoEXT*, const VkAllocationCallbacks*, VkSurfaceKHR*); -#endif +typedef VkResult (APIENTRY *PFN_vkCreateMacOSSurfaceMVK)(VkInstance,const VkMacOSSurfaceCreateInfoMVK*,const VkAllocationCallbacks*,VkSurfaceKHR*); +typedef VkResult (APIENTRY *PFN_vkCreateMetalSurfaceEXT)(VkInstance,const VkMetalSurfaceCreateInfoEXT*,const VkAllocationCallbacks*,VkSurfaceKHR*); #include "posix_thread.h" #include "cocoa_joystick.h" diff --git a/glfw/cocoa_window.m b/glfw/cocoa_window.m index 3749abaae..0d5f14f6f 100644 --- a/glfw/cocoa_window.m +++ b/glfw/cocoa_window.m @@ -2079,19 +2079,16 @@ const char* _glfwPlatformGetClipboardString(void) void _glfwPlatformGetRequiredInstanceExtensions(char** extensions) { -#if defined(VK_USE_PLATFORM_MACOS_MVK) - if (!_glfw.vk.KHR_surface || !_glfw.vk.MVK_macos_surface) - return; - - extensions[0] = "VK_KHR_surface"; - extensions[1] = "VK_MVK_macos_surface"; - -#elif defined(VK_USE_PLATFORM_METAL_EXT) - if (!_glfw.vk.KHR_surface || !_glfw.vk.EXT_metal_surface) - return; - extensions[0] = "VK_KHR_surface"; - extensions[1] = "VK_EXT_metal_surface"; -#endif + if (_glfw.vk.KHR_surface && _glfw.vk.EXT_metal_surface) + { + extensions[0] = "VK_KHR_surface"; + extensions[1] = "VK_EXT_metal_surface"; + } + else if (_glfw.vk.KHR_surface && _glfw.vk.MVK_macos_surface) + { + extensions[0] = "VK_KHR_surface"; + extensions[1] = "VK_MVK_macos_surface"; + } } int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance UNUSED, @@ -2107,35 +2104,6 @@ VkResult _glfwPlatformCreateWindowSurface(VkInstance instance, VkSurfaceKHR* surface) { #if MAC_OS_X_VERSION_MAX_ALLOWED >= 101100 - VkResult err; - -#if defined(VK_USE_PLATFORM_MACOS_MVK) - VkMacOSSurfaceCreateInfoMVK sci; - - PFN_vkCreateMacOSSurfaceMVK vkCreateMacOSSurfaceMVK; - vkCreateMacOSSurfaceMVK = (PFN_vkCreateMacOSSurfaceMVK) - vkGetInstanceProcAddr(instance, "vkCreateMacOSSurfaceMVK"); - if (!vkCreateMacOSSurfaceMVK) - { - _glfwInputError(GLFW_API_UNAVAILABLE, - "Cocoa: Vulkan instance missing VK_MVK_macos_surface extension"); - return VK_ERROR_EXTENSION_NOT_PRESENT; - } - -#elif defined(VK_USE_PLATFORM_METAL_EXT) - VkMetalSurfaceCreateInfoEXT sci; - - PFN_vkCreateMetalSurfaceEXT vkCreateMetalSurfaceEXT; - vkCreateMetalSurfaceEXT = (PFN_vkCreateMetalSurfaceEXT) - vkGetInstanceProcAddr(instance, "vkCreateMetalSurfaceEXT"); - if (!vkCreateMetalSurfaceEXT) - { - _glfwInputError(GLFW_API_UNAVAILABLE, - "Cocoa: Vulkan instance missing VK_EXT_metal_surface extension"); - return VK_ERROR_EXTENSION_NOT_PRESENT; - } -#endif - // HACK: Dynamically load Core Animation to avoid adding an extra // dependency for the majority who don't use MoltenVK NSBundle* bundle = [NSBundle bundleWithPath:@"/System/Library/Frameworks/QuartzCore.framework"]; @@ -2161,21 +2129,49 @@ VkResult _glfwPlatformCreateWindowSurface(VkInstance instance, [window->ns.view setLayer:window->ns.layer]; [window->ns.view setWantsLayer:YES]; - memset(&sci, 0, sizeof(sci)); -#if defined(VK_USE_PLATFORM_MACOS_MVK) - sci.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK; - sci.pView = window->ns.view; + VkResult err; - err = vkCreateMacOSSurfaceMVK(instance, &sci, allocator, surface); + if (_glfw.vk.EXT_metal_surface) + { + VkMetalSurfaceCreateInfoEXT sci; -#elif defined(VK_USE_PLATFORM_METAL_EXT) - sci.sType = VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT; - sci.pNext = NULL; - sci.flags = 0; - sci.pLayer = window->ns.layer; + PFN_vkCreateMetalSurfaceEXT vkCreateMetalSurfaceEXT; + vkCreateMetalSurfaceEXT = (PFN_vkCreateMetalSurfaceEXT) + vkGetInstanceProcAddr(instance, "vkCreateMetalSurfaceEXT"); + if (!vkCreateMetalSurfaceEXT) + { + _glfwInputError(GLFW_API_UNAVAILABLE, + "Cocoa: Vulkan instance missing VK_EXT_metal_surface extension"); + return VK_ERROR_EXTENSION_NOT_PRESENT; + } + + memset(&sci, 0, sizeof(sci)); + sci.sType = VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT; + sci.pLayer = window->ns.layer; + + err = vkCreateMetalSurfaceEXT(instance, &sci, allocator, surface); + } + else + { + VkMacOSSurfaceCreateInfoMVK sci; + + PFN_vkCreateMacOSSurfaceMVK vkCreateMacOSSurfaceMVK; + vkCreateMacOSSurfaceMVK = (PFN_vkCreateMacOSSurfaceMVK) + vkGetInstanceProcAddr(instance, "vkCreateMacOSSurfaceMVK"); + if (!vkCreateMacOSSurfaceMVK) + { + _glfwInputError(GLFW_API_UNAVAILABLE, + "Cocoa: Vulkan instance missing VK_MVK_macos_surface extension"); + return VK_ERROR_EXTENSION_NOT_PRESENT; + } + + memset(&sci, 0, sizeof(sci)); + sci.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK; + sci.pView = window->ns.view; + + err = vkCreateMacOSSurfaceMVK(instance, &sci, allocator, surface); + } - err = vkCreateMetalSurfaceEXT(instance, &sci, allocator, surface); -#endif if (err) { _glfwInputError(GLFW_PLATFORM_ERROR, diff --git a/glfw/internal.h b/glfw/internal.h index 047296443..ceb84d930 100644 --- a/glfw/internal.h +++ b/glfw/internal.h @@ -588,11 +588,8 @@ struct _GLFWlibrary #if defined(_GLFW_WIN32) bool KHR_win32_surface; #elif defined(_GLFW_COCOA) - #if defined(VK_USE_PLATFORM_MACOS_MVK) bool MVK_macos_surface; - #elif defined(VK_USE_PLATFORM_METAL_EXT) bool EXT_metal_surface; - #endif #elif defined(_GLFW_X11) bool KHR_xlib_surface; bool KHR_xcb_surface; diff --git a/glfw/vulkan.c b/glfw/vulkan.c index 7827a0d7c..3f5ba0161 100644 --- a/glfw/vulkan.c +++ b/glfw/vulkan.c @@ -128,13 +128,10 @@ bool _glfwInitVulkan(int mode) else if (strcmp(ep[i].extensionName, "VK_KHR_win32_surface") == 0) _glfw.vk.KHR_win32_surface = true; #elif defined(_GLFW_COCOA) - #if defined(VK_USE_PLATFORM_MACOS_MVK) else if (strcmp(ep[i].extensionName, "VK_MVK_macos_surface") == 0) _glfw.vk.MVK_macos_surface = true; - #elif defined(VK_USE_PLATFORM_METAL_EXT) else if (strcmp(ep[i].extensionName, "VK_EXT_metal_surface") == 0) _glfw.vk.EXT_metal_surface = true; - #endif #elif defined(_GLFW_X11) else if (strcmp(ep[i].extensionName, "VK_KHR_xlib_surface") == 0) _glfw.vk.KHR_xlib_surface = true; From e4fd12001ce2088530080b2562841af4670a3f97 Mon Sep 17 00:00:00 2001 From: Luflosi Date: Fri, 17 Jan 2020 14:12:05 +0100 Subject: [PATCH 3/3] Cocoa: Add fully dynamic loading of Vulkan loader From upstream: https://github.com/glfw/glfw/commit/7da87aaae7039cbdc132f8f563a2603c5e3c73a1. --- glfw/cocoa_init.m | 26 ++++++++++++++++++++++++++ glfw/cocoa_platform.h | 2 ++ glfw/vulkan.c | 2 ++ 3 files changed, 30 insertions(+) diff --git a/glfw/cocoa_init.m b/glfw/cocoa_init.m index bdad46aa8..5252614b7 100644 --- a/glfw/cocoa_init.m +++ b/glfw/cocoa_init.m @@ -529,6 +529,32 @@ static GLFWapplicationwillfinishlaunchingfun finish_launching_callback = NULL; @end +////////////////////////////////////////////////////////////////////////// +////// 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/glfw/cocoa_platform.h b/glfw/cocoa_platform.h index 226950a3f..bcad82fce 100644 --- a/glfw/cocoa_platform.h +++ b/glfw/cocoa_platform.h @@ -239,6 +239,8 @@ void _glfwRestoreVideoModeNS(_GLFWmonitor* monitor); float _glfwTransformYNS(float y); +void* _glfwLoadLocalVulkanLoaderNS(void); + void _glfwClearDisplayLinks(void); void _glfwRestartDisplayLinks(void); void _glfwDispatchTickCallback(void); diff --git a/glfw/vulkan.c b/glfw/vulkan.c index 3f5ba0161..fe8485210 100644 --- a/glfw/vulkan.c +++ b/glfw/vulkan.c @@ -57,6 +57,8 @@ bool _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