forked from Mirror/Ryujinx
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
This commit is contained in:
parent
a906f2071c
commit
6db16b4110
5 changed files with 71 additions and 13 deletions
19
Ryujinx.Common/ReferenceEqualityComparer.cs
Normal file
19
Ryujinx.Common/ReferenceEqualityComparer.cs
Normal file
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -94,7 +94,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
srcTexture.HostTexture.CopyTo(dstTexture.HostTexture, srcRegion, dstRegion, linearFilter);
|
srcTexture.HostTexture.CopyTo(dstTexture.HostTexture, srcRegion, dstRegion, linearFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
dstTexture.Modified = true;
|
dstTexture.SignalModified();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -286,7 +286,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
|
|
||||||
if (color != null)
|
if (color != null)
|
||||||
{
|
{
|
||||||
color.Modified = true;
|
color.SignalModified();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,7 +306,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
||||||
|
|
||||||
if (depthStencil != null)
|
if (depthStencil != null)
|
||||||
{
|
{
|
||||||
depthStencil.Modified = true;
|
depthStencil.SignalModified();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,9 +54,14 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
public LinkedListNode<Texture> CacheNode { get; set; }
|
public LinkedListNode<Texture> CacheNode { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Texture data modified by the GPU.
|
/// Event to fire when texture data is modified by the GPU.
|
||||||
/// </summary>
|
/// </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>
|
/// <summary>
|
||||||
/// Start address of the texture in guest memory.
|
/// Start address of the texture in guest memory.
|
||||||
|
@ -933,6 +938,14 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
_layers = info.GetLayers();
|
_layers = info.GetLayers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Signals that the texture has been modified.
|
||||||
|
/// </summary>
|
||||||
|
public void SignalModified()
|
||||||
|
{
|
||||||
|
Modified?.Invoke(this);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Replaces the host texture, while disposing of the old one if needed.
|
/// Replaces the host texture, while disposing of the old one if needed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -1012,6 +1025,8 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
|
|
||||||
_arrayViewTexture?.Dispose();
|
_arrayViewTexture?.Dispose();
|
||||||
_arrayViewTexture = null;
|
_arrayViewTexture = null;
|
||||||
|
|
||||||
|
Disposed?.Invoke(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -5,6 +5,7 @@ using Ryujinx.Graphics.Gpu.Memory;
|
||||||
using Ryujinx.Graphics.Gpu.State;
|
using Ryujinx.Graphics.Gpu.State;
|
||||||
using Ryujinx.Graphics.Texture;
|
using Ryujinx.Graphics.Texture;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Gpu.Image
|
namespace Ryujinx.Graphics.Gpu.Image
|
||||||
{
|
{
|
||||||
|
@ -35,6 +36,8 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
|
|
||||||
private readonly AutoDeleteCache _cache;
|
private readonly AutoDeleteCache _cache;
|
||||||
|
|
||||||
|
private readonly HashSet<Texture> _modified;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructs a new instance of the texture manager.
|
/// Constructs a new instance of the texture manager.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -57,6 +60,8 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
_textureOverlaps = new Texture[OverlapsBufferInitialCapacity];
|
_textureOverlaps = new Texture[OverlapsBufferInitialCapacity];
|
||||||
|
|
||||||
_cache = new AutoDeleteCache();
|
_cache = new AutoDeleteCache();
|
||||||
|
|
||||||
|
_modified = new HashSet<Texture>(new ReferenceEqualityComparer<Texture>());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -579,6 +584,8 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
if (!isSamplerTexture)
|
if (!isSamplerTexture)
|
||||||
{
|
{
|
||||||
_cache.Add(texture);
|
_cache.Add(texture);
|
||||||
|
texture.Modified += CacheTextureModified;
|
||||||
|
texture.Disposed += CacheTextureDisposed;
|
||||||
}
|
}
|
||||||
|
|
||||||
_textures.Add(texture);
|
_textures.Add(texture);
|
||||||
|
@ -588,6 +595,24 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <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>
|
/// <summary>
|
||||||
/// Resizes the temporary buffer used for range list intersection results, if it has grown too much.
|
/// Resizes the temporary buffer used for range list intersection results, if it has grown too much.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -722,15 +747,14 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Flush()
|
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.Flush();
|
||||||
|
|
||||||
texture.Modified = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_modified.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -740,15 +764,14 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
/// <param name="size">The range size</param>
|
/// <param name="size">The range size</param>
|
||||||
public void Flush(ulong address, ulong size)
|
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.Flush();
|
||||||
|
|
||||||
texture.Modified = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_modified.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -772,6 +795,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
{
|
{
|
||||||
foreach (Texture texture in _textures)
|
foreach (Texture texture in _textures)
|
||||||
{
|
{
|
||||||
|
_modified.Remove(texture);
|
||||||
texture.Dispose();
|
texture.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue