From 423da5cc911bf7545746ad4fd184eff42f32dd9b Mon Sep 17 00:00:00 2001
From: gdkchan <gab.dark.100@gmail.com>
Date: Thu, 29 Oct 2020 18:57:34 -0300
Subject: [PATCH] Scale texture resolution before sending to backend (#1646)

* Work

* Propagate scale factor to copy temp. Not really needed, just here for consistency

* PR feedback
---
 Ryujinx.Graphics.Gpu/Image/Texture.cs         | 18 ++++-----
 Ryujinx.Graphics.Gpu/Image/TextureManager.cs  | 15 ++++++--
 Ryujinx.Graphics.OpenGL/Image/TextureBase.cs  |  7 +---
 Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs  |  2 +-
 .../Image/TextureCopyUnscaled.cs              | 11 +++---
 .../Image/TextureStorage.cs                   | 37 +++++++++----------
 Ryujinx.Graphics.OpenGL/Image/TextureView.cs  |  9 ++---
 7 files changed, 47 insertions(+), 52 deletions(-)

diff --git a/Ryujinx.Graphics.Gpu/Image/Texture.cs b/Ryujinx.Graphics.Gpu/Image/Texture.cs
index 2b1aaa0ad6..0161062948 100644
--- a/Ryujinx.Graphics.Gpu/Image/Texture.cs
+++ b/Ryujinx.Graphics.Gpu/Image/Texture.cs
@@ -181,7 +181,7 @@ namespace Ryujinx.Graphics.Gpu.Image
             {
                 Debug.Assert(!isView);
 
-                TextureCreateInfo createInfo = TextureManager.GetCreateInfo(Info, _context.Capabilities);
+                TextureCreateInfo createInfo = TextureManager.GetCreateInfo(Info, _context.Capabilities, ScaleFactor);
                 HostTexture = _context.Renderer.CreateTexture(createInfo, ScaleFactor);
 
                 SynchronizeMemory(); // Load the data.
@@ -204,7 +204,7 @@ namespace Ryujinx.Graphics.Gpu.Image
                         ScaleFactor = GraphicsConfig.ResScale;
                     }
 
-                    TextureCreateInfo createInfo = TextureManager.GetCreateInfo(Info, _context.Capabilities);
+                    TextureCreateInfo createInfo = TextureManager.GetCreateInfo(Info, _context.Capabilities, ScaleFactor);
                     HostTexture = _context.Renderer.CreateTexture(createInfo, ScaleFactor);
                 }
             }
@@ -232,8 +232,7 @@ namespace Ryujinx.Graphics.Gpu.Image
                 ScaleFactor,
                 ScaleMode);
 
-            TextureCreateInfo createInfo = TextureManager.GetCreateInfo(info, _context.Capabilities);
-
+            TextureCreateInfo createInfo = TextureManager.GetCreateInfo(info, _context.Capabilities, ScaleFactor);
             texture.HostTexture = HostTexture.CreateView(createInfo, firstLayer, firstLevel);
 
             _viewStorage.AddView(texture);
@@ -375,7 +374,7 @@ namespace Ryujinx.Graphics.Gpu.Image
                 Info.SwizzleB,
                 Info.SwizzleA));
 
-            TextureCreateInfo createInfo = TextureManager.GetCreateInfo(Info, _context.Capabilities);
+            TextureCreateInfo createInfo = TextureManager.GetCreateInfo(Info, _context.Capabilities, ScaleFactor);
 
             if (_viewStorage != this)
             {
@@ -451,7 +450,7 @@ namespace Ryujinx.Graphics.Gpu.Image
                 Info.SwizzleB,
                 Info.SwizzleA);
 
