using System;
using System.Runtime.InteropServices;
namespace Ryujinx.Graphics.Gpu.Memory
{
///
/// GPU mapped memory accessor.
///
public class MemoryAccessor
{
private GpuContext _context;
///
/// Creates a new instance of the GPU memory accessor.
///
/// GPU context that the memory accessor belongs to
public MemoryAccessor(GpuContext context)
{
_context = context;
}
///
/// Reads a byte array from GPU mapped memory.
///
/// GPU virtual address where the data is located
/// Size of the data in bytes
/// Byte array with the data
public byte[] ReadBytes(ulong gpuVa, ulong size)
{
return Read(gpuVa, size).ToArray();
}
///
/// Reads data from GPU mapped memory.
/// This reads as much data as possible, up to the specified maximum size.
///
/// GPU virtual address where the data is located
/// Maximum size of the data
/// The data at the specified memory location
public Span Read(ulong gpuVa, ulong maxSize)
{
ulong processVa = _context.MemoryManager.Translate(gpuVa);
ulong size = Math.Min(_context.MemoryManager.GetSubSize(gpuVa), maxSize);
return _context.PhysicalMemory.Read(processVa, size);
}
///
/// Reads a structure from GPU mapped memory.
///
/// Type of the structure
/// GPU virtual address where the strcture is located
/// The structure at the specified memory location
public T Read(ulong gpuVa) where T : struct
{
ulong processVa = _context.MemoryManager.Translate(gpuVa);
ulong size = (uint)Marshal.SizeOf();
return MemoryMarshal.Cast(_context.PhysicalMemory.Read(processVa, size))[0];
}
///
/// Reads a 32-bits signed integer from GPU mapped memory.
///
/// GPU virtual address where the value is located
/// The value at the specified memory location
public int ReadInt32(ulong gpuVa)
{
ulong processVa = _context.MemoryManager.Translate(gpuVa);
return BitConverter.ToInt32(_context.PhysicalMemory.Read(processVa, 4));
}
///
/// Reads a 64-bits unsigned integer from GPU mapped memory.
///
/// GPU virtual address where the value is located
/// The value at the specified memory location
public ulong ReadUInt64(ulong gpuVa)
{
ulong processVa = _context.MemoryManager.Translate(gpuVa);
return BitConverter.ToUInt64(_context.PhysicalMemory.Read(processVa, 8));
}
///
/// Reads a 8-bits unsigned integer from GPU mapped memory.
///
/// GPU virtual address where the value is located
/// The value to be written
public void WriteByte(ulong gpuVa, byte value)
{
ulong processVa = _context.MemoryManager.Translate(gpuVa);
_context.PhysicalMemory.Write(processVa, MemoryMarshal.CreateSpan(ref value, 1));
}
///
/// Writes a 32-bits signed integer to GPU mapped memory.
///
/// GPU virtual address to write the value into
/// The value to be written
public void Write(ulong gpuVa, int value)
{
ulong processVa = _context.MemoryManager.Translate(gpuVa);
_context.PhysicalMemory.Write(processVa, BitConverter.GetBytes(value));
}
///
/// Writes data to GPU mapped memory.
///
/// GPU virtual address to write the data into
/// The data to be written
public void Write(ulong gpuVa, Span data)
{
ulong processVa = _context.MemoryManager.Translate(gpuVa);
_context.PhysicalMemory.Write(processVa, data);
}
}
}