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(g_framebuffer_manager->GetEFBWidth()); - const float rcp_efb_height = 1.0f / static_cast(g_framebuffer_manager->GetEFBHeight()); + const u32 efb_height = g_framebuffer_manager->GetEFBHeight(); + const float rcp_efb_height = 1.0f / static_cast(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(top_coord) + .5f) * rcp_efb_height; + const u32 bottom_coord = (clamp_bottom ? framebuffer_rect.bottom : efb_height) - 1; + 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.padding = 0; g_vertex_manager->UploadUtilityUniforms(&uniforms, sizeof(uniforms));