refactor: use Spans for aligned buffer creation

This commit is contained in:
LotP1 2025-06-03 23:53:48 +02:00
parent ce438f7276
commit fe5b6ad7c7
3 changed files with 32 additions and 28 deletions

View file

@ -110,7 +110,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
ulong size, ulong size,
BufferStage stage, BufferStage stage,
bool sparseCompatible, bool sparseCompatible,
IEnumerable<RangeItem<Buffer>> baseBuffers = null) ReadOnlySpan<RangeItem<Buffer>> baseBuffers)
{ {
_context = context; _context = context;
_physicalMemory = physicalMemory; _physicalMemory = physicalMemory;
@ -126,21 +126,22 @@ namespace Ryujinx.Graphics.Gpu.Memory
_useGranular = size > GranularBufferThreshold; _useGranular = size > GranularBufferThreshold;
IEnumerable<IRegionHandle> baseHandles = null; List<IRegionHandle> baseHandles = null;
if (baseBuffers != null) if (!baseBuffers.IsEmpty)
{ {
baseHandles = baseBuffers.SelectMany(buffer => baseHandles = new List<IRegionHandle>();
foreach (RangeItem<Buffer> buffer in baseBuffers)
{ {
if (buffer.Value._useGranular) if (buffer.Value._useGranular)
{ {
return buffer.Value._memoryTrackingGranular.GetHandles(); baseHandles.AddRange((buffer.Value._memoryTrackingGranular.GetHandles()));
} }
else else
{ {
return Enumerable.Repeat(buffer.Value._memoryTracking, 1); baseHandles.Add(buffer.Value._memoryTracking);
}
} }
});
} }
if (_useGranular) if (_useGranular)

View file

@ -57,7 +57,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
/// <param name="parent">Parent buffer</param> /// <param name="parent">Parent buffer</param>
/// <param name="stage">Initial buffer stage</param> /// <param name="stage">Initial buffer stage</param>
/// <param name="baseBuffers">Buffers to inherit state from</param> /// <param name="baseBuffers">Buffers to inherit state from</param>
public BufferBackingState(GpuContext context, Buffer parent, BufferStage stage, IEnumerable<RangeItem<Buffer>> baseBuffers = null) public BufferBackingState(GpuContext context, Buffer parent, BufferStage stage, ReadOnlySpan<RangeItem<Buffer>> baseBuffers)
{ {
_size = (int)parent.Size; _size = (int)parent.Size;
_systemMemoryType = context.Capabilities.MemoryType; _systemMemoryType = context.Capabilities.MemoryType;
@ -73,7 +73,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
BufferStage storageFlags = stage & BufferStage.StorageMask; BufferStage storageFlags = stage & BufferStage.StorageMask;
if (parent.Size > DeviceLocalSizeThreshold && baseBuffers == null) if (parent.Size > DeviceLocalSizeThreshold && baseBuffers.IsEmpty)
{ {
_desiredType = BufferBackingType.DeviceMemory; _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. // TODO: Might be nice to force atomic access to be device local for any stage.
} }
if (baseBuffers != null) if (!baseBuffers.IsEmpty)
{ {
foreach (RangeItem<Buffer> buffer in baseBuffers) foreach (RangeItem<Buffer> buffer in baseBuffers)
{ {

View file

@ -495,8 +495,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
private void CreateBufferAligned(ulong address, ulong size, BufferStage stage) private void CreateBufferAligned(ulong address, ulong size, BufferStage stage)
{ {
_buffers.Lock.EnterWriteLock(); _buffers.Lock.EnterWriteLock();
RangeItem<Buffer>[] overlaps = _bufferOverlaps; OverlapResult result = _buffers.FindOverlapsNonOverlappingAsSpan(address, size, out ReadOnlySpan<RangeItem<Buffer>> overlaps);
OverlapResult result = _buffers.FindOverlapsNonOverlapping(address, size, ref overlaps);
if (result.Count != 0) if (result.Count != 0)
{ {
@ -534,10 +533,9 @@ namespace Ryujinx.Graphics.Gpu.Memory
size = Math.Max(size, growthSize); size = Math.Max(size, growthSize);
endAddress = address + size; 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); address = Math.Min(address, overlaps[0].Address);
endAddress = Math.Max(endAddress, overlaps[^1].EndAddress); endAddress = Math.Max(endAddress, overlaps[^1].EndAddress);
@ -549,15 +547,20 @@ namespace Ryujinx.Graphics.Gpu.Memory
anySparseCompatible |= buffer.Value.SparseCompatible; anySparseCompatible |= buffer.Value.SparseCompatible;
} }
ulong newSize = endAddress - address; 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 else
{ {
// No overlap, just create a new buffer. // 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<RangeItem<Buffer>>.Empty);
_buffers.Add(buffer); _buffers.Add(buffer);
} }
@ -579,8 +582,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
private void CreateBufferAligned(ulong address, ulong size, BufferStage stage, ulong alignment) private void CreateBufferAligned(ulong address, ulong size, BufferStage stage, ulong alignment)
{ {
_buffers.Lock.EnterWriteLock(); _buffers.Lock.EnterWriteLock();
RangeItem<Buffer>[] overlaps = _bufferOverlaps; OverlapResult result = _buffers.FindOverlapsNonOverlappingAsSpan(address, size, out ReadOnlySpan<RangeItem<Buffer>> overlaps);
OverlapResult result = _buffers.FindOverlapsNonOverlapping(address, size, ref overlaps);
bool sparseAligned = alignment >= SparseBufferAlignmentSize; bool sparseAligned = alignment >= SparseBufferAlignmentSize;
if (result.Count != 0) if (result.Count != 0)
@ -611,21 +613,23 @@ namespace Ryujinx.Graphics.Gpu.Memory
address &= ~(alignment - 1); address &= ~(alignment - 1);
oldOverlapsCount = result.Count; oldOverlapsCount = result.Count;
result = _buffers.FindOverlapsNonOverlapping(address, endAddress - address, ref overlaps); result = _buffers.FindOverlapsNonOverlappingAsSpan(address, endAddress - address, out overlaps);
} }
while (oldOverlapsCount != result.Count); while (oldOverlapsCount != result.Count);
_buffers.RemoveRange(result);
ulong newSize = endAddress - address; 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 else
{ {
// No overlap, just create a new buffer. // 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<RangeItem<Buffer>>.Empty);
_buffers.Add(buffer); _buffers.Add(buffer);
} }
@ -644,14 +648,11 @@ namespace Ryujinx.Graphics.Gpu.Memory
/// <param name="stage">The type of usage that created the buffer</param> /// <param name="stage">The type of usage that created the buffer</param>
/// <param name="sparseCompatible">Indicates if the buffer can be used in a sparse buffer mapping</param> /// <param name="sparseCompatible">Indicates if the buffer can be used in a sparse buffer mapping</param>
/// <param name="overlaps">Buffers overlapping the range</param> /// <param name="overlaps">Buffers overlapping the range</param>
/// <param name="overlapsCount">Total of overlaps</param> private Buffer CreateBufferAligned(ulong address, ulong size, BufferStage stage, bool sparseCompatible, ReadOnlySpan<RangeItem<Buffer>> overlaps)
private void CreateBufferAligned(ulong address, ulong size, BufferStage stage, bool sparseCompatible, RangeItem<Buffer>[] overlaps, int overlapsCount)
{ {
Buffer newBuffer = new(_context, _physicalMemory, address, size, stage, sparseCompatible, overlaps); Buffer newBuffer = new(_context, _physicalMemory, address, size, stage, sparseCompatible, overlaps);
_buffers.Add(newBuffer); for (int index = 0; index < overlaps.Length; index++)
for (int index = 0; index < overlapsCount; index++)
{ {
Buffer buffer = overlaps[index].Value; Buffer buffer = overlaps[index].Value;
@ -669,6 +670,8 @@ namespace Ryujinx.Graphics.Gpu.Memory
NotifyBuffersModified?.Invoke(); NotifyBuffersModified?.Invoke();
RecreateMultiRangeBuffers(address, size); RecreateMultiRangeBuffers(address, size);
return newBuffer;
} }
/// <summary> /// <summary>