From 3791262d9610d711ed5e157951feedade1c2eb43 Mon Sep 17 00:00:00 2001
From: Stenzek <stenzek@gmail.com>
Date: Sun, 31 Mar 2019 14:42:38 +1000
Subject: [PATCH] TextureCache: Use linear filtering on y-scaled and >1xIR VRAM
 copies

---
 Source/Core/VideoBackends/Null/TextureCache.h |  8 ++---
 .../VideoBackends/Software/TextureCache.h     |  8 ++---
 Source/Core/VideoCommon/TextureCacheBase.cpp  | 30 ++++++++++---------
 Source/Core/VideoCommon/TextureCacheBase.h    |  8 ++---
 4 files changed, 28 insertions(+), 26 deletions(-)

diff --git a/Source/Core/VideoBackends/Null/TextureCache.h b/Source/Core/VideoBackends/Null/TextureCache.h
index 678f7e8451..91375430c9 100644
--- a/Source/Core/VideoBackends/Null/TextureCache.h
+++ b/Source/Core/VideoBackends/Null/TextureCache.h
@@ -22,14 +22,14 @@ public:
 protected:
   void CopyEFB(AbstractStagingTexture* dst, const EFBCopyParams& params, u32 native_width,
                u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride, const EFBRectangle& src_rect,
-               bool scale_by_half, float y_scale, float gamma, bool clamp_top, bool clamp_bottom,
-               const EFBCopyFilterCoefficients& filter_coefficients) override
+               bool scale_by_half, bool linear_filter, float y_scale, float gamma, bool clamp_top,
+               bool clamp_bottom, const EFBCopyFilterCoefficients& filter_coefficients) override
   {
   }
 
   void CopyEFBToCacheEntry(TCacheEntry* entry, bool is_depth_copy, const EFBRectangle& src_rect,
-                           bool scale_by_half, EFBCopyFormat dst_format, bool is_intensity,
-                           float gamma, bool clamp_top, bool clamp_bottom,
+                           bool scale_by_half, bool linear_filter, EFBCopyFormat dst_format,
+                           bool is_intensity, float gamma, bool clamp_top, bool clamp_bottom,
                            const EFBCopyFilterCoefficients& filter_coefficients) override
   {
   }
diff --git a/Source/Core/VideoBackends/Software/TextureCache.h b/Source/Core/VideoBackends/Software/TextureCache.h
index 8d2e26d508..62f9198dcc 100644
--- a/Source/Core/VideoBackends/Software/TextureCache.h
+++ b/Source/Core/VideoBackends/Software/TextureCache.h
@@ -12,15 +12,15 @@ class TextureCache : public TextureCacheBase
 protected:
   void CopyEFB(AbstractStagingTexture* dst, const EFBCopyParams& params, u32 native_width,
                u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride, const EFBRectangle& src_rect,
-               bool scale_by_half, float y_scale, float gamma, bool clamp_top, bool clamp_bottom,
-               const EFBCopyFilterCoefficients& filter_coefficients) override
+               bool scale_by_half, bool linear_filter, float y_scale, float gamma, bool clamp_top,
+               bool clamp_bottom, const EFBCopyFilterCoefficients& filter_coefficients) override
   {
     TextureEncoder::Encode(dst, params, native_width, bytes_per_row, num_blocks_y, memory_stride,
                            src_rect, scale_by_half, y_scale, gamma);
   }
   void CopyEFBToCacheEntry(TCacheEntry* entry, bool is_depth_copy, const EFBRectangle& src_rect,
-                           bool scale_by_half, EFBCopyFormat dst_format, bool is_intensity,
-                           float gamma, bool clamp_top, bool clamp_bottom,
+                           bool scale_by_half, bool linear_filter, EFBCopyFormat dst_format,
+                           bool is_intensity, float gamma, bool clamp_top, bool clamp_bottom,
                            const EFBCopyFilterCoefficients& filter_coefficients) override
   {
     // TODO: If we ever want to "fake" vram textures, we would need to implement this
diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp
index bc425fcc7f..0d4c599d3d 100644
--- a/Source/Core/VideoCommon/TextureCacheBase.cpp
+++ b/Source/Core/VideoCommon/TextureCacheBase.cpp
@@ -1424,7 +1424,7 @@ void TextureCacheBase::StitchXFBCopy(TCacheEntry* stitched_entry)
     int dst_height = native_height;
 
     // Scale to internal resolution.
-    if (entry->native_width != entry->GetWidth() || entry->native_height != entry->GetHeight())
+    if (entry->native_width != entry->GetWidth())
     {
       src_x = g_renderer->EFBToScaledX(src_x);
       src_y = g_renderer->EFBToScaledY(src_y);
@@ -1660,6 +1660,12 @@ void TextureCacheBase::CopyRenderTargetToTexture(
     copy_to_vram = false;
   }
 
+  // We also linear filtering for both box filtering and downsampling higher resolutions to 1x.
+  // TODO: This only produces perfect downsampling for 2x IR, other resolutions will need more
+  //       complex down filtering to average all pixels and produce the correct result.
+  const bool linear_filter =
+      !is_depth_copy && (scaleByHalf || g_renderer->GetEFBScale() != 1 || y_scale > 1.0f);
+
   TCacheEntry* entry = nullptr;
   if (copy_to_vram)
   {
@@ -1684,8 +1690,8 @@ void TextureCacheBase::CopyRenderTargetToTexture(
       entry->may_have_overlapping_textures = false;
       entry->is_custom_tex = false;
 
-      CopyEFBToCacheEntry(entry, is_depth_copy, srcRect, scaleByHalf, dstFormat, isIntensity, gamma,
-                          clamp_top, clamp_bottom,
+      CopyEFBToCacheEntry(entry, is_depth_copy, srcRect, scaleByHalf, linear_filter, dstFormat,
+                          isIntensity, gamma, clamp_top, clamp_bottom,
                           GetVRAMCopyFilterCoefficients(filter_coefficients));
 
       if (g_ActiveConfig.bDumpEFBTarget && !is_xfb_copy)
@@ -1719,7 +1725,7 @@ void TextureCacheBase::CopyRenderTargetToTexture(
     if (staging_texture)
     {
       CopyEFB(staging_texture.get(), format, tex_w, bytes_per_row, num_blocks_y, dstStride, srcRect,
-              scaleByHalf, y_scale, gamma, clamp_top, clamp_bottom, coefficients);
+              scaleByHalf, linear_filter, y_scale, gamma, clamp_top, clamp_bottom, coefficients);
 
       // We can't defer if there is no VRAM copy (since we need to update the hash).
       if (!copy_to_vram || !g_ActiveConfig.bDeferEFBCopies)
@@ -2153,8 +2159,9 @@ bool TextureCacheBase::CreateUtilityTextures()
 
 void TextureCacheBase::CopyEFBToCacheEntry(TCacheEntry* entry, bool is_depth_copy,
                                            const EFBRectangle& src_rect, bool scale_by_half,
-                                           EFBCopyFormat dst_format, bool is_intensity, float gamma,
-                                           bool clamp_top, bool clamp_bottom,
+                                           bool linear_filter, EFBCopyFormat dst_format,
+                                           bool is_intensity, float gamma, bool clamp_top,
+                                           bool clamp_bottom,
                                            const EFBCopyFilterCoefficients& filter_coefficients)
 {
   // Flush EFB pokes first, as they're expected to be included.
@@ -2213,7 +2220,7 @@ void TextureCacheBase::CopyEFBToCacheEntry(TCacheEntry* entry, bool is_depth_cop
   g_renderer->SetViewportAndScissor(entry->framebuffer->GetRect());
   g_renderer->SetPipeline(copy_pipeline);
   g_renderer->SetTexture(0, src_texture);
-  g_renderer->SetSamplerState(0, scale_by_half ? RenderState::GetLinearSamplerState() :
+  g_renderer->SetSamplerState(0, linear_filter ? RenderState::GetLinearSamplerState() :
                                                  RenderState::GetPointSamplerState());
   g_renderer->Draw(0, 3);
   g_renderer->EndUtilityDrawing();
@@ -2223,7 +2230,8 @@ void TextureCacheBase::CopyEFBToCacheEntry(TCacheEntry* entry, bool is_depth_cop
 void TextureCacheBase::CopyEFB(AbstractStagingTexture* dst, const EFBCopyParams& params,
                                u32 native_width, u32 bytes_per_row, u32 num_blocks_y,
                                u32 memory_stride, const EFBRectangle& src_rect, bool scale_by_half,
-                               float y_scale, float gamma, bool clamp_top, bool clamp_bottom,
+                               bool linear_filter, float y_scale, float gamma, bool clamp_top,
+                               bool clamp_bottom,
                                const EFBCopyFilterCoefficients& filter_coefficients)
 {
   // Flush EFB pokes first, as they're expected to be included.
@@ -2272,12 +2280,6 @@ void TextureCacheBase::CopyEFB(AbstractStagingTexture* dst, const EFBCopyParams&
   encoder_params.filter_coefficients[2] = filter_coefficients.lower;
   g_vertex_manager->UploadUtilityUniforms(&encoder_params, sizeof(encoder_params));
 
-  // We also linear filtering for both box filtering and downsampling higher resolutions to 1x
-  // TODO: This only produces perfect downsampling for 2x IR, other resolutions will need more
-  //       complex down filtering to average all pixels and produce the correct result.
-  const bool linear_filter =
-      (scale_by_half && !params.depth) || g_renderer->GetEFBScale() != 1 || y_scale > 1.0f;
-
   // Because the shader uses gl_FragCoord and we read it back, we must render to the lower-left.
   const u32 render_width = bytes_per_row / sizeof(u32);
   const u32 render_height = num_blocks_y;
diff --git a/Source/Core/VideoCommon/TextureCacheBase.h b/Source/Core/VideoCommon/TextureCacheBase.h
index 980b864aa1..c33dd4b7df 100644
--- a/Source/Core/VideoCommon/TextureCacheBase.h
+++ b/Source/Core/VideoCommon/TextureCacheBase.h
@@ -243,13 +243,13 @@ protected:
 
   virtual void CopyEFB(AbstractStagingTexture* dst, const EFBCopyParams& params, u32 native_width,
                        u32 bytes_per_row, u32 num_blocks_y, u32 memory_stride,
-                       const EFBRectangle& src_rect, bool scale_by_half, float y_scale, float gamma,
-                       bool clamp_top, bool clamp_bottom,
+                       const EFBRectangle& src_rect, bool scale_by_half, bool linear_filter,
+                       float y_scale, float gamma, bool clamp_top, bool clamp_bottom,
                        const EFBCopyFilterCoefficients& filter_coefficients);
   virtual void CopyEFBToCacheEntry(TCacheEntry* entry, bool is_depth_copy,
                                    const EFBRectangle& src_rect, bool scale_by_half,
-                                   EFBCopyFormat dst_format, bool is_intensity, float gamma,
-                                   bool clamp_top, bool clamp_bottom,
+                                   bool linear_filter, EFBCopyFormat dst_format, bool is_intensity,
+                                   float gamma, bool clamp_top, bool clamp_bottom,
                                    const EFBCopyFilterCoefficients& filter_coefficients);
 
   alignas(16) u8* temp = nullptr;