From 16e981c82c95819c721da6aef6a9a75a523fd813 Mon Sep 17 00:00:00 2001 From: Fire Cube Date: Tue, 25 Feb 2025 20:38:01 +0100 Subject: [PATCH 01/27] first spirv cache implementation --- src/emulator.cpp | 5 ++++ .../renderer_vulkan/vk_pipeline_cache.cpp | 29 +++++++++++++++++-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/emulator.cpp b/src/emulator.cpp index 68c1e332c..0e282b89f 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -248,6 +248,11 @@ void Emulator::Run(const std::filesystem::path& file, const std::vectorGetHLESymbols()); diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 4823b8ffe..97bfc4702 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -17,6 +17,7 @@ #include "video_core/renderer_vulkan/vk_presenter.h" #include "video_core/renderer_vulkan/vk_scheduler.h" #include "video_core/renderer_vulkan/vk_shader_util.h" +#include extern std::unique_ptr presenter; @@ -504,8 +505,31 @@ vk::ShaderModule PipelineCache::CompileModule(Shader::Info& info, Shader::Runtim DumpShader(code, info.pgm_hash, info.stage, perm_idx, "bin"); const auto ir_program = Shader::TranslateProgram(code, pools, info, runtime_info, profile); - auto spv = Shader::Backend::SPIRV::EmitSPIRV(profile, runtime_info, ir_program, binding); - DumpShader(spv, info.pgm_hash, info.stage, perm_idx, "spv"); + + std::string shader_name = GetShaderName(info.stage, info.pgm_hash, perm_idx); + std::string cacheFilename = + shader_name + "_" + Common::g_scm_rev + ".spv "; + + const auto shader_cache_dir = + Common::FS::GetUserPath(Common::FS::PathType::ShaderDir) / "cache"; + std::filesystem::path shader_cache_file_path = shader_cache_dir / cacheFilename; + + std::vector spv; + + if (std::filesystem::exists(shader_cache_file_path)) { + Common::FS::IOFile shader_cache_file(shader_cache_file_path, Common::FS::FileAccessMode::Read); + spv.resize(shader_cache_file.GetSize() / sizeof(u32)); + shader_cache_file.Read(spv); + LOG_INFO(Render_Vulkan, "Loaded SPIR-V from cache: {}", shader_cache_file_path.string()); + } else { + spv = Shader::Backend::SPIRV::EmitSPIRV(profile, runtime_info, ir_program, binding); + + DumpShader(spv, info.pgm_hash, info.stage, perm_idx, "spv"); + + Common::FS::IOFile shader_cache_file(shader_cache_file_path, Common::FS::FileAccessMode::Write); + shader_cache_file.WriteSpan(std::span(spv)); + LOG_INFO(Render_Vulkan, "Compiled SPIR-V and stored in cache: {}", shader_cache_file_path.string()); + } vk::ShaderModule module; @@ -520,6 +544,7 @@ vk::ShaderModule PipelineCache::CompileModule(Shader::Info& info, Shader::Runtim const auto name = GetShaderName(info.stage, info.pgm_hash, perm_idx); Vulkan::SetObjectName(instance.GetDevice(), module, name); + if (Config::collectShadersForDebug()) { DebugState.CollectShader(name, info.l_stage, module, spv, code, patch ? *patch : std::span{}, is_patched); From c188b7c60d35549b94294169538e6b8b5c46c98c Mon Sep 17 00:00:00 2001 From: Fire Cube Date: Tue, 25 Feb 2025 21:07:24 +0100 Subject: [PATCH 02/27] better naming --- .../renderer_vulkan/vk_pipeline_cache.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 97bfc4702..bb46c8375 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -507,28 +507,28 @@ vk::ShaderModule PipelineCache::CompileModule(Shader::Info& info, Shader::Runtim const auto ir_program = Shader::TranslateProgram(code, pools, info, runtime_info, profile); std::string shader_name = GetShaderName(info.stage, info.pgm_hash, perm_idx); - std::string cacheFilename = + std::string spirv_cache_filename = shader_name + "_" + Common::g_scm_rev + ".spv "; const auto shader_cache_dir = Common::FS::GetUserPath(Common::FS::PathType::ShaderDir) / "cache"; - std::filesystem::path shader_cache_file_path = shader_cache_dir / cacheFilename; + std::filesystem::path spirv_cache_file_path = shader_cache_dir / spirv_cache_filename; std::vector spv; - if (std::filesystem::exists(shader_cache_file_path)) { - Common::FS::IOFile shader_cache_file(shader_cache_file_path, Common::FS::FileAccessMode::Read); - spv.resize(shader_cache_file.GetSize() / sizeof(u32)); - shader_cache_file.Read(spv); - LOG_INFO(Render_Vulkan, "Loaded SPIR-V from cache: {}", shader_cache_file_path.string()); + if (std::filesystem::exists(spirv_cache_file_path)) { + Common::FS::IOFile spirv_cache_file(spirv_cache_file_path, Common::FS::FileAccessMode::Read); + spv.resize(spirv_cache_file.GetSize() / sizeof(u32)); + spirv_cache_file.Read(spv); + LOG_INFO(Render_Vulkan, "Loaded SPIR-V from cache: {}", spirv_cache_file_path.string()); } else { spv = Shader::Backend::SPIRV::EmitSPIRV(profile, runtime_info, ir_program, binding); DumpShader(spv, info.pgm_hash, info.stage, perm_idx, "spv"); - Common::FS::IOFile shader_cache_file(shader_cache_file_path, Common::FS::FileAccessMode::Write); + Common::FS::IOFile shader_cache_file(spirv_cache_file_path, Common::FS::FileAccessMode::Write); shader_cache_file.WriteSpan(std::span(spv)); - LOG_INFO(Render_Vulkan, "Compiled SPIR-V and stored in cache: {}", shader_cache_file_path.string()); + LOG_INFO(Render_Vulkan, "Compiled SPIR-V and stored in cache: {}", spirv_cache_file_path.string()); } vk::ShaderModule module; From 2aee03218c93ce74ca4937dbc192bbd9aaa7eebb Mon Sep 17 00:00:00 2001 From: Fire Cube Date: Wed, 30 Apr 2025 19:56:38 +0200 Subject: [PATCH 03/27] temp push --- CMakeLists.txt | 1 + src/common/binary_helper.h | 43 +++++++++++++++++++ .../renderer_vulkan/shader_cache.cpp | 28 ++++++++++++ src/video_core/renderer_vulkan/shader_cache.h | 0 .../renderer_vulkan/vk_pipeline_cache.cpp | 5 +-- 5 files changed, 74 insertions(+), 3 deletions(-) create mode 100644 src/common/binary_helper.h create mode 100644 src/video_core/renderer_vulkan/shader_cache.cpp create mode 100644 src/video_core/renderer_vulkan/shader_cache.h diff --git a/CMakeLists.txt b/CMakeLists.txt index e36c1f280..2014dd1aa 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -633,6 +633,7 @@ set(COMMON src/common/logging/backend.cpp src/common/arch.h src/common/assert.cpp src/common/assert.h + src/common/binary_helper.h src/common/bit_field.h src/common/bounded_threadsafe_queue.h src/common/concepts.h diff --git a/src/common/binary_helper.h b/src/common/binary_helper.h new file mode 100644 index 000000000..b6883cf61 --- /dev/null +++ b/src/common/binary_helper.h @@ -0,0 +1,43 @@ +#include +#include + +using u32 = uint32_t; + +template +void writeBin(std::ostream& os, const T& v) { + os.write(reinterpret_cast(&v), sizeof(T)); +} + +template +void readBin(std::istream& is, T& v) { + is.read(reinterpret_cast(&v), sizeof(T)); +} + +// Spezialfall für Arrays/Blöcke +template +void writeBlock(std::ostream& os, const T* data, size_t count) { + os.write(reinterpret_cast(data), sizeof(T) * count); +} + +template +void readBlock(std::istream& is, T* data, size_t count) { + is.read(reinterpret_cast(data), sizeof(T) * count); +} + +// Spezialfall für Container +template +void writeContainer(std::ostream& os, const std::vector& v) { + u32 n = static_cast(v.size()); + writeBin(os, n); + if (n) + writeBlock(os, v.data(), n); +} + +template +void readContainer(std::istream& is, std::vector& v) { + u32 n; + readBin(is, n); + v.resize(n); + if (n) + readBlock(is, v.data(), n); +} \ No newline at end of file diff --git a/src/video_core/renderer_vulkan/shader_cache.cpp b/src/video_core/renderer_vulkan/shader_cache.cpp new file mode 100644 index 000000000..17860b4dc --- /dev/null +++ b/src/video_core/renderer_vulkan/shader_cache.cpp @@ -0,0 +1,28 @@ +#include +#include +#include + +namespace ShaderCache { + +const auto shader_cache_dir = Common::FS::GetUserPath(Common::FS::PathType::ShaderDir) / "cache"; +std::string CreateShaderID(std::ostream& info_dump, std::ostream& profile_dump) { + std::ostringstream info_stream, profile_stream; + info_stream << info_dump.rdbuf(); + profile_stream << profile_dump.rdbuf(); + + std::string combined_data = info_stream.str() + profile_stream.str(); + + std::hash hasher; + size_t shader_id = hasher(combined_data); + return std::to_string(shader_id); +} + +void GetShader{ + +} +void AddShader(std::vector spv, std::ostream& info_dump, std::ostream& profile_dump) { + + std::string spirv_cache_filename = shader_name + ".spv "; +} + +} \ No newline at end of file diff --git a/src/video_core/renderer_vulkan/shader_cache.h b/src/video_core/renderer_vulkan/shader_cache.h new file mode 100644 index 000000000..e69de29bb diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 49f3ba706..0d5fe8a69 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -493,13 +493,12 @@ vk::ShaderModule PipelineCache::CompileModule(Shader::Info& info, Shader::Runtim DumpShader(code, info.pgm_hash, info.stage, perm_idx, "bin"); const auto ir_program = Shader::TranslateProgram(code, pools, info, runtime_info, profile); - + std::string shader_name = GetShaderName(info.stage, info.pgm_hash, perm_idx); std::string spirv_cache_filename = shader_name + "_" + Common::g_scm_rev + ".spv "; - const auto shader_cache_dir = - Common::FS::GetUserPath(Common::FS::PathType::ShaderDir) / "cache"; + std::filesystem::path spirv_cache_file_path = shader_cache_dir / spirv_cache_filename; std::vector spv; From 09f844add1699f6861e5a80c093c06d224a5cff2 Mon Sep 17 00:00:00 2001 From: Fire Cube Date: Wed, 30 Apr 2025 22:01:22 +0200 Subject: [PATCH 04/27] initial codebase --- CMakeLists.txt | 2 + src/common/binary_helper.h | 4 +- .../renderer_vulkan/shader_cache.cpp | 64 ++++++++++++++++--- src/video_core/renderer_vulkan/shader_cache.h | 20 ++++++ .../renderer_vulkan/vk_pipeline_cache.cpp | 23 +++---- 5 files changed, 93 insertions(+), 20 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2014dd1aa..931783df1 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -893,6 +893,8 @@ set(VIDEO_CORE src/video_core/amdgpu/liverpool.cpp src/video_core/buffer_cache/word_manager.h src/video_core/renderer_vulkan/liverpool_to_vk.cpp src/video_core/renderer_vulkan/liverpool_to_vk.h + src/video_core/renderer_vulkan/shader_cache.cpp + src/video_core/renderer_vulkan/shader_cache.h src/video_core/renderer_vulkan/vk_common.cpp src/video_core/renderer_vulkan/vk_common.h src/video_core/renderer_vulkan/vk_compute_pipeline.cpp diff --git a/src/common/binary_helper.h b/src/common/binary_helper.h index b6883cf61..cfcc213ae 100644 --- a/src/common/binary_helper.h +++ b/src/common/binary_helper.h @@ -1,4 +1,6 @@ -#include +#pragma once + +#include #include using u32 = uint32_t; diff --git a/src/video_core/renderer_vulkan/shader_cache.cpp b/src/video_core/renderer_vulkan/shader_cache.cpp index 17860b4dc..63db08b03 100644 --- a/src/video_core/renderer_vulkan/shader_cache.cpp +++ b/src/video_core/renderer_vulkan/shader_cache.cpp @@ -1,12 +1,21 @@ #include #include #include +#include +#include "common/path_util.h" +#include "common/io_file.h" +#include "common/binary_helper.h" +#include "shader_recompiler/info.h" + +using u64 = uint64_t; namespace ShaderCache { const auto shader_cache_dir = Common::FS::GetUserPath(Common::FS::PathType::ShaderDir) / "cache"; -std::string CreateShaderID(std::ostream& info_dump, std::ostream& profile_dump) { + +std::string CreateShaderID(u64 pgm_hash, size_t perm_idx, std::ostream& info_dump, std::ostream& profile_dump) { std::ostringstream info_stream, profile_stream; + info_stream << pgm_hash << perm_idx; info_stream << info_dump.rdbuf(); profile_stream << profile_dump.rdbuf(); @@ -17,12 +26,51 @@ std::string CreateShaderID(std::ostream& info_dump, std::ostream& profile_dump) return std::to_string(shader_id); } -void GetShader{ - -} -void AddShader(std::vector spv, std::ostream& info_dump, std::ostream& profile_dump) { - - std::string spirv_cache_filename = shader_name + ".spv "; +void DumpInfo(std::ostream& info_dump, Shader::Info info) { + writeBin(info_dump, info.mrt_mask); } -} \ No newline at end of file +void DumpProfile(std::ostream& profile_dump, Shader::Profile profile) { + writeBin(profile_dump, profile.has_broken_spirv_clamp); +} + +bool CheckShaderCache(std::string shader_id) { + return 0; +} + +bool GetShader(std::string shader_id) { + std::string spirv_cache_filename = shader_id + ".spv "; + std::filesystem::path spirv_cache_file_path = shader_cache_dir / spirv_cache_filename; + Common::FS::IOFile spirv_cache_file(spirv_cache_file_path, + Common::FS::FileAccessMode::Read); + std::vector spv; + spv.resize(spirv_cache_file.GetSize() / sizeof(u32)); + spirv_cache_file.Read(spv); +} + +void AddShader(std::string shader_id, std::vector spv, std::ostream& info_dump, std::ostream& profile_dump) { + std::string spirv_cache_filename = shader_id + ".spv "; + std::filesystem::path spirv_cache_file_path = shader_cache_dir / spirv_cache_filename; + Common::FS::IOFile shader_cache_file(spirv_cache_file_path, Common::FS::FileAccessMode::Write); + shader_cache_file.WriteSpan(std::span(spv)); + + std::filesystem::path resources_dump_file_path = shader_cache_dir / (shader_id + ".resources"); + Common::FS::IOFile resources_dump_file(resources_dump_file_path, Common::FS::FileAccessMode::Write); + // Schreibe beide Streams nacheinander in die Ressourcen-Datei + std::ostringstream info_stream, profile_stream; + info_stream << info_dump.rdbuf(); + profile_stream << profile_dump.rdbuf(); + + // Schreibe zuerst die Größe des info-Dumps, dann die Daten + u32 info_size = static_cast(info_stream.str().size()); + resources_dump_file.WriteString(std::span(info_stream.str().data(), info_size)); + + // Schreibe danach die Größe des profile-Dumps, dann die Daten + u32 profile_size = static_cast(profile_stream.str().size()); + resources_dump_file.WriteString( + std::span(profile_stream.str().data(), profile_size)); + + +} + +} // namespace ShaderCache \ No newline at end of file diff --git a/src/video_core/renderer_vulkan/shader_cache.h b/src/video_core/renderer_vulkan/shader_cache.h index e69de29bb..0ae35ed2c 100644 --- a/src/video_core/renderer_vulkan/shader_cache.h +++ b/src/video_core/renderer_vulkan/shader_cache.h @@ -0,0 +1,20 @@ +#pragma once + +#include +#include +#include +#include +#include "shader_recompiler/info.h" + +namespace ShaderCache { + +std::string CreateShaderID(u64 pgm_hash, size_t perm_idx, std::ostream& info_dump, + std::ostream& profile_dump); +void DumpInfo(std::ostream& info_dump, Shader::Info info); +void DumpProfile(std::ostream& profile_dump, Shader::Profile profile); +bool CheckShaderCache(std::string shader_id); +bool GetShader(std::string shader_id); +void AddShader(std::string shader_id, std::vector spv, std::ostream& info_dump, + std::ostream& profile_dump); + +} // namespace ShaderCache diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 0d5fe8a69..ab0f9f3f8 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -12,6 +12,7 @@ #include "shader_recompiler/info.h" #include "shader_recompiler/recompiler.h" #include "shader_recompiler/runtime_info.h" +#include "video_core/renderer_vulkan/shader_cache.h" #include "video_core/renderer_vulkan/vk_instance.h" #include "video_core/renderer_vulkan/vk_pipeline_cache.h" #include "video_core/renderer_vulkan/vk_presenter.h" @@ -492,30 +493,30 @@ vk::ShaderModule PipelineCache::CompileModule(Shader::Info& info, Shader::Runtim perm_idx != 0 ? "(permutation)" : ""); DumpShader(code, info.pgm_hash, info.stage, perm_idx, "bin"); + std::ostringstream info_dump, profile_dump; + ::ShaderCache::DumpInfo(info_dump, info); + ::ShaderCache::DumpProfile(profile_dump, profile); + std::string shader_id = ::ShaderCache::CreateShaderID(info.pgm_hash, perm_idx, info_dump, profile_dump); + ::ShaderCache::AddShader(shader_id, std::vector{}, info_dump, profile_dump); + LOG_INFO(Render_Vulkan, "Shader ID: {}", shader_id); + const auto ir_program = Shader::TranslateProgram(code, pools, info, runtime_info, profile); std::string shader_name = GetShaderName(info.stage, info.pgm_hash, perm_idx); - std::string spirv_cache_filename = - shader_name + "_" + Common::g_scm_rev + ".spv "; - std::filesystem::path spirv_cache_file_path = shader_cache_dir / spirv_cache_filename; std::vector spv; - if (std::filesystem::exists(spirv_cache_file_path)) { - Common::FS::IOFile spirv_cache_file(spirv_cache_file_path, Common::FS::FileAccessMode::Read); - spv.resize(spirv_cache_file.GetSize() / sizeof(u32)); - spirv_cache_file.Read(spv); - LOG_INFO(Render_Vulkan, "Loaded SPIR-V from cache: {}", spirv_cache_file_path.string()); + if (::ShaderCache::CheckShaderCache(shader_id)) { + LOG_INFO(Render_Vulkan, "Loaded SPIR-V from cache"); } else { spv = Shader::Backend::SPIRV::EmitSPIRV(profile, runtime_info, ir_program, binding); DumpShader(spv, info.pgm_hash, info.stage, perm_idx, "spv"); - Common::FS::IOFile shader_cache_file(spirv_cache_file_path, Common::FS::FileAccessMode::Write); - shader_cache_file.WriteSpan(std::span(spv)); - LOG_INFO(Render_Vulkan, "Compiled SPIR-V and stored in cache: {}", spirv_cache_file_path.string()); + + LOG_INFO(Render_Vulkan, "Compiled SPIR-V and stored in cache"); } vk::ShaderModule module; From bde3873781c79e37377243d7e57daf625a5defbc Mon Sep 17 00:00:00 2001 From: Fire Cube Date: Wed, 30 Apr 2025 23:02:05 +0200 Subject: [PATCH 05/27] more --- .../renderer_vulkan/shader_cache.cpp | 30 +++++++++++-------- src/video_core/renderer_vulkan/shader_cache.h | 4 +-- .../renderer_vulkan/vk_pipeline_cache.cpp | 10 +++---- 3 files changed, 25 insertions(+), 19 deletions(-) diff --git a/src/video_core/renderer_vulkan/shader_cache.cpp b/src/video_core/renderer_vulkan/shader_cache.cpp index 63db08b03..cce789b45 100644 --- a/src/video_core/renderer_vulkan/shader_cache.cpp +++ b/src/video_core/renderer_vulkan/shader_cache.cpp @@ -13,11 +13,11 @@ namespace ShaderCache { const auto shader_cache_dir = Common::FS::GetUserPath(Common::FS::PathType::ShaderDir) / "cache"; -std::string CreateShaderID(u64 pgm_hash, size_t perm_idx, std::ostream& info_dump, std::ostream& profile_dump) { +std::string CreateShaderID(u64 pgm_hash, size_t perm_idx, std::ostream& info_serialized, std::ostream& profile_serialized) { std::ostringstream info_stream, profile_stream; info_stream << pgm_hash << perm_idx; - info_stream << info_dump.rdbuf(); - profile_stream << profile_dump.rdbuf(); + info_stream << info_serialized.rdbuf(); + profile_stream << profile_serialized.rdbuf(); std::string combined_data = info_stream.str() + profile_stream.str(); @@ -26,12 +26,20 @@ std::string CreateShaderID(u64 pgm_hash, size_t perm_idx, std::ostream& info_dum return std::to_string(shader_id); } -void DumpInfo(std::ostream& info_dump, Shader::Info info) { - writeBin(info_dump, info.mrt_mask); +void SerializeInfo(std::ostream& info_serialized, Shader::Info info) { + writeBin(info_serialized, info.mrt_mask); } -void DumpProfile(std::ostream& profile_dump, Shader::Profile profile) { - writeBin(profile_dump, profile.has_broken_spirv_clamp); +void DeserializeInfo(std::istream& info_serialized, Shader::Info& info) { + readBin(info_serialized, info.mrt_mask); +} + +void SerializeProfile(std::ostream& profile_serialized, Shader::Profile profile) { + writeBin(profile_serialized, profile.has_broken_spirv_clamp); +} + +void DeserializeProfile(std::istream& profile_serialized, Shader::Profile& profile) { + readBin(profile_serialized, profile.has_broken_spirv_clamp); } bool CheckShaderCache(std::string shader_id) { @@ -48,7 +56,7 @@ bool GetShader(std::string shader_id) { spirv_cache_file.Read(spv); } -void AddShader(std::string shader_id, std::vector spv, std::ostream& info_dump, std::ostream& profile_dump) { +void AddShader(std::string shader_id, std::vector spv, std::ostream& info_serialized, std::ostream& profile_serialized) { std::string spirv_cache_filename = shader_id + ".spv "; std::filesystem::path spirv_cache_file_path = shader_cache_dir / spirv_cache_filename; Common::FS::IOFile shader_cache_file(spirv_cache_file_path, Common::FS::FileAccessMode::Write); @@ -58,8 +66,8 @@ void AddShader(std::string shader_id, std::vector spv, std::ostream& info_d Common::FS::IOFile resources_dump_file(resources_dump_file_path, Common::FS::FileAccessMode::Write); // Schreibe beide Streams nacheinander in die Ressourcen-Datei std::ostringstream info_stream, profile_stream; - info_stream << info_dump.rdbuf(); - profile_stream << profile_dump.rdbuf(); + info_stream << info_serialized.rdbuf(); + profile_stream << profile_serialized.rdbuf(); // Schreibe zuerst die Größe des info-Dumps, dann die Daten u32 info_size = static_cast(info_stream.str().size()); @@ -69,8 +77,6 @@ void AddShader(std::string shader_id, std::vector spv, std::ostream& info_d u32 profile_size = static_cast(profile_stream.str().size()); resources_dump_file.WriteString( std::span(profile_stream.str().data(), profile_size)); - - } } // namespace ShaderCache \ No newline at end of file diff --git a/src/video_core/renderer_vulkan/shader_cache.h b/src/video_core/renderer_vulkan/shader_cache.h index 0ae35ed2c..c789eb855 100644 --- a/src/video_core/renderer_vulkan/shader_cache.h +++ b/src/video_core/renderer_vulkan/shader_cache.h @@ -10,8 +10,8 @@ namespace ShaderCache { std::string CreateShaderID(u64 pgm_hash, size_t perm_idx, std::ostream& info_dump, std::ostream& profile_dump); -void DumpInfo(std::ostream& info_dump, Shader::Info info); -void DumpProfile(std::ostream& profile_dump, Shader::Profile profile); +void SerializeInfo(std::ostream& info_dump, Shader::Info info); +void SerializeProfile(std::ostream& profile_dump, Shader::Profile profile); bool CheckShaderCache(std::string shader_id); bool GetShader(std::string shader_id); void AddShader(std::string shader_id, std::vector spv, std::ostream& info_dump, diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index ab0f9f3f8..ca6b19c91 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -493,11 +493,11 @@ vk::ShaderModule PipelineCache::CompileModule(Shader::Info& info, Shader::Runtim perm_idx != 0 ? "(permutation)" : ""); DumpShader(code, info.pgm_hash, info.stage, perm_idx, "bin"); - std::ostringstream info_dump, profile_dump; - ::ShaderCache::DumpInfo(info_dump, info); - ::ShaderCache::DumpProfile(profile_dump, profile); - std::string shader_id = ::ShaderCache::CreateShaderID(info.pgm_hash, perm_idx, info_dump, profile_dump); - ::ShaderCache::AddShader(shader_id, std::vector{}, info_dump, profile_dump); + std::ostringstream info_serialized, profile_serialized; + ::ShaderCache::SerializeInfo(info_serialized, info); + ::ShaderCache::SerializeProfile(profile_serialized, profile); + std::string shader_id = ::ShaderCache::CreateShaderID(info.pgm_hash, perm_idx, info_serialized, profile_serialized); + ::ShaderCache::AddShader(shader_id, std::vector{}, info_serialized, profile_serialized); LOG_INFO(Render_Vulkan, "Shader ID: {}", shader_id); const auto ir_program = Shader::TranslateProgram(code, pools, info, runtime_info, profile); From 24f17f59f249dd146148ba0c41765c91eb815e27 Mon Sep 17 00:00:00 2001 From: Fire Cube Date: Thu, 1 May 2025 07:11:21 +0200 Subject: [PATCH 06/27] more --- .../renderer_vulkan/shader_cache.cpp | 28 ++++++++++++++++++- src/video_core/renderer_vulkan/shader_cache.h | 13 +++++---- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/src/video_core/renderer_vulkan/shader_cache.cpp b/src/video_core/renderer_vulkan/shader_cache.cpp index cce789b45..8eaa72ad1 100644 --- a/src/video_core/renderer_vulkan/shader_cache.cpp +++ b/src/video_core/renderer_vulkan/shader_cache.cpp @@ -46,7 +46,7 @@ bool CheckShaderCache(std::string shader_id) { return 0; } -bool GetShader(std::string shader_id) { +void GetShader(std::string shader_id, Shader::Info& info, Shader::Profile& profile) { std::string spirv_cache_filename = shader_id + ".spv "; std::filesystem::path spirv_cache_file_path = shader_cache_dir / spirv_cache_filename; Common::FS::IOFile spirv_cache_file(spirv_cache_file_path, @@ -54,6 +54,30 @@ bool GetShader(std::string shader_id) { std::vector spv; spv.resize(spirv_cache_file.GetSize() / sizeof(u32)); spirv_cache_file.Read(spv); + spirv_cache_file.Close(); + + std::filesystem::path resources_dump_file_path = shader_cache_dir / (shader_id + ".resources"); + Common::FS::IOFile resources_dump_file(resources_dump_file_path, + Common::FS::FileAccessMode::Read); + + // Lese die Ressourcendaten + std::vector resources_data; + resources_data.resize(resources_dump_file.GetSize()); + resources_dump_file.Read(resources_data); + resources_dump_file.Close(); + + // Verarbeite die gespeicherten Daten + std::istringstream combined_stream(std::string(resources_data.begin(), resources_data.end())); + + // Deserialisiere info und profile + std::istringstream info_stream; + info_stream.str(std::string(resources_data.begin(), resources_data.end())); + DeserializeInfo(info_stream, info); + + std::istringstream profile_stream; + profile_stream.str( + std::string(resources_data.begin() + info_stream.tellg(), resources_data.end())); + DeserializeProfile(profile_stream, profile); } void AddShader(std::string shader_id, std::vector spv, std::ostream& info_serialized, std::ostream& profile_serialized) { @@ -77,6 +101,8 @@ void AddShader(std::string shader_id, std::vector spv, std::ostream& info_s u32 profile_size = static_cast(profile_stream.str().size()); resources_dump_file.WriteString( std::span(profile_stream.str().data(), profile_size)); + + resources_dump_file.Close(); } } // namespace ShaderCache \ No newline at end of file diff --git a/src/video_core/renderer_vulkan/shader_cache.h b/src/video_core/renderer_vulkan/shader_cache.h index c789eb855..4f885a99d 100644 --- a/src/video_core/renderer_vulkan/shader_cache.h +++ b/src/video_core/renderer_vulkan/shader_cache.h @@ -10,11 +10,14 @@ namespace ShaderCache { std::string CreateShaderID(u64 pgm_hash, size_t perm_idx, std::ostream& info_dump, std::ostream& profile_dump); -void SerializeInfo(std::ostream& info_dump, Shader::Info info); -void SerializeProfile(std::ostream& profile_dump, Shader::Profile profile); +void SerializeInfo(std::ostream& info_serialized, Shader::Info info); +void SerializeProfile(std::ostream& profile_serialized, Shader::Profile profile); +void DeserializeInfo(std::istream& info_serialized, Shader::Info& info); +void DeserializeProfile(std::istream& profile_serialized, Shader::Profile& profile); + bool CheckShaderCache(std::string shader_id); -bool GetShader(std::string shader_id); -void AddShader(std::string shader_id, std::vector spv, std::ostream& info_dump, - std::ostream& profile_dump); +void GetShader(std::string shader_id, Shader::Info& info, Shader::Profile& profile); +void AddShader(std::string shader_id, std::vector spv, std::ostream& info_serialized, + std::ostream& profile_serialized); } // namespace ShaderCache From b32ba2918b2b82a0628a2d0a8e289a805c85b900 Mon Sep 17 00:00:00 2001 From: Fire Cube Date: Thu, 1 May 2025 18:50:20 +0200 Subject: [PATCH 07/27] fix filewriting --- .../renderer_vulkan/shader_cache.cpp | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/video_core/renderer_vulkan/shader_cache.cpp b/src/video_core/renderer_vulkan/shader_cache.cpp index 8eaa72ad1..65df6e295 100644 --- a/src/video_core/renderer_vulkan/shader_cache.cpp +++ b/src/video_core/renderer_vulkan/shader_cache.cpp @@ -81,26 +81,29 @@ void GetShader(std::string shader_id, Shader::Info& info, Shader::Profile& profi } void AddShader(std::string shader_id, std::vector spv, std::ostream& info_serialized, std::ostream& profile_serialized) { - std::string spirv_cache_filename = shader_id + ".spv "; + // SPIR-V-Datei speichern + std::string spirv_cache_filename = shader_id + ".spv"; std::filesystem::path spirv_cache_file_path = shader_cache_dir / spirv_cache_filename; Common::FS::IOFile shader_cache_file(spirv_cache_file_path, Common::FS::FileAccessMode::Write); shader_cache_file.WriteSpan(std::span(spv)); + shader_cache_file.Close(); + // Resources-Datei vorbereiten std::filesystem::path resources_dump_file_path = shader_cache_dir / (shader_id + ".resources"); - Common::FS::IOFile resources_dump_file(resources_dump_file_path, Common::FS::FileAccessMode::Write); - // Schreibe beide Streams nacheinander in die Ressourcen-Datei - std::ostringstream info_stream, profile_stream; - info_stream << info_serialized.rdbuf(); - profile_stream << profile_serialized.rdbuf(); + Common::FS::IOFile resources_dump_file(resources_dump_file_path, + Common::FS::FileAccessMode::Write); - // Schreibe zuerst die Größe des info-Dumps, dann die Daten - u32 info_size = static_cast(info_stream.str().size()); - resources_dump_file.WriteString(std::span(info_stream.str().data(), info_size)); + // Die Streams müssen zurückgesetzt werden, bevor wir sie lesen können + if (std::ostringstream* info_oss = dynamic_cast(&info_serialized)) { + std::string info_data = info_oss->str(); + resources_dump_file.WriteSpan(std::span(info_data.data(), info_data.size())); + } - // Schreibe danach die Größe des profile-Dumps, dann die Daten - u32 profile_size = static_cast(profile_stream.str().size()); - resources_dump_file.WriteString( - std::span(profile_stream.str().data(), profile_size)); + if (std::ostringstream* profile_oss = dynamic_cast(&profile_serialized)) { + std::string profile_data = profile_oss->str(); + resources_dump_file.WriteSpan( + std::span(profile_data.data(), profile_data.size())); + } resources_dump_file.Close(); } From 3eb8000b75789ef7fadabf348369decab3d2a4b3 Mon Sep 17 00:00:00 2001 From: Fire Cube Date: Thu, 1 May 2025 20:58:38 +0200 Subject: [PATCH 08/27] some progress --- src/common/binary_helper.h | 30 ++--- .../renderer_vulkan/shader_cache.cpp | 105 +++++++++++++----- src/video_core/renderer_vulkan/shader_cache.h | 10 +- .../renderer_vulkan/vk_pipeline_cache.cpp | 15 ++- 4 files changed, 102 insertions(+), 58 deletions(-) diff --git a/src/common/binary_helper.h b/src/common/binary_helper.h index cfcc213ae..564896f11 100644 --- a/src/common/binary_helper.h +++ b/src/common/binary_helper.h @@ -2,44 +2,46 @@ #include #include +#include "common/logging/log.h" using u32 = uint32_t; template -void writeBin(std::ostream& os, const T& v) { - os.write(reinterpret_cast(&v), sizeof(T)); +void writeBin(std::ostream& os, const T& v) { + LOG_INFO(Render_Recompiler, "BinaryHelper: Pos: {}", static_cast(os.tellp())); + os.write(reinterpret_cast(&v), sizeof(T)); } template void readBin(std::istream& is, T& v) { - is.read(reinterpret_cast(&v), sizeof(T)); + is.read(reinterpret_cast(&v), sizeof(T)); } // Spezialfall für Arrays/Blöcke template void writeBlock(std::ostream& os, const T* data, size_t count) { - os.write(reinterpret_cast(data), sizeof(T) * count); + os.write(reinterpret_cast(data), sizeof(T) * count); } template void readBlock(std::istream& is, T* data, size_t count) { - is.read(reinterpret_cast(data), sizeof(T) * count); + is.read(reinterpret_cast(data), sizeof(T) * count); } // Spezialfall für Container template void writeContainer(std::ostream& os, const std::vector& v) { - u32 n = static_cast(v.size()); - writeBin(os, n); - if (n) - writeBlock(os, v.data(), n); + u32 n = static_cast(v.size()); + writeBin(os, n); + if (n) + writeBlock(os, v.data(), n); } template void readContainer(std::istream& is, std::vector& v) { - u32 n; - readBin(is, n); - v.resize(n); - if (n) - readBlock(is, v.data(), n); + u32 n; + readBin(is, n); + v.resize(n); + if (n) + readBlock(is, v.data(), n); } \ No newline at end of file diff --git a/src/video_core/renderer_vulkan/shader_cache.cpp b/src/video_core/renderer_vulkan/shader_cache.cpp index 65df6e295..4097b140a 100644 --- a/src/video_core/renderer_vulkan/shader_cache.cpp +++ b/src/video_core/renderer_vulkan/shader_cache.cpp @@ -5,28 +5,93 @@ #include "common/path_util.h" #include "common/io_file.h" #include "common/binary_helper.h" +#include "common/logging/log.h" #include "shader_recompiler/info.h" using u64 = uint64_t; +using u32 = uint32_t; namespace ShaderCache { const auto shader_cache_dir = Common::FS::GetUserPath(Common::FS::PathType::ShaderDir) / "cache"; -std::string CreateShaderID(u64 pgm_hash, size_t perm_idx, std::ostream& info_serialized, std::ostream& profile_serialized) { - std::ostringstream info_stream, profile_stream; - info_stream << pgm_hash << perm_idx; - info_stream << info_serialized.rdbuf(); - profile_stream << profile_serialized.rdbuf(); - - std::string combined_data = info_stream.str() + profile_stream.str(); - +std::string CreateShaderID(u64 pgm_hash, size_t perm_idx, std::ostream& info_serialized) { + std::ostringstream data_stream; + data_stream << pgm_hash << perm_idx; + data_stream << info_serialized.rdbuf(); std::hash hasher; - size_t shader_id = hasher(combined_data); + size_t shader_id = hasher(data_stream.str()); return std::to_string(shader_id); } void SerializeInfo(std::ostream& info_serialized, Shader::Info info) { + // UD Mask + writeBin(info_serialized, info.ud_mask.mask); + + // Buffer-Resources + u32 count = static_cast(info.buffers.size()); + writeBin(info_serialized, count); // Buffer Amount + LOG_INFO(Render_Recompiler, "ShaderCache: Buffer count: {}", info.buffers.size()); + + for (const auto& buffer : info.buffers) { + writeBin(info_serialized, buffer.sharp_idx); + writeBin(info_serialized, static_cast(buffer.used_types)); + writeBin(info_serialized, static_cast(buffer.buffer_type)); + writeBin(info_serialized, buffer.instance_attrib); + writeBin(info_serialized, static_cast(buffer.is_written ? 1 : 0)); + writeBin(info_serialized, static_cast(buffer.is_formatted ? 1 : 0)); + } + + // Image-Resources + count = static_cast(info.images.size()); + writeBin(info_serialized, count); // Image Amount + LOG_INFO(Render_Recompiler, "ShaderCache: Image count: {}", info.images.size()); + for (const auto& image : info.images) { + writeBin(info_serialized, image.sharp_idx); + writeBin(info_serialized, static_cast(image.is_depth ? 1 : 0)); + writeBin(info_serialized, static_cast(image.is_atomic ? 1 : 0)); + writeBin(info_serialized, static_cast(image.is_array ? 1 : 0)); + writeBin(info_serialized, static_cast(image.is_written ? 1 : 0)); + } + + // Sampler-Resources + count = static_cast(info.samplers.size()); + writeBin(info_serialized, count); // Sampler Amount + LOG_INFO(Render_Recompiler, "ShaderCache: Sampler count: {}", info.samplers.size()); + for (const auto& sampler : info.samplers) { + writeBin(info_serialized, sampler.sharp_idx); + } + + // FMask-Resources + count = static_cast(info.fmasks.size()); + writeBin(info_serialized, count); // FMask Amount + LOG_INFO(Render_Recompiler, "ShaderCache: FMask count: {}", info.fmasks.size()); + for (const auto& fmask : info.fmasks) { + writeBin(info_serialized, fmask.sharp_idx); + } + + // GS Copy Data + writeBin(info_serialized, info.gs_copy_data.num_attrs); + + u32 mapCount = static_cast(info.gs_copy_data.attr_map.size()); + writeBin(info_serialized, mapCount); + + for (auto const& [loc, idx] : info.gs_copy_data.attr_map) { + writeBin(info_serialized, loc); + writeBin(info_serialized, idx); + } + + // SRT Info + u32 srtCount = static_cast(info.srt_info.srt_reservations.size()); + writeBin(info_serialized, count); + + for (const auto& res : info.srt_info.srt_reservations) { + writeBin(info_serialized, res.sgpr_base); + writeBin(info_serialized, res.dword_offset); + writeBin(info_serialized, res.num_dwords); + } + + // MRT Mask writeBin(info_serialized, info.mrt_mask); } @@ -34,19 +99,11 @@ void DeserializeInfo(std::istream& info_serialized, Shader::Info& info) { readBin(info_serialized, info.mrt_mask); } -void SerializeProfile(std::ostream& profile_serialized, Shader::Profile profile) { - writeBin(profile_serialized, profile.has_broken_spirv_clamp); -} - -void DeserializeProfile(std::istream& profile_serialized, Shader::Profile& profile) { - readBin(profile_serialized, profile.has_broken_spirv_clamp); -} - bool CheckShaderCache(std::string shader_id) { return 0; } -void GetShader(std::string shader_id, Shader::Info& info, Shader::Profile& profile) { +void GetShader(std::string shader_id, Shader::Info& info) { std::string spirv_cache_filename = shader_id + ".spv "; std::filesystem::path spirv_cache_file_path = shader_cache_dir / spirv_cache_filename; Common::FS::IOFile spirv_cache_file(spirv_cache_file_path, @@ -74,13 +131,9 @@ void GetShader(std::string shader_id, Shader::Info& info, Shader::Profile& profi info_stream.str(std::string(resources_data.begin(), resources_data.end())); DeserializeInfo(info_stream, info); - std::istringstream profile_stream; - profile_stream.str( - std::string(resources_data.begin() + info_stream.tellg(), resources_data.end())); - DeserializeProfile(profile_stream, profile); } -void AddShader(std::string shader_id, std::vector spv, std::ostream& info_serialized, std::ostream& profile_serialized) { +void AddShader(std::string shader_id, std::vector spv, std::ostream& info_serialized) { // SPIR-V-Datei speichern std::string spirv_cache_filename = shader_id + ".spv"; std::filesystem::path spirv_cache_file_path = shader_cache_dir / spirv_cache_filename; @@ -99,12 +152,6 @@ void AddShader(std::string shader_id, std::vector spv, std::ostream& info_s resources_dump_file.WriteSpan(std::span(info_data.data(), info_data.size())); } - if (std::ostringstream* profile_oss = dynamic_cast(&profile_serialized)) { - std::string profile_data = profile_oss->str(); - resources_dump_file.WriteSpan( - std::span(profile_data.data(), profile_data.size())); - } - resources_dump_file.Close(); } diff --git a/src/video_core/renderer_vulkan/shader_cache.h b/src/video_core/renderer_vulkan/shader_cache.h index 4f885a99d..2b5c1ae75 100644 --- a/src/video_core/renderer_vulkan/shader_cache.h +++ b/src/video_core/renderer_vulkan/shader_cache.h @@ -8,16 +8,12 @@ namespace ShaderCache { -std::string CreateShaderID(u64 pgm_hash, size_t perm_idx, std::ostream& info_dump, - std::ostream& profile_dump); +std::string CreateShaderID(u64 pgm_hash, size_t perm_idx, std::ostream& info_dump); void SerializeInfo(std::ostream& info_serialized, Shader::Info info); -void SerializeProfile(std::ostream& profile_serialized, Shader::Profile profile); void DeserializeInfo(std::istream& info_serialized, Shader::Info& info); -void DeserializeProfile(std::istream& profile_serialized, Shader::Profile& profile); bool CheckShaderCache(std::string shader_id); -void GetShader(std::string shader_id, Shader::Info& info, Shader::Profile& profile); -void AddShader(std::string shader_id, std::vector spv, std::ostream& info_serialized, - std::ostream& profile_serialized); +void GetShader(std::string shader_id, Shader::Info& info); +void AddShader(std::string shader_id, std::vector spv, std::ostream& info_serialized); } // namespace ShaderCache diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index ca6b19c91..cb4a6c0ce 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -493,12 +493,6 @@ vk::ShaderModule PipelineCache::CompileModule(Shader::Info& info, Shader::Runtim perm_idx != 0 ? "(permutation)" : ""); DumpShader(code, info.pgm_hash, info.stage, perm_idx, "bin"); - std::ostringstream info_serialized, profile_serialized; - ::ShaderCache::SerializeInfo(info_serialized, info); - ::ShaderCache::SerializeProfile(profile_serialized, profile); - std::string shader_id = ::ShaderCache::CreateShaderID(info.pgm_hash, perm_idx, info_serialized, profile_serialized); - ::ShaderCache::AddShader(shader_id, std::vector{}, info_serialized, profile_serialized); - LOG_INFO(Render_Vulkan, "Shader ID: {}", shader_id); const auto ir_program = Shader::TranslateProgram(code, pools, info, runtime_info, profile); @@ -508,11 +502,16 @@ vk::ShaderModule PipelineCache::CompileModule(Shader::Info& info, Shader::Runtim std::vector spv; - if (::ShaderCache::CheckShaderCache(shader_id)) { + if (false){ //(::ShaderCache::CheckShaderCache(shader_id)) { LOG_INFO(Render_Vulkan, "Loaded SPIR-V from cache"); } else { spv = Shader::Backend::SPIRV::EmitSPIRV(profile, runtime_info, ir_program, binding); - + std::ostringstream info_serialized; + ::ShaderCache::SerializeInfo(info_serialized, info); + std::string shader_id = + ::ShaderCache::CreateShaderID(info.pgm_hash, perm_idx, info_serialized); + ::ShaderCache::AddShader(shader_id, spv, info_serialized); + LOG_INFO(Render_Vulkan, "Shader ID: {}", shader_id); DumpShader(spv, info.pgm_hash, info.stage, perm_idx, "spv"); From a500b98e9bcc2a392acfd2370c31f50387834127 Mon Sep 17 00:00:00 2001 From: Fire Cube Date: Sat, 3 May 2025 15:29:57 +0200 Subject: [PATCH 09/27] more --- src/common/binary_helper.h | 31 +- src/common/hash.h | 9 +- .../renderer_vulkan/shader_cache.cpp | 587 +++++++++++++++++- src/video_core/renderer_vulkan/shader_cache.h | 8 +- .../renderer_vulkan/vk_pipeline_cache.cpp | 35 +- .../renderer_vulkan/vk_pipeline_cache.h | 2 +- 6 files changed, 582 insertions(+), 90 deletions(-) diff --git a/src/common/binary_helper.h b/src/common/binary_helper.h index 564896f11..de1bb9b78 100644 --- a/src/common/binary_helper.h +++ b/src/common/binary_helper.h @@ -15,33 +15,4 @@ void writeBin(std::ostream& os, const T& v) { template void readBin(std::istream& is, T& v) { is.read(reinterpret_cast(&v), sizeof(T)); -} - -// Spezialfall für Arrays/Blöcke -template -void writeBlock(std::ostream& os, const T* data, size_t count) { - os.write(reinterpret_cast(data), sizeof(T) * count); -} - -template -void readBlock(std::istream& is, T* data, size_t count) { - is.read(reinterpret_cast(data), sizeof(T) * count); -} - -// Spezialfall für Container -template -void writeContainer(std::ostream& os, const std::vector& v) { - u32 n = static_cast(v.size()); - writeBin(os, n); - if (n) - writeBlock(os, v.data(), n); -} - -template -void readContainer(std::istream& is, std::vector& v) { - u32 n; - readBin(is, n); - v.resize(n); - if (n) - readBlock(is, v.data(), n); -} \ No newline at end of file +} \ No newline at end of file diff --git a/src/common/hash.h b/src/common/hash.h index d5cacedd7..b29cfb90f 100644 --- a/src/common/hash.h +++ b/src/common/hash.h @@ -5,10 +5,7 @@ #include "common/types.h" -[[nodiscard]] inline u64 HashCombine(const u64 seed, const u64 hash) { - return seed ^ (hash + 0x9e3779b9 + (seed << 12) + (seed >> 4)); -} - -[[nodiscard]] inline u32 HashCombine(const u32 seed, const u32 hash) { - return seed ^ (hash + 0x9e3779b9 + (seed << 6) + (seed >> 2)); +template +T HashCombine(const T& seed, const U& value) { + return seed ^ (static_cast(value) + 0x9e3779b9 + (seed << 6) + (seed >> 2)); } \ No newline at end of file diff --git a/src/video_core/renderer_vulkan/shader_cache.cpp b/src/video_core/renderer_vulkan/shader_cache.cpp index 4097b140a..b256d2cda 100644 --- a/src/video_core/renderer_vulkan/shader_cache.cpp +++ b/src/video_core/renderer_vulkan/shader_cache.cpp @@ -1,12 +1,14 @@ #include #include -#include #include +#include "common/hash.h" #include "common/path_util.h" #include "common/io_file.h" #include "common/binary_helper.h" #include "common/logging/log.h" +#include "shader_recompiler/ir/type.h" #include "shader_recompiler/info.h" +#include "shader_recompiler/specialization.h" using u64 = uint64_t; using u32 = uint32_t; @@ -15,13 +17,242 @@ namespace ShaderCache { const auto shader_cache_dir = Common::FS::GetUserPath(Common::FS::PathType::ShaderDir) / "cache"; -std::string CreateShaderID(u64 pgm_hash, size_t perm_idx, std::ostream& info_serialized) { - std::ostringstream data_stream; - data_stream << pgm_hash << perm_idx; - data_stream << info_serialized.rdbuf(); - std::hash hasher; - size_t shader_id = hasher(data_stream.str()); - return std::to_string(shader_id); +u64 CalculateSpecializationHash(const Shader::StageSpecialization& spec) { + u64 hash = 0; + + // Start mit dem Hash der RuntimeInfo + // Die RuntimeInfo enthält verschiedene Unions, daher müssen wir basierend auf dem Stage-Typ + // hashen + const auto& runtime_info = spec.runtime_info; + hash = HashCombine(hash, static_cast(runtime_info.stage)); + hash = HashCombine(hash, runtime_info.num_user_data); + hash = HashCombine(hash, runtime_info.num_input_vgprs); + hash = HashCombine(hash, runtime_info.num_allocated_vgprs); + hash = HashCombine(hash, static_cast(runtime_info.fp_denorm_mode32)); + hash = HashCombine(hash, static_cast(runtime_info.fp_round_mode32)); + + // Abhängig vom Stage-Typ die spezifischen RuntimeInfo-Felder hashen + switch (runtime_info.stage) { + case Shader::Stage::Local: + hash = HashCombine(hash, runtime_info.ls_info.ls_stride); + hash = HashCombine(hash, runtime_info.ls_info.links_with_tcs); + break; + case Shader::Stage::Export: + hash = HashCombine(hash, runtime_info.es_info.vertex_data_size); + break; + case Shader::Stage::Vertex: + hash = HashCombine(hash, runtime_info.vs_info.num_outputs); + // Hash der Output-Maps + for (size_t i = 0; + i < runtime_info.vs_info.num_outputs && i < runtime_info.vs_info.outputs.size(); ++i) { + const auto& output_map = runtime_info.vs_info.outputs[i]; + for (const auto& output : output_map) { + hash = HashCombine(hash, static_cast(output)); + } + } + hash = HashCombine(hash, runtime_info.vs_info.emulate_depth_negative_one_to_one); + hash = HashCombine(hash, runtime_info.vs_info.clip_disable); + hash = HashCombine(hash, static_cast(runtime_info.vs_info.tess_type)); + hash = HashCombine(hash, static_cast(runtime_info.vs_info.tess_topology)); + hash = HashCombine(hash, static_cast(runtime_info.vs_info.tess_partitioning)); + hash = HashCombine(hash, runtime_info.vs_info.hs_output_cp_stride); + break; + case Shader::Stage::Hull: + hash = HashCombine(hash, runtime_info.hs_info.num_input_control_points); + hash = HashCombine(hash, runtime_info.hs_info.num_threads); + hash = HashCombine(hash, static_cast(runtime_info.hs_info.tess_type)); + hash = HashCombine(hash, runtime_info.hs_info.ls_stride); + hash = HashCombine(hash, runtime_info.hs_info.hs_output_cp_stride); + hash = HashCombine(hash, runtime_info.hs_info.hs_output_base); + break; + case Shader::Stage::Geometry: + hash = HashCombine(hash, runtime_info.gs_info.num_invocations); + hash = HashCombine(hash, runtime_info.gs_info.output_vertices); + hash = HashCombine(hash, runtime_info.gs_info.in_vertex_data_size); + hash = HashCombine(hash, runtime_info.gs_info.out_vertex_data_size); + hash = HashCombine(hash, static_cast(runtime_info.gs_info.in_primitive)); + // Hash der Output-Primitive-Types für alle Streams + for (const auto& out_prim : runtime_info.gs_info.out_primitive) { + hash = HashCombine(hash, static_cast(out_prim)); + } + hash = HashCombine(hash, runtime_info.gs_info.vs_copy_hash); + break; + case Shader::Stage::Fragment: + hash = HashCombine(hash, runtime_info.fs_info.en_flags.raw); + hash = HashCombine(hash, runtime_info.fs_info.addr_flags.raw); + hash = HashCombine(hash, runtime_info.fs_info.num_inputs); + + // Hash der PS-Inputs + for (u32 i = 0; + i < runtime_info.fs_info.num_inputs && i < runtime_info.fs_info.inputs.size(); ++i) { + const auto& input = runtime_info.fs_info.inputs[i]; + hash = HashCombine(hash, input.param_index); + hash = HashCombine(hash, input.is_default); + hash = HashCombine(hash, input.is_flat); + hash = HashCombine(hash, input.default_value); + } + + // Hash der ColorBuffers + for (const auto& color_buffer : runtime_info.fs_info.color_buffers) { + hash = HashCombine(hash, static_cast(color_buffer.num_format)); + hash = HashCombine(hash, static_cast(color_buffer.num_conversion)); + hash = HashCombine(hash, static_cast(color_buffer.export_format)); + hash = HashCombine(hash, color_buffer.needs_unorm_fixup); + hash = HashCombine(hash, color_buffer.swizzle.r); + hash = HashCombine(hash, color_buffer.swizzle.g); + hash = HashCombine(hash, color_buffer.swizzle.b); + hash = HashCombine(hash, color_buffer.swizzle.a); + } + break; + case Shader::Stage::Compute: + hash = HashCombine(hash, runtime_info.cs_info.shared_memory_size); + for (u32 i = 0; i < 3; ++i) { + hash = HashCombine(hash, runtime_info.cs_info.workgroup_size[i]); + hash = HashCombine(hash, runtime_info.cs_info.tgid_enable[i]); + } + break; + } + + // Hash des FetchShader-Daten + if (spec.fetch_shader_data) { + const auto& fetch_shader = *spec.fetch_shader_data; + hash = HashCombine(hash, fetch_shader.size); + hash = HashCombine(hash, static_cast(fetch_shader.vertex_offset_sgpr)); + hash = HashCombine(hash, static_cast(fetch_shader.instance_offset_sgpr)); + + // Hash der Attribute + for (const auto& attr : fetch_shader.attributes) { + hash = HashCombine(hash, static_cast(attr.semantic)); + hash = HashCombine(hash, static_cast(attr.dest_vgpr)); + hash = HashCombine(hash, static_cast(attr.num_elements)); + hash = HashCombine(hash, static_cast(attr.sgpr_base)); + hash = HashCombine(hash, static_cast(attr.dword_offset)); + hash = HashCombine(hash, static_cast(attr.instance_data)); + } + } + + // Hash der VS-Attribut-Spezialisierungen + for (const auto& vs_attrib : spec.vs_attribs) { + hash = HashCombine(hash, vs_attrib.num_components); + hash = HashCombine(hash, static_cast(vs_attrib.num_class)); + hash = HashCombine(hash, vs_attrib.dst_select.r); + hash = HashCombine(hash, vs_attrib.dst_select.g); + hash = HashCombine(hash, vs_attrib.dst_select.b); + hash = HashCombine(hash, vs_attrib.dst_select.a); + } + + // Hash des Bitsets + const std::string bitset_str = spec.bitset.to_string(); + for (size_t i = 0; i < bitset_str.size(); i += 8) { + size_t end = std::min(i + 8, bitset_str.size()); + std::string chunk = bitset_str.substr(i, end - i); + u8 value = 0; + for (size_t j = 0; j < chunk.size(); ++j) { + if (chunk[j] == '1') { + value |= (1 << j); + } + } + hash = HashCombine(hash, value); + } + + // Hash der Buffer-Spezialisierungen + for (const auto& buffer : spec.buffers) { + hash = HashCombine(hash, buffer.stride); + hash = HashCombine(hash, buffer.is_storage); + hash = HashCombine(hash, buffer.is_formatted); + hash = HashCombine(hash, buffer.swizzle_enable); + + if (buffer.is_formatted) { + hash = HashCombine(hash, buffer.data_format); + hash = HashCombine(hash, buffer.num_format); + hash = HashCombine(hash, buffer.dst_select.r); + hash = HashCombine(hash, buffer.dst_select.g); + hash = HashCombine(hash, buffer.dst_select.b); + hash = HashCombine(hash, buffer.dst_select.a); + hash = HashCombine(hash, static_cast(buffer.num_conversion)); + } + + if (buffer.swizzle_enable) { + hash = HashCombine(hash, buffer.index_stride); + hash = HashCombine(hash, buffer.element_size); + } + } + + // Hash der Bild-Spezialisierungen + for (const auto& image : spec.images) { + hash = HashCombine(hash, static_cast(image.type)); + hash = HashCombine(hash, image.is_integer); + hash = HashCombine(hash, image.is_storage); + hash = HashCombine(hash, image.is_cube); + + if (image.is_storage) { + hash = HashCombine(hash, image.dst_select.r); + hash = HashCombine(hash, image.dst_select.g); + hash = HashCombine(hash, image.dst_select.b); + hash = HashCombine(hash, image.dst_select.a); + } + + hash = HashCombine(hash, static_cast(image.num_conversion)); + } + + // Hash der FMask-Spezialisierungen + for (const auto& fmask : spec.fmasks) { + hash = HashCombine(hash, fmask.width); + hash = HashCombine(hash, fmask.height); + } + + // Hash der Sampler-Spezialisierungen + for (const auto& sampler : spec.samplers) { + hash = HashCombine(hash, sampler.force_unnormalized); + } + + // Hash der Start-Bindings + hash = HashCombine(hash, spec.start.buffer); + hash = HashCombine(hash, spec.start.unified); + hash = HashCombine(hash, spec.start.user_data); + + // Hash vom info pointer + if (spec.info) { + hash = HashCombine(hash, spec.info->pgm_hash); + hash = HashCombine(hash, static_cast(spec.info->stage)); + hash = HashCombine(hash, static_cast(spec.info->l_stage)); + hash = HashCombine(hash, spec.info->has_storage_images); + hash = HashCombine(hash, spec.info->has_discard); + hash = HashCombine(hash, spec.info->has_image_gather); + hash = HashCombine(hash, spec.info->has_image_query); + hash = HashCombine(hash, spec.info->uses_lane_id); + hash = HashCombine(hash, spec.info->uses_group_quad); + hash = HashCombine(hash, spec.info->uses_group_ballot); + hash = HashCombine(hash, spec.info->uses_shared); + hash = HashCombine(hash, spec.info->uses_fp16); + hash = HashCombine(hash, spec.info->uses_fp64); + hash = HashCombine(hash, spec.info->uses_pack_10_11_11); + hash = HashCombine(hash, spec.info->uses_unpack_10_11_11); + hash = HashCombine(hash, spec.info->stores_tess_level_outer); + hash = HashCombine(hash, spec.info->stores_tess_level_inner); + hash = HashCombine(hash, spec.info->translation_failed); + hash = HashCombine(hash, spec.info->has_readconst); + hash = HashCombine(hash, spec.info->mrt_mask); + hash = HashCombine(hash, spec.info->has_fetch_shader); + hash = HashCombine(hash, spec.info->fetch_shader_sgpr_base); + + // Hash der Flags für loads und stores + for (size_t i = 0; i < spec.info->loads.flags.size(); ++i) { + hash = HashCombine(hash, spec.info->loads.flags[i]); + } + + for (size_t i = 0; i < spec.info->stores.flags.size(); ++i) { + hash = HashCombine(hash, spec.info->stores.flags[i]); + } + + // Hash der UserDataMask + hash = HashCombine(hash, spec.info->ud_mask.mask); + + // Hash der uses_patches + hash = HashCombine(hash, spec.info->uses_patches); + } + + return hash; } void SerializeInfo(std::ostream& info_serialized, Shader::Info info) { @@ -29,9 +260,8 @@ void SerializeInfo(std::ostream& info_serialized, Shader::Info info) { writeBin(info_serialized, info.ud_mask.mask); // Buffer-Resources - u32 count = static_cast(info.buffers.size()); - writeBin(info_serialized, count); // Buffer Amount - LOG_INFO(Render_Recompiler, "ShaderCache: Buffer count: {}", info.buffers.size()); + u32 bufferCount = static_cast(info.buffers.size()); + writeBin(info_serialized, bufferCount); // Buffer Amount for (const auto& buffer : info.buffers) { writeBin(info_serialized, buffer.sharp_idx); @@ -43,9 +273,9 @@ void SerializeInfo(std::ostream& info_serialized, Shader::Info info) { } // Image-Resources - count = static_cast(info.images.size()); - writeBin(info_serialized, count); // Image Amount - LOG_INFO(Render_Recompiler, "ShaderCache: Image count: {}", info.images.size()); + u32 imageCount = static_cast(info.images.size()); + writeBin(info_serialized, imageCount); // Image Amount + for (const auto& image : info.images) { writeBin(info_serialized, image.sharp_idx); writeBin(info_serialized, static_cast(image.is_depth ? 1 : 0)); @@ -55,35 +285,36 @@ void SerializeInfo(std::ostream& info_serialized, Shader::Info info) { } // Sampler-Resources - count = static_cast(info.samplers.size()); - writeBin(info_serialized, count); // Sampler Amount - LOG_INFO(Render_Recompiler, "ShaderCache: Sampler count: {}", info.samplers.size()); + u32 samplerCount = static_cast(info.samplers.size()); + writeBin(info_serialized, samplerCount); // Sampler Amount + for (const auto& sampler : info.samplers) { writeBin(info_serialized, sampler.sharp_idx); } // FMask-Resources - count = static_cast(info.fmasks.size()); - writeBin(info_serialized, count); // FMask Amount - LOG_INFO(Render_Recompiler, "ShaderCache: FMask count: {}", info.fmasks.size()); + u32 fmaskCount = static_cast(info.fmasks.size()); + writeBin(info_serialized, fmaskCount); // FMask Amount + for (const auto& fmask : info.fmasks) { writeBin(info_serialized, fmask.sharp_idx); } // GS Copy Data - writeBin(info_serialized, info.gs_copy_data.num_attrs); - u32 mapCount = static_cast(info.gs_copy_data.attr_map.size()); writeBin(info_serialized, mapCount); - for (auto const& [loc, idx] : info.gs_copy_data.attr_map) { + for (auto const& [loc, attr_pair] : info.gs_copy_data.attr_map) { writeBin(info_serialized, loc); - writeBin(info_serialized, idx); + // Das erste Element des Paars ist ein Shader::IR::Attribute, ein Enum + writeBin(info_serialized, static_cast(attr_pair.first)); + // Das zweite Element ist ein u32 + writeBin(info_serialized, attr_pair.second); } // SRT Info u32 srtCount = static_cast(info.srt_info.srt_reservations.size()); - writeBin(info_serialized, count); + writeBin(info_serialized, srtCount); for (const auto& res : info.srt_info.srt_reservations) { writeBin(info_serialized, res.sgpr_base); @@ -91,24 +322,313 @@ void SerializeInfo(std::ostream& info_serialized, Shader::Info info) { writeBin(info_serialized, res.num_dwords); } + // Flat UD + + u32 flatCount = static_cast(info.flattened_ud_buf.size()); + writeBin(info_serialized, flatCount); + + for (const auto& flat : info.flattened_ud_buf) { + writeBin(info_serialized, flat); + } + + // Tessellation Data + writeBin(info_serialized, info.tess_consts_ptr_base); + writeBin(info_serialized, info.tess_consts_dword_offset); + + // Flags + writeBin(info_serialized, static_cast(info.has_storage_images ? 1 : 0)); + writeBin(info_serialized, static_cast(info.has_discard ? 1 : 0)); + writeBin(info_serialized, static_cast(info.has_image_gather ? 1 : 0)); + writeBin(info_serialized, static_cast(info.has_image_query ? 1 : 0)); + writeBin(info_serialized, static_cast(info.uses_lane_id ? 1 : 0)); + writeBin(info_serialized, static_cast(info.uses_group_quad ? 1 : 0)); + writeBin(info_serialized, static_cast(info.uses_group_ballot ? 1 : 0)); + writeBin(info_serialized, static_cast(info.uses_shared ? 1 : 0)); + writeBin(info_serialized, static_cast(info.uses_fp16 ? 1 : 0)); + writeBin(info_serialized, static_cast(info.uses_fp64 ? 1 : 0)); + writeBin(info_serialized, static_cast(info.uses_pack_10_11_11 ? 1 : 0)); + writeBin(info_serialized, static_cast(info.uses_unpack_10_11_11 ? 1 : 0)); + writeBin(info_serialized, static_cast(info.stores_tess_level_outer ? 1 : 0)); + writeBin(info_serialized, static_cast(info.stores_tess_level_inner ? 1 : 0)); + writeBin(info_serialized, static_cast(info.translation_failed ? 1 : 0)); + writeBin(info_serialized, static_cast(info.has_readconst ? 1 : 0)); + // MRT Mask writeBin(info_serialized, info.mrt_mask); -} -void DeserializeInfo(std::istream& info_serialized, Shader::Info& info) { - readBin(info_serialized, info.mrt_mask); + // Fetch + + writeBin(info_serialized, static_cast(info.has_fetch_shader ? 1 : 0)); + writeBin(info_serialized, info.fetch_shader_sgpr_base); + + // Stage + writeBin(info_serialized, info.stage); + writeBin(info_serialized, info.l_stage); + writeBin(info_serialized, info.pgm_hash); + + // AttributeFlags für loads + u32 loads_size = static_cast(info.loads.flags.size()); + writeBin(info_serialized, loads_size); + for (size_t i = 0; i < info.loads.flags.size(); ++i) { + writeBin(info_serialized, info.loads.flags[i]); + } + + // AttributeFlags für stores + u32 stores_size = static_cast(info.stores.flags.size()); + writeBin(info_serialized, stores_size); + for (size_t i = 0; i < info.stores.flags.size(); ++i) { + writeBin(info_serialized, info.stores.flags[i]); + } } bool CheckShaderCache(std::string shader_id) { - return 0; + // Überprüfen, ob das Verzeichnis existiert + if (!std::filesystem::exists(shader_cache_dir)) { + LOG_INFO(Render_Vulkan, "Shader-Cache-Verzeichnis existiert nicht"); + return false; + } + + // Überprüfen, ob sowohl die SPIR-V-Datei als auch die Ressourcendatei existieren + std::filesystem::path spirv_cache_file_path = shader_cache_dir / (shader_id + ".spv"); + std::filesystem::path resources_file_path = shader_cache_dir / (shader_id + ".resources"); + + if (!std::filesystem::exists(spirv_cache_file_path)) { + LOG_DEBUG(Render_Vulkan, "SPIR-V-Datei nicht gefunden: {}", spirv_cache_file_path.string()); + return false; + } + + if (!std::filesystem::exists(resources_file_path)) { + LOG_DEBUG(Render_Vulkan, "Ressourcendatei nicht gefunden: {}", + resources_file_path.string()); + return false; + } + + // Überprüfen, ob die Dateien lesbar und nicht leer sind + Common::FS::IOFile spirv_file(spirv_cache_file_path, Common::FS::FileAccessMode::Read); + Common::FS::IOFile resources_file(resources_file_path, Common::FS::FileAccessMode::Read); + + const bool spirv_valid = spirv_file.IsOpen() && spirv_file.GetSize() > 0; + const bool resources_valid = resources_file.IsOpen() && resources_file.GetSize() > 0; + + spirv_file.Close(); + resources_file.Close(); + + if (!spirv_valid || !resources_valid) { + LOG_WARNING(Render_Vulkan, "Ungueltige Dateien im Shader-Cache für ID: {}", shader_id); + // Fehlerhafte Dateien entfernen, um zukünftige Probleme zu vermeiden + if (std::filesystem::exists(spirv_cache_file_path)) { + std::filesystem::remove(spirv_cache_file_path); + } + if (std::filesystem::exists(resources_file_path)) { + std::filesystem::remove(resources_file_path); + } + return false; + } + + LOG_INFO(Render_Vulkan, "Shader mit ID {} im Cache gefunden", shader_id); + return true; } -void GetShader(std::string shader_id, Shader::Info& info) { - std::string spirv_cache_filename = shader_id + ".spv "; +void DeserializeInfo(std::istream& info_serialized, Shader::Info& info) { + // UD Mask + readBin(info_serialized, info.ud_mask.mask); + + // Buffer-Resources + u32 bufferCount; + readBin(info_serialized, bufferCount); + + info.buffers.clear(); + info.buffers.reserve(bufferCount); + for (u32 i = 0; i < bufferCount; ++i) { + Shader::BufferResource buffer; + readBin(info_serialized, buffer.sharp_idx); + u32 used_types; + readBin(info_serialized, used_types); + buffer.used_types = static_cast(used_types); + u32 buffer_type; + readBin(info_serialized, buffer_type); + buffer.buffer_type = static_cast(buffer_type); + readBin(info_serialized, buffer.instance_attrib); + u8 is_written; + readBin(info_serialized, is_written); + buffer.is_written = (is_written == 1); + u8 is_formatted; + readBin(info_serialized, is_formatted); + buffer.is_formatted = (is_formatted == 1); + info.buffers.push_back(std::move(buffer)); + } + + // Image-Resources + u32 imageCount; + readBin(info_serialized, imageCount); + + info.images.clear(); + info.images.reserve(imageCount); + for (u32 i = 0; i < imageCount; ++i) { + Shader::ImageResource image; + readBin(info_serialized, image.sharp_idx); + u8 is_depth; + readBin(info_serialized, is_depth); + image.is_depth = (is_depth == 1); + u8 is_atomic; + readBin(info_serialized, is_atomic); + image.is_atomic = (is_atomic == 1); + u8 is_array; + readBin(info_serialized, is_array); + image.is_array = (is_array == 1); + u8 is_written; + readBin(info_serialized, is_written); + image.is_written = (is_written == 1); + info.images.push_back(std::move(image)); + } + + // Sampler-Resources + u32 samplerCount; + readBin(info_serialized, samplerCount); + + info.samplers.clear(); + info.samplers.reserve(samplerCount); + for (u32 i = 0; i < samplerCount; ++i) { + Shader::SamplerResource sampler; + readBin(info_serialized, sampler.sharp_idx); + info.samplers.push_back(std::move(sampler)); + } + + // FMask-Resources + u32 fmaskCount; + readBin(info_serialized, fmaskCount); + + info.fmasks.clear(); + info.fmasks.reserve(fmaskCount); + for (u32 i = 0; i < fmaskCount; ++i) { + Shader::FMaskResource fmask; + readBin(info_serialized, fmask.sharp_idx); + info.fmasks.push_back(std::move(fmask)); + } + + // GS Copy Data + u32 mapCount; + readBin(info_serialized, mapCount); + + info.gs_copy_data.attr_map.clear(); + for (u32 i = 0; i < mapCount; ++i) { + u32 loc; + u32 attribute_value; + u32 idx; + readBin(info_serialized, loc); + readBin(info_serialized, attribute_value); + readBin(info_serialized, idx); + + // Umwandeln des numerischen Werts zurück in das Shader::IR::Attribute-Enum + Shader::IR::Attribute attribute = static_cast(attribute_value); + + // Einfügen in die Map mit dem richtigen Paar-Typ + info.gs_copy_data.attr_map.emplace(loc, std::make_pair(attribute, idx)); + } + + // SRT Info + u32 srtCount; + readBin(info_serialized, srtCount); + + info.srt_info.srt_reservations.clear(); + info.srt_info.srt_reservations.resize(srtCount); + for (u32 i = 0; i < srtCount; ++i) { + auto& res = info.srt_info.srt_reservations[i]; + readBin(info_serialized, res.sgpr_base); + readBin(info_serialized, res.dword_offset); + readBin(info_serialized, res.num_dwords); + } + + // Flat UD + u32 flatCount; + readBin(info_serialized, flatCount); + + info.flattened_ud_buf.clear(); + info.flattened_ud_buf.resize(flatCount); + for (u32 i = 0; i < flatCount; ++i) { + readBin(info_serialized, info.flattened_ud_buf[i]); + } + + // Tessellation Data + readBin(info_serialized, info.tess_consts_ptr_base); + readBin(info_serialized, info.tess_consts_dword_offset); + + // Flags + u8 flag_value; + readBin(info_serialized, flag_value); + info.has_storage_images = (flag_value == 1); + readBin(info_serialized, flag_value); + info.has_discard = (flag_value == 1); + readBin(info_serialized, flag_value); + info.has_image_gather = (flag_value == 1); + readBin(info_serialized, flag_value); + info.has_image_query = (flag_value == 1); + readBin(info_serialized, flag_value); + info.uses_lane_id = (flag_value == 1); + readBin(info_serialized, flag_value); + info.uses_group_quad = (flag_value == 1); + readBin(info_serialized, flag_value); + info.uses_group_ballot = (flag_value == 1); + readBin(info_serialized, flag_value); + info.uses_shared = (flag_value == 1); + readBin(info_serialized, flag_value); + info.uses_fp16 = (flag_value == 1); + readBin(info_serialized, flag_value); + info.uses_fp64 = (flag_value == 1); + readBin(info_serialized, flag_value); + info.uses_pack_10_11_11 = (flag_value == 1); + readBin(info_serialized, flag_value); + info.uses_unpack_10_11_11 = (flag_value == 1); + readBin(info_serialized, flag_value); + info.stores_tess_level_outer = (flag_value == 1); + readBin(info_serialized, flag_value); + info.stores_tess_level_inner = (flag_value == 1); + readBin(info_serialized, flag_value); + info.translation_failed = (flag_value == 1); + readBin(info_serialized, flag_value); + info.has_readconst = (flag_value == 1); + + // MRT Mask + readBin(info_serialized, info.mrt_mask); + + // Fetch Shader + u8 has_fetch_shader; + readBin(info_serialized, has_fetch_shader); + info.has_fetch_shader = (has_fetch_shader == 1); + readBin(info_serialized, info.fetch_shader_sgpr_base); + + // Stage + readBin(info_serialized, info.stage); + readBin(info_serialized, info.l_stage); + readBin(info_serialized, info.pgm_hash); + + // AttributeFlags für loads + u32 loads_size; + readBin(info_serialized, loads_size); + for (size_t i = 0; i < loads_size && i < info.loads.flags.size(); ++i) { + readBin(info_serialized, info.loads.flags[i]); + } + + // AttributeFlags für stores + u32 stores_size; + readBin(info_serialized, stores_size); + for (size_t i = 0; i < stores_size && i < info.stores.flags.size(); ++i) { + readBin(info_serialized, info.stores.flags[i]); + } + + // Check if there are any remaining bytes in the stream + if (info_serialized.peek() != EOF) { + LOG_WARNING(Render_Vulkan, "Es sind noch {} Bytes im Stream übrig", + info_serialized.gcount()); + } +} + + +void GetShader(std::string shader_id, Shader::Info& info, std::vector& spv) { + std::string spirv_cache_filename = shader_id + ".spv"; std::filesystem::path spirv_cache_file_path = shader_cache_dir / spirv_cache_filename; Common::FS::IOFile spirv_cache_file(spirv_cache_file_path, Common::FS::FileAccessMode::Read); - std::vector spv; spv.resize(spirv_cache_file.GetSize() / sizeof(u32)); spirv_cache_file.Read(spv); spirv_cache_file.Close(); @@ -126,7 +646,6 @@ void GetShader(std::string shader_id, Shader::Info& info) { // Verarbeite die gespeicherten Daten std::istringstream combined_stream(std::string(resources_data.begin(), resources_data.end())); - // Deserialisiere info und profile std::istringstream info_stream; info_stream.str(std::string(resources_data.begin(), resources_data.end())); DeserializeInfo(info_stream, info); @@ -146,7 +665,7 @@ void AddShader(std::string shader_id, std::vector spv, std::ostream& info_s Common::FS::IOFile resources_dump_file(resources_dump_file_path, Common::FS::FileAccessMode::Write); - // Die Streams müssen zurückgesetzt werden, bevor wir sie lesen können + // Die Streams müssen zurückgesetzt werden, bevor wir sie lesen können if (std::ostringstream* info_oss = dynamic_cast(&info_serialized)) { std::string info_data = info_oss->str(); resources_dump_file.WriteSpan(std::span(info_data.data(), info_data.size())); diff --git a/src/video_core/renderer_vulkan/shader_cache.h b/src/video_core/renderer_vulkan/shader_cache.h index 2b5c1ae75..d2320e455 100644 --- a/src/video_core/renderer_vulkan/shader_cache.h +++ b/src/video_core/renderer_vulkan/shader_cache.h @@ -5,15 +5,17 @@ #include #include #include "shader_recompiler/info.h" +#include namespace ShaderCache { -std::string CreateShaderID(u64 pgm_hash, size_t perm_idx, std::ostream& info_dump); -void SerializeInfo(std::ostream& info_serialized, Shader::Info info); +u64 CalculateSpecializationHash(const Shader::StageSpecialization& spec); +void SerializeInfo( + std::ostream& info_serialized, Shader::Info info); void DeserializeInfo(std::istream& info_serialized, Shader::Info& info); bool CheckShaderCache(std::string shader_id); -void GetShader(std::string shader_id, Shader::Info& info); +void GetShader(std::string shader_id, Shader::Info& info, std::vector& spv); void AddShader(std::string shader_id, std::vector spv, std::ostream& info_serialized); } // namespace ShaderCache diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index cb4a6c0ce..4036d3379 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -488,34 +488,36 @@ bool PipelineCache::RefreshComputeKey() { vk::ShaderModule PipelineCache::CompileModule(Shader::Info& info, Shader::RuntimeInfo& runtime_info, std::span code, size_t perm_idx, - Shader::Backend::Bindings& binding) { + Shader::Backend::Bindings& binding, Shader::StageSpecialization spec) { LOG_INFO(Render_Vulkan, "Compiling {} shader {:#x} {}", info.stage, info.pgm_hash, perm_idx != 0 ? "(permutation)" : ""); + DumpShader(code, info.pgm_hash, info.stage, perm_idx, "bin"); - - - const auto ir_program = Shader::TranslateProgram(code, pools, info, runtime_info, profile); std::string shader_name = GetShaderName(info.stage, info.pgm_hash, perm_idx); - - std::vector spv; - - if (false){ //(::ShaderCache::CheckShaderCache(shader_id)) { - LOG_INFO(Render_Vulkan, "Loaded SPIR-V from cache"); + std::string shader_id = std::to_string(::ShaderCache::CalculateSpecializationHash(spec)); + if (::ShaderCache::CheckShaderCache(shader_id)) { + LOG_INFO(Render_Vulkan, "Loaded shader {} {:#x} {} from cache", info.stage, info.pgm_hash, + perm_idx != 0 ? "(permutation)" : ""); + ::ShaderCache::GetShader(shader_id, info, spv); + info.RefreshFlatBuf(); } else { + LOG_INFO(Render_Vulkan, "Shader {} {:#x} {} not in cache", info.stage, + info.pgm_hash, perm_idx != 0 ? "(permutation)" : ""); + const auto ir_program = Shader::TranslateProgram(code, pools, info, runtime_info, profile); spv = Shader::Backend::SPIRV::EmitSPIRV(profile, runtime_info, ir_program, binding); std::ostringstream info_serialized; ::ShaderCache::SerializeInfo(info_serialized, info); - std::string shader_id = - ::ShaderCache::CreateShaderID(info.pgm_hash, perm_idx, info_serialized); + ::ShaderCache::AddShader(shader_id, spv, info_serialized); LOG_INFO(Render_Vulkan, "Shader ID: {}", shader_id); DumpShader(spv, info.pgm_hash, info.stage, perm_idx, "spv"); - LOG_INFO(Render_Vulkan, "Compiled SPIR-V and stored in cache"); + LOG_INFO(Render_Vulkan, "Compiled shader {} {:#x} {} and saved it to cache", info.stage, info.pgm_hash, + perm_idx != 0 ? "(permutation)" : ""); } vk::ShaderModule module; @@ -543,13 +545,14 @@ PipelineCache::Result PipelineCache::GetProgram(Stage stage, LogicalStage l_stag Shader::ShaderParams params, Shader::Backend::Bindings& binding) { auto runtime_info = BuildRuntimeInfo(stage, l_stage); - auto [it_pgm, new_program] = program_cache.try_emplace(params.hash); + auto [it_pgm, new_program] = program_cache.try_emplace(params.hash); // code in vs if (new_program) { it_pgm.value() = std::make_unique(stage, l_stage, params); auto& program = it_pgm.value(); auto start = binding; - const auto module = CompileModule(program->info, runtime_info, params.code, 0, binding); - const auto spec = Shader::StageSpecialization(program->info, runtime_info, profile, start); + Shader::StageSpecialization spec = + Shader::StageSpecialization(program->info, runtime_info, profile, start); + const auto module = CompileModule(program->info, runtime_info, params.code, 0, binding, spec); program->AddPermut(module, std::move(spec)); return std::make_tuple(&program->info, module, spec.fetch_shader_data, HashCombine(params.hash, 0)); @@ -566,7 +569,7 @@ PipelineCache::Result PipelineCache::GetProgram(Stage stage, LogicalStage l_stag const auto it = std::ranges::find(program->modules, spec, &Program::Module::spec); if (it == program->modules.end()) { auto new_info = Shader::Info(stage, l_stage, params); - module = CompileModule(new_info, runtime_info, params.code, perm_idx, binding); + module = CompileModule(new_info, runtime_info, params.code, perm_idx, binding, spec); program->AddPermut(module, std::move(spec)); } else { info.AddBindings(binding); diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.h b/src/video_core/renderer_vulkan/vk_pipeline_cache.h index ba3407b48..c20d06a7b 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.h +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.h @@ -82,7 +82,7 @@ private: std::string_view ext); vk::ShaderModule CompileModule(Shader::Info& info, Shader::RuntimeInfo& runtime_info, std::span code, size_t perm_idx, - Shader::Backend::Bindings& binding); + Shader::Backend::Bindings& binding, Shader::StageSpecialization spec); const Shader::RuntimeInfo& BuildRuntimeInfo(Shader::Stage stage, Shader::LogicalStage l_stage); private: From 3e56133cda50cf062203cea15ab69e3df5e940de Mon Sep 17 00:00:00 2001 From: Fire Cube Date: Sat, 3 May 2025 16:36:39 +0200 Subject: [PATCH 10/27] now heroes give at least a bit of image --- .../renderer_vulkan/shader_cache.cpp | 110 +++++++++++++++++- 1 file changed, 108 insertions(+), 2 deletions(-) diff --git a/src/video_core/renderer_vulkan/shader_cache.cpp b/src/video_core/renderer_vulkan/shader_cache.cpp index b256d2cda..f07c41aa7 100644 --- a/src/video_core/renderer_vulkan/shader_cache.cpp +++ b/src/video_core/renderer_vulkan/shader_cache.cpp @@ -270,6 +270,25 @@ void SerializeInfo(std::ostream& info_serialized, Shader::Info info) { writeBin(info_serialized, buffer.instance_attrib); writeBin(info_serialized, static_cast(buffer.is_written ? 1 : 0)); writeBin(info_serialized, static_cast(buffer.is_formatted ? 1 : 0)); + + writeBin(info_serialized, buffer.inline_cbuf.base_address); + writeBin(info_serialized, buffer.inline_cbuf._padding0); + writeBin(info_serialized, buffer.inline_cbuf.stride); + writeBin(info_serialized, buffer.inline_cbuf.cache_swizzle); + writeBin(info_serialized, buffer.inline_cbuf.swizzle_enable); + writeBin(info_serialized, buffer.inline_cbuf.num_records); + writeBin(info_serialized, buffer.inline_cbuf.dst_sel_x); + writeBin(info_serialized, buffer.inline_cbuf.dst_sel_y); + writeBin(info_serialized, buffer.inline_cbuf.dst_sel_z); + writeBin(info_serialized, buffer.inline_cbuf.dst_sel_w); + writeBin(info_serialized, buffer.inline_cbuf.num_format); + writeBin(info_serialized, buffer.inline_cbuf.data_format); + writeBin(info_serialized, buffer.inline_cbuf.element_size); + writeBin(info_serialized, buffer.inline_cbuf.index_stride); + writeBin(info_serialized, buffer.inline_cbuf.add_tid_enable); + writeBin(info_serialized, buffer.inline_cbuf._padding1); + writeBin(info_serialized, buffer.inline_cbuf.type); + } // Image-Resources @@ -290,6 +309,13 @@ void SerializeInfo(std::ostream& info_serialized, Shader::Info info) { for (const auto& sampler : info.samplers) { writeBin(info_serialized, sampler.sharp_idx); + writeBin(info_serialized, sampler.associated_image); + writeBin(info_serialized, sampler.disable_aniso); + + writeBin(info_serialized, sampler.inline_sampler.raw0); + writeBin(info_serialized, sampler.inline_sampler.raw1); + + } // FMask-Resources @@ -455,6 +481,73 @@ void DeserializeInfo(std::istream& info_serialized, Shader::Info& info) { u8 is_formatted; readBin(info_serialized, is_formatted); buffer.is_formatted = (is_formatted == 1); + + u64 base_address; + readBin(info_serialized, base_address); + buffer.inline_cbuf.base_address = base_address; + + u64 padding0; + readBin(info_serialized, padding0); + buffer.inline_cbuf._padding0 = padding0; + + u64 stride; + readBin(info_serialized, stride); + buffer.inline_cbuf.stride = stride; + + u64 cache_swizzle; + readBin(info_serialized, cache_swizzle); + buffer.inline_cbuf.cache_swizzle = cache_swizzle; + + u64 swizzle_enable; + readBin(info_serialized, swizzle_enable); + buffer.inline_cbuf.swizzle_enable = swizzle_enable; + + readBin(info_serialized, buffer.inline_cbuf.num_records); + + u32 dst_sel_x; + readBin(info_serialized, dst_sel_x); + buffer.inline_cbuf.dst_sel_x = dst_sel_x; + + u32 dst_sel_y; + readBin(info_serialized, dst_sel_y); + buffer.inline_cbuf.dst_sel_y = dst_sel_y; + + u32 dst_sel_z; + readBin(info_serialized, dst_sel_z); + buffer.inline_cbuf.dst_sel_z = dst_sel_z; + + u32 dst_sel_w; + readBin(info_serialized, dst_sel_w); + buffer.inline_cbuf.dst_sel_w = dst_sel_w; + + u32 num_format; + readBin(info_serialized, num_format); + buffer.inline_cbuf.num_format = num_format; + + u32 data_format; + readBin(info_serialized, data_format); + buffer.inline_cbuf.data_format = data_format; + + u32 element_size; + readBin(info_serialized, element_size); + buffer.inline_cbuf.element_size = element_size; + + u32 index_stride; + readBin(info_serialized, index_stride); + buffer.inline_cbuf.index_stride = index_stride; + + u32 add_tid_enable; + readBin(info_serialized, add_tid_enable); + buffer.inline_cbuf.add_tid_enable = add_tid_enable; + + u32 padding1; + readBin(info_serialized, padding1); + buffer.inline_cbuf._padding1 = padding1; + + u32 type; + readBin(info_serialized, type); + buffer.inline_cbuf.type = type; + info.buffers.push_back(std::move(buffer)); } @@ -491,6 +584,19 @@ void DeserializeInfo(std::istream& info_serialized, Shader::Info& info) { for (u32 i = 0; i < samplerCount; ++i) { Shader::SamplerResource sampler; readBin(info_serialized, sampler.sharp_idx); + + u32 associated_image; + readBin(info_serialized, associated_image); + sampler.associated_image = associated_image; + + u32 disable_aniso; + readBin(info_serialized, disable_aniso); + sampler.disable_aniso = disable_aniso; + + // Inline-Sampler deserialisieren + readBin(info_serialized, sampler.inline_sampler.raw0); + readBin(info_serialized, sampler.inline_sampler.raw1); + info.samplers.push_back(std::move(sampler)); } @@ -605,14 +711,14 @@ void DeserializeInfo(std::istream& info_serialized, Shader::Info& info) { // AttributeFlags für loads u32 loads_size; readBin(info_serialized, loads_size); - for (size_t i = 0; i < loads_size && i < info.loads.flags.size(); ++i) { + for (size_t i = 0; i < loads_size; ++i) { readBin(info_serialized, info.loads.flags[i]); } // AttributeFlags für stores u32 stores_size; readBin(info_serialized, stores_size); - for (size_t i = 0; i < stores_size && i < info.stores.flags.size(); ++i) { + for (size_t i = 0; i < stores_size; ++i) { readBin(info_serialized, info.stores.flags[i]); } From b9b75cf2c8f017c7d5932c42b1bfb81c4c446ffa Mon Sep 17 00:00:00 2001 From: Fire Cube Date: Sat, 3 May 2025 19:45:05 +0200 Subject: [PATCH 11/27] crashes fixed --- src/video_core/renderer_vulkan/shader_cache.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/video_core/renderer_vulkan/shader_cache.cpp b/src/video_core/renderer_vulkan/shader_cache.cpp index f07c41aa7..8b12e5209 100644 --- a/src/video_core/renderer_vulkan/shader_cache.cpp +++ b/src/video_core/renderer_vulkan/shader_cache.cpp @@ -348,6 +348,8 @@ void SerializeInfo(std::ostream& info_serialized, Shader::Info info) { writeBin(info_serialized, res.num_dwords); } + writeBin(info_serialized, info.srt_info.flattened_bufsize_dw); + // Flat UD u32 flatCount = static_cast(info.flattened_ud_buf.size()); @@ -645,12 +647,17 @@ void DeserializeInfo(std::istream& info_serialized, Shader::Info& info) { readBin(info_serialized, res.num_dwords); } + readBin(info_serialized, info.srt_info.flattened_bufsize_dw); + // Flat UD + u32 flatCount; readBin(info_serialized, flatCount); info.flattened_ud_buf.clear(); - info.flattened_ud_buf.resize(flatCount); + u32 required_size = std::max(flatCount, info.srt_info.flattened_bufsize_dw); + info.flattened_ud_buf.resize(required_size); + for (u32 i = 0; i < flatCount; ++i) { readBin(info_serialized, info.flattened_ud_buf[i]); } From bcc65e7dd9b4d43e32e8f8e621724813c832e668 Mon Sep 17 00:00:00 2001 From: Fire Cube Date: Sat, 3 May 2025 21:49:09 +0200 Subject: [PATCH 12/27] remove include --- src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 4036d3379..7aacc9b9c 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -18,7 +18,6 @@ #include "video_core/renderer_vulkan/vk_presenter.h" #include "video_core/renderer_vulkan/vk_scheduler.h" #include "video_core/renderer_vulkan/vk_shader_util.h" -#include extern std::unique_ptr presenter; From 6c8a792176c951f2685dc5d8fa7600750cd65acf Mon Sep 17 00:00:00 2001 From: Fire Cube Date: Sat, 3 May 2025 21:50:44 +0200 Subject: [PATCH 13/27] handle file eof when readBin --- src/common/binary_helper.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/common/binary_helper.h b/src/common/binary_helper.h index de1bb9b78..366b1a13d 100644 --- a/src/common/binary_helper.h +++ b/src/common/binary_helper.h @@ -13,6 +13,10 @@ void writeBin(std::ostream& os, const T& v) { } template -void readBin(std::istream& is, T& v) { +void readBin(std::istream& is, T& v) { + if (is.eof()) { + LOG_WARNING(Render_Recompiler, "BinaryHelper: EOF"); + } + LOG_WARNING is.read(reinterpret_cast(&v), sizeof(T)); } \ No newline at end of file From 019172f740856f0b43c3f8c3684c4505ebeb5d4a Mon Sep 17 00:00:00 2001 From: Fire Cube Date: Sat, 3 May 2025 21:52:04 +0200 Subject: [PATCH 14/27] im dumb --- src/common/binary_helper.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/common/binary_helper.h b/src/common/binary_helper.h index 366b1a13d..dcf5c2dc4 100644 --- a/src/common/binary_helper.h +++ b/src/common/binary_helper.h @@ -17,6 +17,5 @@ void readBin(std::istream& is, T& v) { if (is.eof()) { LOG_WARNING(Render_Recompiler, "BinaryHelper: EOF"); } - LOG_WARNING is.read(reinterpret_cast(&v), sizeof(T)); } \ No newline at end of file From 2a3470804752dd54f4ed18f9a2f277b978e0a51c Mon Sep 17 00:00:00 2001 From: Fire Cube Date: Sat, 3 May 2025 22:14:07 +0200 Subject: [PATCH 15/27] more --- .../renderer_vulkan/shader_cache.cpp | 121 +++++++++++------- 1 file changed, 74 insertions(+), 47 deletions(-) diff --git a/src/video_core/renderer_vulkan/shader_cache.cpp b/src/video_core/renderer_vulkan/shader_cache.cpp index 8b12e5209..ffa8bb476 100644 --- a/src/video_core/renderer_vulkan/shader_cache.cpp +++ b/src/video_core/renderer_vulkan/shader_cache.cpp @@ -16,6 +16,7 @@ using u32 = uint32_t; namespace ShaderCache { const auto shader_cache_dir = Common::FS::GetUserPath(Common::FS::PathType::ShaderDir) / "cache"; +std::unordered_map> g_ud_storage; u64 CalculateSpecializationHash(const Shader::StageSpecialization& spec) { u64 hash = 0; @@ -407,54 +408,16 @@ void SerializeInfo(std::ostream& info_serialized, Shader::Info info) { for (size_t i = 0; i < info.stores.flags.size(); ++i) { writeBin(info_serialized, info.stores.flags[i]); } -} -bool CheckShaderCache(std::string shader_id) { - // Überprüfen, ob das Verzeichnis existiert - if (!std::filesystem::exists(shader_cache_dir)) { - LOG_INFO(Render_Vulkan, "Shader-Cache-Verzeichnis existiert nicht"); - return false; + // UserData + u32 userDataSize = static_cast(info.user_data.size()); + writeBin(info_serialized, userDataSize); + for (size_t i = 0; i < info.user_data.size(); ++i) { + writeBin(info_serialized, info.user_data[i]); } - // Überprüfen, ob sowohl die SPIR-V-Datei als auch die Ressourcendatei existieren - std::filesystem::path spirv_cache_file_path = shader_cache_dir / (shader_id + ".spv"); - std::filesystem::path resources_file_path = shader_cache_dir / (shader_id + ".resources"); - - if (!std::filesystem::exists(spirv_cache_file_path)) { - LOG_DEBUG(Render_Vulkan, "SPIR-V-Datei nicht gefunden: {}", spirv_cache_file_path.string()); - return false; - } - - if (!std::filesystem::exists(resources_file_path)) { - LOG_DEBUG(Render_Vulkan, "Ressourcendatei nicht gefunden: {}", - resources_file_path.string()); - return false; - } - - // Überprüfen, ob die Dateien lesbar und nicht leer sind - Common::FS::IOFile spirv_file(spirv_cache_file_path, Common::FS::FileAccessMode::Read); - Common::FS::IOFile resources_file(resources_file_path, Common::FS::FileAccessMode::Read); - - const bool spirv_valid = spirv_file.IsOpen() && spirv_file.GetSize() > 0; - const bool resources_valid = resources_file.IsOpen() && resources_file.GetSize() > 0; - - spirv_file.Close(); - resources_file.Close(); - - if (!spirv_valid || !resources_valid) { - LOG_WARNING(Render_Vulkan, "Ungueltige Dateien im Shader-Cache für ID: {}", shader_id); - // Fehlerhafte Dateien entfernen, um zukünftige Probleme zu vermeiden - if (std::filesystem::exists(spirv_cache_file_path)) { - std::filesystem::remove(spirv_cache_file_path); - } - if (std::filesystem::exists(resources_file_path)) { - std::filesystem::remove(resources_file_path); - } - return false; - } - - LOG_INFO(Render_Vulkan, "Shader mit ID {} im Cache gefunden", shader_id); - return true; + // Pgm Base + writeBin(info_serialized, info.pgm_base); } void DeserializeInfo(std::istream& info_serialized, Shader::Info& info) { @@ -729,13 +692,77 @@ void DeserializeInfo(std::istream& info_serialized, Shader::Info& info) { readBin(info_serialized, info.stores.flags[i]); } + // UserData + u32 userDataSize; + readBin(info_serialized, userDataSize); + + static std::vector temp_user_data_storage; + temp_user_data_storage.clear(); + temp_user_data_storage.resize(userDataSize); + + for (u32 i = 0; i < userDataSize; ++i) { + readBin(info_serialized, temp_user_data_storage[i]); + } + + info.user_data = std::span(temp_user_data_storage); + + // Pgm Base + readBin(info_serialized, info.pgm_base); + + // Check if there are any remaining bytes in the stream if (info_serialized.peek() != EOF) { - LOG_WARNING(Render_Vulkan, "Es sind noch {} Bytes im Stream übrig", - info_serialized.gcount()); + LOG_WARNING(Render_Vulkan, "Es sind noch Bytes im Stream übrig"); } } +bool CheckShaderCache(std::string shader_id) { + // Überprüfen, ob das Verzeichnis existiert + if (!std::filesystem::exists(shader_cache_dir)) { + LOG_INFO(Render_Vulkan, "Shader-Cache-Verzeichnis existiert nicht"); + return false; + } + + // Überprüfen, ob sowohl die SPIR-V-Datei als auch die Ressourcendatei existieren + std::filesystem::path spirv_cache_file_path = shader_cache_dir / (shader_id + ".spv"); + std::filesystem::path resources_file_path = shader_cache_dir / (shader_id + ".resources"); + + if (!std::filesystem::exists(spirv_cache_file_path)) { + LOG_DEBUG(Render_Vulkan, "SPIR-V-Datei nicht gefunden: {}", spirv_cache_file_path.string()); + return false; + } + + if (!std::filesystem::exists(resources_file_path)) { + LOG_DEBUG(Render_Vulkan, "Ressourcendatei nicht gefunden: {}", + resources_file_path.string()); + return false; + } + + // Überprüfen, ob die Dateien lesbar und nicht leer sind + Common::FS::IOFile spirv_file(spirv_cache_file_path, Common::FS::FileAccessMode::Read); + Common::FS::IOFile resources_file(resources_file_path, Common::FS::FileAccessMode::Read); + + const bool spirv_valid = spirv_file.IsOpen() && spirv_file.GetSize() > 0; + const bool resources_valid = resources_file.IsOpen() && resources_file.GetSize() > 0; + + spirv_file.Close(); + resources_file.Close(); + + if (!spirv_valid || !resources_valid) { + LOG_WARNING(Render_Vulkan, "Ungueltige Dateien im Shader-Cache für ID: {}", shader_id); + // Fehlerhafte Dateien entfernen, um zukünftige Probleme zu vermeiden + if (std::filesystem::exists(spirv_cache_file_path)) { + std::filesystem::remove(spirv_cache_file_path); + } + if (std::filesystem::exists(resources_file_path)) { + std::filesystem::remove(resources_file_path); + } + return false; + } + + LOG_INFO(Render_Vulkan, "Shader mit ID {} im Cache gefunden", shader_id); + return true; +} void GetShader(std::string shader_id, Shader::Info& info, std::vector& spv) { std::string spirv_cache_filename = shader_id + ".spv"; From 84ee3f9425c946d8bf380c354814808800d88276 Mon Sep 17 00:00:00 2001 From: Fire Cube Date: Sat, 10 May 2025 22:05:01 +0200 Subject: [PATCH 16/27] more --- .../renderer_vulkan/shader_cache.cpp | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/src/video_core/renderer_vulkan/shader_cache.cpp b/src/video_core/renderer_vulkan/shader_cache.cpp index ffa8bb476..28df9d209 100644 --- a/src/video_core/renderer_vulkan/shader_cache.cpp +++ b/src/video_core/renderer_vulkan/shader_cache.cpp @@ -1,6 +1,12 @@ #include #include #include +#ifdef _WIN32 +#include +#else +#include +#include +#endif #include "common/hash.h" #include "common/path_util.h" #include "common/io_file.h" @@ -350,7 +356,33 @@ void SerializeInfo(std::ostream& info_serialized, Shader::Info info) { } writeBin(info_serialized, info.srt_info.flattened_bufsize_dw); + bool has_walker_func = (info.srt_info.walker_func != nullptr); + writeBin(info_serialized, static_cast(has_walker_func ? 1 : 0)); + if (has_walker_func) { + // Größe des JIT-Codes ermitteln + const u8* walker_start = reinterpret_cast(info.srt_info.walker_func); + + // Wir müssen die Größe des generierten Codes bestimmen + // Dies kann aus der Xbyak::CodeGenerator Instanz extrahiert werden + // Alternativ können wir die Distanz zum nächsten Ret-Befehl berechnen + size_t walker_size = 0; + const u8* ptr = walker_start; + const u32 MAX_CODE_SIZE = 4096; // Sicherheitsbegrenzung + + // Suche nach Ret-Befehl (C3 in x86/x64) + for (walker_size = 0; walker_size < MAX_CODE_SIZE; walker_size++) { + // Einfacher Ret-Befehl (C3) + if (ptr[walker_size] == 0xC3) { + walker_size++; // Ret einschließen + break; + } + } + + // Speichere Größe und JIT-Code + writeBin(info_serialized, static_cast(walker_size)); + info_serialized.write(reinterpret_cast(walker_start), walker_size); + } // Flat UD u32 flatCount = static_cast(info.flattened_ud_buf.size()); @@ -611,7 +643,36 @@ void DeserializeInfo(std::istream& info_serialized, Shader::Info& info) { } readBin(info_serialized, info.srt_info.flattened_bufsize_dw); + // Laden des walker_func JIT-Codes + u8 has_walker_func; + readBin(info_serialized, has_walker_func); + if (has_walker_func == 1) { + // Größe des JIT-Codes lesen + u32 walker_size; + readBin(info_serialized, walker_size); + + // Speicher für ausführbaren Code allokieren + void* code_memory = nullptr; +#ifdef _WIN32 + code_memory = + VirtualAlloc(nullptr, walker_size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); +#else + code_memory = mmap(nullptr, walker_size, PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); +#endif + + if (!code_memory) { + LOG_ERROR(Render_Vulkan, "Konnte keinen ausführbaren Speicher für JIT-Code allokieren"); + return; + } + + // JIT-Code laden + info_serialized.read(reinterpret_cast(code_memory), walker_size); + + // JIT-Funktion zuweisen + info.srt_info.walker_func = reinterpret_cast(code_memory); + } // Flat UD u32 flatCount; From 742b3ced660a34ce3206284224dc2cd220a1b8fe Mon Sep 17 00:00:00 2001 From: Fire Cube Date: Wed, 18 Jun 2025 12:39:50 +0200 Subject: [PATCH 17/27] add CMakePresets.json --- CMakePresets.json | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 CMakePresets.json diff --git a/CMakePresets.json b/CMakePresets.json new file mode 100644 index 000000000..6a446b46d --- /dev/null +++ b/CMakePresets.json @@ -0,0 +1,47 @@ +{ + "version": 3, + "cmakeMinimumRequired": { + "major": 3, + "minor": 24, + "patch": 0 + }, + "configurePresets": [ + { + "name": "x64-Clang-Debug", + "displayName": "Clang x64 Debug", + "generator": "Ninja", + "binaryDir": "${sourceDir}/Build/x64-Clang-Debug", + "cacheVariables": { + "CMAKE_C_COMPILER": "clang-cl", + "CMAKE_CXX_COMPILER": "clang-cl", + "CMAKE_BUILD_TYPE": "Debug", + "CMAKE_INSTALL_PREFIX": "${sourceDir}/Install/x64-Clang-Debug" + + } + }, + { + "name": "x64-Clang-Release", + "displayName": "Clang x64 Release", + "generator": "Ninja", + "binaryDir": "${sourceDir}/Build/x64-Clang-Release", + "cacheVariables": { + "CMAKE_C_COMPILER": "clang-cl", + "CMAKE_CXX_COMPILER": "clang-cl", + "CMAKE_BUILD_TYPE": "Release", + "CMAKE_INSTALL_PREFIX": "${sourceDir}/Install/x64-Clang-Release" + } + }, + { + "name": "x64-Clang-RelWithDebInfo", + "displayName": "Clang x64 RelWithDebInfo", + "generator": "Ninja", + "binaryDir": "${sourceDir}/Build/x64-Clang-RelWithDebInfo", + "cacheVariables": { + "CMAKE_C_COMPILER": "clang-cl", + "CMAKE_CXX_COMPILER": "clang-cl", + "CMAKE_BUILD_TYPE": "RelWithDebInfo", + "CMAKE_INSTALL_PREFIX": "${sourceDir}/Install/x64-Clang-RelWithDebInfo" + } + } + ] +} From dd0365ffc75aa39cacda485ec580f8b70846e733 Mon Sep 17 00:00:00 2001 From: Fire Cube Date: Wed, 18 Jun 2025 13:41:26 +0200 Subject: [PATCH 18/27] Update REUSE.toml --- REUSE.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/REUSE.toml b/REUSE.toml index 662987611..5f5229e4b 100644 --- a/REUSE.toml +++ b/REUSE.toml @@ -5,6 +5,7 @@ path = [ "REUSE.toml", "crowdin.yml", "CMakeSettings.json", + "CMakePresets.json", ".github/FUNDING.yml", ".github/shadps4.png", ".github/workflows/scripts/update_translation.sh", From ddb11feeb7cefb392b18acd12b3f319146fea9da Mon Sep 17 00:00:00 2001 From: Fire Cube Date: Thu, 19 Jun 2025 20:51:34 +0200 Subject: [PATCH 19/27] fix vs --- CMakePresets.json | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/CMakePresets.json b/CMakePresets.json index 6a446b46d..c4d60b04e 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -1,5 +1,5 @@ { - "version": 3, + "version": 5, "cmakeMinimumRequired": { "major": 3, "minor": 24, @@ -16,7 +16,11 @@ "CMAKE_CXX_COMPILER": "clang-cl", "CMAKE_BUILD_TYPE": "Debug", "CMAKE_INSTALL_PREFIX": "${sourceDir}/Install/x64-Clang-Debug" - + }, + "vendor": { + "microsoft.com/VisualStudioSettings/CMake/1.0": { + "intelliSenseMode": "windows-clang-x64" + } } }, { @@ -29,6 +33,11 @@ "CMAKE_CXX_COMPILER": "clang-cl", "CMAKE_BUILD_TYPE": "Release", "CMAKE_INSTALL_PREFIX": "${sourceDir}/Install/x64-Clang-Release" + }, + "vendor": { + "microsoft.com/VisualStudioSettings/CMake/1.0": { + "intelliSenseMode": "windows-clang-x64" + } } }, { @@ -41,6 +50,11 @@ "CMAKE_CXX_COMPILER": "clang-cl", "CMAKE_BUILD_TYPE": "RelWithDebInfo", "CMAKE_INSTALL_PREFIX": "${sourceDir}/Install/x64-Clang-RelWithDebInfo" + }, + "vendor": { + "microsoft.com/VisualStudioSettings/CMake/1.0": { + "intelliSenseMode": "windows-clang-x64" + } } } ] From 8a35cc992016b54be2b806d361ecc5cd87d19b33 Mon Sep 17 00:00:00 2001 From: Fire Cube Date: Sat, 21 Jun 2025 21:00:21 +0200 Subject: [PATCH 20/27] impl --- CMakeLists.txt | 2 ++ CMakePresets.json | 54 ++++++++++++++++++++++++++++++++++++++++++++++ cmake/FindQt.cmake | 12 +++++++++++ 3 files changed, 68 insertions(+) create mode 100644 cmake/FindQt.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index d8fe5f68b..80f326432 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -214,6 +214,8 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/common/scm_rev.cpp.in" "${CMAKE_ message("end git things, remote: ${GIT_REMOTE_NAME}, branch: ${GIT_BRANCH}") +include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/findQt.cmake") + list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") find_package(Boost 1.84.0 CONFIG) find_package(FFmpeg 5.1.2 MODULE) diff --git a/CMakePresets.json b/CMakePresets.json index c4d60b04e..454b4e767 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -23,6 +23,24 @@ } } }, + { + "name": "x64-Clang-Debug-Qt", + "displayName": "Clang x64 Debug with Qt", + "generator": "Ninja", + "binaryDir": "${sourceDir}/Build/x64-Clang-Debug-Qt", + "cacheVariables": { + "CMAKE_C_COMPILER": "clang-cl", + "CMAKE_CXX_COMPILER": "clang-cl", + "CMAKE_BUILD_TYPE": "Debug", + "CMAKE_INSTALL_PREFIX": "${sourceDir}/Install/x64-Clang-Debug-Qt", + "ENABLE_QT_GUI": "ON" + }, + "vendor": { + "microsoft.com/VisualStudioSettings/CMake/1.0": { + "intelliSenseMode": "windows-clang-x64" + } + } + }, { "name": "x64-Clang-Release", "displayName": "Clang x64 Release", @@ -40,6 +58,24 @@ } } }, + { + "name": "x64-Clang-Release-Qt", + "displayName": "Clang x64 Release with Qt", + "generator": "Ninja", + "binaryDir": "${sourceDir}/Build/x64-Clang-Release-Qt", + "cacheVariables": { + "CMAKE_C_COMPILER": "clang-cl", + "CMAKE_CXX_COMPILER": "clang-cl", + "CMAKE_BUILD_TYPE": "Release", + "CMAKE_INSTALL_PREFIX": "${sourceDir}/Install/x64-Clang-Release-Qt", + "ENABLE_QT_GUI": "ON" + }, + "vendor": { + "microsoft.com/VisualStudioSettings/CMake/1.0": { + "intelliSenseMode": "windows-clang-x64" + } + } + }, { "name": "x64-Clang-RelWithDebInfo", "displayName": "Clang x64 RelWithDebInfo", @@ -56,6 +92,24 @@ "intelliSenseMode": "windows-clang-x64" } } + }, + { + "name": "x64-Clang-RelWithDebInfo-Qt", + "displayName": "Clang x64 RelWithDebInfo with Qt", + "generator": "Ninja", + "binaryDir": "${sourceDir}/Build/x64-Clang-RelWithDebInfo-Qt", + "cacheVariables": { + "CMAKE_C_COMPILER": "clang-cl", + "CMAKE_CXX_COMPILER": "clang-cl", + "CMAKE_BUILD_TYPE": "RelWithDebInfo", + "CMAKE_INSTALL_PREFIX": "${sourceDir}/Install/x64-Clang-RelWithDebInfo-Qt", + "ENABLE_QT_GUI": "ON" + }, + "vendor": { + "microsoft.com/VisualStudioSettings/CMake/1.0": { + "intelliSenseMode": "windows-clang-x64" + } + } } ] } diff --git a/cmake/FindQt.cmake b/cmake/FindQt.cmake new file mode 100644 index 000000000..bff3b6a51 --- /dev/null +++ b/cmake/FindQt.cmake @@ -0,0 +1,12 @@ +if(WIN32 AND NOT CMAKE_PREFIX_PATH) + file(GLOB QT_KITS LIST_DIRECTORIES true "C:/Qt/*/msvc*") + list(SORT QT_KITS COMPARE NATURAL) + list(REVERSE QT_KITS) + list(GET QT_KITS 0 QT_PREFIX) + if(QT_PREFIX) + set(CMAKE_PREFIX_PATH "${QT_PREFIX}" CACHE PATH "Qt prefix auto‑detected" FORCE) + message(STATUS "Auto-detected Qt prefix: ${QT_PREFIX}") + else() + message(WARNING "findQt.cmake: no Qt‑Directory found in C:/Qt – please set CMAKE_PREFIX_PATH manually") + endif() +endif() From e4f19145d6ff111f48a26b42fa973bc6472bae83 Mon Sep 17 00:00:00 2001 From: Fire Cube Date: Sat, 21 Jun 2025 21:33:56 +0200 Subject: [PATCH 21/27] adjust CMakeSettings.json --- CMakeSettings.json | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/CMakeSettings.json b/CMakeSettings.json index bb522fcfc..e1ed36887 100644 --- a/CMakeSettings.json +++ b/CMakeSettings.json @@ -12,6 +12,18 @@ "inheritEnvironments": [ "clang_cl_x64_x64" ], "intelliSenseMode": "windows-clang-x64" }, + { + "name": "x64-Clang-Release-Qt", + "generator": "Ninja", + "configurationType": "Release", + "buildRoot": "${projectDir}\\Build\\${name}", + "installRoot": "${projectDir}\\Install\\${name}", + "cmakeCommandArgs": "-DENABLE_QT_GUI=ON", + "buildCommandArgs": "", + "ctestCommandArgs": "", + "inheritEnvironments": [ "clang_cl_x64_x64" ], + "intelliSenseMode": "windows-clang-x64" + }, { "name": "x64-Clang-Debug", "generator": "Ninja", @@ -24,6 +36,18 @@ "inheritEnvironments": [ "clang_cl_x64_x64" ], "intelliSenseMode": "windows-clang-x64" }, + { + "name": "x64-Clang-Debug-Qt", + "generator": "Ninja", + "configurationType": "Debug", + "buildRoot": "${projectDir}\\Build\\${name}", + "installRoot": "${projectDir}\\Install\\${name}", + "cmakeCommandArgs": "-DENABLE_QT_GUI=ON", + "buildCommandArgs": "", + "ctestCommandArgs": "", + "inheritEnvironments": [ "clang_cl_x64_x64" ], + "intelliSenseMode": "windows-clang-x64" + }, { "name": "x64-Clang-RelWithDebInfo", "generator": "Ninja", @@ -35,6 +59,18 @@ "ctestCommandArgs": "", "inheritEnvironments": [ "clang_cl_x64_x64" ], "intelliSenseMode": "windows-clang-x64" + }, + { + "name": "x64-Clang-RelWithDebInfo-Qt", + "generator": "Ninja", + "configurationType": "RelWithDebInfo", + "buildRoot": "${projectDir}\\Build\\${name}", + "installRoot": "${projectDir}\\Install\\${name}", + "cmakeCommandArgs": "-DENABLE_QT_GUI=ON", + "buildCommandArgs": "", + "ctestCommandArgs": "", + "inheritEnvironments": [ "clang_cl_x64_x64" ], + "intelliSenseMode": "windows-clang-x64" } ] } \ No newline at end of file From bee3f1075d20071d5a36a3ce64894d560f44b8bf Mon Sep 17 00:00:00 2001 From: Fire Cube Date: Sat, 21 Jun 2025 21:36:12 +0200 Subject: [PATCH 22/27] add FindQt.cmake to reuse --- cmake/FindQt.cmake | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmake/FindQt.cmake b/cmake/FindQt.cmake index bff3b6a51..d568c55ad 100644 --- a/cmake/FindQt.cmake +++ b/cmake/FindQt.cmake @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +# SPDX-License-Identifier: GPL-2.0-or-later + if(WIN32 AND NOT CMAKE_PREFIX_PATH) file(GLOB QT_KITS LIST_DIRECTORIES true "C:/Qt/*/msvc*") list(SORT QT_KITS COMPARE NATURAL) From 321ed8b26768721c148264fc9f7beae3a775c69c Mon Sep 17 00:00:00 2001 From: Fire Cube Date: Sun, 22 Jun 2025 19:23:54 +0200 Subject: [PATCH 23/27] rename cmake file, add check before running cmake and add inheritation to presets --- CMakeLists.txt | 4 +- CMakePresets.json | 75 ++++++++++---------------------- cmake/DetectQtInstallation.cmake | 14 ++++++ cmake/FindQt.cmake | 15 ------- 4 files changed, 40 insertions(+), 68 deletions(-) create mode 100644 cmake/DetectQtInstallation.cmake delete mode 100644 cmake/FindQt.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 80f326432..8d50e3bf4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -214,7 +214,9 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/common/scm_rev.cpp.in" "${CMAKE_ message("end git things, remote: ${GIT_REMOTE_NAME}, branch: ${GIT_BRANCH}") -include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/findQt.cmake") +if(WIN32 AND ENABLE_QT_GUI AND NOT CMAKE_PREFIX_PATH) + include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/DetectQtInstallation.cmake") +endif () list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") find_package(Boost 1.84.0 CONFIG) diff --git a/CMakePresets.json b/CMakePresets.json index 454b4e767..2aeb0f064 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -6,6 +6,22 @@ "patch": 0 }, "configurePresets": [ + { + "name": "x64-Clang-Base", + "hidden": true, + "generator": "Ninja", + "binaryDir": "${sourceDir}/Build/${presetName}", + "cacheVariables": { + "CMAKE_C_COMPILER": "clang-cl", + "CMAKE_CXX_COMPILER": "clang-cl", + "CMAKE_INSTALL_PREFIX": "${sourceDir}/Build/${presetName}" + }, + "vendor": { + "microsoft.com/VisualStudioSettings/CMake/1.0": { + "intelliSenseMode": "windows-clang-x64" + } + } + }, { "name": "x64-Clang-Debug", "displayName": "Clang x64 Debug", @@ -26,89 +42,44 @@ { "name": "x64-Clang-Debug-Qt", "displayName": "Clang x64 Debug with Qt", - "generator": "Ninja", - "binaryDir": "${sourceDir}/Build/x64-Clang-Debug-Qt", + "inherits": ["x64-Clang-Base"], "cacheVariables": { - "CMAKE_C_COMPILER": "clang-cl", - "CMAKE_CXX_COMPILER": "clang-cl", "CMAKE_BUILD_TYPE": "Debug", - "CMAKE_INSTALL_PREFIX": "${sourceDir}/Install/x64-Clang-Debug-Qt", "ENABLE_QT_GUI": "ON" - }, - "vendor": { - "microsoft.com/VisualStudioSettings/CMake/1.0": { - "intelliSenseMode": "windows-clang-x64" - } } }, { "name": "x64-Clang-Release", "displayName": "Clang x64 Release", - "generator": "Ninja", - "binaryDir": "${sourceDir}/Build/x64-Clang-Release", + "inherits": ["x64-Clang-Base"], "cacheVariables": { - "CMAKE_C_COMPILER": "clang-cl", - "CMAKE_CXX_COMPILER": "clang-cl", - "CMAKE_BUILD_TYPE": "Release", - "CMAKE_INSTALL_PREFIX": "${sourceDir}/Install/x64-Clang-Release" - }, - "vendor": { - "microsoft.com/VisualStudioSettings/CMake/1.0": { - "intelliSenseMode": "windows-clang-x64" - } + "CMAKE_BUILD_TYPE": "Release" } }, { "name": "x64-Clang-Release-Qt", "displayName": "Clang x64 Release with Qt", - "generator": "Ninja", - "binaryDir": "${sourceDir}/Build/x64-Clang-Release-Qt", + "inherits": ["x64-Clang-Base"], "cacheVariables": { - "CMAKE_C_COMPILER": "clang-cl", - "CMAKE_CXX_COMPILER": "clang-cl", "CMAKE_BUILD_TYPE": "Release", - "CMAKE_INSTALL_PREFIX": "${sourceDir}/Install/x64-Clang-Release-Qt", "ENABLE_QT_GUI": "ON" - }, - "vendor": { - "microsoft.com/VisualStudioSettings/CMake/1.0": { - "intelliSenseMode": "windows-clang-x64" - } } }, { "name": "x64-Clang-RelWithDebInfo", "displayName": "Clang x64 RelWithDebInfo", - "generator": "Ninja", - "binaryDir": "${sourceDir}/Build/x64-Clang-RelWithDebInfo", + "inherits": ["x64-Clang-Base"], "cacheVariables": { - "CMAKE_C_COMPILER": "clang-cl", - "CMAKE_CXX_COMPILER": "clang-cl", - "CMAKE_BUILD_TYPE": "RelWithDebInfo", - "CMAKE_INSTALL_PREFIX": "${sourceDir}/Install/x64-Clang-RelWithDebInfo" - }, - "vendor": { - "microsoft.com/VisualStudioSettings/CMake/1.0": { - "intelliSenseMode": "windows-clang-x64" - } + "CMAKE_BUILD_TYPE": "RelWithDebInfo" } }, { "name": "x64-Clang-RelWithDebInfo-Qt", "displayName": "Clang x64 RelWithDebInfo with Qt", - "generator": "Ninja", - "binaryDir": "${sourceDir}/Build/x64-Clang-RelWithDebInfo-Qt", + "inherits": ["x64-Clang-Base"], "cacheVariables": { - "CMAKE_C_COMPILER": "clang-cl", - "CMAKE_CXX_COMPILER": "clang-cl", "CMAKE_BUILD_TYPE": "RelWithDebInfo", - "CMAKE_INSTALL_PREFIX": "${sourceDir}/Install/x64-Clang-RelWithDebInfo-Qt", "ENABLE_QT_GUI": "ON" - }, - "vendor": { - "microsoft.com/VisualStudioSettings/CMake/1.0": { - "intelliSenseMode": "windows-clang-x64" - } } } ] diff --git a/cmake/DetectQtInstallation.cmake b/cmake/DetectQtInstallation.cmake new file mode 100644 index 000000000..0f1dd6a8b --- /dev/null +++ b/cmake/DetectQtInstallation.cmake @@ -0,0 +1,14 @@ +# SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +# SPDX-License-Identifier: GPL-2.0-or-later + +file(GLOB QT_KITS LIST_DIRECTORIES true "C:/Qt/*/msvc*") +list(SORT QT_KITS COMPARE NATURAL) +list(REVERSE QT_KITS) +list(GET QT_KITS 0 QT_PREFIX) +if(QT_PREFIX) + set(CMAKE_PREFIX_PATH "${QT_PREFIX}" CACHE PATH "Qt prefix auto‑detected" FORCE) + message(STATUS "Auto-detected Qt prefix: ${QT_PREFIX}") +else() + message(WARNING "findQt.cmake: no Qt‑Directory found in C:/Qt – please set CMAKE_PREFIX_PATH manually") +endif() + diff --git a/cmake/FindQt.cmake b/cmake/FindQt.cmake deleted file mode 100644 index d568c55ad..000000000 --- a/cmake/FindQt.cmake +++ /dev/null @@ -1,15 +0,0 @@ -# SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -# SPDX-License-Identifier: GPL-2.0-or-later - -if(WIN32 AND NOT CMAKE_PREFIX_PATH) - file(GLOB QT_KITS LIST_DIRECTORIES true "C:/Qt/*/msvc*") - list(SORT QT_KITS COMPARE NATURAL) - list(REVERSE QT_KITS) - list(GET QT_KITS 0 QT_PREFIX) - if(QT_PREFIX) - set(CMAKE_PREFIX_PATH "${QT_PREFIX}" CACHE PATH "Qt prefix auto‑detected" FORCE) - message(STATUS "Auto-detected Qt prefix: ${QT_PREFIX}") - else() - message(WARNING "findQt.cmake: no Qt‑Directory found in C:/Qt – please set CMAKE_PREFIX_PATH manually") - endif() -endif() From 06cae185c9a2aae7dd361353583edfe2f16f151f Mon Sep 17 00:00:00 2001 From: Fire Cube Date: Sun, 22 Jun 2025 19:36:19 +0200 Subject: [PATCH 24/27] add error check in cmake --- cmake/DetectQtInstallation.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/DetectQtInstallation.cmake b/cmake/DetectQtInstallation.cmake index 0f1dd6a8b..d482ed9c7 100644 --- a/cmake/DetectQtInstallation.cmake +++ b/cmake/DetectQtInstallation.cmake @@ -4,8 +4,8 @@ file(GLOB QT_KITS LIST_DIRECTORIES true "C:/Qt/*/msvc*") list(SORT QT_KITS COMPARE NATURAL) list(REVERSE QT_KITS) -list(GET QT_KITS 0 QT_PREFIX) -if(QT_PREFIX) +if(QT_KITS) + list(GET QT_KITS 0 QT_PREFIX) set(CMAKE_PREFIX_PATH "${QT_PREFIX}" CACHE PATH "Qt prefix auto‑detected" FORCE) message(STATUS "Auto-detected Qt prefix: ${QT_PREFIX}") else() From 85b42b6cf85e132c1fddbf6ab8eaaf8458519ae2 Mon Sep 17 00:00:00 2001 From: Fire Cube Date: Tue, 24 Jun 2025 19:03:28 +0200 Subject: [PATCH 25/27] remove german comments --- .../renderer_vulkan/shader_cache.cpp | 23 ------------------- 1 file changed, 23 deletions(-) diff --git a/src/video_core/renderer_vulkan/shader_cache.cpp b/src/video_core/renderer_vulkan/shader_cache.cpp index 28df9d209..0ae720413 100644 --- a/src/video_core/renderer_vulkan/shader_cache.cpp +++ b/src/video_core/renderer_vulkan/shader_cache.cpp @@ -27,9 +27,6 @@ std::unordered_map> g_ud_storage; u64 CalculateSpecializationHash(const Shader::StageSpecialization& spec) { u64 hash = 0; - // Start mit dem Hash der RuntimeInfo - // Die RuntimeInfo enthält verschiedene Unions, daher müssen wir basierend auf dem Stage-Typ - // hashen const auto& runtime_info = spec.runtime_info; hash = HashCombine(hash, static_cast(runtime_info.stage)); hash = HashCombine(hash, runtime_info.num_user_data); @@ -38,7 +35,6 @@ u64 CalculateSpecializationHash(const Shader::StageSpecialization& spec) { hash = HashCombine(hash, static_cast(runtime_info.fp_denorm_mode32)); hash = HashCombine(hash, static_cast(runtime_info.fp_round_mode32)); - // Abhängig vom Stage-Typ die spezifischen RuntimeInfo-Felder hashen switch (runtime_info.stage) { case Shader::Stage::Local: hash = HashCombine(hash, runtime_info.ls_info.ls_stride); @@ -49,7 +45,6 @@ u64 CalculateSpecializationHash(const Shader::StageSpecialization& spec) { break; case Shader::Stage::Vertex: hash = HashCombine(hash, runtime_info.vs_info.num_outputs); - // Hash der Output-Maps for (size_t i = 0; i < runtime_info.vs_info.num_outputs && i < runtime_info.vs_info.outputs.size(); ++i) { const auto& output_map = runtime_info.vs_info.outputs[i]; @@ -78,7 +73,6 @@ u64 CalculateSpecializationHash(const Shader::StageSpecialization& spec) { hash = HashCombine(hash, runtime_info.gs_info.in_vertex_data_size); hash = HashCombine(hash, runtime_info.gs_info.out_vertex_data_size); hash = HashCombine(hash, static_cast(runtime_info.gs_info.in_primitive)); - // Hash der Output-Primitive-Types für alle Streams for (const auto& out_prim : runtime_info.gs_info.out_primitive) { hash = HashCombine(hash, static_cast(out_prim)); } @@ -89,7 +83,6 @@ u64 CalculateSpecializationHash(const Shader::StageSpecialization& spec) { hash = HashCombine(hash, runtime_info.fs_info.addr_flags.raw); hash = HashCombine(hash, runtime_info.fs_info.num_inputs); - // Hash der PS-Inputs for (u32 i = 0; i < runtime_info.fs_info.num_inputs && i < runtime_info.fs_info.inputs.size(); ++i) { const auto& input = runtime_info.fs_info.inputs[i]; @@ -99,7 +92,6 @@ u64 CalculateSpecializationHash(const Shader::StageSpecialization& spec) { hash = HashCombine(hash, input.default_value); } - // Hash der ColorBuffers for (const auto& color_buffer : runtime_info.fs_info.color_buffers) { hash = HashCombine(hash, static_cast(color_buffer.num_format)); hash = HashCombine(hash, static_cast(color_buffer.num_conversion)); @@ -120,14 +112,12 @@ u64 CalculateSpecializationHash(const Shader::StageSpecialization& spec) { break; } - // Hash des FetchShader-Daten if (spec.fetch_shader_data) { const auto& fetch_shader = *spec.fetch_shader_data; hash = HashCombine(hash, fetch_shader.size); hash = HashCombine(hash, static_cast(fetch_shader.vertex_offset_sgpr)); hash = HashCombine(hash, static_cast(fetch_shader.instance_offset_sgpr)); - // Hash der Attribute for (const auto& attr : fetch_shader.attributes) { hash = HashCombine(hash, static_cast(attr.semantic)); hash = HashCombine(hash, static_cast(attr.dest_vgpr)); @@ -138,7 +128,6 @@ u64 CalculateSpecializationHash(const Shader::StageSpecialization& spec) { } } - // Hash der VS-Attribut-Spezialisierungen for (const auto& vs_attrib : spec.vs_attribs) { hash = HashCombine(hash, vs_attrib.num_components); hash = HashCombine(hash, static_cast(vs_attrib.num_class)); @@ -148,7 +137,6 @@ u64 CalculateSpecializationHash(const Shader::StageSpecialization& spec) { hash = HashCombine(hash, vs_attrib.dst_select.a); } - // Hash des Bitsets const std::string bitset_str = spec.bitset.to_string(); for (size_t i = 0; i < bitset_str.size(); i += 8) { size_t end = std::min(i + 8, bitset_str.size()); @@ -162,7 +150,6 @@ u64 CalculateSpecializationHash(const Shader::StageSpecialization& spec) { hash = HashCombine(hash, value); } - // Hash der Buffer-Spezialisierungen for (const auto& buffer : spec.buffers) { hash = HashCombine(hash, buffer.stride); hash = HashCombine(hash, buffer.is_storage); @@ -185,7 +172,6 @@ u64 CalculateSpecializationHash(const Shader::StageSpecialization& spec) { } } - // Hash der Bild-Spezialisierungen for (const auto& image : spec.images) { hash = HashCombine(hash, static_cast(image.type)); hash = HashCombine(hash, image.is_integer); @@ -202,23 +188,19 @@ u64 CalculateSpecializationHash(const Shader::StageSpecialization& spec) { hash = HashCombine(hash, static_cast(image.num_conversion)); } - // Hash der FMask-Spezialisierungen for (const auto& fmask : spec.fmasks) { hash = HashCombine(hash, fmask.width); hash = HashCombine(hash, fmask.height); } - // Hash der Sampler-Spezialisierungen for (const auto& sampler : spec.samplers) { hash = HashCombine(hash, sampler.force_unnormalized); } - // Hash der Start-Bindings hash = HashCombine(hash, spec.start.buffer); hash = HashCombine(hash, spec.start.unified); hash = HashCombine(hash, spec.start.user_data); - // Hash vom info pointer if (spec.info) { hash = HashCombine(hash, spec.info->pgm_hash); hash = HashCombine(hash, static_cast(spec.info->stage)); @@ -243,7 +225,6 @@ u64 CalculateSpecializationHash(const Shader::StageSpecialization& spec) { hash = HashCombine(hash, spec.info->has_fetch_shader); hash = HashCombine(hash, spec.info->fetch_shader_sgpr_base); - // Hash der Flags für loads und stores for (size_t i = 0; i < spec.info->loads.flags.size(); ++i) { hash = HashCombine(hash, spec.info->loads.flags[i]); } @@ -252,10 +233,8 @@ u64 CalculateSpecializationHash(const Shader::StageSpecialization& spec) { hash = HashCombine(hash, spec.info->stores.flags[i]); } - // Hash der UserDataMask hash = HashCombine(hash, spec.info->ud_mask.mask); - // Hash der uses_patches hash = HashCombine(hash, spec.info->uses_patches); } @@ -263,10 +242,8 @@ u64 CalculateSpecializationHash(const Shader::StageSpecialization& spec) { } void SerializeInfo(std::ostream& info_serialized, Shader::Info info) { - // UD Mask writeBin(info_serialized, info.ud_mask.mask); - // Buffer-Resources u32 bufferCount = static_cast(info.buffers.size()); writeBin(info_serialized, bufferCount); // Buffer Amount From 469c8fc241f915f3a5d70e8a1d9a4226167cf877 Mon Sep 17 00:00:00 2001 From: Fire Cube Date: Tue, 24 Jun 2025 20:09:59 +0200 Subject: [PATCH 26/27] many things --- .../renderer_vulkan/shader_cache.cpp | 158 ++++++------------ 1 file changed, 50 insertions(+), 108 deletions(-) diff --git a/src/video_core/renderer_vulkan/shader_cache.cpp b/src/video_core/renderer_vulkan/shader_cache.cpp index 0ae720413..542f12433 100644 --- a/src/video_core/renderer_vulkan/shader_cache.cpp +++ b/src/video_core/renderer_vulkan/shader_cache.cpp @@ -212,7 +212,6 @@ u64 CalculateSpecializationHash(const Shader::StageSpecialization& spec) { hash = HashCombine(hash, spec.info->uses_lane_id); hash = HashCombine(hash, spec.info->uses_group_quad); hash = HashCombine(hash, spec.info->uses_group_ballot); - hash = HashCombine(hash, spec.info->uses_shared); hash = HashCombine(hash, spec.info->uses_fp16); hash = HashCombine(hash, spec.info->uses_fp64); hash = HashCombine(hash, spec.info->uses_pack_10_11_11); @@ -220,7 +219,6 @@ u64 CalculateSpecializationHash(const Shader::StageSpecialization& spec) { hash = HashCombine(hash, spec.info->stores_tess_level_outer); hash = HashCombine(hash, spec.info->stores_tess_level_inner); hash = HashCombine(hash, spec.info->translation_failed); - hash = HashCombine(hash, spec.info->has_readconst); hash = HashCombine(hash, spec.info->mrt_mask); hash = HashCombine(hash, spec.info->has_fetch_shader); hash = HashCombine(hash, spec.info->fetch_shader_sgpr_base); @@ -292,14 +290,29 @@ void SerializeInfo(std::ostream& info_serialized, Shader::Info info) { writeBin(info_serialized, samplerCount); // Sampler Amount for (const auto& sampler : info.samplers) { - writeBin(info_serialized, sampler.sharp_idx); - writeBin(info_serialized, sampler.associated_image); - writeBin(info_serialized, sampler.disable_aniso); + if (std::holds_alternative(sampler.sampler)) + { + std::uint8_t tag = 0; + writeBin(info_serialized, tag); - writeBin(info_serialized, sampler.inline_sampler.raw0); - writeBin(info_serialized, sampler.inline_sampler.raw1); + u32 sharp_idx = std::get(sampler.sampler); + writeBin(info_serialized, sharp_idx); + } + else + { + std::uint8_t tag = 1; + writeBin(info_serialized, tag); + const AmdGpu::Sampler& hw_sampler = + std::get(sampler.sampler); + writeBin(info_serialized, hw_sampler); + } + std::uint8_t packed = + static_cast((sampler.disable_aniso & 0x1) << 4) | + static_cast(sampler.associated_image & 0xF); + + writeBin(info_serialized, packed); } // FMask-Resources @@ -316,9 +329,7 @@ void SerializeInfo(std::ostream& info_serialized, Shader::Info info) { for (auto const& [loc, attr_pair] : info.gs_copy_data.attr_map) { writeBin(info_serialized, loc); - // Das erste Element des Paars ist ein Shader::IR::Attribute, ein Enum writeBin(info_serialized, static_cast(attr_pair.first)); - // Das zweite Element ist ein u32 writeBin(info_serialized, attr_pair.second); } @@ -333,33 +344,7 @@ void SerializeInfo(std::ostream& info_serialized, Shader::Info info) { } writeBin(info_serialized, info.srt_info.flattened_bufsize_dw); - bool has_walker_func = (info.srt_info.walker_func != nullptr); - writeBin(info_serialized, static_cast(has_walker_func ? 1 : 0)); - if (has_walker_func) { - // Größe des JIT-Codes ermitteln - const u8* walker_start = reinterpret_cast(info.srt_info.walker_func); - - // Wir müssen die Größe des generierten Codes bestimmen - // Dies kann aus der Xbyak::CodeGenerator Instanz extrahiert werden - // Alternativ können wir die Distanz zum nächsten Ret-Befehl berechnen - size_t walker_size = 0; - const u8* ptr = walker_start; - const u32 MAX_CODE_SIZE = 4096; // Sicherheitsbegrenzung - - // Suche nach Ret-Befehl (C3 in x86/x64) - for (walker_size = 0; walker_size < MAX_CODE_SIZE; walker_size++) { - // Einfacher Ret-Befehl (C3) - if (ptr[walker_size] == 0xC3) { - walker_size++; // Ret einschließen - break; - } - } - - // Speichere Größe und JIT-Code - writeBin(info_serialized, static_cast(walker_size)); - info_serialized.write(reinterpret_cast(walker_start), walker_size); - } // Flat UD u32 flatCount = static_cast(info.flattened_ud_buf.size()); @@ -381,7 +366,6 @@ void SerializeInfo(std::ostream& info_serialized, Shader::Info info) { writeBin(info_serialized, static_cast(info.uses_lane_id ? 1 : 0)); writeBin(info_serialized, static_cast(info.uses_group_quad ? 1 : 0)); writeBin(info_serialized, static_cast(info.uses_group_ballot ? 1 : 0)); - writeBin(info_serialized, static_cast(info.uses_shared ? 1 : 0)); writeBin(info_serialized, static_cast(info.uses_fp16 ? 1 : 0)); writeBin(info_serialized, static_cast(info.uses_fp64 ? 1 : 0)); writeBin(info_serialized, static_cast(info.uses_pack_10_11_11 ? 1 : 0)); @@ -389,7 +373,6 @@ void SerializeInfo(std::ostream& info_serialized, Shader::Info info) { writeBin(info_serialized, static_cast(info.stores_tess_level_outer ? 1 : 0)); writeBin(info_serialized, static_cast(info.stores_tess_level_inner ? 1 : 0)); writeBin(info_serialized, static_cast(info.translation_failed ? 1 : 0)); - writeBin(info_serialized, static_cast(info.has_readconst ? 1 : 0)); // MRT Mask writeBin(info_serialized, info.mrt_mask); @@ -404,14 +387,14 @@ void SerializeInfo(std::ostream& info_serialized, Shader::Info info) { writeBin(info_serialized, info.l_stage); writeBin(info_serialized, info.pgm_hash); - // AttributeFlags für loads + // AttributeFlags for loads u32 loads_size = static_cast(info.loads.flags.size()); writeBin(info_serialized, loads_size); for (size_t i = 0; i < info.loads.flags.size(); ++i) { writeBin(info_serialized, info.loads.flags[i]); } - // AttributeFlags für stores + // AttributeFlags for stores u32 stores_size = static_cast(info.stores.flags.size()); writeBin(info_serialized, stores_size); for (size_t i = 0; i < info.stores.flags.size(); ++i) { @@ -555,22 +538,32 @@ void DeserializeInfo(std::istream& info_serialized, Shader::Info& info) { info.samplers.clear(); info.samplers.reserve(samplerCount); - for (u32 i = 0; i < samplerCount; ++i) { - Shader::SamplerResource sampler; - readBin(info_serialized, sampler.sharp_idx); + for (u32 i = 0; i < samplerCount; ++i) + { + std::uint8_t tag; + readBin(info_serialized, tag); - u32 associated_image; - readBin(info_serialized, associated_image); - sampler.associated_image = associated_image; + Shader::SamplerResource sampler{0, 0, false}; // Dummy-Init - u32 disable_aniso; - readBin(info_serialized, disable_aniso); - sampler.disable_aniso = disable_aniso; + if (tag == 0) + { + u32 sharp_idx; + readBin(info_serialized, sharp_idx); + sampler.sampler = sharp_idx; + } + else + { + AmdGpu::Sampler hw_sampler; + readBin(info_serialized, hw_sampler); + sampler.sampler = hw_sampler; + } + + std::uint8_t packed; + readBin(info_serialized, packed); + + sampler.associated_image = packed & 0xF; + sampler.disable_aniso = (packed >> 4) & 0x1; - // Inline-Sampler deserialisieren - readBin(info_serialized, sampler.inline_sampler.raw0); - readBin(info_serialized, sampler.inline_sampler.raw1); - info.samplers.push_back(std::move(sampler)); } @@ -598,11 +591,7 @@ void DeserializeInfo(std::istream& info_serialized, Shader::Info& info) { readBin(info_serialized, loc); readBin(info_serialized, attribute_value); readBin(info_serialized, idx); - - // Umwandeln des numerischen Werts zurück in das Shader::IR::Attribute-Enum Shader::IR::Attribute attribute = static_cast(attribute_value); - - // Einfügen in die Map mit dem richtigen Paar-Typ info.gs_copy_data.attr_map.emplace(loc, std::make_pair(attribute, idx)); } @@ -620,36 +609,7 @@ void DeserializeInfo(std::istream& info_serialized, Shader::Info& info) { } readBin(info_serialized, info.srt_info.flattened_bufsize_dw); - // Laden des walker_func JIT-Codes - u8 has_walker_func; - readBin(info_serialized, has_walker_func); - if (has_walker_func == 1) { - // Größe des JIT-Codes lesen - u32 walker_size; - readBin(info_serialized, walker_size); - - // Speicher für ausführbaren Code allokieren - void* code_memory = nullptr; -#ifdef _WIN32 - code_memory = - VirtualAlloc(nullptr, walker_size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); -#else - code_memory = mmap(nullptr, walker_size, PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); -#endif - - if (!code_memory) { - LOG_ERROR(Render_Vulkan, "Konnte keinen ausführbaren Speicher für JIT-Code allokieren"); - return; - } - - // JIT-Code laden - info_serialized.read(reinterpret_cast(code_memory), walker_size); - - // JIT-Funktion zuweisen - info.srt_info.walker_func = reinterpret_cast(code_memory); - } // Flat UD u32 flatCount; @@ -684,8 +644,6 @@ void DeserializeInfo(std::istream& info_serialized, Shader::Info& info) { readBin(info_serialized, flag_value); info.uses_group_ballot = (flag_value == 1); readBin(info_serialized, flag_value); - info.uses_shared = (flag_value == 1); - readBin(info_serialized, flag_value); info.uses_fp16 = (flag_value == 1); readBin(info_serialized, flag_value); info.uses_fp64 = (flag_value == 1); @@ -699,8 +657,6 @@ void DeserializeInfo(std::istream& info_serialized, Shader::Info& info) { info.stores_tess_level_inner = (flag_value == 1); readBin(info_serialized, flag_value); info.translation_failed = (flag_value == 1); - readBin(info_serialized, flag_value); - info.has_readconst = (flag_value == 1); // MRT Mask readBin(info_serialized, info.mrt_mask); @@ -716,14 +672,14 @@ void DeserializeInfo(std::istream& info_serialized, Shader::Info& info) { readBin(info_serialized, info.l_stage); readBin(info_serialized, info.pgm_hash); - // AttributeFlags für loads + // AttributeFlags for loads u32 loads_size; readBin(info_serialized, loads_size); for (size_t i = 0; i < loads_size; ++i) { readBin(info_serialized, info.loads.flags[i]); } - // AttributeFlags für stores + // AttributeFlags for stores u32 stores_size; readBin(info_serialized, stores_size); for (size_t i = 0; i < stores_size; ++i) { @@ -750,18 +706,11 @@ void DeserializeInfo(std::istream& info_serialized, Shader::Info& info) { // Check if there are any remaining bytes in the stream if (info_serialized.peek() != EOF) { - LOG_WARNING(Render_Vulkan, "Es sind noch Bytes im Stream übrig"); + LOG_WARNING(Render_Vulkan, "There are remaining bytes in the cache file"); } } bool CheckShaderCache(std::string shader_id) { - // Überprüfen, ob das Verzeichnis existiert - if (!std::filesystem::exists(shader_cache_dir)) { - LOG_INFO(Render_Vulkan, "Shader-Cache-Verzeichnis existiert nicht"); - return false; - } - - // Überprüfen, ob sowohl die SPIR-V-Datei als auch die Ressourcendatei existieren std::filesystem::path spirv_cache_file_path = shader_cache_dir / (shader_id + ".spv"); std::filesystem::path resources_file_path = shader_cache_dir / (shader_id + ".resources"); @@ -776,7 +725,6 @@ bool CheckShaderCache(std::string shader_id) { return false; } - // Überprüfen, ob die Dateien lesbar und nicht leer sind Common::FS::IOFile spirv_file(spirv_cache_file_path, Common::FS::FileAccessMode::Read); Common::FS::IOFile resources_file(resources_file_path, Common::FS::FileAccessMode::Read); @@ -787,8 +735,7 @@ bool CheckShaderCache(std::string shader_id) { resources_file.Close(); if (!spirv_valid || !resources_valid) { - LOG_WARNING(Render_Vulkan, "Ungueltige Dateien im Shader-Cache für ID: {}", shader_id); - // Fehlerhafte Dateien entfernen, um zukünftige Probleme zu vermeiden + LOG_WARNING(Render_Vulkan, "Invalid cache file for shader with ID: {}", shader_id); if (std::filesystem::exists(spirv_cache_file_path)) { std::filesystem::remove(spirv_cache_file_path); } @@ -798,7 +745,7 @@ bool CheckShaderCache(std::string shader_id) { return false; } - LOG_INFO(Render_Vulkan, "Shader mit ID {} im Cache gefunden", shader_id); + LOG_INFO(Render_Vulkan, "Found shader with ID {} in the cache", shader_id); return true; } @@ -815,13 +762,11 @@ void GetShader(std::string shader_id, Shader::Info& info, std::vector& spv) Common::FS::IOFile resources_dump_file(resources_dump_file_path, Common::FS::FileAccessMode::Read); - // Lese die Ressourcendaten std::vector resources_data; resources_data.resize(resources_dump_file.GetSize()); resources_dump_file.Read(resources_data); resources_dump_file.Close(); - // Verarbeite die gespeicherten Daten std::istringstream combined_stream(std::string(resources_data.begin(), resources_data.end())); std::istringstream info_stream; @@ -831,19 +776,16 @@ void GetShader(std::string shader_id, Shader::Info& info, std::vector& spv) } void AddShader(std::string shader_id, std::vector spv, std::ostream& info_serialized) { - // SPIR-V-Datei speichern std::string spirv_cache_filename = shader_id + ".spv"; std::filesystem::path spirv_cache_file_path = shader_cache_dir / spirv_cache_filename; Common::FS::IOFile shader_cache_file(spirv_cache_file_path, Common::FS::FileAccessMode::Write); shader_cache_file.WriteSpan(std::span(spv)); shader_cache_file.Close(); - // Resources-Datei vorbereiten std::filesystem::path resources_dump_file_path = shader_cache_dir / (shader_id + ".resources"); Common::FS::IOFile resources_dump_file(resources_dump_file_path, Common::FS::FileAccessMode::Write); - // Die Streams müssen zurückgesetzt werden, bevor wir sie lesen können if (std::ostringstream* info_oss = dynamic_cast(&info_serialized)) { std::string info_data = info_oss->str(); resources_dump_file.WriteSpan(std::span(info_data.data(), info_data.size())); From 1e71ac8f997315e800bea844b78f8d837efc0de6 Mon Sep 17 00:00:00 2001 From: Fire Cube Date: Tue, 24 Jun 2025 20:16:43 +0200 Subject: [PATCH 27/27] should fix linux build --- src/video_core/renderer_vulkan/shader_cache.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/video_core/renderer_vulkan/shader_cache.cpp b/src/video_core/renderer_vulkan/shader_cache.cpp index 542f12433..7533674d1 100644 --- a/src/video_core/renderer_vulkan/shader_cache.cpp +++ b/src/video_core/renderer_vulkan/shader_cache.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #ifdef _WIN32 #include #else