Texture/Vertex/Index data cache (#132)
* Initial implementation of the texture cache * Cache vertex and index data aswell, some cleanup * Improve handling of the cache by storing cached ranges on a list for each page * Delete old data from the caches automatically, ensure that the cache is cleaned when the mapping/size changes, and some general cleanup
This commit is contained in:
parent
81b59077f8
commit
eafe47fee0
2 changed files with 134 additions and 2 deletions
|
@ -54,7 +54,14 @@ namespace ChocolArm64.Memory
|
||||||
|
|
||||||
ExAddrs = new HashSet<long>();
|
ExAddrs = new HashSet<long>();
|
||||||
|
|
||||||
Ram = Marshal.AllocHGlobal((IntPtr)AMemoryMgr.RamSize + AMemoryMgr.PageSize);
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
|
{
|
||||||
|
Ram = AMemoryWin32.Allocate((IntPtr)AMemoryMgr.RamSize + AMemoryMgr.PageSize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Ram = Marshal.AllocHGlobal((IntPtr)AMemoryMgr.RamSize + AMemoryMgr.PageSize);
|
||||||
|
}
|
||||||
|
|
||||||
RamPtr = (byte*)Ram;
|
RamPtr = (byte*)Ram;
|
||||||
}
|
}
|
||||||
|
@ -141,6 +148,51 @@ namespace ChocolArm64.Memory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long GetHostPageSize()
|
||||||
|
{
|
||||||
|
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
|
{
|
||||||
|
return AMemoryMgr.PageSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
IntPtr MemAddress = new IntPtr(RamPtr);
|
||||||
|
IntPtr MemSize = new IntPtr(AMemoryMgr.RamSize);
|
||||||
|
|
||||||
|
long PageSize = AMemoryWin32.IsRegionModified(MemAddress, MemSize, Reset: false);
|
||||||
|
|
||||||
|
if (PageSize < 1)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
return PageSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsRegionModified(long Position, long Size)
|
||||||
|
{
|
||||||
|
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
long EndPos = Position + Size;
|
||||||
|
|
||||||
|
if ((ulong)EndPos < (ulong)Position)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ulong)EndPos > AMemoryMgr.RamSize)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
IntPtr MemAddress = new IntPtr(RamPtr + Position);
|
||||||
|
IntPtr MemSize = new IntPtr(Size);
|
||||||
|
|
||||||
|
return AMemoryWin32.IsRegionModified(MemAddress, MemSize, Reset: true) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
public sbyte ReadSByte(long Position)
|
public sbyte ReadSByte(long Position)
|
||||||
{
|
{
|
||||||
return (sbyte)ReadByte(Position);
|
return (sbyte)ReadByte(Position);
|
||||||
|
@ -640,7 +692,14 @@ namespace ChocolArm64.Memory
|
||||||
{
|
{
|
||||||
if (Ram != IntPtr.Zero)
|
if (Ram != IntPtr.Zero)
|
||||||
{
|
{
|
||||||
Marshal.FreeHGlobal(Ram);
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
|
{
|
||||||
|
AMemoryWin32.Free(Ram);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Marshal.FreeHGlobal(Ram);
|
||||||
|
}
|
||||||
|
|
||||||
Ram = IntPtr.Zero;
|
Ram = IntPtr.Zero;
|
||||||
}
|
}
|
||||||
|
|
73
Memory/AMemoryWin32.cs
Normal file
73
Memory/AMemoryWin32.cs
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace ChocolArm64.Memory
|
||||||
|
{
|
||||||
|
static class AMemoryWin32
|
||||||
|
{
|
||||||
|
private const int MEM_COMMIT = 0x00001000;
|
||||||
|
private const int MEM_RESERVE = 0x00002000;
|
||||||
|
private const int MEM_WRITE_WATCH = 0x00200000;
|
||||||
|
|
||||||
|
private const int PAGE_READWRITE = 0x04;
|
||||||
|
|
||||||
|
private const int MEM_RELEASE = 0x8000;
|
||||||
|
|
||||||
|
private const int WRITE_WATCH_FLAG_RESET = 1;
|
||||||
|
|
||||||
|
[DllImport("kernel32.dll")]
|
||||||
|
private static extern IntPtr VirtualAlloc(IntPtr lpAddress, IntPtr dwSize, int flAllocationType, int flProtect);
|
||||||
|
|
||||||
|
[DllImport("kernel32.dll")]
|
||||||
|
private static extern bool VirtualFree(IntPtr lpAddress, IntPtr dwSize, int dwFreeType);
|
||||||
|
|
||||||
|
[DllImport("kernel32.dll")]
|
||||||
|
private unsafe static extern int GetWriteWatch(
|
||||||
|
int dwFlags,
|
||||||
|
IntPtr lpBaseAddress,
|
||||||
|
IntPtr dwRegionSize,
|
||||||
|
IntPtr[] lpAddresses,
|
||||||
|
long* lpdwCount,
|
||||||
|
long* lpdwGranularity);
|
||||||
|
|
||||||
|
public static IntPtr Allocate(IntPtr Size)
|
||||||
|
{
|
||||||
|
const int Flags = MEM_COMMIT | MEM_RESERVE | MEM_WRITE_WATCH;
|
||||||
|
|
||||||
|
IntPtr Address = VirtualAlloc(IntPtr.Zero, Size, Flags, PAGE_READWRITE);
|
||||||
|
|
||||||
|
if (Address == IntPtr.Zero)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Address;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Free(IntPtr Address)
|
||||||
|
{
|
||||||
|
VirtualFree(Address, IntPtr.Zero, MEM_RELEASE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public unsafe static long IsRegionModified(IntPtr Address, IntPtr Size, bool Reset)
|
||||||
|
{
|
||||||
|
IntPtr[] Addresses = new IntPtr[1];
|
||||||
|
|
||||||
|
long Count = Addresses.Length;
|
||||||
|
|
||||||
|
long Granularity;
|
||||||
|
|
||||||
|
int Flags = Reset ? WRITE_WATCH_FLAG_RESET : 0;
|
||||||
|
|
||||||
|
GetWriteWatch(
|
||||||
|
Flags,
|
||||||
|
Address,
|
||||||
|
Size,
|
||||||
|
Addresses,
|
||||||
|
&Count,
|
||||||
|
&Granularity);
|
||||||
|
|
||||||
|
return Count != 0 ? Granularity : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue