Optimize address translation and write tracking on the MMU (#571)

* Implement faster address translation and write tracking on the MMU

* Rename MemoryAlloc to MemoryManagement, and other nits

* Support multi-level page tables

* Fix typo

* Reword comment a bit

* Support scalar vector loads/stores on the memory fast path, and minor fixes

* Add missing cast

* Alignment

* Fix VirtualFree function signature

* Change MemoryProtection enum to uint aswell for consistency
This commit is contained in:
gdkchan 2019-02-24 04:24:35 -03:00 committed by jduncanator
parent a3d46e4133
commit 5001f78b1d
24 changed files with 1005 additions and 621 deletions

View file

@ -1,4 +1,3 @@
using ChocolArm64.Events;
using ChocolArm64.Memory;
using System.Collections.Concurrent;
@ -19,35 +18,28 @@ namespace Ryujinx.Graphics.Memory
{
_memory = memory;
_memory.ObservedAccess += MemoryAccessHandler;
CachedPages = new ConcurrentDictionary<long, int>[1 << 20];
}
private void MemoryAccessHandler(object sender, MemoryAccessEventArgs e)
{
long pa = _memory.GetPhysicalAddress(e.Position);
CachedPages[pa >> PageBits]?.Clear();
}
public bool IsRegionModified(long position, long size, NvGpuBufferType bufferType)
{
long pa = _memory.GetPhysicalAddress(position);
long va = position;
long addr = pa;
long pa = _memory.GetPhysicalAddress(va);
long endAddr = (addr + size + PageMask) & ~PageMask;
long endAddr = (va + size + PageMask) & ~PageMask;
long addrTruncated = va & ~PageMask;
bool modified = _memory.IsRegionModified(addrTruncated, endAddr - addrTruncated);
int newBuffMask = 1 << (int)bufferType;
_memory.StartObservingRegion(position, size);
long cachedPagesCount = 0;
while (addr < endAddr)
while (va < endAddr)
{
long page = addr >> PageBits;
long page = _memory.GetPhysicalAddress(va) >> PageBits;
ConcurrentDictionary<long, int> dictionary = CachedPages[page];
@ -57,6 +49,10 @@ namespace Ryujinx.Graphics.Memory
CachedPages[page] = dictionary;
}
else if (modified)
{
CachedPages[page].Clear();
}
if (dictionary.TryGetValue(pa, out int currBuffMask))
{
@ -74,10 +70,10 @@ namespace Ryujinx.Graphics.Memory
dictionary[pa] = newBuffMask;
}
addr += PageSize;
va += PageSize;
}
return cachedPagesCount != (endAddr - pa + PageMask) >> PageBits;
return cachedPagesCount != (endAddr - addrTruncated) >> PageBits;
}
}
}