From 69d27a69cde943e973c35992d485f4641dece7fb Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 11 Jun 2019 18:13:46 -0700 Subject: [PATCH] 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 | 2 +- include/SDL_vulkan.h | 6 ++--- src/video/cocoa/SDL_cocoavulkan.m | 15 ++++++----- src/video/uikit/SDL_uikitvulkan.m | 41 +++++++++++++++++++++---------- 4 files changed, 39 insertions(+), 25 deletions(-) diff --git a/include/SDL_config_macosx.h b/include/SDL_config_macosx.h index 0ab84cb10c6d6..c494b2e318d02 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 972cca4d7c265..d69a436b3eae7 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 38c9b5ccf32cf..4801d768b89ec 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 a436133bfac3b..c4b779d10ee37 100644 --- a/src/video/uikit/SDL_uikitvulkan.m +++ b/src/video/uikit/SDL_uikitvulkan.m @@ -39,7 +39,10 @@ #include -#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; }