Add a GetSpan method to the memory manager and use it on GPU (#877)
This commit is contained in:
parent
8b90924c1e
commit
b8e3909d80
20 changed files with 93 additions and 48 deletions
|
@ -1,6 +1,7 @@
|
|||
using ARMeilleure.State;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
|
||||
|
@ -552,6 +553,50 @@ namespace ARMeilleure.Memory
|
|||
return data;
|
||||
}
|
||||
|
||||
public ReadOnlySpan<byte> GetSpan(ulong address, ulong size)
|
||||
{
|
||||
if (IsContiguous(address, size))
|
||||
{
|
||||
return new ReadOnlySpan<byte>((void*)Translate((long)address), (int)size);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ReadBytes((long)address, (long)size);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private bool IsContiguous(ulong address, ulong size)
|
||||
{
|
||||
if (!IsValidPosition((long)address))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ulong endVa = (address + size + PageMask) & ~(ulong)PageMask;
|
||||
|
||||
address &= ~(ulong)PageMask;
|
||||
|
||||
int pages = (int)((endVa - address) / PageSize);
|
||||
|
||||
for (int page = 0; page < pages - 1; page++)
|
||||
{
|
||||
if (!IsValidPosition((long)address + PageSize))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (GetPtEntry((long)address) + PageSize != GetPtEntry((long)address + PageSize))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
address += PageSize;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void WriteSByte(long position, sbyte value)
|
||||
{
|
||||
WriteByte(position, (byte)value);
|
||||
|
|
|
@ -8,8 +8,8 @@ namespace Ryujinx.Graphics.GAL
|
|||
|
||||
byte[] GetData(int offset, int size);
|
||||
|
||||
void SetData(Span<byte> data);
|
||||
void SetData(ReadOnlySpan<byte> data);
|
||||
|
||||
void SetData(int offset, Span<byte> data);
|
||||
void SetData(int offset, ReadOnlySpan<byte> data);
|
||||
}
|
||||
}
|
|
@ -11,6 +11,6 @@ namespace Ryujinx.Graphics.GAL
|
|||
|
||||
byte[] GetData();
|
||||
|
||||
void SetData(Span<byte> data);
|
||||
void SetData(ReadOnlySpan<byte> data);
|
||||
}
|
||||
}
|
|
@ -77,7 +77,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
|||
|
||||
sbDescAddress += (ulong)sbDescOffset;
|
||||
|
||||
Span<byte> sbDescriptorData = _context.PhysicalMemory.Read(sbDescAddress, 0x10);
|
||||
ReadOnlySpan<byte> sbDescriptorData = _context.PhysicalMemory.GetSpan(sbDescAddress, 0x10);
|
||||
|
||||
SbDescriptor sbDescriptor = MemoryMarshal.Cast<byte, SbDescriptor>(sbDescriptorData)[0];
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
|||
ulong srcAddress = srcBaseAddress + (ulong)srcOffset;
|
||||
ulong dstAddress = dstBaseAddress + (ulong)dstOffset;
|
||||
|
||||
Span<byte> pixel = _context.PhysicalMemory.Read(srcAddress, (ulong)srcBpp);
|
||||
ReadOnlySpan<byte> pixel = _context.PhysicalMemory.GetSpan(srcAddress, (ulong)srcBpp);
|
||||
|
||||
_context.PhysicalMemory.Write(dstAddress, pixel);
|
||||
}
|
||||
|
|
|
@ -235,7 +235,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
|||
|
||||
sbDescAddress += (ulong)sbDescOffset;
|
||||
|
||||
Span<byte> sbDescriptorData = _context.PhysicalMemory.Read(sbDescAddress, 0x10);
|
||||
ReadOnlySpan<byte> sbDescriptorData = _context.PhysicalMemory.GetSpan(sbDescAddress, 0x10);
|
||||
|
||||
SbDescriptor sbDescriptor = MemoryMarshal.Cast<byte, SbDescriptor>(sbDescriptorData)[0];
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
{
|
||||
ulong address = Address + (ulong)(uint)id * DescriptorSize;
|
||||
|
||||
Span<byte> data = Context.PhysicalMemory.Read(address, DescriptorSize);
|
||||
ReadOnlySpan<byte> data = Context.PhysicalMemory.GetSpan(address, DescriptorSize);
|
||||
|
||||
SamplerDescriptor descriptor = MemoryMarshal.Cast<byte, SamplerDescriptor>(data)[0];
|
||||
|
||||
|
|
|
@ -304,7 +304,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
return;
|
||||
}
|
||||
|
||||
Span<byte> data = _context.PhysicalMemory.Read(Address, Size);
|
||||
ReadOnlySpan<byte> data = _context.PhysicalMemory.GetSpan(Address, Size);
|
||||
|
||||
if (Info.IsLinear)
|
||||
{
|
||||
|
|
|
@ -197,7 +197,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
address = bufferManager.GetGraphicsUniformBufferAddress(stageIndex, binding.CbufSlot);
|
||||
}
|
||||
|
||||
packedId = MemoryMarshal.Cast<byte, int>(_context.PhysicalMemory.Read(address + (ulong)binding.CbufOffset * 4, 4))[0];
|
||||
packedId = MemoryMarshal.Cast<byte, int>(_context.PhysicalMemory.GetSpan(address + (ulong)binding.CbufOffset * 4, 4))[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -321,7 +321,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
|
||||
address += (uint)wordOffset * 4;
|
||||
|
||||
return BitConverter.ToInt32(_context.PhysicalMemory.Read(address, 4));
|
||||
return BitConverter.ToInt32(_context.PhysicalMemory.GetSpan(address, 4));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -85,7 +85,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
{
|
||||
ulong address = Address + (ulong)(uint)id * DescriptorSize;
|
||||
|
||||
Span<byte> data = Context.PhysicalMemory.Read(address, DescriptorSize);
|
||||
ReadOnlySpan<byte> data = Context.PhysicalMemory.GetSpan(address, DescriptorSize);
|
||||
|
||||
return MemoryMarshal.Cast<byte, TextureDescriptor>(data)[0];
|
||||
}
|
||||
|
@ -107,7 +107,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
|
||||
if (texture != null)
|
||||
{
|
||||
Span<byte> data = Context.PhysicalMemory.Read(address, DescriptorSize);
|
||||
ReadOnlySpan<byte> data = Context.PhysicalMemory.GetSpan(address, DescriptorSize);
|
||||
|
||||
TextureDescriptor descriptor = MemoryMarshal.Cast<byte, TextureDescriptor>(data)[0];
|
||||
|
||||
|
|
|
@ -123,7 +123,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||
|
||||
int offset = (int)(mAddress - Address);
|
||||
|
||||
HostBuffer.SetData(offset, _context.PhysicalMemory.Read(mAddress, mSize));
|
||||
HostBuffer.SetData(offset, _context.PhysicalMemory.GetSpan(mAddress, mSize));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -157,7 +157,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||
/// </summary>
|
||||
public void Invalidate()
|
||||
{
|
||||
HostBuffer.SetData(0, _context.PhysicalMemory.Read(Address, Size));
|
||||
HostBuffer.SetData(0, _context.PhysicalMemory.GetSpan(Address, Size));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -27,23 +27,23 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||
/// <returns>Byte array with the data</returns>
|
||||
public byte[] ReadBytes(ulong gpuVa, ulong size)
|
||||
{
|
||||
return Read(gpuVa, size).ToArray();
|
||||
return GetSpan(gpuVa, size).ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads data from GPU mapped memory.
|
||||
/// Gets a read-only span of data from GPU mapped memory.
|
||||
/// This reads as much data as possible, up to the specified maximum size.
|
||||
/// </summary>
|
||||
/// <param name="gpuVa">GPU virtual address where the data is located</param>
|
||||
/// <param name="maxSize">Maximum size of the data</param>
|
||||
/// <returns>The data at the specified memory location</returns>
|
||||
public Span<byte> Read(ulong gpuVa, ulong maxSize)
|
||||
/// <returns>The span of the data at the specified memory location</returns>
|
||||
public ReadOnlySpan<byte> GetSpan(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);
|
||||
return _context.PhysicalMemory.GetSpan(processVa, size);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -58,7 +58,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||
|
||||
ulong size = (uint)Marshal.SizeOf<T>();
|
||||
|
||||
return MemoryMarshal.Cast<byte, T>(_context.PhysicalMemory.Read(processVa, size))[0];
|
||||
return MemoryMarshal.Cast<byte, T>(_context.PhysicalMemory.GetSpan(processVa, size))[0];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -70,7 +70,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||
{
|
||||
ulong processVa = _context.MemoryManager.Translate(gpuVa);
|
||||
|
||||
return BitConverter.ToInt32(_context.PhysicalMemory.Read(processVa, 4));
|
||||
return BitConverter.ToInt32(_context.PhysicalMemory.GetSpan(processVa, 4));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -82,7 +82,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||
{
|
||||
ulong processVa = _context.MemoryManager.Translate(gpuVa);
|
||||
|
||||
return BitConverter.ToUInt64(_context.PhysicalMemory.Read(processVa, 8));
|
||||
return BitConverter.ToUInt64(_context.PhysicalMemory.GetSpan(processVa, 8));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -22,14 +22,14 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads data from the application process.
|
||||
/// Gets a span of data from the application process.
|
||||
/// </summary>
|
||||
/// <param name="address">Address to be read</param>
|
||||
/// <param name="size">Size in bytes to be read</param>
|
||||
/// <returns>The data at the specified memory location</returns>
|
||||
public Span<byte> Read(ulong address, ulong size)
|
||||
/// <param name="address">Start address of the range</param>
|
||||
/// <param name="size">Size in bytes to be range</param>
|
||||
/// <returns>A read only span of the data at the specified memory location</returns>
|
||||
public ReadOnlySpan<byte> GetSpan(ulong address, ulong size)
|
||||
{
|
||||
return _cpuMemory.ReadBytes((long)address, (long)size);
|
||||
return _cpuMemory.GetSpan(address, size);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -37,7 +37,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||
/// </summary>
|
||||
/// <param name="address">Address to write into</param>
|
||||
/// <param name="data">Data to be written</param>
|
||||
public void Write(ulong address, Span<byte> data)
|
||||
public void Write(ulong address, ReadOnlySpan<byte> data)
|
||||
{
|
||||
_cpuMemory.WriteBytes((long)address, data.ToArray());
|
||||
}
|
||||
|
|
|
@ -265,7 +265,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
|
||||
ShaderProgram program;
|
||||
|
||||
Span<byte> code = _context.MemoryAccessor.Read(gpuVa, MaxProgramSize);
|
||||
ReadOnlySpan<byte> code = _context.MemoryAccessor.GetSpan(gpuVa, MaxProgramSize);
|
||||
|
||||
program = Translator.Translate(code, callbacks, DefaultFlags | TranslationFlags.Compute);
|
||||
|
||||
|
@ -319,8 +319,8 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
|
||||
if (gpuVaA != 0)
|
||||
{
|
||||
Span<byte> codeA = _context.MemoryAccessor.Read(gpuVaA, MaxProgramSize);
|
||||
Span<byte> codeB = _context.MemoryAccessor.Read(gpuVa, MaxProgramSize);
|
||||
ReadOnlySpan<byte> codeA = _context.MemoryAccessor.GetSpan(gpuVaA, MaxProgramSize);
|
||||
ReadOnlySpan<byte> codeB = _context.MemoryAccessor.GetSpan(gpuVa, MaxProgramSize);
|
||||
|
||||
program = Translator.Translate(codeA, codeB, callbacks, DefaultFlags);
|
||||
|
||||
|
@ -340,7 +340,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
}
|
||||
else
|
||||
{
|
||||
Span<byte> code = _context.MemoryAccessor.Read(gpuVa, MaxProgramSize);
|
||||
ReadOnlySpan<byte> code = _context.MemoryAccessor.GetSpan(gpuVa, MaxProgramSize);
|
||||
|
||||
program = Translator.Translate(code, callbacks, DefaultFlags);
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||
/// <param name="compute">True for compute shader code, false for graphics shader code</param>
|
||||
/// <param name="fullPath">Output path for the shader code with header included</param>
|
||||
/// <param name="codePath">Output path for the shader code without header</param>
|
||||
public void Dump(Span<byte> code, bool compute, out string fullPath, out string codePath)
|
||||
public void Dump(ReadOnlySpan<byte> code, bool compute, out string fullPath, out string codePath)
|
||||
{
|
||||
_dumpPath = GraphicsConfig.ShadersDumpPath;
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
return data;
|
||||
}
|
||||
|
||||
public void SetData(Span<byte> data)
|
||||
public void SetData(ReadOnlySpan<byte> data)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
|
@ -53,7 +53,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
}
|
||||
}
|
||||
|
||||
public void SetData(int offset, Span<byte> data)
|
||||
public void SetData(int offset, ReadOnlySpan<byte> data)
|
||||
{
|
||||
GL.BindBuffer(BufferTarget.CopyWriteBuffer, Handle);
|
||||
|
||||
|
|
|
@ -217,7 +217,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
}
|
||||
}
|
||||
|
||||
public void SetData(Span<byte> data)
|
||||
public void SetData(ReadOnlySpan<byte> data)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
|||
_opActivators = new ConcurrentDictionary<Type, OpActivator>();
|
||||
}
|
||||
|
||||
public static Block[] Decode(Span<byte> code, ulong headerSize)
|
||||
public static Block[] Decode(ReadOnlySpan<byte> code, ulong headerSize)
|
||||
{
|
||||
List<Block> blocks = new List<Block>();
|
||||
|
||||
|
@ -214,10 +214,10 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
|||
}
|
||||
|
||||
private static void FillBlock(
|
||||
Span<byte> code,
|
||||
Block block,
|
||||
ulong limitAddress,
|
||||
ulong startAddress)
|
||||
ReadOnlySpan<byte> code,
|
||||
Block block,
|
||||
ulong limitAddress,
|
||||
ulong startAddress)
|
||||
{
|
||||
ulong address = block.Address;
|
||||
|
||||
|
|
|
@ -76,9 +76,9 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||
public bool OmapSampleMask { get; }
|
||||
public bool OmapDepth { get; }
|
||||
|
||||
public ShaderHeader(Span<byte> code)
|
||||
public ShaderHeader(ReadOnlySpan<byte> code)
|
||||
{
|
||||
Span<int> header = MemoryMarshal.Cast<byte, int>(code);
|
||||
ReadOnlySpan<int> header = MemoryMarshal.Cast<byte, int>(code);
|
||||
|
||||
int commonWord0 = header[0];
|
||||
int commonWord1 = header[1];
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||
{
|
||||
private const int HeaderSize = 0x50;
|
||||
|
||||
public static Span<byte> ExtractCode(Span<byte> code, bool compute, out int headerSize)
|
||||
public static ReadOnlySpan<byte> ExtractCode(ReadOnlySpan<byte> code, bool compute, out int headerSize)
|
||||
{
|
||||
headerSize = compute ? 0 : HeaderSize;
|
||||
|
||||
|
@ -38,14 +38,14 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||
return code.Slice(0, headerSize + (int)endAddress);
|
||||
}
|
||||
|
||||
public static ShaderProgram Translate(Span<byte> code, TranslatorCallbacks callbacks, TranslationFlags flags)
|
||||
public static ShaderProgram Translate(ReadOnlySpan<byte> code, TranslatorCallbacks callbacks, TranslationFlags flags)
|
||||
{
|
||||
Operation[] ops = DecodeShader(code, callbacks, flags, out ShaderConfig config, out int size);
|
||||
|
||||
return Translate(ops, config, size);
|
||||
}
|
||||
|
||||
public static ShaderProgram Translate(Span<byte> vpACode, Span<byte> vpBCode, TranslatorCallbacks callbacks, TranslationFlags flags)
|
||||
public static ShaderProgram Translate(ReadOnlySpan<byte> vpACode, ReadOnlySpan<byte> vpBCode, TranslatorCallbacks callbacks, TranslationFlags flags)
|
||||
{
|
||||
Operation[] vpAOps = DecodeShader(vpACode, callbacks, flags, out _, out _);
|
||||
Operation[] vpBOps = DecodeShader(vpBCode, callbacks, flags, out ShaderConfig config, out int sizeB);
|
||||
|
@ -88,7 +88,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||
}
|
||||
|
||||
private static Operation[] DecodeShader(
|
||||
Span<byte> code,
|
||||
ReadOnlySpan<byte> code,
|
||||
TranslatorCallbacks callbacks,
|
||||
TranslationFlags flags,
|
||||
out ShaderConfig config,
|
||||
|
|
Reference in a new issue