diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d8719da..d5439f12 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -145,6 +145,8 @@ elseif (WIN32) elseif (APPLE) set(_GLFW_COCOA 1) message(STATUS "Using Cocoa for window creation") + set(VK_USE_PLATFORM_METAL_EXT 1) + message(STATUS "Using VK_EXT_metal_surface") elseif (UNIX) set(_GLFW_X11 1) message(STATUS "Using X11 for window creation") diff --git a/docs/compat.dox b/docs/compat.dox index c437e350..99934e46 100644 --- a/docs/compat.dox +++ b/docs/compat.dox @@ -268,10 +268,10 @@ surfaces on Microsoft Windows. If any of these extensions are not available, @ref glfwGetRequiredInstanceExtensions will return an empty list and window surface creation will fail. -GLFW uses the `VK_KHR_surface` and `VK_MVK_macos_surface` extensions to create -surfaces on macOS. If any of these extensions are not available, @ref -glfwGetRequiredInstanceExtensions will return an empty list and window surface -creation will fail. +GLFW uses the `VK_KHR_surface` and either the `VK_MVK_macos_surface` or +`VK_EXT_metal_surface` extensions to create surfaces on macOS. If any of these +extensions are not available, @ref glfwGetRequiredInstanceExtensions will +return an empty list and window surface creation will fail. GLFW uses the `VK_KHR_surface` and either the `VK_KHR_xlib_surface` or `VK_KHR_xcb_surface` extensions to create surfaces on X11. If `VK_KHR_surface` diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index d6843f68..4f5f3607 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -5776,8 +5776,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/src/cocoa_platform.h b/src/cocoa_platform.h index 434f46dd..d1b51d6d 100644 --- a/src/cocoa_platform.h +++ b/src/cocoa_platform.h @@ -60,6 +60,7 @@ typedef void* id; #define NSWindowStyleMaskTitled NSTitledWindowMask #endif +#if defined(VK_USE_PLATFORM_MACOS_MVK) typedef VkFlags VkMacOSSurfaceCreateFlagsMVK; typedef struct VkMacOSSurfaceCreateInfoMVK @@ -72,6 +73,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/src/cocoa_window.m b/src/cocoa_window.m index 546f9a82..c8f084d5 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -1715,11 +1715,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, @@ -1738,9 +1746,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) @@ -1750,6 +1760,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"]; @@ -1776,10 +1800,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/src/glfw_config.h.in b/src/glfw_config.h.in index f4876da2..ae058965 100644 --- a/src/glfw_config.h.in +++ b/src/glfw_config.h.in @@ -40,6 +40,7 @@ #cmakedefine _GLFW_WIN32 // Define this to 1 if building GLFW for Cocoa #cmakedefine _GLFW_COCOA +#cmakedefine VK_USE_PLATFORM_METAL_EXT // Define this to 1 if building GLFW for Wayland #cmakedefine _GLFW_WAYLAND // Define this to 1 if building GLFW for OSMesa diff --git a/src/internal.h b/src/internal.h index 4c75c9b1..33342d9f 100644 --- a/src/internal.h +++ b/src/internal.h @@ -128,6 +128,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; @@ -558,7 +559,11 @@ struct _GLFWlibrary #if defined(_GLFW_WIN32) GLFWbool KHR_win32_surface; #elif defined(_GLFW_COCOA) + #if defined(VK_USE_PLATFORM_MACOS_MVK) GLFWbool MVK_macos_surface; + #elif defined(VK_USE_PLATFORM_METAL_EXT) + GLFWbool EXT_metal_surface; + #endif #elif defined(_GLFW_X11) GLFWbool KHR_xlib_surface; GLFWbool KHR_xcb_surface; diff --git a/src/vulkan.c b/src/vulkan.c index 6fd0af2c..f6b07ec8 100644 --- a/src/vulkan.c +++ b/src/vulkan.c @@ -128,8 +128,13 @@ GLFWbool _glfwInitVulkan(int mode) else if (strcmp(ep[i].extensionName, "VK_KHR_win32_surface") == 0) _glfw.vk.KHR_win32_surface = GLFW_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 = GLFW_TRUE; + #elif defined(VK_USE_PLATFORM_METAL_EXT) + else if (strcmp(ep[i].extensionName, "VK_EXT_metal_surface") == 0) + _glfw.vk.EXT_metal_surface = GLFW_TRUE; + #endif #elif defined(_GLFW_X11) else if (strcmp(ep[i].extensionName, "VK_KHR_xlib_surface") == 0) _glfw.vk.KHR_xlib_surface = GLFW_TRUE;