Commit 69d27a69cde943e973c35992d485f4641dece7fb

Sam Lantinga 2019-06-11T18:13:46

Fixed bug 4570 - Support Vulkan Portability rather than MoltenVK specifically Dzmitry Malyshau Current code, search paths, and error messages are written to only consider MoltenVK on macOS as a Vulkan Portability implementation. It's not the only implementation available to the users. gfx-portability [1] has been shown to run a number of titles well, including Dota2, Dolphin Emulator, and vkQuake3, often out-performing MoltenVK in frame rate and stability (see Dolphin benchmark [2]). There is no reason for SDL to be that specific, it's not using any MVK-specific functions other than the WSI initialization ("VK_MVK_macos_surface"). gfx-portability exposes this extension as well, and a more generic WSI extension is in process. It would be good if SDL was written in a more generic way that expect a Vulkan Portability library as opposed to MoltenVK specifically. [1] https://github.com/gfx-rs/portability [2] https://gfx-rs.github.io/2019/03/22/dolphin-macos-performance.html

diff --git a/include/SDL_config_macosx.h b/include/SDL_config_macosx.h
index 0ab84cb..c494b2e 100644
--- a/include/SDL_config_macosx.h
+++ b/include/SDL_config_macosx.h
@@ -218,7 +218,7 @@
 #endif
 
 /* Enable Vulkan support */
-/* Metal/MoltenVK/Vulkan only supported on 64-bit architectures with 10.11+ */
+/* Metal/Vulkan Portability only supported on 64-bit architectures with 10.11+ */
 #if TARGET_CPU_X86_64 && (MAC_OS_X_VERSION_MAX_ALLOWED >= 101100)
 #define SDL_VIDEO_VULKAN 1
 #else
diff --git a/include/SDL_vulkan.h b/include/SDL_vulkan.h
index 972cca4..d69a436 100644
--- a/include/SDL_vulkan.h
+++ b/include/SDL_vulkan.h
@@ -98,8 +98,8 @@ typedef VkSurfaceKHR SDL_vulkanSurface; /* for compatibility with Tizen */
  *        applications to link with libvulkan (and historically MoltenVK was
  *        provided as a static library). If it is not found then, on macOS, SDL
  *        will attempt to load \c vulkan.framework/vulkan, \c libvulkan.1.dylib,
- *        \c MoltenVK.framework/MoltenVK and \c libMoltenVK.dylib in that order.
- *        On iOS SDL will attempt to load \c libMoltenVK.dylib. Applications
+ *        followed by \c libvulkan.dylib, in that order.
+ *        On iOS SDL will attempt to load \c libvulkan.dylib only. Applications
  *        using a dynamic framework or .dylib must ensure it is included in its
  *        application bundle.
  *
@@ -153,7 +153,7 @@ extern DECLSPEC void SDLCALL SDL_Vulkan_UnloadLibrary(void);
  *  is smaller than the number of required extensions, \c SDL_FALSE will be
  *  returned instead of \c SDL_TRUE, to indicate that not all the required
  *  extensions were returned.
- * 
+ *
  *  \note If \c window is not NULL, it will be checked against its creation
  *        flags to ensure that the Vulkan flag is present. This parameter
  *        will be removed in a future major release.
diff --git a/src/video/cocoa/SDL_cocoavulkan.m b/src/video/cocoa/SDL_cocoavulkan.m
index 38c9b5c..4801d76 100644
--- a/src/video/cocoa/SDL_cocoavulkan.m
+++ b/src/video/cocoa/SDL_cocoavulkan.m
@@ -19,7 +19,7 @@
   3. This notice may not be removed or altered from any source distribution.
 */
 
-/* 
+/*
  * @author Mark Callow, www.edgewise-consulting.com. Based on Jacob Lifshay's
  * SDL_x11vulkan.c.
  */
@@ -42,6 +42,7 @@
 const char* defaultPaths[] = {
     "vulkan.framework/vulkan",
     "libvulkan.1.dylib",
+    "libvulkan.dylib",
     "MoltenVK.framework/MoltenVK",
     "libMoltenVK.dylib"
 };
@@ -58,7 +59,7 @@ int Cocoa_Vulkan_LoadLibrary(_THIS, const char *path)
     PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = NULL;
 
     if (_this->vulkan_config.loader_handle) {
-        return SDL_SetError("Vulkan/MoltenVK already loaded");
+        return SDL_SetError("Vulkan Portability library is already loaded.");
     }
 
     /* Load the Vulkan loader library */
