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;