diff --git a/README.md b/README.md index 97572d210..3adabc2d4 100644 --- a/README.md +++ b/README.md @@ -288,12 +288,17 @@ The emulator can also be started directly with a legally obtained game directory ./_Build/linux/install/kyty_emulator --game "/games/ExampleGame" ``` -On macOS, point SDL at the MoltenVK library explicitly; the hardened runtime prevents it from -being picked up from the executable's directory: +On macOS, a bundled `libMoltenVK.dylib` next to `kyty_emulator` is found automatically; no +environment variable is required: ```bash -cd _Build/macos/install -SDL_VULKAN_LIBRARY="$PWD/libMoltenVK.dylib" ./kyty_emulator --game "/games/ExampleGame" +./_Build/macos/install/kyty_emulator --game "/games/ExampleGame" +``` + +To override the Vulkan loader, set `SDL_VULKAN_LIBRARY`: + +```bash +SDL_VULKAN_LIBRARY=/path/to/libMoltenVK.dylib ./kyty_emulator --game "/games/ExampleGame" ``` Run `kyty_emulator --help` to see the available graphics, logging, validation, profiling, and diff --git a/src/graphics/presentation/window/vulkanWindow.cpp b/src/graphics/presentation/window/vulkanWindow.cpp index 6d1e5df6b..0dc981c83 100644 --- a/src/graphics/presentation/window/vulkanWindow.cpp +++ b/src/graphics/presentation/window/vulkanWindow.cpp @@ -10,6 +10,7 @@ #include "SDL_pixels.h" #include "SDL_rwops.h" #include "SDL_stdinc.h" +#include "SDL_filesystem.h" #include "SDL_surface.h" #include "SDL_thread.h" #include "SDL_touch.h" @@ -40,6 +41,7 @@ #include #include +#include #include #include #include @@ -875,6 +877,26 @@ void WindowContext::CreateVulkan() { EXIT_IF(graphic_ctx.device != nullptr); EXIT_IF(surface != nullptr); +#if defined(__APPLE__) + // On macOS the Vulkan loader comes from MoltenVK. SDL's default + // probe only searches system library paths, so a bundled + // libMoltenVK.dylib next to the executable is invisible under the + // hardened runtime. Probe it explicitly before falling back. + if (const char* sdl_vulkan_library = std::getenv("SDL_VULKAN_LIBRARY"); + sdl_vulkan_library != nullptr) { + LOGF("Vulkan loader override: SDL_VULKAN_LIBRARY=%s\n", sdl_vulkan_library); + } else if (char* base_path = SDL_GetBasePath(); base_path != nullptr) { + const std::string moltenvk_path = std::string(base_path) + "libMoltenVK.dylib"; + SDL_free(base_path); + if (SDL_Vulkan_LoadLibrary(moltenvk_path.c_str()) == 0) { + LOGF("Vulkan loader: %s\n", moltenvk_path.c_str()); + } else { + LOGF("Bundled Vulkan loader not found at %s (%s); trying system loader\n", + moltenvk_path.c_str(), SDL_GetError()); + } + } +#endif + auto get_instance_proc_addr = reinterpret_cast(SDL_Vulkan_GetVkGetInstanceProcAddr()); if (get_instance_proc_addr == nullptr) {