aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Ryujinx.Audio/Renderer/Server/StateUpdater.cs9
-rw-r--r--Ryujinx.Audio/Renderer/Server/Voice/VoiceState.cs4
-rw-r--r--Ryujinx.Common/Memory/ByteMemoryPool.ByteMemoryPoolBuffer.cs51
-rw-r--r--Ryujinx.Common/Memory/ByteMemoryPool.cs108
-rw-r--r--Ryujinx.HLE/HOS/Ipc/IpcMessage.cs123
-rw-r--r--Ryujinx.HLE/HOS/Kernel/Common/KTimeManager.cs17
-rw-r--r--Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs7
-rw-r--r--Ryujinx.HLE/HOS/Kernel/Threading/KSynchronization.cs7
-rw-r--r--Ryujinx.HLE/HOS/Services/Audio/AudioRenderer/AudioRendererServer.cs35
-rw-r--r--Ryujinx.HLE/HOS/Services/IpcService.cs2
-rw-r--r--Ryujinx.HLE/HOS/Services/ServerBase.cs2
-rw-r--r--Ryujinx.HLE/HOS/Services/SurfaceFlinger/IHOSBinderDriver.cs21
-rw-r--r--Ryujinx.Input.SDL2/SDL2Gamepad.cs14
13 files changed, 297 insertions, 103 deletions
diff --git a/Ryujinx.Audio/Renderer/Server/StateUpdater.cs b/Ryujinx.Audio/Renderer/Server/StateUpdater.cs
index 0446cd8c..5cf539c6 100644
--- a/Ryujinx.Audio/Renderer/Server/StateUpdater.cs
+++ b/Ryujinx.Audio/Renderer/Server/StateUpdater.cs
@@ -11,6 +11,7 @@ using Ryujinx.Audio.Renderer.Server.Voice;
using Ryujinx.Audio.Renderer.Utils;
using Ryujinx.Common.Logging;
using System;
+using System.Buffers;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@@ -149,12 +150,16 @@ namespace Ryujinx.Audio.Renderer.Server
state.InUse = false;
}
+ Memory<VoiceUpdateState>[] voiceUpdateStatesArray = ArrayPool<Memory<VoiceUpdateState>>.Shared.Rent(Constants.VoiceChannelCountMax);
+
+ Span<Memory<VoiceUpdateState>> voiceUpdateStates = voiceUpdateStatesArray.AsSpan(0, Constants.VoiceChannelCountMax);
+
// Start processing
for (int i = 0; i < context.GetCount(); i++)
{
VoiceInParameter parameter = parameters[i];
- Memory<VoiceUpdateState>[] voiceUpdateStates = new Memory<VoiceUpdateState>[Constants.VoiceChannelCountMax];
+ voiceUpdateStates.Fill(Memory<VoiceUpdateState>.Empty);
ref VoiceOutStatus outStatus = ref SpanIOHelper.GetWriteRef<VoiceOutStatus>(ref _output)[0];
@@ -197,6 +202,8 @@ namespace Ryujinx.Audio.Renderer.Server
}
}
+ ArrayPool<Memory<VoiceUpdateState>>.Shared.Return(voiceUpdateStatesArray);
+
int currentOutputSize = _output.Length;
OutputHeader.VoicesSize = (uint)(Unsafe.SizeOf<VoiceOutStatus>() * context.GetCount());
diff --git a/Ryujinx.Audio/Renderer/Server/Voice/VoiceState.cs b/Ryujinx.Audio/Renderer/Server/Voice/VoiceState.cs
index 006d6dd3..0bf53c54 100644
--- a/Ryujinx.Audio/Renderer/Server/Voice/VoiceState.cs
+++ b/Ryujinx.Audio/Renderer/Server/Voice/VoiceState.cs
@@ -378,7 +378,7 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
/// <param name="outStatus">The given user output.</param>
/// <param name="parameter">The user parameter.</param>
/// <param name="voiceUpdateStates">The voice states associated to the <see cref="VoiceState"/>.</param>
- public void WriteOutStatus(ref VoiceOutStatus outStatus, ref VoiceInParameter parameter, Memory<VoiceUpdateState>[] voiceUpdateStates)
+ public void WriteOutStatus(ref VoiceOutStatus outStatus, ref VoiceInParameter parameter, ReadOnlySpan<Memory<VoiceUpdateState>> voiceUpdateStates)
{
#if DEBUG
// Sanity check in debug mode of the internal state
@@ -424,7 +424,7 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
/// <param name="voiceUpdateStates">The voice states associated to the <see cref="VoiceState"/>.</param>
/// <param name="mapper">The mapper to use.</param>
/// <param name="behaviourContext">The behaviour context.</param>
- public void UpdateWaveBuffers(out ErrorInfo[] errorInfos, ref VoiceInParameter parameter, Memory<VoiceUpdateState>[] voiceUpdateStates, ref PoolMapper mapper, ref BehaviourContext behaviourContext)
+ public void UpdateWaveBuffers(out ErrorInfo[] errorInfos, ref VoiceInParameter parameter, ReadOnlySpan<Memory<VoiceUpdateState>> voiceUpdateStates, ref PoolMapper mapper, ref BehaviourContext behaviourContext)
{
errorInfos = new ErrorInfo[Constants.VoiceWaveBufferCount * 2];
diff --git a/Ryujinx.Common/Memory/ByteMemoryPool.ByteMemoryPoolBuffer.cs b/Ryujinx.Common/Memory/ByteMemoryPool.ByteMemoryPoolBuffer.cs
new file mode 100644
index 00000000..eda350bd
--- /dev/null
+++ b/Ryujinx.Common/Memory/ByteMemoryPool.ByteMemoryPoolBuffer.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Buffers;
+using System.Threading;
+
+namespace Ryujinx.Common.Memory
+{
+ public sealed partial class ByteMemoryPool
+ {
+ /// <summary>
+ /// Represents a <see cref="IMemoryOwner{Byte}"/> that wraps an array rented from
+ /// <see cref="ArrayPool{Byte}.Shared"/> and exposes it as <see cref="Memory{Byte}"/>
+ /// with a length of the requested size.
+ /// </summary>
+ private sealed class ByteMemoryPoolBuffer : IMemoryOwner<byte>
+ {
+ private byte[] _array;
+ private readonly int _length;
+
+ public ByteMemoryPoolBuffer(int length)
+ {
+ _array = ArrayPool<byte>.Shared.Rent(length);
+ _length = length;
+ }
+
+ /// <summary>
+ /// Returns a <see cref="Memory{Byte}"/> belonging to this owner.
+ /// </summary>
+ public Memory<byte> Memory
+ {
+ get
+ {
+ byte[] array = _array;
+
+ ObjectDisposedException.ThrowIf(array is null, this);
+
+ return new Memory<byte>(array, 0, _length);
+ }
+ }
+
+ public void Dispose()
+ {
+ var array = Interlocked.Exchange(ref _array, null);
+
+ if (array != null)
+ {
+ ArrayPool<byte>.Shared.Return(array);
+ }
+ }
+ }
+ }
+}
diff --git a/Ryujinx.Common/Memory/ByteMemoryPool.cs b/Ryujinx.Common/Memory/ByteMemoryPool.cs
new file mode 100644
index 00000000..2910f408
--- /dev/null
+++ b/Ryujinx.Common/Memory/ByteMemoryPool.cs
@@ -0,0 +1,108 @@
+using System;
+using System.Buffers;
+
+namespace Ryujinx.Common.Memory
+{
+ /// <summary>
+ /// Provides a pool of re-usable byte array instances.
+ /// </summary>
+ public sealed partial class ByteMemoryPool
+ {
+ private static readonly ByteMemoryPool _shared = new ByteMemoryPool();
+
+ /// <summary>
+ /// Constructs a <see cref="ByteMemoryPool"/> instance. Private to force access through
+ /// the <see cref="ByteMemoryPool.Shared"/> instance.
+ /// </summary>
+ private ByteMemoryPool()
+ {
+ // No implementation
+ }
+
+ /// <summary>
+ /// Retrieves a shared <see cref="ByteMemoryPool"/> instance.
+ /// </summary>
+ public static ByteMemoryPool Shared => _shared;
+
+ /// <summary>
+ /// Returns the maximum buffer size supported by this pool.
+ /// </summary>
+ public int MaxBufferSize => Array.MaxLength;
+
+ /// <summary>
+ /// Rents a byte memory buffer from <see cref="ArrayPool{Byte}.Shared"/>.
+ /// The buffer may contain data from a prior use.
+ /// </summary>
+ /// <param name="length">The buffer's required length in bytes</param>
+ /// <returns>A <see cref="IMemoryOwner{Byte}"/> wrapping the rented memory</returns>
+ /// <exception cref="ArgumentOutOfRangeException"></exception>
+ public IMemoryOwner<byte> Rent(long length)
+ => RentImpl(checked((int)length));
+
+ /// <summary>
+ /// Rents a byte memory buffer from <see cref="ArrayPool{Byte}.Shared"/>.
+ /// The buffer may contain data from a prior use.
+ /// </summary>
+ /// <param name="length">The buffer's required length in bytes</param>
+ /// <returns>A <see cref="IMemoryOwner{Byte}"/> wrapping the rented memory</returns>
+ /// <exception cref="ArgumentOutOfRangeException"></exception>
+ public IMemoryOwner<byte> Rent(ulong length)
+ => RentImpl(checked((int)length));
+
+ /// <summary>
+ /// Rents a byte memory buffer from <see cref="ArrayPool{Byte}.Shared"/>.
+ /// The buffer may contain data from a prior use.
+ /// </summary>
+ /// <param name="length">The buffer's required length in bytes</param>
+ /// <returns>A <see cref="IMemoryOwner{Byte}"/> wrapping the rented memory</returns>
+ /// <exception cref="ArgumentOutOfRangeException"></exception>
+ public IMemoryOwner<byte> Rent(int length)
+ => RentImpl(length);
+
+ /// <summary>
+ /// Rents a byte memory buffer from <see cref="ArrayPool{Byte}.Shared"/>.
+ /// The buffer's contents are cleared (set to all 0s) before returning.
+ /// </summary>
+ /// <param name="length">The buffer's required length in bytes</param>
+ /// <returns>A <see cref="IMemoryOwner{Byte}"/> wrapping the rented memory</returns>
+ /// <exception cref="ArgumentOutOfRangeException"></exception>
+ public IMemoryOwner<byte> RentCleared(long length)
+ => RentCleared(checked((int)length));
+
+ /// <summary>
+ /// Rents a byte memory buffer from <see cref="ArrayPool{Byte}.Shared"/>.
+ /// The buffer's contents are cleared (set to all 0s) before returning.
+ /// </summary>
+ /// <param name="length">The buffer's required length in bytes</param>
+ /// <returns>A <see cref="IMemoryOwner{Byte}"/> wrapping the rented memory</returns>
+ /// <exception cref="ArgumentOutOfRangeException"></exception>
+ public IMemoryOwner<byte> RentCleared(ulong length)
+ => RentCleared(checked((int)length));
+
+ /// <summary>
+ /// Rents a byte memory buffer from <see cref="ArrayPool{Byte}.Shared"/>.
+ /// The buffer's contents are cleared (set to all 0s) before returning.
+ /// </summary>
+ /// <param name="length">The buffer's required length in bytes</param>
+ /// <returns>A <see cref="IMemoryOwner{Byte}"/> wrapping the rented memory</returns>
+ /// <exception cref="ArgumentOutOfRangeException"></exception>
+ public IMemoryOwner<byte> RentCleared(int length)
+ {
+ var buffer = RentImpl(length);
+
+ buffer.Memory.Span.Clear();
+
+ return buffer;
+ }
+
+ private static ByteMemoryPoolBuffer RentImpl(int length)
+ {
+ if ((uint)length > Array.MaxLength)
+ {
+ throw new ArgumentOutOfRangeException(nameof(length), length, null);
+ }
+
+ return new ByteMemoryPoolBuffer(length);
+ }
+ }
+}
diff --git a/Ryujinx.HLE/HOS/Ipc/IpcMessage.cs b/Ryujinx.HLE/HOS/Ipc/IpcMessage.cs
index 394bf888..21630c42 100644
--- a/Ryujinx.HLE/HOS/Ipc/IpcMessage.cs
+++ b/Ryujinx.HLE/HOS/Ipc/IpcMessage.cs
@@ -27,98 +27,103 @@ namespace Ryujinx.HLE.HOS.Ipc
public IpcMessage()
{
- PtrBuff = new List<IpcPtrBuffDesc>();
- SendBuff = new List<IpcBuffDesc>();
- ReceiveBuff = new List<IpcBuffDesc>();
- ExchangeBuff = new List<IpcBuffDesc>();
- RecvListBuff = new List<IpcRecvListBuffDesc>();
+ PtrBuff = new List<IpcPtrBuffDesc>(0);
+ SendBuff = new List<IpcBuffDesc>(0);
+ ReceiveBuff = new List<IpcBuffDesc>(0);
+ ExchangeBuff = new List<IpcBuffDesc>(0);
+ RecvListBuff = new List<IpcRecvListBuffDesc>(0);
- ObjectIds = new List<int>();
+ ObjectIds = new List<int>(0);
}
- public IpcMessage(ReadOnlySpan<byte> data, long cmdPtr) : this()
+ public IpcMessage(ReadOnlySpan<byte> data, long cmdPtr)
{
using (RecyclableMemoryStream ms = MemoryStreamManager.Shared.GetStream(data))
{
BinaryReader reader = new BinaryReader(ms);
- Initialize(reader, cmdPtr);
- }
- }
+ int word0 = reader.ReadInt32();
+ int word1 = reader.ReadInt32();
- private void Initialize(BinaryReader reader, long cmdPtr)
- {
- int word0 = reader.ReadInt32();
- int word1 = reader.ReadInt32();
+ Type = (IpcMessageType)(word0 & 0xffff);
- Type = (IpcMessageType)(word0 & 0xffff);
+ int ptrBuffCount = (word0 >> 16) & 0xf;
+ int sendBuffCount = (word0 >> 20) & 0xf;
+ int recvBuffCount = (word0 >> 24) & 0xf;
+ int xchgBuffCount = (word0 >> 28) & 0xf;
- int ptrBuffCount = (word0 >> 16) & 0xf;
- int sendBuffCount = (word0 >> 20) & 0xf;
- int recvBuffCount = (word0 >> 24) & 0xf;
- int xchgBuffCount = (word0 >> 28) & 0xf;
+ int rawDataSize = (word1 >> 0) & 0x3ff;
+ int recvListFlags = (word1 >> 10) & 0xf;
+ bool hndDescEnable = ((word1 >> 31) & 0x1) != 0;
- int rawDataSize = (word1 >> 0) & 0x3ff;
- int recvListFlags = (word1 >> 10) & 0xf;
- bool hndDescEnable = ((word1 >> 31) & 0x1) != 0;
+ if (hndDescEnable)
+ {
+ HandleDesc = new IpcHandleDesc(reader);
+ }
- if (hndDescEnable)
- {
- HandleDesc = new IpcHandleDesc(reader);
- }
+ PtrBuff = new List<IpcPtrBuffDesc>(ptrBuffCount);
- for (int index = 0; index < ptrBuffCount; index++)
- {
- PtrBuff.Add(new IpcPtrBuffDesc(reader));
- }
+ for (int index = 0; index < ptrBuffCount; index++)
+ {
+ PtrBuff.Add(new IpcPtrBuffDesc(reader));
+ }
- void ReadBuff(List<IpcBuffDesc> buff, int count)
- {
- for (int index = 0; index < count; index++)
+ static List<IpcBuffDesc> ReadBuff(BinaryReader reader, int count)
{
- buff.Add(new IpcBuffDesc(reader));
+ List<IpcBuffDesc> buff = new List<IpcBuffDesc>(count);
+
+ for (int index = 0; index < count; index++)
+ {
+ buff.Add(new IpcBuffDesc(reader));
+ }
+
+ return buff;
}
- }
- ReadBuff(SendBuff, sendBuffCount);
- ReadBuff(ReceiveBuff, recvBuffCount);
- ReadBuff(ExchangeBuff, xchgBuffCount);
+ SendBuff = ReadBuff(reader, sendBuffCount);
+ ReceiveBuff = ReadBuff(reader, recvBuffCount);
+ ExchangeBuff = ReadBuff(reader, xchgBuffCount);
- rawDataSize *= 4;
+ rawDataSize *= 4;
- long recvListPos = reader.BaseStream.Position + rawDataSize;
+ long recvListPos = reader.BaseStream.Position + rawDataSize;
// Only CMIF has the padding requirements.
if (Type < IpcMessageType.TipcCloseSession)
{
long pad0 = GetPadSize16(reader.BaseStream.Position + cmdPtr);
- if (rawDataSize != 0)
- {
- rawDataSize -= (int)pad0;
+ if (rawDataSize != 0)
+ {
+ rawDataSize -= (int)pad0;
+ }
+
+ reader.BaseStream.Seek(pad0, SeekOrigin.Current);
}
- reader.BaseStream.Seek(pad0, SeekOrigin.Current);
- }
+ int recvListCount = recvListFlags - 2;
- int recvListCount = recvListFlags - 2;
+ if (recvListCount == 0)
+ {
+ recvListCount = 1;
+ }
+ else if (recvListCount < 0)
+ {
+ recvListCount = 0;
+ }
- if (recvListCount == 0)
- {
- recvListCount = 1;
- }
- else if (recvListCount < 0)
- {
- recvListCount = 0;
- }
+ RawData = reader.ReadBytes(rawDataSize);
- RawData = reader.ReadBytes(rawDataSize);
+ reader.BaseStream.Seek(recvListPos, SeekOrigin.Begin);
- reader.BaseStream.Seek(recvListPos, SeekOrigin.Begin);
+ RecvListBuff = new List<IpcRecvListBuffDesc>(recvListCount);
- for (int index = 0; index < recvListCount; index++)
- {
- RecvListBuff.Add(new IpcRecvListBuffDesc(reader.ReadUInt64()));
+ for (int index = 0; index < recvListCount; index++)
+ {
+ RecvListBuff.Add(new IpcRecvListBuffDesc(reader.ReadUInt64()));
+ }
+
+ ObjectIds = new List<int>(0);
}
}
diff --git a/Ryujinx.HLE/HOS/Kernel/Common/KTimeManager.cs b/Ryujinx.HLE/HOS/Kernel/Common/KTimeManager.cs
index 1af171b9..c0cd9ce9 100644
--- a/Ryujinx.HLE/HOS/Kernel/Common/KTimeManager.cs
+++ b/Ryujinx.HLE/HOS/Kernel/Common/KTimeManager.cs
@@ -71,7 +71,13 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
{
lock (_context.CriticalSection.Lock)
{
- _waitingObjects.RemoveAll(x => x.Object == schedulerObj);
+ for (int index = _waitingObjects.Count - 1; index >= 0; index--)
+ {
+ if (_waitingObjects[index].Object == schedulerObj)
+ {
+ _waitingObjects.RemoveAt(index);
+ }
+ }
}
}
@@ -105,16 +111,19 @@ namespace Ryujinx.HLE.HOS.Kernel.Common
}
else
{
- while (Interlocked.Read(ref _enforceWakeupFromSpinWait) != 1 && PerformanceCounter.ElapsedTicks <= next.TimePoint)
+ while (Interlocked.Read(ref _enforceWakeupFromSpinWait) != 1 && PerformanceCounter.ElapsedTicks < next.TimePoint)
{
+ // Our time is close - don't let SpinWait go off and potentially Thread.Sleep().
if (spinWait.NextSpinWillYield)
{
Thread.Yield();
spinWait.Reset();
}
-
- spinWait.SpinOnce();
+ else
+ {
+ spinWait.SpinOnce();
+ }
}
spinWait.Reset();
diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs
index c6467208..3163c348 100644
--- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs
+++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs
@@ -9,6 +9,7 @@ using Ryujinx.HLE.HOS.Kernel.Process;
using Ryujinx.HLE.HOS.Kernel.Threading;
using Ryujinx.Horizon.Common;
using System;
+using System.Buffers;
using System.Threading;
namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
@@ -553,7 +554,9 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
KProcess currentProcess = KernelStatic.GetCurrentProcess();
- KSynchronizationObject[] syncObjs = handles.Length == 0 ? Array.Empty<KSynchronizationObject>() : new KSynchronizationObject[handles.Length];
+ KSynchronizationObject[] syncObjsArray = ArrayPool<KSynchronizationObject>.Shared.Rent(handles.Length);
+
+ Span<KSynchronizationObject> syncObjs = syncObjsArray.AsSpan(0, handles.Length);
for (int index = 0; index < handles.Length; index++)
{
@@ -606,6 +609,8 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
}
}
+ ArrayPool<KSynchronizationObject>.Shared.Return(syncObjsArray);
+
return result;
}
diff --git a/Ryujinx.HLE/HOS/Kernel/Threading/KSynchronization.cs b/Ryujinx.HLE/HOS/Kernel/Threading/KSynchronization.cs
index 973d5f6a..d42f9003 100644
--- a/Ryujinx.HLE/HOS/Kernel/Threading/KSynchronization.cs
+++ b/Ryujinx.HLE/HOS/Kernel/Threading/KSynchronization.cs
@@ -1,6 +1,7 @@
using Ryujinx.HLE.HOS.Kernel.Common;
using Ryujinx.Horizon.Common;
using System;
+using System.Buffers;
using System.Collections.Generic;
namespace Ryujinx.HLE.HOS.Kernel.Threading
@@ -59,7 +60,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
}
else
{
- LinkedListNode<KThread>[] syncNodes = syncObjs.Length == 0 ? Array.Empty<LinkedListNode<KThread>>() : new LinkedListNode<KThread>[syncObjs.Length];
+ LinkedListNode<KThread>[] syncNodesArray = ArrayPool<LinkedListNode<KThread>>.Shared.Rent(syncObjs.Length);
+
+ Span<LinkedListNode<KThread>> syncNodes = syncNodesArray.AsSpan(0, syncObjs.Length);
for (int index = 0; index < syncObjs.Length; index++)
{
@@ -101,6 +104,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
handleIndex = index;
}
}
+
+ ArrayPool<LinkedListNode<KThread>>.Shared.Return(syncNodesArray);
}
_context.CriticalSection.Leave();
diff --git a/Ryujinx.HLE/HOS/Services/Audio/AudioRenderer/AudioRendererServer.cs b/Ryujinx.HLE/HOS/Services/Audio/AudioRenderer/AudioRendererServer.cs
index 81321046..a137c413 100644
--- a/Ryujinx.HLE/HOS/Services/Audio/AudioRenderer/AudioRendererServer.cs
+++ b/Ryujinx.HLE/HOS/Services/Audio/AudioRenderer/AudioRendererServer.cs
@@ -1,4 +1,5 @@
using Ryujinx.Common.Logging;
+using Ryujinx.Common.Memory;
using Ryujinx.HLE.HOS.Ipc;
using Ryujinx.HLE.HOS.Kernel.Threading;
using Ryujinx.Horizon.Common;
@@ -68,25 +69,29 @@ namespace Ryujinx.HLE.HOS.Services.Audio.AudioRenderer
ReadOnlyMemory<byte> input = context.Memory.GetSpan(inputPosition, (int)inputSize).ToArray();
- Memory<byte> output = new byte[outputSize];
- Memory<byte> performanceOutput = new byte[performanceOutputSize];
+ using (IMemoryOwner<byte> outputOwner = ByteMemoryPool.Shared.RentCleared(outputSize))
+ using (IMemoryOwner<byte> performanceOutputOwner = ByteMemoryPool.Shared.RentCleared(performanceOutputSize))
+ {
+ Memory<byte> output = outputOwner.Memory;
+ Memory<byte> performanceOutput = performanceOutputOwner.Memory;
- using MemoryHandle outputHandle = output.Pin();
- using MemoryHandle performanceOutputHandle = performanceOutput.Pin();
+ using MemoryHandle outputHandle = output.Pin();
+ using MemoryHandle performanceOutputHandle = performanceOutput.Pin();
- ResultCode result = _impl.RequestUpdate(output, performanceOutput, input);
+ ResultCode result = _impl.RequestUpdate(output, performanceOutput, input);
- if (result == ResultCode.Success)
- {
- context.Memory.Write(outputPosition, output.Span);
- context.Memory.Write(performanceOutputPosition, performanceOutput.Span);
- }
- else
- {
- Logger.Error?.Print(LogClass.ServiceAudio, $"Error while processing renderer update: 0x{(int)result:X}");
- }
+ if (result == ResultCode.Success)
+ {
+ context.Memory.Write(outputPosition, output.Span);
+ context.Memory.Write(performanceOutputPosition, performanceOutput.Span);
+ }
+ else
+ {
+ Logger.Error?.Print(LogClass.ServiceAudio, $"Error while processing renderer update: 0x{(int)result:X}");
+ }
- return result;
+ return result;
+ }
}
[CommandCmif(5)]
diff --git a/Ryujinx.HLE/HOS/Services/IpcService.cs b/Ryujinx.HLE/HOS/Services/IpcService.cs
index f42fd0e2..048a68a9 100644
--- a/Ryujinx.HLE/HOS/Services/IpcService.cs
+++ b/Ryujinx.HLE/HOS/Services/IpcService.cs
@@ -76,6 +76,8 @@ namespace Ryujinx.HLE.HOS.Services
context.RequestData.BaseStream.Seek(0x10 + dataPayloadSize, SeekOrigin.Begin);
+ context.Request.ObjectIds.EnsureCapacity(inputObjCount);
+
for (int index = 0; index < inputObjCount; index++)
{
context.Request.ObjectIds.Add(context.RequestData.ReadInt32());
diff --git a/Ryujinx.HLE/HOS/Services/ServerBase.cs b/Ryujinx.HLE/HOS/Services/ServerBase.cs
index 762b4fa4..b994679a 100644
--- a/Ryujinx.HLE/HOS/Services/ServerBase.cs
+++ b/Ryujinx.HLE/HOS/Services/ServerBase.cs
@@ -217,6 +217,8 @@ namespace Ryujinx.HLE.HOS.Services
if (noReceive)
{
+ response.PtrBuff.EnsureCapacity(request.RecvListBuff.Count);
+
for (int i = 0; i < request.RecvListBuff.Count; i++)
{
ulong size = (ulong)BinaryPrimitives.ReadInt16LittleEndian(request.RawData.AsSpan(sizesOffset + i * 2, 2));
diff --git a/Ryujinx.HLE/HOS/Services/SurfaceFlinger/IHOSBinderDriver.cs b/Ryujinx.HLE/HOS/Services/SurfaceFlinger/IHOSBinderDriver.cs
index 0724c83e..42fc2761 100644
--- a/Ryujinx.HLE/HOS/Services/SurfaceFlinger/IHOSBinderDriver.cs
+++ b/Ryujinx.HLE/HOS/Services/SurfaceFlinger/IHOSBinderDriver.cs
@@ -1,7 +1,9 @@
-using Ryujinx.HLE.HOS.Ipc;
+using Ryujinx.Common.Memory;
+using Ryujinx.HLE.HOS.Ipc;
using Ryujinx.HLE.HOS.Kernel.Threading;
using Ryujinx.Horizon.Common;
using System;
+using System.Buffers;
namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
{
@@ -83,16 +85,19 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
ReadOnlySpan<byte> inputParcel = context.Memory.GetSpan(dataPos, (int)dataSize);
- Span<byte> outputParcel = new Span<byte>(new byte[replySize]);
+ using (IMemoryOwner<byte> outputParcelOwner = ByteMemoryPool.Shared.RentCleared(replySize))
+ {
+ Span<byte> outputParcel = outputParcelOwner.Memory.Span;
+
+ ResultCode result = OnTransact(binderId, code, flags, inputParcel, outputParcel);
- ResultCode result = OnTransact(binderId, code, flags, inputParcel, outputParcel);
+ if (result == ResultCode.Success)
+ {
+ context.Memory.Write(replyPos, outputParcel);
+ }
- if (result == ResultCode.Success)
- {
- context.Memory.Write(replyPos, outputParcel);
+ return result;
}
-
- return result;
}
protected abstract ResultCode AdjustRefcount(int binderId, int addVal, int type);
diff --git a/Ryujinx.Input.SDL2/SDL2Gamepad.cs b/Ryujinx.Input.SDL2/SDL2Gamepad.cs
index eec4e07e..92552673 100644
--- a/Ryujinx.Input.SDL2/SDL2Gamepad.cs
+++ b/Ryujinx.Input.SDL2/SDL2Gamepad.cs
@@ -12,17 +12,7 @@ namespace Ryujinx.Input.SDL2
{
private bool HasConfiguration => _configuration != null;
- private class ButtonMappingEntry
- {
- public readonly GamepadButtonInputId To;
- public readonly GamepadButtonInputId From;
-
- public ButtonMappingEntry(GamepadButtonInputId to, GamepadButtonInputId from)
- {
- To = to;
- From = from;
- }
- }
+ private record struct ButtonMappingEntry(GamepadButtonInputId To, GamepadButtonInputId From);
private StandardControllerInputConfig _configuration;
@@ -85,7 +75,7 @@ namespace Ryujinx.Input.SDL2
public SDL2Gamepad(IntPtr gamepadHandle, string driverId)
{
_gamepadHandle = gamepadHandle;
- _buttonsUserMapping = new List<ButtonMappingEntry>();
+ _buttonsUserMapping = new List<ButtonMappingEntry>(20);
Name = SDL_GameControllerName(_gamepadHandle);
Id = driverId;