forked from Mirror/Ryujinx
Prefer truly perfect texture matches over fomat aliased ones (#1754)
This commit is contained in:
parent
88633f4bc2
commit
0108004691
5 changed files with 60 additions and 34 deletions
|
@ -800,29 +800,31 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="info">Texture information to compare against</param>
|
/// <param name="info">Texture information to compare against</param>
|
||||||
/// <param name="flags">Comparison flags</param>
|
/// <param name="flags">Comparison flags</param>
|
||||||
/// <returns>True if the textures are strictly equal or similar, false otherwise</returns>
|
/// <returns>A value indicating how well this texture matches the given info</returns>
|
||||||
public bool IsPerfectMatch(TextureInfo info, TextureSearchFlags flags)
|
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))
|
if (!TextureCompatibility.LayoutMatches(Info, info))
|
||||||
{
|
{
|
||||||
return false;
|
return TextureMatchQuality.NoMatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!TextureCompatibility.SizeMatches(Info, info, (flags & TextureSearchFlags.Strict) == 0))
|
if (!TextureCompatibility.SizeMatches(Info, info, (flags & TextureSearchFlags.Strict) == 0))
|
||||||
{
|
{
|
||||||
return false;
|
return TextureMatchQuality.NoMatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((flags & TextureSearchFlags.ForSampler) != 0 || (flags & TextureSearchFlags.Strict) != 0)
|
if ((flags & TextureSearchFlags.ForSampler) != 0 || (flags & TextureSearchFlags.Strict) != 0)
|
||||||
{
|
{
|
||||||
if (!TextureCompatibility.SamplerParamsMatches(Info, info))
|
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))
|
if (!msTargetCompatible && !TextureCompatibility.TargetAndSamplesCompatible(Info, info))
|
||||||
{
|
{
|
||||||
return false;
|
return TextureMatchQuality.NoMatch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!TextureCompatibility.TargetAndSamplesCompatible(Info, info))
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -125,14 +125,14 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
/// <param name="rhs">Texture information to compare with</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="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="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>
|
/// <returns>A value indicating how well the formats match</returns>
|
||||||
public static bool FormatMatches(TextureInfo lhs, TextureInfo rhs, bool forSampler, bool forCopy)
|
public static TextureMatchQuality FormatMatches(TextureInfo lhs, TextureInfo rhs, bool forSampler, bool forCopy)
|
||||||
{
|
{
|
||||||
// D32F and R32F texture have the same representation internally,
|
// D32F and R32F texture have the same representation internally,
|
||||||
// however the R32F format is used to sample from depth textures.
|
// 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 || forCopy))
|
||||||
{
|
{
|
||||||
return true;
|
return TextureMatchQuality.FormatAlias;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (forCopy)
|
if (forCopy)
|
||||||
|
@ -141,22 +141,22 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
// use equivalent color formats. We must also consider them as compatible.
|
// use equivalent color formats. We must also consider them as compatible.
|
||||||
if (lhs.FormatInfo.Format == Format.S8Uint && rhs.FormatInfo.Format == Format.R8Unorm)
|
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)
|
if (lhs.FormatInfo.Format == Format.D16Unorm && rhs.FormatInfo.Format == Format.R16Unorm)
|
||||||
{
|
{
|
||||||
return true;
|
return TextureMatchQuality.FormatAlias;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((lhs.FormatInfo.Format == Format.D24UnormS8Uint ||
|
if ((lhs.FormatInfo.Format == Format.D24UnormS8Uint ||
|
||||||
lhs.FormatInfo.Format == Format.D24X8Unorm) && rhs.FormatInfo.Format == Format.B8G8R8A8Unorm)
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -682,26 +682,43 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
sameAddressOverlapsCount = _textures.FindOverlaps(info.Address, ref _textureOverlaps);
|
sameAddressOverlapsCount = _textures.FindOverlaps(info.Address, ref _textureOverlaps);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Texture texture = null;
|
||||||
|
|
||||||
|
TextureMatchQuality bestQuality = TextureMatchQuality.NoMatch;
|
||||||
|
|
||||||
for (int index = 0; index < sameAddressOverlapsCount; index++)
|
for (int index = 0; index < sameAddressOverlapsCount; index++)
|
||||||
{
|
{
|
||||||
Texture overlap = _textureOverlaps[index];
|
Texture overlap = _textureOverlaps[index];
|
||||||
|
|
||||||
if (overlap.IsPerfectMatch(info, flags))
|
TextureMatchQuality matchQuality = overlap.IsExactMatch(info, flags);
|
||||||
|
|
||||||
|
if (matchQuality == TextureMatchQuality.Perfect)
|
||||||
{
|
{
|
||||||
if (!isSamplerTexture)
|
texture = overlap;
|
||||||
{
|
break;
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
|
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.
|
// 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);
|
overlapsCount = _textures.FindOverlaps(info.Address, size, ref _textureOverlaps);
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture texture = null;
|
|
||||||
|
|
||||||
for (int index = 0; index < overlapsCount; index++)
|
for (int index = 0; index < overlapsCount; index++)
|
||||||
{
|
{
|
||||||
Texture overlap = _textureOverlaps[index];
|
Texture overlap = _textureOverlaps[index];
|
||||||
|
|
9
Ryujinx.Graphics.Gpu/Image/TextureMatchQuality.cs
Normal file
9
Ryujinx.Graphics.Gpu/Image/TextureMatchQuality.cs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
namespace Ryujinx.Graphics.Gpu.Image
|
||||||
|
{
|
||||||
|
enum TextureMatchQuality
|
||||||
|
{
|
||||||
|
NoMatch,
|
||||||
|
FormatAlias,
|
||||||
|
Perfect
|
||||||
|
}
|
||||||
|
}
|
|
@ -121,7 +121,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
|
|
||||||
// If the descriptors are the same, the texture is the same,
|
// If the descriptors are the same, the texture is the same,
|
||||||
// we don't need to remove as it was not modified. Just continue.
|
// 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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue