Fixed bug 4570 - Support Vulkan Portability rather than MoltenVK specifically
authorSam Lantinga <slouken@libsdl.org>
Tue, 11 Jun 2019 18:13:46 -0700
changeset 128384a089aa4ff81
parent 12837 e319b798dc2d
child 12839 1b94a9e6746e
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
include/SDL_config_macosx.h
include/SDL_vulkan.h
src/video/cocoa/SDL_cocoavulkan.m
src/video/uikit/SDL_uikitvulkan.m
     1.1 --- a/include/SDL_config_macosx.h	Tue Jun 11 15:06:35 2019 -0400
     1.2 +++ b/include/SDL_config_macosx.h	Tue Jun 11 18:13:46 2019 -0700
     1.3 @@ -218,7 +218,7 @@
     1.4  #endif
     1.5  
     1.6  /* Enable Vulkan support */
     1.7 -/* Metal/MoltenVK/Vulkan only supported on 64-bit architectures with 10.11+ */
     1.8 +/* Metal/Vulkan Portability only supported on 64-bit architectures with 10.11+ */
     1.9  #if TARGET_CPU_X86_64 && (MAC_OS_X_VERSION_MAX_ALLOWED >= 101100)
    1.10  #define SDL_VIDEO_VULKAN 1
    1.11  #else
     2.1 --- a/include/SDL_vulkan.h	Tue Jun 11 15:06:35 2019 -0400
     2.2 +++ b/include/SDL_vulkan.h	Tue Jun 11 18:13:46 2019 -0700
     2.3 @@ -98,8 +98,8 @@
     2.4   *        applications to link with libvulkan (and historically MoltenVK was
     2.5   *        provided as a static library). If it is not found then, on macOS, SDL
     2.6   *        will attempt to load \c vulkan.framework/vulkan, \c libvulkan.1.dylib,
     2.7 - *        \c MoltenVK.framework/MoltenVK and \c libMoltenVK.dylib in that order.
     2.8 - *        On iOS SDL will attempt to load \c libMoltenVK.dylib. Applications
     2.9 + *        followed by \c libvulkan.dylib, in that order.
    2.10 + *        On iOS SDL will attempt to load \c libvulkan.dylib only. Applications
    2.11   *        using a dynamic framework or .dylib must ensure it is included in its
    2.12   *        application bundle.
    2.13   *
    2.14 @@ -153,7 +153,7 @@
    2.15   *  is smaller than the number of required extensions, \c SDL_FALSE will be
    2.16   *  returned instead of \c SDL_TRUE, to indicate that not all the required
    2.17   *  extensions were returned.
    2.18 - * 
    2.19 + *
    2.20   *  \note If \c window is not NULL, it will be checked against its creation
    2.21   *        flags to ensure that the Vulkan flag is present. This parameter
    2.22   *        will be removed in a future major release.
     3.1 --- a/src/video/cocoa/SDL_cocoavulkan.m	Tue Jun 11 15:06:35 2019 -0400
     3.2 +++ b/src/video/cocoa/SDL_cocoavulkan.m	Tue Jun 11 18:13:46 2019 -0700
     3.3 @@ -19,7 +19,7 @@
     3.4    3. This notice may not be removed or altered from any source distribution.
     3.5  */
     3.6  
     3.7 -/* 
     3.8 +/*
     3.9   * @author Mark Callow, www.edgewise-consulting.com. Based on Jacob Lifshay's
    3.10   * SDL_x11vulkan.c.
    3.11   */
    3.12 @@ -42,6 +42,7 @@
    3.13  const char* defaultPaths[] = {
    3.14      "vulkan.framework/vulkan",
    3.15      "libvulkan.1.dylib",
    3.16 +    "libvulkan.dylib",
    3.17      "MoltenVK.framework/MoltenVK",
    3.18      "libMoltenVK.dylib"
    3.19  };
    3.20 @@ -58,7 +59,7 @@
    3.21      PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = NULL;
    3.22  
    3.23      if (_this->vulkan_config.loader_handle) {
    3.24 -        return SDL_SetError("Vulkan/MoltenVK already loaded");
    3.25 +        return SDL_SetError("Vulkan Portability library is already loaded.");
    3.26      }
    3.27  
    3.28      /* Load the Vulkan loader library */
    3.29 @@ -67,9 +68,7 @@
    3.30      }
    3.31  
    3.32      if (!path) {
    3.33 -        /* MoltenVK framework, currently, v0.17.0, has a static library and is
    3.34 -         * the recommended way to use the package. There is likely no object to
    3.35 -         * load. */
    3.36 +        /* Handle the case where Vulkan Portability is linked statically. */
    3.37          vkGetInstanceProcAddr =
    3.38           (PFN_vkGetInstanceProcAddr)dlsym(DEFAULT_HANDLE,
    3.39                                            "vkGetInstanceProcAddr");
    3.40 @@ -99,7 +98,7 @@
    3.41          }
    3.42  
    3.43          if (_this->vulkan_config.loader_handle == NULL) {
    3.44 -            return SDL_SetError("Failed to load Vulkan/MoltenVK library");
    3.45 +            return SDL_SetError("Failed to load Vulkan Portability library");
    3.46          }
    3.47  
    3.48          SDL_strlcpy(_this->vulkan_config.loader_path, foundPath,
    3.49 @@ -139,11 +138,11 @@
    3.50      }
    3.51      SDL_free(extensions);
    3.52      if (!hasSurfaceExtension) {
    3.53 -        SDL_SetError("Installed MoltenVK/Vulkan doesn't implement the "
    3.54 +        SDL_SetError("Installed Vulkan Portability library doesn't implement the "
    3.55                       VK_KHR_SURFACE_EXTENSION_NAME " extension");
    3.56          goto fail;
    3.57      } else if (!hasMacOSSurfaceExtension) {
    3.58 -        SDL_SetError("Installed MoltenVK/Vulkan doesn't implement the "
    3.59 +        SDL_SetError("Installed Vulkan Portability library doesn't implement the "
    3.60                       VK_MVK_MACOS_SURFACE_EXTENSION_NAME "extension");
    3.61          goto fail;
    3.62      }
     4.1 --- a/src/video/uikit/SDL_uikitvulkan.m	Tue Jun 11 15:06:35 2019 -0400
     4.2 +++ b/src/video/uikit/SDL_uikitvulkan.m	Tue Jun 11 18:13:46 2019 -0700
     4.3 @@ -39,7 +39,10 @@
     4.4  
     4.5  #include <dlfcn.h>
     4.6  
     4.7 -#define DEFAULT_MOLTENVK  "libMoltenVK.dylib"
     4.8 +const char* defaultPaths[] = {
     4.9 +    "libvulkan.dylib",
    4.10 +};
    4.11 +
    4.12  /* Since libSDL is static, could use RTLD_SELF. Using RTLD_DEFAULT is future
    4.13   * proofing. */
    4.14  #define DEFAULT_HANDLE RTLD_DEFAULT
    4.15 @@ -53,7 +56,7 @@
    4.16      PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = NULL;
    4.17  
    4.18      if (_this->vulkan_config.loader_handle) {
    4.19 -        return SDL_SetError("MoltenVK/Vulkan already loaded");
    4.20 +        return SDL_SetError("Vulkan Portability library is already loaded.");
    4.21      }
    4.22  
    4.23      /* Load the Vulkan loader library */
    4.24 @@ -62,9 +65,7 @@
    4.25      }
    4.26  
    4.27      if (!path) {
    4.28 -        /* MoltenVK framework, currently, v0.17.0, has a static library and is
    4.29 -         * the recommended way to use the package. There is likely no object to
    4.30 -         * load. */
    4.31 +        /* Handle the case where Vulkan Portability is linked statically. */
    4.32          vkGetInstanceProcAddr =
    4.33          (PFN_vkGetInstanceProcAddr)dlsym(DEFAULT_HANDLE,
    4.34                                           "vkGetInstanceProcAddr");
    4.35 @@ -73,15 +74,29 @@
    4.36      if (vkGetInstanceProcAddr) {
    4.37          _this->vulkan_config.loader_handle = DEFAULT_HANDLE;
    4.38      } else {
    4.39 -        if (!path) {
    4.40 +        const char** paths;
    4.41 +        const char *foundPath = NULL;
    4.42 +        int numPaths;
    4.43 +        int i;
    4.44 +
    4.45 +        if (path) {
    4.46 +            paths = &path;
    4.47 +            numPaths = 1;
    4.48 +        } else {
    4.49              /* Look for the .dylib packaged with the application instead. */
    4.50 -            path = DEFAULT_MOLTENVK;
    4.51 +            paths = defaultPaths;
    4.52 +            numPaths = SDL_arraysize(defaultPaths);
    4.53          }
    4.54  
    4.55 -        _this->vulkan_config.loader_handle = SDL_LoadObject(path);
    4.56 -        if (!_this->vulkan_config.loader_handle) {
    4.57 -            return -1;
    4.58 +        for (i = 0; i < numPaths && _this->vulkan_config.loader_handle == NULL; i++) {
    4.59 +            foundPath = paths[i];
    4.60 +            _this->vulkan_config.loader_handle = SDL_LoadObject(foundPath);
    4.61          }
    4.62 +
    4.63 +        if (_this->vulkan_config.loader_handle == NULL) {
    4.64 +            return SDL_SetError("Failed to load Vulkan Portability library");
    4.65 +        }
    4.66 +
    4.67          SDL_strlcpy(_this->vulkan_config.loader_path, path,
    4.68                      SDL_arraysize(_this->vulkan_config.loader_path));
    4.69          vkGetInstanceProcAddr =
    4.70 @@ -93,7 +108,7 @@
    4.71      if (!vkGetInstanceProcAddr) {
    4.72          SDL_SetError("Failed to find %s in either executable or %s: %s",
    4.73                       "vkGetInstanceProcAddr",
    4.74 -                     DEFAULT_MOLTENVK,
    4.75 +                     "linked Vulkan Portability library",
    4.76                       (const char *) dlerror());
    4.77          goto fail;
    4.78      }
    4.79 @@ -128,11 +143,11 @@
    4.80      SDL_free(extensions);
    4.81  
    4.82      if (!hasSurfaceExtension) {
    4.83 -        SDL_SetError("Installed MoltenVK/Vulkan doesn't implement the "
    4.84 +        SDL_SetError("Installed Vulkan Portability doesn't implement the "
    4.85                       VK_KHR_SURFACE_EXTENSION_NAME " extension");
    4.86          goto fail;
    4.87      } else if (!hasIOSSurfaceExtension) {
    4.88 -        SDL_SetError("Installed MoltenVK/Vulkan doesn't implement the "
    4.89 +        SDL_SetError("Installed Vulkan Portability doesn't implement the "
    4.90                       VK_MVK_IOS_SURFACE_EXTENSION_NAME "extension");
    4.91          goto fail;
    4.92      }