diff --git a/src/Ryujinx.Graphics.Gpu/Memory/Buffer.cs b/src/Ryujinx.Graphics.Gpu/Memory/Buffer.cs index 25034b95a..060358d62 100644 --- a/src/Ryujinx.Graphics.Gpu/Memory/Buffer.cs +++ b/src/Ryujinx.Graphics.Gpu/Memory/Buffer.cs @@ -110,7 +110,7 @@ namespace Ryujinx.Graphics.Gpu.Memory ulong size, BufferStage stage, bool sparseCompatible, - IEnumerable> baseBuffers = null) + ReadOnlySpan> baseBuffers) { _context = context; _physicalMemory = physicalMemory; @@ -126,21 +126,22 @@ namespace Ryujinx.Graphics.Gpu.Memory _useGranular = size > GranularBufferThreshold; - IEnumerable baseHandles = null; + List baseHandles = null; - if (baseBuffers != null) + if (!baseBuffers.IsEmpty) { - baseHandles = baseBuffers.SelectMany(buffer => + baseHandles = new List(); + foreach (RangeItem buffer in baseBuffers) { if (buffer.Value._useGranular) { - return buffer.Value._memoryTrackingGranular.GetHandles(); + baseHandles.AddRange((buffer.Value._memoryTrackingGranular.GetHandles())); } else { - return Enumerable.Repeat(buffer.Value._memoryTracking, 1); + baseHandles.Add(buffer.Value._memoryTracking); } - }); + } } if (_useGranular) diff --git a/src/Ryujinx.Graphics.Gpu/Memory/BufferBackingState.cs b/src/Ryujinx.Graphics.Gpu/Memory/BufferBackingState.cs index 61f0f9d6d..1029c38d9 100644 --- a/src/Ryujinx.Graphics.Gpu/Memory/BufferBackingState.cs +++ b/src/Ryujinx.Graphics.Gpu/Memory/BufferBackingState.cs @@ -57,7 +57,7 @@ namespace Ryujinx.Graphics.Gpu.Memory /// Parent buffer /// Initial buffer stage /// Buffers to inherit state from - public BufferBackingState(GpuContext context, Buffer parent, BufferStage stage, IEnumerable> baseBuffers = null) + public BufferBackingState(GpuContext context, Buffer parent, BufferStage stage, ReadOnlySpan> baseBuffers) { _size = (int)parent.Size; _systemMemoryType = context.Capabilities.MemoryType; @@ -73,7 +73,7 @@ namespace Ryujinx.Graphics.Gpu.Memory BufferStage storageFlags = stage & BufferStage.StorageMask; - if (parent.Size > DeviceLocalSizeThreshold && baseBuffers == null) + if (parent.Size > DeviceLocalSizeThreshold && baseBuffers.IsEmpty) { _desiredType = BufferBackingType.DeviceMemory; } @@ -101,7 +101,7 @@ namespace Ryujinx.Graphics.Gpu.Memory // TODO: Might be nice to force atomic access to be device local for any stage. } - if (baseBuffers != null) + if (!baseBuffers.IsEmpty) { foreach (RangeItem buffer in baseBuffers) { diff --git a/src/Ryujinx.Graphics.Gpu/Memory/BufferCache.cs b/src/Ryujinx.Graphics.Gpu/Memory/BufferCache.cs index 6c2520979..6afcb5a68 100644 --- a/src/Ryujinx.Graphics.Gpu/Memory/BufferCache.cs +++ b/src/Ryujinx.Graphics.Gpu/Memory/BufferCache.cs @@ -495,8 +495,7 @@ namespace Ryujinx.Graphics.Gpu.Memory private void CreateBufferAligned(ulong address, ulong size, BufferStage stage) { _buffers.Lock.EnterWriteLock(); - RangeItem[] overlaps = _bufferOverlaps; - OverlapResult result = _buffers.FindOverlapsNonOverlapping(address, size, ref overlaps); + OverlapResult result = _buffers.FindOverlapsNonOverlappingAsSpan(address, size, out ReadOnlySpan> overlaps); if (result.Count != 0) { @@ -534,10 +533,9 @@ namespace Ryujinx.Graphics.Gpu.Memory size = Math.Max(size, growthSize); endAddress = address + size; - result = _buffers.FindOverlapsNonOverlapping(address, size, ref overlaps); + result = _buffers.FindOverlapsNonOverlappingAsSpan(address, size, out overlaps); } - _buffers.RemoveRange(result); address = Math.Min(address, overlaps[0].Address); endAddress = Math.Max(endAddress, overlaps[^1].EndAddress); @@ -549,15 +547,20 @@ namespace Ryujinx.Graphics.Gpu.Memory anySparseCompatible |= buffer.Value.SparseCompatible; } + ulong newSize = endAddress - address; - CreateBufferAligned(address, newSize, stage, anySparseCompatible, overlaps, result.Count); + Buffer newBuffer = CreateBufferAligned(address, newSize, stage, anySparseCompatible, overlaps); + + _buffers.RemoveRange(result); + + _buffers.Add(newBuffer); } } else { // No overlap, just create a new buffer. - Buffer buffer = new(_context, _physicalMemory, address, size, stage, sparseCompatible: false); + Buffer buffer = new(_context, _physicalMemory, address, size, stage, sparseCompatible: false, ReadOnlySpan>.Empty); _buffers.Add(buffer); } @@ -579,8 +582,7 @@ namespace Ryujinx.Graphics.Gpu.Memory private void CreateBufferAligned(ulong address, ulong size, BufferStage stage, ulong alignment) { _buffers.Lock.EnterWriteLock(); - RangeItem[] overlaps = _bufferOverlaps; - OverlapResult result = _buffers.FindOverlapsNonOverlapping(address, size, ref overlaps); + OverlapResult result = _buffers.FindOverlapsNonOverlappingAsSpan(address, size, out ReadOnlySpan> overlaps); bool sparseAligned = alignment >= SparseBufferAlignmentSize; if (result.Count != 0) @@ -611,21 +613,23 @@ namespace Ryujinx.Graphics.Gpu.Memory address &= ~(alignment - 1); oldOverlapsCount = result.Count; - result = _buffers.FindOverlapsNonOverlapping(address, endAddress - address, ref overlaps); + result = _buffers.FindOverlapsNonOverlappingAsSpan(address, endAddress - address, out overlaps); } while (oldOverlapsCount != result.Count); - _buffers.RemoveRange(result); - ulong newSize = endAddress - address; - CreateBufferAligned(address, newSize, stage, sparseAligned, overlaps, result.Count); + Buffer newBuffer = CreateBufferAligned(address, newSize, stage, sparseAligned, overlaps); + + _buffers.RemoveRange(result); + + _buffers.Add(newBuffer); } } else { // No overlap, just create a new buffer. - Buffer buffer = new(_context, _physicalMemory, address, size, stage, sparseAligned); + Buffer buffer = new(_context, _physicalMemory, address, size, stage, sparseAligned, ReadOnlySpan>.Empty); _buffers.Add(buffer); } @@ -644,14 +648,11 @@ namespace Ryujinx.Graphics.Gpu.Memory /// The type of usage that created the buffer /// Indicates if the buffer can be used in a sparse buffer mapping /// Buffers overlapping the range - /// Total of overlaps - private void CreateBufferAligned(ulong address, ulong size, BufferStage stage, bool sparseCompatible, RangeItem[] overlaps, int overlapsCount) + private Buffer CreateBufferAligned(ulong address, ulong size, BufferStage stage, bool sparseCompatible, ReadOnlySpan> overlaps) { Buffer newBuffer = new(_context, _physicalMemory, address, size, stage, sparseCompatible, overlaps); - _buffers.Add(newBuffer); - - for (int index = 0; index < overlapsCount; index++) + for (int index = 0; index < overlaps.Length; index++) { Buffer buffer = overlaps[index].Value; @@ -669,6 +670,8 @@ namespace Ryujinx.Graphics.Gpu.Memory NotifyBuffersModified?.Invoke(); RecreateMultiRangeBuffers(address, size); + + return newBuffer; } ///