diff --git a/Ryujinx.Graphics.Gpu/Image/Texture.cs b/Ryujinx.Graphics.Gpu/Image/Texture.cs
index 7fb41572d..45a270519 100644
--- a/Ryujinx.Graphics.Gpu/Image/Texture.cs
+++ b/Ryujinx.Graphics.Gpu/Image/Texture.cs
@@ -800,29 +800,31 @@ namespace Ryujinx.Graphics.Gpu.Image
///
/// Texture information to compare against
/// Comparison flags
- /// True if the textures are strictly equal or similar, false otherwise
- public bool IsPerfectMatch(TextureInfo info, TextureSearchFlags flags)
+ /// A value indicating how well this texture matches the given info
+ public TextureMatchQuality IsExactMatch(TextureInfo info, TextureSearchFlags flags)
{
- if (!TextureCompatibility.FormatMatches(Info, info, (flags & TextureSearchFlags.ForSampler) != 0, (flags & TextureSearchFlags.ForCopy) != 0))
+ TextureMatchQuality matchQuality = TextureCompatibility.FormatMatches(Info, info, (flags & TextureSearchFlags.ForSampler) != 0, (flags & TextureSearchFlags.ForCopy) != 0);
+
+ if (matchQuality == TextureMatchQuality.NoMatch)
{
- return false;
+ return matchQuality;
}
if (!TextureCompatibility.LayoutMatches(Info, info))
{
- return false;
+ return TextureMatchQuality.NoMatch;
}
if (!TextureCompatibility.SizeMatches(Info, info, (flags & TextureSearchFlags.Strict) == 0))
{
- return false;
+ return TextureMatchQuality.NoMatch;
}
if ((flags & TextureSearchFlags.ForSampler) != 0 || (flags & TextureSearchFlags.Strict) != 0)
{
if (!TextureCompatibility.SamplerParamsMatches(Info, info))
{
- return false;
+ return TextureMatchQuality.NoMatch;
}
}
@@ -832,15 +834,15 @@ namespace Ryujinx.Graphics.Gpu.Image
if (!msTargetCompatible && !TextureCompatibility.TargetAndSamplesCompatible(Info, info))
{
- return false;
+ return TextureMatchQuality.NoMatch;
}
}
else if (!TextureCompatibility.TargetAndSamplesCompatible(Info, info))
{
- return false;
+ return TextureMatchQuality.NoMatch;
}
- return Info.Address == info.Address && Info.Levels == info.Levels;
+ return Info.Address == info.Address && Info.Levels == info.Levels ? matchQuality : TextureMatchQuality.NoMatch;
}
///
diff --git a/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs b/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs
index 2507519b5..e3574be5d 100644
--- a/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs
@@ -125,14 +125,14 @@ namespace Ryujinx.Graphics.Gpu.Image
/// Texture information to compare with
/// 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
- public static bool FormatMatches(TextureInfo lhs, TextureInfo rhs, bool forSampler, bool forCopy)
+ /// A value indicating how well the formats match
+ public static TextureMatchQuality FormatMatches(TextureInfo lhs, TextureInfo rhs, 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 (lhs.FormatInfo.Format == Format.D32Float && rhs.FormatInfo.Format == Format.R32Float && (forSampler || forCopy))
{
- return true;
+ return TextureMatchQuality.FormatAlias;
}
if (forCopy)
@@ -141,22 +141,22 @@ namespace Ryujinx.Graphics.Gpu.Image
// use equivalent color formats. We must also consider them as compatible.
if (lhs.FormatInfo.Format == Format.S8Uint && rhs.FormatInfo.Format == Format.R8Unorm)
{
- return true;
+ return TextureMatchQuality.FormatAlias;
}
if (lhs.FormatInfo.Format == Format.D16Unorm && rhs.FormatInfo.Format == Format.R16Unorm)
{
- return true;
+ return TextureMatchQuality.FormatAlias;
}
if ((lhs.FormatInfo.Format == Format.D24UnormS8Uint ||
lhs.FormatInfo.Format == Format.D24X8Unorm) && rhs.FormatInfo.Format == Format.B8G8R8A8Unorm)
{
- return true;
+ return TextureMatchQuality.FormatAlias;
}
}
- return lhs.FormatInfo.Format == rhs.FormatInfo.Format;
+ return lhs.FormatInfo.Format == rhs.FormatInfo.Format ? TextureMatchQuality.Perfect : TextureMatchQuality.NoMatch;
}
///
diff --git a/Ryujinx.Graphics.Gpu/Image/TextureManager.cs b/Ryujinx.Graphics.Gpu/Image/TextureManager.cs
index 0834d7acc..6b11a6715 100644
--- a/Ryujinx.Graphics.Gpu/Image/TextureManager.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TextureManager.cs
@@ -682,26 +682,43 @@ namespace Ryujinx.Graphics.Gpu.Image
sameAddressOverlapsCount = _textures.FindOverlaps(info.Address, ref _textureOverlaps);
}
+ Texture texture = null;
+
+ TextureMatchQuality bestQuality = TextureMatchQuality.NoMatch;
+
for (int index = 0; index < sameAddressOverlapsCount; index++)
{
Texture overlap = _textureOverlaps[index];
- if (overlap.IsPerfectMatch(info, flags))
+ TextureMatchQuality matchQuality = overlap.IsExactMatch(info, flags);
+
+ if (matchQuality == TextureMatchQuality.Perfect)
{
- if (!isSamplerTexture)
- {
- // If not a sampler texture, it is managed by the auto delete
- // cache, ensure that it is on the "top" of the list to avoid
- // deletion.
- _cache.Lift(overlap);
- }
-
- ChangeSizeIfNeeded(info, overlap, isSamplerTexture, sizeHint);
-
- overlap.SynchronizeMemory();
-
- return overlap;
+ texture = overlap;
+ break;
}
+ else if (matchQuality > bestQuality)
+ {
+ texture = overlap;
+ bestQuality = matchQuality;
+ }
+ }
+
+ if (texture != null)
+ {
+ if (!isSamplerTexture)
+ {
+ // If not a sampler texture, it is managed by the auto delete
+ // cache, ensure that it is on the "top" of the list to avoid
+ // deletion.
+ _cache.Lift(texture);
+ }
+
+ ChangeSizeIfNeeded(info, texture, isSamplerTexture, sizeHint);
+
+ texture.SynchronizeMemory();
+
+ return texture;
}
// Calculate texture sizes, used to find all overlapping textures.
@@ -743,8 +760,6 @@ namespace Ryujinx.Graphics.Gpu.Image
overlapsCount = _textures.FindOverlaps(info.Address, size, ref _textureOverlaps);
}
- Texture texture = null;
-
for (int index = 0; index < overlapsCount; index++)
{
Texture overlap = _textureOverlaps[index];
diff --git a/Ryujinx.Graphics.Gpu/Image/TextureMatchQuality.cs b/Ryujinx.Graphics.Gpu/Image/TextureMatchQuality.cs
new file mode 100644
index 000000000..1351bf242
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/Image/TextureMatchQuality.cs
@@ -0,0 +1,9 @@
+namespace Ryujinx.Graphics.Gpu.Image
+{
+ enum TextureMatchQuality
+ {
+ NoMatch,
+ FormatAlias,
+ Perfect
+ }
+}
diff --git a/Ryujinx.Graphics.Gpu/Image/TexturePool.cs b/Ryujinx.Graphics.Gpu/Image/TexturePool.cs
index e26dc501d..53d810b96 100644
--- a/Ryujinx.Graphics.Gpu/Image/TexturePool.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TexturePool.cs
@@ -121,7 +121,7 @@ namespace Ryujinx.Graphics.Gpu.Image
// If the descriptors are the same, the texture is the same,
// we don't need to remove as it was not modified. Just continue.
- if (texture.IsPerfectMatch(GetInfo(descriptor), TextureSearchFlags.Strict))
+ if (texture.IsExactMatch(GetInfo(descriptor), TextureSearchFlags.Strict) != TextureMatchQuality.NoMatch)
{
continue;
}