Skip to content

Commit

Permalink
Fixed bug 4570 - Support Vulkan Portability rather than MoltenVK spec…
Browse files Browse the repository at this point in the history
…ifically

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
  • Loading branch information
slouken committed Jun 12, 2019
1 parent 3e9bf28 commit 69d27a6
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 25 deletions.
2 changes: 1 addition & 1 deletion include/SDL_config_macosx.h
Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions include/SDL_vulkan.h
Expand Up @@ -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.
*
Expand Down Expand Up @@ -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.
Expand Down
15 changes: 7 additions & 8 deletions src/video/cocoa/SDL_cocoavulkan.m
Expand Up @@ -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.
*/
Expand All @@ -42,6 +42,7 @@
const char* defaultPaths[] = {
"vulkan.framework/vulkan",
"libvulkan.1.dylib",
"libvulkan.dylib",
"MoltenVK.framework/MoltenVK",
"libMoltenVK.dylib"
};
Expand All @@ -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 */
Expand All @@ -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");
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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;
}
Expand Down
41 changes: 28 additions & 13 deletions src/video/uikit/SDL_uikitvulkan.m
Expand Up @@ -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
Expand All @@ -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 */
Expand All @@ -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");
Expand All @@ -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 =
Expand All @@ -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;
}
Expand Down Expand Up @@ -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;
}
Expand Down

0 comments on commit 69d27a6

Please sign in to comment.