浏览代码

Cocoa: Add support for VK_EXT_metal_surface

This adds optional support for the VK_EXT_metal_surface instance
extension.

Closes #1619.
ByunghoonKim 5 年之前
父节点
当前提交
c5cb4a253a
共有 8 个文件被更改,包括 73 次插入7 次删除
  1. 2 0
      CMakeLists.txt
  2. 4 4
      docs/compat.dox
  3. 3 2
      include/GLFW/glfw3.h
  4. 18 0
      src/cocoa_platform.h
  5. 35 1
      src/cocoa_window.m
  6. 1 0
      src/glfw_config.h.in
  7. 5 0
      src/internal.h
  8. 5 0
      src/vulkan.c

+ 2 - 0
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")

+ 4 - 4
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`

+ 3 - 2
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

+ 18 - 0
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"

+ 35 - 1
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;
+
+#if defined(VK_USE_PLATFORM_MACOS_MVK)
     VkMacOSSurfaceCreateInfoMVK sci;
-    PFN_vkCreateMacOSSurfaceMVK vkCreateMacOSSurfaceMVK;
 
+    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,

+ 1 - 0
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

+ 5 - 0
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;

+ 5 - 0
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;