Gpu: Fix thread safety of ReregisterRanges (#3865)

A quick fix to prevent reading the wrong value of Count when reregistering ranges for a new target buffer. Buffer flushes from another thread can modify the range list when the lock isn't active, which can change the count.

This prevents some crashes in Pokemon Scarlet/Violet. It's probably likely that buffer migration during flush is causing some other issues in this game, but this at least prevents the crashing.
This commit is contained in:
riperiperi 2022-11-18 20:47:29 +00:00 committed by GitHub
parent 131baebe2a
commit de162a648b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -325,13 +325,15 @@ namespace Ryujinx.Graphics.Gpu.Memory
public void ReregisterRanges(Action<ulong, ulong> rangeAction) public void ReregisterRanges(Action<ulong, ulong> rangeAction)
{ {
ref var ranges = ref ThreadStaticArray<BufferModifiedRange>.Get(); ref var ranges = ref ThreadStaticArray<BufferModifiedRange>.Get();
int count;
// Range list must be consistent for this operation. // Range list must be consistent for this operation.
lock (_lock) lock (_lock)
{ {
if (ranges.Length < Count) count = Count;
if (ranges.Length < count)
{ {
Array.Resize(ref ranges, Count); Array.Resize(ref ranges, count);
} }
int i = 0; int i = 0;
@ -342,7 +344,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
} }
ulong currentSync = _context.SyncNumber; ulong currentSync = _context.SyncNumber;
for (int i = 0; i < Count; i++) for (int i = 0; i < count; i++)
{ {
BufferModifiedRange range = ranges[i]; BufferModifiedRange range = ranges[i];
if (range.SyncNumber != currentSync) if (range.SyncNumber != currentSync)