diff --git a/src/Ryujinx.Graphics.Gpu/Memory/BufferCache.cs b/src/Ryujinx.Graphics.Gpu/Memory/BufferCache.cs index b55de8962..0d623ff95 100644 --- a/src/Ryujinx.Graphics.Gpu/Memory/BufferCache.cs +++ b/src/Ryujinx.Graphics.Gpu/Memory/BufferCache.cs @@ -487,10 +487,12 @@ namespace Ryujinx.Graphics.Gpu.Memory /// The type of usage that created the buffer private void CreateBufferAligned(ulong address, ulong size, BufferStage stage) { + Buffer newBuffer = null; + _buffers.Lock.EnterWriteLock(); Span> overlaps = _buffers.FindOverlapsAsSpan(address, size); - if (overlaps.Length > 0) + if (overlaps.Length != 0) { // The buffer already exists. We can just return the existing buffer // if the buffer we need is fully contained inside the overlapping buffer. @@ -530,13 +532,13 @@ namespace Ryujinx.Graphics.Gpu.Memory address = Math.Min(address, overlaps[0].Address); endAddress = Math.Max(endAddress, overlaps[^1].EndAddress); - - RangeItem[] overlapsArray = overlaps.ToArray(); for (int i = 0; i < overlaps.Length; i++) { anySparseCompatible |= overlaps[i].Value.SparseCompatible; } + + RangeItem[] overlapsArray = overlaps.ToArray(); _buffers.RemoveRange(overlaps[0], overlaps[^1]); @@ -544,22 +546,29 @@ namespace Ryujinx.Graphics.Gpu.Memory ulong newSize = endAddress - address; - Buffer newBuffer = CreateBufferAligned(address, newSize, stage, anySparseCompatible, overlapsArray); - - _buffers.Lock.EnterWriteLock(); - - _buffers.Add(newBuffer); + newBuffer = CreateBufferAligned(address, newSize, stage, anySparseCompatible, overlapsArray); + } + else + { + _buffers.Lock.ExitWriteLock(); } } else { + _buffers.Lock.ExitWriteLock(); + // No overlap, just create a new buffer. - Buffer buffer = new(_context, _physicalMemory, address, size, stage, sparseCompatible: false, []); - - _buffers.Add(buffer); + newBuffer = new(_context, _physicalMemory, address, size, stage, sparseCompatible: false, []); + } + + if (newBuffer is not null) + { + _buffers.Lock.EnterWriteLock(); + + _buffers.Add(newBuffer); + + _buffers.Lock.ExitWriteLock(); } - - _buffers.Lock.ExitWriteLock(); } /// @@ -574,11 +583,12 @@ namespace Ryujinx.Graphics.Gpu.Memory private void CreateBufferAligned(ulong address, ulong size, BufferStage stage, ulong alignment) { bool sparseAligned = alignment >= SparseBufferAlignmentSize; + Buffer newBuffer = null; _buffers.Lock.EnterWriteLock(); Span> overlaps = _buffers.FindOverlapsAsSpan(address, size); - if (overlaps.Length > 0) + if (overlaps.Length != 0) { // If the buffer already exists, make sure if covers the entire range, // and make sure it is properly aligned, otherwise sparse mapping may fail. @@ -595,19 +605,20 @@ namespace Ryujinx.Graphics.Gpu.Memory // overlaps more buffers, so try again after each extension // and ensure we cover all overlaps. - RangeItem oldFirst; endAddress = Math.Max(endAddress, overlaps[^1].EndAddress); - + int oldOverlapCount; + do { address = Math.Min(address, overlaps[0].Address); + endAddress = Math.Max(endAddress, overlaps[^1].EndAddress); address &= ~(alignment - 1); - oldFirst = overlaps[0]; + oldOverlapCount = overlaps.Length; overlaps = _buffers.FindOverlapsAsSpan(address, endAddress - address); } - while (oldFirst != overlaps[0]); + while (oldOverlapCount != overlaps.Length); ulong newSize = endAddress - address; @@ -617,22 +628,29 @@ namespace Ryujinx.Graphics.Gpu.Memory _buffers.Lock.ExitWriteLock(); - Buffer newBuffer = CreateBufferAligned(address, newSize, stage, sparseAligned, overlapsArray); - - _buffers.Lock.EnterWriteLock(); - - _buffers.Add(newBuffer); + newBuffer = CreateBufferAligned(address, newSize, stage, sparseAligned, overlapsArray); + } + else + { + _buffers.Lock.ExitWriteLock(); } } else { + _buffers.Lock.ExitWriteLock(); + // No overlap, just create a new buffer. - Buffer buffer = new(_context, _physicalMemory, address, size, stage, sparseAligned, []); - - _buffers.Add(buffer); + newBuffer = new(_context, _physicalMemory, address, size, stage, sparseAligned, []); + } + + if (newBuffer is not null) + { + _buffers.Lock.EnterWriteLock(); + + _buffers.Add(newBuffer); + + _buffers.Lock.ExitWriteLock(); } - - _buffers.Lock.ExitWriteLock(); } /// @@ -879,7 +897,7 @@ namespace Ryujinx.Graphics.Gpu.Memory { MemoryRange subRange = range.GetSubRange(i); - Buffer subBuffer = _buffers.FindOverlapFast(subRange.Address, subRange.Size).Value; + Buffer subBuffer = _buffers.FindOverlap(subRange.Address, subRange.Size).Value; subBuffer.SynchronizeMemory(subRange.Address, subRange.Size); @@ -977,7 +995,7 @@ namespace Ryujinx.Graphics.Gpu.Memory { if (size != 0) { - Buffer buffer = _buffers.FindOverlapFast(address, size).Value; + Buffer buffer = _buffers.FindOverlap(address, size).Value; if (copyBackVirtual) { diff --git a/src/Ryujinx.Graphics.Gpu/Memory/BufferModifiedRangeList.cs b/src/Ryujinx.Graphics.Gpu/Memory/BufferModifiedRangeList.cs index 46a76ed7c..cd9043059 100644 --- a/src/Ryujinx.Graphics.Gpu/Memory/BufferModifiedRangeList.cs +++ b/src/Ryujinx.Graphics.Gpu/Memory/BufferModifiedRangeList.cs @@ -473,6 +473,7 @@ namespace Ryujinx.Graphics.Gpu.Memory ranges._migrationTarget = this; Lock.EnterWriteLock(); + foreach (BufferModifiedRange range in inheritRanges) { Add(range); diff --git a/src/Ryujinx.Memory/Range/NonOverlappingRangeList.cs b/src/Ryujinx.Memory/Range/NonOverlappingRangeList.cs index 2d0f36c72..b493134c9 100644 --- a/src/Ryujinx.Memory/Range/NonOverlappingRangeList.cs +++ b/src/Ryujinx.Memory/Range/NonOverlappingRangeList.cs @@ -12,9 +12,6 @@ namespace Ryujinx.Memory.Range /// Type of the range. public unsafe class NonOverlappingRangeList : RangeListBase where T : class, INonOverlappingRange { - // private readonly Dictionary> _quickAccess = new(AddressEqualityComparer.Comparer); - // private readonly Dictionary> _fastQuickAccess = new(AddressEqualityComparer.Comparer); - public readonly ReaderWriterLockSlim Lock = new(); /// @@ -44,8 +41,6 @@ namespace Ryujinx.Memory.Range RangeItem rangeItem = new(item); Insert(index, rangeItem); - - // _quickAccess.Add(item.Address, rangeItem); } /// @@ -71,15 +66,7 @@ namespace Ryujinx.Memory.Range Items[index + 1].Previous = rangeItem; } - // foreach (ulong addr in Items[index].QuickAccessAddresses) - // { - // _quickAccess.Remove(addr); - // _fastQuickAccess.Remove(addr); - // } - Items[index] = rangeItem; - - // _quickAccess[item.Address] = rangeItem; return true; } @@ -108,19 +95,8 @@ namespace Ryujinx.Memory.Range Items[index + 1].Previous = rangeItem; } - // foreach (ulong addr in item.QuickAccessAddresses) - // { - // _quickAccess.Remove(addr); - // _fastQuickAccess.Remove(addr); - // } - Items[index] = rangeItem; - // if (item.Address != rangeItem.Address) - // _quickAccess.Remove(item.Address); - // - // _quickAccess[rangeItem.Address] = rangeItem; - return true; } @@ -196,14 +172,6 @@ namespace Ryujinx.Memory.Range if (index >= 0 && Items[index].Value.Equals(item)) { - // _quickAccess.Remove(item.Address); - // - // foreach (ulong addr in Items[index].QuickAccessAddresses) - // { - // _quickAccess.Remove(addr); - // _fastQuickAccess.Remove(addr); - // } - RemoveAt(index); return true; @@ -232,16 +200,6 @@ namespace Ryujinx.Memory.Range (int startIndex, int endIndex) = BinarySearchEdges(startItem.Address, endItem.EndAddress); - // for (int i = startIndex; i < endIndex; i++) - // { - // _quickAccess.Remove(Items[i].Address); - // foreach (ulong addr in Items[i].QuickAccessAddresses) - // { - // _quickAccess.Remove(addr); - // _fastQuickAccess.Remove(addr); - // } - // } - if (endIndex < Count) { Items[endIndex].Previous = startIndex > 0 ? Items[startIndex - 1] : null; @@ -279,13 +237,6 @@ namespace Ryujinx.Memory.Range while (Items[endIndex] is not null && Items[endIndex].Address < address + size) { - // _quickAccess.Remove(Items[endIndex].Address); - // foreach (ulong addr in Items[endIndex].QuickAccessAddresses) - // { - // _quickAccess.Remove(addr); - // _fastQuickAccess.Remove(addr); - // } - if (endIndex == Count - 1) { break; @@ -322,8 +273,6 @@ namespace Ryujinx.Memory.Range Lock.EnterWriteLock(); Count = 0; Lock.ExitWriteLock(); - // _quickAccess.Clear(); - // _fastQuickAccess.Clear(); } /// @@ -436,11 +385,6 @@ namespace Ryujinx.Memory.Range [MethodImpl(MethodImplOptions.AggressiveInlining)] public override RangeItem FindOverlap(ulong address, ulong size) { - // if (_quickAccess.TryGetValue(address, out RangeItem overlap)) - // { - // return overlap; - // } - int index = BinarySearchLeftEdge(address, address + size); if (index < 0) @@ -448,12 +392,6 @@ namespace Ryujinx.Memory.Range return null; } - // if (Items[index].Address < address) - // { - // _quickAccess.TryAdd(address, Items[index]); - // Items[index].QuickAccessAddresses.Add(address); - // } - return Items[index]; } @@ -466,28 +404,12 @@ namespace Ryujinx.Memory.Range [MethodImpl(MethodImplOptions.AggressiveInlining)] public override RangeItem FindOverlapFast(ulong address, ulong size) { - // if (_quickAccess.TryGetValue(address, out RangeItem overlap) || _fastQuickAccess.TryGetValue(address, out overlap)) - // { - // return overlap; - // } - int index = BinarySearch(address, address + size); if (index < 0) { return null; } - - // if (Items[index].Address < address) - // { - // _quickAccess.TryAdd(address, Items[index]); - // } - // else - // { - // _fastQuickAccess.TryAdd(address, Items[index]); - // } - // - // Items[index].QuickAccessAddresses.Add(address); return Items[index]; }