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 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 /// Maximum size of the data /// The span of the data at the specified memory location public ReadOnlySpan GetSpan(ulong gpuVa, ulong maxSize) { ulong processVa = _context.MemoryManager.Translate(gpuVa); ulong size = _context.MemoryManager.GetSubSize(gpuVa, maxSize); return _context.PhysicalMemory.GetSpan(processVa, size); } /// /// Reads a structure from GPU mapped memory. /// /// Type of the structure /// GPU virtual address where the structure 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.GetSpan(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.GetSpan(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.GetSpan(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); } } }