Compare commits
2 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
c26aeefe03 | ||
|
666e05f5cb |
@@ -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());
|
||||
|
@@ -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];
|
||||
|
||||
|
@@ -7,6 +7,7 @@ using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.Windows;
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Common.Utilities;
|
||||
using Ryujinx.Ui.Common.Models.Amiibo;
|
||||
using System;
|
||||
@@ -42,13 +43,18 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
private bool _showAllAmiibo;
|
||||
private bool _useRandomUuid;
|
||||
private string _usage;
|
||||
|
||||
|
||||
private static readonly AmiiboJsonSerializerContext SerializerContext = new(JsonHelper.GetDefaultSerializerOptions());
|
||||
|
||||
public AmiiboWindowViewModel(StyleableWindow owner, string lastScannedAmiiboId, string titleId)
|
||||
{
|
||||
_owner = owner;
|
||||
_httpClient = new HttpClient { Timeout = TimeSpan.FromMilliseconds(5000) };
|
||||
|
||||
_httpClient = new HttpClient
|
||||
{
|
||||
Timeout = TimeSpan.FromSeconds(30)
|
||||
};
|
||||
|
||||
LastScannedAmiiboId = lastScannedAmiiboId;
|
||||
TitleId = titleId;
|
||||
|
||||
@@ -89,9 +95,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
_showAllAmiibo = value;
|
||||
|
||||
#pragma warning disable 4014
|
||||
ParseAmiiboData();
|
||||
#pragma warning restore 4014
|
||||
|
||||
OnPropertyChanged();
|
||||
}
|
||||
@@ -203,8 +207,10 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
amiiboJsonString = await DownloadAmiiboJson();
|
||||
}
|
||||
catch
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, $"Failed to download amiibo data: {ex}");
|
||||
|
||||
ShowInfoDialog();
|
||||
}
|
||||
}
|
||||
@@ -369,8 +375,10 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
return false;
|
||||
}
|
||||
catch
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, $"Failed to check for amiibo updates: {ex}");
|
||||
|
||||
ShowInfoDialog();
|
||||
|
||||
return false;
|
||||
@@ -393,6 +401,8 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
return amiiboJsonString;
|
||||
}
|
||||
|
||||
Logger.Error?.Print(LogClass.Application, $"Failed to download amiibo data. Response status code: {response.StatusCode}");
|
||||
|
||||
await ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance[LocaleKeys.DialogAmiiboApiTitle],
|
||||
LocaleManager.Instance[LocaleKeys.DialogAmiiboApiFailFetchMessage],
|
||||
LocaleManager.Instance[LocaleKeys.InputDialogOk],
|
||||
@@ -429,6 +439,10 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
AmiiboImage = bitmap.CreateScaledBitmap(new PixelSize(resizeWidth, resizeHeight));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, $"Failed to get amiibo preview. Response status code: {response.StatusCode}");
|
||||
}
|
||||
}
|
||||
|
||||
private void ResetAmiiboPreview()
|
||||
|
51
Ryujinx.Common/Memory/ByteMemoryPool.ByteMemoryPoolBuffer.cs
Normal file
51
Ryujinx.Common/Memory/ByteMemoryPool.ByteMemoryPoolBuffer.cs
Normal file
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
108
Ryujinx.Common/Memory/ByteMemoryPool.cs
Normal file
108
Ryujinx.Common/Memory/ByteMemoryPool.cs
Normal file
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
|
||||
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++)
|
||||
if (hndDescEnable)
|
||||
{
|
||||
buff.Add(new IpcBuffDesc(reader));
|
||||
HandleDesc = new IpcHandleDesc(reader);
|
||||
}
|
||||
}
|
||||
|
||||
ReadBuff(SendBuff, sendBuffCount);
|
||||
ReadBuff(ReceiveBuff, recvBuffCount);
|
||||
ReadBuff(ExchangeBuff, xchgBuffCount);
|
||||
PtrBuff = new List<IpcPtrBuffDesc>(ptrBuffCount);
|
||||
|
||||
rawDataSize *= 4;
|
||||
for (int index = 0; index < ptrBuffCount; index++)
|
||||
{
|
||||
PtrBuff.Add(new IpcPtrBuffDesc(reader));
|
||||
}
|
||||
|
||||
long recvListPos = reader.BaseStream.Position + rawDataSize;
|
||||
static List<IpcBuffDesc> ReadBuff(BinaryReader reader, int count)
|
||||
{
|
||||
List<IpcBuffDesc> buff = new List<IpcBuffDesc>(count);
|
||||
|
||||
for (int index = 0; index < count; index++)
|
||||
{
|
||||
buff.Add(new IpcBuffDesc(reader));
|
||||
}
|
||||
|
||||
return buff;
|
||||
}
|
||||
|
||||
SendBuff = ReadBuff(reader, sendBuffCount);
|
||||
ReceiveBuff = ReadBuff(reader, recvBuffCount);
|
||||
ExchangeBuff = ReadBuff(reader, xchgBuffCount);
|
||||
|
||||
rawDataSize *= 4;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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();
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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();
|
||||
|
@@ -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 MemoryHandle outputHandle = output.Pin();
|
||||
using MemoryHandle performanceOutputHandle = performanceOutput.Pin();
|
||||
|
||||
ResultCode result = _impl.RequestUpdate(output, performanceOutput, input);
|
||||
|
||||
if (result == ResultCode.Success)
|
||||
using (IMemoryOwner<byte> outputOwner = ByteMemoryPool.Shared.RentCleared(outputSize))
|
||||
using (IMemoryOwner<byte> performanceOutputOwner = ByteMemoryPool.Shared.RentCleared(performanceOutputSize))
|
||||
{
|
||||
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}");
|
||||
}
|
||||
Memory<byte> output = outputOwner.Memory;
|
||||
Memory<byte> performanceOutput = performanceOutputOwner.Memory;
|
||||
|
||||
return result;
|
||||
using MemoryHandle outputHandle = output.Pin();
|
||||
using MemoryHandle performanceOutputHandle = performanceOutput.Pin();
|
||||
|
||||
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}");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
[CommandCmif(5)]
|
||||
|
@@ -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());
|
||||
|
@@ -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));
|
||||
|
@@ -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]);
|
||||
|
||||
ResultCode result = OnTransact(binderId, code, flags, inputParcel, outputParcel);
|
||||
|
||||
if (result == ResultCode.Success)
|
||||
using (IMemoryOwner<byte> outputParcelOwner = ByteMemoryPool.Shared.RentCleared(replySize))
|
||||
{
|
||||
context.Memory.Write(replyPos, outputParcel);
|
||||
}
|
||||
Span<byte> outputParcel = outputParcelOwner.Memory.Span;
|
||||
|
||||
ResultCode result = OnTransact(binderId, code, flags, inputParcel, outputParcel);
|
||||
|
||||
return result;
|
||||
if (result == ResultCode.Success)
|
||||
{
|
||||
context.Memory.Write(replyPos, outputParcel);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract ResultCode AdjustRefcount(int binderId, int addVal, int type);
|
||||
|
@@ -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;
|
||||
|
@@ -1,6 +1,7 @@
|
||||
using Gtk;
|
||||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Common.Utilities;
|
||||
using Ryujinx.Ui.Common.Configuration;
|
||||
using Ryujinx.Ui.Common.Models.Amiibo;
|
||||
@@ -12,7 +13,6 @@ using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using AmiiboApi = Ryujinx.Ui.Common.Models.Amiibo.AmiiboApi;
|
||||
using AmiiboJsonSerializerContext = Ryujinx.Ui.Common.Models.Amiibo.AmiiboJsonSerializerContext;
|
||||
@@ -57,7 +57,7 @@ namespace Ryujinx.Ui.Windows
|
||||
|
||||
_httpClient = new HttpClient()
|
||||
{
|
||||
Timeout = TimeSpan.FromMilliseconds(5000)
|
||||
Timeout = TimeSpan.FromSeconds(30)
|
||||
};
|
||||
|
||||
Directory.CreateDirectory(System.IO.Path.Join(AppDataManager.BaseDirPath, "system", "amiibo"));
|
||||
@@ -93,8 +93,10 @@ namespace Ryujinx.Ui.Windows
|
||||
{
|
||||
amiiboJsonString = await DownloadAmiiboJson();
|
||||
}
|
||||
catch
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, $"Failed to download amiibo data: {ex}");
|
||||
|
||||
ShowInfoDialog();
|
||||
|
||||
Close();
|
||||
@@ -183,8 +185,10 @@ namespace Ryujinx.Ui.Windows
|
||||
|
||||
return false;
|
||||
}
|
||||
catch
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, $"Failed to check for amiibo updates: {ex}");
|
||||
|
||||
ShowInfoDialog();
|
||||
|
||||
return false;
|
||||
@@ -208,6 +212,8 @@ namespace Ryujinx.Ui.Windows
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, $"Failed to download amiibo data. Response status code: {response.StatusCode}");
|
||||
|
||||
GtkDialog.CreateInfoDialog($"Amiibo API", "An error occured while fetching information from the API.");
|
||||
|
||||
Close();
|
||||
@@ -233,6 +239,10 @@ namespace Ryujinx.Ui.Windows
|
||||
|
||||
_amiiboImage.Pixbuf = amiiboPreview.ScaleSimple(resizeWidth, resizeHeight, Gdk.InterpType.Bilinear);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, $"Failed to get amiibo preview. Response status code: {response.StatusCode}");
|
||||
}
|
||||
}
|
||||
|
||||
private void ShowInfoDialog()
|
||||
@@ -374,4 +384,4 @@ namespace Ryujinx.Ui.Windows
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user