diff --git a/Ryujinx.Graphics.Gpu/Image/Texture.cs b/Ryujinx.Graphics.Gpu/Image/Texture.cs index 87c409a0..2c4a3e4e 100644 --- a/Ryujinx.Graphics.Gpu/Image/Texture.cs +++ b/Ryujinx.Graphics.Gpu/Image/Texture.cs @@ -667,7 +667,7 @@ namespace Ryujinx.Graphics.Gpu.Image /// True if the textures are strictly equal or similar, false otherwise 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. /// /// Texture information to compare with - /// True to perform a strict comparison (formats must be exactly equal) + /// Indicates that the texture will be used for shader sampling + /// Indicates that the texture will be used as copy source or target /// True if the format matches, with the given comparison rules - 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; } diff --git a/Ryujinx.Graphics.Gpu/Image/TextureManager.cs b/Ryujinx.Graphics.Gpu/Image/TextureManager.cs index 69bee541..c69f69c6 100644 --- a/Ryujinx.Graphics.Gpu/Image/TextureManager.cs +++ b/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. /// - /// If this is not -1, it indicates that only the given indexed target will be used. + /// If this is not -1, it indicates that only the given indexed target will be used. 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 /// The texture 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); diff --git a/Ryujinx.Graphics.Gpu/Image/TexturePool.cs b/Ryujinx.Graphics.Gpu/Image/TexturePool.cs index 1494a142..c35c3aeb 100644 --- a/Ryujinx.Graphics.Gpu/Image/TexturePool.cs +++ b/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(); diff --git a/Ryujinx.Graphics.Gpu/Image/TextureSearchFlags.cs b/Ryujinx.Graphics.Gpu/Image/TextureSearchFlags.cs index 33ac775c..45e55c02 100644 --- a/Ryujinx.Graphics.Gpu/Image/TextureSearchFlags.cs +++ b/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 } } \ No newline at end of file