From f010863ecec4c03af5b7ad7ffe0a40ab145f9cd7 Mon Sep 17 00:00:00 2001 From: PabloMK7 Date: Mon, 2 Feb 2026 18:25:03 +0100 Subject: [PATCH] video_core: vulkan: Only store hashes in shader cache maps (#1710) --- src/common/hash.h | 35 +++++++++++++++++++ .../renderer_vulkan/vk_pipeline_cache.cpp | 14 ++++---- .../renderer_vulkan/vk_pipeline_cache.h | 9 ++--- 3 files changed, 48 insertions(+), 10 deletions(-) diff --git a/src/common/hash.h b/src/common/hash.h index de7cf0536..1df29638a 100644 --- a/src/common/hash.h +++ b/src/common/hash.h @@ -6,6 +6,7 @@ #include #include +#include #include #include "cityhash.h" #include "common/common_types.h" @@ -99,4 +100,38 @@ struct HashableStruct { } }; +/// Helper struct that provides a hashable string with basic string API +template +struct HashableString { + std::string value; + + HashableString() = default; + HashableString(const std::string& s) : value(s) {} + HashableString(std::string&& s) noexcept : value(std::move(s)) {} + + std::size_t Hash() const noexcept { + return ComputeHash64(value.data(), value.size()); + } + + bool empty() const noexcept { + return value.empty(); + } + + std::size_t size() const noexcept { + return value.size(); + } + + const char* data() const noexcept { + return value.data(); + } + + operator std::string_view() const noexcept { + return value; + } + + operator std::string&&() && noexcept { + return std::move(value); + } +}; + } // namespace Common diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 3a730ab5f..4100ac509 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -408,16 +408,18 @@ bool PipelineCache::UseProgrammableVertexShader(const Pica::RegsInternal& regs, } } - const auto [it, new_config] = programmable_vertex_map.try_emplace(config); + const auto config_hash = config.Hash(); + + const auto [it, new_config] = programmable_vertex_map.try_emplace(config_hash); if (new_config) { - auto program = GLSL::GenerateVertexShader(setup, config, true); + auto program = Common::HashableString(GLSL::GenerateVertexShader(setup, config, true)); if (program.empty()) { LOG_ERROR(Render_Vulkan, "Failed to retrieve programmable vertex shader"); - programmable_vertex_map[config] = nullptr; + programmable_vertex_map[config_hash] = nullptr; return false; } - auto [iter, new_program] = programmable_vertex_cache.try_emplace(program, instance); + auto [iter, new_program] = programmable_vertex_cache.try_emplace(program.Hash(), instance); auto& shader = iter->second; if (new_program) { @@ -456,7 +458,7 @@ bool PipelineCache::UseFixedGeometryShader(const Pica::RegsInternal& regs) { } const PicaFixedGSConfig gs_config{regs, instance.IsShaderClipDistanceSupported()}; - auto [it, new_shader] = fixed_geometry_shaders.try_emplace(gs_config, instance); + auto [it, new_shader] = fixed_geometry_shaders.try_emplace(gs_config.Hash(), instance); auto& shader = it->second; if (new_shader) { @@ -481,7 +483,7 @@ void PipelineCache::UseTrivialGeometryShader() { void PipelineCache::UseFragmentShader(const Pica::RegsInternal& regs, const Pica::Shader::UserConfig& user) { const FSConfig fs_config{regs, user, profile}; - const auto [it, new_shader] = fragment_shaders.try_emplace(fs_config, instance); + const auto [it, new_shader] = fragment_shaders.try_emplace(fs_config.Hash(), instance); auto& shader = it->second; if (new_shader) { diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.h b/src/video_core/renderer_vulkan/vk_pipeline_cache.h index c4f2ea062..b7ae7011f 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.h +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.h @@ -135,10 +135,11 @@ private: std::array shader_hashes; std::array current_shaders; - std::unordered_map programmable_vertex_map; - std::unordered_map programmable_vertex_cache; - std::unordered_map fixed_geometry_shaders; - std::unordered_map fragment_shaders; + + std::unordered_map programmable_vertex_map; + std::unordered_map programmable_vertex_cache; + std::unordered_map fixed_geometry_shaders; + std::unordered_map fragment_shaders; Shader trivial_vertex_shader; u64 current_program_id{0};