-            TextureCreateInfo createInfo = TextureManager.GetCreateInfo(viewInfo, _context.Capabilities);
+            TextureCreateInfo createInfo = TextureManager.GetCreateInfo(viewInfo, _context.Capabilities, ScaleFactor);
 
             for (int i = 0; i < Info.DepthOrLayers; i++)
             {
@@ -475,8 +474,7 @@ namespace Ryujinx.Graphics.Gpu.Image
         {
             if (storage == null)
             {
-                TextureCreateInfo createInfo = TextureManager.GetCreateInfo(Info, _context.Capabilities);
-
+                TextureCreateInfo createInfo = TextureManager.GetCreateInfo(Info, _context.Capabilities, scale);
                 storage = _context.Renderer.CreateTexture(createInfo, scale);
             }
 
@@ -530,12 +528,10 @@ namespace Ryujinx.Graphics.Gpu.Image
                     Logger.Debug?.Print(LogClass.Gpu, $"  Recreating view {Info.Width}x{Info.Height} {Info.FormatInfo.Format.ToString()}.");
                     view.ScaleFactor = scale;
 
-                    TextureCreateInfo viewCreateInfo = TextureManager.GetCreateInfo(view.Info, _context.Capabilities);
-
+                    TextureCreateInfo viewCreateInfo = TextureManager.GetCreateInfo(view.Info, _context.Capabilities, scale);
                     ITexture newView = HostTexture.CreateView(viewCreateInfo, view._firstLayer - _firstLayer, view._firstLevel - _firstLevel);
 
                     view.ReplaceStorage(newView);
-
                     view.ScaleMode = newScaleMode;
                 }
             }
diff --git a/Ryujinx.Graphics.Gpu/Image/TextureManager.cs b/Ryujinx.Graphics.Gpu/Image/TextureManager.cs
index 27292f56c9..b0e715ea4c 100644
--- a/Ryujinx.Graphics.Gpu/Image/TextureManager.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TextureManager.cs
@@ -754,7 +754,7 @@ namespace Ryujinx.Graphics.Gpu.Image
                     }
 
                     break;
