mirror of
https://github.com/hedge-dev/UnleashedRecomp.git
synced 2025-04-28 21:37:58 +03:00
Merge 2872dbb743
into 8370312454
This commit is contained in:
commit
0b7a03e5b3
111 changed files with 2191 additions and 301 deletions
72
.github/workflows/validate.yml
vendored
72
.github/workflows/validate.yml
vendored
|
@ -210,3 +210,75 @@ jobs:
|
|||
with:
|
||||
name: UnleashedRecomp-Flatpak
|
||||
path: ./${{ env.FLATPAK_ID }}.flatpak
|
||||
build-macos:
|
||||
name: Build macOS
|
||||
runs-on: macos-15
|
||||
strategy:
|
||||
matrix:
|
||||
arch: [ "arm64" ]
|
||||
preset: ["macos-debug", "macos-release", "macos-relwithdebinfo"]
|
||||
env:
|
||||
CMAKE_PRESET: ${{ matrix.preset }}
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Checkout Private Repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: ${{ secrets.ASSET_REPO }}
|
||||
token: ${{ secrets.ASSET_REPO_TOKEN }}
|
||||
path: ./private
|
||||
|
||||
- name: Setup ccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
with:
|
||||
key: ccache-${{ runner.os }}-${{ matrix.arch }}-${{ matrix.preset }}
|
||||
|
||||
- name: Cache vcpkg
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
./thirdparty/vcpkg/downloads
|
||||
./thirdparty/vcpkg/packages
|
||||
key: vcpkg-${{ runner.os }}-${{ matrix.arch }}-${{ hashFiles('vcpkg.json') }}
|
||||
restore-keys: |
|
||||
vcpkg-${{ runner.os }}-${{ matrix.arch }}-
|
||||
|
||||
- name: Install Dependencies (macOS)
|
||||
run: |
|
||||
brew install ninja
|
||||
|
||||
- name: Cache ccache Directory
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: /tmp/ccache
|
||||
key: ccache-${{ runner.os }}-${{ matrix.arch }}-${{ matrix.preset }}
|
||||
|
||||
- name: Prepare Project
|
||||
run: |
|
||||
cp ./private/* ./UnleashedRecompLib/private
|
||||
|
||||
- name: Configure Project
|
||||
env:
|
||||
CCACHE_DIR: /tmp/ccache
|
||||
run: cmake . --preset ${{ env.CMAKE_PRESET }} -DCMAKE_OSX_ARCHITECTURES=${{ matrix.arch }} -DSDL2MIXER_VORBIS=VORBISFILE -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_C_COMPILER_LAUNCHER=ccache
|
||||
|
||||
- name: Build Project
|
||||
env:
|
||||
CCACHE_DIR: /tmp/ccache
|
||||
run: cmake --build ./out/build/${{ env.CMAKE_PRESET }} --target UnleashedRecomp
|
||||
|
||||
- name: Pack Release
|
||||
run: |
|
||||
codesign --deep -fs - "./out/build/${{ env.CMAKE_PRESET }}/UnleashedRecomp/Unleashed Recompiled.app"
|
||||
tar -czf UnleashedRecomp-macOS-${{ matrix.arch }}-${{ env.CMAKE_PRESET }}.tar.gz -C ./out/build/${{ env.CMAKE_PRESET }}/UnleashedRecomp "Unleashed Recompiled.app"
|
||||
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: UnleashedRecomp-macOS-${{ matrix.arch }}-${{ env.CMAKE_PRESET }}
|
||||
path: UnleashedRecomp-macOS-${{ matrix.arch }}-${{ env.CMAKE_PRESET }}.tar.gz
|
||||
|
|
8
.gitmodules
vendored
8
.gitmodules
vendored
|
@ -6,7 +6,7 @@
|
|||
url = https://github.com/redorav/ddspp.git
|
||||
[submodule "tools/XenosRecomp"]
|
||||
path = tools/XenosRecomp
|
||||
url = https://github.com/hedge-dev/XenosRecomp.git
|
||||
url = https://github.com/IsaacMarovitz/XenosRecomp.git
|
||||
[submodule "UnleashedRecompResources"]
|
||||
path = UnleashedRecompResources
|
||||
url = https://github.com/hedge-dev/UnleashedRecompResources.git
|
||||
|
@ -58,6 +58,12 @@
|
|||
[submodule "thirdparty/json"]
|
||||
path = thirdparty/json
|
||||
url = https://github.com/nlohmann/json
|
||||
[submodule "thirdparty/MoltenVK/MoltenVK"]
|
||||
path = thirdparty/MoltenVK/MoltenVK
|
||||
url = https://github.com/KhronosGroup/MoltenVK.git
|
||||
[submodule "thirdparty/MoltenVK/SPIRV-Cross"]
|
||||
path = thirdparty/MoltenVK/SPIRV-Cross
|
||||
url = https://github.com/KhronosGroup/SPIRV-Cross.git
|
||||
[submodule "UnleashedRecomp/api"]
|
||||
path = UnleashedRecomp/api
|
||||
url = https://github.com/hedge-dev/SWA.git
|
||||
|
|
|
@ -4,7 +4,6 @@ if(NOT DEFINED ENV{VCPKG_ROOT})
|
|||
message(FATAL_ERROR "VCPKG_ROOT is not defined!")
|
||||
endif()
|
||||
|
||||
include($ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake)
|
||||
set(UNLEASHED_RECOMP_THIRDPARTY_ROOT ${CMAKE_SOURCE_DIR}/thirdparty)
|
||||
set(UNLEASHED_RECOMP_TOOLS_ROOT ${CMAKE_SOURCE_DIR}/tools)
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
|
@ -18,16 +17,32 @@ endif()
|
|||
|
||||
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||
|
||||
# Target Sandy Bridge for all projects
|
||||
add_compile_options(
|
||||
-march=sandybridge
|
||||
)
|
||||
if (APPLE)
|
||||
enable_language(OBJC OBJCXX)
|
||||
endif()
|
||||
|
||||
project("UnleashedRecomp-ALL")
|
||||
|
||||
if (CMAKE_OSX_ARCHITECTURES)
|
||||
set(UNLEASHED_RECOMP_ARCHITECTURE ${CMAKE_OSX_ARCHITECTURES})
|
||||
elseif(CMAKE_SYSTEM_PROCESSOR)
|
||||
set(UNLEASHED_RECOMP_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR})
|
||||
else()
|
||||
set(UNLEASHED_RECOMP_ARCHITECTURE ${CMAKE_HOST_SYSTEM_PROCESSOR})
|
||||
endif()
|
||||
string(TOLOWER "${UNLEASHED_RECOMP_ARCHITECTURE}" UNLEASHED_RECOMP_ARCHITECTURE)
|
||||
message(STATUS "Detected architecture: ${UNLEASHED_RECOMP_ARCHITECTURE}")
|
||||
|
||||
if (UNLEASHED_RECOMP_ARCHITECTURE STREQUAL "x86_64" OR UNLEASHED_RECOMP_ARCHITECTURE STREQUAL "amd64")
|
||||
# Target Sandy Bridge for all projects
|
||||
add_compile_options(
|
||||
-march=sandybridge
|
||||
)
|
||||
endif()
|
||||
|
||||
add_subdirectory(${UNLEASHED_RECOMP_THIRDPARTY_ROOT})
|
||||
add_subdirectory(${UNLEASHED_RECOMP_TOOLS_ROOT})
|
||||
|
||||
project("UnleashedRecomp-ALL")
|
||||
|
||||
# Include sub-projects.
|
||||
add_subdirectory("UnleashedRecompLib")
|
||||
add_subdirectory("UnleashedRecomp")
|
||||
|
|
|
@ -113,6 +113,58 @@
|
|||
"CMAKE_BUILD_TYPE": "Release",
|
||||
"CMAKE_INTERPROCEDURAL_OPTIMIZATION": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "macos-base",
|
||||
"hidden": true,
|
||||
"generator": "Ninja",
|
||||
"binaryDir": "${sourceDir}/out/build/${presetName}",
|
||||
"installDir": "${sourceDir}/out/install/${presetName}",
|
||||
"cacheVariables": {
|
||||
"CMAKE_TOOLCHAIN_FILE": {
|
||||
"value": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake",
|
||||
"type": "FILEPATH"
|
||||
},
|
||||
"CMAKE_OSX_DEPLOYMENT_TARGET": "13.0"
|
||||
},
|
||||
"environment": {
|
||||
"VCPKG_ROOT": "${sourceDir}/thirdparty/vcpkg"
|
||||
},
|
||||
"condition": {
|
||||
"type": "equals",
|
||||
"lhs": "${hostSystemName}",
|
||||
"rhs": "Darwin"
|
||||
},
|
||||
"vendor": {
|
||||
"microsoft.com/VisualStudioRemoteSettings/CMake/2.0": {
|
||||
"remoteSourceRootDir": "$env{HOME}/.vs/$ms{projectDirName}"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "macos-debug",
|
||||
"displayName": "macOS-Debug",
|
||||
"inherits": "macos-base",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Debug"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "macos-relwithdebinfo",
|
||||
"displayName": "macOS-RelWithDebInfo",
|
||||
"inherits": "macos-base",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "RelWithDebInfo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "macos-release",
|
||||
"displayName": "macOS-Release",
|
||||
"inherits": "macos-base",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Release",
|
||||
"CMAKE_INTERPROCEDURAL_OPTIMIZATION": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -4,6 +4,10 @@ if (WIN32)
|
|||
option(UNLEASHED_RECOMP_D3D12 "Add D3D12 support for rendering" ON)
|
||||
endif()
|
||||
|
||||
if (APPLE)
|
||||
option(UNLEASHED_RECOMP_METAL "Add Metal support for rendering" ON)
|
||||
endif()
|
||||
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
option(UNLEASHED_RECOMP_FLATPAK "Configure the build for Flatpak compatibility." OFF)
|
||||
endif()
|
||||
|
@ -97,6 +101,14 @@ elseif (CMAKE_SYSTEM_NAME MATCHES "Linux")
|
|||
"os/linux/user_linux.cpp"
|
||||
"os/linux/version_linux.cpp"
|
||||
)
|
||||
elseif (APPLE)
|
||||
set(UNLEASHED_RECOMP_OS_CXX_SOURCES
|
||||
"os/macos/logger_macos.cpp"
|
||||
"os/macos/media_macos.cpp"
|
||||
"os/macos/process_macos.cpp"
|
||||
"os/macos/user_macos.cpp"
|
||||
"os/macos/version_macos.cpp"
|
||||
)
|
||||
endif()
|
||||
|
||||
set(UNLEASHED_RECOMP_CPU_CXX_SOURCES
|
||||
|
@ -119,7 +131,7 @@ endif()
|
|||
|
||||
set(UNLEASHED_RECOMP_APU_CXX_SOURCES
|
||||
"apu/audio.cpp"
|
||||
"apu/embedded_player.cpp"
|
||||
"apu/embedded_player.cpp"
|
||||
"apu/driver/sdl2_driver.cpp"
|
||||
)
|
||||
|
||||
|
@ -149,16 +161,16 @@ set(UNLEASHED_RECOMP_PATCHES_CXX_SOURCES
|
|||
|
||||
set(UNLEASHED_RECOMP_UI_CXX_SOURCES
|
||||
"ui/achievement_menu.cpp"
|
||||
"ui/achievement_overlay.cpp"
|
||||
"ui/achievement_overlay.cpp"
|
||||
"ui/black_bar.cpp"
|
||||
"ui/button_guide.cpp"
|
||||
"ui/fader.cpp"
|
||||
"ui/game_window.cpp"
|
||||
"ui/game_window.cpp"
|
||||
"ui/imgui_utils.cpp"
|
||||
"ui/installer_wizard.cpp"
|
||||
"ui/message_window.cpp"
|
||||
"ui/options_menu.cpp"
|
||||
"ui/options_menu_thumbnails.cpp"
|
||||
"ui/options_menu_thumbnails.cpp"
|
||||
"ui/tv_static.cpp"
|
||||
)
|
||||
|
||||
|
@ -180,7 +192,7 @@ set(UNLEASHED_RECOMP_INSTALL_CXX_SOURCES
|
|||
set(UNLEASHED_RECOMP_USER_CXX_SOURCES
|
||||
"user/achievement_data.cpp"
|
||||
"user/achievement_manager.cpp"
|
||||
"user/config.cpp"
|
||||
"user/config.cpp"
|
||||
"user/registry.cpp"
|
||||
"user/paths.cpp"
|
||||
"user/persistent_data.cpp"
|
||||
|
@ -250,11 +262,11 @@ set(UNLEASHED_RECOMP_CXX_SOURCES
|
|||
${UNLEASHED_RECOMP_USER_CXX_SOURCES}
|
||||
${UNLEASHED_RECOMP_MOD_CXX_SOURCES}
|
||||
${UNLEASHED_RECOMP_THIRDPARTY_SOURCES}
|
||||
)
|
||||
)
|
||||
|
||||
include("version.cmake")
|
||||
|
||||
set(VERSION_TXT "${PROJECT_SOURCE_DIR}/res/version.txt")
|
||||
include("version.cmake")
|
||||
|
||||
set(VERSION_TXT "${PROJECT_SOURCE_DIR}/res/version.txt")
|
||||
|
||||
# Only show Git info and build type if not Release.
|
||||
set(SHOW_GIT_INFO_AND_BUILD_TYPE 0)
|
||||
|
@ -262,6 +274,10 @@ if (NOT ${CMAKE_BUILD_TYPE} MATCHES "Release")
|
|||
set(SHOW_GIT_INFO_AND_BUILD_TYPE 1)
|
||||
endif()
|
||||
|
||||
if (UNLEASHED_RECOMP_METAL)
|
||||
set(XCRUN_TOOL "/usr/bin/xcrun")
|
||||
endif()
|
||||
|
||||
GenerateVersionSources(
|
||||
OUTPUT_DIR ${PROJECT_SOURCE_DIR}
|
||||
VERSION_TXT ${VERSION_TXT}
|
||||
|
@ -270,43 +286,85 @@ GenerateVersionSources(
|
|||
BUILD_TYPE ${CMAKE_BUILD_TYPE}
|
||||
SHOW_GIT_INFO ${SHOW_GIT_INFO_AND_BUILD_TYPE}
|
||||
SHOW_BUILD_TYPE ${SHOW_GIT_INFO_AND_BUILD_TYPE}
|
||||
)
|
||||
)
|
||||
|
||||
if (WIN32)
|
||||
# Create binary version number for Win32 integer attributes.
|
||||
CreateVersionString(
|
||||
VERSION_TXT ${VERSION_TXT}
|
||||
OUTPUT_CSV 1
|
||||
OUTPUT_VAR WIN32_VERSION_BINARY
|
||||
)
|
||||
|
||||
# Create string version number for Win32 detailed attributes.
|
||||
CreateVersionString(
|
||||
VERSION_TXT ${VERSION_TXT}
|
||||
BUILD_TYPE ${CMAKE_BUILD_TYPE}
|
||||
SHOW_GIT_INFO ${SHOW_GIT_INFO_AND_BUILD_TYPE}
|
||||
SHOW_BUILD_TYPE ${SHOW_GIT_INFO_AND_BUILD_TYPE}
|
||||
OUTPUT_VAR WIN32_VERSION_STRING
|
||||
)
|
||||
|
||||
# Create binary version number for Win32 integer attributes.
|
||||
CreateVersionString(
|
||||
VERSION_TXT ${VERSION_TXT}
|
||||
OUTPUT_CSV 1
|
||||
OUTPUT_VAR WIN32_VERSION_BINARY
|
||||
)
|
||||
|
||||
# Create string version number for Win32 detailed attributes.
|
||||
CreateVersionString(
|
||||
VERSION_TXT ${VERSION_TXT}
|
||||
BUILD_TYPE ${CMAKE_BUILD_TYPE}
|
||||
SHOW_GIT_INFO ${SHOW_GIT_INFO_AND_BUILD_TYPE}
|
||||
SHOW_BUILD_TYPE ${SHOW_GIT_INFO_AND_BUILD_TYPE}
|
||||
OUTPUT_VAR WIN32_VERSION_STRING
|
||||
)
|
||||
|
||||
# Set Win32 icon path.
|
||||
set(WIN32_ICON_PATH "${PROJECT_SOURCE_DIR}/../UnleashedRecompResources/images/game_icon.ico")
|
||||
set(WIN32_ICON_PATH "${PROJECT_SOURCE_DIR}/../UnleashedRecompResources/images/game_icon.ico")
|
||||
|
||||
configure_file("res/win32/res.rc.template" "${CMAKE_BINARY_DIR}/res.rc" @ONLY)
|
||||
add_executable(UnleashedRecomp ${UNLEASHED_RECOMP_CXX_SOURCES} "${CMAKE_BINARY_DIR}/res.rc")
|
||||
|
||||
# Hide console for release configurations.
|
||||
if (${CMAKE_BUILD_TYPE} MATCHES "Release")
|
||||
target_link_options(UnleashedRecomp PRIVATE "/SUBSYSTEM:WINDOWS" "/ENTRY:mainCRTStartup")
|
||||
add_executable(UnleashedRecomp ${UNLEASHED_RECOMP_CXX_SOURCES} "${CMAKE_BINARY_DIR}/res.rc")
|
||||
|
||||
# Hide console for release configurations.
|
||||
if (${CMAKE_BUILD_TYPE} MATCHES "Release")
|
||||
target_link_options(UnleashedRecomp PRIVATE "/SUBSYSTEM:WINDOWS" "/ENTRY:mainCRTStartup")
|
||||
endif()
|
||||
elseif (APPLE)
|
||||
# Create version number for app bundle.
|
||||
CreateVersionString(
|
||||
VERSION_TXT ${VERSION_TXT}
|
||||
OUTPUT_VAR MACOS_BUNDLE_VERSION
|
||||
)
|
||||
|
||||
add_executable(UnleashedRecomp MACOSX_BUNDLE
|
||||
${UNLEASHED_RECOMP_CXX_SOURCES}
|
||||
res/macos/game_icon.icns
|
||||
)
|
||||
set_source_files_properties(res/macos/game_icon.icns PROPERTIES
|
||||
MACOSX_PACKAGE_LOCATION Resources)
|
||||
set_target_properties(UnleashedRecomp PROPERTIES
|
||||
OUTPUT_NAME "Unleashed Recompiled"
|
||||
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/res/macos/MacOSXBundleInfo.plist.in
|
||||
MACOSX_BUNDLE_GUI_IDENTIFIER hedge-dev.UnleashedRecomp
|
||||
MACOSX_BUNDLE_BUNDLE_NAME "Unleashed Recompiled"
|
||||
MACOSX_BUNDLE_BUNDLE_VERSION ${MACOS_BUNDLE_VERSION}
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING ${MACOS_BUNDLE_VERSION}
|
||||
MACOSX_BUNDLE_ICON_FILE "game_icon.icns"
|
||||
)
|
||||
|
||||
# Linking with MoltenVK directly would prevent using the system Vulkan loader to load with debug layers.
|
||||
# Instead, copy the MoltenVK dylib to the app bundle along with an ICD file for the loader to find it.
|
||||
# In the event the loader is not installed, the MoltenVK dylib can still be picked up directly in the app bundle.
|
||||
set(MVK_ICD "${UNLEASHED_RECOMP_THIRDPARTY_ROOT}/MoltenVK/MoltenVK_icd.json")
|
||||
target_sources(UnleashedRecomp PRIVATE ${MVK_ICD})
|
||||
set_source_files_properties(${MVK_ICD} PROPERTIES MACOSX_PACKAGE_LOCATION Resources/vulkan/icd.d)
|
||||
|
||||
# Unfortunately using the MoltenVK target output as a resource file does not quite create the correct
|
||||
# dependency chain, so we need to resolve the paths manually and create a copy target dependency chain.
|
||||
set(MVK_DYLIB_SRC "${CMAKE_BINARY_DIR}/thirdparty/MoltenVK/libMoltenVK.dylib")
|
||||
set(MVK_DYLIB_DST "${CMAKE_CURRENT_BINARY_DIR}/Unleashed Recompiled.app/Contents/Frameworks/libMoltenVK.dylib")
|
||||
add_custom_command(
|
||||
OUTPUT ${MVK_DYLIB_DST}
|
||||
DEPENDS ${MVK_DYLIB_SRC}
|
||||
COMMAND cmake -E copy ${MVK_DYLIB_SRC} ${MVK_DYLIB_DST})
|
||||
add_custom_target(CopyMoltenVK DEPENDS ${MVK_DYLIB_DST})
|
||||
add_dependencies(CopyMoltenVK MoltenVK)
|
||||
add_dependencies(UnleashedRecomp CopyMoltenVK)
|
||||
set_property(TARGET UnleashedRecomp APPEND PROPERTY BUILD_RPATH "@executable_path/../Frameworks")
|
||||
else()
|
||||
add_executable(UnleashedRecomp ${UNLEASHED_RECOMP_CXX_SOURCES})
|
||||
endif()
|
||||
|
||||
if (UNLEASHED_RECOMP_FLATPAK)
|
||||
target_compile_definitions(UnleashedRecomp PRIVATE
|
||||
"UNLEASHED_RECOMP_FLATPAK"
|
||||
"GAME_INSTALL_DIRECTORY=\"/var/data\""
|
||||
target_compile_definitions(UnleashedRecomp PRIVATE
|
||||
"UNLEASHED_RECOMP_FLATPAK"
|
||||
"GAME_INSTALL_DIRECTORY=\"/var/data\""
|
||||
)
|
||||
endif()
|
||||
|
||||
|
@ -320,23 +378,25 @@ if (UNLEASHED_RECOMP_D3D12)
|
|||
)
|
||||
endif()
|
||||
|
||||
if (UNLEASHED_RECOMP_METAL)
|
||||
target_compile_definitions(UnleashedRecomp PRIVATE UNLEASHED_RECOMP_METAL)
|
||||
endif()
|
||||
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
target_compile_definitions(UnleashedRecomp PRIVATE SDL_VULKAN_ENABLED)
|
||||
endif()
|
||||
|
||||
find_package(directx-dxc REQUIRED)
|
||||
find_package(CURL REQUIRED)
|
||||
|
||||
if (UNLEASHED_RECOMP_D3D12)
|
||||
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/D3D12)
|
||||
add_custom_command(TARGET UnleashedRecomp POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_PROPERTY:Microsoft::DirectX12-Core,IMPORTED_LOCATION_RELEASE> ${CMAKE_CURRENT_BINARY_DIR}/D3D12
|
||||
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_PROPERTY:Microsoft::DirectX12-Layers,IMPORTED_LOCATION_DEBUG> ${CMAKE_CURRENT_BINARY_DIR}/D3D12
|
||||
COMMAND_EXPAND_LISTS
|
||||
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_PROPERTY:Microsoft::DirectX12-Core,IMPORTED_LOCATION_RELEASE> $<TARGET_FILE_DIR:UnleashedRecomp>/D3D12
|
||||
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_PROPERTY:Microsoft::DirectX12-Layers,IMPORTED_LOCATION_DEBUG> $<TARGET_FILE_DIR:UnleashedRecomp>/D3D12
|
||||
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_PROPERTY:Microsoft::DirectXShaderCompiler,IMPORTED_LOCATION> $<TARGET_FILE_DIR:UnleashedRecomp>
|
||||
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_PROPERTY:Microsoft::DXIL,IMPORTED_LOCATION> $<TARGET_FILE_DIR:UnleashedRecomp>
|
||||
COMMAND_EXPAND_LISTS
|
||||
)
|
||||
|
||||
find_file(DIRECTX_DXIL_LIBRARY "dxil.dll")
|
||||
file(COPY ${DIRECTX_DXIL_LIBRARY} DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
target_link_libraries(UnleashedRecomp PRIVATE
|
||||
Microsoft::DirectX-Headers
|
||||
|
@ -348,18 +408,16 @@ if (UNLEASHED_RECOMP_D3D12)
|
|||
)
|
||||
endif()
|
||||
|
||||
file(CHMOD ${DIRECTX_DXC_TOOL} PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE)
|
||||
|
||||
if (WIN32)
|
||||
target_link_libraries(UnleashedRecomp PRIVATE
|
||||
comctl32
|
||||
comctl32
|
||||
dwmapi
|
||||
ntdll
|
||||
ntdll
|
||||
Shcore
|
||||
Synchronization
|
||||
winmm
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
target_link_libraries(UnleashedRecomp PRIVATE
|
||||
fmt::fmt
|
||||
|
@ -391,35 +449,50 @@ endif()
|
|||
target_precompile_headers(UnleashedRecomp PUBLIC ${UNLEASHED_RECOMP_PRECOMPILED_HEADERS})
|
||||
|
||||
function(compile_shader FILE_PATH TARGET_NAME)
|
||||
set(FILE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/gpu/shader/${FILE_PATH}.hlsl)
|
||||
cmake_path(GET FILE_PATH STEM VARIABLE_NAME)
|
||||
set(HLSL_FILE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/gpu/shader/hlsl/${FILE_PATH}.hlsl)
|
||||
set(MSL_FILE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/gpu/shader/msl/${FILE_PATH}.metal)
|
||||
cmake_path(GET HLSL_FILE_PATH STEM HLSL_NAME)
|
||||
cmake_path(GET MSL_FILE_PATH STEM MSL_NAME)
|
||||
if (UNLEASHED_RECOMP_METAL)
|
||||
add_custom_command(
|
||||
OUTPUT ${MSL_FILE_PATH}.ir
|
||||
COMMAND ${XCRUN_TOOL} -sdk macosx metal -o ${MSL_FILE_PATH}.ir -c ${MSL_FILE_PATH} -D__air__ -frecord-sources -gline-tables-only
|
||||
DEPENDS ${MSL_FILE_PATH}
|
||||
)
|
||||
add_custom_command(
|
||||
OUTPUT ${MSL_FILE_PATH}.metallib
|
||||
COMMAND ${XCRUN_TOOL} -sdk macosx metallib -o ${MSL_FILE_PATH}.metallib ${MSL_FILE_PATH}.ir
|
||||
DEPENDS ${MSL_FILE_PATH}.ir
|
||||
)
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${MSL_FILE_PATH}.metallib" DEST_FILE "${MSL_FILE_PATH}.metallib" ARRAY_NAME "g_${MSL_NAME}_air")
|
||||
endif()
|
||||
if (UNLEASHED_RECOMP_D3D12)
|
||||
add_custom_command(
|
||||
OUTPUT ${FILE_PATH}.dxil.h
|
||||
COMMAND ${DIRECTX_DXC_TOOL} -T ${TARGET_NAME} -HV 2021 -all-resources-bound -Wno-ignored-attributes -Fh ${FILE_PATH}.dxil.h ${FILE_PATH} -Vn g_${VARIABLE_NAME}_dxil
|
||||
DEPENDS ${FILE_PATH}
|
||||
OUTPUT ${HLSL_FILE_PATH}.dxil.h
|
||||
COMMAND ${DIRECTX_DXC_TOOL} -T ${TARGET_NAME} -HV 2021 -all-resources-bound -Wno-ignored-attributes -Fh ${HLSL_FILE_PATH}.dxil.h ${HLSL_FILE_PATH} -Vn g_${HLSL_NAME}_dxil
|
||||
DEPENDS ${HLSL_FILE_PATH}
|
||||
)
|
||||
target_sources(UnleashedRecomp PRIVATE ${FILE_PATH}.dxil.h)
|
||||
target_sources(UnleashedRecomp PRIVATE ${HLSL_FILE_PATH}.dxil.h)
|
||||
endif()
|
||||
add_custom_command(
|
||||
OUTPUT ${FILE_PATH}.spirv.h
|
||||
COMMAND ${DIRECTX_DXC_TOOL} -T ${TARGET_NAME} -HV 2021 -all-resources-bound -spirv -fvk-use-dx-layout ${ARGN} -Fh ${FILE_PATH}.spirv.h ${FILE_PATH} -Vn g_${VARIABLE_NAME}_spirv
|
||||
DEPENDS ${FILE_PATH}
|
||||
OUTPUT ${HLSL_FILE_PATH}.spirv.h
|
||||
COMMAND ${DIRECTX_DXC_TOOL} -T ${TARGET_NAME} -HV 2021 -all-resources-bound -spirv -fvk-use-dx-layout ${ARGN} -Fh ${HLSL_FILE_PATH}.spirv.h ${HLSL_FILE_PATH} -Vn g_${HLSL_NAME}_spirv
|
||||
DEPENDS ${HLSL_FILE_PATH}
|
||||
)
|
||||
target_sources(UnleashedRecomp PRIVATE ${FILE_PATH}.spirv.h)
|
||||
target_sources(UnleashedRecomp PRIVATE ${HLSL_FILE_PATH}.spirv.h)
|
||||
endfunction()
|
||||
|
||||
function(compile_vertex_shader FILE_PATH)
|
||||
compile_shader(${FILE_PATH} vs_6_0 -fvk-invert-y)
|
||||
compile_shader(${FILE_PATH} vs_6_0 -fvk-invert-y -DUNLEASHED_RECOMP)
|
||||
endfunction()
|
||||
|
||||
function(compile_pixel_shader FILE_PATH)
|
||||
compile_shader(${FILE_PATH} ps_6_0)
|
||||
compile_shader(${FILE_PATH} ps_6_0 -DUNLEASHED_RECOMP)
|
||||
endfunction()
|
||||
|
||||
compile_pixel_shader(blend_color_alpha_ps)
|
||||
compile_vertex_shader(copy_vs)
|
||||
compile_pixel_shader(copy_color_ps)
|
||||
compile_pixel_shader(blend_color_alpha_ps)
|
||||
compile_vertex_shader(copy_vs)
|
||||
compile_pixel_shader(copy_color_ps)
|
||||
compile_pixel_shader(copy_depth_ps)
|
||||
compile_pixel_shader(csd_filter_ps)
|
||||
compile_vertex_shader(csd_no_tex_vs)
|
||||
|
@ -433,7 +506,7 @@ compile_pixel_shader(gamma_correction_ps)
|
|||
compile_pixel_shader(imgui_ps)
|
||||
compile_vertex_shader(imgui_vs)
|
||||
compile_pixel_shader(movie_ps)
|
||||
compile_vertex_shader(movie_vs)
|
||||
compile_vertex_shader(movie_vs)
|
||||
compile_pixel_shader(resolve_msaa_color_2x)
|
||||
compile_pixel_shader(resolve_msaa_color_4x)
|
||||
compile_pixel_shader(resolve_msaa_color_8x)
|
||||
|
@ -443,7 +516,7 @@ compile_pixel_shader(resolve_msaa_depth_8x)
|
|||
|
||||
set(RESOURCES_SOURCE_PATH "${PROJECT_SOURCE_DIR}/../UnleashedRecompResources")
|
||||
set(RESOURCES_OUTPUT_PATH "${PROJECT_SOURCE_DIR}/res")
|
||||
|
||||
|
||||
## Miscellaneous ##
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/bc_diff/button_bc_diff.bin" DEST_FILE "${RESOURCES_OUTPUT_PATH}/bc_diff/button_bc_diff.bin" ARRAY_NAME "g_button_bc_diff" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/font/im_font_atlas.bin" DEST_FILE "${RESOURCES_OUTPUT_PATH}/font/im_font_atlas.bin" ARRAY_NAME "g_im_font_atlas" COMPRESSION_TYPE "zstd")
|
||||
|
@ -455,7 +528,7 @@ BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/co
|
|||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/common/kbm.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/common/kbm.dds" ARRAY_NAME "g_kbm" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/common/select.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/common/select.dds" ARRAY_NAME "g_select" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/common/light.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/common/light.dds" ARRAY_NAME "g_light" COMPRESSION_TYPE "zstd")
|
||||
|
||||
|
||||
## Installer ##
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/arrow_circle.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/arrow_circle.dds" ARRAY_NAME "g_arrow_circle" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/install_001.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/install_001.dds" ARRAY_NAME "g_install_001" COMPRESSION_TYPE "zstd")
|
||||
|
@ -467,23 +540,23 @@ BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/in
|
|||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/install_007.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/install_007.dds" ARRAY_NAME "g_install_007" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/install_008.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/install_008.dds" ARRAY_NAME "g_install_008" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/miles_electric_icon.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/miles_electric_icon.dds" ARRAY_NAME "g_miles_electric_icon" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/pulse_install.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/pulse_install.dds" ARRAY_NAME "g_pulse_install" COMPRESSION_TYPE "zstd")
|
||||
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/pulse_install.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/pulse_install.dds" ARRAY_NAME "g_pulse_install" COMPRESSION_TYPE "zstd")
|
||||
|
||||
## Options Menu ##
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/achievement_notifications.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/achievement_notifications.dds" ARRAY_NAME "g_achievement_notifications" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/allow_background_input_ps.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/allow_background_input_ps.dds" ARRAY_NAME "g_allow_background_input_ps" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/allow_background_input_xb.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/allow_background_input_xb.dds" ARRAY_NAME "g_allow_background_input_xb" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/antialiasing_none.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/antialiasing_none.dds" ARRAY_NAME "g_antialiasing_none" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/antialiasing_2x.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/antialiasing_2x.dds" ARRAY_NAME "g_antialiasing_2x" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/antialiasing_4x.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/antialiasing_4x.dds" ARRAY_NAME "g_antialiasing_4x" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/antialiasing_none.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/antialiasing_none.dds" ARRAY_NAME "g_antialiasing_none" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/antialiasing_2x.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/antialiasing_2x.dds" ARRAY_NAME "g_antialiasing_2x" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/antialiasing_4x.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/antialiasing_4x.dds" ARRAY_NAME "g_antialiasing_4x" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/antialiasing_8x.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/antialiasing_8x.dds" ARRAY_NAME "g_antialiasing_8x" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/aspect_ratio.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/aspect_ratio.dds" ARRAY_NAME "g_aspect_ratio" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/battle_theme.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/battle_theme.dds" ARRAY_NAME "g_battle_theme" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/brightness.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/brightness.dds" ARRAY_NAME "g_brightness" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/channel_stereo.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/channel_stereo.dds" ARRAY_NAME "g_channel_stereo" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/channel_surround.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/channel_surround.dds" ARRAY_NAME "g_channel_surround" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/brightness.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/brightness.dds" ARRAY_NAME "g_brightness" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/channel_stereo.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/channel_stereo.dds" ARRAY_NAME "g_channel_stereo" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/channel_surround.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/channel_surround.dds" ARRAY_NAME "g_channel_surround" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/control_tutorial_ps.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/control_tutorial_ps.dds" ARRAY_NAME "g_control_tutorial_ps" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/control_tutorial_xb.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/control_tutorial_xb.dds" ARRAY_NAME "g_control_tutorial_xb" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/control_tutorial_xb.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/control_tutorial_xb.dds" ARRAY_NAME "g_control_tutorial_xb" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/controller_icons.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/controller_icons.dds" ARRAY_NAME "g_controller_icons" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/default.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/default.dds" ARRAY_NAME "g_default" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/effects_volume.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/effects_volume.dds" ARRAY_NAME "g_effects_volume" COMPRESSION_TYPE "zstd")
|
||||
|
@ -499,7 +572,7 @@ BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/op
|
|||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/motion_blur_off.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/motion_blur_off.dds" ARRAY_NAME "g_motion_blur_off" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/motion_blur_original.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/motion_blur_original.dds" ARRAY_NAME "g_motion_blur_original" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/motion_blur_enhanced.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/motion_blur_enhanced.dds" ARRAY_NAME "g_motion_blur_enhanced" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/movie_scale_fit.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/movie_scale_fit.dds" ARRAY_NAME "g_movie_scale_fit" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/movie_scale_fit.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/movie_scale_fit.dds" ARRAY_NAME "g_movie_scale_fit" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/movie_scale_fill.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/movie_scale_fill.dds" ARRAY_NAME "g_movie_scale_fill" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/music_attenuation.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/music_attenuation.dds" ARRAY_NAME "g_music_attenuation" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/music_volume.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/music_volume.dds" ARRAY_NAME "g_music_volume" COMPRESSION_TYPE "zstd")
|
||||
|
@ -508,34 +581,34 @@ BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/op
|
|||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/shadow_resolution_x2048.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/shadow_resolution_x2048.dds" ARRAY_NAME "g_shadow_resolution_x2048" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/shadow_resolution_x4096.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/shadow_resolution_x4096.dds" ARRAY_NAME "g_shadow_resolution_x4096" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/shadow_resolution_x8192.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/shadow_resolution_x8192.dds" ARRAY_NAME "g_shadow_resolution_x8192" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/time_transition_ps.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/time_transition_ps.dds" ARRAY_NAME "g_time_of_day_transition_playstation" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/time_transition_ps.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/time_transition_ps.dds" ARRAY_NAME "g_time_of_day_transition_playstation" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/time_transition_xb.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/time_transition_xb.dds" ARRAY_NAME "g_time_of_day_transition_xbox" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/transparency_antialiasing_false.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/transparency_antialiasing_false.dds" ARRAY_NAME "g_transparency_antialiasing_false" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/transparency_antialiasing_true.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/transparency_antialiasing_true.dds" ARRAY_NAME "g_transparency_antialiasing_true" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/ui_alignment_centre.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/ui_alignment_centre.dds" ARRAY_NAME "g_ui_alignment_centre" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/ui_alignment_centre.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/ui_alignment_centre.dds" ARRAY_NAME "g_ui_alignment_centre" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/ui_alignment_edge.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/ui_alignment_edge.dds" ARRAY_NAME "g_ui_alignment_edge" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/vertical_camera.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/vertical_camera.dds" ARRAY_NAME "g_vertical_camera" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/voice_language.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/voice_language.dds" ARRAY_NAME "g_voice_language" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/vibration_ps.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/vibration_ps.dds" ARRAY_NAME "g_vibration_ps" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/vibration_xb.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/vibration_xb.dds" ARRAY_NAME "g_vibration_xb" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/vsync_on.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/vsync_on.dds" ARRAY_NAME "g_vsync_on" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/vibration_xb.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/vibration_xb.dds" ARRAY_NAME "g_vibration_xb" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/vsync_on.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/vsync_on.dds" ARRAY_NAME "g_vsync_on" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/vsync_off.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/vsync_off.dds" ARRAY_NAME "g_vsync_off" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/window_size.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/window_size.dds" ARRAY_NAME "g_window_size" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/xbox_color_correction.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/xbox_color_correction.dds" ARRAY_NAME "g_xbox_color_correction" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/miles_electric.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/miles_electric.dds" ARRAY_NAME "g_miles_electric" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/options_static.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/options_static.dds" ARRAY_NAME "g_options_static" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/miles_electric.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/miles_electric.dds" ARRAY_NAME "g_miles_electric" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/options_static.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/options_static.dds" ARRAY_NAME "g_options_static" COMPRESSION_TYPE "zstd")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/options_static_flash.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/options_static_flash.dds" ARRAY_NAME "g_options_static_flash" COMPRESSION_TYPE "zstd")
|
||||
|
||||
|
||||
## Game Icon ##
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/game_icon.bmp" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/game_icon.bmp" ARRAY_NAME "g_game_icon")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/game_icon_night.bmp" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/game_icon_night.bmp" ARRAY_NAME "g_game_icon_night")
|
||||
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/game_icon_night.bmp" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/game_icon_night.bmp" ARRAY_NAME "g_game_icon_night")
|
||||
|
||||
## Audio ##
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/music/installer.ogg" DEST_FILE "${RESOURCES_OUTPUT_PATH}/music/installer.ogg" ARRAY_NAME "g_installer_music")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/music/installer.ogg" DEST_FILE "${RESOURCES_OUTPUT_PATH}/music/installer.ogg" ARRAY_NAME "g_installer_music")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/sounds/sys_worldmap_cursor.ogg" DEST_FILE "${RESOURCES_OUTPUT_PATH}/sounds/sys_worldmap_cursor.ogg" ARRAY_NAME "g_sys_worldmap_cursor")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/sounds/sys_worldmap_finaldecide.ogg" DEST_FILE "${RESOURCES_OUTPUT_PATH}/sounds/sys_worldmap_finaldecide.ogg" ARRAY_NAME "g_sys_worldmap_finaldecide")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/sounds/sys_actstg_pausecansel.ogg" DEST_FILE "${RESOURCES_OUTPUT_PATH}/sounds/sys_actstg_pausecansel.ogg" ARRAY_NAME "g_sys_actstg_pausecansel")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/sounds/sys_actstg_pausecursor.ogg" DEST_FILE "${RESOURCES_OUTPUT_PATH}/sounds/sys_actstg_pausecursor.ogg" ARRAY_NAME "g_sys_actstg_pausecursor")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/sounds/sys_actstg_pausedecide.ogg" DEST_FILE "${RESOURCES_OUTPUT_PATH}/sounds/sys_actstg_pausedecide.ogg" ARRAY_NAME "g_sys_actstg_pausedecide")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/sounds/sys_actstg_pausewinclose.ogg" DEST_FILE "${RESOURCES_OUTPUT_PATH}/sounds/sys_actstg_pausewinclose.ogg" ARRAY_NAME "g_sys_actstg_pausewinclose")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/sounds/sys_actstg_pausewinopen.ogg" DEST_FILE "${RESOURCES_OUTPUT_PATH}/sounds/sys_actstg_pausewinopen.ogg" ARRAY_NAME "g_sys_actstg_pausewinopen")
|
||||
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/sounds/sys_actstg_pausewinopen.ogg" DEST_FILE "${RESOURCES_OUTPUT_PATH}/sounds/sys_actstg_pausewinopen.ogg" ARRAY_NAME "g_sys_actstg_pausewinopen")
|
||||
|
|
|
@ -40,29 +40,101 @@ GuestThreadContext::~GuestThreadContext()
|
|||
g_userHeap.Free(thread);
|
||||
}
|
||||
|
||||
static void GuestThreadFunc(GuestThreadHandle* hThread)
|
||||
#ifdef USE_PTHREAD
|
||||
static size_t GetStackSize()
|
||||
{
|
||||
// Cache as this should not change.
|
||||
static size_t stackSize = 0;
|
||||
if (stackSize == 0)
|
||||
{
|
||||
// 8 MiB is a typical default.
|
||||
constexpr auto defaultSize = 8 * 1024 * 1024;
|
||||
struct rlimit lim;
|
||||
const auto ret = getrlimit(RLIMIT_STACK, &lim);
|
||||
if (ret == 0 && lim.rlim_cur < defaultSize)
|
||||
{
|
||||
// Use what the system allows.
|
||||
stackSize = lim.rlim_cur;
|
||||
}
|
||||
else
|
||||
{
|
||||
stackSize = defaultSize;
|
||||
}
|
||||
}
|
||||
return stackSize;
|
||||
}
|
||||
|
||||
static void* GuestThreadFunc(void* arg)
|
||||
{
|
||||
GuestThreadHandle* hThread = (GuestThreadHandle*)arg;
|
||||
#else
|
||||
static void* GuestThreadFunc(GuestThreadHandle* hThread)
|
||||
{
|
||||
#endif
|
||||
hThread->suspended.wait(true);
|
||||
GuestThread::Start(hThread->params);
|
||||
#ifdef USE_PTHREAD
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
GuestThreadHandle::GuestThreadHandle(const GuestThreadParams& params)
|
||||
: params(params), suspended((params.flags & 0x1) != 0), thread(GuestThreadFunc, this)
|
||||
: params(params), suspended((params.flags & 0x1) != 0)
|
||||
#ifdef USE_PTHREAD
|
||||
{
|
||||
pthread_attr_t attr;
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setstacksize(&attr, GetStackSize());
|
||||
const auto ret = pthread_create(&thread, &attr, GuestThreadFunc, this);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "pthread_create failed with error code 0x%X.\n", ret);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#else
|
||||
, thread(GuestThreadFunc, this)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
GuestThreadHandle::~GuestThreadHandle()
|
||||
{
|
||||
#ifdef USE_PTHREAD
|
||||
pthread_join(thread, nullptr);
|
||||
#else
|
||||
if (thread.joinable())
|
||||
thread.join();
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename ThreadType>
|
||||
static uint32_t CalcThreadId(const ThreadType& id)
|
||||
{
|
||||
if constexpr (sizeof(id) == 4)
|
||||
return *reinterpret_cast<const uint32_t*>(&id);
|
||||
else
|
||||
return XXH32(&id, sizeof(id), 0);
|
||||
}
|
||||
|
||||
uint32_t GuestThreadHandle::GetThreadId() const
|
||||
{
|
||||
#ifdef USE_PTHREAD
|
||||
return CalcThreadId(thread);
|
||||
#else
|
||||
return CalcThreadId(thread.get_id());
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t GuestThreadHandle::Wait(uint32_t timeout)
|
||||
{
|
||||
assert(timeout == INFINITE);
|
||||
|
||||
#ifdef USE_PTHREAD
|
||||
pthread_join(thread, nullptr);
|
||||
#else
|
||||
if (thread.joinable())
|
||||
thread.join();
|
||||
#endif
|
||||
|
||||
return STATUS_WAIT_0;
|
||||
}
|
||||
|
@ -80,27 +152,25 @@ uint32_t GuestThread::Start(const GuestThreadParams& params)
|
|||
return ctx.ppcContext.r3.u32;
|
||||
}
|
||||
|
||||
static uint32_t GetThreadId(const std::thread::id& id)
|
||||
{
|
||||
if constexpr (sizeof(id) == 4)
|
||||
return *reinterpret_cast<const uint32_t*>(&id);
|
||||
else
|
||||
return XXH32(&id, sizeof(id), 0);
|
||||
}
|
||||
|
||||
GuestThreadHandle* GuestThread::Start(const GuestThreadParams& params, uint32_t* threadId)
|
||||
{
|
||||
auto hThread = CreateKernelObject<GuestThreadHandle>(params);
|
||||
|
||||
if (threadId != nullptr)
|
||||
*threadId = GetThreadId(hThread->thread.get_id());
|
||||
{
|
||||
*threadId = hThread->GetThreadId();
|
||||
}
|
||||
|
||||
return hThread;
|
||||
}
|
||||
|
||||
uint32_t GuestThread::GetCurrentThreadId()
|
||||
{
|
||||
return GetThreadId(std::this_thread::get_id());
|
||||
#ifdef USE_PTHREAD
|
||||
return CalcThreadId(pthread_self());
|
||||
#else
|
||||
return CalcThreadId(std::this_thread::get_id());
|
||||
#endif
|
||||
}
|
||||
|
||||
void GuestThread::SetLastError(uint32_t error)
|
||||
|
|
|
@ -2,6 +2,15 @@
|
|||
|
||||
#include <kernel/xdm.h>
|
||||
|
||||
// Use pthreads directly on macOS to be able to increase default stack size.
|
||||
#ifdef __APPLE__
|
||||
#define USE_PTHREAD 1
|
||||
#endif
|
||||
|
||||
#ifdef USE_PTHREAD
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#define CURRENT_THREAD_HANDLE uint32_t(-2)
|
||||
|
||||
struct GuestThreadContext
|
||||
|
@ -24,11 +33,17 @@ struct GuestThreadHandle : KernelObject
|
|||
{
|
||||
GuestThreadParams params;
|
||||
std::atomic<bool> suspended;
|
||||
#ifdef USE_PTHREAD
|
||||
pthread_t thread;
|
||||
#else
|
||||
std::thread thread;
|
||||
#endif
|
||||
|
||||
GuestThreadHandle(const GuestThreadParams& params);
|
||||
~GuestThreadHandle() override;
|
||||
|
||||
uint32_t GetThreadId() const;
|
||||
|
||||
uint32_t Wait(uint32_t timeout) override;
|
||||
};
|
||||
|
||||
|
|
|
@ -63,3 +63,47 @@ inline std::unique_ptr<uint8_t[]> ReadAllBytes(const char* filePath, size_t& fil
|
|||
|
||||
return data;
|
||||
}
|
||||
|
||||
#ifndef __cpp_lib_atomic_ref
|
||||
// Polyfill for std::atomic_ref
|
||||
namespace std {
|
||||
template <typename value_type>
|
||||
class atomic_ref
|
||||
{
|
||||
public:
|
||||
atomic_ref(value_type& ref)
|
||||
{
|
||||
ptr = reinterpret_cast<std::atomic<value_type>*>(&ref);
|
||||
}
|
||||
|
||||
void store(value_type desired)
|
||||
{
|
||||
ptr->store(desired);
|
||||
}
|
||||
|
||||
bool compare_exchange_weak(value_type& expected, value_type desired)
|
||||
{
|
||||
return ptr->compare_exchange_weak(expected, desired);
|
||||
}
|
||||
|
||||
void wait(value_type old)
|
||||
{
|
||||
ptr->wait(old);
|
||||
}
|
||||
|
||||
void notify_one()
|
||||
{
|
||||
ptr->notify_one();
|
||||
}
|
||||
|
||||
bool operator=(const value_type& rhs)
|
||||
{
|
||||
store(rhs);
|
||||
}
|
||||
|
||||
private:
|
||||
std::atomic<value_type>* ptr;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
#define IMGUI_SHADER_MODIFIER_RECTANGLE_BEVEL 10
|
||||
#define IMGUI_SHADER_MODIFIER_LOW_QUALITY_TEXT 11
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if defined(__cplusplus) && !defined(__air__)
|
||||
|
||||
enum class ImGuiCallback : int32_t
|
||||
{
|
||||
|
|
|
@ -3437,6 +3437,7 @@ namespace plume {
|
|||
adapter = adapterOption;
|
||||
d3d = deviceOption;
|
||||
shaderModel = dataShaderModel.HighestShaderModel;
|
||||
capabilities.geometryShader = true;
|
||||
capabilities.raytracing = rtSupportOption;
|
||||
capabilities.raytracingStateUpdate = rtStateUpdateSupportOption;
|
||||
capabilities.sampleLocations = samplePositionsOption;
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#undef ControlMask
|
||||
#undef Success
|
||||
#elif defined(__APPLE__)
|
||||
typedef struct _NSWindow NSWindow;
|
||||
#include <SDL.h>
|
||||
#endif
|
||||
|
||||
#ifdef SDL_VULKAN_ENABLED
|
||||
|
@ -52,7 +52,9 @@ namespace plume {
|
|||
};
|
||||
#elif defined(__APPLE__)
|
||||
struct RenderWindow {
|
||||
NSWindow* window;
|
||||
SDL_Window* window;
|
||||
void* view;
|
||||
|
||||
bool operator==(const struct RenderWindow& rhs) const {
|
||||
return window == rhs.window;
|
||||
}
|
||||
|
@ -1784,6 +1786,9 @@ namespace plume {
|
|||
};
|
||||
|
||||
struct RenderDeviceCapabilities {
|
||||
// Geometry shaders.
|
||||
bool geometryShader = false;
|
||||
|
||||
// Raytracing.
|
||||
bool raytracing = false;
|
||||
bool raytracingStateUpdate = false;
|
||||
|
|
|
@ -51,13 +51,18 @@ namespace plume {
|
|||
VK_KHR_ANDROID_SURFACE_EXTENSION_NAME,
|
||||
# elif defined(__linux__)
|
||||
VK_KHR_XLIB_SURFACE_EXTENSION_NAME,
|
||||
# elif defined(__APPLE__)
|
||||
VK_EXT_METAL_SURFACE_EXTENSION_NAME,
|
||||
# endif
|
||||
};
|
||||
|
||||
static const std::unordered_set<std::string> OptionalInstanceExtensions = {
|
||||
// No optional instance extensions yet.
|
||||
# if defined(__APPLE__)
|
||||
// Tells the system Vulkan loader to enumerate portability drivers, if supported.
|
||||
VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME,
|
||||
# endif
|
||||
};
|
||||
|
||||
|
||||
static const std::unordered_set<std::string> RequiredDeviceExtensions = {
|
||||
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
|
||||
VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME,
|
||||
|
@ -79,6 +84,8 @@ namespace plume {
|
|||
VK_KHR_PRESENT_ID_EXTENSION_NAME,
|
||||
VK_KHR_PRESENT_WAIT_EXTENSION_NAME,
|
||||
VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME,
|
||||
// Vulkan spec requires this to be enabled if supported by the driver.
|
||||
VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME,
|
||||
};
|
||||
|
||||
// Common functions.
|
||||
|
@ -567,14 +574,16 @@ namespace plume {
|
|||
}
|
||||
}
|
||||
|
||||
static VkPipelineStageFlags toStageFlags(RenderBarrierStages stages, bool rtSupported) {
|
||||
static VkPipelineStageFlags toStageFlags(RenderBarrierStages stages, bool geometrySupported, bool rtSupported) {
|
||||
VkPipelineStageFlags flags = 0;
|
||||
|
||||
if (stages & RenderBarrierStage::GRAPHICS) {
|
||||
flags |= VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT;
|
||||
flags |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
|
||||
flags |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT;
|
||||
flags |= VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
|
||||
if (geometrySupported) {
|
||||
flags |= VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
|
||||
}
|
||||
flags |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
||||
flags |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
|
||||
flags |= VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
|
||||
|
@ -2051,6 +2060,19 @@ namespace plume {
|
|||
fprintf(stderr, "vkCreateXlibSurfaceKHR failed with error code 0x%X.\n", res);
|
||||
return;
|
||||
}
|
||||
# elif defined(__APPLE__)
|
||||
assert(renderWindow.window != 0);
|
||||
assert(renderWindow.view != 0);
|
||||
VkMetalSurfaceCreateInfoEXT surfaceCreateInfo = {};
|
||||
surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT;
|
||||
surfaceCreateInfo.pLayer = renderWindow.view;
|
||||
|
||||
VulkanInterface *renderInterface = commandQueue->device->renderInterface;
|
||||
res = vkCreateMetalSurfaceEXT(renderInterface->instance, &surfaceCreateInfo, nullptr, &surface);
|
||||
if (res != VK_SUCCESS) {
|
||||
fprintf(stderr, "vkCreateMetalSurfaceEXT failed with error code 0x%X.\n", res);
|
||||
return;
|
||||
}
|
||||
# endif
|
||||
|
||||
VkBool32 presentSupported = false;
|
||||
|
@ -2191,7 +2213,14 @@ namespace plume {
|
|||
}
|
||||
|
||||
// Handle the error silently.
|
||||
#if defined(__APPLE__)
|
||||
// Under MoltenVK, VK_SUBOPTIMAL_KHR does not result in a valid state for rendering. We intentionally
|
||||
// only check for this error during present to avoid having to synchronize manually against the semaphore
|
||||
// signalled by vkAcquireNextImageKHR.
|
||||
if (res != VK_SUCCESS) {
|
||||
#else
|
||||
if ((res != VK_SUCCESS) && (res != VK_SUBOPTIMAL_KHR)) {
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2360,6 +2389,8 @@ namespace plume {
|
|||
// The attributes width and height members do not include the border.
|
||||
dstWidth = attributes.width;
|
||||
dstHeight = attributes.height;
|
||||
# elif defined(__APPLE__)
|
||||
SDL_GetWindowSizeInPixels(renderWindow.window, (int *)(&dstWidth), (int *)(&dstHeight));
|
||||
# endif
|
||||
}
|
||||
|
||||
|
@ -2683,9 +2714,10 @@ namespace plume {
|
|||
|
||||
endActiveRenderPass();
|
||||
|
||||
const bool geometryEnabled = device->capabilities.geometryShader;
|
||||
const bool rtEnabled = device->capabilities.raytracing;
|
||||
VkPipelineStageFlags srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
||||
VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT | toStageFlags(stages, rtEnabled);
|
||||
VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT | toStageFlags(stages, geometryEnabled, rtEnabled);
|
||||
thread_local std::vector<VkBufferMemoryBarrier> bufferMemoryBarriers;
|
||||
thread_local std::vector<VkImageMemoryBarrier> imageMemoryBarriers;
|
||||
bufferMemoryBarriers.clear();
|
||||
|
@ -2704,7 +2736,7 @@ namespace plume {
|
|||
bufferMemoryBarrier.offset = 0;
|
||||
bufferMemoryBarrier.size = interfaceBuffer->desc.size;
|
||||
bufferMemoryBarriers.emplace_back(bufferMemoryBarrier);
|
||||
srcStageMask |= toStageFlags(interfaceBuffer->barrierStages, rtEnabled);
|
||||
srcStageMask |= toStageFlags(interfaceBuffer->barrierStages, geometryEnabled, rtEnabled);
|
||||
interfaceBuffer->barrierStages = stages;
|
||||
}
|
||||
|
||||
|
@ -2724,7 +2756,7 @@ namespace plume {
|
|||
imageMemoryBarrier.subresourceRange.layerCount = interfaceTexture->desc.arraySize;
|
||||
imageMemoryBarrier.subresourceRange.aspectMask = (interfaceTexture->desc.flags & RenderTextureFlag::DEPTH_TARGET) ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
imageMemoryBarriers.emplace_back(imageMemoryBarrier);
|
||||
srcStageMask |= toStageFlags(interfaceTexture->barrierStages, rtEnabled);
|
||||
srcStageMask |= toStageFlags(interfaceTexture->barrierStages, geometryEnabled, rtEnabled);
|
||||
interfaceTexture->textureLayout = textureBarrier.layout;
|
||||
interfaceTexture->barrierStages = stages;
|
||||
}
|
||||
|
@ -2890,6 +2922,9 @@ namespace plume {
|
|||
offsetVector.clear();
|
||||
for (uint32_t i = 0; i < viewCount; i++) {
|
||||
const VulkanBuffer *interfaceBuffer = static_cast<const VulkanBuffer *>(views[i].buffer.ref);
|
||||
if (interfaceBuffer == nullptr && !device->nullDescriptorSupported) {
|
||||
interfaceBuffer = static_cast<const VulkanBuffer *>(device->nullBuffer.get());
|
||||
}
|
||||
bufferVector.emplace_back((interfaceBuffer != nullptr) ? interfaceBuffer->vk : VK_NULL_HANDLE);
|
||||
offsetVector.emplace_back(views[i].buffer.offset);
|
||||
}
|
||||
|
@ -3696,6 +3731,11 @@ namespace plume {
|
|||
bufferDeviceAddressFeatures.pNext = featuresChain;
|
||||
featuresChain = &bufferDeviceAddressFeatures;
|
||||
|
||||
VkPhysicalDevicePortabilitySubsetFeaturesKHR portabilityFeatures = {};
|
||||
portabilityFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_FEATURES_KHR;
|
||||
portabilityFeatures.pNext = featuresChain;
|
||||
featuresChain = &portabilityFeatures;
|
||||
|
||||
VkPhysicalDeviceFeatures2 deviceFeatures = {};
|
||||
deviceFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
|
||||
deviceFeatures.pNext = featuresChain;
|
||||
|
@ -3766,6 +3806,12 @@ namespace plume {
|
|||
createDeviceChain = &bufferDeviceAddressFeatures;
|
||||
}
|
||||
|
||||
const bool portabilitySubset = supportedOptionalExtensions.find(VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME) != supportedOptionalExtensions.end();
|
||||
if (portabilitySubset) {
|
||||
portabilityFeatures.pNext = createDeviceChain;
|
||||
createDeviceChain = &portabilityFeatures;
|
||||
}
|
||||
|
||||
// Retrieve the information for the queue families.
|
||||
uint32_t queueFamilyCount = 0;
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyCount, nullptr);
|
||||
|
@ -3778,6 +3824,7 @@ namespace plume {
|
|||
uint32_t familyIndex = 0;
|
||||
uint32_t familySetBits = sizeof(uint32_t) * 8;
|
||||
uint32_t familyQueueCount = 0;
|
||||
bool familyUsed = false;
|
||||
for (uint32_t i = 0; i < queueFamilyCount; i++) {
|
||||
const VkQueueFamilyProperties &props = queueFamilyProperties[i];
|
||||
|
||||
|
@ -3787,11 +3834,14 @@ namespace plume {
|
|||
}
|
||||
|
||||
// Prefer picking the queues with the least amount of bits set that match the mask we're looking for.
|
||||
// If the queue families have matching capabilities but one is already used, prefer the unused one.
|
||||
uint32_t setBits = numberOfSetBits(props.queueFlags);
|
||||
if ((setBits < familySetBits) || ((setBits == familySetBits) && (props.queueCount > familyQueueCount))) {
|
||||
bool used = queueFamilyUsed[i];
|
||||
if ((setBits < familySetBits) || ((setBits == familySetBits) && ((props.queueCount > familyQueueCount) || (familyUsed && !used)))) {
|
||||
familyIndex = i;
|
||||
familySetBits = setBits;
|
||||
familyQueueCount = props.queueCount;
|
||||
familyUsed = used;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3912,6 +3962,7 @@ namespace plume {
|
|||
description.dedicatedVideoMemory = memoryHeapSize;
|
||||
|
||||
// Fill capabilities.
|
||||
capabilities.geometryShader = deviceFeatures.features.geometryShader;
|
||||
capabilities.raytracing = rtSupported;
|
||||
capabilities.raytracingStateUpdate = false;
|
||||
capabilities.sampleLocations = sampleLocationsSupported;
|
||||
|
@ -3920,13 +3971,25 @@ namespace plume {
|
|||
capabilities.presentWait = presentWait;
|
||||
capabilities.displayTiming = supportedOptionalExtensions.find(VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME) != supportedOptionalExtensions.end();
|
||||
capabilities.preferHDR = memoryHeapSize > (512 * 1024 * 1024);
|
||||
#if defined(__APPLE__)
|
||||
// MoltenVK supports triangle fans but does so via compute shaders to translate to lists, since it has to
|
||||
// support all cases including indirect draw. This results in renderpass restarts that can harm performance,
|
||||
// so force disable native triangle fan support and rely on the game to emulate fans if needed.
|
||||
capabilities.triangleFan = false;
|
||||
#else
|
||||
capabilities.triangleFan = true;
|
||||
#endif
|
||||
capabilities.dynamicDepthBias = true;
|
||||
capabilities.uma = (description.type == RenderDeviceType::INTEGRATED) && hasHostVisibleDeviceLocalMemory;
|
||||
capabilities.gpuUploadHeap = capabilities.uma;
|
||||
|
||||
// Fill Vulkan-only capabilities.
|
||||
loadStoreOpNoneSupported = supportedOptionalExtensions.find(VK_EXT_LOAD_STORE_OP_NONE_EXTENSION_NAME) != supportedOptionalExtensions.end();
|
||||
nullDescriptorSupported = nullDescriptor;
|
||||
|
||||
if (!nullDescriptorSupported) {
|
||||
nullBuffer = createBuffer(RenderBufferDesc::DefaultBuffer(16, RenderBufferFlag::VERTEX));
|
||||
}
|
||||
}
|
||||
|
||||
VulkanDevice::~VulkanDevice() {
|
||||
|
@ -4253,6 +4316,10 @@ namespace plume {
|
|||
createInfo.ppEnabledLayerNames = nullptr;
|
||||
createInfo.enabledLayerCount = 0;
|
||||
|
||||
# ifdef __APPLE__
|
||||
createInfo.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
|
||||
# endif
|
||||
|
||||
// Check for extensions.
|
||||
uint32_t extensionCount;
|
||||
vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);
|
||||
|
|
|
@ -20,8 +20,13 @@
|
|||
#define VK_USE_PLATFORM_ANDROID_KHR
|
||||
#elif defined(__linux__)
|
||||
#define VK_USE_PLATFORM_XLIB_KHR
|
||||
#elif defined(__APPLE__)
|
||||
#define VK_USE_PLATFORM_METAL_EXT
|
||||
#endif
|
||||
|
||||
// For VK_KHR_portability_subset
|
||||
#define VK_ENABLE_BETA_EXTENSIONS
|
||||
|
||||
#include <volk.h>
|
||||
|
||||
#ifdef __clang__
|
||||
|
@ -403,7 +408,9 @@ namespace plume {
|
|||
RenderDeviceDescription description;
|
||||
VkPhysicalDeviceRayTracingPipelinePropertiesKHR rtPipelineProperties = {};
|
||||
VkPhysicalDeviceSampleLocationsPropertiesEXT sampleLocationProperties = {};
|
||||
std::unique_ptr<RenderBuffer> nullBuffer = nullptr;
|
||||
bool loadStoreOpNoneSupported = false;
|
||||
bool nullDescriptorSupported = false;
|
||||
|
||||
VulkanDevice(VulkanInterface *renderInterface, const std::string &preferredDeviceName);
|
||||
~VulkanDevice() override;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include "../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
|
||||
#include "../../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
|
||||
|
||||
#ifdef __spirv__
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
#include "../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
|
||||
#include "../../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
|
||||
|
||||
#ifdef __spirv__
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
#include "../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
|
||||
#include "../../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
|
||||
|
||||
#ifdef __spirv__
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
#include "../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
|
||||
#include "../../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
|
||||
|
||||
#ifdef __spirv__
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
#include "../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
|
||||
#include "../../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
|
||||
|
||||
#ifdef __spirv__
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
#include "../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
|
||||
#include "../../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
|
||||
|
||||
#ifdef __spirv__
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
#include "../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
|
||||
#include "../../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
|
||||
|
||||
#ifdef __spirv__
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "../imgui/imgui_common.h"
|
||||
#include "../../imgui/imgui_common.h"
|
||||
|
||||
struct PushConstants
|
||||
{
|
|
@ -1,6 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
|
||||
#include "../../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
|
||||
|
||||
#ifdef __spirv__
|
||||
|
4
UnleashedRecomp/gpu/shader/msl/.gitignore
vendored
Normal file
4
UnleashedRecomp/gpu/shader/msl/.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
*.ir
|
||||
*.metallib
|
||||
*.metal.*.c
|
||||
*.metal.*.h
|
31
UnleashedRecomp/gpu/shader/msl/blend_color_alpha_ps.metal
Normal file
31
UnleashedRecomp/gpu/shader/msl/blend_color_alpha_ps.metal
Normal file
|
@ -0,0 +1,31 @@
|
|||
#include "../../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
|
||||
|
||||
#define g_SrcAlpha_DestAlpha (*(reinterpret_cast<device float4*>(g_PushConstants.PixelShaderConstants + 2400)))
|
||||
#define s0_Texture2DDescriptorIndex (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 0)))
|
||||
#define s0_SamplerDescriptorIndex (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 192)))
|
||||
|
||||
struct Interpolators
|
||||
{
|
||||
float4 iTexCoord0 [[user(TEXCOORD0)]];
|
||||
};
|
||||
|
||||
[[fragment]]
|
||||
float4 shaderMain(float4 iPos [[position]],
|
||||
Interpolators input [[stage_in]],
|
||||
constant Texture2DDescriptorHeap& g_Texture2DDescriptorHeap [[buffer(0)]],
|
||||
constant SamplerDescriptorHeap& g_SamplerDescriptorHeap [[buffer(3)]],
|
||||
constant PushConstants& g_PushConstants [[buffer(4)]])
|
||||
{
|
||||
texture2d<float> texture = g_Texture2DDescriptorHeap.g[s0_Texture2DDescriptorIndex];
|
||||
sampler samplerState = g_SamplerDescriptorHeap.g[s0_SamplerDescriptorIndex];
|
||||
|
||||
float4 color = texture.sample(samplerState, input.iTexCoord0.xy);
|
||||
|
||||
if (any(input.iTexCoord0.xy < 0.0 || input.iTexCoord0.xy > 1.0))
|
||||
color = float4(0.0, 0.0, 0.0, 1.0);
|
||||
|
||||
color.rgb *= color.a * g_SrcAlpha_DestAlpha.x;
|
||||
color.a = g_SrcAlpha_DestAlpha.y + (1.0 - color.a) * g_SrcAlpha_DestAlpha.x;
|
||||
|
||||
return color;
|
||||
}
|
14
UnleashedRecomp/gpu/shader/msl/copy_color_ps.metal
Normal file
14
UnleashedRecomp/gpu/shader/msl/copy_color_ps.metal
Normal file
|
@ -0,0 +1,14 @@
|
|||
#include "copy_common.metali"
|
||||
|
||||
struct Texture2DDescriptorHeap
|
||||
{
|
||||
array<texture2d<float>, 1> g [[id(0)]];
|
||||
};
|
||||
|
||||
[[fragment]]
|
||||
float4 shaderMain(float4 position [[position]],
|
||||
constant Texture2DDescriptorHeap& g_Texture2DDescriptorHeap [[buffer(0)]],
|
||||
constant PushConstants& g_PushConstants [[buffer(4)]])
|
||||
{
|
||||
return g_Texture2DDescriptorHeap.g[g_PushConstants.ResourceDescriptorIndex].read(uint2(position.xy), 0);
|
||||
}
|
9
UnleashedRecomp/gpu/shader/msl/copy_common.metali
Normal file
9
UnleashedRecomp/gpu/shader/msl/copy_common.metali
Normal file
|
@ -0,0 +1,9 @@
|
|||
#pragma once
|
||||
#include <metal_stdlib>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct PushConstants
|
||||
{
|
||||
uint ResourceDescriptorIndex;
|
||||
};
|
23
UnleashedRecomp/gpu/shader/msl/copy_depth_ps.metal
Normal file
23
UnleashedRecomp/gpu/shader/msl/copy_depth_ps.metal
Normal file
|
@ -0,0 +1,23 @@
|
|||
#include "copy_common.metali"
|
||||
|
||||
struct Texture2DDescriptorHeap
|
||||
{
|
||||
array<texture2d<float>, 1> g [[id(0)]];
|
||||
};
|
||||
|
||||
struct PixelShaderOutput
|
||||
{
|
||||
float oDepth [[depth(any)]];
|
||||
};
|
||||
|
||||
[[fragment]]
|
||||
PixelShaderOutput shaderMain(float4 position [[position]],
|
||||
constant Texture2DDescriptorHeap& g_Texture2DDescriptorHeap [[buffer(0)]],
|
||||
constant PushConstants& g_PushConstants [[buffer(4)]])
|
||||
{
|
||||
PixelShaderOutput output = PixelShaderOutput{};
|
||||
|
||||
output.oDepth = g_Texture2DDescriptorHeap.g[g_PushConstants.ResourceDescriptorIndex].read(uint2(position.xy), 0).x;
|
||||
|
||||
return output;
|
||||
}
|
16
UnleashedRecomp/gpu/shader/msl/copy_vs.metal
Normal file
16
UnleashedRecomp/gpu/shader/msl/copy_vs.metal
Normal file
|
@ -0,0 +1,16 @@
|
|||
struct Interpolators
|
||||
{
|
||||
float4 position [[position]];
|
||||
float2 texCoord [[user(TEXCOORD)]];
|
||||
};
|
||||
|
||||
[[vertex]]
|
||||
Interpolators shaderMain(uint vertexId [[vertex_id]])
|
||||
{
|
||||
Interpolators interpolators;
|
||||
|
||||
interpolators.texCoord = float2((vertexId << 1) & 2, vertexId & 2);
|
||||
interpolators.position = float4(interpolators.texCoord * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0);
|
||||
|
||||
return interpolators;
|
||||
}
|
38
UnleashedRecomp/gpu/shader/msl/csd_filter_ps.metal
Normal file
38
UnleashedRecomp/gpu/shader/msl/csd_filter_ps.metal
Normal file
|
@ -0,0 +1,38 @@
|
|||
#include "../../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
|
||||
|
||||
#define s0_Texture2DDescriptorIndex (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 0)))
|
||||
#define s0_SamplerDescriptorIndex (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 192)))
|
||||
|
||||
struct Interpolators
|
||||
{
|
||||
float4 iPosition [[position]];
|
||||
float4 iTexCoord0 [[user(TEXCOORD0)]];
|
||||
float4 iTexCoord1 [[user(TEXCOORD1)]];
|
||||
};
|
||||
|
||||
[[fragment]]
|
||||
float4 shaderMain(Interpolators input [[stage_in]],
|
||||
constant Texture2DDescriptorHeap& g_Texture2DDescriptorHeap [[buffer(0)]],
|
||||
constant SamplerDescriptorHeap& g_SamplerDescriptorHeap [[buffer(3)]],
|
||||
constant PushConstants& g_PushConstants [[buffer(4)]])
|
||||
{
|
||||
texture2d<float> texture = g_Texture2DDescriptorHeap.g[s0_Texture2DDescriptorIndex];
|
||||
sampler samplerState = g_SamplerDescriptorHeap.g[s0_SamplerDescriptorIndex];
|
||||
|
||||
uint2 dimensions = getTexture2DDimensions(texture);
|
||||
|
||||
// https://www.shadertoy.com/view/csX3RH
|
||||
float2 uvTexspace = input.iTexCoord1.xy * float2(dimensions);
|
||||
float2 seam = floor(uvTexspace + 0.5);
|
||||
uvTexspace = (uvTexspace - seam) / fwidth(uvTexspace) + seam;
|
||||
uvTexspace = clamp(uvTexspace, seam - 0.5, seam + 0.5);
|
||||
float2 texCoord = uvTexspace / float2(dimensions);
|
||||
|
||||
float4 color = texture.sample(samplerState, texCoord);
|
||||
color *= input.iTexCoord0;
|
||||
|
||||
// The game enables alpha test for CSD, but the alpha threshold doesn't seem to be assigned anywhere? Weird.
|
||||
clip(color.a - g_AlphaThreshold);
|
||||
|
||||
return color;
|
||||
}
|
64
UnleashedRecomp/gpu/shader/msl/csd_no_tex_vs.metal
Normal file
64
UnleashedRecomp/gpu/shader/msl/csd_no_tex_vs.metal
Normal file
|
@ -0,0 +1,64 @@
|
|||
#include "../../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
|
||||
|
||||
#define g_ViewportSize (*(reinterpret_cast<device float4*>(g_PushConstants.VertexShaderConstants + 2880)))
|
||||
#define g_Z (*(reinterpret_cast<device float4*>(g_PushConstants.VertexShaderConstants + 3936)))
|
||||
|
||||
struct VertexShaderInput
|
||||
{
|
||||
float4 iPosition0 [[attribute(0)]];
|
||||
float4 iColor0 [[attribute(8)]];
|
||||
};
|
||||
|
||||
struct Interpolators
|
||||
{
|
||||
float4 oPos [[position]];
|
||||
float4 oTexCoord0 [[user(TEXCOORD0)]];
|
||||
float4 oTexCoord1 [[user(TEXCOORD1)]];
|
||||
float4 oTexCoord2 [[user(TEXCOORD2)]];
|
||||
float4 oTexCoord3 [[user(TEXCOORD3)]];
|
||||
float4 oTexCoord4 [[user(TEXCOORD4)]];
|
||||
float4 oTexCoord5 [[user(TEXCOORD5)]];
|
||||
float4 oTexCoord6 [[user(TEXCOORD6)]];
|
||||
float4 oTexCoord7 [[user(TEXCOORD7)]];
|
||||
float4 oTexCoord8 [[user(TEXCOORD8)]];
|
||||
float4 oTexCoord9 [[user(TEXCOORD9)]];
|
||||
float4 oTexCoord10 [[user(TEXCOORD10)]];
|
||||
float4 oTexCoord11 [[user(TEXCOORD11)]];
|
||||
float4 oTexCoord12 [[user(TEXCOORD12)]];
|
||||
float4 oTexCoord13 [[user(TEXCOORD13)]];
|
||||
float4 oTexCoord14 [[user(TEXCOORD14)]];
|
||||
float4 oTexCoord15 [[user(TEXCOORD15)]];
|
||||
float4 oColor0 [[user(COLOR0)]];
|
||||
float4 oColor1 [[user(COLOR1)]];
|
||||
};
|
||||
|
||||
[[vertex]]
|
||||
Interpolators shaderMain(VertexShaderInput input [[stage_in]],
|
||||
constant PushConstants& g_PushConstants [[buffer(4)]])
|
||||
{
|
||||
Interpolators output;
|
||||
|
||||
output.oPos.xy = (input.iPosition0.xy - 0.5) * g_ViewportSize.zw * float2(2.0, -2.0) + float2(-1.0, 1.0);
|
||||
output.oPos.z = g_Z.x;
|
||||
output.oPos.w = 1.0;
|
||||
output.oTexCoord0 = input.iColor0.wxyz;
|
||||
output.oTexCoord1 = 0.0;
|
||||
output.oTexCoord2 = 0.0;
|
||||
output.oTexCoord3 = 0.0;
|
||||
output.oTexCoord4 = 0.0;
|
||||
output.oTexCoord5 = 0.0;
|
||||
output.oTexCoord6 = 0.0;
|
||||
output.oTexCoord7 = 0.0;
|
||||
output.oTexCoord8 = 0.0;
|
||||
output.oTexCoord9 = 0.0;
|
||||
output.oTexCoord10 = 0.0;
|
||||
output.oTexCoord11 = 0.0;
|
||||
output.oTexCoord12 = 0.0;
|
||||
output.oTexCoord13 = 0.0;
|
||||
output.oTexCoord14 = 0.0;
|
||||
output.oTexCoord15 = 0.0;
|
||||
output.oColor0 = 0.0;
|
||||
output.oColor1 = 0.0;
|
||||
|
||||
return output;
|
||||
}
|
66
UnleashedRecomp/gpu/shader/msl/csd_vs.metal
Normal file
66
UnleashedRecomp/gpu/shader/msl/csd_vs.metal
Normal file
|
@ -0,0 +1,66 @@
|
|||
#include "../../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
|
||||
|
||||
#define g_ViewportSize (*(reinterpret_cast<device float4*>(g_PushConstants.VertexShaderConstants + 2880)))
|
||||
#define g_Z (*(reinterpret_cast<device float4*>(g_PushConstants.VertexShaderConstants + 3936)))
|
||||
|
||||
struct VertexShaderInput
|
||||
{
|
||||
float4 iPosition0 [[attribute(0)]];
|
||||
float4 iColor0 [[attribute(8)]];
|
||||
float4 iTexCoord0 [[attribute(4)]];
|
||||
};
|
||||
|
||||
struct Interpolators
|
||||
{
|
||||
float4 oPos [[position]];
|
||||
float4 oTexCoord0 [[user(TEXCOORD0)]];
|
||||
float4 oTexCoord1 [[user(TEXCOORD1)]];
|
||||
float4 oTexCoord2 [[user(TEXCOORD2)]];
|
||||
float4 oTexCoord3 [[user(TEXCOORD3)]];
|
||||
float4 oTexCoord4 [[user(TEXCOORD4)]];
|
||||
float4 oTexCoord5 [[user(TEXCOORD5)]];
|
||||
float4 oTexCoord6 [[user(TEXCOORD6)]];
|
||||
float4 oTexCoord7 [[user(TEXCOORD7)]];
|
||||
float4 oTexCoord8 [[user(TEXCOORD8)]];
|
||||
float4 oTexCoord9 [[user(TEXCOORD9)]];
|
||||
float4 oTexCoord10 [[user(TEXCOORD10)]];
|
||||
float4 oTexCoord11 [[user(TEXCOORD11)]];
|
||||
float4 oTexCoord12 [[user(TEXCOORD12)]];
|
||||
float4 oTexCoord13 [[user(TEXCOORD13)]];
|
||||
float4 oTexCoord14 [[user(TEXCOORD14)]];
|
||||
float4 oTexCoord15 [[user(TEXCOORD15)]];
|
||||
float4 oColor0 [[user(COLOR0)]];
|
||||
float4 oColor1 [[user(COLOR1)]];
|
||||
};
|
||||
|
||||
[[vertex]]
|
||||
Interpolators shaderMain(VertexShaderInput input [[stage_in]],
|
||||
constant PushConstants& g_PushConstants [[buffer(4)]])
|
||||
{
|
||||
Interpolators output;
|
||||
|
||||
output.oPos.xy = (input.iPosition0.xy - 0.5) * g_ViewportSize.zw * float2(2.0, -2.0) + float2(-1.0, 1.0);
|
||||
output.oPos.z = g_Z.x;
|
||||
output.oPos.w = 1.0;
|
||||
output.oTexCoord0 = input.iColor0.wxyz;
|
||||
output.oTexCoord1.xy = input.iTexCoord0.xy;
|
||||
output.oTexCoord1.zw = 0.0;
|
||||
output.oTexCoord2 = 0.0;
|
||||
output.oTexCoord3 = 0.0;
|
||||
output.oTexCoord4 = 0.0;
|
||||
output.oTexCoord5 = 0.0;
|
||||
output.oTexCoord6 = 0.0;
|
||||
output.oTexCoord7 = 0.0;
|
||||
output.oTexCoord8 = 0.0;
|
||||
output.oTexCoord9 = 0.0;
|
||||
output.oTexCoord10 = 0.0;
|
||||
output.oTexCoord11 = 0.0;
|
||||
output.oTexCoord12 = 0.0;
|
||||
output.oTexCoord13 = 0.0;
|
||||
output.oTexCoord14 = 0.0;
|
||||
output.oTexCoord15 = 0.0;
|
||||
output.oColor0 = 0.0;
|
||||
output.oColor1 = 0.0;
|
||||
|
||||
return output;
|
||||
}
|
59
UnleashedRecomp/gpu/shader/msl/enhanced_motion_blur_ps.metal
Normal file
59
UnleashedRecomp/gpu/shader/msl/enhanced_motion_blur_ps.metal
Normal file
|
@ -0,0 +1,59 @@
|
|||
#include "../../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
|
||||
|
||||
#define g_BlurRate (*(reinterpret_cast<device float4*>(g_PushConstants.PixelShaderConstants + 2400)))
|
||||
#define g_ViewportSize (*(reinterpret_cast<device float4*>(g_PushConstants.PixelShaderConstants + 384)))
|
||||
|
||||
#define sampColor_Texture2DDescriptorIndex (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 0)))
|
||||
#define sampColor_SamplerDescriptorIndex (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 192)))
|
||||
|
||||
#define sampVelocityMap_Texture2DDescriptorIndex (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 4)))
|
||||
#define sampVelocityMap_SamplerDescriptorIndex (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 196)))
|
||||
|
||||
#define sampZBuffer_Texture2DDescriptorIndex (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 8)))
|
||||
#define sampZBuffer_SamplerDescriptorIndex (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 200)))
|
||||
|
||||
struct Interpolators
|
||||
{
|
||||
float4 texCoord [[user(TEXCOORD0)]];
|
||||
};
|
||||
|
||||
[[fragment]]
|
||||
float4 shaderMain(float4 position [[position]],
|
||||
Interpolators input [[stage_in]],
|
||||
constant Texture2DDescriptorHeap& g_Texture2DDescriptorHeap [[buffer(0)]],
|
||||
constant SamplerDescriptorHeap& g_SamplerDescriptorHeap [[buffer(3)]],
|
||||
constant PushConstants& g_PushConstants [[buffer(4)]])
|
||||
{
|
||||
texture2d<float> sampColor = g_Texture2DDescriptorHeap.g[sampColor_Texture2DDescriptorIndex];
|
||||
texture2d<float> sampVelocityMap = g_Texture2DDescriptorHeap.g[sampVelocityMap_Texture2DDescriptorIndex];
|
||||
texture2d<float> sampZBuffer = g_Texture2DDescriptorHeap.g[sampZBuffer_Texture2DDescriptorIndex];
|
||||
|
||||
sampler sampColor_s = g_SamplerDescriptorHeap.g[sampColor_SamplerDescriptorIndex];
|
||||
sampler sampVelocityMap_s = g_SamplerDescriptorHeap.g[sampVelocityMap_SamplerDescriptorIndex];
|
||||
sampler sampZBuffer_s = g_SamplerDescriptorHeap.g[sampZBuffer_SamplerDescriptorIndex];
|
||||
|
||||
float depth = sampZBuffer.sample(sampZBuffer_s, input.texCoord.xy, level(0)).x;
|
||||
float4 velocityMap = sampVelocityMap.sample(sampVelocityMap_s, input.texCoord.xy, level(0));
|
||||
float2 velocity = (velocityMap.xz + velocityMap.yw / 255.0) * 2.0 - 1.0;
|
||||
|
||||
int sampleCount = min(64, int(round(length(velocity * g_ViewportSize.xy))));
|
||||
float2 sampleOffset = velocity / (float) sampleCount;
|
||||
|
||||
float3 color = sampColor.sample(sampColor_s, input.texCoord.xy, level(0)).rgb;
|
||||
int count = 1;
|
||||
|
||||
for (int i = 1; i <= sampleCount; i++)
|
||||
{
|
||||
float2 sampleCoord = input.texCoord.xy + sampleOffset * i;
|
||||
float3 sampleColor = sampColor.sample(sampColor_s, sampleCoord, level(0)).rgb;
|
||||
float sampleDepth = sampZBuffer.sample(sampZBuffer_s, sampleCoord, 0).x;
|
||||
|
||||
if (sampleDepth - depth < 0.01)
|
||||
{
|
||||
color += sampleColor;
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return float4(color / count, g_BlurRate.x * saturate(dot(abs(velocity), g_ViewportSize.xy) / 8.0) * saturate(float(count - 1)));
|
||||
}
|
23
UnleashedRecomp/gpu/shader/msl/gamma_correction_ps.metal
Normal file
23
UnleashedRecomp/gpu/shader/msl/gamma_correction_ps.metal
Normal file
|
@ -0,0 +1,23 @@
|
|||
#include "../../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
|
||||
|
||||
#define g_Gamma (*(reinterpret_cast<device float3*>(g_PushConstants.SharedConstants + 0)))
|
||||
#define g_TextureDescriptorIndex (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 12)))
|
||||
|
||||
#define g_ViewportOffset (*(reinterpret_cast<device int2*>(g_PushConstants.SharedConstants + 16)))
|
||||
#define g_ViewportSize (*(reinterpret_cast<device int2*>(g_PushConstants.SharedConstants + 24)))
|
||||
|
||||
[[fragment]]
|
||||
float4 shaderMain(float4 position [[position]],
|
||||
constant Texture2DDescriptorHeap& g_Texture2DDescriptorHeap [[buffer(0)]],
|
||||
constant PushConstants& g_PushConstants [[buffer(4)]])
|
||||
{
|
||||
texture2d<float> texture = g_Texture2DDescriptorHeap.g[g_TextureDescriptorIndex];
|
||||
|
||||
int2 movedPosition = int2(position.xy) - g_ViewportOffset;
|
||||
bool boxed = any(movedPosition < 0) || any(movedPosition >= g_ViewportSize);
|
||||
if (boxed) movedPosition = 0;
|
||||
|
||||
float4 color = boxed ? 0.0 : texture.read(uint2(movedPosition), 0);
|
||||
color.rgb = pow(color.rgb, g_Gamma);
|
||||
return color;
|
||||
}
|
63
UnleashedRecomp/gpu/shader/msl/gaussian_blur.metali
Normal file
63
UnleashedRecomp/gpu/shader/msl/gaussian_blur.metali
Normal file
|
@ -0,0 +1,63 @@
|
|||
#include "../../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
|
||||
|
||||
#define g_ViewportSize (*(reinterpret_cast<device float4*>(g_PushConstants.PixelShaderConstants + 384)))
|
||||
#define g_offsets(INDEX) selectWrapper((INDEX) < 74,(*(reinterpret_cast<device float4*>(g_PushConstants.PixelShaderConstants + (150 + min(INDEX, 73)) * 16))), 0.0)
|
||||
#define g_weights (*(reinterpret_cast<device float4*>(g_PushConstants.PixelShaderConstants + 2656)))
|
||||
|
||||
#define s0_Texture2DDescriptorIndex (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 0)))
|
||||
#define s0_SamplerDescriptorIndex (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 192)))
|
||||
|
||||
#ifdef __INTELLISENSE__
|
||||
#define KERNEL_SIZE 5
|
||||
#endif
|
||||
|
||||
#define PI 3.14159265358979323846
|
||||
|
||||
float ComputeWeight(float x)
|
||||
{
|
||||
float std = 0.952;
|
||||
return exp(-(x * x) / (2.0 * std * std)) / (std * sqrt(2.0 * PI));
|
||||
}
|
||||
|
||||
struct Interpolators
|
||||
{
|
||||
float4 iTexCoord0 [[user(TEXCOORD0)]];
|
||||
};
|
||||
|
||||
[[fragment]]
|
||||
float4 shaderMain(float4 iPosition [[position]],
|
||||
Interpolators input [[stage_in]],
|
||||
constant Texture2DDescriptorHeap& g_Texture2DDescriptorHeap [[buffer(0)]],
|
||||
constant SamplerDescriptorHeap& g_SamplerDescriptorHeap [[buffer(3)]],
|
||||
constant PushConstants& g_PushConstants [[buffer(4)]])
|
||||
{
|
||||
texture2d<float> texture = g_Texture2DDescriptorHeap.g[s0_Texture2DDescriptorIndex];
|
||||
sampler samplerState = g_SamplerDescriptorHeap.g[s0_SamplerDescriptorIndex];
|
||||
|
||||
float scale;
|
||||
if ((g_ViewportSize.x * g_ViewportSize.w) >= (16.0 / 9.0))
|
||||
scale = g_ViewportSize.y / 360.0;
|
||||
else
|
||||
scale = g_ViewportSize.x / 640.0;
|
||||
|
||||
float2 offsets[3];
|
||||
offsets[0] = g_offsets(0).xy * scale;
|
||||
offsets[1] = g_offsets(0).zw * scale;
|
||||
offsets[2] = g_offsets(1).xy * scale;
|
||||
|
||||
float4 color = 0.0;
|
||||
float weightSum = 0.0;
|
||||
|
||||
for (int i = 0; i < KERNEL_SIZE; i++)
|
||||
{
|
||||
float step = i / float(KERNEL_SIZE - 1);
|
||||
float scaled = step * 2;
|
||||
float2 offset = mix(offsets[int(scaled)], offsets[min(int(scaled) + 1, 2)], frac(scaled));
|
||||
float offsetScale = 1.0 / 0.75;
|
||||
float weight = ComputeWeight(mix(-offsetScale, offsetScale, step));
|
||||
color += texture.sample(samplerState, input.iTexCoord0.xy + offset, level(0)) * weight;
|
||||
weightSum += weight;
|
||||
}
|
||||
|
||||
return color / weightSum;
|
||||
}
|
2
UnleashedRecomp/gpu/shader/msl/gaussian_blur_3x3.metal
Normal file
2
UnleashedRecomp/gpu/shader/msl/gaussian_blur_3x3.metal
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define KERNEL_SIZE 3
|
||||
#include "gaussian_blur.metali"
|
2
UnleashedRecomp/gpu/shader/msl/gaussian_blur_5x5.metal
Normal file
2
UnleashedRecomp/gpu/shader/msl/gaussian_blur_5x5.metal
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define KERNEL_SIZE 5
|
||||
#include "gaussian_blur.metali"
|
2
UnleashedRecomp/gpu/shader/msl/gaussian_blur_7x7.metal
Normal file
2
UnleashedRecomp/gpu/shader/msl/gaussian_blur_7x7.metal
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define KERNEL_SIZE 7
|
||||
#include "gaussian_blur.metali"
|
2
UnleashedRecomp/gpu/shader/msl/gaussian_blur_9x9.metal
Normal file
2
UnleashedRecomp/gpu/shader/msl/gaussian_blur_9x9.metal
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define KERNEL_SIZE 9
|
||||
#include "gaussian_blur.metali"
|
41
UnleashedRecomp/gpu/shader/msl/imgui_common.metali
Normal file
41
UnleashedRecomp/gpu/shader/msl/imgui_common.metali
Normal file
|
@ -0,0 +1,41 @@
|
|||
#pragma once
|
||||
#include <metal_stdlib>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
#include "../../imgui/imgui_common.h"
|
||||
|
||||
struct PushConstants
|
||||
{
|
||||
float2 BoundsMin;
|
||||
float2 BoundsMax;
|
||||
uint GradientTopLeft;
|
||||
uint GradientTopRight;
|
||||
uint GradientBottomRight;
|
||||
uint GradientBottomLeft;
|
||||
uint ShaderModifier;
|
||||
uint Texture2DDescriptorIndex;
|
||||
float2 DisplaySize;
|
||||
float2 InverseDisplaySize;
|
||||
float2 Origin;
|
||||
float2 Scale;
|
||||
float2 ProceduralOrigin;
|
||||
float Outline;
|
||||
};
|
||||
|
||||
struct Interpolators
|
||||
{
|
||||
float4 Position [[position]];
|
||||
float2 UV;
|
||||
float4 Color;
|
||||
};
|
||||
|
||||
struct Texture2DDescriptorHeap
|
||||
{
|
||||
array<texture2d<float>, 1> g [[id(0)]];
|
||||
};
|
||||
|
||||
struct SamplerDescriptorHeap
|
||||
{
|
||||
array<sampler, 1> g [[id(0)]];
|
||||
};
|
235
UnleashedRecomp/gpu/shader/msl/imgui_ps.metal
Normal file
235
UnleashedRecomp/gpu/shader/msl/imgui_ps.metal
Normal file
|
@ -0,0 +1,235 @@
|
|||
#include "imgui_common.metali"
|
||||
|
||||
float4 DecodeColor(uint color)
|
||||
{
|
||||
return float4(color & 0xFF, (color >> 8) & 0xFF, (color >> 16) & 0xFF, (color >> 24) & 0xFF) / 255.0;
|
||||
}
|
||||
|
||||
float4 SamplePoint(int2 position, constant PushConstants& g_PushConstants)
|
||||
{
|
||||
switch (g_PushConstants.ShaderModifier)
|
||||
{
|
||||
case IMGUI_SHADER_MODIFIER_SCANLINE:
|
||||
{
|
||||
if (int(position.y) % 2 == 0)
|
||||
return float4(1.0, 1.0, 1.0, 0.0);
|
||||
|
||||
break;
|
||||
}
|
||||
case IMGUI_SHADER_MODIFIER_CHECKERBOARD:
|
||||
{
|
||||
int remnantX = int(position.x) % 9;
|
||||
int remnantY = int(position.y) % 9;
|
||||
|
||||
float4 color = 1.0;
|
||||
|
||||
if (remnantX == 0 || remnantY == 0)
|
||||
color.a = 0.0;
|
||||
|
||||
if ((remnantY % 2) == 0)
|
||||
color.rgb = 0.5;
|
||||
|
||||
return color;
|
||||
}
|
||||
case IMGUI_SHADER_MODIFIER_SCANLINE_BUTTON:
|
||||
{
|
||||
if (int(position.y) % 2 == 0)
|
||||
return float4(1.0, 1.0, 1.0, 0.5);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
float4 SampleLinear(float2 uvTexspace, constant PushConstants& g_PushConstants)
|
||||
{
|
||||
int2 integerPart = int2(floor(uvTexspace));
|
||||
float2 fracPart = fract(uvTexspace);
|
||||
|
||||
float4 topLeft = SamplePoint(integerPart + int2(0, 0), g_PushConstants);
|
||||
float4 topRight = SamplePoint(integerPart + int2(1, 0), g_PushConstants);
|
||||
float4 bottomLeft = SamplePoint(integerPart + int2(0, 1), g_PushConstants);
|
||||
float4 bottomRight = SamplePoint(integerPart + int2(1, 1), g_PushConstants);
|
||||
|
||||
float4 top = mix(topLeft, topRight, fracPart.x);
|
||||
float4 bottom = mix(bottomLeft, bottomRight, fracPart.x);
|
||||
|
||||
return mix(top, bottom, fracPart.y);
|
||||
}
|
||||
|
||||
float4 PixelAntialiasing(float2 uvTexspace, constant PushConstants& g_PushConstants)
|
||||
{
|
||||
if ((g_PushConstants.DisplaySize.x * g_PushConstants.InverseDisplaySize.y) >= (4.0 / 3.0))
|
||||
uvTexspace *= g_PushConstants.InverseDisplaySize.y * 720.0;
|
||||
else
|
||||
uvTexspace *= g_PushConstants.InverseDisplaySize.x * 960.0;
|
||||
|
||||
float2 seam = floor(uvTexspace + 0.5);
|
||||
uvTexspace = (uvTexspace - seam) / fwidth(uvTexspace) + seam;
|
||||
uvTexspace = clamp(uvTexspace, seam - 0.5, seam + 0.5);
|
||||
|
||||
return SampleLinear(uvTexspace - 0.5, g_PushConstants);
|
||||
}
|
||||
|
||||
float median(float r, float g, float b)
|
||||
{
|
||||
return max(min(r, g), min(max(r, g), b));
|
||||
}
|
||||
|
||||
float4 SampleSdfFont(float4 color, texture2d<float> texture, float2 uv, float2 screenTexSize,
|
||||
constant SamplerDescriptorHeap& g_SamplerDescriptorHeap,
|
||||
constant PushConstants& g_PushConstants)
|
||||
{
|
||||
float4 textureColor = texture.sample(g_SamplerDescriptorHeap.g[0], uv);
|
||||
|
||||
uint width = texture.get_width();
|
||||
uint height = texture.get_height();
|
||||
|
||||
float pxRange = 8.0;
|
||||
float2 unitRange = pxRange / float2(width, height);
|
||||
float screenPxRange = max(0.5 * dot(unitRange, screenTexSize), 1.0);
|
||||
|
||||
float sd = median(textureColor.r, textureColor.g, textureColor.b) - 0.5;
|
||||
float screenPxDistance = screenPxRange * (sd + g_PushConstants.Outline / (pxRange * 1.5));
|
||||
|
||||
if (g_PushConstants.ShaderModifier == IMGUI_SHADER_MODIFIER_TITLE_BEVEL)
|
||||
{
|
||||
float2 normal = normalize(float3(dfdx(sd), dfdy(sd), 0.01)).xy;
|
||||
float3 rimColor = float3(1, 0.8, 0.29);
|
||||
float3 shadowColor = float3(0.84, 0.57, 0);
|
||||
|
||||
float cosTheta = dot(normal, normalize(float2(1, 1)));
|
||||
float3 gradient = mix(color.rgb, cosTheta >= 0.0 ? rimColor : shadowColor, abs(cosTheta));
|
||||
color.rgb = mix(gradient, color.rgb, pow(saturate(sd + 0.77), 32.0));
|
||||
}
|
||||
else if (g_PushConstants.ShaderModifier == IMGUI_SHADER_MODIFIER_CATEGORY_BEVEL)
|
||||
{
|
||||
float2 normal = normalize(float3(dfdx(sd), dfdy(sd), 0.25)).xy;
|
||||
float cosTheta = dot(normal, normalize(float2(1, 1)));
|
||||
float gradient = 1.0 + cosTheta * 0.5;
|
||||
color.rgb = saturate(color.rgb * gradient);
|
||||
}
|
||||
else if (g_PushConstants.ShaderModifier == IMGUI_SHADER_MODIFIER_TEXT_SKEW)
|
||||
{
|
||||
float2 normal = normalize(float3(dfdx(sd), dfdy(sd), 0.5)).xy;
|
||||
float cosTheta = dot(normal, normalize(float2(1, 1)));
|
||||
float gradient = saturate(1.0 + cosTheta);
|
||||
color.rgb = mix(color.rgb * gradient, color.rgb, pow(saturate(sd + 0.77), 32.0));
|
||||
}
|
||||
|
||||
color.a *= saturate(screenPxDistance + 0.5);
|
||||
color.a *= textureColor.a;
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
[[fragment]]
|
||||
float4 shaderMain(Interpolators interpolators [[stage_in]],
|
||||
constant Texture2DDescriptorHeap& g_Texture2DDescriptorHeap [[buffer(0)]],
|
||||
constant SamplerDescriptorHeap& g_SamplerDescriptorHeap [[buffer(1)]],
|
||||
constant PushConstants& g_PushConstants [[buffer(4)]])
|
||||
{
|
||||
float4 color = interpolators.Color;
|
||||
color *= PixelAntialiasing(interpolators.Position.xy - g_PushConstants.ProceduralOrigin, g_PushConstants);
|
||||
|
||||
if (g_PushConstants.Texture2DDescriptorIndex != 0)
|
||||
{
|
||||
texture2d<float> texture = g_Texture2DDescriptorHeap.g[g_PushConstants.Texture2DDescriptorIndex & 0x7FFFFFFF];
|
||||
|
||||
if ((g_PushConstants.Texture2DDescriptorIndex & 0x80000000) != 0)
|
||||
{
|
||||
if (g_PushConstants.ShaderModifier == IMGUI_SHADER_MODIFIER_LOW_QUALITY_TEXT)
|
||||
{
|
||||
float scale;
|
||||
float invScale;
|
||||
|
||||
if ((g_PushConstants.DisplaySize.x * g_PushConstants.InverseDisplaySize.y) >= (4.0 / 3.0))
|
||||
{
|
||||
scale = g_PushConstants.InverseDisplaySize.y * 720.0;
|
||||
invScale = g_PushConstants.DisplaySize.y / 720.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
scale = g_PushConstants.InverseDisplaySize.x * 960.0;
|
||||
invScale = g_PushConstants.DisplaySize.x / 960.0;
|
||||
}
|
||||
|
||||
float2 lowQualityPosition = (interpolators.Position.xy - 0.5) * scale;
|
||||
float2 fracPart = fract(lowQualityPosition);
|
||||
|
||||
float2 uvStep = fwidth(interpolators.UV) * invScale;
|
||||
float2 lowQualityUV = interpolators.UV - fracPart * uvStep;
|
||||
float2 screenTexSize = 1.0 / uvStep;
|
||||
|
||||
float4 topLeft = SampleSdfFont(color, texture, lowQualityUV + float2(0, 0), screenTexSize, g_SamplerDescriptorHeap, g_PushConstants);
|
||||
float4 topRight = SampleSdfFont(color, texture, lowQualityUV + float2(uvStep.x, 0), screenTexSize, g_SamplerDescriptorHeap, g_PushConstants);
|
||||
float4 bottomLeft = SampleSdfFont(color, texture, lowQualityUV + float2(0, uvStep.y), screenTexSize, g_SamplerDescriptorHeap, g_PushConstants);
|
||||
float4 bottomRight = SampleSdfFont(color, texture, lowQualityUV + uvStep.xy, screenTexSize, g_SamplerDescriptorHeap, g_PushConstants);
|
||||
|
||||
float4 top = mix(topLeft, topRight, fracPart.x);
|
||||
float4 bottom = mix(bottomLeft, bottomRight, fracPart.x);
|
||||
|
||||
color = mix(top, bottom, fracPart.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
color = SampleSdfFont(color, texture, interpolators.UV, 1.0 / fwidth(interpolators.UV), g_SamplerDescriptorHeap, g_PushConstants);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
color *= texture.sample(g_SamplerDescriptorHeap.g[0], interpolators.UV);
|
||||
}
|
||||
}
|
||||
|
||||
if (g_PushConstants.ShaderModifier == IMGUI_SHADER_MODIFIER_HORIZONTAL_MARQUEE_FADE)
|
||||
{
|
||||
float minAlpha = saturate((interpolators.Position.x - g_PushConstants.BoundsMin.x) / g_PushConstants.Scale.x);
|
||||
float maxAlpha = saturate((g_PushConstants.BoundsMax.x - interpolators.Position.x) / g_PushConstants.Scale.y);
|
||||
|
||||
color.a *= minAlpha;
|
||||
color.a *= maxAlpha;
|
||||
}
|
||||
else if (g_PushConstants.ShaderModifier == IMGUI_SHADER_MODIFIER_VERTICAL_MARQUEE_FADE)
|
||||
{
|
||||
float minAlpha = saturate((interpolators.Position.y - g_PushConstants.BoundsMin.y) / g_PushConstants.Scale.x);
|
||||
float maxAlpha = saturate((g_PushConstants.BoundsMax.y - interpolators.Position.y) / g_PushConstants.Scale.y);
|
||||
|
||||
color.a *= minAlpha;
|
||||
color.a *= maxAlpha;
|
||||
}
|
||||
else if (any(g_PushConstants.BoundsMin != g_PushConstants.BoundsMax))
|
||||
{
|
||||
float2 factor = saturate((interpolators.Position.xy - g_PushConstants.BoundsMin) / (g_PushConstants.BoundsMax - g_PushConstants.BoundsMin));
|
||||
|
||||
if (g_PushConstants.ShaderModifier == IMGUI_SHADER_MODIFIER_RECTANGLE_BEVEL)
|
||||
{
|
||||
float bevelSize = 0.9;
|
||||
|
||||
float shadow = saturate((factor.x - bevelSize) / (1.0 - bevelSize));
|
||||
shadow = max(shadow, saturate((factor.y - bevelSize) / (1.0 - bevelSize)));
|
||||
|
||||
float rim = saturate((1.0 - factor.x - bevelSize) / (1.0 - bevelSize));
|
||||
rim = max(rim, saturate((1.0 - factor.y - bevelSize) / (1.0 - bevelSize)));
|
||||
|
||||
float3 rimColor = float3(1, 0.8, 0.29);
|
||||
float3 shadowColor = float3(0.84, 0.57, 0);
|
||||
|
||||
color.rgb = mix(color.rgb, rimColor, smoothstep(0.0, 1.0, rim));
|
||||
color.rgb = mix(color.rgb, shadowColor, smoothstep(0.0, 1.0, shadow));
|
||||
}
|
||||
else
|
||||
{
|
||||
float4 top = mix(DecodeColor(g_PushConstants.GradientTopLeft), DecodeColor(g_PushConstants.GradientTopRight), smoothstep(0.0, 1.0, factor.x));
|
||||
float4 bottom = mix(DecodeColor(g_PushConstants.GradientBottomLeft), DecodeColor(g_PushConstants.GradientBottomRight), smoothstep(0.0, 1.0, factor.x));
|
||||
color *= mix(top, bottom, smoothstep(0.0, 1.0, factor.y));
|
||||
}
|
||||
}
|
||||
|
||||
if (g_PushConstants.ShaderModifier == IMGUI_SHADER_MODIFIER_GRAYSCALE)
|
||||
color.rgb = dot(color.rgb, float3(0.2126, 0.7152, 0.0722));
|
||||
|
||||
return color;
|
||||
}
|
32
UnleashedRecomp/gpu/shader/msl/imgui_vs.metal
Normal file
32
UnleashedRecomp/gpu/shader/msl/imgui_vs.metal
Normal file
|
@ -0,0 +1,32 @@
|
|||
#include "imgui_common.metali"
|
||||
|
||||
struct VertexStageIn
|
||||
{
|
||||
float2 position [[attribute(0)]];
|
||||
float2 uv [[attribute(1)]];
|
||||
float4 color [[attribute(2)]];
|
||||
};
|
||||
|
||||
[[vertex]]
|
||||
Interpolators shaderMain(VertexStageIn input [[stage_in]],
|
||||
constant PushConstants& g_PushConstants [[buffer(4)]])
|
||||
{
|
||||
Interpolators interpolators = Interpolators{};
|
||||
|
||||
if (g_PushConstants.ShaderModifier == IMGUI_SHADER_MODIFIER_TEXT_SKEW)
|
||||
{
|
||||
if (input.position.y < g_PushConstants.Origin.y)
|
||||
input.position.x += g_PushConstants.Scale.x;
|
||||
}
|
||||
else if (g_PushConstants.ShaderModifier != IMGUI_SHADER_MODIFIER_HORIZONTAL_MARQUEE_FADE &&
|
||||
g_PushConstants.ShaderModifier != IMGUI_SHADER_MODIFIER_VERTICAL_MARQUEE_FADE)
|
||||
{
|
||||
input.position.xy = g_PushConstants.Origin + (input.position.xy - g_PushConstants.Origin) * g_PushConstants.Scale;
|
||||
}
|
||||
|
||||
interpolators.Position = float4(input.position.xy * g_PushConstants.InverseDisplaySize * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0);
|
||||
interpolators.UV = input.uv;
|
||||
interpolators.Color = input.color;
|
||||
|
||||
return interpolators;
|
||||
}
|
39
UnleashedRecomp/gpu/shader/msl/movie_common.metali
Normal file
39
UnleashedRecomp/gpu/shader/msl/movie_common.metali
Normal file
|
@ -0,0 +1,39 @@
|
|||
#pragma once
|
||||
|
||||
#include "../../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
|
||||
|
||||
#define fZmin (*(reinterpret_cast<device float*>(g_PushConstants.PixelShaderConstants + 0)))
|
||||
#define fZmax (*(reinterpret_cast<device float*>(g_PushConstants.PixelShaderConstants + 16)))
|
||||
|
||||
#define Tex0_ResourceDescriptorIndex (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 0)))
|
||||
#define Tex1_ResourceDescriptorIndex (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 4)))
|
||||
#define Tex2_ResourceDescriptorIndex (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 8)))
|
||||
#define Tex3_ResourceDescriptorIndex (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 12)))
|
||||
#define Tex4_ResourceDescriptorIndex (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 16)))
|
||||
|
||||
#define Tex0_SamplerDescriptorIndex (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 64)))
|
||||
#define Tex1_SamplerDescriptorIndex (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 68)))
|
||||
#define Tex2_SamplerDescriptorIndex (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 72)))
|
||||
#define Tex3_SamplerDescriptorIndex (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 76)))
|
||||
#define Tex4_SamplerDescriptorIndex (*(reinterpret_cast<device uint*>(g_PushConstants.SharedConstants + 80)))
|
||||
|
||||
#define bCsc (g_Booleans & (1 << (16 + 0)))
|
||||
#define bAmv (g_Booleans & (1 << (16 + 1)))
|
||||
#define bZmv (g_Booleans & (1 << (16 + 2)))
|
||||
|
||||
struct VertexShaderInput
|
||||
{
|
||||
float4 ObjPos [[attribute(0)]];
|
||||
float2 UV [[attribute(4)]];
|
||||
};
|
||||
|
||||
struct Interpolators
|
||||
{
|
||||
float4 ProjPos [[position]];
|
||||
float2 UV;
|
||||
};
|
||||
|
||||
struct PixelShaderOutput
|
||||
{
|
||||
float4 Color [[color(0)]];
|
||||
};
|
104
UnleashedRecomp/gpu/shader/msl/movie_ps.metal
Normal file
104
UnleashedRecomp/gpu/shader/msl/movie_ps.metal
Normal file
|
@ -0,0 +1,104 @@
|
|||
#include "movie_common.metali"
|
||||
|
||||
[[fragment]]
|
||||
PixelShaderOutput shaderMain(Interpolators In [[stage_in]],
|
||||
constant Texture2DDescriptorHeap& g_Texture2DDescriptorHeap [[buffer(0)]],
|
||||
constant SamplerDescriptorHeap& g_SamplerDescriptorHeap [[buffer(3)]],
|
||||
constant PushConstants& g_PushConstants [[buffer(4)]])
|
||||
{
|
||||
texture2d<float> Tex0 = g_Texture2DDescriptorHeap.g[Tex0_ResourceDescriptorIndex];
|
||||
texture2d<float> Tex1 = g_Texture2DDescriptorHeap.g[Tex1_ResourceDescriptorIndex];
|
||||
texture2d<float> Tex2 = g_Texture2DDescriptorHeap.g[Tex2_ResourceDescriptorIndex];
|
||||
texture2d<float> Tex3 = g_Texture2DDescriptorHeap.g[Tex3_ResourceDescriptorIndex];
|
||||
texture2d<float> Tex4 = g_Texture2DDescriptorHeap.g[Tex4_ResourceDescriptorIndex];
|
||||
|
||||
sampler Tex0_s = g_SamplerDescriptorHeap.g[Tex0_SamplerDescriptorIndex];
|
||||
sampler Tex1_s = g_SamplerDescriptorHeap.g[Tex1_SamplerDescriptorIndex];
|
||||
sampler Tex2_s = g_SamplerDescriptorHeap.g[Tex2_SamplerDescriptorIndex];
|
||||
sampler Tex3_s = g_SamplerDescriptorHeap.g[Tex3_SamplerDescriptorIndex];
|
||||
sampler Tex4_s = g_SamplerDescriptorHeap.g[Tex4_SamplerDescriptorIndex];
|
||||
|
||||
PixelShaderOutput Out;
|
||||
float ValY = Tex0.sample(Tex0_s, In.UV).r;
|
||||
float ValU = Tex1.sample(Tex1_s, In.UV).r - 0.5;
|
||||
float ValV = Tex2.sample(Tex2_s, In.UV).r - 0.5;
|
||||
float ValA = 1.0;
|
||||
float ValD = 0.0;
|
||||
if (bAmv)
|
||||
ValA = (Tex3.sample(Tex3_s, In.UV).r - 0.0625) * 1.164;
|
||||
if (bZmv)
|
||||
{
|
||||
ValD = (Tex4.sample(Tex4_s, In.UV).r - 0.0625) * 1.164;
|
||||
if (ValD < 9.0 / 255.0)
|
||||
{
|
||||
ValD = 0.0;
|
||||
}
|
||||
else if (ValD < 17.0 / 255.0)
|
||||
{
|
||||
ValD = fZmin;
|
||||
}
|
||||
else if (ValD < 224.0 / 255.0)
|
||||
{
|
||||
ValD = (ValD - 17.0 / 255.0) / (223.0 / 255.0 - 17.0 / 255.0) * (fZmax - fZmin) + fZmin;
|
||||
}
|
||||
else if (ValD < 240.0 / 255.0)
|
||||
{
|
||||
ValD = fZmax;
|
||||
}
|
||||
else
|
||||
{
|
||||
ValD = 1.0;
|
||||
}
|
||||
}
|
||||
if (bCsc)
|
||||
{
|
||||
if (ValY < 16.0 / 255.0)
|
||||
{
|
||||
ValY = ValY * 3.0 / 2.0;
|
||||
}
|
||||
else if (ValY < 176.0 / 255.0)
|
||||
{
|
||||
ValY = 24.0 / 255.0 + (ValY - 16.0 / 255.0) / 2.0;
|
||||
}
|
||||
else if (ValY < 192.0 / 255.0)
|
||||
{
|
||||
ValY = 104.0 / 255.0 + (ValY - 176.0 / 255.0) / 1.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ValY = 120.0 / 255.0 + (ValY - 192.0 / 255.0) * 2.0;
|
||||
}
|
||||
if (abs(ValU) < 24.0 / 255.0)
|
||||
{
|
||||
ValU /= 3.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ValU = (8.0 / 255.0 + (abs(ValU) - 24.0 / 255.0) * (120.0 / 104.0)) * sign(ValU);
|
||||
}
|
||||
if (abs(ValV) < 24.0 / 255.0)
|
||||
{
|
||||
ValV /= 3.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ValV = (8.0 / 255.0 + (abs(ValV) - 24.0 / 255.0) * (120.0 / 104.0)) * sign(ValV);
|
||||
}
|
||||
Out.Color.r = ValY + ValV * 1.402;
|
||||
Out.Color.g = ValY - ValU * 0.344 - ValV * 0.714;
|
||||
Out.Color.b = ValY + ValU * 1.772;
|
||||
}
|
||||
else
|
||||
{
|
||||
ValY = (ValY - 0.0625) * 1.164;
|
||||
Out.Color.r = ValY + ValV * 1.596;
|
||||
Out.Color.g = ValY - ValU * 0.392 - ValV * 0.813;
|
||||
Out.Color.b = ValY + ValU * 2.017;
|
||||
}
|
||||
Out.Color.a = ValA;
|
||||
|
||||
if (any(In.UV < 0.0) || any(In.UV > 1.0))
|
||||
Out.Color.rgb = 0.0;
|
||||
|
||||
return Out;
|
||||
}
|
10
UnleashedRecomp/gpu/shader/msl/movie_vs.metal
Normal file
10
UnleashedRecomp/gpu/shader/msl/movie_vs.metal
Normal file
|
@ -0,0 +1,10 @@
|
|||
#include "movie_common.metali"
|
||||
|
||||
[[vertex]]
|
||||
Interpolators shaderMain(VertexShaderInput In [[stage_in]])
|
||||
{
|
||||
Interpolators Out;
|
||||
Out.ProjPos = In.ObjPos;
|
||||
Out.UV = In.UV;
|
||||
return Out;
|
||||
}
|
21
UnleashedRecomp/gpu/shader/msl/resolve_msaa_color.metali
Normal file
21
UnleashedRecomp/gpu/shader/msl/resolve_msaa_color.metali
Normal file
|
@ -0,0 +1,21 @@
|
|||
#pragma once
|
||||
|
||||
#include "copy_common.metali"
|
||||
|
||||
struct Texture2DMSDescriptorHeap
|
||||
{
|
||||
array<texture2d_ms<float>, 1> g [[id(0)]];
|
||||
};
|
||||
|
||||
[[fragment]]
|
||||
float4 shaderMain(float4 position [[position]],
|
||||
constant Texture2DMSDescriptorHeap& g_Texture2DMSDescriptorHeap [[buffer(0)]],
|
||||
constant PushConstants& g_PushConstants [[buffer(4)]])
|
||||
{
|
||||
float4 result = g_Texture2DMSDescriptorHeap.g[g_PushConstants.ResourceDescriptorIndex].read(uint2(position.xy), 0);
|
||||
|
||||
for (int i = 1; i < SAMPLE_COUNT; i++)
|
||||
result += g_Texture2DMSDescriptorHeap.g[g_PushConstants.ResourceDescriptorIndex].read(uint2(position.xy), i);
|
||||
|
||||
return result / SAMPLE_COUNT;
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
#define SAMPLE_COUNT 2
|
||||
#include "resolve_msaa_color.metali"
|
|
@ -0,0 +1,2 @@
|
|||
#define SAMPLE_COUNT 4
|
||||
#include "resolve_msaa_color.metali"
|
|
@ -0,0 +1,2 @@
|
|||
#define SAMPLE_COUNT 8
|
||||
#include "resolve_msaa_color.metali"
|
30
UnleashedRecomp/gpu/shader/msl/resolve_msaa_depth.metali
Normal file
30
UnleashedRecomp/gpu/shader/msl/resolve_msaa_depth.metali
Normal file
|
@ -0,0 +1,30 @@
|
|||
#pragma once
|
||||
|
||||
#include "copy_common.metali"
|
||||
|
||||
struct Texture2DMSDescriptorHeap
|
||||
{
|
||||
array<texture2d_ms<float>, 1> g [[id(0)]];
|
||||
};
|
||||
|
||||
struct PixelShaderOutput
|
||||
{
|
||||
float oDepth [[depth(any)]];
|
||||
};
|
||||
|
||||
[[fragment]]
|
||||
PixelShaderOutput shaderMain(float4 position [[position]],
|
||||
constant Texture2DMSDescriptorHeap& g_Texture2DMSDescriptorHeap [[buffer(0)]],
|
||||
constant PushConstants& g_PushConstants [[buffer(4)]])
|
||||
{
|
||||
PixelShaderOutput output = PixelShaderOutput{};
|
||||
|
||||
float result = g_Texture2DMSDescriptorHeap.g[g_PushConstants.ResourceDescriptorIndex].read(uint2(position.xy), 0).x;
|
||||
|
||||
for (int i = 1; i < SAMPLE_COUNT; i++)
|
||||
result = min(result, g_Texture2DMSDescriptorHeap.g[g_PushConstants.ResourceDescriptorIndex].read(uint2(position.xy), i).x);
|
||||
|
||||
output.oDepth = result;
|
||||
|
||||
return output;
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
#define SAMPLE_COUNT 2
|
||||
#include "resolve_msaa_depth.metali"
|
|
@ -0,0 +1,2 @@
|
|||
#define SAMPLE_COUNT 4
|
||||
#include "resolve_msaa_depth.metali"
|
|
@ -0,0 +1,2 @@
|
|||
#define SAMPLE_COUNT 8
|
||||
#include "resolve_msaa_depth.metali"
|
|
@ -37,57 +37,84 @@
|
|||
#include <magic_enum/magic_enum.hpp>
|
||||
#endif
|
||||
|
||||
#define UNLEASHED_RECOMP
|
||||
#include "../../tools/XenosRecomp/XenosRecomp/shader_common.h"
|
||||
|
||||
#ifdef UNLEASHED_RECOMP_D3D12
|
||||
#include "shader/blend_color_alpha_ps.hlsl.dxil.h"
|
||||
#include "shader/copy_vs.hlsl.dxil.h"
|
||||
#include "shader/copy_color_ps.hlsl.dxil.h"
|
||||
#include "shader/copy_depth_ps.hlsl.dxil.h"
|
||||
#include "shader/csd_filter_ps.hlsl.dxil.h"
|
||||
#include "shader/csd_no_tex_vs.hlsl.dxil.h"
|
||||
#include "shader/csd_vs.hlsl.dxil.h"
|
||||
#include "shader/enhanced_motion_blur_ps.hlsl.dxil.h"
|
||||
#include "shader/gamma_correction_ps.hlsl.dxil.h"
|
||||
#include "shader/gaussian_blur_3x3.hlsl.dxil.h"
|
||||
#include "shader/gaussian_blur_5x5.hlsl.dxil.h"
|
||||
#include "shader/gaussian_blur_7x7.hlsl.dxil.h"
|
||||
#include "shader/gaussian_blur_9x9.hlsl.dxil.h"
|
||||
#include "shader/imgui_ps.hlsl.dxil.h"
|
||||
#include "shader/imgui_vs.hlsl.dxil.h"
|
||||
#include "shader/movie_ps.hlsl.dxil.h"
|
||||
#include "shader/movie_vs.hlsl.dxil.h"
|
||||
#include "shader/resolve_msaa_color_2x.hlsl.dxil.h"
|
||||
#include "shader/resolve_msaa_color_4x.hlsl.dxil.h"
|
||||
#include "shader/resolve_msaa_color_8x.hlsl.dxil.h"
|
||||
#include "shader/resolve_msaa_depth_2x.hlsl.dxil.h"
|
||||
#include "shader/resolve_msaa_depth_4x.hlsl.dxil.h"
|
||||
#include "shader/resolve_msaa_depth_8x.hlsl.dxil.h"
|
||||
#include "shader/hlsl/blend_color_alpha_ps.hlsl.dxil.h"
|
||||
#include "shader/hlsl/copy_vs.hlsl.dxil.h"
|
||||
#include "shader/hlsl/copy_color_ps.hlsl.dxil.h"
|
||||
#include "shader/hlsl/copy_depth_ps.hlsl.dxil.h"
|
||||
#include "shader/hlsl/csd_filter_ps.hlsl.dxil.h"
|
||||
#include "shader/hlsl/csd_no_tex_vs.hlsl.dxil.h"
|
||||
#include "shader/hlsl/csd_vs.hlsl.dxil.h"
|
||||
#include "shader/hlsl/enhanced_motion_blur_ps.hlsl.dxil.h"
|
||||
#include "shader/hlsl/gamma_correction_ps.hlsl.dxil.h"
|
||||
#include "shader/hlsl/gaussian_blur_3x3.hlsl.dxil.h"
|
||||
#include "shader/hlsl/gaussian_blur_5x5.hlsl.dxil.h"
|
||||
#include "shader/hlsl/gaussian_blur_7x7.hlsl.dxil.h"
|
||||
#include "shader/hlsl/gaussian_blur_9x9.hlsl.dxil.h"
|
||||
#include "shader/hlsl/imgui_ps.hlsl.dxil.h"
|
||||
#include "shader/hlsl/imgui_vs.hlsl.dxil.h"
|
||||
#include "shader/hlsl/movie_ps.hlsl.dxil.h"
|
||||
#include "shader/hlsl/movie_vs.hlsl.dxil.h"
|
||||
#include "shader/hlsl/resolve_msaa_color_2x.hlsl.dxil.h"
|
||||
#include "shader/hlsl/resolve_msaa_color_4x.hlsl.dxil.h"
|
||||
#include "shader/hlsl/resolve_msaa_color_8x.hlsl.dxil.h"
|
||||
#include "shader/hlsl/resolve_msaa_depth_2x.hlsl.dxil.h"
|
||||
#include "shader/hlsl/resolve_msaa_depth_4x.hlsl.dxil.h"
|
||||
#include "shader/hlsl/resolve_msaa_depth_8x.hlsl.dxil.h"
|
||||
#endif
|
||||
|
||||
#include "shader/blend_color_alpha_ps.hlsl.spirv.h"
|
||||
#include "shader/copy_vs.hlsl.spirv.h"
|
||||
#include "shader/copy_color_ps.hlsl.spirv.h"
|
||||
#include "shader/copy_depth_ps.hlsl.spirv.h"
|
||||
#include "shader/csd_filter_ps.hlsl.spirv.h"
|
||||
#include "shader/csd_no_tex_vs.hlsl.spirv.h"
|
||||
#include "shader/csd_vs.hlsl.spirv.h"
|
||||
#include "shader/enhanced_motion_blur_ps.hlsl.spirv.h"
|
||||
#include "shader/gamma_correction_ps.hlsl.spirv.h"
|
||||
#include "shader/gaussian_blur_3x3.hlsl.spirv.h"
|
||||
#include "shader/gaussian_blur_5x5.hlsl.spirv.h"
|
||||
#include "shader/gaussian_blur_7x7.hlsl.spirv.h"
|
||||
#include "shader/gaussian_blur_9x9.hlsl.spirv.h"
|
||||
#include "shader/imgui_ps.hlsl.spirv.h"
|
||||
#include "shader/imgui_vs.hlsl.spirv.h"
|
||||
#include "shader/movie_ps.hlsl.spirv.h"
|
||||
#include "shader/movie_vs.hlsl.spirv.h"
|
||||
#include "shader/resolve_msaa_color_2x.hlsl.spirv.h"
|
||||
#include "shader/resolve_msaa_color_4x.hlsl.spirv.h"
|
||||
#include "shader/resolve_msaa_color_8x.hlsl.spirv.h"
|
||||
#include "shader/resolve_msaa_depth_2x.hlsl.spirv.h"
|
||||
#include "shader/resolve_msaa_depth_4x.hlsl.spirv.h"
|
||||
#include "shader/resolve_msaa_depth_8x.hlsl.spirv.h"
|
||||
#ifdef UNLEASHED_RECOMP_METAL
|
||||
#include "shader/msl/blend_color_alpha_ps.metal.metallib.h"
|
||||
#include "shader/msl/copy_vs.metal.metallib.h"
|
||||
#include "shader/msl/copy_color_ps.metal.metallib.h"
|
||||
#include "shader/msl/copy_depth_ps.metal.metallib.h"
|
||||
#include "shader/msl/csd_filter_ps.metal.metallib.h"
|
||||
#include "shader/msl/csd_no_tex_vs.metal.metallib.h"
|
||||
#include "shader/msl/csd_vs.metal.metallib.h"
|
||||
#include "shader/msl/enhanced_motion_blur_ps.metal.metallib.h"
|
||||
#include "shader/msl/gamma_correction_ps.metal.metallib.h"
|
||||
#include "shader/msl/gaussian_blur_3x3.metal.metallib.h"
|
||||
#include "shader/msl/gaussian_blur_5x5.metal.metallib.h"
|
||||
#include "shader/msl/gaussian_blur_7x7.metal.metallib.h"
|
||||
#include "shader/msl/gaussian_blur_9x9.metal.metallib.h"
|
||||
#include "shader/msl/imgui_ps.metal.metallib.h"
|
||||
#include "shader/msl/imgui_vs.metal.metallib.h"
|
||||
#include "shader/msl/movie_ps.metal.metallib.h"
|
||||
#include "shader/msl/movie_vs.metal.metallib.h"
|
||||
#include "shader/msl/resolve_msaa_color_2x.metal.metallib.h"
|
||||
#include "shader/msl/resolve_msaa_color_4x.metal.metallib.h"
|
||||
#include "shader/msl/resolve_msaa_color_8x.metal.metallib.h"
|
||||
#include "shader/msl/resolve_msaa_depth_2x.metal.metallib.h"
|
||||
#include "shader/msl/resolve_msaa_depth_4x.metal.metallib.h"
|
||||
#include "shader/msl/resolve_msaa_depth_8x.metal.metallib.h"
|
||||
#endif
|
||||
|
||||
#include "shader/hlsl/blend_color_alpha_ps.hlsl.spirv.h"
|
||||
#include "shader/hlsl/copy_vs.hlsl.spirv.h"
|
||||
#include "shader/hlsl/copy_color_ps.hlsl.spirv.h"
|
||||
#include "shader/hlsl/copy_depth_ps.hlsl.spirv.h"
|
||||
#include "shader/hlsl/csd_filter_ps.hlsl.spirv.h"
|
||||
#include "shader/hlsl/csd_no_tex_vs.hlsl.spirv.h"
|
||||
#include "shader/hlsl/csd_vs.hlsl.spirv.h"
|
||||
#include "shader/hlsl/enhanced_motion_blur_ps.hlsl.spirv.h"
|
||||
#include "shader/hlsl/gamma_correction_ps.hlsl.spirv.h"
|
||||
#include "shader/hlsl/gaussian_blur_3x3.hlsl.spirv.h"
|
||||
#include "shader/hlsl/gaussian_blur_5x5.hlsl.spirv.h"
|
||||
#include "shader/hlsl/gaussian_blur_7x7.hlsl.spirv.h"
|
||||
#include "shader/hlsl/gaussian_blur_9x9.hlsl.spirv.h"
|
||||
#include "shader/hlsl/imgui_ps.hlsl.spirv.h"
|
||||
#include "shader/hlsl/imgui_vs.hlsl.spirv.h"
|
||||
#include "shader/hlsl/movie_ps.hlsl.spirv.h"
|
||||
#include "shader/hlsl/movie_vs.hlsl.spirv.h"
|
||||
#include "shader/hlsl/resolve_msaa_color_2x.hlsl.spirv.h"
|
||||
#include "shader/hlsl/resolve_msaa_color_4x.hlsl.spirv.h"
|
||||
#include "shader/hlsl/resolve_msaa_color_8x.hlsl.spirv.h"
|
||||
#include "shader/hlsl/resolve_msaa_depth_2x.hlsl.spirv.h"
|
||||
#include "shader/hlsl/resolve_msaa_depth_4x.hlsl.spirv.h"
|
||||
#include "shader/hlsl/resolve_msaa_depth_8x.hlsl.spirv.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
extern "C"
|
||||
|
@ -102,6 +129,9 @@ namespace plume
|
|||
#ifdef UNLEASHED_RECOMP_D3D12
|
||||
extern std::unique_ptr<RenderInterface> CreateD3D12Interface();
|
||||
#endif
|
||||
#ifdef UNLEASHED_RECOMP_METAL
|
||||
extern std::unique_ptr<RenderInterface> CreateMetalInterface();
|
||||
#endif
|
||||
#ifdef SDL_VULKAN_ENABLED
|
||||
extern std::unique_ptr<RenderInterface> CreateVulkanInterface(RenderWindow sdlWindow);
|
||||
#else
|
||||
|
@ -282,17 +312,14 @@ static Profiler g_swapChainAcquireProfiler;
|
|||
static bool g_profilerVisible;
|
||||
static bool g_profilerWasToggled;
|
||||
|
||||
#ifdef UNLEASHED_RECOMP_D3D12
|
||||
static bool g_vulkan = false;
|
||||
#if !defined(UNLEASHED_RECOMP_D3D12) && !defined(UNLEASHED_RECOMP_METAL)
|
||||
static constexpr Backend g_backend = Backend::VULKAN;
|
||||
#else
|
||||
static constexpr bool g_vulkan = true;
|
||||
static Backend g_backend;
|
||||
#endif
|
||||
|
||||
static bool g_triangleStripWorkaround = false;
|
||||
|
||||
static bool g_hardwareResolve = true;
|
||||
static bool g_hardwareDepthResolve = true;
|
||||
|
||||
static std::unique_ptr<RenderInterface> g_interface;
|
||||
static std::unique_ptr<RenderDevice> g_device;
|
||||
|
||||
|
@ -779,18 +806,27 @@ static std::unique_ptr<uint8_t[]> g_buttonBcDiff;
|
|||
|
||||
static void LoadEmbeddedResources()
|
||||
{
|
||||
if (g_vulkan)
|
||||
switch (g_backend)
|
||||
{
|
||||
case Backend::VULKAN:
|
||||
g_shaderCache = std::make_unique<uint8_t[]>(g_spirvCacheDecompressedSize);
|
||||
ZSTD_decompress(g_shaderCache.get(), g_spirvCacheDecompressedSize, g_compressedSpirvCache, g_spirvCacheCompressedSize);
|
||||
}
|
||||
#ifdef UNLEASHED_RECOMP_D3D12
|
||||
else
|
||||
{
|
||||
g_shaderCache = std::make_unique<uint8_t[]>(g_dxilCacheDecompressedSize);
|
||||
ZSTD_decompress(g_shaderCache.get(), g_dxilCacheDecompressedSize, g_compressedDxilCache, g_dxilCacheCompressedSize);
|
||||
}
|
||||
break;
|
||||
#ifdef UNLEASHED_RECOM_D3D12
|
||||
case Backend::D3D12:
|
||||
g_shaderCache = std::make_unique<uint8_t[]>(g_dxilCacheDecompressedSize);
|
||||
ZSTD_decompress(g_shaderCache.get(), g_dxilCacheDecompressedSize, g_compressedDxilCache, g_dxilCacheCompressedSize);
|
||||
break;
|
||||
#endif
|
||||
#ifdef UNLEASHED_RECOMP_METAL
|
||||
case Backend::METAL:
|
||||
g_shaderCache = std::make_unique<uint8_t[]>(g_airCacheDecompressedSize);
|
||||
ZSTD_decompress(g_shaderCache.get(), g_airCacheDecompressedSize, g_compressedAirCache, g_airCacheCompressedSize);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
#endif
|
||||
}
|
||||
|
||||
g_buttonBcDiff = decompressZstd(g_button_bc_diff, g_button_bc_diff_uncompressed_size);
|
||||
}
|
||||
|
@ -1297,10 +1333,19 @@ static std::unique_ptr<GuestShader> g_enhancedMotionBlurShader;
|
|||
|
||||
#define CREATE_SHADER(NAME) \
|
||||
g_device->createShader( \
|
||||
g_vulkan ? g_##NAME##_spirv : g_##NAME##_dxil, \
|
||||
g_vulkan ? sizeof(g_##NAME##_spirv) : sizeof(g_##NAME##_dxil), \
|
||||
(g_backend == Backend::VULKAN) ? g_##NAME##_spirv : g_##NAME##_dxil, \
|
||||
(g_backend == Backend::VULKAN) ? sizeof(g_##NAME##_spirv) : sizeof(g_##NAME##_dxil), \
|
||||
"main", \
|
||||
g_vulkan ? RenderShaderFormat::SPIRV : RenderShaderFormat::DXIL)
|
||||
(g_backend == Backend::VULKAN) ? RenderShaderFormat::SPIRV : RenderShaderFormat::DXIL)
|
||||
|
||||
#elif UNLEASHED_RECOMP_METAL
|
||||
|
||||
#define CREATE_SHADER(NAME) \
|
||||
g_device->createShader( \
|
||||
(g_backend == Backend::VULKAN) ? g_##NAME##_spirv : g_##NAME##_air, \
|
||||
(g_backend == Backend::VULKAN) ? sizeof(g_##NAME##_spirv) : sizeof(g_##NAME##_air), \
|
||||
(g_backend == Backend::VULKAN) ? "main" : "shaderMain", \
|
||||
(g_backend == Backend::VULKAN) ? RenderShaderFormat::SPIRV : RenderShaderFormat::METAL)
|
||||
|
||||
#else
|
||||
|
||||
|
@ -1671,7 +1716,12 @@ bool Video::CreateHostDevice(const char *sdlVideoDriver, bool graphicsApiRetry)
|
|||
GameWindow::Init(sdlVideoDriver);
|
||||
|
||||
#ifdef UNLEASHED_RECOMP_D3D12
|
||||
g_vulkan = DetectWine() || Config::GraphicsAPI == EGraphicsAPI::Vulkan;
|
||||
g_backend = (DetectWine() || Config::GraphicsAPI == EGraphicsAPI::Vulkan) ? Backend::VULKAN : Backend::D3D12;
|
||||
#endif
|
||||
|
||||
#ifdef UNLEASHED_RECOMP_METAL
|
||||
// TODO: Set this based on a config value and change default to Metal
|
||||
g_backend = Backend::METAL;
|
||||
#endif
|
||||
|
||||
// Attempt to create the possible backends using a vector of function pointers. Whichever succeeds first will be the chosen API.
|
||||
|
@ -1682,11 +1732,21 @@ bool Video::CreateHostDevice(const char *sdlVideoDriver, bool graphicsApiRetry)
|
|||
if (graphicsApiRetry)
|
||||
{
|
||||
// If we are attempting to create again after a reboot due to a crash, swap the order.
|
||||
g_vulkan = !g_vulkan;
|
||||
if (g_backend == Backend::VULKAN)
|
||||
{
|
||||
g_backend = Backend::D3D12;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_backend = Backend::VULKAN;
|
||||
}
|
||||
}
|
||||
|
||||
interfaceFunctions.push_back(g_vulkan ? CreateVulkanInterfaceWrapper : CreateD3D12Interface);
|
||||
interfaceFunctions.push_back(g_vulkan ? CreateD3D12Interface : CreateVulkanInterfaceWrapper);
|
||||
|
||||
interfaceFunctions.push_back((g_backend == Backend::VULKAN) ? CreateVulkanInterfaceWrapper : CreateD3D12Interface);
|
||||
interfaceFunctions.push_back((g_backend == Backend::VULKAN) ? CreateD3D12Interface : CreateVulkanInterfaceWrapper);
|
||||
#elif UNLEASHED_RECOMP_METAL
|
||||
interfaceFunctions.push_back((g_backend == Backend::VULKAN) ? CreateVulkanInterfaceWrapper : CreateMetalInterface);
|
||||
interfaceFunctions.push_back((g_backend == Backend::VULKAN) ? CreateMetalInterface : CreateVulkanInterfaceWrapper);
|
||||
#else
|
||||
interfaceFunctions.push_back(CreateVulkanInterfaceWrapper);
|
||||
#endif
|
||||
|
@ -1698,9 +1758,9 @@ bool Video::CreateHostDevice(const char *sdlVideoDriver, bool graphicsApiRetry)
|
|||
__try
|
||||
#endif
|
||||
{
|
||||
g_interface = interfaceFunction();
|
||||
g_interface = interfaceFunction();
|
||||
if (g_interface == nullptr)
|
||||
{
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1734,11 +1794,11 @@ bool Video::CreateHostDevice(const char *sdlVideoDriver, bool graphicsApiRetry)
|
|||
// Allow redirection to Vulkan only if we are not retrying after a crash,
|
||||
// so the user can at least boot the game with D3D12 if Vulkan fails to work.
|
||||
if (!graphicsApiRetry && redirectToVulkan)
|
||||
{
|
||||
g_device.reset();
|
||||
g_interface.reset();
|
||||
continue;
|
||||
}
|
||||
{
|
||||
g_device.reset();
|
||||
g_interface.reset();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Hardware resolve seems to be completely bugged on Intel D3D12 drivers.
|
||||
g_hardwareResolve = (deviceDescription.vendor != RenderDeviceVendor::INTEL);
|
||||
|
@ -1781,7 +1841,7 @@ bool Video::CreateHostDevice(const char *sdlVideoDriver, bool graphicsApiRetry)
|
|||
if (graphicsApiRetry)
|
||||
{
|
||||
// If we managed to create a device after retrying it in a reboot, remember the one we picked.
|
||||
Config::GraphicsAPI = g_vulkan ? EGraphicsAPI::Vulkan : EGraphicsAPI::D3D12;
|
||||
Config::GraphicsAPI = (g_backend == Backend::VULKAN) ? EGraphicsAPI::Vulkan : EGraphicsAPI::D3D12;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1819,7 +1879,7 @@ bool Video::CreateHostDevice(const char *sdlVideoDriver, bool graphicsApiRetry)
|
|||
g_queue = g_device->createCommandQueue(RenderCommandListType::DIRECT);
|
||||
|
||||
for (auto& commandList : g_commandLists)
|
||||
commandList = g_device->createCommandList(RenderCommandListType::DIRECT);
|
||||
commandList = g_queue->createCommandList();
|
||||
|
||||
for (auto& commandFence : g_commandFences)
|
||||
commandFence = g_device->createCommandFence();
|
||||
|
@ -1828,7 +1888,7 @@ bool Video::CreateHostDevice(const char *sdlVideoDriver, bool graphicsApiRetry)
|
|||
queryPool = g_device->createQueryPool(NUM_QUERIES);
|
||||
|
||||
g_copyQueue = g_device->createCommandQueue(RenderCommandListType::COPY);
|
||||
g_copyCommandList = g_device->createCommandList(RenderCommandListType::COPY);
|
||||
g_copyCommandList = g_copyQueue->createCommandList();
|
||||
g_copyCommandFence = g_device->createCommandFence();
|
||||
|
||||
uint32_t bufferCount = 2;
|
||||
|
@ -1836,17 +1896,19 @@ bool Video::CreateHostDevice(const char *sdlVideoDriver, bool graphicsApiRetry)
|
|||
switch (Config::TripleBuffering)
|
||||
{
|
||||
case ETripleBuffering::Auto:
|
||||
if (g_vulkan)
|
||||
{
|
||||
switch (g_backend) {
|
||||
case Backend::VULKAN:
|
||||
// Defaulting to 3 is fine if presentWait as supported, as the maximum frame latency allowed is only 1.
|
||||
bufferCount = g_device->getCapabilities().presentWait ? 3 : 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
case Backend::D3D12:
|
||||
// Defaulting to 3 is fine on D3D12 thanks to flip discard model.
|
||||
bufferCount = 3;
|
||||
break;
|
||||
case Backend::METAL:
|
||||
bufferCount = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
case ETripleBuffering::On:
|
||||
bufferCount = 3;
|
||||
|
@ -1941,7 +2003,7 @@ bool Video::CreateHostDevice(const char *sdlVideoDriver, bool graphicsApiRetry)
|
|||
|
||||
pipelineLayoutBuilder.addDescriptorSet(descriptorSetBuilder);
|
||||
|
||||
if (g_vulkan)
|
||||
if (g_backend != Backend::D3D12)
|
||||
{
|
||||
pipelineLayoutBuilder.addPushConstant(0, 4, 24, RenderShaderStageFlag::VERTEX | RenderShaderStageFlag::PIXEL);
|
||||
}
|
||||
|
@ -2056,12 +2118,7 @@ void Video::WaitForGPU()
|
|||
{
|
||||
g_waitForGPUCount++;
|
||||
|
||||
if (g_vulkan)
|
||||
{
|
||||
g_device->waitIdle();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Wait for all queued frames to finish.
|
||||
for (size_t i = 0; i < NUM_FRAMES; i++)
|
||||
{
|
||||
if (g_commandListStates[i])
|
||||
|
@ -2070,9 +2127,11 @@ void Video::WaitForGPU()
|
|||
g_commandListStates[i] = false;
|
||||
}
|
||||
}
|
||||
g_queue->executeCommandLists(nullptr, g_commandFences[0].get());
|
||||
// Execute an empty command list and wait for it to end to guarantee that any remaining presentation has finished.
|
||||
g_commandLists[0]->begin();
|
||||
g_commandLists[0]->end();
|
||||
g_queue->executeCommandLists(g_commandLists[0].get(), g_commandFences[0].get());
|
||||
g_queue->waitForCommandFence(g_commandFences[0].get());
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t CreateDevice(uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5, be<uint32_t>* a6)
|
||||
|
@ -2210,14 +2269,14 @@ static void UnlockBuffer(GuestBuffer* buffer, bool useCopyQueue)
|
|||
{
|
||||
auto copyBuffer = [&](T* dest)
|
||||
{
|
||||
auto src = reinterpret_cast<const T*>(buffer->mappedMemory);
|
||||
auto src = reinterpret_cast<const T*>(buffer->mappedMemory);
|
||||
|
||||
for (size_t i = 0; i < buffer->dataSize; i += sizeof(T))
|
||||
{
|
||||
*dest = ByteSwap(*src);
|
||||
++dest;
|
||||
++src;
|
||||
}
|
||||
for (size_t i = 0; i < buffer->dataSize; i += sizeof(T))
|
||||
{
|
||||
*dest = ByteSwap(*src);
|
||||
++dest;
|
||||
++src;
|
||||
}
|
||||
};
|
||||
|
||||
if (useCopyQueue && g_capabilities.gpuUploadHeap)
|
||||
|
@ -2229,25 +2288,25 @@ static void UnlockBuffer(GuestBuffer* buffer, bool useCopyQueue)
|
|||
{
|
||||
auto uploadBuffer = g_device->createBuffer(RenderBufferDesc::UploadBuffer(buffer->dataSize));
|
||||
copyBuffer(reinterpret_cast<T*>(uploadBuffer->map()));
|
||||
uploadBuffer->unmap();
|
||||
uploadBuffer->unmap();
|
||||
|
||||
if (useCopyQueue)
|
||||
{
|
||||
ExecuteCopyCommandList([&]
|
||||
{
|
||||
g_copyCommandList->copyBufferRegion(buffer->buffer->at(0), uploadBuffer->at(0), buffer->dataSize);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
auto& commandList = g_commandLists[g_frame];
|
||||
if (useCopyQueue)
|
||||
{
|
||||
ExecuteCopyCommandList([&]
|
||||
{
|
||||
g_copyCommandList->copyBufferRegion(buffer->buffer->at(0), uploadBuffer->at(0), buffer->dataSize);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
auto& commandList = g_commandLists[g_frame];
|
||||
|
||||
commandList->barriers(RenderBarrierStage::COPY, RenderBufferBarrier(buffer->buffer.get(), RenderBufferAccess::WRITE));
|
||||
commandList->copyBufferRegion(buffer->buffer->at(0), uploadBuffer->at(0), buffer->dataSize);
|
||||
commandList->barriers(RenderBarrierStage::GRAPHICS, RenderBufferBarrier(buffer->buffer.get(), RenderBufferAccess::READ));
|
||||
commandList->barriers(RenderBarrierStage::COPY, RenderBufferBarrier(buffer->buffer.get(), RenderBufferAccess::WRITE));
|
||||
commandList->copyBufferRegion(buffer->buffer->at(0), uploadBuffer->at(0), buffer->dataSize);
|
||||
commandList->barriers(RenderBarrierStage::GRAPHICS, RenderBufferBarrier(buffer->buffer.get(), RenderBufferAccess::READ));
|
||||
|
||||
g_tempBuffers[g_frame].emplace_back(std::move(uploadBuffer));
|
||||
}
|
||||
g_tempBuffers[g_frame].emplace_back(std::move(uploadBuffer));
|
||||
}
|
||||
}
|
||||
|
||||
g_bufferUploadCount++;
|
||||
|
@ -2438,12 +2497,25 @@ static void DrawProfiler()
|
|||
ImGui::Text("Present Wait: %s", g_capabilities.presentWait ? "Supported" : "Unsupported");
|
||||
ImGui::Text("Triangle Fan: %s", g_capabilities.triangleFan ? "Supported" : "Unsupported");
|
||||
ImGui::Text("Dynamic Depth Bias: %s", g_capabilities.dynamicDepthBias ? "Supported" : "Unsupported");
|
||||
ImGui::Text("Hardware Resolve Modes: %s", g_capabilities.resolveModes ? "Supported" : "Unsupported");
|
||||
ImGui::Text("Triangle Strip Workaround: %s", g_triangleStripWorkaround ? "Enabled" : "Disabled");
|
||||
ImGui::Text("Hardware Resolve: %s", g_hardwareResolve ? "Enabled" : "Disabled");
|
||||
ImGui::Text("Hardware Depth Resolve: %s", g_hardwareDepthResolve ? "Enabled" : "Disabled");
|
||||
ImGui::NewLine();
|
||||
|
||||
ImGui::Text("API: %s", g_vulkan ? "Vulkan" : "D3D12");
|
||||
std::string backend;
|
||||
|
||||
switch (g_backend) {
|
||||
case Backend::VULKAN:
|
||||
backend = "Vulkan";
|
||||
break;
|
||||
case Backend::D3D12:
|
||||
backend = "D3D12";
|
||||
break;
|
||||
case Backend::METAL:
|
||||
backend = "Metal";
|
||||
break;
|
||||
}
|
||||
|
||||
ImGui::Text("API: %s", backend.c_str());
|
||||
ImGui::Text("Device: %s", g_device->getDescription().name.c_str());
|
||||
ImGui::Text("Device Type: %s", DeviceTypeName(g_device->getDescription().type));
|
||||
ImGui::Text("VRAM: %.2f MiB", (double)(g_device->getDescription().dedicatedVideoMemory) / (1024.0 * 1024.0));
|
||||
|
@ -2867,7 +2939,7 @@ static void SetRootDescriptor(const UploadAllocation& allocation, size_t index)
|
|||
{
|
||||
auto& commandList = g_commandLists[g_frame];
|
||||
|
||||
if (g_vulkan)
|
||||
if (g_backend != Backend::D3D12)
|
||||
commandList->setGraphicsPushConstants(0, &allocation.deviceAddress, 8 * index, 8);
|
||||
else
|
||||
commandList->setGraphicsRootDescriptor(allocation.buffer->at(allocation.offset), index);
|
||||
|
@ -3354,12 +3426,9 @@ static bool PopulateBarriersForStretchRect(GuestSurface* renderTarget, GuestSurf
|
|||
RenderTextureLayout dstLayout;
|
||||
bool shaderResolve = true;
|
||||
|
||||
if (multiSampling && g_hardwareResolve)
|
||||
if (multiSampling)
|
||||
{
|
||||
// Hardware depth resolve is only supported on D3D12 when programmable sample positions are available.
|
||||
bool hardwareDepthResolveAvailable = g_hardwareDepthResolve && !g_vulkan && g_capabilities.sampleLocations;
|
||||
|
||||
if (surface->format != RenderFormat::D32_FLOAT || hardwareDepthResolveAvailable)
|
||||
if (surface->format != RenderFormat::D32_FLOAT || g_capabilities.resolveModes)
|
||||
{
|
||||
srcLayout = RenderTextureLayout::RESOLVE_SOURCE;
|
||||
dstLayout = RenderTextureLayout::RESOLVE_DEST;
|
||||
|
@ -3399,11 +3468,9 @@ static void ExecutePendingStretchRectCommands(GuestSurface* renderTarget, GuestS
|
|||
{
|
||||
bool shaderResolve = true;
|
||||
|
||||
if (multiSampling && g_hardwareResolve)
|
||||
if (multiSampling)
|
||||
{
|
||||
bool hardwareDepthResolveAvailable = g_hardwareDepthResolve && !g_vulkan && g_capabilities.sampleLocations;
|
||||
|
||||
if (surface->format != RenderFormat::D32_FLOAT || hardwareDepthResolveAvailable)
|
||||
if (surface->format != RenderFormat::D32_FLOAT || g_capabilities.resolveModes)
|
||||
{
|
||||
if (surface->format == RenderFormat::D32_FLOAT)
|
||||
commandList->resolveTextureRegion(texture->texture, 0, 0, surface->texture, nullptr, RenderResolveMode::MIN);
|
||||
|
@ -3519,7 +3586,7 @@ static void ExecutePendingStretchRectCommands(GuestSurface* renderTarget, GuestS
|
|||
g_dirtyStates.pipelineState = true;
|
||||
g_dirtyStates.scissorRect = true;
|
||||
|
||||
if (g_vulkan)
|
||||
if (g_backend != Backend::D3D12)
|
||||
{
|
||||
g_dirtyStates.vertexShaderConstants = true; // The push constant call invalidates vertex shader constants.
|
||||
g_dirtyStates.depthBias = true; // Static depth bias in copy pipeline invalidates dynamic depth bias.
|
||||
|
@ -3832,7 +3899,7 @@ static void ProcSetScissorRect(const RenderCommand& cmd)
|
|||
|
||||
static RenderShader* GetOrLinkShader(GuestShader* guestShader, uint32_t specConstants)
|
||||
{
|
||||
if (g_vulkan ||
|
||||
if (g_backend != Backend::D3D12 ||
|
||||
guestShader->shaderCacheEntry == nullptr ||
|
||||
guestShader->shaderCacheEntry->specConstantsMask == 0)
|
||||
{
|
||||
|
@ -3842,7 +3909,9 @@ static RenderShader* GetOrLinkShader(GuestShader* guestShader, uint32_t specCons
|
|||
{
|
||||
assert(guestShader->shaderCacheEntry != nullptr);
|
||||
|
||||
if (g_vulkan)
|
||||
switch (g_backend)
|
||||
{
|
||||
case Backend::VULKAN:
|
||||
{
|
||||
auto compressedSpirvData = g_shaderCache.get() + guestShader->shaderCacheEntry->spirvOffset;
|
||||
|
||||
|
@ -3850,12 +3919,21 @@ static RenderShader* GetOrLinkShader(GuestShader* guestShader, uint32_t specCons
|
|||
bool result = smolv::Decode(compressedSpirvData, guestShader->shaderCacheEntry->spirvSize, decoded.data(), decoded.size());
|
||||
assert(result);
|
||||
|
||||
guestShader->shader = g_device->createShader(decoded.data(), decoded.size(), "main", RenderShaderFormat::SPIRV);
|
||||
guestShader->shader = g_device->createShader(decoded.data(), decoded.size(), "shaderMain", RenderShaderFormat::SPIRV);
|
||||
break;
|
||||
}
|
||||
case Backend::METAL:
|
||||
{
|
||||
guestShader->shader = g_device->createShader(g_shaderCache.get() + guestShader->shaderCacheEntry->airOffset,
|
||||
guestShader->shaderCacheEntry->airSize, "shaderMain", RenderShaderFormat::METAL);
|
||||
break;
|
||||
}
|
||||
else
|
||||
case Backend::D3D12:
|
||||
{
|
||||
guestShader->shader = g_device->createShader(g_shaderCache.get() + guestShader->shaderCacheEntry->dxilOffset,
|
||||
guestShader->shaderCacheEntry->dxilSize, "main", RenderShaderFormat::DXIL);
|
||||
guestShader->shader = g_device->createShader(g_shaderCache.get() + guestShader->shaderCacheEntry->dxilOffset,
|
||||
guestShader->shaderCacheEntry->dxilSize, "shaderMain", RenderShaderFormat::DXIL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3960,7 +4038,7 @@ static RenderShader* GetOrLinkShader(GuestShader* guestShader, uint32_t specCons
|
|||
const wchar_t* libraryNames[] = { specConstantsLibName, shaderLibName };
|
||||
|
||||
ComPtr<IDxcOperationResult> result;
|
||||
HRESULT hr = s_dxcLinker->Link(L"main", guestShader->type == ResourceType::VertexShader ? L"vs_6_0" : L"ps_6_0",
|
||||
HRESULT hr = s_dxcLinker->Link(L"shaderMain", guestShader->type == ResourceType::VertexShader ? L"vs_6_0" : L"ps_6_0",
|
||||
libraryNames, std::size(libraryNames), nullptr, 0, result.GetAddressOf());
|
||||
|
||||
assert(SUCCEEDED(hr) && result != nullptr);
|
||||
|
@ -3975,7 +4053,7 @@ static RenderShader* GetOrLinkShader(GuestShader* guestShader, uint32_t specCons
|
|||
auto& linkedShader = guestShader->linkedShaders[specConstants];
|
||||
if (linkedShader == nullptr)
|
||||
{
|
||||
linkedShader = g_device->createShader(blob->GetBufferPointer(), blob->GetBufferSize(), "main", RenderShaderFormat::DXIL);
|
||||
linkedShader = g_device->createShader(blob->GetBufferPointer(), blob->GetBufferSize(), "shaderMain", RenderShaderFormat::DXIL);
|
||||
guestShader->shaderBlobs.push_back(std::move(blob));
|
||||
}
|
||||
|
||||
|
@ -4473,7 +4551,7 @@ static void FlushRenderStateForRenderThread()
|
|||
|
||||
// D3D12 resets depth bias values to the pipeline values, even if they are dynamic.
|
||||
// We can reduce unnecessary calls by making common depth bias values part of the pipeline.
|
||||
if (g_capabilities.dynamicDepthBias && !g_vulkan)
|
||||
if (g_capabilities.dynamicDepthBias && g_backend == Backend::D3D12)
|
||||
{
|
||||
bool useDepthBias = (g_depthBias != 0) || (g_slopeScaledDepthBias != 0.0f);
|
||||
|
||||
|
@ -4489,7 +4567,7 @@ static void FlushRenderStateForRenderThread()
|
|||
commandList->setPipeline(CreateGraphicsPipelineInRenderThread(g_pipelineState));
|
||||
|
||||
// D3D12 resets the depth bias values. Check if they need to be set again.
|
||||
if (g_capabilities.dynamicDepthBias && !g_vulkan)
|
||||
if (g_capabilities.dynamicDepthBias && g_backend == Backend::D3D12)
|
||||
g_dirtyStates.depthBias = (g_depthBias != g_pipelineState.depthBias) || (g_slopeScaledDepthBias != g_pipelineState.slopeScaledDepthBias);
|
||||
}
|
||||
|
||||
|
@ -4523,7 +4601,7 @@ static void FlushRenderStateForRenderThread()
|
|||
g_inputSlots + g_dirtyStates.vertexStreamFirst);
|
||||
}
|
||||
|
||||
if (g_dirtyStates.indices && (!g_vulkan || g_indexBufferView.buffer.ref != nullptr))
|
||||
if (g_dirtyStates.indices && (g_backend == Backend::D3D12 || g_indexBufferView.buffer.ref != nullptr))
|
||||
commandList->setIndexBuffer(&g_indexBufferView);
|
||||
|
||||
g_dirtyStates = DirtyStates(false);
|
||||
|
@ -5712,10 +5790,10 @@ static bool LoadTexture(GuestTexture& texture, const uint8_t* data, size_t dataS
|
|||
g_copyCommandList->barriers(RenderBarrierStage::COPY, RenderTextureBarrier(texture.texture, RenderTextureLayout::COPY_DEST));
|
||||
|
||||
auto copyTextureRegion = [&](Slice& slice, uint32_t subresourceIndex)
|
||||
{
|
||||
g_copyCommandList->copyTextureRegion(
|
||||
RenderTextureCopyLocation::Subresource(texture.texture, subresourceIndex),
|
||||
RenderTextureCopyLocation::PlacedFootprint(uploadBuffer.get(), desc.format, slice.width, slice.height, slice.depth, (slice.dstRowPitch * 8) / ddsDesc.bitsPerPixelOrBlock * ddsDesc.blockWidth, slice.dstOffset));
|
||||
{
|
||||
g_copyCommandList->copyTextureRegion(
|
||||
RenderTextureCopyLocation::Subresource(texture.texture, subresourceIndex % desc.mipLevels, subresourceIndex / desc.mipLevels),
|
||||
RenderTextureCopyLocation::PlacedFootprint(uploadBuffer.get(), desc.format, slice.width, slice.height, slice.depth, (slice.dstRowPitch * 8) / ddsDesc.bitsPerPixelOrBlock * ddsDesc.blockWidth, slice.dstOffset));
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < slices.size(); i++)
|
||||
|
@ -6458,7 +6536,7 @@ static void CompileMeshPipeline(const Mesh& mesh, CompilationArgs& args)
|
|||
if (g_capabilities.dynamicDepthBias)
|
||||
{
|
||||
// Put common depth bias values for reducing unnecessary calls.
|
||||
if (!g_vulkan)
|
||||
if (g_backend == Backend::D3D12)
|
||||
{
|
||||
pipelineState.depthBias = COMMON_DEPTH_BIAS_VALUE;
|
||||
pipelineState.slopeScaledDepthBias = COMMON_SLOPE_SCALED_DEPTH_BIAS_VALUE;
|
||||
|
@ -7220,7 +7298,7 @@ static void PipelineTaskConsumerThread()
|
|||
pipelineState.primitiveTopology = RenderPrimitiveTopology::TRIANGLE_LIST;
|
||||
|
||||
// Zero out depth bias for Vulkan, we only store common values for D3D12.
|
||||
if (g_capabilities.dynamicDepthBias && g_vulkan)
|
||||
if (g_capabilities.dynamicDepthBias && g_backend != Backend::D3D12)
|
||||
{
|
||||
pipelineState.depthBias = 0;
|
||||
pipelineState.slopeScaledDepthBias = 0.0f;
|
||||
|
|
|
@ -26,6 +26,12 @@ struct Video
|
|||
static void ComputeViewportDimensions();
|
||||
};
|
||||
|
||||
enum class Backend {
|
||||
VULKAN,
|
||||
D3D12,
|
||||
METAL
|
||||
};
|
||||
|
||||
struct GuestSamplerState
|
||||
{
|
||||
be<uint32_t> data[6];
|
||||
|
|
|
@ -166,6 +166,9 @@ void UpdateChecker::visitWebsite()
|
|||
#elif defined(__linux__)
|
||||
std::string command = "xdg-open " + std::string(VISIT_URL) + " &";
|
||||
std::system(command.c_str());
|
||||
#elif defined(__APPLE__)
|
||||
std::string command = "open " + std::string(VISIT_URL) + " &";
|
||||
std::system(command.c_str());
|
||||
#else
|
||||
static_assert(false, "Visit website not implemented for this platform.");
|
||||
#endif
|
||||
|
|
|
@ -660,7 +660,7 @@ void KeQueryBasePriorityThread()
|
|||
|
||||
uint32_t NtSuspendThread(GuestThreadHandle* hThread, uint32_t* suspendCount)
|
||||
{
|
||||
assert(hThread != GetKernelObject(CURRENT_THREAD_HANDLE) && hThread->thread.get_id() == std::this_thread::get_id());
|
||||
assert(hThread != GetKernelObject(CURRENT_THREAD_HANDLE) && hThread->GetThreadId() == GuestThread::GetCurrentThreadId());
|
||||
|
||||
hThread->suspended = true;
|
||||
hThread->suspended.wait(true);
|
||||
|
|
|
@ -306,26 +306,26 @@ uint32_t XamContentCreateEx(uint32_t dwUserIndex, const char* szRootName, const
|
|||
|
||||
if (!exists)
|
||||
{
|
||||
std::string root = "";
|
||||
std::filesystem::path rootPath;
|
||||
|
||||
if (pContentData->dwContentType == XCONTENTTYPE_SAVEDATA)
|
||||
{
|
||||
std::u8string savePathU8 = GetSavePath(true).u8string();
|
||||
root = (const char *)(savePathU8.c_str());
|
||||
rootPath = GetSavePath(true);
|
||||
}
|
||||
else if (pContentData->dwContentType == XCONTENTTYPE_DLC)
|
||||
{
|
||||
root = GAME_INSTALL_DIRECTORY "/dlc";
|
||||
rootPath = GetGamePath() / "dlc";
|
||||
}
|
||||
else
|
||||
{
|
||||
root = GAME_INSTALL_DIRECTORY;
|
||||
rootPath = GetGamePath();
|
||||
}
|
||||
|
||||
const std::string root = (const char*)rootPath.u8string().c_str();
|
||||
XamRegisterContent(*pContentData, root);
|
||||
|
||||
std::error_code ec;
|
||||
std::filesystem::create_directory(std::u8string_view((const char8_t*)(root.c_str())), ec);
|
||||
std::filesystem::create_directory(rootPath, ec);
|
||||
|
||||
XamRootCreate(szRootName, root);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#include <stdafx.h>
|
||||
#ifdef __x86_64__
|
||||
#include <cpuid.h>
|
||||
#endif
|
||||
#include <cpu/guest_thread.h>
|
||||
#include <gpu/video.h>
|
||||
#include <kernel/function.h>
|
||||
|
@ -69,8 +71,10 @@ void KiSystemStartup()
|
|||
|
||||
const auto gameContent = XamMakeContent(XCONTENTTYPE_RESERVED, "Game");
|
||||
const auto updateContent = XamMakeContent(XCONTENTTYPE_RESERVED, "Update");
|
||||
XamRegisterContent(gameContent, GAME_INSTALL_DIRECTORY "/game");
|
||||
XamRegisterContent(updateContent, GAME_INSTALL_DIRECTORY "/update");
|
||||
const std::string gamePath = (const char*)(GetGamePath() / "game").u8string().c_str();
|
||||
const std::string updatePath = (const char*)(GetGamePath() / "update").u8string().c_str();
|
||||
XamRegisterContent(gameContent, gamePath);
|
||||
XamRegisterContent(updateContent, updatePath);
|
||||
|
||||
const auto saveFilePath = GetSaveFilePath(true);
|
||||
bool saveFileExists = std::filesystem::exists(saveFilePath);
|
||||
|
@ -102,7 +106,7 @@ void KiSystemStartup()
|
|||
XamContentCreateEx(0, "D", &gameContent, OPEN_EXISTING, nullptr, nullptr, 0, 0, nullptr);
|
||||
|
||||
std::error_code ec;
|
||||
for (auto& file : std::filesystem::directory_iterator(GAME_INSTALL_DIRECTORY "/dlc", ec))
|
||||
for (auto& file : std::filesystem::directory_iterator(GetGamePath() / "dlc", ec))
|
||||
{
|
||||
if (file.is_directory())
|
||||
{
|
||||
|
@ -165,10 +169,10 @@ uint32_t LdrLoadModule(const std::filesystem::path &path)
|
|||
return entry;
|
||||
}
|
||||
|
||||
#ifdef __x86_64__
|
||||
__attribute__((constructor(101), target("no-avx,no-avx2"), noinline))
|
||||
void init()
|
||||
{
|
||||
#ifdef __x86_64__
|
||||
uint32_t eax, ebx, ecx, edx;
|
||||
|
||||
// Execute CPUID for processor info and feature bits.
|
||||
|
@ -185,8 +189,8 @@ void init()
|
|||
|
||||
std::_Exit(1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
@ -324,7 +328,7 @@ int main(int argc, char *argv[])
|
|||
HostStartup();
|
||||
|
||||
std::filesystem::path modulePath;
|
||||
bool isGameInstalled = Installer::checkGameInstall(GAME_INSTALL_DIRECTORY, modulePath);
|
||||
bool isGameInstalled = Installer::checkGameInstall(GetGamePath(), modulePath);
|
||||
bool runInstallerWizard = forceInstaller || forceDLCInstaller || !isGameInstalled;
|
||||
if (runInstallerWizard)
|
||||
{
|
||||
|
@ -334,7 +338,7 @@ int main(int argc, char *argv[])
|
|||
std::_Exit(1);
|
||||
}
|
||||
|
||||
if (!InstallerWizard::Run(GAME_INSTALL_DIRECTORY, isGameInstalled && forceDLCInstaller))
|
||||
if (!InstallerWizard::Run(GetGamePath(), isGameInstalled && forceDLCInstaller))
|
||||
{
|
||||
std::_Exit(0);
|
||||
}
|
||||
|
|
|
@ -100,7 +100,7 @@ void ModLoader::Init()
|
|||
{
|
||||
configIni = {};
|
||||
|
||||
if (!configIni.read(GAME_INSTALL_DIRECTORY "/cpkredir.ini"))
|
||||
if (!configIni.read(GetGamePath() / "cpkredir.ini"))
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,11 @@ std::filesystem::path os::process::GetExecutablePath()
|
|||
}
|
||||
}
|
||||
|
||||
std::filesystem::path os::process::GetExecutableRoot()
|
||||
{
|
||||
return GetExecutablePath().remove_filename();
|
||||
}
|
||||
|
||||
std::filesystem::path os::process::GetWorkingDirectory()
|
||||
{
|
||||
char cwd[PATH_MAX] = {};
|
||||
|
|
17
UnleashedRecomp/os/macos/logger_macos.cpp
Normal file
17
UnleashedRecomp/os/macos/logger_macos.cpp
Normal file
|
@ -0,0 +1,17 @@
|
|||
#include <os/logger.h>
|
||||
|
||||
void os::logger::Init()
|
||||
{
|
||||
}
|
||||
|
||||
void os::logger::Log(const std::string_view str, ELogType type, const char* func)
|
||||
{
|
||||
if (func)
|
||||
{
|
||||
fmt::println("[{}] {}", func, str);
|
||||
}
|
||||
else
|
||||
{
|
||||
fmt::println("{}", str);
|
||||
}
|
||||
}
|
7
UnleashedRecomp/os/macos/media_macos.cpp
Normal file
7
UnleashedRecomp/os/macos/media_macos.cpp
Normal file
|
@ -0,0 +1,7 @@
|
|||
#include <os/media.h>
|
||||
|
||||
bool os::media::IsExternalMediaPlaying()
|
||||
{
|
||||
// This functionality is not supported in macOS.
|
||||
return false;
|
||||
}
|
137
UnleashedRecomp/os/macos/process_macos.cpp
Normal file
137
UnleashedRecomp/os/macos/process_macos.cpp
Normal file
|
@ -0,0 +1,137 @@
|
|||
#include <os/process.h>
|
||||
|
||||
#include <CoreFoundation/CFBundle.h>
|
||||
#include <dlfcn.h>
|
||||
#include <mach-o/dyld.h>
|
||||
#include <signal.h>
|
||||
#include <sys/param.h>
|
||||
#include <unistd.h>
|
||||
|
||||
std::filesystem::path os::process::GetExecutablePath()
|
||||
{
|
||||
uint32_t exePathSize = PATH_MAX;
|
||||
char exePath[PATH_MAX] = {};
|
||||
if (_NSGetExecutablePath(exePath, &exePathSize) == 0)
|
||||
{
|
||||
return std::filesystem::path(std::u8string_view((const char8_t*)(exePath)));
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::filesystem::path();
|
||||
}
|
||||
}
|
||||
|
||||
using IsTranslocatedURLFunc = Boolean (*)(CFURLRef path, bool* isTranslocated,
|
||||
CFErrorRef* __nullable error);
|
||||
using CreateOriginalPathForURLFunc = CFURLRef __nullable (*)(CFURLRef translocatedPath,
|
||||
CFErrorRef* __nullable error);
|
||||
|
||||
static CFURLRef UntranslocateBundlePath(const CFURLRef bundlePath)
|
||||
{
|
||||
CFURLRef resultPath = nullptr;
|
||||
if (void* securityHandle = dlopen("/System/Library/Frameworks/Security.framework/Security", RTLD_LAZY))
|
||||
{
|
||||
const auto IsTranslocatedURL = reinterpret_cast<IsTranslocatedURLFunc>(
|
||||
dlsym(securityHandle, "SecTranslocateIsTranslocatedURL"));
|
||||
const auto CreateOriginalPathForURL = reinterpret_cast<CreateOriginalPathForURLFunc>(
|
||||
dlsym(securityHandle, "SecTranslocateCreateOriginalPathForURL"));
|
||||
|
||||
bool translocated = false;
|
||||
if (IsTranslocatedURL && CreateOriginalPathForURL &&
|
||||
IsTranslocatedURL(bundlePath, &translocated, nullptr) && translocated)
|
||||
{
|
||||
resultPath = CreateOriginalPathForURL(bundlePath, nullptr);
|
||||
}
|
||||
|
||||
dlclose(securityHandle);
|
||||
}
|
||||
return resultPath;
|
||||
}
|
||||
|
||||
std::filesystem::path os::process::GetExecutableRoot()
|
||||
{
|
||||
std::filesystem::path resultPath = GetExecutablePath().remove_filename();
|
||||
if (CFBundleRef bundleRef = CFBundleGetMainBundle())
|
||||
{
|
||||
if (CFURLRef bundleUrlRef = CFBundleCopyBundleURL(bundleRef))
|
||||
{
|
||||
// The OS may relocate the app elsewhere for security reasons if,
|
||||
// for example, it was downloaded and opened from the Downloads
|
||||
// folder. In this case, we need to untranslocate the path to
|
||||
// find out where the actual app bundle is.
|
||||
CFURLRef untranslocatedUrlRef = UntranslocateBundlePath(bundleUrlRef);
|
||||
|
||||
char appBundlePath[MAXPATHLEN];
|
||||
if (CFURLGetFileSystemRepresentation(
|
||||
untranslocatedUrlRef ? untranslocatedUrlRef : bundleUrlRef, true,
|
||||
reinterpret_cast<uint8_t*>(appBundlePath), sizeof(appBundlePath)))
|
||||
{
|
||||
resultPath = std::filesystem::path(appBundlePath).parent_path();
|
||||
}
|
||||
|
||||
if (untranslocatedUrlRef)
|
||||
{
|
||||
CFRelease(untranslocatedUrlRef);
|
||||
}
|
||||
CFRelease(bundleUrlRef);
|
||||
}
|
||||
}
|
||||
return resultPath;
|
||||
}
|
||||
|
||||
std::filesystem::path os::process::GetWorkingDirectory()
|
||||
{
|
||||
char cwd[PATH_MAX] = {};
|
||||
char *res = getcwd(cwd, sizeof(cwd));
|
||||
if (res != nullptr)
|
||||
{
|
||||
return std::filesystem::path(std::u8string_view((const char8_t*)(cwd)));
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::filesystem::path();
|
||||
}
|
||||
}
|
||||
|
||||
bool os::process::SetWorkingDirectory(const std::filesystem::path& path)
|
||||
{
|
||||
return chdir(path.c_str()) == 0;
|
||||
}
|
||||
|
||||
bool os::process::StartProcess(const std::filesystem::path& path, const std::vector<std::string>& args, std::filesystem::path work)
|
||||
{
|
||||
pid_t pid = fork();
|
||||
if (pid < 0)
|
||||
return false;
|
||||
|
||||
if (pid == 0)
|
||||
{
|
||||
setsid();
|
||||
|
||||
std::u8string workU8 = work.u8string();
|
||||
chdir((const char*)(workU8.c_str()));
|
||||
|
||||
std::u8string pathU8 = path.u8string();
|
||||
std::vector<char*> argStrs;
|
||||
argStrs.push_back((char*)(pathU8.c_str()));
|
||||
for (const std::string& arg : args)
|
||||
argStrs.push_back((char *)(arg.c_str()));
|
||||
|
||||
argStrs.push_back(nullptr);
|
||||
execvp((const char*)(pathU8.c_str()), argStrs.data());
|
||||
raise(SIGKILL);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void os::process::CheckConsole()
|
||||
{
|
||||
// Always visible on macOS.
|
||||
g_consoleVisible = true;
|
||||
}
|
||||
|
||||
void os::process::ShowConsole()
|
||||
{
|
||||
// Unnecessary on macOS.
|
||||
}
|
21
UnleashedRecomp/os/macos/registry_macos.inl
Normal file
21
UnleashedRecomp/os/macos/registry_macos.inl
Normal file
|
@ -0,0 +1,21 @@
|
|||
#include <os/registry.h>
|
||||
|
||||
// TODO: Implement
|
||||
inline bool os::registry::Init()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: read from file?
|
||||
template<typename T>
|
||||
bool os::registry::ReadValue(const std::string_view& name, T& data)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: write to file?
|
||||
template<typename T>
|
||||
bool os::registry::WriteValue(const std::string_view& name, const T& data)
|
||||
{
|
||||
return false;
|
||||
}
|
6
UnleashedRecomp/os/macos/user_macos.cpp
Normal file
6
UnleashedRecomp/os/macos/user_macos.cpp
Normal file
|
@ -0,0 +1,6 @@
|
|||
#include <os/user.h>
|
||||
|
||||
bool os::user::IsDarkTheme()
|
||||
{
|
||||
return false;
|
||||
}
|
7
UnleashedRecomp/os/macos/version_macos.cpp
Normal file
7
UnleashedRecomp/os/macos/version_macos.cpp
Normal file
|
@ -0,0 +1,7 @@
|
|||
#include <os/version.h>
|
||||
|
||||
os::version::OSVersion os::version::GetOSVersion()
|
||||
{
|
||||
assert(false && "Unimplemented.");
|
||||
return os::version::OSVersion();
|
||||
}
|
|
@ -5,6 +5,7 @@ namespace os::process
|
|||
inline bool g_consoleVisible;
|
||||
|
||||
std::filesystem::path GetExecutablePath();
|
||||
std::filesystem::path GetExecutableRoot();
|
||||
std::filesystem::path GetWorkingDirectory();
|
||||
bool SetWorkingDirectory(const std::filesystem::path& path);
|
||||
bool StartProcess(const std::filesystem::path& path, const std::vector<std::string>& args, std::filesystem::path work = {});
|
||||
|
|
|
@ -15,4 +15,6 @@ namespace os::registry
|
|||
#include <os/win32/registry_win32.inl>
|
||||
#elif defined(__linux__)
|
||||
#include <os/linux/registry_linux.inl>
|
||||
#elif defined(__APPLE__)
|
||||
#include <os/macos/registry_macos.inl>
|
||||
#endif
|
||||
|
|
|
@ -10,6 +10,11 @@ std::filesystem::path os::process::GetExecutablePath()
|
|||
return std::filesystem::path(exePath);
|
||||
}
|
||||
|
||||
std::filesystem::path os::process::GetExecutableRoot()
|
||||
{
|
||||
return GetExecutablePath().remove_filename();
|
||||
}
|
||||
|
||||
std::filesystem::path os::process::GetWorkingDirectory()
|
||||
{
|
||||
WCHAR workPath[MAX_PATH];
|
||||
|
|
42
UnleashedRecomp/res/macos/MacOSXBundleInfo.plist.in
Normal file
42
UnleashedRecomp/res/macos/MacOSXBundleInfo.plist.in
Normal file
|
@ -0,0 +1,42 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
|
||||
<key>CFBundleGetInfoString</key>
|
||||
<string>${MACOSX_BUNDLE_INFO_STRING}</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>${MACOSX_BUNDLE_ICON_FILE}</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleLongVersionString</key>
|
||||
<string>${MACOSX_BUNDLE_LONG_VERSION_STRING}</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
|
||||
<key>CSResourcesFileMapped</key>
|
||||
<true/>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>${MACOSX_BUNDLE_COPYRIGHT}</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>13.0</string>
|
||||
<key>LSApplicationCategoryType</key>
|
||||
<string>public.app-category.games</string>
|
||||
<key>GCSupportsGameMode</key>
|
||||
<true/>
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
BIN
UnleashedRecomp/res/macos/game_icon.icns
Normal file
BIN
UnleashedRecomp/res/macos/game_icon.icns
Normal file
Binary file not shown.
|
@ -20,7 +20,7 @@ std::unique_ptr<GuestTexture> g_upKBMIcons;
|
|||
|
||||
float g_sideMargins = DEFAULT_SIDE_MARGINS;
|
||||
|
||||
std::vector<Button> g_buttons;
|
||||
static std::vector<Button> g_buttons;
|
||||
|
||||
std::unordered_map<EButtonIcon, float> g_iconWidths =
|
||||
{
|
||||
|
|
|
@ -217,6 +217,9 @@ void GameWindow::Init(const char* sdlVideoDriver)
|
|||
s_renderWindow = s_pWindow;
|
||||
#elif defined(__linux__)
|
||||
s_renderWindow = { info.info.x11.display, info.info.x11.window };
|
||||
#elif defined(__APPLE__)
|
||||
s_renderWindow.window = info.info.cocoa.window;
|
||||
s_renderWindow.view = SDL_Metal_GetLayer(SDL_Metal_CreateView(s_pWindow));
|
||||
#else
|
||||
static_assert(false, "Unknown platform.");
|
||||
#endif
|
||||
|
|
|
@ -1146,7 +1146,11 @@ static void PickerStart(bool folderMode) {
|
|||
g_currentPickerVisible = true;
|
||||
|
||||
// Optional single thread mode for testing on systems that do not interact well with the separate thread being used for NFD.
|
||||
#ifdef __APPLE__
|
||||
constexpr bool singleThreadMode = true;
|
||||
#else
|
||||
constexpr bool singleThreadMode = false;
|
||||
#endif
|
||||
if (singleThreadMode)
|
||||
PickerThreadProcess();
|
||||
else
|
||||
|
|
|
@ -41,7 +41,7 @@ static ImFont* g_fntSeurat;
|
|||
|
||||
std::string g_text;
|
||||
int g_result;
|
||||
std::vector<std::string> g_buttons;
|
||||
static std::vector<std::string> g_buttons;
|
||||
int g_defaultButtonIndex;
|
||||
int g_cancelButtonIndex;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include "paths.h"
|
||||
#include <os/process.h>
|
||||
|
||||
std::filesystem::path g_executableRoot = os::process::GetExecutablePath().remove_filename();
|
||||
std::filesystem::path g_executableRoot = os::process::GetExecutableRoot();
|
||||
std::filesystem::path g_userPath = BuildUserPath();
|
||||
|
||||
bool CheckPortable()
|
||||
|
@ -22,18 +22,24 @@ std::filesystem::path BuildUserPath()
|
|||
userPath = std::filesystem::path{ knownPath } / USER_DIRECTORY;
|
||||
|
||||
CoTaskMemFree(knownPath);
|
||||
#elif defined(__linux__)
|
||||
#elif defined(__linux__) || defined(__APPLE__)
|
||||
const char* homeDir = getenv("HOME");
|
||||
#if defined(__linux__)
|
||||
if (homeDir == nullptr)
|
||||
{
|
||||
homeDir = getpwuid(getuid())->pw_dir;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (homeDir != nullptr)
|
||||
{
|
||||
// Prefer to store in the .config directory if it exists. Use the home directory otherwise.
|
||||
std::filesystem::path homePath = homeDir;
|
||||
#if defined(__linux__)
|
||||
std::filesystem::path configPath = homePath / ".config";
|
||||
#else
|
||||
std::filesystem::path configPath = homePath / "Library" / "Application Support";
|
||||
#endif
|
||||
if (std::filesystem::exists(configPath))
|
||||
userPath = configPath / USER_DIRECTORY;
|
||||
else
|
||||
|
|
|
@ -10,15 +10,22 @@
|
|||
|
||||
extern std::filesystem::path g_executableRoot;
|
||||
|
||||
inline std::filesystem::path GetGamePath()
|
||||
{
|
||||
return GAME_INSTALL_DIRECTORY;
|
||||
}
|
||||
|
||||
bool CheckPortable();
|
||||
std::filesystem::path BuildUserPath();
|
||||
const std::filesystem::path& GetUserPath();
|
||||
|
||||
inline std::filesystem::path GetGamePath()
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
// On macOS, there is the expectation that the app may be installed to
|
||||
// /Applications/, and the bundle should not be modified. Thus we need
|
||||
// to install game files to the user directory instead of next to the app.
|
||||
return GetUserPath();
|
||||
#else
|
||||
return GAME_INSTALL_DIRECTORY;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline std::filesystem::path GetSavePath(bool checkForMods)
|
||||
{
|
||||
if (checkForMods && !ModLoader::s_saveFilePath.empty())
|
||||
|
|
|
@ -53,6 +53,7 @@ target_compile_definitions(XenosRecomp PRIVATE
|
|||
XENOS_RECOMP_INPUT=\"${CMAKE_CURRENT_SOURCE_DIR}/private\"
|
||||
XENOS_RECOMP_OUTPUT=\"${CMAKE_CURRENT_SOURCE_DIR}/shader/shader_cache.cpp\"
|
||||
XENOS_RECOMP_INCLUDE_INPUT=\"${XENOS_RECOMP_INCLUDE}\"
|
||||
UNLEASHED_RECOMP
|
||||
)
|
||||
|
||||
file(GLOB XENOS_RECOMP_SOURCES
|
||||
|
@ -79,4 +80,5 @@ add_library(UnleashedRecompLib
|
|||
)
|
||||
|
||||
target_include_directories(UnleashedRecompLib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_include_directories(UnleashedRecompLib PRIVATE "${UNLEASHED_RECOMP_TOOLS_ROOT}/XenonRecomp/thirdparty/simde")
|
||||
target_precompile_headers(UnleashedRecompLib PUBLIC "ppc/ppc_recomp_shared.h")
|
||||
|
|
|
@ -7,6 +7,8 @@ struct ShaderCacheEntry
|
|||
const uint32_t dxilSize;
|
||||
const uint32_t spirvOffset;
|
||||
const uint32_t spirvSize;
|
||||
const uint32_t airOffset;
|
||||
const uint32_t airSize;
|
||||
const uint32_t specConstantsMask;
|
||||
struct GuestShader* guestShader;
|
||||
};
|
||||
|
@ -18,6 +20,10 @@ extern const uint8_t g_compressedDxilCache[];
|
|||
extern const size_t g_dxilCacheCompressedSize;
|
||||
extern const size_t g_dxilCacheDecompressedSize;
|
||||
|
||||
extern const uint8_t g_compressedAirCache[];
|
||||
extern const size_t g_airCacheCompressedSize;
|
||||
extern const size_t g_airCacheDecompressedSize;
|
||||
|
||||
extern const uint8_t g_compressedSpirvCache[];
|
||||
extern const size_t g_spirvCacheCompressedSize;
|
||||
extern const size_t g_spirvCacheDecompressedSize;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue