aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs95
1 files changed, 84 insertions, 11 deletions
diff --git a/src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs b/src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs
index 5743c89c..b9ff060e 100644
--- a/src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs
+++ b/src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs
@@ -8,6 +8,7 @@ using Ryujinx.Graphics.Texture;
using Ryujinx.Memory.Range;
using System;
using System.Collections.Generic;
+using System.Threading;
namespace Ryujinx.Graphics.Gpu.Image
{
@@ -39,6 +40,8 @@ namespace Ryujinx.Graphics.Gpu.Image
private readonly MultiRangeList<Texture> _textures;
private readonly HashSet<Texture> _partiallyMappedTextures;
+ private readonly ReaderWriterLockSlim _texturesLock;
+
private Texture[] _textureOverlaps;
private OverlapInfo[] _overlapInfo;
@@ -57,6 +60,8 @@ namespace Ryujinx.Graphics.Gpu.Image
_textures = new MultiRangeList<Texture>();
_partiallyMappedTextures = new HashSet<Texture>();
+ _texturesLock = new ReaderWriterLockSlim();
+
_textureOverlaps = new Texture[OverlapsBufferInitialCapacity];
_overlapInfo = new OverlapInfo[OverlapsBufferInitialCapacity];
@@ -75,10 +80,16 @@ namespace Ryujinx.Graphics.Gpu.Image
MultiRange unmapped = ((MemoryManager)sender).GetPhysicalRegions(e.Address, e.Size);
- lock (_textures)
+ _texturesLock.EnterReadLock();
+
+ try
{
overlapCount = _textures.FindOverlaps(unmapped, ref overlaps);
}
+ finally
+ {
+ _texturesLock.ExitReadLock();
+ }
if (overlapCount > 0)
{
@@ -217,7 +228,18 @@ namespace Ryujinx.Graphics.Gpu.Image
public bool UpdateMapping(Texture texture, MultiRange range)
{
// There cannot be an existing texture compatible with this mapping in the texture cache already.
- int overlapCount = _textures.FindOverlaps(range, ref _textureOverlaps);
+ int overlapCount;
+
+ _texturesLock.EnterReadLock();
+
+ try
+ {
+ overlapCount = _textures.FindOverlaps(range, ref _textureOverlaps);
+ }
+ finally
+ {
+ _texturesLock.ExitReadLock();
+ }
for (int i = 0; i < overlapCount; i++)
{
@@ -231,11 +253,20 @@ namespace Ryujinx.Graphics.Gpu.Image
}
}
- _textures.Remove(texture);
+ _texturesLock.EnterWriteLock();
- texture.ReplaceRange(range);
+ try
+ {
+ _textures.Remove(texture);
- _textures.Add(texture);
+ texture.ReplaceRange(range);
+
+ _textures.Add(texture);
+ }
+ finally
+ {
+ _texturesLock.ExitWriteLock();
+ }
return true;
}
@@ -611,11 +642,17 @@ namespace Ryujinx.Graphics.Gpu.Image
int sameAddressOverlapsCount;
- lock (_textures)
+ _texturesLock.EnterReadLock();
+
+ try
{
// Try to find a perfect texture match, with the same address and parameters.
sameAddressOverlapsCount = _textures.FindOverlaps(address, ref _textureOverlaps);
}
+ finally
+ {
+ _texturesLock.ExitReadLock();
+ }
Texture texture = null;
@@ -698,10 +735,16 @@ namespace Ryujinx.Graphics.Gpu.Image
if (info.Target != Target.TextureBuffer)
{
- lock (_textures)
+ _texturesLock.EnterReadLock();
+
+ try
{
overlapsCount = _textures.FindOverlaps(range.Value, ref _textureOverlaps);
}
+ finally
+ {
+ _texturesLock.ExitReadLock();
+ }
}
if (_overlapInfo.Length != _textureOverlaps.Length)
@@ -1025,10 +1068,16 @@ namespace Ryujinx.Graphics.Gpu.Image
_cache.Add(texture);
}
- lock (_textures)
+ _texturesLock.EnterWriteLock();
+
+ try
{
_textures.Add(texture);
}
+ finally
+ {
+ _texturesLock.ExitWriteLock();
+ }
if (partiallyMapped)
{
@@ -1091,7 +1140,19 @@ namespace Ryujinx.Graphics.Gpu.Image
return null;
}
- int addressMatches = _textures.FindOverlaps(address, ref _textureOverlaps);
+ int addressMatches;
+
+ _texturesLock.EnterReadLock();
+
+ try
+ {
+ addressMatches = _textures.FindOverlaps(address, ref _textureOverlaps);
+ }
+ finally
+ {
+ _texturesLock.ExitReadLock();
+ }
+
Texture textureMatch = null;
for (int i = 0; i < addressMatches; i++)
@@ -1232,10 +1293,16 @@ namespace Ryujinx.Graphics.Gpu.Image
/// <param name="texture">The texture to be removed</param>
public void RemoveTextureFromCache(Texture texture)
{
- lock (_textures)
+ _texturesLock.EnterWriteLock();
+
+ try
{
_textures.Remove(texture);
}
+ finally
+ {
+ _texturesLock.ExitWriteLock();
+ }
lock (_partiallyMappedTextures)
{
@@ -1324,13 +1391,19 @@ namespace Ryujinx.Graphics.Gpu.Image
/// </summary>
public void Dispose()
{
- lock (_textures)
+ _texturesLock.EnterReadLock();
+
+ try
{
foreach (Texture texture in _textures)
{
texture.Dispose();
}
}
+ finally
+ {
+ _texturesLock.ExitReadLock();
+ }
}
}
}