-                } 
+                }
                 else if (overlapCompatibility == TextureViewCompatibility.CopyOnly)
                 {
                     // TODO: Copy rules for targets created after the container texture. See below.
@@ -833,7 +833,7 @@ namespace Ryujinx.Graphics.Gpu.Image
 
                     TextureInfo overlapInfo = AdjustSizes(texture, overlap.Info, oInfo.FirstLevel);
 
-                    TextureCreateInfo createInfo = GetCreateInfo(overlapInfo, _context.Capabilities);
+                    TextureCreateInfo createInfo = GetCreateInfo(overlapInfo, _context.Capabilities, overlap.ScaleFactor);
 
                     if (texture.ScaleFactor != overlap.ScaleFactor)
                     {
@@ -944,7 +944,7 @@ namespace Ryujinx.Graphics.Gpu.Image
                 }
                 else
                 {
-                    // Bpp may be a mismatch between the target texture and the param. 
+                    // Bpp may be a mismatch between the target texture and the param.
                     // Due to the way linear strided and block layouts work, widths can be multiplied by Bpp for comparison.
                     // Note: tex.Width is the aligned texture size. Prefer param.XCount, as the destination should be a texture with that exact size.
 
@@ -1054,8 +1054,9 @@ namespace Ryujinx.Graphics.Gpu.Image
         /// </summary>
         /// <param name="info">Texture information</param>
         /// <param name="caps">GPU capabilities</param>
+        /// <param name="scale">Texture scale factor, to be applied to the texture size</param>
         /// <returns>The texture creation information</returns>
-        public static TextureCreateInfo GetCreateInfo(TextureInfo info, Capabilities caps)
+        public static TextureCreateInfo GetCreateInfo(TextureInfo info, Capabilities caps, float scale)
         {
             FormatInfo formatInfo = info.FormatInfo;
 
@@ -1092,6 +1093,12 @@ namespace Ryujinx.Graphics.Gpu.Image
 
             int depth = info.GetDepth() * info.GetLayers();
 
+            if (scale != 1f)
+            {
+                width  = (int)MathF.Ceiling(width  * scale);
+                height = (int)MathF.Ceiling(height * scale);
+            }
+
             return new TextureCreateInfo(
                 width,
                 height,
diff --git a/Ryujinx.Graphics.OpenGL/Image/TextureBase.cs b/Ryujinx.Graphics.OpenGL/Image/TextureBase.cs
index 5f786decc7..2e70fa82a0 100644
--- a/Ryujinx.Graphics.OpenGL/Image/TextureBase.cs
+++ b/Ryujinx.Graphics.OpenGL/Image/TextureBase.cs
@@ -1,6 +1,5 @@
 using OpenTK.Graphics.OpenGL;
 using Ryujinx.Graphics.GAL;
-using System;
 
 namespace Ryujinx.Graphics.OpenGL.Image
 {
@@ -10,8 +9,8 @@ namespace Ryujinx.Graphics.OpenGL.Image
 
         public TextureCreateInfo Info { get; }
 
-        public int Width { get; }
-        public int Height { get; }
+        public int Width => Info.Width;
+        public int Height => Info.Height;
         public float ScaleFactor { get; }
 
         public Target Target => Info.Target;
@@ -20,8 +19,6 @@ namespace Ryujinx.Graphics.OpenGL.Image
         public TextureBase(TextureCreateInfo info, float scaleFactor = 1f)
         {
             Info = info;
-            Width = (int)Math.Ceiling(Info.Width * scaleFactor);
-            Height = (int)Math.Ceiling(Info.Height * scaleFactor);
             ScaleFactor = scaleFactor;
 
             Handle = GL.GenTexture();
diff --git a/Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs b/Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs
index edfbec5f82..191e9b634c 100644
--- a/Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs
+++ b/Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs
@@ -129,7 +129,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
 
         public TextureView BgraSwap(TextureView from)
         {
-            TextureView to = (TextureView)_renderer.CreateTexture(from.Info, 1f);
+            TextureView to = (TextureView)_renderer.CreateTexture(from.Info, from.ScaleFactor);
 
             EnsurePbo(from);
 
diff --git a/Ryujinx.Graphics.OpenGL/Image/TextureCopyUnscaled.cs b/Ryujinx.Graphics.OpenGL/Image/TextureCopyUnscaled.cs
index 02ae3b581a..2840113854 100644
--- a/Ryujinx.Graphics.OpenGL/Image/TextureCopyUnscaled.cs
+++ b/Ryujinx.Graphics.OpenGL/Image/TextureCopyUnscaled.cs
@@ -15,16 +15,15 @@ namespace Ryujinx.Graphics.OpenGL.Image
             int srcLayer,
             int dstLayer,
             int srcLevel,
-            int dstLevel,
-            float scaleFactor = 1f)
+            int dstLevel)
         {
-            int srcWidth  = (int)Math.Ceiling(srcInfo.Width * scaleFactor);
-            int srcHeight = (int)Math.Ceiling(srcInfo.Height * scaleFactor);
+            int srcWidth  = srcInfo.Width;
+            int srcHeight = srcInfo.Height;
             int srcDepth  = srcInfo.GetDepthOrLayers();
             int srcLevels = srcInfo.Levels;
 
-            int dstWidth  = (int)Math.Ceiling(dstInfo.Width * scaleFactor);
-            int dstHeight = (int)Math.Ceiling(dstInfo.Height * scaleFactor);
+            int dstWidth  = dstInfo.Width;
+            int dstHeight = dstInfo.Height;
             int dstDepth  = dstInfo.GetDepthOrLayers();
             int dstLevels = dstInfo.Levels;
 
diff --git a/Ryujinx.Graphics.OpenGL/Image/TextureStorage.cs b/Ryujinx.Graphics.OpenGL/Image/TextureStorage.cs
index 635b6c2ce8..b34b02bf78 100644
--- a/Ryujinx.Graphics.OpenGL/Image/TextureStorage.cs
+++ b/Ryujinx.Graphics.OpenGL/Image/TextureStorage.cs
@@ -37,9 +37,6 @@ namespace Ryujinx.Graphics.OpenGL.Image
 
             GL.BindTexture(target, Handle);
 
-            int width = (int)Math.Ceiling(Info.Width * ScaleFactor);
-            int height = (int)Math.Ceiling(Info.Height * ScaleFactor);
-
             FormatInfo format = FormatTable.GetFormatInfo(Info.Format);
 
             SizedInternalFormat internalFormat;
@@ -60,7 +57,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
                         TextureTarget1d.Texture1D,
                         Info.Levels,
                         internalFormat,
-                        width);
+                        Info.Width);
                     break;
 
                 case Target.Texture1DArray:
@@ -68,8 +65,8 @@ namespace Ryujinx.Graphics.OpenGL.Image
                         TextureTarget2d.Texture1DArray,
                         Info.Levels,
                         internalFormat,
-                        width,
-                        height);
+                        Info.Width,
+                        Info.Height);
                     break;
 
                 case Target.Texture2D:
@@ -77,8 +74,8 @@ namespace Ryujinx.Graphics.OpenGL.Image
                         TextureTarget2d.Texture2D,
                         Info.Levels,
                         internalFormat,
-                        width,
-                        height);
+                        Info.Width,
+                        Info.Height);
                     break;
 
                 case Target.Texture2DArray:
