diff options
| author | riperiperi <rhy3756547@hotmail.com> | 2020-02-06 21:49:26 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-02-07 08:49:26 +1100 |
| commit | 6db16b411031b17ac171dac3899ce0488a1b40df (patch) | |
| tree | 5e33452e60dc563db8e2bfbd32927c147baa5fa8 | |
| parent | a906f2071cbe4caf53c697bcb7dfa91e3e7dcfae (diff) | |
Only enumerate cached textures that are modified when flushing. (#918)
* Only enumarate cached textures that are modified when flushing, rather than all of them.
* Remove locking.
* Add missing clear.
* Remove texture from modified list when data is disposed.
In case the game does not call either flush method at any point.
* Add ReferenceEqualityComparer from jD for the HashSet
| -rw-r--r-- | Ryujinx.Common/ReferenceEqualityComparer.cs | 19 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Engine/MethodCopyTexture.cs | 2 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Engine/Methods.cs | 4 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Image/Texture.cs | 19 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Image/TextureManager.cs | 40 |
5 files changed, 71 insertions, 13 deletions
diff --git a/Ryujinx.Common/ReferenceEqualityComparer.cs b/Ryujinx.Common/ReferenceEqualityComparer.cs new file mode 100644 index 00000000..d8ec29d8 --- /dev/null +++ b/Ryujinx.Common/ReferenceEqualityComparer.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; + +namespace Ryujinx.Common +{ + public class ReferenceEqualityComparer<T> : IEqualityComparer<T> + where T : class + { + public bool Equals(T x, T y) + { + return x == y; + } + + public int GetHashCode([DisallowNull] T obj) + { + return obj.GetHashCode(); + } + } +} diff --git a/Ryujinx.Graphics.Gpu/Engine/MethodCopyTexture.cs b/Ryujinx.Graphics.Gpu/Engine/MethodCopyTexture.cs index 8d1b2b71..4900db1b 100644 --- a/Ryujinx.Graphics.Gpu/Engine/MethodCopyTexture.cs +++ b/Ryujinx.Graphics.Gpu/Engine/MethodCopyTexture.cs @@ -94,7 +94,7 @@ namespace Ryujinx.Graphics.Gpu.Engine srcTexture.HostTexture.CopyTo(dstTexture.HostTexture, srcRegion, dstRegion, linearFilter); } - dstTexture.Modified = true; + dstTexture.SignalModified(); } } }
\ No newline at end of file diff --git a/Ryujinx.Graphics.Gpu/Engine/Methods.cs b/Ryujinx.Graphics.Gpu/Engine/Methods.cs index d9e7582b..a2c9876e 100644 --- a/Ryujinx.Graphics.Gpu/Engine/Methods.cs +++ b/Ryujinx.Graphics.Gpu/Engine/Methods.cs @@ -286,7 +286,7 @@ namespace Ryujinx.Graphics.Gpu.Engine if (color != null) { - color.Modified = true; + color.SignalModified(); } } @@ -306,7 +306,7 @@ namespace Ryujinx.Graphics.Gpu.Engine if (depthStencil != null) { - depthStencil.Modified = true; + depthStencil.SignalModified(); } } diff --git a/Ryujinx.Graphics.Gpu/Image/Texture.cs b/Ryujinx.Graphics.Gpu/Image/Texture.cs index 7d5e9079..7511bdfa 100644 --- a/Ryujinx.Graphics.Gpu/Image/Texture.cs +++ b/Ryujinx.Graphics.Gpu/Image/Texture.cs @@ -54,9 +54,14 @@ namespace Ryujinx.Graphics.Gpu.Image public LinkedListNode<Texture> CacheNode { get; set; } /// <summary> - /// Texture data modified by the GPU. + /// Event to fire when texture data is modified by the GPU. /// </summary> - public bool Modified { get; set; } + public event Action<Texture> Modified; + + /// <summary> + /// Event to fire when texture data is disposed. + /// </summary> + public event Action<Texture> Disposed; /// <summary> /// Start address of the texture in guest memory. @@ -934,6 +939,14 @@ namespace Ryujinx.Graphics.Gpu.Image } /// <summary> + /// Signals that the texture has been modified. + /// </summary> + public void SignalModified() + { + Modified?.Invoke(this); + } + + /// <summary> /// Replaces the host texture, while disposing of the old one if needed. /// </summary> /// <param name="hostTexture">The new host texture</param> @@ -1012,6 +1025,8 @@ namespace Ryujinx.Graphics.Gpu.Image _arrayViewTexture?.Dispose(); _arrayViewTexture = null; + + Disposed?.Invoke(this); } /// <summary> diff --git a/Ryujinx.Graphics.Gpu/Image/TextureManager.cs b/Ryujinx.Graphics.Gpu/Image/TextureManager.cs index 15727191..87fb4161 100644 --- a/Ryujinx.Graphics.Gpu/Image/TextureManager.cs +++ b/Ryujinx.Graphics.Gpu/Image/TextureManager.cs @@ -5,6 +5,7 @@ using Ryujinx.Graphics.Gpu.Memory; using Ryujinx.Graphics.Gpu.State; using Ryujinx.Graphics.Texture; using System; +using System.Collections.Generic; namespace Ryujinx.Graphics.Gpu.Image { @@ -35,6 +36,8 @@ namespace Ryujinx.Graphics.Gpu.Image private readonly AutoDeleteCache _cache; + private readonly HashSet<Texture> _modified; + /// <summary> /// Constructs a new instance of the texture manager. /// </summary> @@ -57,6 +60,8 @@ namespace Ryujinx.Graphics.Gpu.Image _textureOverlaps = new Texture[OverlapsBufferInitialCapacity]; _cache = new AutoDeleteCache(); + + _modified = new HashSet<Texture>(new ReferenceEqualityComparer<Texture>()); } /// <summary> @@ -579,6 +584,8 @@ namespace Ryujinx.Graphics.Gpu.Image if (!isSamplerTexture) { _cache.Add(texture); + texture.Modified += CacheTextureModified; + texture.Disposed += CacheTextureDisposed; } _textures.Add(texture); @@ -589,6 +596,24 @@ namespace Ryujinx.Graphics.Gpu.Image } /// <summary> + /// Signaled when a cache texture is modified, and adds it to a set to be enumerated when flushing textures. + /// </summary> + /// <param name="texture">The texture that was modified.</param> + private void CacheTextureModified(Texture texture) + { + _modified.Add(texture); + } + + /// <summary> + /// Signaled when a cache texture is disposed, so it can be removed from the set of modified textures if present. + /// </summary> + /// <param name="texture">The texture that was diosposed.</param> + private void CacheTextureDisposed(Texture texture) + { + _modified.Remove(texture); + } + + /// <summary> /// Resizes the temporary buffer used for range list intersection results, if it has grown too much. /// </summary> private void ShrinkOverlapsBufferIfNeeded() @@ -722,15 +747,14 @@ namespace Ryujinx.Graphics.Gpu.Image /// </summary> public void Flush() { - foreach (Texture texture in _cache) + foreach (Texture texture in _modified) { - if (texture.Info.IsLinear && texture.Modified) + if (texture.Info.IsLinear) { texture.Flush(); - - texture.Modified = false; } } + _modified.Clear(); } /// <summary> @@ -740,15 +764,14 @@ namespace Ryujinx.Graphics.Gpu.Image /// <param name="size">The range size</param> public void Flush(ulong address, ulong size) { - foreach (Texture texture in _cache) + foreach (Texture texture in _modified) { - if (texture.OverlapsWith(address, size) && texture.Modified) + if (texture.OverlapsWith(address, size)) { texture.Flush(); - - texture.Modified = false; } } + _modified.Clear(); } /// <summary> @@ -772,6 +795,7 @@ namespace Ryujinx.Graphics.Gpu.Image { foreach (Texture texture in _textures) { + _modified.Remove(texture); texture.Dispose(); } } |
