skip unnecessary copy

merge-requests/195/head
LotP1 2025-10-26 19:22:40 +01:00
parent 7adea58204
commit 1dcda7f8fd
8 changed files with 78 additions and 15 deletions

View File

@ -151,6 +151,11 @@ namespace Ryujinx.Cpu.AppleHv
} }
} }
public override bool TryReadUnsafe(ulong va, int length, out Span<byte> data)
{
throw new NotImplementedException();
}
public override void Write(ulong va, ReadOnlySpan<byte> data) public override void Write(ulong va, ReadOnlySpan<byte> data)
{ {
try try

View File

@ -174,6 +174,11 @@ namespace Ryujinx.Cpu.Jit
} }
} }
} }
public override bool TryReadUnsafe(ulong va, int length, out Span<byte> data)
{
throw new NotImplementedException();
}
public override void Write(ulong va, ReadOnlySpan<byte> data) public override void Write(ulong va, ReadOnlySpan<byte> data)
{ {

View File

@ -151,6 +151,11 @@ namespace Ryujinx.Cpu.Jit
return default; return default;
} }
} }
public override bool TryReadUnsafe(ulong va, int length, out Span<byte> data)
{
throw new NotImplementedException();
}
public override T ReadTracked<T>(ulong va) public override T ReadTracked<T>(ulong va)
{ {

View File

@ -227,6 +227,11 @@ namespace Ryujinx.Cpu.Jit
} }
} }
} }
public override bool TryReadUnsafe(ulong va, int length, out Span<byte> data)
{
throw new NotImplementedException();
}
public override bool WriteWithRedundancyCheck(ulong va, ReadOnlySpan<byte> data) public override bool WriteWithRedundancyCheck(ulong va, ReadOnlySpan<byte> data)
{ {

View File

@ -123,15 +123,15 @@ namespace Ryujinx.HLE.HOS.Services.Nv
return NvResult.InvalidSize; return NvResult.InvalidSize;
} }
byte[] outputData = new byte[outputDataSize]; if (!context.Memory.TryReadUnsafe(inputDataPosition, (int)inputDataSize, out arguments))
{
byte[] temp = new byte[inputDataSize]; arguments = new byte[inputDataSize];
context.Memory.Read(inputDataPosition, arguments);
context.Memory.Read(inputDataPosition, temp); }
else
Buffer.BlockCopy(temp, 0, outputData, 0, temp.Length); {
arguments = arguments.ToArray();
arguments = new Span<byte>(outputData); }
} }
else if (isWrite) else if (isWrite)
{ {
@ -470,12 +470,12 @@ namespace Ryujinx.HLE.HOS.Services.Nv
(ulong inlineInBufferPosition, ulong inlineInBufferSize) = context.Request.GetBufferType0x21(1); (ulong inlineInBufferPosition, ulong inlineInBufferSize) = context.Request.GetBufferType0x21(1);
errorCode = GetIoctlArgument(context, ioctlCommand, out Span<byte> arguments); errorCode = GetIoctlArgument(context, ioctlCommand, out Span<byte> arguments);
byte[] temp = new byte[inlineInBufferSize]; if (!context.Memory.TryReadUnsafe(inlineInBufferPosition, (int)inlineInBufferSize, out Span<byte> inlineInBuffer))
{
context.Memory.Read(inlineInBufferPosition, temp); inlineInBuffer = new byte[inlineInBufferSize];
context.Memory.Read(inlineInBufferPosition, inlineInBuffer);
Span<byte> inlineInBuffer = new(temp); }
if (errorCode == NvResult.Success) if (errorCode == NvResult.Success)
{ {

View File

@ -60,6 +60,15 @@ namespace Ryujinx.Memory
/// <param name="data">Span to store the data being read into</param> /// <param name="data">Span to store the data being read into</param>
/// <exception cref="InvalidMemoryRegionException">Throw for unhandled invalid or unmapped memory accesses</exception> /// <exception cref="InvalidMemoryRegionException">Throw for unhandled invalid or unmapped memory accesses</exception>
void Read(ulong va, Span<byte> data); void Read(ulong va, Span<byte> data);
/// <summary>
/// Gets a span of CPU mapped memory.
/// </summary>
/// <param name="va">Virtual address of the data in memory</param>
/// <param name="length">Length of the data in memory</param>
/// <param name="data">Span that references the data being read</param>
/// <exception cref="InvalidMemoryRegionException">Throw for unhandled invalid or unmapped memory accesses</exception>
bool TryReadUnsafe(ulong va, int length, out Span<byte> data);
/// <summary> /// <summary>
/// Writes data to CPU mapped memory. /// Writes data to CPU mapped memory.

View File

@ -159,6 +159,13 @@ namespace Ryujinx.Memory
AssertValidAddressAndSize(va, data.Length); AssertValidAddressAndSize(va, data.Length);
if (IsContiguousAndMapped(va, data.Length))
{
nuint pa = TranslateVirtualAddressChecked(va);
GetPhysicalAddressSpan(pa, data.Length).CopyTo(data);
}
int offset = 0, size; int offset = 0, size;
if ((va & PageMask) != 0) if ((va & PageMask) != 0)
@ -182,6 +189,28 @@ namespace Ryujinx.Memory
} }
} }
public virtual bool TryReadUnsafe(ulong va, int length, out Span<byte> data)
{
if (!IsContiguousAndMapped(va, length))
{
data = default;
return false;
}
if (length == 0)
{
data = Span<byte>.Empty;
return true;
}
AssertValidAddressAndSize(va, length);
nuint pa = TranslateVirtualAddressChecked(va);
data = GetPhysicalAddressSpan(pa, length);
return true;
}
public virtual T ReadTracked<T>(ulong va) where T : unmanaged public virtual T ReadTracked<T>(ulong va) where T : unmanaged
{ {
SignalMemoryTracking(va, (ulong)Unsafe.SizeOf<T>(), false); SignalMemoryTracking(va, (ulong)Unsafe.SizeOf<T>(), false);

View File

@ -42,6 +42,11 @@ namespace Ryujinx.Tests.Memory
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public bool TryReadUnsafe(ulong va, int lenfth, out Span<byte> data)
{
throw new NotImplementedException();
}
public void Write<T>(ulong va, T value) where T : unmanaged public void Write<T>(ulong va, T value) where T : unmanaged
{ {