mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2025-06-29 08:46:24 +02:00
initial commit
This commit is contained in:
parent
d688fed7d2
commit
be8f4897a2
10 changed files with 935 additions and 407 deletions
|
@ -2,7 +2,6 @@ using Ryujinx.Graphics.GAL;
|
|||
using Ryujinx.Memory.Range;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Ryujinx.Graphics.Gpu.Memory
|
||||
|
@ -42,7 +41,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||
private readonly RangeList<Buffer> _buffers;
|
||||
private readonly MultiRangeList<MultiRangeBuffer> _multiRangeBuffers;
|
||||
|
||||
private Buffer[] _bufferOverlaps;
|
||||
private RangeItem<Buffer>[] _bufferOverlaps;
|
||||
|
||||
private readonly Dictionary<ulong, BufferCacheEntry> _dirtyCache;
|
||||
private readonly Dictionary<ulong, BufferCacheEntry> _modifiedCache;
|
||||
|
@ -64,7 +63,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||
_buffers = [];
|
||||
_multiRangeBuffers = [];
|
||||
|
||||
_bufferOverlaps = new Buffer[OverlapsBufferInitialCapacity];
|
||||
_bufferOverlaps = new RangeItem<Buffer>[OverlapsBufferInitialCapacity];
|
||||
|
||||
_dirtyCache = new Dictionary<ulong, BufferCacheEntry>();
|
||||
|
||||
|
@ -79,7 +78,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||
/// <param name="e">Event arguments</param>
|
||||
public void MemoryUnmappedHandler(object sender, UnmapEventArgs e)
|
||||
{
|
||||
Buffer[] overlaps = new Buffer[10];
|
||||
RangeItem<Buffer>[] overlaps = new RangeItem<Buffer>[10];
|
||||
int overlapCount;
|
||||
|
||||
MultiRange range = ((MemoryManager)sender).GetPhysicalRegions(e.Address, e.Size);
|
||||
|
@ -90,12 +89,12 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||
|
||||
lock (_buffers)
|
||||
{
|
||||
overlapCount = _buffers.FindOverlaps(subRange.Address, subRange.Size, ref overlaps);
|
||||
overlapCount = _buffers.FindOverlaps(subRange.Address, subRange.Size, ref overlaps).Count;
|
||||
}
|
||||
|
||||
for (int i = 0; i < overlapCount; i++)
|
||||
{
|
||||
overlaps[i].Unmapped(subRange.Address, subRange.Size);
|
||||
overlaps[i].Value.Unmapped(subRange.Address, subRange.Size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -495,10 +494,11 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||
/// <param name="stage">The type of usage that created the buffer</param>
|
||||
private void CreateBufferAligned(ulong address, ulong size, BufferStage stage)
|
||||
{
|
||||
Buffer[] overlaps = _bufferOverlaps;
|
||||
int overlapsCount = _buffers.FindOverlapsNonOverlapping(address, size, ref overlaps);
|
||||
_buffers.Lock.EnterWriteLock();
|
||||
RangeItem<Buffer>[] overlaps = _bufferOverlaps;
|
||||
OverlapResult result = _buffers.FindOverlapsNonOverlapping(address, size, ref overlaps);
|
||||
|
||||
if (overlapsCount != 0)
|
||||
if (result.Count != 0)
|
||||
{
|
||||
// The buffer already exists. We can just return the existing buffer
|
||||
// if the buffer we need is fully contained inside the overlapping buffer.
|
||||
|
@ -507,7 +507,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||
// old buffer(s) to the new buffer.
|
||||
|
||||
ulong endAddress = address + size;
|
||||
Buffer overlap0 = overlaps[0];
|
||||
RangeItem<Buffer> overlap0 = overlaps[0];
|
||||
|
||||
if (overlap0.Address > address || overlap0.EndAddress < endAddress)
|
||||
{
|
||||
|
@ -522,39 +522,36 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||
// sequential memory.
|
||||
// Allowing for 2 pages (rather than just one) is necessary to catch cases where the
|
||||
// range crosses a page, and after alignment, ends having a size of 2 pages.
|
||||
if (overlapsCount == 1 &&
|
||||
if (result.Count == 1 &&
|
||||
address >= overlap0.Address &&
|
||||
endAddress - overlap0.EndAddress <= BufferAlignmentSize * 2)
|
||||
{
|
||||
// Try to grow the buffer by 1.5x of its current size.
|
||||
// This improves performance in the cases where the buffer is resized often by small amounts.
|
||||
ulong existingSize = overlap0.Size;
|
||||
ulong existingSize = overlap0.Value.Size;
|
||||
ulong growthSize = (existingSize + Math.Min(existingSize >> 1, MaxDynamicGrowthSize)) & ~BufferAlignmentMask;
|
||||
|
||||
size = Math.Max(size, growthSize);
|
||||
endAddress = address + size;
|
||||
|
||||
overlapsCount = _buffers.FindOverlapsNonOverlapping(address, size, ref overlaps);
|
||||
result = _buffers.FindOverlapsNonOverlapping(address, size, ref overlaps);
|
||||
}
|
||||
|
||||
_buffers.RemoveRange(result);
|
||||
|
||||
address = Math.Min(address, overlaps[0].Address);
|
||||
endAddress = Math.Max(endAddress, overlaps[^1].EndAddress);
|
||||
|
||||
for (int index = 0; index < overlapsCount; index++)
|
||||
for (int index = 0; index < result.Count; index++)
|
||||
{
|
||||
Buffer buffer = overlaps[index];
|
||||
RangeItem<Buffer> buffer = overlaps[index];
|
||||
|
||||
anySparseCompatible |= buffer.SparseCompatible;
|
||||
|
||||
address = Math.Min(address, buffer.Address);
|
||||
endAddress = Math.Max(endAddress, buffer.EndAddress);
|
||||
|
||||
lock (_buffers)
|
||||
{
|
||||
_buffers.Remove(buffer);
|
||||
}
|
||||
anySparseCompatible |= buffer.Value.SparseCompatible;
|
||||
}
|
||||
|
||||
ulong newSize = endAddress - address;
|
||||
|
||||
CreateBufferAligned(address, newSize, stage, anySparseCompatible, overlaps, overlapsCount);
|
||||
CreateBufferAligned(address, newSize, stage, anySparseCompatible, overlaps, result.Count);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -562,11 +559,10 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||
// No overlap, just create a new buffer.
|
||||
Buffer buffer = new(_context, _physicalMemory, address, size, stage, sparseCompatible: false);
|
||||
|
||||
lock (_buffers)
|
||||
{
|
||||
_buffers.Add(buffer);
|
||||
}
|
||||
_buffers.Add(buffer);
|
||||
}
|
||||
|
||||
_buffers.Lock.ExitWriteLock();
|
||||
|
||||
ShrinkOverlapsBufferIfNeeded();
|
||||
}
|
||||
|
@ -582,22 +578,23 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||
/// <param name="alignment">Alignment of the start address of the buffer</param>
|
||||
private void CreateBufferAligned(ulong address, ulong size, BufferStage stage, ulong alignment)
|
||||
{
|
||||
Buffer[] overlaps = _bufferOverlaps;
|
||||
int overlapsCount = _buffers.FindOverlapsNonOverlapping(address, size, ref overlaps);
|
||||
_buffers.Lock.EnterWriteLock();
|
||||
RangeItem<Buffer>[] overlaps = _bufferOverlaps;
|
||||
OverlapResult result = _buffers.FindOverlapsNonOverlapping(address, size, ref overlaps);
|
||||
bool sparseAligned = alignment >= SparseBufferAlignmentSize;
|
||||
|
||||
if (overlapsCount != 0)
|
||||
if (result.Count != 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.
|
||||
|
||||
ulong endAddress = address + size;
|
||||
Buffer overlap0 = overlaps[0];
|
||||
RangeItem<Buffer> overlap0 = overlaps[0];
|
||||
|
||||
if (overlap0.Address > address ||
|
||||
overlap0.EndAddress < endAddress ||
|
||||
(overlap0.Address & (alignment - 1)) != 0 ||
|
||||
(!overlap0.SparseCompatible && sparseAligned))
|
||||
(!overlap0.Value.SparseCompatible && sparseAligned))
|
||||
{
|
||||
// We need to make sure the new buffer is properly aligned.
|
||||
// However, after the range is aligned, it is possible that it
|
||||
|
@ -605,35 +602,24 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||
// and ensure we cover all overlaps.
|
||||
|
||||
int oldOverlapsCount;
|
||||
endAddress = Math.Max(endAddress, overlaps[^1].EndAddress);
|
||||
|
||||
do
|
||||
{
|
||||
for (int index = 0; index < overlapsCount; index++)
|
||||
{
|
||||
Buffer buffer = overlaps[index];
|
||||
|
||||
address = Math.Min(address, buffer.Address);
|
||||
endAddress = Math.Max(endAddress, buffer.EndAddress);
|
||||
}
|
||||
address = Math.Min(address, overlaps[0].Address);
|
||||
|
||||
address &= ~(alignment - 1);
|
||||
|
||||
oldOverlapsCount = overlapsCount;
|
||||
overlapsCount = _buffers.FindOverlapsNonOverlapping(address, endAddress - address, ref overlaps);
|
||||
oldOverlapsCount = result.Count;
|
||||
result = _buffers.FindOverlapsNonOverlapping(address, endAddress - address, ref overlaps);
|
||||
}
|
||||
while (oldOverlapsCount != overlapsCount);
|
||||
while (oldOverlapsCount != result.Count);
|
||||
|
||||
lock (_buffers)
|
||||
{
|
||||
for (int index = 0; index < overlapsCount; index++)
|
||||
{
|
||||
_buffers.Remove(overlaps[index]);
|
||||
}
|
||||
}
|
||||
_buffers.RemoveRange(result);
|
||||
|
||||
ulong newSize = endAddress - address;
|
||||
|
||||
CreateBufferAligned(address, newSize, stage, sparseAligned, overlaps, overlapsCount);
|
||||
CreateBufferAligned(address, newSize, stage, sparseAligned, overlaps, result.Count);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -641,11 +627,9 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||
// No overlap, just create a new buffer.
|
||||
Buffer buffer = new(_context, _physicalMemory, address, size, stage, sparseAligned);
|
||||
|
||||
lock (_buffers)
|
||||
{
|
||||
_buffers.Add(buffer);
|
||||
}
|
||||
_buffers.Add(buffer);
|
||||
}
|
||||
_buffers.Lock.ExitWriteLock();
|
||||
|
||||
ShrinkOverlapsBufferIfNeeded();
|
||||
}
|
||||
|
@ -661,18 +645,15 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||
/// <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="overlapsCount">Total of overlaps</param>
|
||||
private void CreateBufferAligned(ulong address, ulong size, BufferStage stage, bool sparseCompatible, Buffer[] overlaps, int overlapsCount)
|
||||
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.Take(overlapsCount));
|
||||
Buffer newBuffer = new(_context, _physicalMemory, address, size, stage, sparseCompatible, overlaps);
|
||||
|
||||
lock (_buffers)
|
||||
{
|
||||
_buffers.Add(newBuffer);
|
||||
}
|
||||
_buffers.Add(newBuffer);
|
||||
|
||||
for (int index = 0; index < overlapsCount; index++)
|
||||
{
|
||||
Buffer buffer = overlaps[index];
|
||||
Buffer buffer = overlaps[index].Value;
|
||||
|
||||
int dstOffset = (int)(buffer.Address - newBuffer.Address);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue