diff --git a/UnleashedRecomp/CMakeLists.txt b/UnleashedRecomp/CMakeLists.txt index 0ff32f3e..91ef0e8e 100644 --- a/UnleashedRecomp/CMakeLists.txt +++ b/UnleashedRecomp/CMakeLists.txt @@ -104,6 +104,7 @@ find_package(xxHash CONFIG REQUIRED) find_package(PkgConfig REQUIRED) pkg_check_modules(tomlplusplus REQUIRED IMPORTED_TARGET tomlplusplus) find_package(directx-dxc REQUIRED) +find_package(zstd CONFIG REQUIRED) target_link_libraries(UnleashedRecomp PRIVATE comctl32 @@ -123,6 +124,7 @@ target_link_libraries(UnleashedRecomp PRIVATE winmm xxHash::xxhash PkgConfig::tomlplusplus + zstd::libzstd_static ) target_include_directories(UnleashedRecomp PRIVATE diff --git a/UnleashedRecomp/gpu/video.cpp b/UnleashedRecomp/gpu/video.cpp index 980a1ea3..dc308dab 100644 --- a/UnleashedRecomp/gpu/video.cpp +++ b/UnleashedRecomp/gpu/video.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "video.h" #include "ui/window.h" @@ -290,42 +291,17 @@ static void FlushBarriers() } } -struct ShaderCacheHeader -{ - uint32_t version; - uint32_t shaderCount; - uint32_t reserved0; - uint32_t reserved1; -}; - -struct ShaderCacheEntry -{ - XXH64_hash_t hash; - uint32_t dxilOffset; - uint32_t dxilSize; - uint32_t spirvOffset; - uint32_t spirvSize; - GuestShader* shader = nullptr; -}; - static std::unique_ptr g_shaderCache; static void LoadShaderCache() { - FILE* file = fopen("ShaderCache.bin", "rb"); - if (file) - { - fseek(file, 0, SEEK_END); - long fileSize = ftell(file); - fseek(file, 0, SEEK_SET); - g_shaderCache = std::make_unique(fileSize); - fread(g_shaderCache.get(), 1, fileSize, file); - fclose(file); - } - else - { - MessageBox(nullptr, TEXT("Unable to locate ShaderCache.bin in root directory."), TEXT("SWA"), MB_ICONERROR); - } + const size_t decompressedSize = g_vulkan ? g_spirvCacheDecompressedSize : g_dxilCacheDecompressedSize; + g_shaderCache = std::make_unique(decompressedSize); + + ZSTD_decompress(g_shaderCache.get(), + decompressedSize, + g_vulkan ? g_compressedSpirvCache : g_compressedDxilCache, + g_vulkan ? g_spirvCacheCompressedSize : g_dxilCacheCompressedSize); } static void SetRenderState(GuestDevice* device, uint32_t value) @@ -2082,10 +2058,8 @@ static GuestShader* CreateShader(const be* function, ResourceType reso { XXH64_hash_t hash = XXH3_64bits(function, function[1] + function[2]); - auto shaderCache = reinterpret_cast(g_shaderCache.get()); - auto begin = reinterpret_cast(shaderCache + 1); - auto end = begin + shaderCache->shaderCount; - auto findResult = std::lower_bound(begin, end, hash, [](ShaderCacheEntry& lhs, XXH64_hash_t rhs) + auto end = g_shaderCacheEntries + g_shaderCacheEntryCount; + auto findResult = std::lower_bound(g_shaderCacheEntries, end, hash, [](ShaderCacheEntry& lhs, XXH64_hash_t rhs) { return lhs.hash < rhs; }); @@ -2094,7 +2068,7 @@ static GuestShader* CreateShader(const be* function, ResourceType reso if (findResult != end && findResult->hash == hash) { - if (findResult->shader == nullptr) + if (findResult->userData == nullptr) { shader = g_userHeap.AllocPhysical(resourceType); @@ -2103,11 +2077,11 @@ static GuestShader* CreateShader(const be* function, ResourceType reso else shader->shader = g_device->createShader(g_shaderCache.get() + findResult->dxilOffset, findResult->dxilSize, "main", RenderShaderFormat::DXIL); - findResult->shader = shader; + findResult->userData = shader; } else { - shader = findResult->shader; + shader = reinterpret_cast(findResult->userData); } } diff --git a/UnleashedRecomp/stdafx.h b/UnleashedRecomp/stdafx.h index bd19ddf1..6233ba01 100644 --- a/UnleashedRecomp/stdafx.h +++ b/UnleashedRecomp/stdafx.h @@ -13,6 +13,7 @@ #include #include #include +#include #include "framework.h" #include "mutex.h" diff --git a/UnleashedRecompLib/CMakeLists.txt b/UnleashedRecompLib/CMakeLists.txt index 18413f69..8561424a 100644 --- a/UnleashedRecompLib/CMakeLists.txt +++ b/UnleashedRecompLib/CMakeLists.txt @@ -5,10 +5,17 @@ add_compile_options( "-march=sandybridge" "-fno-strict-aliasing") -file(GLOB SWA_RECOMPILED_SOURCES "ppc/*.cpp") -add_library(UnleashedRecompLib "main.cpp" ${SWA_RECOMPILED_SOURCES}) +file(GLOB SWA_PPC_RECOMPILED_SOURCES "ppc/*.cpp") +file(GLOB SWA_SHADER_RECOMPILED_SOURCES "shader/*.cpp") +add_library(UnleashedRecompLib "main.cpp" ${SWA_PPC_RECOMPILED_SOURCES} "shader/shader_cache.h" ${SWA_SHADER_RECOMPILED_SOURCES}) target_include_directories(UnleashedRecompLib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) target_precompile_headers(UnleashedRecompLib PUBLIC ppc/ppc_recomp_shared.h) -target_compile_definitions(PowerRecomp PRIVATE CONFIG_FILE_PATH=\"${CMAKE_CURRENT_SOURCE_DIR}/config/SWA.toml\") + +target_compile_definitions(PowerRecomp PRIVATE + CONFIG_FILE_PATH=\"${CMAKE_CURRENT_SOURCE_DIR}/config/SWA.toml\") + +target_compile_definitions(ShaderRecomp PRIVATE + SHADER_RECOMP_INPUT=\"${CMAKE_CURRENT_SOURCE_DIR}/private\" + SHADER_RECOMP_OUTPUT=\"${CMAKE_CURRENT_SOURCE_DIR}/shader/shader_cache.cpp\") diff --git a/UnleashedRecompLib/shader/.gitignore b/UnleashedRecompLib/shader/.gitignore new file mode 100644 index 00000000..c4b3ea7e --- /dev/null +++ b/UnleashedRecompLib/shader/.gitignore @@ -0,0 +1,3 @@ +* +!shader_cache.h +!.gitignore diff --git a/UnleashedRecompLib/shader/shader_cache.h b/UnleashedRecompLib/shader/shader_cache.h new file mode 100644 index 00000000..7b64ebd9 --- /dev/null +++ b/UnleashedRecompLib/shader/shader_cache.h @@ -0,0 +1,22 @@ +#pragma once + +struct ShaderCacheEntry +{ + uint64_t hash; + uint32_t dxilOffset; + uint32_t dxilSize; + uint32_t spirvOffset; + uint32_t spirvSize; + void* userData; +}; + +extern ShaderCacheEntry g_shaderCacheEntries[]; +extern size_t g_shaderCacheEntryCount; + +extern uint8_t g_compressedDxilCache[]; +extern size_t g_dxilCacheCompressedSize; +extern size_t g_dxilCacheDecompressedSize; + +extern uint8_t g_compressedSpirvCache[]; +extern size_t g_spirvCacheCompressedSize; +extern size_t g_spirvCacheDecompressedSize; diff --git a/thirdparty/CMakeLists.txt b/thirdparty/CMakeLists.txt index 07a10b86..d0b89ccd 100644 --- a/thirdparty/CMakeLists.txt +++ b/thirdparty/CMakeLists.txt @@ -1,2 +1,3 @@ -add_subdirectory(${SWA_THIRDPARTY_ROOT}/PowerRecomp) +add_subdirectory(${SWA_THIRDPARTY_ROOT}/PowerRecomp) +add_subdirectory(${SWA_THIRDPARTY_ROOT}/ShaderRecomp) add_subdirectory(${SWA_THIRDPARTY_ROOT}/o1heap) diff --git a/thirdparty/ShaderRecomp b/thirdparty/ShaderRecomp index 9da6b59c..b1521427 160000 --- a/thirdparty/ShaderRecomp +++ b/thirdparty/ShaderRecomp @@ -1 +1 @@ -Subproject commit 9da6b59ce51c5becc919c2f1aed7c5e5f3b86f31 +Subproject commit b15214270923fa9d73dd59d5a27170acdcb8d689 diff --git a/vcpkg.json b/vcpkg.json index 0526b52d..3ab39e98 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -10,6 +10,7 @@ "vulkan-memory-allocator", "xxhash", "pkgconf", - "tomlplusplus" + "tomlplusplus", + "zstd" ] }