More flexible memory manager (#307)

* Keep track mapped buffers with fixed offsets

* Started rewriting the memory manager

* Initial support for MapPhysicalMemory and UnmapPhysicalMemory, other tweaks

* MapPhysicalMemory/UnmapPhysicalMemory support, other tweaks

* Rebased

* Optimize the map/unmap physical memory svcs

* Integrate shared font support

* Fix address space reserve alignment

* Some fixes related to gpu memory mapping

* Some cleanup

* Only try uploading const buffers that are really used

* Check if memory region is contiguous

* Rebased

* Add missing count increment on IsRegionModified

* Check for reads/writes outside of the address space, optimize translation with a tail call
This commit is contained in:
gdkchan 2018-08-15 15:59:51 -03:00 committed by GitHub
parent 76d95dee05
commit c393cdf8e3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
64 changed files with 3289 additions and 1852 deletions

View file

@ -1,7 +1,6 @@
using ChocolArm64.Memory;
using Ryujinx.Graphics.Gal;
using System;
using System.Collections.Concurrent;
namespace Ryujinx.HLE.Gpu.Memory
{
@ -26,18 +25,6 @@ namespace Ryujinx.HLE.Gpu.Memory
public AMemory Memory { get; private set; }
private struct MappedMemory
{
public long Size;
public MappedMemory(long Size)
{
this.Size = Size;
}
}
private ConcurrentDictionary<long, MappedMemory> Maps;
private NvGpuVmmCache Cache;
private const long PteUnmapped = -1;
@ -49,8 +36,6 @@ namespace Ryujinx.HLE.Gpu.Memory
{
this.Memory = Memory;
Maps = new ConcurrentDictionary<long, MappedMemory>();
Cache = new NvGpuVmmCache();
PageTable = new long[PTLvl0Size][];
@ -60,14 +45,6 @@ namespace Ryujinx.HLE.Gpu.Memory
{
lock (PageTable)
{
for (long Offset = 0; Offset < Size; Offset += PageSize)
{
if (GetPte(VA + Offset) != PteReserved)
{
return Map(PA, Size);
}
}
for (long Offset = 0; Offset < Size; Offset += PageSize)
{
SetPte(VA + Offset, PA + Offset);
@ -85,10 +62,6 @@ namespace Ryujinx.HLE.Gpu.Memory
if (VA != -1)
{
MappedMemory Map = new MappedMemory(Size);
Maps.AddOrUpdate(VA, Map, (Key, Old) => Map);
for (long Offset = 0; Offset < Size; Offset += PageSize)
{
SetPte(VA + Offset, PA + Offset);
@ -99,19 +72,7 @@ namespace Ryujinx.HLE.Gpu.Memory
}
}
public bool Unmap(long VA)
{
if (Maps.TryRemove(VA, out MappedMemory Map))
{
Free(VA, Map.Size);
return true;
}
return false;
}
public long Reserve(long VA, long Size, long Align)
public long ReserveFixed(long VA, long Size)
{
lock (PageTable)
{
@ -119,7 +80,7 @@ namespace Ryujinx.HLE.Gpu.Memory
{
if (IsPageInUse(VA + Offset))
{
return Reserve(Size, Align);
return -1;
}
}
@ -163,7 +124,9 @@ namespace Ryujinx.HLE.Gpu.Memory
private long GetFreePosition(long Size, long Align = 1)
{
long Position = 0;
//Note: Address 0 is not considered valid by the driver,
//when 0 is returned it's considered a mapping error.
long Position = PageSize;
long FreeSize = 0;
if (Align < 1)

View file

@ -1,4 +1,5 @@
using ChocolArm64.Memory;
using Ryujinx.HLE.Memory;
using System;
using System.Collections.Generic;
@ -129,14 +130,11 @@ namespace Ryujinx.HLE.Gpu.Memory
{
(bool[] Modified, long ModifiedCount) = Memory.IsRegionModified(PA, Size);
if (Modified == null)
{
return true;
}
PA = Memory.GetPhysicalAddress(PA);
ClearCachedPagesIfNeeded();
long PageSize = Memory.GetHostPageSize();
long PageSize = AMemory.PageSize;
EnsureResidencyInitialized(PageSize);
@ -159,9 +157,9 @@ namespace Ryujinx.HLE.Gpu.Memory
while (PA < PAEnd)
{
long Key = PA & ~Mask;
long Key = PA & ~AMemory.PageMask;
long PAPgEnd = Math.Min((PA + PageSize) & ~Mask, PAEnd);
long PAPgEnd = Math.Min((PA + AMemory.PageSize) & ~AMemory.PageMask, PAEnd);
bool IsCached = Cache.TryGetValue(Key, out CachedPage Cp);
@ -228,7 +226,7 @@ namespace Ryujinx.HLE.Gpu.Memory
{
if (Residency == null)
{
Residency = new HashSet<long>[AMemoryMgr.RamSize / PageSize];
Residency = new HashSet<long>[DeviceMemory.RamSize / PageSize];
for (int i = 0; i < Residency.Length; i++)
{