@@ -86,8 +83,8 @@ namespace Ryujinx.Graphics.OpenGL.Image
                         TextureTarget3d.Texture2DArray,
                         Info.Levels,
                         internalFormat,
-                        width,
-                        height,
+                        Info.Width,
+                        Info.Height,
                         Info.Depth);
                     break;
 
@@ -96,8 +93,8 @@ namespace Ryujinx.Graphics.OpenGL.Image
                         TextureTargetMultisample2d.Texture2DMultisample,
                         Info.Samples,
                         internalFormat,
-                        width,
-                        height,
+                        Info.Width,
+                        Info.Height,
                         true);
                     break;
 
@@ -106,8 +103,8 @@ namespace Ryujinx.Graphics.OpenGL.Image
                         TextureTargetMultisample3d.Texture2DMultisampleArray,
                         Info.Samples,
                         internalFormat,
-                        width,
-                        height,
+                        Info.Width,
+                        Info.Height,
                         Info.Depth,
                         true);
                     break;
@@ -117,8 +114,8 @@ namespace Ryujinx.Graphics.OpenGL.Image
                         TextureTarget3d.Texture3D,
                         Info.Levels,
                         internalFormat,
-                        width,
-                        height,
+                        Info.Width,
+                        Info.Height,
                         Info.Depth);
                     break;
 
@@ -127,8 +124,8 @@ namespace Ryujinx.Graphics.OpenGL.Image
                         TextureTarget2d.TextureCubeMap,
                         Info.Levels,
                         internalFormat,
-                        width,
-                        height);
+                        Info.Width,
+                        Info.Height);
                     break;
 
                 case Target.CubemapArray:
@@ -136,8 +133,8 @@ namespace Ryujinx.Graphics.OpenGL.Image
                         (TextureTarget3d)All.TextureCubeMapArray,
                         Info.Levels,
                         internalFormat,
-                        width,
-                        height,
+                        Info.Width,
+                        Info.Height,
                         Info.Depth);
                     break;
 
diff --git a/Ryujinx.Graphics.OpenGL/Image/TextureView.cs b/Ryujinx.Graphics.OpenGL/Image/TextureView.cs
index 04cadae73a..449c18d4b6 100644
--- a/Ryujinx.Graphics.OpenGL/Image/TextureView.cs
+++ b/Ryujinx.Graphics.OpenGL/Image/TextureView.cs
@@ -134,7 +134,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
                     _incompatibleFormatView = (TextureView)_renderer.CreateTexture(Info, ScaleFactor);
                 }
 
-                TextureCopyUnscaled.Copy(_parent.Info, _incompatibleFormatView.Info, _parent.Handle, _incompatibleFormatView.Handle, FirstLayer, 0, FirstLevel, 0, ScaleFactor);
+                TextureCopyUnscaled.Copy(_parent.Info, _incompatibleFormatView.Info, _parent.Handle, _incompatibleFormatView.Handle, FirstLayer, 0, FirstLevel, 0);
 
                 return _incompatibleFormatView.Handle;
             }
@@ -146,7 +146,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
         {
             if (_incompatibleFormatView != null)
             {
-                TextureCopyUnscaled.Copy(_incompatibleFormatView.Info, _parent.Info, _incompatibleFormatView.Handle, _parent.Handle, 0, FirstLayer, 0, FirstLevel, ScaleFactor);
+                TextureCopyUnscaled.Copy(_incompatibleFormatView.Info, _parent.Info, _incompatibleFormatView.Handle, _parent.Handle, 0, FirstLayer, 0, FirstLevel);
             }
         }
 
@@ -154,7 +154,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
         {
             TextureView destinationView = (TextureView)destination;
 
-            TextureCopyUnscaled.Copy(Info, destinationView.Info, Handle, destinationView.Handle, 0, firstLayer, 0, firstLevel, ScaleFactor);
+            TextureCopyUnscaled.Copy(Info, destinationView.Info, Handle, destinationView.Handle, 0, firstLayer, 0, firstLevel);
 
             if (destinationView._emulatedViewParent != null)
             {
@@ -166,8 +166,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
                     0,
                     destinationView.FirstLayer,
                     0,
-                    destinationView.FirstLevel,
-                    ScaleFactor);
+                    destinationView.FirstLevel);
             }
         }