@@ -67,9 +68,7 @@ int Cocoa_Vulkan_LoadLibrary(_THIS, const char *path)
     }
 
     if (!path) {
-        /* MoltenVK framework, currently, v0.17.0, has a static library and is
-         * the recommended way to use the package. There is likely no object to
-         * load. */
+        /* Handle the case where Vulkan Portability is linked statically. */
         vkGetInstanceProcAddr =
          (PFN_vkGetInstanceProcAddr)dlsym(DEFAULT_HANDLE,
                                           "vkGetInstanceProcAddr");
@@ -99,7 +98,7 @@ int Cocoa_Vulkan_LoadLibrary(_THIS, const char *path)
         }
 
         if (_this->vulkan_config.loader_handle == NULL) {
-            return SDL_SetError("Failed to load Vulkan/MoltenVK library");
+            return SDL_SetError("Failed to load Vulkan Portability library");
         }
 
         SDL_strlcpy(_this->vulkan_config.loader_path, foundPath,
@@ -139,11 +138,11 @@ int Cocoa_Vulkan_LoadLibrary(_THIS, const char *path)
     }
     SDL_free(extensions);
     if (!hasSurfaceExtension) {
-        SDL_SetError("Installed MoltenVK/Vulkan doesn't implement the "
+        SDL_SetError("Installed Vulkan Portability library doesn't implement the "
                      VK_KHR_SURFACE_EXTENSION_NAME " extension");
         goto fail;
     } else if (!hasMacOSSurfaceExtension) {
-        SDL_SetError("Installed MoltenVK/Vulkan doesn't implement the "
+        SDL_SetError("Installed Vulkan Portability library doesn't implement the "
                      VK_MVK_MACOS_SURFACE_EXTENSION_NAME "extension");
         goto fail;
     }
diff --git a/src/video/uikit/SDL_uikitvulkan.m b/src/video/uikit/SDL_uikitvulkan.m
index a436133..c4b779d 100644
--- a/src/video/uikit/SDL_uikitvulkan.m
+++ b/src/video/uikit/SDL_uikitvulkan.m
@@ -39,7 +39,10 @@
 
 #include <dlfcn.h>
 
-#define DEFAULT_MOLTENVK  "libMoltenVK.dylib"
+const char* defaultPaths[] = {
+    "libvulkan.dylib",
+};
+
 /* Since libSDL is static, could use RTLD_SELF. Using RTLD_DEFAULT is future
  * proofing. */
 #define DEFAULT_HANDLE RTLD_DEFAULT
@@ -53,7 +56,7 @@ int UIKit_Vulkan_LoadLibrary(_THIS, const char *path)
     PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = NULL;
 
     if (_this->vulkan_config.loader_handle) {
-        return SDL_SetError("MoltenVK/Vulkan already loaded");
+        return SDL_SetError("Vulkan Portability library is already loaded.");
     }
 
     /* Load the Vulkan loader library */
@@ -62,9 +65,7 @@ int UIKit_Vulkan_LoadLibrary(_THIS, const char *path)
     }
 
     if (!path) {
-        /* MoltenVK framework, currently, v0.17.0, has a static library and is
-         * the recommended way to use the package. There is likely no object to
-         * load. */
+        /* Handle the case where Vulkan Portability is linked statically. */
         vkGetInstanceProcAddr =
         (PFN_vkGetInstanceProcAddr)dlsym(DEFAULT_HANDLE,
                                          "vkGetInstanceProcAddr");
@@ -73,15 +74,29 @@ int UIKit_Vulkan_LoadLibrary(_THIS, const char *path)
     if (vkGetInstanceProcAddr) {
         _this->vulkan_config.loader_handle = DEFAULT_HANDLE;
     } else {
-        if (!path) {
+        const char** paths;
+        const char *foundPath = NULL;
+        int numPaths;
+        int i;
+
+        if (path) {
+            paths = &path;
+            numPaths = 1;
+        } else {
             /* Look for the .dylib packaged with the application instead. */
-            path = DEFAULT_MOLTENVK;
+            paths = defaultPaths;
+            numPaths = SDL_arraysize(defaultPaths);
+        }
+
+        for (i = 0; i < numPaths && _this->vulkan_config.loader_handle == NULL; i++) {
+            foundPath = paths[i];
+            _this->vulkan_config.loader_handle = SDL_LoadObject(foundPath);
         }
 
-        _this->vulkan_config.loader_handle = SDL_LoadObject(path);
-        if (!_this->vulkan_config.loader_handle) {
-            return -1;
+        if (_this->vulkan_config.loader_handle == NULL) {
+            return SDL_SetError("Failed to load Vulkan Portability library");
         }
+
         SDL_strlcpy(_this->vulkan_config.loader_path, path,
                     SDL_arraysize(_this->vulkan_config.loader_path));
         vkGetInstanceProcAddr =
@@ -93,7 +108,7 @@ int UIKit_Vulkan_LoadLibrary(_THIS, const char *path)
     if (!vkGetInstanceProcAddr) {
         SDL_SetError("Failed to find %s in either executable or %s: %s",
                      "vkGetInstanceProcAddr",
-                     DEFAULT_MOLTENVK,
+                     "linked Vulkan Portability library",
                      (const char *) dlerror());
         goto fail;
     }
@@ -128,11 +143,11 @@ int UIKit_Vulkan_LoadLibrary(_THIS, const char *path)
     SDL_free(extensions);
 
     if (!hasSurfaceExtension) {
-        SDL_SetError("Installed MoltenVK/Vulkan doesn't implement the "
+        SDL_SetError("Installed Vulkan Portability doesn't implement the "
                      VK_KHR_SURFACE_EXTENSION_NAME " extension");
         goto fail;
     } else if (!hasIOSSurfaceExtension) {
-        SDL_SetError("Installed MoltenVK/Vulkan doesn't implement the "
+        SDL_SetError("Installed Vulkan Portability doesn't implement the "
                      VK_MVK_IOS_SURFACE_EXTENSION_NAME "extension");
         goto fail;
     }