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