Support official Vulkan SDK for macOS. This tries to load vulkan.framework or libvulkan.1.dylib before MoltenVK.framework or libMoltenVK.dylib. In the previous version, layers would not work for applications run-time loading the default library.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
diff --git a/include/SDL_vulkan.h b/include/SDL_vulkan.h
index d238e22..f04c21a 100644
--- a/include/SDL_vulkan.h
+++ b/include/SDL_vulkan.h
@@ -69,30 +69,43 @@ typedef VkSurfaceKHR SDL_vulkanSurface; /* for compatibility with Tizen */
* \brief Dynamically load a Vulkan loader library.
*
* \param [in] path The platform dependent Vulkan loader library name, or
- * \c NULL to open the default Vulkan loader library.
+ * \c NULL.
*
* \return \c 0 on success, or \c -1 if the library couldn't be loaded.
*
- * This should be done after initializing the video driver, but before
+ * If \a path is NULL SDL will use the value of the environment variable
+ * \c SDL_VULKAN_LIBRARY, if set, otherwise it loads the default Vulkan
+ * loader library.
+ *
+ * This should be called after initializing the video driver, but before
* creating any Vulkan windows. If no Vulkan loader library is loaded, the
* default library will be loaded upon creation of the first Vulkan window.
*
- * \note If you specify a non-NULL \a path, you should retrieve all of the
- * Vulkan functions used in your program from the dynamic library using
+ * \note It is fairly common for Vulkan applications to link with \a libvulkan
+ * instead of explicitly loading it at run time. This will work with
+ * SDL provided the application links to a dynamic library and both it
+ * and SDL use the same search path.
+ *
+ * \note If you specify a non-NULL \c path, an application should retrieve all
+ * of the Vulkan functions it uses from the dynamic library using
* \c SDL_Vulkan_GetVkGetInstanceProcAddr() unless you can guarantee
- * \a path points to the same vulkan loader library that you linked to.
+ * \c path points to the same vulkan loader library the application
+ * linked to.
*
* \note On Apple devices, if \a path is NULL, SDL will attempt to find
* the vkGetInstanceProcAddr address within all the mach-o images of
- * the current process. This is because the currently (v0.17.0)
- * recommended MoltenVK (Vulkan on Metal) usage is as a static library.
- * If it is not found then SDL will attempt to load \c libMoltenVK.dylib.
- * Applications using the dylib alternative therefore do not need to do
- * anything special when calling SDL.
- *
- * \note On non-Apple devices, SDL requires you to either not link to the
- * Vulkan loader or link to a dynamic library version. This limitation
- * may be removed in a future version of SDL.
+ * the current process. This is because it is fairly common for Vulkan
+ * 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
+ * using a dynamic framework or .dylib must ensure it is included in its
+ * application bundle.
+ *
+ * \note On non-Apple devices, application linking with a static libvulkan is
+ * not supported. Either do not link to the Vulkan loader or link to a
+ * dynamic library version.
*
* \note This function will fail if there are no working Vulkan drivers
* installed.
diff --git a/src/video/cocoa/SDL_cocoavulkan.m b/src/video/cocoa/SDL_cocoavulkan.m
index ce72774..2cf55bb 100644
--- a/src/video/cocoa/SDL_cocoavulkan.m
+++ b/src/video/cocoa/SDL_cocoavulkan.m
@@ -39,7 +39,13 @@
#include <dlfcn.h>
-#define DEFAULT_MOLTENVK "libMoltenVK.dylib"
+const char* defaultPaths[] = {
+ "vulkan.framework/vulkan",
+ "libvulkan.1.dylib",
+ "MoltenVK.framework/MoltenVK",
+ "libMoltenVK.dylib"
+};
+
/* Since libSDL is most likely a .dylib, need RTLD_DEFAULT not RTLD_SELF. */
#define DEFAULT_HANDLE RTLD_DEFAULT
@@ -52,7 +58,7 @@ int Cocoa_Vulkan_LoadLibrary(_THIS, const char *path)
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = NULL;
if (_this->vulkan_config.loader_handle) {
- SDL_SetError("MoltenVK/Vulkan already loaded");
+ SDL_SetError("Vulkan/MoltenVK already loaded");
return -1;
}
@@ -60,6 +66,7 @@ int Cocoa_Vulkan_LoadLibrary(_THIS, const char *path)
if (!path) {
path = SDL_getenv("SDL_VULKAN_LIBRARY");
}
+
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
@@ -68,20 +75,35 @@ int Cocoa_Vulkan_LoadLibrary(_THIS, const char *path)
(PFN_vkGetInstanceProcAddr)dlsym(DEFAULT_HANDLE,
"vkGetInstanceProcAddr");
}
-
+
if (vkGetInstanceProcAddr) {
_this->vulkan_config.loader_handle = DEFAULT_HANDLE;
} else {
- if (!path) {
- /* Look for the .dylib packaged with the application instead. */
- path = DEFAULT_MOLTENVK;
+ const char** paths;
+ int numPaths;
+ int i;
+
+ if (path) {
+ paths = &path;
+ numPaths = 1;
+ } else {
+ /* Look for framework or .dylib packaged with the application
+ * instead. */
+ paths = defaultPaths;
+ numPaths = SDL_arraysize(defaultPaths);
}
- _this->vulkan_config.loader_handle = SDL_LoadObject(path);
- if (!_this->vulkan_config.loader_handle) {
- return -1;
+ for (i=0; i < numPaths; i++) {
+ _this->vulkan_config.loader_handle = SDL_LoadObject(paths[i]);
+ if (_this->vulkan_config.loader_handle)
+ break;
+ else
+ continue;
}
- SDL_strlcpy(_this->vulkan_config.loader_path, path,
+ if (i == numPaths)
+ return -1;
+
+ SDL_strlcpy(_this->vulkan_config.loader_path, paths[i],
SDL_arraysize(_this->vulkan_config.loader_path));
vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)SDL_LoadFunction(
_this->vulkan_config.loader_handle, "vkGetInstanceProcAddr");
@@ -90,7 +112,7 @@ int Cocoa_Vulkan_LoadLibrary(_THIS, const char *path)
if (!vkGetInstanceProcAddr) {
SDL_SetError("Failed to find %s in either executable or %s: %s",
"vkGetInstanceProcAddr",
- DEFAULT_MOLTENVK,
+ _this->vulkan_config.loader_path,
(const char *) dlerror());
goto fail;
}