From 4d1579acbf60ff23f14b591db762267f93092d0c Mon Sep 17 00:00:00 2001
From: gdkchan <gab.dark.100@gmail.com>
Date: Wed, 3 May 2023 21:20:12 -0300
Subject: Fix some invalid blits involving depth textures (#4723)

---
 src/Ryujinx.Graphics.Gpu/Engine/Twod/TwodClass.cs      | 9 ++++++++-
 src/Ryujinx.Graphics.Gpu/Image/Texture.cs              | 2 +-
 src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs         | 8 ++++++++
 src/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs | 8 ++++----
 src/Ryujinx.Graphics.Gpu/Image/TextureSearchFlags.cs   | 5 +++--
 5 files changed, 24 insertions(+), 8 deletions(-)

diff --git a/src/Ryujinx.Graphics.Gpu/Engine/Twod/TwodClass.cs b/src/Ryujinx.Graphics.Gpu/Engine/Twod/TwodClass.cs
index 4ce53e78..2ac84ab5 100644
--- a/src/Ryujinx.Graphics.Gpu/Engine/Twod/TwodClass.cs
+++ b/src/Ryujinx.Graphics.Gpu/Engine/Twod/TwodClass.cs
@@ -300,11 +300,16 @@ namespace Ryujinx.Graphics.Gpu.Engine.Twod
                 IsCopyRegionComplete(srcCopyTexture, srcCopyTextureFormat, srcX1, srcY1, srcX2, srcY2) &&
                 IsCopyRegionComplete(dstCopyTexture, dstCopyTextureFormat, dstX1, dstY1, dstX2, dstY2);
 
+            // We can only allow aliasing of color formats as depth if the source and destination textures
+            // are the same, as we can't blit between different depth formats.
+            bool srcDepthAlias = srcCopyTexture.Format == dstCopyTexture.Format;
+
             var srcTexture = memoryManager.Physical.TextureCache.FindOrCreateTexture(
                 memoryManager,
                 srcCopyTexture,
                 offset,
                 srcCopyTextureFormat,
+                srcDepthAlias,
                 !canDirectCopy,
                 false,
                 srcHint);
@@ -325,6 +330,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Twod
             // When the source texture that was found has a depth format,
             // we must enforce the target texture also has a depth format,
             // as copies between depth and color formats are not allowed.
+            // For depth blit, the destination texture format should always match exactly.
 
             if (srcTexture.Format.IsDepthOrStencil())
             {
@@ -340,7 +346,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Twod
                 dstCopyTexture,
                 0,
                 dstCopyTextureFormat,
-                true,
+                depthAlias: false,
+                shouldCreate: true,
                 srcTexture.ScaleMode == TextureScaleMode.Scaled,
                 dstHint);
 
diff --git a/src/Ryujinx.Graphics.Gpu/Image/Texture.cs b/src/Ryujinx.Graphics.Gpu/Image/Texture.cs
index 6c9de8d6..0427d09b 100644
--- a/src/Ryujinx.Graphics.Gpu/Image/Texture.cs
+++ b/src/Ryujinx.Graphics.Gpu/Image/Texture.cs
@@ -1118,7 +1118,7 @@ namespace Ryujinx.Graphics.Gpu.Image
         {
             bool forSampler = (flags & TextureSearchFlags.ForSampler) != 0;
 
-            TextureMatchQuality matchQuality = TextureCompatibility.FormatMatches(Info, info, forSampler, (flags & TextureSearchFlags.ForCopy) != 0);
+            TextureMatchQuality matchQuality = TextureCompatibility.FormatMatches(Info, info, forSampler, (flags & TextureSearchFlags.DepthAlias) != 0);
 
             if (matchQuality == TextureMatchQuality.NoMatch)
             {
diff --git a/src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs b/src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs
index fc2c07e5..49191239 100644
--- a/src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs
+++ b/src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs
@@ -249,6 +249,8 @@ namespace Ryujinx.Graphics.Gpu.Image
         /// <param name="copyTexture">Copy texture to find or create</param>
         /// <param name="offset">Offset to be added to the physical texture address</param>
         /// <param name="formatInfo">Format information of the copy texture</param>
+        /// <param name="depthAlias">Indicates if aliasing between color and depth format should be allowed</param>
+        /// <param name="shouldCreate">Indicates if a new texture should be created if none is found on the cache</param>
         /// <param name="preferScaling">Indicates if the texture should be scaled from the start</param>
         /// <param name="sizeHint">A hint indicating the minimum used size for the texture</param>
         /// <returns>The texture</returns>
@@ -257,6 +259,7 @@ namespace Ryujinx.Graphics.Gpu.Image
             TwodTexture copyTexture,
             ulong offset,
             FormatInfo formatInfo,
+            bool depthAlias,
             bool shouldCreate,
             bool preferScaling,
             Size sizeHint)
@@ -293,6 +296,11 @@ namespace Ryujinx.Graphics.Gpu.Image
 
             TextureSearchFlags flags = TextureSearchFlags.ForCopy;
 
+            if (depthAlias)
+            {
+                flags |= TextureSearchFlags.DepthAlias;
+            }
+
             if (preferScaling)
             {
                 flags |= TextureSearchFlags.WithUpscale;
diff --git a/src/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs b/src/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs
index e93ea0c0..5d846222 100644
--- a/src/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs
+++ b/src/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs
@@ -220,18 +220,18 @@ namespace Ryujinx.Graphics.Gpu.Image
         /// <param name="lhs">Texture information to compare</param>
         /// <param name="rhs">Texture information to compare with</param>
         /// <param name="forSampler">Indicates that the texture will be used for shader sampling</param>
-        /// <param name="forCopy">Indicates that the texture will be used as copy source or target</param>
+        /// <param name="depthAlias">Indicates if aliasing between color and depth format should be allowed</param>
         /// <returns>A value indicating how well the formats match</returns>
-        public static TextureMatchQuality FormatMatches(TextureInfo lhs, TextureInfo rhs, bool forSampler, bool forCopy)
+        public static TextureMatchQuality FormatMatches(TextureInfo lhs, TextureInfo rhs, bool forSampler, bool depthAlias)
         {
             // D32F and R32F texture have the same representation internally,
             // however the R32F format is used to sample from depth textures.
-            if (lhs.FormatInfo.Format == Format.D32Float && rhs.FormatInfo.Format == Format.R32Float && (forSampler || forCopy))
+            if (lhs.FormatInfo.Format == Format.D32Float && rhs.FormatInfo.Format == Format.R32Float && (forSampler || depthAlias))
             {
                 return TextureMatchQuality.FormatAlias;
             }
 
-            if (forCopy)
+            if (depthAlias)
             {
                 // The 2D engine does not support depth-stencil formats, so it will instead
                 // use equivalent color formats. We must also consider them as compatible.
diff --git a/src/Ryujinx.Graphics.Gpu/Image/TextureSearchFlags.cs b/src/Ryujinx.Graphics.Gpu/Image/TextureSearchFlags.cs
index 890bf173..d7b99a17 100644
--- a/src/Ryujinx.Graphics.Gpu/Image/TextureSearchFlags.cs
+++ b/src/Ryujinx.Graphics.Gpu/Image/TextureSearchFlags.cs
@@ -11,7 +11,8 @@ namespace Ryujinx.Graphics.Gpu.Image
         None        = 0,
         ForSampler  = 1 << 1,
         ForCopy     = 1 << 2,
-        WithUpscale = 1 << 3,
-        NoCreate    = 1 << 4
+        DepthAlias  = 1 << 3,
+        WithUpscale = 1 << 4,
+        NoCreate    = 1 << 5
     }
 }
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2