diff --git a/CMakeLists.txt b/CMakeLists.txt index 6c40f0a8..b49a6c8d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -647,13 +647,18 @@ target_link_libraries(shadps4 PRIVATE magic_enum::magic_enum fmt::fmt toml11::to target_link_libraries(shadps4 PRIVATE Boost::headers GPUOpen::VulkanMemoryAllocator sirit Vulkan::Headers xxHash::xxhash Zydis::Zydis glslang::SPIRV glslang::glslang SDL3::SDL3) if (APPLE) + option(USE_SYSTEM_VULKAN_LOADER "Enables using the system Vulkan loader instead of directly linking with MoltenVK. Useful for loading validation layers." OFF) + if (USE_SYSTEM_VULKAN_LOADER) + target_compile_definitions(shadps4 PRIVATE USE_SYSTEM_VULKAN_LOADER=1) + else() + # Link MoltenVK for Vulkan support + find_library(MOLTENVK MoltenVK REQUIRED) + target_link_libraries(shadps4 PRIVATE ${MOLTENVK}) + endif() + # Reserve system-managed memory space. target_link_options(shadps4 PRIVATE -Wl,-no_pie,-no_fixup_chains,-no_huge,-pagezero_size,0x4000,-segaddr,TCB_SPACE,0x4000,-segaddr,GUEST_SYSTEM,0x400000,-image_base,0x20000000000) - # Link MoltenVK for Vulkan support - find_library(MOLTENVK MoltenVK REQUIRED) - target_link_libraries(shadps4 PRIVATE ${MOLTENVK}) - # Replacement for std::chrono::time_zone target_link_libraries(shadps4 PRIVATE date::date-tz) diff --git a/src/video_core/renderer_vulkan/vk_common.h b/src/video_core/renderer_vulkan/vk_common.h index 7db6fb06..3e048749 100644 --- a/src/video_core/renderer_vulkan/vk_common.h +++ b/src/video_core/renderer_vulkan/vk_common.h @@ -3,6 +3,10 @@ #pragma once +#if defined(__APPLE__) && !USE_SYSTEM_VULKAN_LOADER +#define VULKAN_HPP_ENABLE_DYNAMIC_LOADER_TOOL 0 +#endif + // Include vulkan-hpp header #define VK_ENABLE_BETA_EXTENSIONS #define VK_NO_PROTOTYPES diff --git a/src/video_core/renderer_vulkan/vk_instance.cpp b/src/video_core/renderer_vulkan/vk_instance.cpp index 34727d27..001b3a7f 100644 --- a/src/video_core/renderer_vulkan/vk_instance.cpp +++ b/src/video_core/renderer_vulkan/vk_instance.cpp @@ -47,13 +47,13 @@ std::string GetReadableVersion(u32 version) { } // Anonymous namespace Instance::Instance(bool enable_validation, bool dump_command_buffers) - : instance{CreateInstance(dl, Frontend::WindowSystemType::Headless, enable_validation, + : instance{CreateInstance(Frontend::WindowSystemType::Headless, enable_validation, dump_command_buffers)}, physical_devices{instance->enumeratePhysicalDevices()} {} Instance::Instance(Frontend::WindowSDL& window, s32 physical_device_index, bool enable_validation /*= false*/) - : instance{CreateInstance(dl, window.getWindowInfo().type, enable_validation, false)}, + : instance{CreateInstance(window.getWindowInfo().type, enable_validation, false)}, physical_devices{instance->enumeratePhysicalDevices()} { if (enable_validation) { debug_callback = CreateDebugCallback(*instance); diff --git a/src/video_core/renderer_vulkan/vk_instance.h b/src/video_core/renderer_vulkan/vk_instance.h index 5f985d4a..59b3cc35 100644 --- a/src/video_core/renderer_vulkan/vk_instance.h +++ b/src/video_core/renderer_vulkan/vk_instance.h @@ -17,12 +17,6 @@ class WindowSDL; VK_DEFINE_HANDLE(VmaAllocator) -#ifdef __APPLE__ -#define VULKAN_LIBRARY_NAME "libMoltenVK.dylib" -#else -#define VULKAN_LIBRARY_NAME -#endif - namespace Vulkan { class Instance { @@ -240,7 +234,6 @@ private: vk::Format GetAlternativeFormat(const vk::Format format) const; private: - vk::DynamicLoader dl{VULKAN_LIBRARY_NAME}; vk::UniqueInstance instance; vk::PhysicalDevice physical_device; vk::UniqueDevice device; diff --git a/src/video_core/renderer_vulkan/vk_platform.cpp b/src/video_core/renderer_vulkan/vk_platform.cpp index c73a8139..7774cd2d 100644 --- a/src/video_core/renderer_vulkan/vk_platform.cpp +++ b/src/video_core/renderer_vulkan/vk_platform.cpp @@ -20,6 +20,15 @@ #include "sdl_window.h" #include "video_core/renderer_vulkan/vk_platform.h" +#if VULKAN_HPP_ENABLE_DYNAMIC_LOADER_TOOL +static vk::DynamicLoader dl; +#else +extern "C" { +VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, + const char* pName); +} +#endif + namespace Vulkan { static const char* const VALIDATION_LAYER_NAME = "VK_LAYER_KHRONOS_validation"; @@ -186,12 +195,14 @@ std::vector GetInstanceExtensions(Frontend::WindowSystemType window return extensions; } -vk::UniqueInstance CreateInstance(vk::DynamicLoader& dl, Frontend::WindowSystemType window_type, - bool enable_validation, bool dump_command_buffers) { +vk::UniqueInstance CreateInstance(Frontend::WindowSystemType window_type, bool enable_validation, + bool dump_command_buffers) { LOG_INFO(Render_Vulkan, "Creating vulkan instance"); +#if VULKAN_HPP_ENABLE_DYNAMIC_LOADER_TOOL auto vkGetInstanceProcAddr = dl.getProcAddress("vkGetInstanceProcAddr"); +#endif VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr); const u32 available_version = VULKAN_HPP_DEFAULT_DISPATCHER.vkEnumerateInstanceVersion @@ -216,12 +227,19 @@ vk::UniqueInstance CreateInstance(vk::DynamicLoader& dl, Frontend::WindowSystemT u32 num_layers = 0; std::array layers; +#if VULKAN_HPP_ENABLE_DYNAMIC_LOADER_TOOL if (enable_validation) { layers[num_layers++] = VALIDATION_LAYER_NAME; } if (dump_command_buffers) { layers[num_layers++] = API_DUMP_LAYER_NAME; } +#else + if (enable_validation || dump_command_buffers) { + LOG_WARNING(Render_Vulkan, + "Skipping loading Vulkan layers as dynamic loading is not enabled."); + } +#endif vk::Bool32 enable_sync = enable_validation && Config::vkValidationSyncEnabled() ? vk::True : vk::False; diff --git a/src/video_core/renderer_vulkan/vk_platform.h b/src/video_core/renderer_vulkan/vk_platform.h index 582de383..413fa347 100644 --- a/src/video_core/renderer_vulkan/vk_platform.h +++ b/src/video_core/renderer_vulkan/vk_platform.h @@ -21,8 +21,8 @@ constexpr u32 TargetVulkanApiVersion = VK_API_VERSION_1_2; vk::SurfaceKHR CreateSurface(vk::Instance instance, const Frontend::WindowSDL& emu_window); -vk::UniqueInstance CreateInstance(vk::DynamicLoader& dl, Frontend::WindowSystemType window_type, - bool enable_validation, bool dump_command_buffers); +vk::UniqueInstance CreateInstance(Frontend::WindowSystemType window_type, bool enable_validation, + bool dump_command_buffers); vk::UniqueDebugUtilsMessengerEXT CreateDebugCallback(vk::Instance instance);