renderer_vulkan: Support loading Vulkan layers on macOS SDL build. (#2832)

This commit is contained in:
squidbus 2025-04-23 01:10:03 -07:00 committed by GitHub
parent ee7fe305c9
commit 53ca64f6ff
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 58 additions and 45 deletions

View file

@ -205,8 +205,8 @@ jobs:
run: | run: |
mkdir upload mkdir upload
mv ${{github.workspace}}/build/shadps4 upload mv ${{github.workspace}}/build/shadps4 upload
cp ${{github.workspace}}/build/externals/MoltenVK/libMoltenVK.dylib upload mv ${{github.workspace}}/build/MoltenVK_icd.json upload
install_name_tool -add_rpath "@executable_path" upload/shadps4 mv ${{github.workspace}}/build/libMoltenVK.dylib upload
- uses: actions/upload-artifact@v4 - uses: actions/upload-artifact@v4
with: with:
name: shadps4-macos-sdl-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }} name: shadps4-macos-sdl-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }}

2
.gitmodules vendored
View file

@ -97,7 +97,7 @@
shallow = true shallow = true
[submodule "externals/MoltenVK/SPIRV-Cross"] [submodule "externals/MoltenVK/SPIRV-Cross"]
path = externals/MoltenVK/SPIRV-Cross path = externals/MoltenVK/SPIRV-Cross
url = https://github.com/billhollings/SPIRV-Cross url = https://github.com/KhronosGroup/SPIRV-Cross
shallow = true shallow = true
[submodule "externals/MoltenVK/MoltenVK"] [submodule "externals/MoltenVK/MoltenVK"]
path = externals/MoltenVK/MoltenVK path = externals/MoltenVK/MoltenVK

View file

@ -1083,34 +1083,45 @@ if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" AND ENABLE_USERFAULTFD)
endif() endif()
if (APPLE) if (APPLE)
if (ENABLE_QT_GUI) # Include MoltenVK, along with an ICD file so it can be found by the system Vulkan loader if used for loading layers.
# Include MoltenVK in the app bundle, along with an ICD file so it can be found by the system Vulkan loader if used for loading layers. set(MVK_DYLIB_SRC ${CMAKE_CURRENT_BINARY_DIR}/externals/MoltenVK/libMoltenVK.dylib)
set(MVK_ICD ${CMAKE_CURRENT_SOURCE_DIR}/externals/MoltenVK/MoltenVK_icd.json)
target_sources(shadps4 PRIVATE ${MVK_ICD})
set_source_files_properties(${MVK_ICD} PROPERTIES MACOSX_PACKAGE_LOCATION Resources/vulkan/icd.d)
set(MVK_DYLIB_SRC ${CMAKE_CURRENT_BINARY_DIR}/externals/MoltenVK/libMoltenVK.dylib) if (ENABLE_QT_GUI)
set(MVK_DYLIB_DST ${CMAKE_CURRENT_BINARY_DIR}/shadps4.app/Contents/Frameworks/libMoltenVK.dylib) set_property(TARGET shadps4 APPEND PROPERTY BUILD_RPATH "@executable_path/../Frameworks")
add_custom_command( set(MVK_ICD_DST ${CMAKE_CURRENT_BINARY_DIR}/shadps4.app/Contents/Resources/vulkan/icd.d/MoltenVK_icd.json)
OUTPUT ${MVK_DYLIB_DST} set(MVK_DYLIB_DST ${CMAKE_CURRENT_BINARY_DIR}/shadps4.app/Contents/Frameworks/libMoltenVK.dylib)
DEPENDS ${MVK_DYLIB_SRC} set(MVK_DYLIB_ICD_PATH "../../../Frameworks/libMoltenVK.dylib")
COMMAND cmake -E copy ${MVK_DYLIB_SRC} ${MVK_DYLIB_DST}) else()
add_custom_target(CopyMoltenVK DEPENDS ${MVK_DYLIB_DST}) set_property(TARGET shadps4 APPEND PROPERTY BUILD_RPATH "@executable_path")
add_dependencies(CopyMoltenVK MoltenVK) set(MVK_ICD_DST ${CMAKE_CURRENT_BINARY_DIR}/MoltenVK_icd.json)
add_dependencies(shadps4 CopyMoltenVK) set(MVK_DYLIB_DST ${CMAKE_CURRENT_BINARY_DIR}/libMoltenVK.dylib)
set_property(TARGET shadps4 APPEND PROPERTY BUILD_RPATH "@executable_path/../Frameworks") set(MVK_DYLIB_ICD_PATH "./libMoltenVK.dylib")
else() endif()
# For non-bundled SDL build, just do a normal library link.
target_link_libraries(shadps4 PRIVATE MoltenVK)
endif()
if (ARCHITECTURE STREQUAL "x86_64") cmake_path(GET MVK_ICD_DST PARENT_PATH MVK_ICD_DST_PARENT)
# Reserve system-managed memory space. cmake_path(GET MVK_DYLIB_DST PARENT_PATH MVK_DYLIB_DST_PARENT)
target_link_options(shadps4 PRIVATE -Wl,-no_pie,-no_fixup_chains,-no_huge,-pagezero_size,0x4000,-segaddr,TCB_SPACE,0x4000,-segaddr,SYSTEM_MANAGED,0x400000,-segaddr,SYSTEM_RESERVED,0x7FFFFC000,-image_base,0x20000000000)
endif()
# Replacement for std::chrono::time_zone set(MVK_ICD "\\\{ \\\"file_format_version\\\": \\\"1.0.0\\\", \\\"ICD\\\": \\\{ \\\"library_path\\\": \\\"${MVK_DYLIB_ICD_PATH}\\\", \\\"api_version\\\": \\\"1.2.0\\\", \\\"is_portability_driver\\\": true \\\} \\\}")
target_link_libraries(shadps4 PRIVATE date::date-tz) add_custom_command(
OUTPUT ${MVK_ICD_DST}
COMMAND ${CMAKE_COMMAND} -E make_directory ${MVK_ICD_DST_PARENT} && ${CMAKE_COMMAND} -E echo ${MVK_ICD} > ${MVK_ICD_DST})
add_custom_command(
OUTPUT ${MVK_DYLIB_DST}
DEPENDS ${MVK_DYLIB_SRC}
COMMAND ${CMAKE_COMMAND} -E make_directory ${MVK_DYLIB_DST_PARENT} && ${CMAKE_COMMAND} -E copy ${MVK_DYLIB_SRC} ${MVK_DYLIB_DST})
add_custom_target(CopyMoltenVK DEPENDS ${MVK_ICD_DST} ${MVK_DYLIB_DST})
add_dependencies(CopyMoltenVK MoltenVK)
add_dependencies(shadps4 CopyMoltenVK)
if (ARCHITECTURE STREQUAL "x86_64")
# 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,SYSTEM_MANAGED,0x400000,-segaddr,SYSTEM_RESERVED,0x7FFFFC000,-image_base,0x20000000000)
endif()
# Replacement for std::chrono::time_zone
target_link_libraries(shadps4 PRIVATE date::date-tz)
endif() endif()
if (NOT ENABLE_QT_GUI) if (NOT ENABLE_QT_GUI)

@ -1 +1 @@
Subproject commit 067fc6c85b02f37dfda58eeda49d8458e093ed60 Subproject commit 4cf8f94684c53e581eb9cc694dd3305d1f7d9959

View file

@ -1,8 +0,0 @@
{
"file_format_version": "1.0.0",
"ICD": {
"library_path": "../../../Frameworks/libMoltenVK.dylib",
"api_version": "1.2.0",
"is_portability_driver": true
}
}

@ -1 +1 @@
Subproject commit 185833a61cbe29ce3bfb5a499ffb3dfeaee3bbe7 Subproject commit 2275d0efc4f2fa46851035d9d3c67c105bc8b99e

View file

@ -88,7 +88,7 @@ static std::optional<std::filesystem::path> GetBundleParentDirectory() {
#endif #endif
static auto UserPaths = [] { static auto UserPaths = [] {
#ifdef __APPLE__ #if defined(__APPLE__) && defined(ENABLE_QT_GUI)
// Set the current path to the directory containing the app bundle. // Set the current path to the directory containing the app bundle.
if (const auto bundle_dir = GetBundleParentDirectory()) { if (const auto bundle_dir = GetBundleParentDirectory()) {
std::filesystem::current_path(*bundle_dir); std::filesystem::current_path(*bundle_dir);

View file

@ -22,6 +22,10 @@
#include "sdl_window.h" #include "sdl_window.h"
#include "video_core/renderer_vulkan/vk_platform.h" #include "video_core/renderer_vulkan/vk_platform.h"
#ifdef __APPLE__
#include <mach-o/dyld.h>
#endif
namespace Vulkan { namespace Vulkan {
static const char* const VALIDATION_LAYER_NAME = "VK_LAYER_KHRONOS_validation"; static const char* const VALIDATION_LAYER_NAME = "VK_LAYER_KHRONOS_validation";
@ -223,19 +227,25 @@ vk::UniqueInstance CreateInstance(Frontend::WindowSystemType window_type, bool e
LOG_INFO(Render_Vulkan, "Creating vulkan instance"); LOG_INFO(Render_Vulkan, "Creating vulkan instance");
#ifdef __APPLE__ #ifdef __APPLE__
#ifdef ENABLE_QT_GUI #ifndef ENABLE_QT_GUI
// Initialize the environment with the path to the MoltenVK ICD, so that the loader will
// find it.
static const auto icd_path = [] {
char path[PATH_MAX];
u32 length = PATH_MAX;
_NSGetExecutablePath(path, &length);
return std::filesystem::path(path).parent_path() / "MoltenVK_icd.json";
}();
setenv("VK_DRIVER_FILES", icd_path.c_str(), true);
#endif
// If the Vulkan loader exists in /usr/local/lib, give it priority. The Vulkan SDK // If the Vulkan loader exists in /usr/local/lib, give it priority. The Vulkan SDK
// installs it here by default but it is not in the default library search path. // installs it here by default, but it is not in the default library search path.
// The loader has a clause to check for it, but at a lower priority than the bundled // The loader has a clause to check for it, but at a lower priority than the bundled
// libMoltenVK.dylib, so we need to handle it ourselves to give it priority. // libMoltenVK.dylib, so we need to handle it ourselves to give it priority.
static const std::string usr_local_path = "/usr/local/lib/libvulkan.dylib"; static const std::string usr_local_path = "/usr/local/lib/libvulkan.dylib";
static vk::detail::DynamicLoader dl = std::filesystem::exists(usr_local_path) static vk::detail::DynamicLoader dl = std::filesystem::exists(usr_local_path)
? vk::detail::DynamicLoader(usr_local_path) ? vk::detail::DynamicLoader(usr_local_path)
: vk::detail::DynamicLoader(); : vk::detail::DynamicLoader();
#else
// TODO: Support layer loading in SDL build. For now just make sure we load the right MoltenVK.
static vk::detail::DynamicLoader dl("libMoltenVK.dylib");
#endif
#else #else
static vk::detail::DynamicLoader dl; static vk::detail::DynamicLoader dl;
#endif #endif