Просмотр исходного кода

Fix depth stencil formats copy by matching equivalent color formats (#1198)

gdkchan 5 лет назад
Родитель
Сommit
2900dda633

+ 28 - 6
Ryujinx.Graphics.Gpu/Image/Texture.cs

@@ -667,7 +667,7 @@ namespace Ryujinx.Graphics.Gpu.Image
         /// <returns>True if the textures are strictly equal or similar, false otherwise</returns>
         public bool IsPerfectMatch(TextureInfo info, TextureSearchFlags flags)
         {
-            if (!FormatMatches(info, (flags & TextureSearchFlags.Strict) != 0))
+            if (!FormatMatches(info, (flags & TextureSearchFlags.ForSampler) != 0, (flags & TextureSearchFlags.ForCopy) != 0))
             {
                 return false;
             }
@@ -682,7 +682,7 @@ namespace Ryujinx.Graphics.Gpu.Image
                 return false;
             }
 
-            if ((flags & TextureSearchFlags.Sampler) != 0)
+            if ((flags & TextureSearchFlags.ForSampler) != 0 || (flags & TextureSearchFlags.Strict) != 0)
             {
                 if (!SamplerParamsMatches(info))
                 {
@@ -690,7 +690,7 @@ namespace Ryujinx.Graphics.Gpu.Image
                 }
             }
 
-            if ((flags & TextureSearchFlags.IgnoreMs) != 0)
+            if ((flags & TextureSearchFlags.ForCopy) != 0)
             {
                 bool msTargetCompatible = Info.Target == Target.Texture2DMultisample && info.Target == Target.Texture2D;
 
@@ -711,17 +711,39 @@ namespace Ryujinx.Graphics.Gpu.Image
         /// Checks if the texture format matches with the specified texture information.
         /// </summary>
         /// <param name="info">Texture information to compare with</param>
-        /// <param name="strict">True to perform a strict comparison (formats must be exactly equal)</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>
         /// <returns>True if the format matches, with the given comparison rules</returns>
-        private bool FormatMatches(TextureInfo info, bool strict)
+        private bool FormatMatches(TextureInfo info, bool forSampler, bool forCopy)
         {
             // D32F and R32F texture have the same representation internally,
             // however the R32F format is used to sample from depth textures.
-            if (Info.FormatInfo.Format == Format.D32Float && info.FormatInfo.Format == Format.R32Float && !strict)
+            if (Info.FormatInfo.Format == Format.D32Float && info.FormatInfo.Format == Format.R32Float && (forSampler || forCopy))
             {
                 return true;
             }
 
+            if (forCopy)
+            {
+                // The 2D engine does not support depth-stencil formats, so it will instead
+                // use equivalent color formats. We must also consider them as compatible.
+                if (Info.FormatInfo.Format == Format.S8Uint && info.FormatInfo.Format == Format.R8Unorm)
+                {
+                    return true;
+                }
+
+                if (Info.FormatInfo.Format == Format.D16Unorm && info.FormatInfo.Format == Format.R16Unorm)
+                {
+                    return true;
+                }
+
+                if ((Info.FormatInfo.Format == Format.D24UnormS8Uint ||
+                     Info.FormatInfo.Format == Format.D24X8Unorm) && info.FormatInfo.Format == Format.B8G8R8A8Unorm)
+                {
+                    return true;
+                }
+            }
+
             return Info.FormatInfo.Format == info.FormatInfo.Format;
         }
 

+ 4 - 4
Ryujinx.Graphics.Gpu/Image/TextureManager.cs

@@ -189,7 +189,7 @@ namespace Ryujinx.Graphics.Gpu.Image
         /// This will update scale to match the configured scale, scale textures that are eligible but not scaled,
         /// and propagate blacklisted status from one texture to the ones bound with it.
         /// </summary>
-        /// <param name="singleUse">If this is not -1, it indicates that only the given indexed target will be used.</param> 
+        /// <param name="singleUse">If this is not -1, it indicates that only the given indexed target will be used.</param>
         public void UpdateRenderTargetScale(int singleUse)
         {
             // Make sure all scales for render targets are at the highest they should be. Blacklisted targets should propagate their scale to the other targets.
@@ -454,7 +454,7 @@ namespace Ryujinx.Graphics.Gpu.Image
                 Target.Texture2D,
                 formatInfo);
 
-            TextureSearchFlags flags = TextureSearchFlags.IgnoreMs;
+            TextureSearchFlags flags = TextureSearchFlags.ForCopy;
 
             if (preferScaling)
             {
@@ -608,7 +608,7 @@ namespace Ryujinx.Graphics.Gpu.Image
         /// <returns>The texture</returns>
         public Texture FindOrCreateTexture(TextureInfo info, TextureSearchFlags flags = TextureSearchFlags.None)
         {
-            bool isSamplerTexture = (flags & TextureSearchFlags.Sampler) != 0;
+            bool isSamplerTexture = (flags & TextureSearchFlags.ForSampler) != 0;
 
             bool isScalable = IsUpscaleCompatible(info);
 
@@ -737,7 +737,7 @@ namespace Ryujinx.Graphics.Gpu.Image
 
                         if (texture.ScaleFactor != overlap.ScaleFactor)
                         {
-                            // A bit tricky, our new texture may need to contain an existing texture that is upscaled, but isn't itself. 
+                            // A bit tricky, our new texture may need to contain an existing texture that is upscaled, but isn't itself.
                             // In that case, we prefer the higher scale only if our format is render-target-like, otherwise we scale the view down before copy.
 
                             texture.PropagateScale(overlap);

+ 1 - 1
Ryujinx.Graphics.Gpu/Image/TexturePool.cs

@@ -59,7 +59,7 @@ namespace Ryujinx.Graphics.Gpu.Image
                     return null;
                 }
 
-                texture = Context.Methods.TextureManager.FindOrCreateTexture(info, TextureSearchFlags.Sampler);
+                texture = Context.Methods.TextureManager.FindOrCreateTexture(info, TextureSearchFlags.ForSampler);
 
                 texture.IncrementReferenceCount();
 

+ 4 - 4
Ryujinx.Graphics.Gpu/Image/TextureSearchFlags.cs

@@ -8,10 +8,10 @@ namespace Ryujinx.Graphics.Gpu.Image
     [Flags]
     enum TextureSearchFlags
     {
-        None     = 0,
-        IgnoreMs = 1 << 0,
-        Strict   = 1 << 1 | Sampler,
-        Sampler  = 1 << 2,
+        None        = 0,
+        Strict      = 1 << 0,
+        ForSampler  = 1 << 1,
+        ForCopy     = 1 << 2,
         WithUpscale = 1 << 3
     }
 }