summaryrefslogtreecommitdiff
path: root/Source/Core/VideoCommon/TextureCacheBase.cpp
diff options
context:
space:
mode:
authorPokechu22 <Pokechu022@gmail.com>2022-01-25 19:39:23 -0800
committerPokechu22 <Pokechu022@gmail.com>2022-01-25 19:53:25 -0800
commit25c547e9e5821e5b6da4c0d691253e80611baba0 (patch)
tree6b4ef68ed939a2fa2c5404c370e5d1a561b9c86f /Source/Core/VideoCommon/TextureCacheBase.cpp
parente741d4783aec801b04ece1ff2ce8054893b21f5e (diff)
Fix incorrect copy filter clamping
We need to clamp to the center of pixels, or else things end up working out incorrectly. This also fixes an off-by-1 for the bottom line.
Diffstat (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp')
-rw-r--r--Source/Core/VideoCommon/TextureCacheBase.cpp15
1 files changed, 11 insertions, 4 deletions
diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp
index efe6a381a0..e651e26746 100644
--- a/Source/Core/VideoCommon/TextureCacheBase.cpp
+++ b/Source/Core/VideoCommon/TextureCacheBase.cpp
@@ -2676,7 +2676,8 @@ void TextureCacheBase::CopyEFBToCacheEntry(TCacheEntry* entry, bool is_depth_cop
};
Uniforms uniforms;
const float rcp_efb_width = 1.0f / static_cast<float>(g_framebuffer_manager->GetEFBWidth());
- const float rcp_efb_height = 1.0f / static_cast<float>(g_framebuffer_manager->GetEFBHeight());
+ const u32 efb_height = g_framebuffer_manager->GetEFBHeight();
+ const float rcp_efb_height = 1.0f / static_cast<float>(efb_height);
uniforms.src_left = framebuffer_rect.left * rcp_efb_width;
uniforms.src_top = framebuffer_rect.top * rcp_efb_height;
uniforms.src_width = framebuffer_rect.GetWidth() * rcp_efb_width;
@@ -2685,9 +2686,15 @@ void TextureCacheBase::CopyEFBToCacheEntry(TCacheEntry* entry, bool is_depth_cop
uniforms.filter_coefficients[1] = filter_coefficients.middle;
uniforms.filter_coefficients[2] = filter_coefficients.lower;
uniforms.gamma_rcp = 1.0f / gamma;
- uniforms.clamp_top = clamp_top ? framebuffer_rect.top * rcp_efb_height : 0.0f;
- int bottom_coord = framebuffer_rect.bottom - 1;
- uniforms.clamp_bottom = clamp_bottom ? bottom_coord * rcp_efb_height : 1.0f;
+ // NOTE: when the clamp bits aren't set, the hardware will happily read beyond the EFB,
+ // which returns random garbage from the empty bus (confirmed by hardware tests).
+ //
+ // In our implementation, the garbage just so happens to be the top or bottom row.
+ // Statistically, that could happen.
+ const u32 top_coord = clamp_top ? framebuffer_rect.top : 0;
+ uniforms.clamp_top = (static_cast<float>(top_coord) + .5f) * rcp_efb_height;
+ const u32 bottom_coord = (clamp_bottom ? framebuffer_rect.bottom : efb_height) - 1;
+ uniforms.clamp_bottom = (static_cast<float>(bottom_coord) + .5f) * rcp_efb_height;
uniforms.pixel_height = g_ActiveConfig.bCopyEFBScaled ? rcp_efb_height : 1.0f / EFB_HEIGHT;
uniforms.padding = 0;
g_vertex_manager->UploadUtilityUniforms(&uniforms, sizeof(uniforms));