From ec514fa08e9d4624db6a7948fdf4b1a0b6586963 Mon Sep 17 00:00:00 2001 From: IndecisiveTurtle Date: Sun, 1 Dec 2024 16:35:38 +0200 Subject: [PATCH] shader_recompiler: Specialize UBOs on size * Some games can perform manual vertex pulling and thus bind read only buffers of varying size. We only recompile when the vsharp size is larger than size in shader, in opposite case its not needed --- src/shader_recompiler/info.h | 2 +- src/shader_recompiler/specialization.h | 10 ++++++++-- src/video_core/renderer_vulkan/vk_rasterizer.cpp | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/shader_recompiler/info.h b/src/shader_recompiler/info.h index f2283f8bb..494bbb4bb 100644 --- a/src/shader_recompiler/info.h +++ b/src/shader_recompiler/info.h @@ -108,7 +108,7 @@ struct PushData { void AddTexelOffset(u32 binding, u32 multiplier, u32 texel_offset) { ASSERT(texel_offset < 64 && multiplier < 16); - buf_offsets[binding] = texel_offset | (std::bit_width(multiplier) << 6); + buf_offsets[binding] = texel_offset | ((std::bit_width(multiplier) - 1) << 6); } }; static_assert(sizeof(PushData) <= 128, diff --git a/src/shader_recompiler/specialization.h b/src/shader_recompiler/specialization.h index 82c064640..2a3bd62f4 100644 --- a/src/shader_recompiler/specialization.h +++ b/src/shader_recompiler/specialization.h @@ -9,7 +9,6 @@ #include "frontend/fetch_shader.h" #include "shader_recompiler/backend/bindings.h" #include "shader_recompiler/info.h" -#include "shader_recompiler/ir/passes/srt.h" namespace Shader { @@ -22,8 +21,12 @@ struct VsAttribSpecialization { struct BufferSpecialization { u16 stride : 14; u16 is_storage : 1; + u32 size = 0; - auto operator<=>(const BufferSpecialization&) const = default; + bool operator==(const BufferSpecialization& other) const { + return stride == other.stride && is_storage == other.is_storage && + (size >= other.is_storage || is_storage); + } }; struct TextureBufferSpecialization { @@ -86,6 +89,9 @@ struct StageSpecialization { [](auto& spec, const auto& desc, AmdGpu::Buffer sharp) { spec.stride = sharp.GetStride(); spec.is_storage = desc.IsStorage(sharp); + if (!spec.is_storage) { + spec.size = sharp.GetSize(); + } }); ForEachSharp(binding, tex_buffers, info->texture_buffers, [](auto& spec, const auto& desc, AmdGpu::Buffer sharp) { diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 93d03b450..ed55de13b 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -549,7 +549,7 @@ void Rasterizer::BindBuffers(const Shader::Info& stage, Shader::Backend::Binding vsharp.base_address, vsharp.GetSize(), desc.is_written, true, buffer_id); const u32 fmt_stride = AmdGpu::NumBits(vsharp.GetDataFmt()) >> 3; const u32 buf_stride = vsharp.GetStride(); - ASSERT_MSG(buf_stride % fmt_stride, "Texel buffer stride must match format stride"); + ASSERT_MSG(buf_stride % fmt_stride == 0, "Texel buffer stride must match format stride"); const u32 offset_aligned = Common::AlignDown(offset, alignment); const u32 adjust = offset - offset_aligned; ASSERT(adjust % fmt_stride == 0);