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, 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, ReadOnlySpan data) { ulong processVa = _context.MemoryManager.Translate(gpuVa); _context.PhysicalMemory.Write(processVa, data); } } }