Archived
1
0
Fork 0
forked from Mirror/Ryujinx

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 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();
}
}
}
}