From c7158912423d4782e98a9cca48be0c5dd5aeb93d Mon Sep 17 00:00:00 2001 From: "Mr. Big Britches" <111622360+MrBigBritches@users.noreply.github.com> Date: Tue, 20 Oct 2026 08:37:43 +0200 Subject: [PATCH] shader: memoize the tessellation layout per LS/HS pair and VGT configuration --- src/graphics/shader/shader.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/graphics/shader/shader.cpp b/src/graphics/shader/shader.cpp index d9f661d2c..f6339fceb 100644 --- a/src/graphics/shader/shader.cpp +++ b/src/graphics/shader/shader.cpp @@ -47,6 +47,8 @@ struct ShaderMapEntry { static std::unique_ptr> g_shader_map; static std::mutex g_shader_map_mutex; +static std::unordered_map g_tess_layouts; +static std::mutex g_tess_layouts_mutex; void ShaderInit() { EXIT_IF(g_shader_map != nullptr); @@ -652,7 +654,18 @@ PrepareTessellationPrograms(const HW::VertexShaderInfo& regs, const HW::Context& }; EXIT_IF(tess.input_control_points == 0 || tess.input_control_points > 32 || tess.output_control_points == 0 || tess.output_control_points > 32); - ShaderRecompiler::AnalyzeTessellationPrograms(params[0].code, params[1].code, tess); + // Reflection decodes both programs; the key also covers the VGT fields cached in tess. + const uint64_t key[] = {local_hash, control_hash, + uint64_t {sh.m_vgtLsHsConfig & 0xfff00u} << 32u | sh.m_vgtTfParam}; + { + std::scoped_lock lock(g_tess_layouts_mutex); + auto [entry, inserted] = g_tess_layouts.try_emplace(XXH3_64bits(key, sizeof(key)), tess); + if (inserted) { + ShaderRecompiler::AnalyzeTessellationPrograms(params[0].code, params[1].code, + entry->second); + } + tess = entry->second; + } for (auto& stage: input_info) { stage.tess = tess; }