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:
parent
76d95dee05
commit
c393cdf8e3
64 changed files with 3289 additions and 1852 deletions
112
Ryujinx.HLE/Memory/ArenaAllocator.cs
Normal file
112
Ryujinx.HLE/Memory/ArenaAllocator.cs
Normal file
|
@ -0,0 +1,112 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace Ryujinx.HLE.Memory
|
||||
{
|
||||
class ArenaAllocator
|
||||
{
|
||||
private class Region
|
||||
{
|
||||
public long Position { get; set; }
|
||||
public long Size { get; set; }
|
||||
|
||||
public Region(long Position, long Size)
|
||||
{
|
||||
this.Position = Position;
|
||||
this.Size = Size;
|
||||
}
|
||||
}
|
||||
|
||||
private LinkedList<Region> FreeRegions;
|
||||
|
||||
public long TotalAvailableSize { get; private set; }
|
||||
public long TotalUsedSize { get; private set; }
|
||||
|
||||
public ArenaAllocator(long ArenaSize)
|
||||
{
|
||||
TotalAvailableSize = ArenaSize;
|
||||
|
||||
FreeRegions = new LinkedList<Region>();
|
||||
|
||||
FreeRegions.AddFirst(new Region(0, ArenaSize));
|
||||
}
|
||||
|
||||
public bool TryAllocate(long Size, out long Position)
|
||||
{
|
||||
LinkedListNode<Region> Node = FreeRegions.First;
|
||||
|
||||
while (Node != null)
|
||||
{
|
||||
Region Rg = Node.Value;
|
||||
|
||||
if ((ulong)Rg.Size >= (ulong)Size)
|
||||
{
|
||||
Position = Rg.Position;
|
||||
|
||||
Rg.Position += Size;
|
||||
Rg.Size -= Size;
|
||||
|
||||
TotalUsedSize += Size;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Node = Node.Next;
|
||||
}
|
||||
|
||||
Position = 0;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Free(long Position, long Size)
|
||||
{
|
||||
long End = Position + Size;
|
||||
|
||||
Region NewRg = new Region(Position, Size);
|
||||
|
||||
LinkedListNode<Region> Node = FreeRegions.First;
|
||||
LinkedListNode<Region> PrevSz = Node;
|
||||
|
||||
while (Node != null)
|
||||
{
|
||||
LinkedListNode<Region> NextNode = Node.Next;
|
||||
|
||||
Region Rg = Node.Value;
|
||||
|
||||
long RgEnd = Rg.Position + Rg.Size;
|
||||
|
||||
if (Rg.Position == End)
|
||||
{
|
||||
NewRg.Size += Rg.Size;
|
||||
|
||||
FreeRegions.Remove(Node);
|
||||
}
|
||||
else if (RgEnd == Position)
|
||||
{
|
||||
NewRg.Position = Rg.Position;
|
||||
NewRg.Size += Rg.Size;
|
||||
|
||||
FreeRegions.Remove(Node);
|
||||
}
|
||||
else if ((ulong)Rg.Size < (ulong)NewRg.Size &&
|
||||
(ulong)Rg.Size > (ulong)PrevSz.Value.Size)
|
||||
{
|
||||
PrevSz = Node;
|
||||
}
|
||||
|
||||
Node = NextNode;
|
||||
}
|
||||
|
||||
if ((ulong)PrevSz.Value.Size < (ulong)Size)
|
||||
{
|
||||
FreeRegions.AddAfter(PrevSz, NewRg);
|
||||
}
|
||||
else
|
||||
{
|
||||
FreeRegions.AddFirst(NewRg);
|
||||
}
|
||||
|
||||
TotalUsedSize -= Size;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue