aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorriperiperi <rhy3756547@hotmail.com>2020-02-06 21:49:26 +0000
committerGitHub <noreply@github.com>2020-02-07 08:49:26 +1100
commit6db16b411031b17ac171dac3899ce0488a1b40df (patch)
tree5e33452e60dc563db8e2bfbd32927c147baa5fa8
parenta906f2071cbe4caf53c697bcb7dfa91e3e7dcfae (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.cs19
-rw-r--r--Ryujinx.Graphics.Gpu/Engine/MethodCopyTexture.cs2
-rw-r--r--Ryujinx.Graphics.Gpu/Engine/Methods.cs4
-rw-r--r--Ryujinx.Graphics.Gpu/Image/Texture.cs19
-rw-r--r--Ryujinx.Graphics.Gpu/Image/TextureManager.cs40
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();
}
}