From 037d28e936afdabd68c6415192f987e6d0f2e4dd Mon Sep 17 00:00:00 2001 From: Patrick Ferry <8967997+PatrickFerry@users.noreply.github.com> Date: Tue, 3 Sep 2024 21:02:29 +0100 Subject: [PATCH] Half Pixel Offset for Linear Filter This seems to be a problem for even IRs when the user does not use the scaled EFB copies setting --- Source/Core/VideoCommon/TextureCacheBase.cpp | 10 +++++++++ .../VideoCommon/TextureConverterShaderGen.cpp | 22 +++++++++++++++---- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index d3ff5b575c..8a53e54d8a 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -2906,6 +2906,11 @@ void TextureCacheBase::CopyEFBToCacheEntry(RcTcacheEntry& entry, bool is_depth_c float clamp_top; float clamp_bottom; float pixel_height; + float rcp_pixel_width; + float rcp_pixel_height; + float efb_scale; + u32 efb_copy_scaled; + u32 linear_filter; u32 padding; }; Uniforms uniforms; @@ -2930,6 +2935,11 @@ void TextureCacheBase::CopyEFBToCacheEntry(RcTcacheEntry& entry, bool is_depth_c uniforms.clamp_bottom = (uniforms.src_top + uniforms.src_height); uniforms.clamp_bottom -= (static_cast(bottom_coord) + .5f) * rcp_efb_height; uniforms.pixel_height = g_ActiveConfig.bCopyEFBScaled ? rcp_efb_height : 1.0f / EFB_HEIGHT; + uniforms.rcp_pixel_width = rcp_efb_width; + uniforms.rcp_pixel_height = rcp_efb_height; + uniforms.efb_scale = static_cast(g_framebuffer_manager->GetEFBScale()); + uniforms.efb_copy_scaled = g_ActiveConfig.bCopyEFBScaled ? 1u : 0u; + uniforms.linear_filter = linear_filter ? 1u : 0u; uniforms.padding = 0; g_vertex_manager->UploadUtilityUniforms(&uniforms, sizeof(uniforms)); diff --git a/Source/Core/VideoCommon/TextureConverterShaderGen.cpp b/Source/Core/VideoCommon/TextureConverterShaderGen.cpp index 73ca7ff35d..bd5c98a42c 100644 --- a/Source/Core/VideoCommon/TextureConverterShaderGen.cpp +++ b/Source/Core/VideoCommon/TextureConverterShaderGen.cpp @@ -61,6 +61,11 @@ static void WriteHeader(APIType api_type, ShaderCode& out) " float gamma_rcp;\n" " float2 clamp_tb;\n" " float pixel_height;\n" + " float rcp_pixel_width;\n" + " float rcp_pixel_height;\n" + " float efb_scale;\n" + " uint efb_copy_scaled;\n" + " uint linear_filter;\n" "}};\n"); } @@ -106,18 +111,27 @@ ShaderCode GeneratePixelShader(APIType api_type, const UidData* uid_data) out.Write("SAMPLER_BINDING(0) uniform sampler2DArray samp0;\n"); out.Write("uint4 SampleEFB(float3 uv, float y_offset) {{\n" " float clamp_top = src_offset.y + clamp_tb.x;\n" - " float clamp_bottom = (src_offset.y + src_size.y) - clamp_tb.y;\n"); + " float clamp_bottom = (src_offset.y + src_size.y) - clamp_tb.y;\n" + " float shift_x = 0.0f;\n" + " float shift_y = 0.0f;\n"); + + // Linear filtering half pixel offset for even IRs + out.Write(" if(linear_filter == 1 && efb_copy_scaled == 0 && mod(efb_scale, 2.0f) == 0){{\n" + " shift_x = rcp_pixel_width / 2.f;\n" + " shift_y = rcp_pixel_height / 2.f;\n" + " }}\n"); // Reverse the direction for OpenGL if (api_type == APIType::OpenGL) { out.Write(" clamp_top = src_offset.y + clamp_tb.y;\n" " clamp_bottom = (src_offset.y + src_size.y) - clamp_tb.x;\n" - " y_offset = -y_offset;\n"); + " y_offset = -y_offset;\n" + " shift_y = -shift_y;\n"); } - out.Write(" float clamp_y = clamp(uv.y + (y_offset * pixel_height), clamp_top, clamp_bottom);\n" - " float4 tex_sample = texture(samp0, float3(uv.x, clamp_y, {}));\n", + out.Write(" float clamp_y = clamp(uv.y + shift_y + (y_offset * pixel_height), clamp_top, clamp_bottom);\n" + " float4 tex_sample = texture(samp0, float3(uv.x + shift_x, clamp_y, {}));\n", mono_depth ? "0.0" : "uv.z"); if (uid_data->is_depth_copy)