Add missing lock on texture cache UpdateMapping method (#6657)

This commit is contained in:
gdkchan 2024-05-14 12:23:13 -03:00 committed by GitHub
parent a3dc295c5f
commit cd78adf07f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

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