using System;
using System.Runtime.CompilerServices;
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, int size)
{
return GetSpan(gpuVa, size).ToArray();
}
///
/// Gets a read-only span of 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
/// Size of the data
/// The span of the data at the specified memory location
public ReadOnlySpan GetSpan(ulong gpuVa, int size)
{
ulong processVa = _context.MemoryManager.Translate(gpuVa);
return _context.PhysicalMemory.GetSpan(processVa, size);
}
///
/// Reads data from GPU mapped memory.
///
/// Type of the data
/// GPU virtual address where the data is located
/// The data at the specified memory location
public T Read(ulong gpuVa) where T : unmanaged
{
ulong processVa = _context.MemoryManager.Translate(gpuVa);
return MemoryMarshal.Cast(_context.PhysicalMemory.GetSpan(processVa, Unsafe.SizeOf()))[0];
}
///
/// 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, T value) where T : unmanaged
{
ulong processVa = _context.MemoryManager.Translate(gpuVa);
_context.PhysicalMemory.Write(processVa, MemoryMarshal.Cast(MemoryMarshal.CreateSpan(ref value, 1)));
}
///
/// Writes data to GPU mapped memory.
///
/// GPU virtual address to write the data into
/// The data to be written
public void Write(ulong gpuVa, ReadOnlySpan data)
{
ulong processVa = _context.MemoryManager.Translate(gpuVa);
_context.PhysicalMemory.Write(processVa, data);
}
}
}