Browse Source

vulkan: Add support for MoltenVK (Vulkan on macOS)

rdb 2 years ago
parent
commit
e7918d24d8

+ 23 - 1
makepanda/makepanda.py

@@ -923,13 +923,22 @@ if (COMPILER=="GCC"):
     SmartPkgEnable("OPUS",      "opusfile",  ("opusfile", "opus", "ogg"), ("ogg/ogg.h", "opus/opusfile.h", "opus"))
     SmartPkgEnable("OPUS",      "opusfile",  ("opusfile", "opus", "ogg"), ("ogg/ogg.h", "opus/opusfile.h", "opus"))
     SmartPkgEnable("JPEG",      "",          ("jpeg"), "jpeglib.h")
     SmartPkgEnable("JPEG",      "",          ("jpeg"), "jpeglib.h")
     SmartPkgEnable("PNG",       "libpng",    ("png"), "png.h", tool = "libpng-config")
     SmartPkgEnable("PNG",       "libpng",    ("png"), "png.h", tool = "libpng-config")
-    SmartPkgEnable("VULKAN",    "",          ("vulkan"), "vulkan/vulkan.h")
     SmartPkgEnable("GLSLANG",   "",          ("MachineIndependent", "GenericCodeGen", "SPIRV", "OSDependent", "OGLCompiler", "HLSL", "glslang-default-resource-limits"), "glslang/Public/ShaderLang.h")
     SmartPkgEnable("GLSLANG",   "",          ("MachineIndependent", "GenericCodeGen", "SPIRV", "OSDependent", "OGLCompiler", "HLSL", "glslang-default-resource-limits"), "glslang/Public/ShaderLang.h")
     SmartPkgEnable("SPIRV-TOOLS", "",        ("SPIRV-Tools-opt", "SPIRV-Tools"), "spirv-tools/optimizer.hpp")
     SmartPkgEnable("SPIRV-TOOLS", "",        ("SPIRV-Tools-opt", "SPIRV-Tools"), "spirv-tools/optimizer.hpp")
     SmartPkgEnable("SPIRV-CROSS-GLSL", "",   ("spirv-cross-core", "spirv-cross-glsl"), "spirv_cross/spirv_cross.hpp", thirdparty_dir="spirv-cross")
     SmartPkgEnable("SPIRV-CROSS-GLSL", "",   ("spirv-cross-core", "spirv-cross-glsl"), "spirv_cross/spirv_cross.hpp", thirdparty_dir="spirv-cross")
     SmartPkgEnable("SPIRV-CROSS-HLSL", "",   ("spirv-cross-core", "spirv-cross-hlsl"), "spirv_cross/spirv_cross.hpp", thirdparty_dir="spirv-cross")
     SmartPkgEnable("SPIRV-CROSS-HLSL", "",   ("spirv-cross-core", "spirv-cross-hlsl"), "spirv_cross/spirv_cross.hpp", thirdparty_dir="spirv-cross")
     SmartPkgEnable("MIMALLOC",  "",          ("mimalloc"), "mimalloc.h")
     SmartPkgEnable("MIMALLOC",  "",          ("mimalloc"), "mimalloc.h")
 
 
+    if "VULKAN" in SDK:
+        IncDirectory("VULKAN", os.path.join(SDK["VULKAN"], "include"))
+        if GetTarget() == "darwin":
+            # This gets copied to built/lib, below
+            LibName("VULKAN", "-lMoltenVK")
+        else:
+            LibName("VULKAN", os.path.join(SDK["VULKAN"], "lib", "libvulkan.so"))
+    else:
+        SmartPkgEnable("VULKAN", "", ("vulkan"), "vulkan/vulkan.h")
+
     # Copy freetype libraries to be specified after harfbuzz libraries as well,
     # Copy freetype libraries to be specified after harfbuzz libraries as well,
     # because there's a circular dependency between the two libraries.
     # because there's a circular dependency between the two libraries.
     if not PkgSkip("FREETYPE") and not PkgSkip("HARFBUZZ"):
     if not PkgSkip("FREETYPE") and not PkgSkip("HARFBUZZ"):
@@ -3201,6 +3210,16 @@ if GetTarget() == 'windows' and "VISUALSTUDIO" in SDK:
     if os.path.isfile(os.path.join(dir, "vcruntime" + vcver + ".dll")):
     if os.path.isfile(os.path.join(dir, "vcruntime" + vcver + ".dll")):
         CopyFile(GetOutputDir() + "/bin/", os.path.join(dir, "vcruntime" + vcver + ".dll"))
         CopyFile(GetOutputDir() + "/bin/", os.path.join(dir, "vcruntime" + vcver + ".dll"))
 
 
+# Copy over the MoltenVK library.
+if GetTarget() == 'darwin' and not PkgSkip("VULKAN") and "VULKAN" in SDK:
+    dylib = os.path.join(SDK["VULKAN"], "lib", "libMoltenVK.dylib")
+    target = os.path.join(GetOutputDir(), "lib", "libMoltenVK.dylib")
+    if NeedsBuild([target], [dylib]):
+        CopyFile(target, dylib)
+        oscmd('install_name_tool -id @loader_path/../lib/libMoltenVK.dylib ' + target)
+        oscmd('codesign -f -s - ' + target)
+        JustBuilt([target], [dylib])
+
 ########################################################################
 ########################################################################
 ##
 ##
 ## Copy various stuff into the build.
 ## Copy various stuff into the build.
@@ -4836,6 +4855,9 @@ if not PkgSkip("VULKAN"):
   if GetTarget() == 'windows':
   if GetTarget() == 'windows':
     TargetAdd('libp3vulkandisplay.dll', input='libp3windisplay.dll')
     TargetAdd('libp3vulkandisplay.dll', input='libp3windisplay.dll')
     TargetAdd('libp3vulkandisplay.dll', opts=['MODULE', 'VULKAN'])
     TargetAdd('libp3vulkandisplay.dll', opts=['MODULE', 'VULKAN'])
+  elif GetTarget() == 'darwin':
+    TargetAdd('libp3vulkandisplay.dll', input='p3cocoadisplay_composite1.obj')
+    TargetAdd('libp3vulkandisplay.dll', opts=['MODULE', 'VULKAN', 'CARBON'])
   else:
   else:
     TargetAdd('libp3vulkandisplay.dll', input='p3x11display_composite1.obj')
     TargetAdd('libp3vulkandisplay.dll', input='p3x11display_composite1.obj')
     TargetAdd('libp3vulkandisplay.dll', opts=['MODULE', 'VULKAN', 'X11', 'XRANDR', 'XF86DGA', 'XCURSOR'])
     TargetAdd('libp3vulkandisplay.dll', opts=['MODULE', 'VULKAN', 'X11', 'XRANDR', 'XF86DGA', 'XCURSOR'])

+ 9 - 0
makepanda/makepandacore.py

@@ -2623,6 +2623,15 @@ def SdkLocateAndroid():
         SDK["JDK"] = jdk_home
         SDK["JDK"] = jdk_home
 
 
 def SdkLocateVulkan():
 def SdkLocateVulkan():
+    if GetTarget() not in ('windows', 'darwin'):
+        return
+
+    path = os.environ.get('VULKAN_SDK')
+    if path and os.path.isdir(path):
+        print("Using Vulkan SDK at %s" % (path))
+        SDK["VULKAN"] = path
+        return
+
     if GetHost() != 'windows' or GetTarget() != 'windows':
     if GetHost() != 'windows' or GetTarget() != 'windows':
         return
         return
 
 

+ 3 - 0
panda/src/vulkandisplay/config_vulkandisplay.h

@@ -31,6 +31,9 @@ extern "C" EXPCL_VULKANDISPLAY int get_pipe_type_p3vulkandisplay();
 #ifdef _WIN32
 #ifdef _WIN32
 #define VK_USE_PLATFORM_WIN32_KHR
 #define VK_USE_PLATFORM_WIN32_KHR
 
 
+#elif defined(HAVE_COCOA)
+#define VK_USE_PLATFORM_METAL_EXT
+
 #elif defined(HAVE_X11)
 #elif defined(HAVE_X11)
 // Make sure Eigen is included first to avoid conflict
 // Make sure Eigen is included first to avoid conflict
 #include "lsimpleMatrix.h"
 #include "lsimpleMatrix.h"

+ 10 - 0
panda/src/vulkandisplay/vulkanGraphicsPipe.cxx

@@ -111,6 +111,12 @@ VulkanGraphicsPipe() : _max_allocation_size(0) {
     extensions.push_back("VK_KHR_win32_surface");
     extensions.push_back("VK_KHR_win32_surface");
     _has_surface_ext = true;
     _has_surface_ext = true;
   }
   }
+#elif defined(HAVE_COCOA)
+  if (has_instance_extension("VK_EXT_metal_surface")) {
+    extensions.push_back("VK_KHR_surface");
+    extensions.push_back("VK_EXT_metal_surface");
+    _has_surface_ext = true;
+  }
 #elif defined(HAVE_X11)
 #elif defined(HAVE_X11)
   if (has_instance_extension("VK_KHR_xlib_surface")) {
   if (has_instance_extension("VK_KHR_xlib_surface")) {
     extensions.push_back("VK_KHR_surface");
     extensions.push_back("VK_KHR_surface");
@@ -701,6 +707,10 @@ VulkanGraphicsPipe() : _max_allocation_size(0) {
 #endif  // !NDEBUG
 #endif  // !NDEBUG
 
 
   _is_valid = true;
   _is_valid = true;
+
+#ifdef HAVE_COCOA
+  _supported_types = OT_window | OT_buffer | OT_texture_buffer;
+#endif
 }
 }
 
 
 /**
 /**

+ 3 - 0
panda/src/vulkandisplay/vulkanGraphicsPipe.h

@@ -20,6 +20,9 @@
 #ifdef _WIN32
 #ifdef _WIN32
 #include "winGraphicsPipe.h"
 #include "winGraphicsPipe.h"
 typedef WinGraphicsPipe BaseGraphicsPipe;
 typedef WinGraphicsPipe BaseGraphicsPipe;
+#elif defined(HAVE_COCOA)
+#include "cocoaGraphicsPipe.h"
+typedef CocoaGraphicsPipe BaseGraphicsPipe;
 #elif defined(HAVE_X11)
 #elif defined(HAVE_X11)
 #include "x11GraphicsPipe.h"
 #include "x11GraphicsPipe.h"
 typedef x11GraphicsPipe BaseGraphicsPipe;
 typedef x11GraphicsPipe BaseGraphicsPipe;

+ 20 - 0
panda/src/vulkandisplay/vulkanGraphicsWindow.cxx

@@ -14,6 +14,11 @@
 #include "vulkanGraphicsWindow.h"
 #include "vulkanGraphicsWindow.h"
 #include "vulkanGraphicsStateGuardian.h"
 #include "vulkanGraphicsStateGuardian.h"
 
 
+#ifdef HAVE_COCOA
+#include <objc/objc.h>
+#include <objc/message.h>
+#endif
+
 TypeHandle VulkanGraphicsWindow::_type_handle;
 TypeHandle VulkanGraphicsWindow::_type_handle;
 
 
 /**
 /**
@@ -444,6 +449,21 @@ open_window() {
 
 
   err = vkCreateWin32SurfaceKHR(vkpipe->_instance, &surface_info, nullptr, &_surface);
   err = vkCreateWin32SurfaceKHR(vkpipe->_instance, &surface_info, nullptr, &_surface);
 
 
+#elif defined(HAVE_COCOA)
+  CAMetalLayer *layer;
+  layer = ((CAMetalLayer *(*)(objc_class *cls, SEL sel))objc_msgSend)(objc_getClass("CAMetalLayer"), sel_registerName("layer"));
+  ((void (*)(id self, SEL sel, id delegate))objc_msgSend)((id)layer, sel_registerName("setDelegate:"), _view);
+  ((void (*)(id self, SEL sel, BOOL arg))objc_msgSend)(_view, sel_registerName("setWantsLayer:"), TRUE);
+  ((void (*)(id self, SEL sel, id arg))objc_msgSend)(_view, sel_registerName("setLayer:"), (id)layer);
+
+  VkMetalSurfaceCreateInfoEXT surface_info;
+  surface_info.sType = VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT;
+  surface_info.pNext = nullptr;
+  surface_info.flags = 0;
+  surface_info.pLayer = layer;
+
+  err = vkCreateMetalSurfaceEXT(vkpipe->_instance, &surface_info, nullptr, &_surface);
+
 #elif defined(HAVE_X11)
 #elif defined(HAVE_X11)
   VkXlibSurfaceCreateInfoKHR surface_info;
   VkXlibSurfaceCreateInfoKHR surface_info;
   surface_info.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
   surface_info.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;

+ 4 - 0
panda/src/vulkandisplay/vulkanGraphicsWindow.h

@@ -19,6 +19,10 @@
 #ifdef _WIN32
 #ifdef _WIN32
 #include "winGraphicsWindow.h"
 #include "winGraphicsWindow.h"
 typedef WinGraphicsWindow BaseGraphicsWindow;
 typedef WinGraphicsWindow BaseGraphicsWindow;
+#elif defined(HAVE_COCOA)
+#include "cocoaGraphicsWindow.h"
+typedef CocoaGraphicsWindow BaseGraphicsWindow;
+typedef void CAMetalLayer;
 #elif defined(HAVE_X11)
 #elif defined(HAVE_X11)
 #include "x11GraphicsWindow.h"
 #include "x11GraphicsWindow.h"
 typedef x11GraphicsWindow BaseGraphicsWindow;
 typedef x11GraphicsWindow BaseGraphicsWindow;