Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add missing lock on texture cache UpdateMapping method #6657

Merged
merged 1 commit into from
May 14, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
95 changes: 84 additions & 11 deletions src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using Ryujinx.Memory.Range;
using System;
using System.Collections.Generic;
using System.Threading;

namespace Ryujinx.Graphics.Gpu.Image
{
Expand Down Expand Up @@ -39,6 +40,8 @@ public OverlapInfo(TextureViewCompatibility compatibility, int firstLayer, int f
private readonly MultiRangeList<Texture> _textures;
private readonly HashSet<Texture> _partiallyMappedTextures;

private readonly ReaderWriterLockSlim _texturesLock;

private Texture[] _textureOverlaps;
private OverlapInfo[] _overlapInfo;

Expand All @@ -57,6 +60,8 @@ public TextureCache(GpuContext context, PhysicalMemory physicalMemory)
_textures = new MultiRangeList<Texture>();
_partiallyMappedTextures = new HashSet<Texture>();

_texturesLock = new ReaderWriterLockSlim();

_textureOverlaps = new Texture[OverlapsBufferInitialCapacity];
_overlapInfo = new OverlapInfo[OverlapsBufferInitialCapacity];

Expand All @@ -75,10 +80,16 @@ public void MemoryUnmappedHandler(object sender, UnmapEventArgs e)

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)
{
Expand Down Expand Up @@ -217,7 +228,18 @@ public void Lift(Texture texture)
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++)
{
Expand All @@ -231,11 +253,20 @@ public bool UpdateMapping(Texture texture, MultiRange range)
}
}

_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;
}
Expand Down Expand Up @@ -611,11 +642,17 @@ private static void DiscardIfNeeded(bool discard, Texture texture, Size? sizeHin

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;

Expand Down Expand Up @@ -698,10 +735,16 @@ private static void DiscardIfNeeded(bool discard, Texture texture, Size? sizeHin

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)
Expand Down Expand Up @@ -1025,10 +1068,16 @@ private static void DiscardIfNeeded(bool discard, Texture texture, Size? sizeHin
_cache.Add(texture);
}

lock (_textures)
_texturesLock.EnterWriteLock();

try
{
_textures.Add(texture);
}
finally
{
_texturesLock.ExitWriteLock();
}

if (partiallyMapped)
{
Expand Down Expand Up @@ -1091,7 +1140,19 @@ public Texture FindShortCache(in TextureDescriptor descriptor)
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++)
Expand Down Expand Up @@ -1232,10 +1293,16 @@ public static TextureCreateInfo GetCreateInfo(TextureInfo info, Capabilities cap
/// <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)
{
Expand Down Expand Up @@ -1324,13 +1391,19 @@ public void Tick()
/// </summary>
public void Dispose()
{
lock (_textures)
_texturesLock.EnterReadLock();

try
{
foreach (Texture texture in _textures)
{
texture.Dispose();
}
}
finally
{
_texturesLock.ExitReadLock();
}
}
}
}