diff options
| author | riperiperi <rhy3756547@hotmail.com> | 2020-11-27 18:46:23 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-11-27 19:46:23 +0100 |
| commit | 0108004691a582f7df8e629c1e68a6bb0e0b90e7 (patch) | |
| tree | bb3090e6670c22cd2eee144c7060f9dd3b252f2b | |
| parent | 88633f4bc2987c3118c4d0f482870b7871b47e81 (diff) | |
Prefer truly perfect texture matches over fomat aliased ones (#1754)
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Image/Texture.cs | 22 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs | 14 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Image/TextureManager.cs | 43 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Image/TextureMatchQuality.cs | 9 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Image/TexturePool.cs | 2 |
5 files changed, 58 insertions, 32 deletions
diff --git a/Ryujinx.Graphics.Gpu/Image/Texture.cs b/Ryujinx.Graphics.Gpu/Image/Texture.cs index 7fb41572..45a27051 100644 --- a/Ryujinx.Graphics.Gpu/Image/Texture.cs +++ b/Ryujinx.Graphics.Gpu/Image/Texture.cs @@ -800,29 +800,31 @@ namespace Ryujinx.Graphics.Gpu.Image /// </summary> /// <param name="info">Texture information to compare against</param> /// <param name="flags">Comparison flags</param> - /// <returns>True if the textures are strictly equal or similar, false otherwise</returns> - public bool IsPerfectMatch(TextureInfo info, TextureSearchFlags flags) + /// <returns>A value indicating how well this texture matches the given info</returns> + 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; } /// <summary> diff --git a/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs b/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs index 2507519b..e3574be5 100644 --- a/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs +++ b/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs @@ -125,14 +125,14 @@ namespace Ryujinx.Graphics.Gpu.Image /// <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="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> - public static bool FormatMatches(TextureInfo lhs, TextureInfo rhs, bool forSampler, bool forCopy) + /// <returns>A value indicating how well the formats match</returns> + 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; } /// <summary> diff --git a/Ryujinx.Graphics.Gpu/Image/TextureManager.cs b/Ryujinx.Graphics.Gpu/Image/TextureManager.cs index 0834d7ac..6b11a671 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); - } + texture = overlap; + break; + } + else if (matchQuality > bestQuality) + { + texture = overlap; + bestQuality = matchQuality; + } + } - ChangeSizeIfNeeded(info, overlap, isSamplerTexture, sizeHint); + 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); + } - overlap.SynchronizeMemory(); + ChangeSizeIfNeeded(info, texture, isSamplerTexture, sizeHint); - return overlap; - } + 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 00000000..1351bf24 --- /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 e26dc501..53d810b9 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; } |
