From c900c049c8d41a72f8be2837bbc3dd684909e1ae Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Fri, 10 Jan 2025 18:52:54 -0800 Subject: [PATCH] specialization: Fix uniform buffer size check. --- src/shader_recompiler/specialization.h | 38 +++++++++++++++---- .../renderer_vulkan/vk_pipeline_cache.cpp | 11 ++++-- 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/src/shader_recompiler/specialization.h b/src/shader_recompiler/specialization.h index 0a10542fefe..e48a42c5939 100644 --- a/src/shader_recompiler/specialization.h +++ b/src/shader_recompiler/specialization.h @@ -16,6 +16,10 @@ struct VsAttribSpecialization { AmdGpu::NumberClass num_class{}; auto operator<=>(const VsAttribSpecialization&) const = default; + + [[nodiscard]] bool IsCompatible(const VsAttribSpecialization& other) const { + return *this == other; + } }; struct BufferSpecialization { @@ -26,7 +30,7 @@ struct BufferSpecialization { u8 element_size : 2 = 0; u32 size = 0; - bool operator==(const BufferSpecialization& other) const { + [[nodiscard]] bool IsCompatible(const BufferSpecialization& other) const { return stride == other.stride && is_storage == other.is_storage && swizzle_enable == other.swizzle_enable && (!swizzle_enable || @@ -41,6 +45,10 @@ struct TextureBufferSpecialization { AmdGpu::NumberConversion num_conversion{}; auto operator<=>(const TextureBufferSpecialization&) const = default; + + [[nodiscard]] bool IsCompatible(const TextureBufferSpecialization& other) const { + return *this == other; + } }; struct ImageSpecialization { @@ -51,6 +59,10 @@ struct ImageSpecialization { AmdGpu::NumberConversion num_conversion{}; auto operator<=>(const ImageSpecialization&) const = default; + + [[nodiscard]] bool IsCompatible(const ImageSpecialization& other) const { + return *this == other; + } }; struct FMaskSpecialization { @@ -58,12 +70,20 @@ struct FMaskSpecialization { u32 height; auto operator<=>(const FMaskSpecialization&) const = default; + + [[nodiscard]] bool IsCompatible(const FMaskSpecialization& other) const { + return *this == other; + } }; struct SamplerSpecialization { bool force_unnormalized = false; auto operator<=>(const SamplerSpecialization&) const = default; + + [[nodiscard]] bool IsCompatible(const SamplerSpecialization& other) const { + return *this == other; + } }; /** @@ -179,7 +199,9 @@ struct StageSpecialization { } } - bool operator==(const StageSpecialization& other) const { + /// Checks if the permutation this specialization is for can be used in place of 'other'. + /// Note that this operation is not bidirectional. + [[nodiscard]] bool IsCompatible(const StageSpecialization& other) const { if (start != other.start) { return false; } @@ -190,7 +212,7 @@ struct StageSpecialization { return false; } for (u32 i = 0; i < vs_attribs.size(); i++) { - if (vs_attribs[i] != other.vs_attribs[i]) { + if (!vs_attribs[i].IsCompatible(other.vs_attribs[i])) { return false; } } @@ -202,27 +224,27 @@ struct StageSpecialization { binding++; } for (u32 i = 0; i < buffers.size(); i++) { - if (other.bitset[binding++] && buffers[i] != other.buffers[i]) { + if (other.bitset[binding++] && !buffers[i].IsCompatible(other.buffers[i])) { return false; } } for (u32 i = 0; i < tex_buffers.size(); i++) { - if (other.bitset[binding++] && tex_buffers[i] != other.tex_buffers[i]) { + if (other.bitset[binding++] && !tex_buffers[i].IsCompatible(other.tex_buffers[i])) { return false; } } for (u32 i = 0; i < images.size(); i++) { - if (other.bitset[binding++] && images[i] != other.images[i]) { + if (other.bitset[binding++] && !images[i].IsCompatible(other.images[i])) { return false; } } for (u32 i = 0; i < fmasks.size(); i++) { - if (other.bitset[binding++] && fmasks[i] != other.fmasks[i]) { + if (other.bitset[binding++] && !fmasks[i].IsCompatible(other.fmasks[i])) { return false; } } for (u32 i = 0; i < samplers.size(); i++) { - if (samplers[i] != other.samplers[i]) { + if (!samplers[i].IsCompatible(other.samplers[i])) { return false; } } diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index f934943899f..2033345eab5 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -517,8 +517,9 @@ PipelineCache::Result PipelineCache::GetProgram(Stage stage, LogicalStage l_stag 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); + const auto fetch_shader = spec.fetch_shader_data; program->AddPermut(module, std::move(spec)); - return std::make_tuple(&program->info, module, spec.fetch_shader_data, + return std::make_tuple(&program->info, module, fetch_shader, HashCombine(params.hash, 0)); } it_pgm.value()->info.user_data = params.user_data; @@ -527,10 +528,13 @@ PipelineCache::Result PipelineCache::GetProgram(Stage stage, LogicalStage l_stag auto& info = program->info; info.RefreshFlatBuf(); const auto spec = Shader::StageSpecialization(info, runtime_info, profile, binding); + const auto fetch_shader = spec.fetch_shader_data; size_t perm_idx = program->modules.size(); vk::ShaderModule module{}; - const auto it = std::ranges::find(program->modules, spec, &Program::Module::spec); + const auto it = std::ranges::find_if(program->modules, [&spec](const auto& module) { + return module.spec.IsCompatible(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); @@ -540,8 +544,7 @@ PipelineCache::Result PipelineCache::GetProgram(Stage stage, LogicalStage l_stag module = it->module; perm_idx = std::distance(program->modules.begin(), it); } - return std::make_tuple(&info, module, spec.fetch_shader_data, - HashCombine(params.hash, perm_idx)); + return std::make_tuple(&info, module, fetch_shader, HashCombine(params.hash, perm_idx)); } std::optional PipelineCache::ReplaceShader(vk::ShaderModule module,