diff options
Diffstat (limited to 'Ryujinx.Graphics.Gpu/Memory/Buffer.cs')
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Memory/Buffer.cs | 74 |
1 files changed, 42 insertions, 32 deletions
diff --git a/Ryujinx.Graphics.Gpu/Memory/Buffer.cs b/Ryujinx.Graphics.Gpu/Memory/Buffer.cs index 2394f90d..3cc96432 100644 --- a/Ryujinx.Graphics.Gpu/Memory/Buffer.cs +++ b/Ryujinx.Graphics.Gpu/Memory/Buffer.cs @@ -1,4 +1,6 @@ +using Ryujinx.Cpu.Tracking; using Ryujinx.Graphics.GAL; +using Ryujinx.Memory.Range; using System; namespace Ryujinx.Graphics.Gpu.Memory @@ -8,6 +10,8 @@ namespace Ryujinx.Graphics.Gpu.Memory /// </summary> class Buffer : IRange, IDisposable { + private static ulong GranularBufferThreshold = 4096; + private readonly GpuContext _context; /// <summary> @@ -30,9 +34,11 @@ namespace Ryujinx.Graphics.Gpu.Memory /// </summary> public ulong EndAddress => Address + Size; - private readonly (ulong, ulong)[] _modifiedRanges; + private CpuSmartMultiRegionHandle _memoryTrackingGranular; + private CpuRegionHandle _memoryTracking; + private int _sequenceNumber; - private readonly int[] _sequenceNumbers; + private bool _useGranular; /// <summary> /// Creates a new instance of the buffer. @@ -48,9 +54,16 @@ namespace Ryujinx.Graphics.Gpu.Memory Handle = context.Renderer.CreateBuffer((int)size); - _modifiedRanges = new (ulong, ulong)[size / PhysicalMemory.PageSize]; + _useGranular = size > GranularBufferThreshold; - _sequenceNumbers = new int[size / MemoryManager.PageSize]; + if (_useGranular) + { + _memoryTrackingGranular = context.PhysicalMemory.BeginSmartGranularTracking(address, size); + } + else + { + _memoryTracking = context.PhysicalMemory.BeginTracking(address, size); + } } /// <summary> @@ -91,41 +104,35 @@ namespace Ryujinx.Graphics.Gpu.Memory /// <param name="size">Size in bytes of the range to synchronize</param> public void SynchronizeMemory(ulong address, ulong size) { - int currentSequenceNumber = _context.SequenceNumber; - - bool needsSync = false; - - ulong buffOffset = address - Address; - - ulong buffEndOffset = (buffOffset + size + MemoryManager.PageMask) & ~MemoryManager.PageMask; - - int startIndex = (int)(buffOffset / MemoryManager.PageSize); - int endIndex = (int)(buffEndOffset / MemoryManager.PageSize); - - for (int index = startIndex; index < endIndex; index++) + if (_useGranular) { - if (_sequenceNumbers[index] != currentSequenceNumber) + _memoryTrackingGranular.QueryModified(address, size, (ulong mAddress, ulong mSize) => { - _sequenceNumbers[index] = currentSequenceNumber; + if (mAddress < Address) + { + mAddress = Address; + } - needsSync = true; - } - } + ulong maxSize = Address + Size - mAddress; - if (!needsSync) - { - return; - } + if (mSize > maxSize) + { + mSize = maxSize; + } - int count = _context.PhysicalMemory.QueryModified(address, size, ResourceName.Buffer, _modifiedRanges); + int offset = (int)(mAddress - Address); - for (int index = 0; index < count; index++) + _context.Renderer.SetBufferData(Handle, offset, _context.PhysicalMemory.GetSpan(mAddress, (int)mSize)); + }, _context.SequenceNumber); + } + else { - (ulong mAddress, ulong mSize) = _modifiedRanges[index]; - - int offset = (int)(mAddress - Address); - - _context.Renderer.SetBufferData(Handle, offset, _context.PhysicalMemory.GetSpan(mAddress, (int)mSize)); + if (_memoryTracking.Dirty && _context.SequenceNumber != _sequenceNumber) + { + _memoryTracking.Reprotect(); + _context.Renderer.SetBufferData(Handle, 0, _context.PhysicalMemory.GetSpan(Address, (int)Size)); + _sequenceNumber = _context.SequenceNumber; + } } } @@ -161,6 +168,9 @@ namespace Ryujinx.Graphics.Gpu.Memory public void Dispose() { _context.Renderer.DeleteBuffer(Handle); + + _memoryTrackingGranular?.Dispose(); + _memoryTracking?.Dispose(); } } }
\ No newline at end of file |
