Merge branch ryujinx:master into ui-userprofiles-and-misc

This commit is contained in:
Neo 2025-10-26 04:46:37 -05:00
commit 5d3f22ac57
93 changed files with 1002 additions and 891 deletions

View file

@ -14,10 +14,10 @@
<PackageVersion Include="Microsoft.Build.Utilities.Core" Version="17.12.6" /> <PackageVersion Include="Microsoft.Build.Utilities.Core" Version="17.12.6" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" /> <PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
<PackageVersion Include="Projektanker.Icons.Avalonia" Version="9.6.2" /> <PackageVersion Include="Projektanker.Icons.Avalonia" Version="9.6.2" />
<PackageVersion Include="Projektanker.Icons.Avalonia.FontAwesome" Version="9.6.2"/> <PackageVersion Include="Projektanker.Icons.Avalonia.FontAwesome" Version="9.6.2" />
<PackageVersion Include="Projektanker.Icons.Avalonia.MaterialDesign" Version="9.6.2"/> <PackageVersion Include="Projektanker.Icons.Avalonia.MaterialDesign" Version="9.6.2" />
<PackageVersion Include="CommandLineParser" Version="2.9.1" /> <PackageVersion Include="CommandLineParser" Version="2.9.1" />
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.4.0"/> <PackageVersion Include="CommunityToolkit.Mvvm" Version="8.4.0" />
<PackageVersion Include="Concentus" Version="2.2.2" /> <PackageVersion Include="Concentus" Version="2.2.2" />
<PackageVersion Include="DiscordRichPresence" Version="1.6.1.70" /> <PackageVersion Include="DiscordRichPresence" Version="1.6.1.70" />
<PackageVersion Include="DynamicData" Version="9.4.1" /> <PackageVersion Include="DynamicData" Version="9.4.1" />
@ -40,11 +40,11 @@
<PackageVersion Include="Ryujinx.Audio.OpenAL.Dependencies" Version="1.21.0.1" /> <PackageVersion Include="Ryujinx.Audio.OpenAL.Dependencies" Version="1.21.0.1" />
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies.AllArch" Version="6.1.2-build3" /> <PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies.AllArch" Version="6.1.2-build3" />
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" /> <PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
<PackageVersion Include="Ryujinx.LibHac" Version="0.21.0-alpha.117" /> <PackageVersion Include="Ryujinx.LibHac" Version="0.21.0-alpha.126" />
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.30.0-build32" /> <PackageVersion Include="Ryujinx.SDL2-CS" Version="2.30.0-build32" />
<PackageVersion Include="Ryujinx.UpdateClient" Version="1.0.44" /> <PackageVersion Include="Ryujinx.UpdateClient" Version="1.0.44" />
<PackageVersion Include="Ryujinx.Systems.Update.Common" Version="1.0.44" /> <PackageVersion Include="Ryujinx.Systems.Update.Common" Version="1.0.44" />
<PackageVersion Include="Gommon" Version="2.7.2.1" /> <PackageVersion Include="Gommon" Version="2.8.0.1" />
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" /> <PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
<PackageVersion Include="Sep" Version="0.11.1" /> <PackageVersion Include="Sep" Version="0.11.1" />
<PackageVersion Include="shaderc.net" Version="0.1.0" /> <PackageVersion Include="shaderc.net" Version="0.1.0" />
@ -59,4 +59,4 @@
<PackageVersion Include="System.Management" Version="9.0.2" /> <PackageVersion Include="System.Management" Version="9.0.2" />
<PackageVersion Include="UnicornEngine.Unicorn" Version="2.0.2-rc1-fb78016" /> <PackageVersion Include="UnicornEngine.Unicorn" Version="2.0.2-rc1-fb78016" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View file

@ -14668,6 +14668,156 @@
"zh_TW": "為獲得最佳效能,建議停用著色器傾印。您是否要立即停用著色器傾印嗎?" "zh_TW": "為獲得最佳效能,建議停用著色器傾印。您是否要立即停用著色器傾印嗎?"
} }
}, },
{
"ID": "NotificationLaunchCheckDramSizeTitle",
"Translations": {
"ar_SA": "",
"de_DE": "",
"el_GR": "",
"en_US": "{0} DRAM Enabled",
"es_ES": "",
"fr_FR": "",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
"ko_KR": "",
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
"ru_RU": "",
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
"zh_TW": ""
}
},
{
"ID": "NotificationLaunchCheckDramSizeMessage",
"Translations": {
"ar_SA": "",
"de_DE": "",
"el_GR": "",
"en_US": "Using above 4GiB DRAM may cause crashes in some applications.",
"es_ES": "",
"fr_FR": "",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
"ko_KR": "",
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
"ru_RU": "",
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
"zh_TW": ""
}
},
{
"ID": "NotificationLaunchCheckGdbStubTitle",
"Translations": {
"ar_SA": "",
"de_DE": "",
"el_GR": "",
"en_US": "Debug: GDB Stub Enabled (Port: {0})",
"es_ES": "",
"fr_FR": "",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
"ko_KR": "",
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
"ru_RU": "",
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
"zh_TW": ""
}
},
{
"ID": "NotificationLaunchCheckGdbStubMessage",
"Translations": {
"ar_SA": "",
"de_DE": "",
"el_GR": "",
"en_US": "This will affect performance.",
"es_ES": "",
"fr_FR": "",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
"ko_KR": "",
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
"ru_RU": "",
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
"zh_TW": ""
}
},
{
"ID": "NotificationLaunchCheckSuspendOnStartTitle",
"Translations": {
"ar_SA": "",
"de_DE": "",
"el_GR": "",
"en_US": "Debug: Suspend on Start Enabled",
"es_ES": "",
"fr_FR": "",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
"ko_KR": "",
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
"ru_RU": "",
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
"zh_TW": ""
}
},
{
"ID": "NotificationLaunchCheckSuspendOnStartMessage",
"Translations": {
"ar_SA": "",
"de_DE": "",
"el_GR": "",
"en_US": "Application has been suspended. Attach a debugger to continue.",
"es_ES": "",
"fr_FR": "",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
"ko_KR": "",
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
"ru_RU": "",
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
"zh_TW": ""
}
},
{ {
"ID": "DialogLoadAppGameAlreadyLoadedMessage", "ID": "DialogLoadAppGameAlreadyLoadedMessage",
"Translations": { "Translations": {

View file

@ -34,7 +34,7 @@
<key>CFBundleInfoDictionaryVersion</key> <key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string> <string>6.0</string>
<key>CFBundleLongVersionString</key> <key>CFBundleLongVersionString</key>
<string>%%RYUJINX_BUILD_VERSION%%-%%RYUJINX_BUILD_GIT_HASH%%"</string> <string>%%RYUJINX_BUILD_VERSION%%-%%RYUJINX_BUILD_GIT_HASH%%</string>
<key>CFBundleName</key> <key>CFBundleName</key>
<string>Ryujinx</string> <string>Ryujinx</string>
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
@ -44,13 +44,13 @@
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>????</string> <string>????</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>1.2.0</string> <string>%%RYUJINX_BUILD_VERSION%%</string>
<key>NSHighResolutionCapable</key> <key>NSHighResolutionCapable</key>
<true/> <true/>
<key>CSResourcesFileMapped</key> <key>CSResourcesFileMapped</key>
<true/> <true/>
<key>NSHumanReadableCopyright</key> <key>NSHumanReadableCopyright</key>
<string>Copyright © 2018 - 2023 Ryujinx Team and Contributors.</string> <string>Copyright © 2018 - 2024 Ryujinx Team and Contributors. Copyright © 2024 - 2025 Ryubing and Contributors.</string>
<key>LSApplicationCategoryType</key> <key>LSApplicationCategoryType</key>
<string>public.app-category.games</string> <string>public.app-category.games</string>
<key>LSMinimumSystemVersion</key> <key>LSMinimumSystemVersion</key>

View file

@ -1,5 +1,4 @@
using System; using System;
using System.Diagnostics.CodeAnalysis;
namespace ARMeilleure.CodeGen.X86 namespace ARMeilleure.CodeGen.X86
{ {

View file

@ -2,7 +2,6 @@ using ARMeilleure.CodeGen.RegisterAllocators;
using ARMeilleure.IntermediateRepresentation; using ARMeilleure.IntermediateRepresentation;
using Microsoft.IO; using Microsoft.IO;
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using System.IO;
using System.Numerics; using System.Numerics;
namespace ARMeilleure.CodeGen.X86 namespace ARMeilleure.CodeGen.X86

View file

@ -1,5 +1,3 @@
using System.Diagnostics.CodeAnalysis;
namespace ARMeilleure.CodeGen.X86 namespace ARMeilleure.CodeGen.X86
{ {
enum X86Register enum X86Register

View file

@ -2,7 +2,6 @@ using ARMeilleure.Decoders;
using ARMeilleure.IntermediateRepresentation; using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation; using ARMeilleure.Translation;
using System; using System;
using System.Diagnostics.CodeAnalysis;
using static ARMeilleure.Instructions.InstEmitHelper; using static ARMeilleure.Instructions.InstEmitHelper;
namespace ARMeilleure.Instructions namespace ARMeilleure.Instructions

View file

@ -1,5 +1,4 @@
using System; using System;
using System.Diagnostics.CodeAnalysis;
namespace ARMeilleure.IntermediateRepresentation namespace ARMeilleure.IntermediateRepresentation
{ {

View file

@ -11,27 +11,32 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.AdpcmDataSourceVersion1; public CommandType CommandType => CommandType.AdpcmDataSourceVersion1;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public ushort OutputBufferIndex { get; } public ushort OutputBufferIndex { get; private set; }
public uint SampleRate { get; } public uint SampleRate { get; private set; }
public float Pitch { get; } public float Pitch { get; private set; }
public WaveBuffer[] WaveBuffers { get; } public WaveBuffer[] WaveBuffers { get; }
public Memory<VoiceState> State { get; } public Memory<VoiceState> State { get; private set; }
public ulong AdpcmParameter { get; } public ulong AdpcmParameter { get; private set; }
public ulong AdpcmParameterSize { get; } public ulong AdpcmParameterSize { get; private set; }
public DecodingBehaviour DecodingBehaviour { get; } public DecodingBehaviour DecodingBehaviour { get; private set; }
public AdpcmDataSourceCommandVersion1(ref VoiceInfo serverInfo, Memory<VoiceState> state, ushort outputBufferIndex, int nodeId) public AdpcmDataSourceCommandVersion1()
{
WaveBuffers = new WaveBuffer[Constants.VoiceWaveBufferCount];
}
public AdpcmDataSourceCommandVersion1 Initialize(ref VoiceInfo serverInfo, Memory<VoiceState> state, ushort outputBufferIndex, int nodeId)
{ {
Enabled = true; Enabled = true;
NodeId = nodeId; NodeId = nodeId;
@ -42,8 +47,6 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
Span<Server.Voice.WaveBuffer> waveBufferSpan = serverInfo.WaveBuffers.AsSpan(); Span<Server.Voice.WaveBuffer> waveBufferSpan = serverInfo.WaveBuffers.AsSpan();
WaveBuffers = new WaveBuffer[Constants.VoiceWaveBufferCount];
for (int i = 0; i < WaveBuffers.Length; i++) for (int i = 0; i < WaveBuffers.Length; i++)
{ {
ref Server.Voice.WaveBuffer voiceWaveBuffer = ref waveBufferSpan[i]; ref Server.Voice.WaveBuffer voiceWaveBuffer = ref waveBufferSpan[i];
@ -55,6 +58,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
AdpcmParameterSize = serverInfo.DataSourceStateAddressInfo.Size; AdpcmParameterSize = serverInfo.DataSourceStateAddressInfo.Size;
State = state; State = state;
DecodingBehaviour = serverInfo.DecodingBehaviour; DecodingBehaviour = serverInfo.DecodingBehaviour;
return this;
} }
public void Process(CommandList context) public void Process(CommandList context)

View file

@ -12,26 +12,31 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.AuxiliaryBuffer; public CommandType CommandType => CommandType.AuxiliaryBuffer;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public uint InputBufferIndex { get; } public uint InputBufferIndex { get; private set; }
public uint OutputBufferIndex { get; } public uint OutputBufferIndex { get; private set; }
public AuxiliaryBufferAddresses BufferInfo { get; } public AuxiliaryBufferAddresses BufferInfo { get; private set; }
public CpuAddress InputBuffer { get; } public CpuAddress InputBuffer { get; private set; }
public CpuAddress OutputBuffer { get; } public CpuAddress OutputBuffer { get; private set; }
public uint CountMax { get; } public uint CountMax { get; private set; }
public uint UpdateCount { get; } public uint UpdateCount { get; private set; }
public uint WriteOffset { get; } public uint WriteOffset { get; private set; }
public bool IsEffectEnabled { get; } public bool IsEffectEnabled { get; private set; }
public AuxiliaryBufferCommand( public AuxiliaryBufferCommand()
{
}
public AuxiliaryBufferCommand Initialize(
uint bufferOffset, uint bufferOffset,
byte inputBufferOffset, byte inputBufferOffset,
byte outputBufferOffset, byte outputBufferOffset,
@ -55,6 +60,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
UpdateCount = updateCount; UpdateCount = updateCount;
WriteOffset = writeOffset; WriteOffset = writeOffset;
IsEffectEnabled = isEnabled; IsEffectEnabled = isEnabled;
return this;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]

View file

@ -9,32 +9,37 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.BiquadFilterAndMix; public CommandType CommandType => CommandType.BiquadFilterAndMix;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public ushort InputBufferIndex { get; } public ushort InputBufferIndex { get; private set; }
public ushort OutputBufferIndex { get; } public ushort OutputBufferIndex { get; private set; }
private BiquadFilterParameter2 _parameter; private BiquadFilterParameter2 _parameter;
public Memory<BiquadFilterState> BiquadFilterState { get; } public Memory<BiquadFilterState> BiquadFilterState { get; private set; }
public Memory<BiquadFilterState> PreviousBiquadFilterState { get; } public Memory<BiquadFilterState> PreviousBiquadFilterState { get; private set; }
public Memory<VoiceState> State { get; } public Memory<VoiceState> State { get; private set; }
public int LastSampleIndex { get; } public int LastSampleIndex { get; private set; }
public float Volume0 { get; } public float Volume0 { get; private set; }
public float Volume1 { get; } public float Volume1 { get; private set; }
public bool NeedInitialization { get; } public bool NeedInitialization { get; private set; }
public bool HasVolumeRamp { get; } public bool HasVolumeRamp { get; private set; }
public bool IsFirstMixBuffer { get; } public bool IsFirstMixBuffer { get; private set; }
public BiquadFilterAndMixCommand( public BiquadFilterAndMixCommand()
{
}
public BiquadFilterAndMixCommand Initialize(
float volume0, float volume0,
float volume1, float volume1,
uint inputBufferIndex, uint inputBufferIndex,
@ -68,6 +73,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
NeedInitialization = needInitialization; NeedInitialization = needInitialization;
HasVolumeRamp = hasVolumeRamp; HasVolumeRamp = hasVolumeRamp;
IsFirstMixBuffer = isFirstMixBuffer; IsFirstMixBuffer = isFirstMixBuffer;
return this;
} }
public void Process(CommandList context) public void Process(CommandList context)

View file

@ -8,20 +8,25 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.BiquadFilter; public CommandType CommandType => CommandType.BiquadFilter;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public Memory<BiquadFilterState> BiquadFilterState { get; } public Memory<BiquadFilterState> BiquadFilterState { get; private set; }
public int InputBufferIndex { get; } public int InputBufferIndex { get; private set; }
public int OutputBufferIndex { get; } public int OutputBufferIndex { get; private set; }
public bool NeedInitialization { get; } public bool NeedInitialization { get; private set; }
private BiquadFilterParameter2 _parameter; private BiquadFilterParameter2 _parameter;
public BiquadFilterCommand( public BiquadFilterCommand()
{
}
public BiquadFilterCommand Initialize(
int baseIndex, int baseIndex,
ref BiquadFilterParameter2 filter, ref BiquadFilterParameter2 filter,
Memory<BiquadFilterState> biquadFilterStateMemory, Memory<BiquadFilterState> biquadFilterStateMemory,
@ -38,6 +43,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
Enabled = true; Enabled = true;
NodeId = nodeId; NodeId = nodeId;
return this;
} }
public void Process(CommandList context) public void Process(CommandList context)

View file

@ -12,25 +12,30 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.CaptureBuffer; public CommandType CommandType => CommandType.CaptureBuffer;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public uint InputBufferIndex { get; } public uint InputBufferIndex { get; private set; }
public ulong CpuBufferInfoAddress { get; } public ulong CpuBufferInfoAddress { get; private set; }
public ulong DspBufferInfoAddress { get; } public ulong DspBufferInfoAddress { get; private set; }
public CpuAddress OutputBuffer { get; } public CpuAddress OutputBuffer { get; private set; }
public uint CountMax { get; } public uint CountMax { get; private set; }
public uint UpdateCount { get; } public uint UpdateCount { get; private set; }
public uint WriteOffset { get; } public uint WriteOffset { get; private set; }
public bool IsEffectEnabled { get; } public bool IsEffectEnabled { get; private set; }
public CaptureBufferCommand(uint bufferOffset, byte inputBufferOffset, ulong sendBufferInfo, bool isEnabled, public CaptureBufferCommand()
{
}
public CaptureBufferCommand Initialize(uint bufferOffset, byte inputBufferOffset, ulong sendBufferInfo, bool isEnabled,
uint countMax, CpuAddress outputBuffer, uint updateCount, uint writeOffset, int nodeId) uint countMax, CpuAddress outputBuffer, uint updateCount, uint writeOffset, int nodeId)
{ {
Enabled = true; Enabled = true;
@ -43,6 +48,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
UpdateCount = updateCount; UpdateCount = updateCount;
WriteOffset = writeOffset; WriteOffset = writeOffset;
IsEffectEnabled = isEnabled; IsEffectEnabled = isEnabled;
return this;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]

View file

@ -9,25 +9,29 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.CircularBufferSink; public CommandType CommandType => CommandType.CircularBufferSink;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public ushort[] Input { get; } public ushort[] Input { get; }
public uint InputCount { get; } public uint InputCount { get; private set; }
public ulong CircularBuffer { get; } public ulong CircularBuffer { get; private set; }
public ulong CircularBufferSize { get; } public ulong CircularBufferSize { get; private set; }
public ulong CurrentOffset { get; } public ulong CurrentOffset { get; private set; }
public CircularBufferSinkCommand(uint bufferOffset, ref CircularBufferParameter parameter, ref AddressInfo circularBufferAddressInfo, uint currentOffset, int nodeId) public CircularBufferSinkCommand()
{
Input = new ushort[Constants.ChannelCountMax];
}
public CircularBufferSinkCommand Initialize(uint bufferOffset, ref CircularBufferParameter parameter, ref AddressInfo circularBufferAddressInfo, uint currentOffset, int nodeId)
{ {
Enabled = true; Enabled = true;
NodeId = nodeId; NodeId = nodeId;
Input = new ushort[Constants.ChannelCountMax];
InputCount = parameter.InputCount; InputCount = parameter.InputCount;
Span<byte> inputSpan = parameter.Input.AsSpan(); Span<byte> inputSpan = parameter.Input.AsSpan();
@ -42,6 +46,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
CurrentOffset = currentOffset; CurrentOffset = currentOffset;
Debug.Assert(CircularBuffer != 0); Debug.Assert(CircularBuffer != 0);
return this;
} }
public void Process(CommandList context) public void Process(CommandList context)

View file

@ -4,16 +4,23 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.ClearMixBuffer; public CommandType CommandType => CommandType.ClearMixBuffer;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public ClearMixBufferCommand(int nodeId) public ClearMixBufferCommand()
{
}
public ClearMixBufferCommand Initialize(int nodeId)
{ {
Enabled = true; Enabled = true;
NodeId = nodeId; NodeId = nodeId;
return this;
} }
public void Process(CommandList context) public void Process(CommandList context)

View file

@ -20,6 +20,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
public Memory<float> Buffers { get; } public Memory<float> Buffers { get; }
public uint BufferCount { get; } public uint BufferCount { get; }
private readonly static ObjectPool<List<ICommand>> CommandsListPool = new(() => new List<ICommand>(256));
public List<ICommand> Commands { get; } public List<ICommand> Commands { get; }
public IVirtualMemoryManager MemoryManager { get; } public IVirtualMemoryManager MemoryManager { get; }
@ -46,7 +47,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
SampleRate = sampleRate; SampleRate = sampleRate;
BufferCount = mixBufferCount + voiceChannelCountMax; BufferCount = mixBufferCount + voiceChannelCountMax;
Buffers = mixBuffer; Buffers = mixBuffer;
Commands = []; Commands = CommandsListPool.Allocate();
MemoryManager = memoryManager; MemoryManager = memoryManager;
_buffersEntryCount = Buffers.Length; _buffersEntryCount = Buffers.Length;
@ -142,6 +143,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
} }
} }
} }
CommandBuffer.ReleaseCommand(command);
} }
EndTime = (ulong)PerformanceCounter.ElapsedNanoseconds; EndTime = (ulong)PerformanceCounter.ElapsedNanoseconds;
@ -149,6 +152,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
public void Dispose() public void Dispose()
{ {
Commands.Clear();
CommandsListPool.Release(Commands);
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
_buffersMemoryHandle.Dispose(); _buffersMemoryHandle.Dispose();
} }

View file

@ -15,22 +15,28 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.Compressor; public CommandType CommandType => CommandType.Compressor;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public CompressorParameter Parameter => _parameter; public CompressorParameter Parameter => _parameter;
public Memory<CompressorState> State { get; } public Memory<CompressorState> State { get; private set; }
public Memory<EffectResultState> ResultState { get; } public Memory<EffectResultState> ResultState { get; private set; }
public ushort[] OutputBufferIndices { get; } public ushort[] OutputBufferIndices { get; }
public ushort[] InputBufferIndices { get; } public ushort[] InputBufferIndices { get; }
public bool IsEffectEnabled { get; } public bool IsEffectEnabled { get; private set; }
private CompressorParameter _parameter; private CompressorParameter _parameter;
public CompressorCommand(uint bufferOffset, CompressorParameter parameter, Memory<CompressorState> state, Memory<EffectResultState> resultState, bool isEnabled, int nodeId) public CompressorCommand()
{
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
}
public CompressorCommand Initialize(uint bufferOffset, CompressorParameter parameter, Memory<CompressorState> state, Memory<EffectResultState> resultState, bool isEnabled, int nodeId)
{ {
Enabled = true; Enabled = true;
NodeId = nodeId; NodeId = nodeId;
@ -39,9 +45,6 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
ResultState = resultState; ResultState = resultState;
IsEffectEnabled = isEnabled; IsEffectEnabled = isEnabled;
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
Span<byte> inputSpan = _parameter.Input.AsSpan(); Span<byte> inputSpan = _parameter.Input.AsSpan();
Span<byte> outputSpan = _parameter.Output.AsSpan(); Span<byte> outputSpan = _parameter.Output.AsSpan();
@ -51,6 +54,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
InputBufferIndices[i] = (ushort)(bufferOffset + inputSpan[i]); InputBufferIndices[i] = (ushort)(bufferOffset + inputSpan[i]);
OutputBufferIndices[i] = (ushort)(bufferOffset + outputSpan[i]); OutputBufferIndices[i] = (ushort)(bufferOffset + outputSpan[i]);
} }
return this;
} }
public void Process(CommandList context) public void Process(CommandList context)

View file

@ -4,22 +4,29 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.CopyMixBuffer; public CommandType CommandType => CommandType.CopyMixBuffer;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public ushort InputBufferIndex { get; } public ushort InputBufferIndex { get; private set; }
public ushort OutputBufferIndex { get; } public ushort OutputBufferIndex { get; private set; }
public CopyMixBufferCommand(uint inputBufferIndex, uint outputBufferIndex, int nodeId) public CopyMixBufferCommand()
{
}
public CopyMixBufferCommand Initialize(uint inputBufferIndex, uint outputBufferIndex, int nodeId)
{ {
Enabled = true; Enabled = true;
NodeId = nodeId; NodeId = nodeId;
InputBufferIndex = (ushort)inputBufferIndex; InputBufferIndex = (ushort)inputBufferIndex;
OutputBufferIndex = (ushort)outputBufferIndex; OutputBufferIndex = (ushort)outputBufferIndex;
return this;
} }
public void Process(CommandList context) public void Process(CommandList context)

View file

@ -11,35 +11,40 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType { get; } public CommandType CommandType { get; private set; }
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public ushort OutputBufferIndex { get; } public ushort OutputBufferIndex { get; private set; }
public uint SampleRate { get; } public uint SampleRate { get; private set; }
public float Pitch { get; } public float Pitch { get; private set; }
public WaveBuffer[] WaveBuffers { get; } public WaveBuffer[] WaveBuffers { get; }
public Memory<VoiceState> State { get; } public Memory<VoiceState> State { get; private set; }
public ulong ExtraParameter { get; } public ulong ExtraParameter { get; private set; }
public ulong ExtraParameterSize { get; } public ulong ExtraParameterSize { get; private set; }
public uint ChannelIndex { get; } public uint ChannelIndex { get; private set; }
public uint ChannelCount { get; } public uint ChannelCount { get; private set; }
public DecodingBehaviour DecodingBehaviour { get; } public DecodingBehaviour DecodingBehaviour { get; private set; }
public SampleFormat SampleFormat { get; } public SampleFormat SampleFormat { get; private set; }
public SampleRateConversionQuality SrcQuality { get; } public SampleRateConversionQuality SrcQuality { get; private set; }
public DataSourceVersion2Command(ref VoiceInfo serverInfo, Memory<VoiceState> state, ushort outputBufferIndex, ushort channelIndex, int nodeId) public DataSourceVersion2Command()
{
WaveBuffers = new WaveBuffer[Constants.VoiceWaveBufferCount];
}
public DataSourceVersion2Command Initialize(ref VoiceInfo serverInfo, Memory<VoiceState> state, ushort outputBufferIndex, ushort channelIndex, int nodeId)
{ {
Enabled = true; Enabled = true;
NodeId = nodeId; NodeId = nodeId;
@ -55,8 +60,6 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
Span<Server.Voice.WaveBuffer> waveBufferSpan = serverInfo.WaveBuffers.AsSpan(); Span<Server.Voice.WaveBuffer> waveBufferSpan = serverInfo.WaveBuffers.AsSpan();
WaveBuffers = new WaveBuffer[Constants.VoiceWaveBufferCount];
for (int i = 0; i < WaveBuffers.Length; i++) for (int i = 0; i < WaveBuffers.Length; i++)
{ {
ref Server.Voice.WaveBuffer voiceWaveBuffer = ref waveBufferSpan[i]; ref Server.Voice.WaveBuffer voiceWaveBuffer = ref waveBufferSpan[i];
@ -72,6 +75,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
State = state; State = state;
DecodingBehaviour = serverInfo.DecodingBehaviour; DecodingBehaviour = serverInfo.DecodingBehaviour;
return this;
} }
private static CommandType GetCommandTypeBySampleFormat(SampleFormat sampleFormat) private static CommandType GetCommandTypeBySampleFormat(SampleFormat sampleFormat)

View file

@ -13,24 +13,30 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.Delay; public CommandType CommandType => CommandType.Delay;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public DelayParameter Parameter => _parameter; public DelayParameter Parameter => _parameter;
public Memory<DelayState> State { get; } public Memory<DelayState> State { get; private set; }
public ulong WorkBuffer { get; } public ulong WorkBuffer { get; private set; }
public ushort[] OutputBufferIndices { get; } public ushort[] OutputBufferIndices { get; }
public ushort[] InputBufferIndices { get; } public ushort[] InputBufferIndices { get; }
public bool IsEffectEnabled { get; } public bool IsEffectEnabled { get; private set; }
private DelayParameter _parameter; private DelayParameter _parameter;
private const int FixedPointPrecision = 14; private const int FixedPointPrecision = 14;
public DelayCommand(uint bufferOffset, DelayParameter parameter, Memory<DelayState> state, bool isEnabled, ulong workBuffer, int nodeId, bool newEffectChannelMappingSupported) public DelayCommand()
{
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
}
public DelayCommand Initialize(uint bufferOffset, DelayParameter parameter, Memory<DelayState> state, bool isEnabled, ulong workBuffer, int nodeId, bool newEffectChannelMappingSupported)
{ {
Enabled = true; Enabled = true;
NodeId = nodeId; NodeId = nodeId;
@ -39,9 +45,6 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
WorkBuffer = workBuffer; WorkBuffer = workBuffer;
IsEffectEnabled = isEnabled; IsEffectEnabled = isEnabled;
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
Span<byte> inputSpan = Parameter.Input.AsSpan(); Span<byte> inputSpan = Parameter.Input.AsSpan();
Span<byte> outputSpan = Parameter.Output.AsSpan(); Span<byte> outputSpan = Parameter.Output.AsSpan();
@ -54,6 +57,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
DataSourceHelper.RemapLegacyChannelEffectMappingToChannelResourceMapping(newEffectChannelMappingSupported, InputBufferIndices, Parameter.ChannelCount); DataSourceHelper.RemapLegacyChannelEffectMappingToChannelResourceMapping(newEffectChannelMappingSupported, InputBufferIndices, Parameter.ChannelCount);
DataSourceHelper.RemapLegacyChannelEffectMappingToChannelResourceMapping(newEffectChannelMappingSupported, OutputBufferIndices, Parameter.ChannelCount); DataSourceHelper.RemapLegacyChannelEffectMappingToChannelResourceMapping(newEffectChannelMappingSupported, OutputBufferIndices, Parameter.ChannelCount);
return this;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]

View file

@ -7,21 +7,26 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.DepopForMixBuffers; public CommandType CommandType => CommandType.DepopForMixBuffers;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public uint MixBufferOffset { get; } public uint MixBufferOffset { get; private set; }
public uint MixBufferCount { get; } public uint MixBufferCount { get; private set; }
public float Decay { get; } public float Decay { get; private set; }
public Memory<float> DepopBuffer { get; } public Memory<float> DepopBuffer { get; private set; }
public DepopForMixBuffersCommand(Memory<float> depopBuffer, uint bufferOffset, uint mixBufferCount, int nodeId, uint sampleRate) public DepopForMixBuffersCommand()
{
}
public DepopForMixBuffersCommand Initialize(Memory<float> depopBuffer, uint bufferOffset, uint mixBufferCount, int nodeId, uint sampleRate)
{ {
Enabled = true; Enabled = true;
NodeId = nodeId; NodeId = nodeId;
@ -37,6 +42,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
Decay = 0.943695f; Decay = 0.943695f;
} }
return this;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]

View file

@ -7,27 +7,30 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.DepopPrepare; public CommandType CommandType => CommandType.DepopPrepare;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public uint MixBufferCount { get; } public uint MixBufferCount { get; private set; }
public ushort[] OutputBufferIndices { get; } public ushort[] OutputBufferIndices { get; }
public Memory<VoiceState> State { get; } public Memory<VoiceState> State { get; private set; }
public Memory<float> DepopBuffer { get; } public Memory<float> DepopBuffer { get; private set; }
public DepopPrepareCommand(Memory<VoiceState> state, Memory<float> depopBuffer, uint mixBufferCount, uint bufferOffset, int nodeId, bool enabled) public DepopPrepareCommand()
{
OutputBufferIndices = new ushort[Constants.MixBufferCountMax];
}
public DepopPrepareCommand Initialize(Memory<VoiceState> state, Memory<float> depopBuffer, uint mixBufferCount, uint bufferOffset, int nodeId, bool enabled)
{ {
Enabled = enabled; Enabled = enabled;
NodeId = nodeId; NodeId = nodeId;
MixBufferCount = mixBufferCount; MixBufferCount = mixBufferCount;
OutputBufferIndices = new ushort[Constants.MixBufferCountMax];
for (int i = 0; i < Constants.MixBufferCountMax; i++) for (int i = 0; i < Constants.MixBufferCountMax; i++)
{ {
OutputBufferIndices[i] = (ushort)(bufferOffset + i); OutputBufferIndices[i] = (ushort)(bufferOffset + i);
@ -35,6 +38,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
State = state; State = state;
DepopBuffer = depopBuffer; DepopBuffer = depopBuffer;
return this;
} }
public void Process(CommandList context) public void Process(CommandList context)

View file

@ -10,22 +10,27 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.DeviceSink; public CommandType CommandType => CommandType.DeviceSink;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public string DeviceName { get; } public string DeviceName { get; private set; }
public int SessionId { get; } public int SessionId { get; private set; }
public uint InputCount { get; } public uint InputCount { get; private set; }
public ushort[] InputBufferIndices { get; } public ushort[] InputBufferIndices { get; private set; }
public Memory<float> Buffers { get; } public Memory<float> Buffers { get; private set; }
public DeviceSinkCommand(uint bufferOffset, DeviceSink sink, int sessionId, Memory<float> buffers, int nodeId) public DeviceSinkCommand()
{
}
public DeviceSinkCommand Initialize(uint bufferOffset, DeviceSink sink, int sessionId, Memory<float> buffers, int nodeId)
{ {
Enabled = true; Enabled = true;
NodeId = nodeId; NodeId = nodeId;
@ -50,6 +55,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
Buffers = buffers; Buffers = buffers;
} }
return this;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]

View file

@ -7,7 +7,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.DownMixSurroundToStereo; public CommandType CommandType => CommandType.DownMixSurroundToStereo;
@ -16,16 +16,19 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
public ushort[] InputBufferIndices { get; } public ushort[] InputBufferIndices { get; }
public ushort[] OutputBufferIndices { get; } public ushort[] OutputBufferIndices { get; }
public float[] Coefficients { get; } public float[] Coefficients { get; private set; }
public DownMixSurroundToStereoCommand(uint bufferOffset, Span<byte> inputBufferOffset, Span<byte> outputBufferOffset, float[] downMixParameter, int nodeId) public DownMixSurroundToStereoCommand()
{
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
}
public DownMixSurroundToStereoCommand Initialize(uint bufferOffset, Span<byte> inputBufferOffset, Span<byte> outputBufferOffset, float[] downMixParameter, int nodeId)
{ {
Enabled = true; Enabled = true;
NodeId = nodeId; NodeId = nodeId;
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
for (int i = 0; i < Constants.VoiceChannelCountMax; i++) for (int i = 0; i < Constants.VoiceChannelCountMax; i++)
{ {
InputBufferIndices[i] = (ushort)(bufferOffset + inputBufferOffset[i]); InputBufferIndices[i] = (ushort)(bufferOffset + inputBufferOffset[i]);
@ -33,6 +36,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
} }
Coefficients = downMixParameter; Coefficients = downMixParameter;
return this;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]

View file

@ -1,5 +1,4 @@
using Ryujinx.Audio.Renderer.Server.Splitter; using Ryujinx.Audio.Renderer.Server.Splitter;
using System;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
namespace Ryujinx.Audio.Renderer.Dsp.Command namespace Ryujinx.Audio.Renderer.Dsp.Command
@ -8,38 +7,43 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.FillBuffer; public CommandType CommandType => CommandType.FillBuffer;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public SplitterDestinationVersion1 Destination1 { get; } public SplitterDestinationVersion1 Destination1 { get; private set; }
public SplitterDestinationVersion2 Destination2 { get; } public SplitterDestinationVersion2 Destination2 { get; private set; }
public bool IsV2 { get; } public bool IsV2 { get; private set; }
public int Length { get; } public int Length { get; private set; }
public float Value { get; } public float Value { get; private set; }
public FillBufferCommand(SplitterDestinationVersion1 destination, int length, float value, int nodeId) public FillBufferCommand()
{ {
Enabled = true;
NodeId = nodeId;
Destination1 = destination;
IsV2 = false;
Length = length;
Value = value;
} }
public FillBufferCommand(SplitterDestinationVersion2 destination, int length, float value, int nodeId) public FillBufferCommand Initialize(SplitterDestination destination, int length, float value, int nodeId)
{ {
Enabled = true; Enabled = true;
NodeId = nodeId; NodeId = nodeId;
if (Unsafe.IsNullRef(ref destination.GetV2RefOrNull()))
{
Destination1 = destination.GetV1RefOrNull();
IsV2 = false;
}
else
{
Destination2 = destination.GetV2RefOrNull();
IsV2 = true;
}
Destination2 = destination;
IsV2 = true;
Length = length; Length = length;
Value = value; Value = value;
return this;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]

View file

@ -10,22 +10,28 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.LimiterVersion1; public CommandType CommandType => CommandType.LimiterVersion1;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public LimiterParameter Parameter => _parameter; public LimiterParameter Parameter => _parameter;
public Memory<LimiterState> State { get; } public Memory<LimiterState> State { get; private set; }
public ulong WorkBuffer { get; } public ulong WorkBuffer { get; private set; }
public ushort[] OutputBufferIndices { get; } public ushort[] OutputBufferIndices { get; }
public ushort[] InputBufferIndices { get; } public ushort[] InputBufferIndices { get; }
public bool IsEffectEnabled { get; } public bool IsEffectEnabled { get; private set; }
private LimiterParameter _parameter; private LimiterParameter _parameter;
public LimiterCommandVersion1(uint bufferOffset, LimiterParameter parameter, Memory<LimiterState> state, bool isEnabled, ulong workBuffer, int nodeId) public LimiterCommandVersion1()
{
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
}
public LimiterCommandVersion1 Initialize(uint bufferOffset, LimiterParameter parameter, Memory<LimiterState> state, bool isEnabled, ulong workBuffer, int nodeId)
{ {
Enabled = true; Enabled = true;
NodeId = nodeId; NodeId = nodeId;
@ -35,9 +41,6 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
IsEffectEnabled = isEnabled; IsEffectEnabled = isEnabled;
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
Span<byte> inputSpan = _parameter.Input.AsSpan(); Span<byte> inputSpan = _parameter.Input.AsSpan();
Span<byte> outputSpan = _parameter.Output.AsSpan(); Span<byte> outputSpan = _parameter.Output.AsSpan();
@ -46,6 +49,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
InputBufferIndices[i] = (ushort)(bufferOffset + inputSpan[i]); InputBufferIndices[i] = (ushort)(bufferOffset + inputSpan[i]);
OutputBufferIndices[i] = (ushort)(bufferOffset + outputSpan[i]); OutputBufferIndices[i] = (ushort)(bufferOffset + outputSpan[i]);
} }
return this;
} }
public void Process(CommandList context) public void Process(CommandList context)

View file

@ -12,23 +12,29 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.LimiterVersion2; public CommandType CommandType => CommandType.LimiterVersion2;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public LimiterParameter Parameter => _parameter; public LimiterParameter Parameter => _parameter;
public Memory<LimiterState> State { get; } public Memory<LimiterState> State { get; private set; }
public Memory<EffectResultState> ResultState { get; } public Memory<EffectResultState> ResultState { get; private set; }
public ulong WorkBuffer { get; } public ulong WorkBuffer { get; private set; }
public ushort[] OutputBufferIndices { get; } public ushort[] OutputBufferIndices { get; }
public ushort[] InputBufferIndices { get; } public ushort[] InputBufferIndices { get; }
public bool IsEffectEnabled { get; } public bool IsEffectEnabled { get; private set; }
private LimiterParameter _parameter; private LimiterParameter _parameter;
public LimiterCommandVersion2( public LimiterCommandVersion2()
{
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
}
public LimiterCommandVersion2 Initialize(
uint bufferOffset, uint bufferOffset,
LimiterParameter parameter, LimiterParameter parameter,
Memory<LimiterState> state, Memory<LimiterState> state,
@ -45,9 +51,6 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
WorkBuffer = workBuffer; WorkBuffer = workBuffer;
IsEffectEnabled = isEnabled; IsEffectEnabled = isEnabled;
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
Span<byte> inputSpan = _parameter.Input.AsSpan(); Span<byte> inputSpan = _parameter.Input.AsSpan();
Span<byte> outputSpan = _parameter.Output.AsSpan(); Span<byte> outputSpan = _parameter.Output.AsSpan();
@ -57,6 +60,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
InputBufferIndices[i] = (ushort)(bufferOffset + inputSpan[i]); InputBufferIndices[i] = (ushort)(bufferOffset + inputSpan[i]);
OutputBufferIndices[i] = (ushort)(bufferOffset + outputSpan[i]); OutputBufferIndices[i] = (ushort)(bufferOffset + outputSpan[i]);
} }
return this;
} }
public void Process(CommandList context) public void Process(CommandList context)

View file

@ -11,18 +11,23 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.Mix; public CommandType CommandType => CommandType.Mix;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public ushort InputBufferIndex { get; } public ushort InputBufferIndex { get; private set; }
public ushort OutputBufferIndex { get; } public ushort OutputBufferIndex { get; private set; }
public float Volume { get; } public float Volume { get; private set; }
public MixCommand(uint inputBufferIndex, uint outputBufferIndex, int nodeId, float volume) public MixCommand()
{
}
public MixCommand Initialize(uint inputBufferIndex, uint outputBufferIndex, int nodeId, float volume)
{ {
Enabled = true; Enabled = true;
NodeId = nodeId; NodeId = nodeId;
@ -31,6 +36,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
OutputBufferIndex = (ushort)outputBufferIndex; OutputBufferIndex = (ushort)outputBufferIndex;
Volume = volume; Volume = volume;
return this;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]

View file

@ -8,23 +8,28 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.MixRamp; public CommandType CommandType => CommandType.MixRamp;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public ushort InputBufferIndex { get; } public ushort InputBufferIndex { get; private set; }
public ushort OutputBufferIndex { get; } public ushort OutputBufferIndex { get; private set; }
public float Volume0 { get; } public float Volume0 { get; private set; }
public float Volume1 { get; } public float Volume1 { get; private set; }
public Memory<VoiceState> State { get; } public Memory<VoiceState> State { get; private set; }
public int LastSampleIndex { get; } public int LastSampleIndex { get; private set; }
public MixRampCommand(float volume0, float volume1, uint inputBufferIndex, uint outputBufferIndex, int lastSampleIndex, Memory<VoiceState> state, int nodeId) public MixRampCommand()
{
}
public MixRampCommand Initialize(float volume0, float volume1, uint inputBufferIndex, uint outputBufferIndex, int lastSampleIndex, Memory<VoiceState> state, int nodeId)
{ {
Enabled = true; Enabled = true;
NodeId = nodeId; NodeId = nodeId;
@ -37,6 +42,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
State = state; State = state;
LastSampleIndex = lastSampleIndex; LastSampleIndex = lastSampleIndex;
return this;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]

View file

@ -8,23 +8,28 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.MixRampGrouped; public CommandType CommandType => CommandType.MixRampGrouped;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public uint MixBufferCount { get; } public uint MixBufferCount { get; private set; }
public ushort[] InputBufferIndices { get; } public ushort[] InputBufferIndices { get; private set; }
public ushort[] OutputBufferIndices { get; } public ushort[] OutputBufferIndices { get; private set; }
public float[] Volume0 { get; } public float[] Volume0 { get; private set; }
public float[] Volume1 { get; } public float[] Volume1 { get; private set; }
public Memory<VoiceState> State { get; } public Memory<VoiceState> State { get; private set; }
public MixRampGroupedCommand( public MixRampGroupedCommand()
{
}
public MixRampGroupedCommand Initialize(
uint mixBufferCount, uint mixBufferCount,
uint inputBufferIndex, uint inputBufferIndex,
uint outputBufferIndex, uint outputBufferIndex,
@ -52,6 +57,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
} }
State = state; State = state;
return this;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]

View file

@ -9,36 +9,41 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.MultiTapBiquadFilterAndMix; public CommandType CommandType => CommandType.MultiTapBiquadFilterAndMix;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public ushort InputBufferIndex { get; } public ushort InputBufferIndex { get; private set; }
public ushort OutputBufferIndex { get; } public ushort OutputBufferIndex { get; private set; }
private BiquadFilterParameter2 _parameter0; private BiquadFilterParameter2 _parameter0;
private BiquadFilterParameter2 _parameter1; private BiquadFilterParameter2 _parameter1;
public Memory<BiquadFilterState> BiquadFilterState0 { get; } public Memory<BiquadFilterState> BiquadFilterState0 { get; private set; }
public Memory<BiquadFilterState> BiquadFilterState1 { get; } public Memory<BiquadFilterState> BiquadFilterState1 { get; private set; }
public Memory<BiquadFilterState> PreviousBiquadFilterState0 { get; } public Memory<BiquadFilterState> PreviousBiquadFilterState0 { get; private set; }
public Memory<BiquadFilterState> PreviousBiquadFilterState1 { get; } public Memory<BiquadFilterState> PreviousBiquadFilterState1 { get; private set; }
public Memory<VoiceState> State { get; } public Memory<VoiceState> State { get; private set; }
public int LastSampleIndex { get; } public int LastSampleIndex { get; private set; }
public float Volume0 { get; } public float Volume0 { get; private set; }
public float Volume1 { get; } public float Volume1 { get; private set; }
public bool NeedInitialization0 { get; } public bool NeedInitialization0 { get; private set; }
public bool NeedInitialization1 { get; } public bool NeedInitialization1 { get; private set; }
public bool HasVolumeRamp { get; } public bool HasVolumeRamp { get; private set; }
public bool IsFirstMixBuffer { get; } public bool IsFirstMixBuffer { get; private set; }
public MultiTapBiquadFilterAndMixCommand( public MultiTapBiquadFilterAndMixCommand()
{
}
public MultiTapBiquadFilterAndMixCommand Initialize(
float volume0, float volume0,
float volume1, float volume1,
uint inputBufferIndex, uint inputBufferIndex,
@ -80,6 +85,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
NeedInitialization1 = needInitialization1; NeedInitialization1 = needInitialization1;
HasVolumeRamp = hasVolumeRamp; HasVolumeRamp = hasVolumeRamp;
IsFirstMixBuffer = isFirstMixBuffer; IsFirstMixBuffer = isFirstMixBuffer;
return this;
} }
private void UpdateState(Memory<BiquadFilterState> state, Memory<BiquadFilterState> previousState, bool needInitialization) private void UpdateState(Memory<BiquadFilterState> state, Memory<BiquadFilterState> previousState, bool needInitialization)

View file

@ -8,40 +8,47 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.MultiTapBiquadFilter; public CommandType CommandType => CommandType.MultiTapBiquadFilter;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
private readonly BiquadFilterParameter2[] _parameters; public BiquadFilterParameter2[] Parameters { get; private set; }
private readonly Memory<BiquadFilterState> _biquadFilterStates; public Memory<BiquadFilterState> BiquadFilterStates { get; private set; }
private readonly int _inputBufferIndex; public int InputBufferIndex { get; private set; }
private readonly int _outputBufferIndex; public int OutputBufferIndex { get; private set; }
private readonly bool[] _isInitialized; public bool[] IsInitialized { get; private set; }
public MultiTapBiquadFilterCommand(int baseIndex, ReadOnlySpan<BiquadFilterParameter2> filters, Memory<BiquadFilterState> biquadFilterStateMemory, int inputBufferOffset, int outputBufferOffset, ReadOnlySpan<bool> isInitialized, int nodeId) public MultiTapBiquadFilterCommand()
{ {
_parameters = filters.ToArray();
_biquadFilterStates = biquadFilterStateMemory; }
_inputBufferIndex = baseIndex + inputBufferOffset;
_outputBufferIndex = baseIndex + outputBufferOffset; public MultiTapBiquadFilterCommand Initialize(int baseIndex, ReadOnlySpan<BiquadFilterParameter2> filters, Memory<BiquadFilterState> biquadFilterStateMemory, int inputBufferOffset, int outputBufferOffset, ReadOnlySpan<bool> isInitialized, int nodeId)
_isInitialized = isInitialized.ToArray(); {
Parameters = filters.ToArray();
BiquadFilterStates = biquadFilterStateMemory;
InputBufferIndex = baseIndex + inputBufferOffset;
OutputBufferIndex = baseIndex + outputBufferOffset;
IsInitialized = isInitialized.ToArray();
Enabled = true; Enabled = true;
NodeId = nodeId; NodeId = nodeId;
return this;
} }
public void Process(CommandList context) public void Process(CommandList context)
{ {
Span<BiquadFilterState> states = _biquadFilterStates.Span; Span<BiquadFilterState> states = BiquadFilterStates.Span;
ReadOnlySpan<float> inputBuffer = context.GetBuffer(_inputBufferIndex); ReadOnlySpan<float> inputBuffer = context.GetBuffer(InputBufferIndex);
Span<float> outputBuffer = context.GetBuffer(_outputBufferIndex); Span<float> outputBuffer = context.GetBuffer(OutputBufferIndex);
for (int i = 0; i < _parameters.Length; i++) for (int i = 0; i < Parameters.Length; i++)
{ {
if (!_isInitialized[i]) if (!IsInitialized[i])
{ {
states[i] = new BiquadFilterState(); states[i] = new BiquadFilterState();
} }
@ -49,13 +56,13 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
// NOTE: Nintendo only implement single and double biquad filters but no generic path when the command definition suggests it could be done. // NOTE: Nintendo only implement single and double biquad filters but no generic path when the command definition suggests it could be done.
// As such we currently only implement a generic path for simplicity for double biquad. // As such we currently only implement a generic path for simplicity for double biquad.
if (_parameters.Length == 1) if (Parameters.Length == 1)
{ {
BiquadFilterHelper.ProcessBiquadFilter(ref _parameters[0], ref states[0], outputBuffer, inputBuffer, context.SampleCount); BiquadFilterHelper.ProcessBiquadFilter(ref Parameters[0], ref states[0], outputBuffer, inputBuffer, context.SampleCount);
} }
else else
{ {
BiquadFilterHelper.ProcessBiquadFilter(_parameters, states, outputBuffer, inputBuffer, context.SampleCount); BiquadFilterHelper.ProcessBiquadFilter(Parameters, states, outputBuffer, inputBuffer, context.SampleCount);
} }
} }
} }

View file

@ -11,26 +11,31 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.PcmFloatDataSourceVersion1; public CommandType CommandType => CommandType.PcmFloatDataSourceVersion1;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public ushort OutputBufferIndex { get; } public ushort OutputBufferIndex { get; private set; }
public uint SampleRate { get; } public uint SampleRate { get; private set; }
public uint ChannelIndex { get; } public uint ChannelIndex { get; private set; }
public uint ChannelCount { get; } public uint ChannelCount { get; private set; }
public float Pitch { get; } public float Pitch { get; private set; }
public WaveBuffer[] WaveBuffers { get; } public WaveBuffer[] WaveBuffers { get; }
public Memory<VoiceState> State { get; } public Memory<VoiceState> State { get; private set; }
public DecodingBehaviour DecodingBehaviour { get; } public DecodingBehaviour DecodingBehaviour { get; private set; }
public PcmFloatDataSourceCommandVersion1(ref VoiceInfo serverInfo, Memory<VoiceState> state, ushort outputBufferIndex, ushort channelIndex, int nodeId) public PcmFloatDataSourceCommandVersion1()
{
WaveBuffers = new WaveBuffer[Constants.VoiceWaveBufferCount];
}
public PcmFloatDataSourceCommandVersion1 Initialize(ref VoiceInfo serverInfo, Memory<VoiceState> state, ushort outputBufferIndex, ushort channelIndex, int nodeId)
{ {
Enabled = true; Enabled = true;
NodeId = nodeId; NodeId = nodeId;
@ -40,8 +45,6 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
ChannelIndex = channelIndex; ChannelIndex = channelIndex;
ChannelCount = serverInfo.ChannelsCount; ChannelCount = serverInfo.ChannelsCount;
Pitch = serverInfo.Pitch; Pitch = serverInfo.Pitch;
WaveBuffers = new WaveBuffer[Constants.VoiceWaveBufferCount];
Span<Server.Voice.WaveBuffer> waveBufferSpan = serverInfo.WaveBuffers.AsSpan(); Span<Server.Voice.WaveBuffer> waveBufferSpan = serverInfo.WaveBuffers.AsSpan();
@ -54,6 +57,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
State = state; State = state;
DecodingBehaviour = serverInfo.DecodingBehaviour; DecodingBehaviour = serverInfo.DecodingBehaviour;
return this;
} }
public void Process(CommandList context) public void Process(CommandList context)

View file

@ -11,26 +11,31 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.PcmInt16DataSourceVersion1; public CommandType CommandType => CommandType.PcmInt16DataSourceVersion1;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public ushort OutputBufferIndex { get; } public ushort OutputBufferIndex { get; private set; }
public uint SampleRate { get; } public uint SampleRate { get; private set; }
public uint ChannelIndex { get; } public uint ChannelIndex { get; private set; }
public uint ChannelCount { get; } public uint ChannelCount { get; private set; }
public float Pitch { get; } public float Pitch { get; private set; }
public WaveBuffer[] WaveBuffers { get; } public WaveBuffer[] WaveBuffers { get; }
public Memory<VoiceState> State { get; } public Memory<VoiceState> State { get; private set; }
public DecodingBehaviour DecodingBehaviour { get; } public DecodingBehaviour DecodingBehaviour { get; private set; }
public PcmInt16DataSourceCommandVersion1(ref VoiceInfo serverInfo, Memory<VoiceState> state, ushort outputBufferIndex, ushort channelIndex, int nodeId) public PcmInt16DataSourceCommandVersion1()
{
WaveBuffers = new WaveBuffer[Constants.VoiceWaveBufferCount];
}
public PcmInt16DataSourceCommandVersion1 Initialize(ref VoiceInfo serverInfo, Memory<VoiceState> state, ushort outputBufferIndex, ushort channelIndex, int nodeId)
{ {
Enabled = true; Enabled = true;
NodeId = nodeId; NodeId = nodeId;
@ -40,8 +45,6 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
ChannelIndex = channelIndex; ChannelIndex = channelIndex;
ChannelCount = serverInfo.ChannelsCount; ChannelCount = serverInfo.ChannelsCount;
Pitch = serverInfo.Pitch; Pitch = serverInfo.Pitch;
WaveBuffers = new WaveBuffer[Constants.VoiceWaveBufferCount];
Span<Server.Voice.WaveBuffer> waveBufferSpan = serverInfo.WaveBuffers.AsSpan(); Span<Server.Voice.WaveBuffer> waveBufferSpan = serverInfo.WaveBuffers.AsSpan();
@ -54,6 +57,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
State = state; State = state;
DecodingBehaviour = serverInfo.DecodingBehaviour; DecodingBehaviour = serverInfo.DecodingBehaviour;
return this;
} }
public void Process(CommandList context) public void Process(CommandList context)

View file

@ -13,22 +13,34 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.Performance; public CommandType CommandType => CommandType.Performance;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public PerformanceEntryAddresses PerformanceEntryAddresses { get; } public PerformanceEntryAddresses PerformanceEntryAddresses { get; private set; }
public Type PerformanceType { get; set; } public Type PerformanceType { get; set; }
public PerformanceCommand(ref PerformanceEntryAddresses performanceEntryAddresses, Type performanceType, int nodeId) public PerformanceCommand()
{ {
}
public PerformanceCommand Initialize(ref PerformanceEntryAddresses performanceEntryAddresses, Type performanceType, int nodeId)
{
if (PerformanceEntryAddresses is not null)
{
PerformanceEntryAddresses.PerformanceEntryAddressesPool.Release(PerformanceEntryAddresses);
}
Enabled = true; Enabled = true;
PerformanceEntryAddresses = performanceEntryAddresses; PerformanceEntryAddresses = performanceEntryAddresses;
PerformanceType = performanceType; PerformanceType = performanceType;
NodeId = nodeId; NodeId = nodeId;
return this;
} }
public void Process(CommandList context) public void Process(CommandList context)

View file

@ -35,26 +35,32 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.Reverb3d; public CommandType CommandType => CommandType.Reverb3d;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public ushort InputBufferIndex { get; } public ushort InputBufferIndex { get; private set; }
public ushort OutputBufferIndex { get; } public ushort OutputBufferIndex { get; private set; }
public Reverb3dParameter Parameter => _parameter; public Reverb3dParameter Parameter => _parameter;
public Memory<Reverb3dState> State { get; } public Memory<Reverb3dState> State { get; private set; }
public ulong WorkBuffer { get; } public ulong WorkBuffer { get; private set; }
public ushort[] OutputBufferIndices { get; } public ushort[] OutputBufferIndices { get; }
public ushort[] InputBufferIndices { get; } public ushort[] InputBufferIndices { get; }
public bool IsEffectEnabled { get; } public bool IsEffectEnabled { get; private set; }
private Reverb3dParameter _parameter; private Reverb3dParameter _parameter;
public Reverb3dCommand(uint bufferOffset, Reverb3dParameter parameter, Memory<Reverb3dState> state, bool isEnabled, ulong workBuffer, int nodeId, bool newEffectChannelMappingSupported) public Reverb3dCommand()
{
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
}
public Reverb3dCommand Initialize(uint bufferOffset, Reverb3dParameter parameter, Memory<Reverb3dState> state, bool isEnabled, ulong workBuffer, int nodeId, bool newEffectChannelMappingSupported)
{ {
Enabled = true; Enabled = true;
IsEffectEnabled = isEnabled; IsEffectEnabled = isEnabled;
@ -62,9 +68,6 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
_parameter = parameter; _parameter = parameter;
State = state; State = state;
WorkBuffer = workBuffer; WorkBuffer = workBuffer;
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
Span<byte> inputSpan = Parameter.Input.AsSpan(); Span<byte> inputSpan = Parameter.Input.AsSpan();
Span<byte> outputSpan = Parameter.Output.AsSpan(); Span<byte> outputSpan = Parameter.Output.AsSpan();
@ -79,6 +82,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
// TODO: Update reverb 3d processing and remove this to use RemapLegacyChannelEffectMappingToChannelResourceMapping. // TODO: Update reverb 3d processing and remove this to use RemapLegacyChannelEffectMappingToChannelResourceMapping.
DataSourceHelper.RemapChannelResourceMappingToLegacy(newEffectChannelMappingSupported, InputBufferIndices, Parameter.ChannelCount); DataSourceHelper.RemapChannelResourceMappingToLegacy(newEffectChannelMappingSupported, InputBufferIndices, Parameter.ChannelCount);
DataSourceHelper.RemapChannelResourceMappingToLegacy(newEffectChannelMappingSupported, OutputBufferIndices, Parameter.ChannelCount); DataSourceHelper.RemapChannelResourceMappingToLegacy(newEffectChannelMappingSupported, OutputBufferIndices, Parameter.ChannelCount);
return this;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]

View file

@ -33,26 +33,32 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.Reverb; public CommandType CommandType => CommandType.Reverb;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public ReverbParameter Parameter => _parameter; public ReverbParameter Parameter => _parameter;
public Memory<ReverbState> State { get; } public Memory<ReverbState> State { get; private set; }
public ulong WorkBuffer { get; } public ulong WorkBuffer { get; private set; }
public ushort[] OutputBufferIndices { get; } public ushort[] OutputBufferIndices { get; }
public ushort[] InputBufferIndices { get; } public ushort[] InputBufferIndices { get; }
public bool IsLongSizePreDelaySupported { get; } public bool IsLongSizePreDelaySupported { get; private set; }
public bool IsEffectEnabled { get; } public bool IsEffectEnabled { get; private set; }
private ReverbParameter _parameter; private ReverbParameter _parameter;
private const int FixedPointPrecision = 14; private const int FixedPointPrecision = 14;
public ReverbCommand(uint bufferOffset, ReverbParameter parameter, Memory<ReverbState> state, bool isEnabled, ulong workBuffer, int nodeId, bool isLongSizePreDelaySupported, bool newEffectChannelMappingSupported) public ReverbCommand()
{
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
}
public ReverbCommand Initialize(uint bufferOffset, ReverbParameter parameter, Memory<ReverbState> state, bool isEnabled, ulong workBuffer, int nodeId, bool isLongSizePreDelaySupported, bool newEffectChannelMappingSupported)
{ {
Enabled = true; Enabled = true;
IsEffectEnabled = isEnabled; IsEffectEnabled = isEnabled;
@ -60,9 +66,6 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
_parameter = parameter; _parameter = parameter;
State = state; State = state;
WorkBuffer = workBuffer; WorkBuffer = workBuffer;
InputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax];
Span<byte> inputSpan = Parameter.Input.AsSpan(); Span<byte> inputSpan = Parameter.Input.AsSpan();
Span<byte> outputSpan = Parameter.Output.AsSpan(); Span<byte> outputSpan = Parameter.Output.AsSpan();
@ -79,6 +82,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
// TODO: Update reverb processing and remove this to use RemapLegacyChannelEffectMappingToChannelResourceMapping. // TODO: Update reverb processing and remove this to use RemapLegacyChannelEffectMappingToChannelResourceMapping.
DataSourceHelper.RemapChannelResourceMappingToLegacy(newEffectChannelMappingSupported, InputBufferIndices, Parameter.ChannelCount); DataSourceHelper.RemapChannelResourceMappingToLegacy(newEffectChannelMappingSupported, InputBufferIndices, Parameter.ChannelCount);
DataSourceHelper.RemapChannelResourceMappingToLegacy(newEffectChannelMappingSupported, OutputBufferIndices, Parameter.ChannelCount); DataSourceHelper.RemapChannelResourceMappingToLegacy(newEffectChannelMappingSupported, OutputBufferIndices, Parameter.ChannelCount);
return this;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]

View file

@ -7,22 +7,27 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.Upsample; public CommandType CommandType => CommandType.Upsample;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public uint BufferCount { get; } public uint BufferCount { get; private set; }
public uint InputBufferIndex { get; } public uint InputBufferIndex { get; private set; }
public uint InputSampleCount { get; } public uint InputSampleCount { get; private set; }
public uint InputSampleRate { get; } public uint InputSampleRate { get; private set; }
public UpsamplerInfo UpsamplerInfo { get; } public UpsamplerInfo UpsamplerInfo { get; private set; }
public Memory<float> OutBuffer { get; } public Memory<float> OutBuffer { get; private set; }
public UpsampleCommand(uint bufferOffset, UpsamplerInfo info, uint inputCount, Span<byte> inputBufferOffset, uint bufferCount, uint sampleCount, uint sampleRate, int nodeId) public UpsampleCommand()
{
}
public UpsampleCommand Initialize(uint bufferOffset, UpsamplerInfo info, uint inputCount, Span<byte> inputBufferOffset, uint bufferCount, uint sampleCount, uint sampleRate, int nodeId)
{ {
Enabled = true; Enabled = true;
NodeId = nodeId; NodeId = nodeId;
@ -47,6 +52,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
} }
UpsamplerInfo = info; UpsamplerInfo = info;
return this;
} }
private Span<float> GetBuffer(int index, int sampleCount) private Span<float> GetBuffer(int index, int sampleCount)

View file

@ -11,18 +11,23 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.Volume; public CommandType CommandType => CommandType.Volume;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public ushort InputBufferIndex { get; } public ushort InputBufferIndex { get; private set; }
public ushort OutputBufferIndex { get; } public ushort OutputBufferIndex { get; private set; }
public float Volume { get; } public float Volume { get; private set; }
public VolumeCommand(float volume, uint bufferIndex, int nodeId) public VolumeCommand()
{
}
public VolumeCommand Initialize(float volume, uint bufferIndex, int nodeId)
{ {
Enabled = true; Enabled = true;
NodeId = nodeId; NodeId = nodeId;
@ -31,6 +36,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
OutputBufferIndex = (ushort)bufferIndex; OutputBufferIndex = (ushort)bufferIndex;
Volume = volume; Volume = volume;
return this;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]

View file

@ -7,19 +7,24 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
{ {
public bool Enabled { get; set; } public bool Enabled { get; set; }
public int NodeId { get; } public int NodeId { get; private set; }
public CommandType CommandType => CommandType.VolumeRamp; public CommandType CommandType => CommandType.VolumeRamp;
public uint EstimatedProcessingTime { get; set; } public uint EstimatedProcessingTime { get; set; }
public ushort InputBufferIndex { get; } public ushort InputBufferIndex { get; private set; }
public ushort OutputBufferIndex { get; } public ushort OutputBufferIndex { get; private set; }
public float Volume0 { get; } public float Volume0 { get; private set; }
public float Volume1 { get; } public float Volume1 { get; private set; }
public VolumeRampCommand(float volume0, float volume1, uint bufferIndex, int nodeId) public VolumeRampCommand()
{
}
public VolumeRampCommand Initialize(float volume0, float volume1, uint bufferIndex, int nodeId)
{ {
Enabled = true; Enabled = true;
NodeId = nodeId; NodeId = nodeId;
@ -29,6 +34,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
Volume0 = volume0; Volume0 = volume0;
Volume1 = volume1; Volume1 = volume1;
return this;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]

View file

@ -1,97 +0,0 @@
using Ryujinx.Audio.Renderer.Common;
using Ryujinx.Common.Utilities;
using System;
using System.Runtime.InteropServices;
namespace Ryujinx.Audio.Renderer.Parameter
{
/// <summary>
/// Input information for an effect version 2. (added with REV9)
/// </summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct EffectInParameterVersion3 : IEffectInParameter
{
/// <summary>
/// Type of the effect.
/// </summary>
public EffectType Type;
/// <summary>
/// Set to true if the effect is new.
/// </summary>
[MarshalAs(UnmanagedType.I1)]
public bool IsNew;
/// <summary>
/// Set to true if the effect must be active.
/// </summary>
[MarshalAs(UnmanagedType.I1)]
public bool IsEnabled;
/// <summary>
/// Reserved/padding.
/// </summary>
private readonly byte _reserved1;
/// <summary>
/// The target mix id of the effect.
/// </summary>
public int MixId;
/// <summary>
/// Address of the processing workbuffer.
/// </summary>
/// <remarks>This is additional data that could be required by the effect processing.</remarks>
public ulong BufferBase;
/// <summary>
/// Size of the processing workbuffer.
/// </summary>
/// <remarks>This is additional data that could be required by the effect processing.</remarks>
public ulong BufferSize;
/// <summary>
/// Position of the effect while processing effects.
/// </summary>
public uint ProcessingOrder;
/// <summary>
/// Reserved/padding.
/// </summary>
private readonly uint _reserved2;
/// <summary>
/// Specific data storage.
/// </summary>
private SpecificDataStruct _specificDataStart;
[StructLayout(LayoutKind.Sequential, Size = 0xA0, Pack = 1)]
private struct SpecificDataStruct { }
public Span<byte> SpecificData => SpanHelpers.AsSpan<SpecificDataStruct, byte>(ref _specificDataStart);
readonly EffectType IEffectInParameter.Type => Type;
readonly bool IEffectInParameter.IsNew => IsNew;
readonly bool IEffectInParameter.IsEnabled => IsEnabled;
readonly int IEffectInParameter.MixId => MixId;
readonly ulong IEffectInParameter.BufferBase => BufferBase;
readonly ulong IEffectInParameter.BufferSize => BufferSize;
readonly uint IEffectInParameter.ProcessingOrder => ProcessingOrder;
/// <summary>
/// Check if the given channel count is valid.
/// </summary>
/// <param name="channelCount">The channel count to check</param>
/// <returns>Returns true if the channel count is valid.</returns>
public static bool IsChannelCountValid(int channelCount)
{
return channelCount is 1 or 2 or 4 or 6;
}
}
}

View file

@ -1,9 +1,6 @@
using Ryujinx.Audio.Common; using Ryujinx.Audio.Common;
using Ryujinx.Audio.Renderer.Common; using Ryujinx.Audio.Renderer.Common;
using Ryujinx.Audio.Renderer.Dsp;
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace Ryujinx.Audio.Renderer.Parameter namespace Ryujinx.Audio.Renderer.Parameter

View file

@ -8,8 +8,8 @@ using Ryujinx.Audio.Renderer.Server.Sink;
using Ryujinx.Audio.Renderer.Server.Splitter; using Ryujinx.Audio.Renderer.Server.Splitter;
using Ryujinx.Audio.Renderer.Server.Upsampler; using Ryujinx.Audio.Renderer.Server.Upsampler;
using Ryujinx.Audio.Renderer.Server.Voice; using Ryujinx.Audio.Renderer.Server.Voice;
using Ryujinx.Common;
using System; using System;
using System.Runtime.CompilerServices;
using CpuAddress = System.UInt64; using CpuAddress = System.UInt64;
namespace Ryujinx.Audio.Renderer.Server namespace Ryujinx.Audio.Renderer.Server
@ -34,6 +34,170 @@ namespace Ryujinx.Audio.Renderer.Server
/// </summary> /// </summary>
public CommandList CommandList { get; } public CommandList CommandList { get; }
private readonly static ObjectPool<PcmInt16DataSourceCommandVersion1> _pcmInt16DataSourceCommandVersion1Pool = new(() => new PcmInt16DataSourceCommandVersion1());
private readonly static ObjectPool<PcmFloatDataSourceCommandVersion1> _pcmFloatDataSourceCommandVersion1Pool = new(() => new PcmFloatDataSourceCommandVersion1());
private readonly static ObjectPool<AdpcmDataSourceCommandVersion1> _adpcmDataSourceCommandVersion1Pool = new(() => new AdpcmDataSourceCommandVersion1());
private readonly static ObjectPool<DataSourceVersion2Command> _dataSourceVersion2CommandPool = new(() => new DataSourceVersion2Command());
private readonly static ObjectPool<VolumeCommand> _volumeCommandPool = new(() => new VolumeCommand());
private readonly static ObjectPool<VolumeRampCommand> _volumeRampCommandPool = new(() => new VolumeRampCommand());
private readonly static ObjectPool<BiquadFilterCommand> _biquadFilterCommandPool = new(() => new BiquadFilterCommand());
private readonly static ObjectPool<MixCommand> _mixCommandPool = new(() => new MixCommand());
private readonly static ObjectPool<MixRampCommand> _mixRampCommandPool = new(() => new MixRampCommand());
private readonly static ObjectPool<MixRampGroupedCommand> _mixRampGroupedCommandPool = new(() => new MixRampGroupedCommand());
private readonly static ObjectPool<DepopPrepareCommand> _depopPrepareCommandPool = new(() => new DepopPrepareCommand());
private readonly static ObjectPool<DepopForMixBuffersCommand> _depopForMixBuffersCommandPool = new(() => new DepopForMixBuffersCommand());
private readonly static ObjectPool<DelayCommand> _delayCommandPool = new(() => new DelayCommand());
private readonly static ObjectPool<UpsampleCommand> _upsampleCommandPool = new(() => new UpsampleCommand());
private readonly static ObjectPool<DownMixSurroundToStereoCommand> _downMixSurroundToStereoCommandPool = new(() => new DownMixSurroundToStereoCommand());
private readonly static ObjectPool<AuxiliaryBufferCommand> _auxiliaryBufferCommandPool = new(() => new AuxiliaryBufferCommand());
private readonly static ObjectPool<DeviceSinkCommand> _deviceSinkCommandPool = new(() => new DeviceSinkCommand());
private readonly static ObjectPool<CircularBufferSinkCommand> _circularBufferSinkCommandPool = new(() => new CircularBufferSinkCommand());
private readonly static ObjectPool<ReverbCommand> _reverbCommandPool = new(() => new ReverbCommand());
private readonly static ObjectPool<Reverb3dCommand> _reverb3dCommandPool = new(() => new Reverb3dCommand());
private readonly static ObjectPool<PerformanceCommand> _performanceCommandPool = new(() => new PerformanceCommand());
private readonly static ObjectPool<ClearMixBufferCommand> _clearMixBufferCommandPool = new(() => new ClearMixBufferCommand());
private readonly static ObjectPool<CopyMixBufferCommand> _copyMixBufferCommandPool = new(() => new CopyMixBufferCommand());
private readonly static ObjectPool<LimiterCommandVersion1> _limiterCommandVersion1Pool = new(() => new LimiterCommandVersion1());
private readonly static ObjectPool<LimiterCommandVersion2> _limiterCommandVersion2Pool = new(() => new LimiterCommandVersion2());
private readonly static ObjectPool<MultiTapBiquadFilterCommand> _multiTapBiquadFilterCommandPool = new(() => new MultiTapBiquadFilterCommand());
private readonly static ObjectPool<CaptureBufferCommand> _captureBufferCommandPool = new(() => new CaptureBufferCommand());
private readonly static ObjectPool<CompressorCommand> _compressorCommandPool = new(() => new CompressorCommand());
private readonly static ObjectPool<BiquadFilterAndMixCommand> _biquadFilterAndMixCommandPool = new(() => new BiquadFilterAndMixCommand());
private readonly static ObjectPool<MultiTapBiquadFilterAndMixCommand> _multiTapBiquadFilterAndMixCommandPool = new(() => new MultiTapBiquadFilterAndMixCommand());
private readonly static ObjectPool<FillBufferCommand> _fillBufferCommandPool = new(() => new FillBufferCommand());
public static void ReleaseCommand(ICommand command)
{
switch (command.CommandType)
{
case CommandType.PcmInt16DataSourceVersion1:
_pcmInt16DataSourceCommandVersion1Pool.Release((PcmInt16DataSourceCommandVersion1)command);
break;
case CommandType.PcmInt16DataSourceVersion2:
_dataSourceVersion2CommandPool.Release((DataSourceVersion2Command)command);
break;
case CommandType.PcmFloatDataSourceVersion1:
_pcmFloatDataSourceCommandVersion1Pool.Release((PcmFloatDataSourceCommandVersion1)command);
break;
case CommandType.PcmFloatDataSourceVersion2:
_dataSourceVersion2CommandPool.Release((DataSourceVersion2Command)command);
break;
case CommandType.AdpcmDataSourceVersion1:
_adpcmDataSourceCommandVersion1Pool.Release((AdpcmDataSourceCommandVersion1)command);
break;
case CommandType.AdpcmDataSourceVersion2:
_dataSourceVersion2CommandPool.Release((DataSourceVersion2Command)command);
break;
case CommandType.Volume:
_volumeCommandPool.Release((VolumeCommand)command);
break;
case CommandType.VolumeRamp:
_volumeRampCommandPool.Release((VolumeRampCommand)command);
break;
case CommandType.BiquadFilter:
_biquadFilterCommandPool.Release((BiquadFilterCommand)command);
break;
case CommandType.BiquadFilterFloatCoeff:
throw new NotImplementedException();
break;
case CommandType.Mix:
_mixCommandPool.Release((MixCommand)command);
break;
case CommandType.MixRamp:
_mixRampCommandPool.Release((MixRampCommand)command);
break;
case CommandType.MixRampGrouped:
_mixRampGroupedCommandPool.Release((MixRampGroupedCommand)command);
break;
case CommandType.DepopPrepare:
_depopPrepareCommandPool.Release((DepopPrepareCommand)command);
break;
case CommandType.DepopForMixBuffers:
_depopForMixBuffersCommandPool.Release((DepopForMixBuffersCommand)command);
break;
case CommandType.Delay:
_delayCommandPool.Release((DelayCommand)command);
break;
case CommandType.Upsample:
_upsampleCommandPool.Release((UpsampleCommand)command);
break;
case CommandType.DownMixSurroundToStereo:
_downMixSurroundToStereoCommandPool.Release((DownMixSurroundToStereoCommand)command);
break;
case CommandType.AuxiliaryBuffer:
_auxiliaryBufferCommandPool.Release((AuxiliaryBufferCommand)command);
break;
case CommandType.DeviceSink:
_deviceSinkCommandPool.Release((DeviceSinkCommand)command);
break;
case CommandType.CircularBufferSink:
_circularBufferSinkCommandPool.Release((CircularBufferSinkCommand)command);
break;
case CommandType.Reverb:
_reverbCommandPool.Release((ReverbCommand)command);
break;
case CommandType.Reverb3d:
_reverb3dCommandPool.Release((Reverb3dCommand)command);
break;
case CommandType.Performance:
_performanceCommandPool.Release((PerformanceCommand)command);
break;
case CommandType.ClearMixBuffer:
_clearMixBufferCommandPool.Release((ClearMixBufferCommand)command);
break;
case CommandType.CopyMixBuffer:
_copyMixBufferCommandPool.Release((CopyMixBufferCommand)command);
break;
case CommandType.LimiterVersion1:
_limiterCommandVersion1Pool.Release((LimiterCommandVersion1)command);
break;
case CommandType.LimiterVersion2:
_limiterCommandVersion2Pool.Release((LimiterCommandVersion2)command);
break;
case CommandType.MultiTapBiquadFilter:
_multiTapBiquadFilterCommandPool.Release((MultiTapBiquadFilterCommand)command);
break;
case CommandType.MultiTapBiquadFilterFloatCoeff:
throw new NotImplementedException();
break;
case CommandType.CaptureBuffer:
_captureBufferCommandPool.Release((CaptureBufferCommand)command);
break;
case CommandType.Compressor:
_compressorCommandPool.Release((CompressorCommand)command);
break;
case CommandType.BiquadFilterAndMix:
_biquadFilterAndMixCommandPool.Release((BiquadFilterAndMixCommand)command);
break;
case CommandType.BiquadFilterAndMixFloatCoeff:
throw new NotImplementedException();
break;
case CommandType.MultiTapBiquadFilterAndMix:
_multiTapBiquadFilterAndMixCommandPool.Release((MultiTapBiquadFilterAndMixCommand)command);
break;
case CommandType.MultiTapBiquadFilterAndMixFloatCoef:
throw new NotImplementedException();
break;
case CommandType.AuxiliaryBufferGrouped:
throw new NotImplementedException();
break;
case CommandType.FillMixBuffer:
throw new NotImplementedException();
break;
case CommandType.BiquadFilterCrossFade:
throw new NotImplementedException();
break;
case CommandType.MultiTapBiquadFilterCrossFade:
throw new NotImplementedException();
break;
case CommandType.FillBuffer:
_fillBufferCommandPool.Release((FillBufferCommand)command);
break;
default:
throw new NotImplementedException();
}
}
/// <summary> /// <summary>
/// Create a new <see cref="CommandBuffer"/>. /// Create a new <see cref="CommandBuffer"/>.
/// </summary> /// </summary>
@ -63,7 +227,7 @@ namespace Ryujinx.Audio.Renderer.Server
/// <param name="nodeId">The node id associated to this command.</param> /// <param name="nodeId">The node id associated to this command.</param>
public void GenerateClearMixBuffer(int nodeId) public void GenerateClearMixBuffer(int nodeId)
{ {
ClearMixBufferCommand command = new(nodeId); ClearMixBufferCommand command = _clearMixBufferCommandPool.Allocate().Initialize(nodeId);
command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command); command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command);
@ -81,7 +245,7 @@ namespace Ryujinx.Audio.Renderer.Server
/// <param name="wasPlaying">Set to true if the voice was playing previously.</param> /// <param name="wasPlaying">Set to true if the voice was playing previously.</param>
public void GenerateDepopPrepare(Memory<VoiceState> state, Memory<float> depopBuffer, uint bufferCount, uint bufferOffset, int nodeId, bool wasPlaying) public void GenerateDepopPrepare(Memory<VoiceState> state, Memory<float> depopBuffer, uint bufferCount, uint bufferOffset, int nodeId, bool wasPlaying)
{ {
DepopPrepareCommand command = new(state, depopBuffer, bufferCount, bufferOffset, nodeId, wasPlaying); DepopPrepareCommand command = _depopPrepareCommandPool.Allocate().Initialize(state, depopBuffer, bufferCount, bufferOffset, nodeId, wasPlaying);
command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command); command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command);
@ -96,7 +260,7 @@ namespace Ryujinx.Audio.Renderer.Server
/// <param name="nodeId">The node id associated to this command.</param> /// <param name="nodeId">The node id associated to this command.</param>
public void GeneratePerformance(ref PerformanceEntryAddresses performanceEntryAddresses, PerformanceCommand.Type type, int nodeId) public void GeneratePerformance(ref PerformanceEntryAddresses performanceEntryAddresses, PerformanceCommand.Type type, int nodeId)
{ {
PerformanceCommand command = new(ref performanceEntryAddresses, type, nodeId); PerformanceCommand command = _performanceCommandPool.Allocate().Initialize(ref performanceEntryAddresses, type, nodeId);
command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command); command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command);
@ -112,7 +276,7 @@ namespace Ryujinx.Audio.Renderer.Server
/// <param name="nodeId">The node id associated to this command.</param> /// <param name="nodeId">The node id associated to this command.</param>
public void GenerateVolumeRamp(float previousVolume, float volume, uint bufferIndex, int nodeId) public void GenerateVolumeRamp(float previousVolume, float volume, uint bufferIndex, int nodeId)
{ {
VolumeRampCommand command = new(previousVolume, volume, bufferIndex, nodeId); VolumeRampCommand command = _volumeRampCommandPool.Allocate().Initialize(previousVolume, volume, bufferIndex, nodeId);
command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command); command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command);
@ -129,7 +293,7 @@ namespace Ryujinx.Audio.Renderer.Server
/// <param name="nodeId">The node id associated to this command.</param> /// <param name="nodeId">The node id associated to this command.</param>
public void GenerateDataSourceVersion2(ref VoiceInfo voiceInfo, Memory<VoiceState> state, ushort outputBufferIndex, ushort channelIndex, int nodeId) public void GenerateDataSourceVersion2(ref VoiceInfo voiceInfo, Memory<VoiceState> state, ushort outputBufferIndex, ushort channelIndex, int nodeId)
{ {
DataSourceVersion2Command command = new(ref voiceInfo, state, outputBufferIndex, channelIndex, nodeId); DataSourceVersion2Command command = _dataSourceVersion2CommandPool.Allocate().Initialize(ref voiceInfo, state, outputBufferIndex, channelIndex, nodeId);
command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command); command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command);
@ -146,7 +310,7 @@ namespace Ryujinx.Audio.Renderer.Server
/// <param name="nodeId">The node id associated to this command.</param> /// <param name="nodeId">The node id associated to this command.</param>
public void GeneratePcmInt16DataSourceVersion1(ref VoiceInfo voiceInfo, Memory<VoiceState> state, ushort outputBufferIndex, ushort channelIndex, int nodeId) public void GeneratePcmInt16DataSourceVersion1(ref VoiceInfo voiceInfo, Memory<VoiceState> state, ushort outputBufferIndex, ushort channelIndex, int nodeId)
{ {
PcmInt16DataSourceCommandVersion1 command = new(ref voiceInfo, state, outputBufferIndex, channelIndex, nodeId); PcmInt16DataSourceCommandVersion1 command = _pcmInt16DataSourceCommandVersion1Pool.Allocate().Initialize(ref voiceInfo, state, outputBufferIndex, channelIndex, nodeId);
command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command); command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command);
@ -163,7 +327,7 @@ namespace Ryujinx.Audio.Renderer.Server
/// <param name="nodeId">The node id associated to this command.</param> /// <param name="nodeId">The node id associated to this command.</param>
public void GeneratePcmFloatDataSourceVersion1(ref VoiceInfo voiceInfo, Memory<VoiceState> state, ushort outputBufferIndex, ushort channelIndex, int nodeId) public void GeneratePcmFloatDataSourceVersion1(ref VoiceInfo voiceInfo, Memory<VoiceState> state, ushort outputBufferIndex, ushort channelIndex, int nodeId)
{ {
PcmFloatDataSourceCommandVersion1 command = new(ref voiceInfo, state, outputBufferIndex, channelIndex, nodeId); PcmFloatDataSourceCommandVersion1 command = _pcmFloatDataSourceCommandVersion1Pool.Allocate().Initialize(ref voiceInfo, state, outputBufferIndex, channelIndex, nodeId);
command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command); command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command);
@ -179,7 +343,7 @@ namespace Ryujinx.Audio.Renderer.Server
/// <param name="nodeId">The node id associated to this command.</param> /// <param name="nodeId">The node id associated to this command.</param>
public void GenerateAdpcmDataSourceVersion1(ref VoiceInfo voiceInfo, Memory<VoiceState> state, ushort outputBufferIndex, int nodeId) public void GenerateAdpcmDataSourceVersion1(ref VoiceInfo voiceInfo, Memory<VoiceState> state, ushort outputBufferIndex, int nodeId)
{ {
AdpcmDataSourceCommandVersion1 command = new(ref voiceInfo, state, outputBufferIndex, nodeId); AdpcmDataSourceCommandVersion1 command = _adpcmDataSourceCommandVersion1Pool.Allocate().Initialize(ref voiceInfo, state, outputBufferIndex, nodeId);
command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command); command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command);
@ -198,7 +362,7 @@ namespace Ryujinx.Audio.Renderer.Server
/// <param name="nodeId">The node id associated to this command.</param> /// <param name="nodeId">The node id associated to this command.</param>
public void GenerateBiquadFilter(int baseIndex, ref BiquadFilterParameter2 filter, Memory<BiquadFilterState> biquadFilterStateMemory, int inputBufferOffset, int outputBufferOffset, bool needInitialization, int nodeId) public void GenerateBiquadFilter(int baseIndex, ref BiquadFilterParameter2 filter, Memory<BiquadFilterState> biquadFilterStateMemory, int inputBufferOffset, int outputBufferOffset, bool needInitialization, int nodeId)
{ {
BiquadFilterCommand command = new(baseIndex, ref filter, biquadFilterStateMemory, inputBufferOffset, outputBufferOffset, needInitialization, nodeId); BiquadFilterCommand command = _biquadFilterCommandPool.Allocate().Initialize(baseIndex, ref filter, biquadFilterStateMemory, inputBufferOffset, outputBufferOffset, needInitialization, nodeId);
command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command); command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command);
@ -217,7 +381,7 @@ namespace Ryujinx.Audio.Renderer.Server
/// <param name="nodeId">The node id associated to this command.</param> /// <param name="nodeId">The node id associated to this command.</param>
public void GenerateMultiTapBiquadFilter(int baseIndex, ReadOnlySpan<BiquadFilterParameter2> filters, Memory<BiquadFilterState> biquadFilterStatesMemory, int inputBufferOffset, int outputBufferOffset, ReadOnlySpan<bool> isInitialized, int nodeId) public void GenerateMultiTapBiquadFilter(int baseIndex, ReadOnlySpan<BiquadFilterParameter2> filters, Memory<BiquadFilterState> biquadFilterStatesMemory, int inputBufferOffset, int outputBufferOffset, ReadOnlySpan<bool> isInitialized, int nodeId)
{ {
MultiTapBiquadFilterCommand command = new(baseIndex, filters, biquadFilterStatesMemory, inputBufferOffset, outputBufferOffset, isInitialized, nodeId); MultiTapBiquadFilterCommand command = _multiTapBiquadFilterCommandPool.Allocate().Initialize(baseIndex, filters, biquadFilterStatesMemory, inputBufferOffset, outputBufferOffset, isInitialized, nodeId);
command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command); command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command);
@ -236,7 +400,7 @@ namespace Ryujinx.Audio.Renderer.Server
/// <param name="nodeId">The node id associated to this command.</param> /// <param name="nodeId">The node id associated to this command.</param>
public void GenerateMixRampGrouped(uint mixBufferCount, uint inputBufferIndex, uint outputBufferIndex, ReadOnlySpan<float> previousVolume, ReadOnlySpan<float> volume, Memory<VoiceState> state, int nodeId) public void GenerateMixRampGrouped(uint mixBufferCount, uint inputBufferIndex, uint outputBufferIndex, ReadOnlySpan<float> previousVolume, ReadOnlySpan<float> volume, Memory<VoiceState> state, int nodeId)
{ {
MixRampGroupedCommand command = new(mixBufferCount, inputBufferIndex, outputBufferIndex, previousVolume, volume, state, nodeId); MixRampGroupedCommand command = _mixRampGroupedCommandPool.Allocate().Initialize(mixBufferCount, inputBufferIndex, outputBufferIndex, previousVolume, volume, state, nodeId);
command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command); command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command);
@ -255,7 +419,7 @@ namespace Ryujinx.Audio.Renderer.Server
/// <param name="nodeId">The node id associated to this command.</param> /// <param name="nodeId">The node id associated to this command.</param>
public void GenerateMixRamp(float previousVolume, float volume, uint inputBufferIndex, uint outputBufferIndex, int lastSampleIndex, Memory<VoiceState> state, int nodeId) public void GenerateMixRamp(float previousVolume, float volume, uint inputBufferIndex, uint outputBufferIndex, int lastSampleIndex, Memory<VoiceState> state, int nodeId)
{ {
MixRampCommand command = new(previousVolume, volume, inputBufferIndex, outputBufferIndex, lastSampleIndex, state, nodeId); MixRampCommand command = _mixRampCommandPool.Allocate().Initialize(previousVolume, volume, inputBufferIndex, outputBufferIndex, lastSampleIndex, state, nodeId);
command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command); command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command);
@ -293,7 +457,7 @@ namespace Ryujinx.Audio.Renderer.Server
bool isFirstMixBuffer, bool isFirstMixBuffer,
int nodeId) int nodeId)
{ {
BiquadFilterAndMixCommand command = new( BiquadFilterAndMixCommand command = _biquadFilterAndMixCommandPool.Allocate().Initialize(
previousVolume, previousVolume,
volume, volume,
inputBufferIndex, inputBufferIndex,
@ -352,7 +516,7 @@ namespace Ryujinx.Audio.Renderer.Server
bool isFirstMixBuffer, bool isFirstMixBuffer,
int nodeId) int nodeId)
{ {
MultiTapBiquadFilterAndMixCommand command = new( MultiTapBiquadFilterAndMixCommand command = _multiTapBiquadFilterAndMixCommandPool.Allocate().Initialize(
previousVolume, previousVolume,
volume, volume,
inputBufferIndex, inputBufferIndex,
@ -386,7 +550,7 @@ namespace Ryujinx.Audio.Renderer.Server
/// <param name="sampleRate">The target sample rate in use.</param> /// <param name="sampleRate">The target sample rate in use.</param>
public void GenerateDepopForMixBuffers(Memory<float> depopBuffer, uint bufferOffset, uint bufferCount, int nodeId, uint sampleRate) public void GenerateDepopForMixBuffers(Memory<float> depopBuffer, uint bufferOffset, uint bufferCount, int nodeId, uint sampleRate)
{ {
DepopForMixBuffersCommand command = new(depopBuffer, bufferOffset, bufferCount, nodeId, sampleRate); DepopForMixBuffersCommand command = _depopForMixBuffersCommandPool.Allocate().Initialize(depopBuffer, bufferOffset, bufferCount, nodeId, sampleRate);
command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command); command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command);
@ -401,7 +565,7 @@ namespace Ryujinx.Audio.Renderer.Server
/// <param name="nodeId">The node id associated to this command.</param> /// <param name="nodeId">The node id associated to this command.</param>
public void GenerateCopyMixBuffer(uint inputBufferIndex, uint outputBufferIndex, int nodeId) public void GenerateCopyMixBuffer(uint inputBufferIndex, uint outputBufferIndex, int nodeId)
{ {
CopyMixBufferCommand command = new(inputBufferIndex, outputBufferIndex, nodeId); CopyMixBufferCommand command = _copyMixBufferCommandPool.Allocate().Initialize(inputBufferIndex, outputBufferIndex, nodeId);
command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command); command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command);
@ -417,7 +581,7 @@ namespace Ryujinx.Audio.Renderer.Server
/// <param name="volume">The mix volume.</param> /// <param name="volume">The mix volume.</param>
public void GenerateMix(uint inputBufferIndex, uint outputBufferIndex, int nodeId, float volume) public void GenerateMix(uint inputBufferIndex, uint outputBufferIndex, int nodeId, float volume)
{ {
MixCommand command = new(inputBufferIndex, outputBufferIndex, nodeId, volume); MixCommand command = _mixCommandPool.Allocate().Initialize(inputBufferIndex, outputBufferIndex, nodeId, volume);
command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command); command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command);
@ -439,7 +603,7 @@ namespace Ryujinx.Audio.Renderer.Server
{ {
if (parameter.IsChannelCountValid()) if (parameter.IsChannelCountValid())
{ {
ReverbCommand command = new(bufferOffset, parameter, state, isEnabled, workBuffer, nodeId, isLongSizePreDelaySupported, newEffectChannelMappingSupported); ReverbCommand command = _reverbCommandPool.Allocate().Initialize(bufferOffset, parameter, state, isEnabled, workBuffer, nodeId, isLongSizePreDelaySupported, newEffectChannelMappingSupported);
command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command); command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command);
@ -461,7 +625,7 @@ namespace Ryujinx.Audio.Renderer.Server
{ {
if (parameter.IsChannelCountValid()) if (parameter.IsChannelCountValid())
{ {
Reverb3dCommand command = new(bufferOffset, parameter, state, isEnabled, workBuffer, nodeId, newEffectChannelMappingSupported); Reverb3dCommand command = _reverb3dCommandPool.Allocate().Initialize(bufferOffset, parameter, state, isEnabled, workBuffer, nodeId, newEffectChannelMappingSupported);
command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command); command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command);
@ -483,7 +647,7 @@ namespace Ryujinx.Audio.Renderer.Server
{ {
if (parameter.IsChannelCountValid()) if (parameter.IsChannelCountValid())
{ {
DelayCommand command = new(bufferOffset, parameter, state, isEnabled, workBuffer, nodeId, newEffectChannelMappingSupported); DelayCommand command = _delayCommandPool.Allocate().Initialize(bufferOffset, parameter, state, isEnabled, workBuffer, nodeId, newEffectChannelMappingSupported);
command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command); command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command);
@ -504,7 +668,7 @@ namespace Ryujinx.Audio.Renderer.Server
{ {
if (parameter.IsChannelCountValid()) if (parameter.IsChannelCountValid())
{ {
LimiterCommandVersion1 command = new(bufferOffset, parameter, state, isEnabled, workBuffer, nodeId); LimiterCommandVersion1 command = _limiterCommandVersion1Pool.Allocate().Initialize(bufferOffset, parameter, state, isEnabled, workBuffer, nodeId);
command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command); command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command);
@ -526,7 +690,7 @@ namespace Ryujinx.Audio.Renderer.Server
{ {
if (parameter.IsChannelCountValid()) if (parameter.IsChannelCountValid())
{ {
LimiterCommandVersion2 command = new(bufferOffset, parameter, state, effectResultState, isEnabled, workBuffer, nodeId); LimiterCommandVersion2 command = _limiterCommandVersion2Pool.Allocate().Initialize(bufferOffset, parameter, state, effectResultState, isEnabled, workBuffer, nodeId);
command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command); command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command);
@ -552,7 +716,7 @@ namespace Ryujinx.Audio.Renderer.Server
{ {
if (state.SendBufferInfoBase != 0 && state.ReturnBufferInfoBase != 0) if (state.SendBufferInfoBase != 0 && state.ReturnBufferInfoBase != 0)
{ {
AuxiliaryBufferCommand command = new(bufferOffset, inputBufferOffset, outputBufferOffset, ref state, isEnabled, countMax, outputBuffer, inputBuffer, updateCount, writeOffset, nodeId); AuxiliaryBufferCommand command = _auxiliaryBufferCommandPool.Allocate().Initialize(bufferOffset, inputBufferOffset, outputBufferOffset, ref state, isEnabled, countMax, outputBuffer, inputBuffer, updateCount, writeOffset, nodeId);
command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command); command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command);
@ -576,7 +740,7 @@ namespace Ryujinx.Audio.Renderer.Server
{ {
if (sendBufferInfo != 0) if (sendBufferInfo != 0)
{ {
CaptureBufferCommand command = new(bufferOffset, inputBufferOffset, sendBufferInfo, isEnabled, countMax, outputBuffer, updateCount, writeOffset, nodeId); CaptureBufferCommand command = _captureBufferCommandPool.Allocate().Initialize(bufferOffset, inputBufferOffset, sendBufferInfo, isEnabled, countMax, outputBuffer, updateCount, writeOffset, nodeId);
command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command); command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command);
@ -597,7 +761,7 @@ namespace Ryujinx.Audio.Renderer.Server
{ {
if (parameter.IsChannelCountValid()) if (parameter.IsChannelCountValid())
{ {
CompressorCommand command = new(bufferOffset, parameter, state, effectResultState, isEnabled, nodeId); CompressorCommand command = _compressorCommandPool.Allocate().Initialize(bufferOffset, parameter, state, effectResultState, isEnabled, nodeId);
command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command); command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command);
@ -613,7 +777,7 @@ namespace Ryujinx.Audio.Renderer.Server
/// <param name="nodeId">The node id associated to this command.</param> /// <param name="nodeId">The node id associated to this command.</param>
public void GenerateVolume(float volume, uint bufferOffset, int nodeId) public void GenerateVolume(float volume, uint bufferOffset, int nodeId)
{ {
VolumeCommand command = new(volume, bufferOffset, nodeId); VolumeCommand command = _volumeCommandPool.Allocate().Initialize(volume, bufferOffset, nodeId);
command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command); command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command);
@ -628,7 +792,7 @@ namespace Ryujinx.Audio.Renderer.Server
/// <param name="nodeId">The node id associated to this command.</param> /// <param name="nodeId">The node id associated to this command.</param>
public void GenerateCircularBuffer(uint bufferOffset, CircularBufferSink sink, int nodeId) public void GenerateCircularBuffer(uint bufferOffset, CircularBufferSink sink, int nodeId)
{ {
CircularBufferSinkCommand command = new(bufferOffset, ref sink.Parameter, ref sink.CircularBufferAddressInfo, sink.CurrentWriteOffset, nodeId); CircularBufferSinkCommand command = _circularBufferSinkCommandPool.Allocate().Initialize(bufferOffset, ref sink.Parameter, ref sink.CircularBufferAddressInfo, sink.CurrentWriteOffset, nodeId);
command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command); command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command);
@ -645,7 +809,7 @@ namespace Ryujinx.Audio.Renderer.Server
/// <param name="nodeId">The node id associated to this command.</param> /// <param name="nodeId">The node id associated to this command.</param>
public void GenerateDownMixSurroundToStereo(uint bufferOffset, Span<byte> inputBufferOffset, Span<byte> outputBufferOffset, float[] downMixParameter, int nodeId) public void GenerateDownMixSurroundToStereo(uint bufferOffset, Span<byte> inputBufferOffset, Span<byte> outputBufferOffset, float[] downMixParameter, int nodeId)
{ {
DownMixSurroundToStereoCommand command = new(bufferOffset, inputBufferOffset, outputBufferOffset, downMixParameter, nodeId); DownMixSurroundToStereoCommand command = _downMixSurroundToStereoCommandPool.Allocate().Initialize(bufferOffset, inputBufferOffset, outputBufferOffset, downMixParameter, nodeId);
command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command); command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command);
@ -665,7 +829,7 @@ namespace Ryujinx.Audio.Renderer.Server
/// <param name="nodeId">The node id associated to this command.</param> /// <param name="nodeId">The node id associated to this command.</param>
public void GenerateUpsample(uint bufferOffset, UpsamplerInfo upsampler, uint inputCount, Span<byte> inputBufferOffset, uint bufferCountPerSample, uint sampleCount, uint sampleRate, int nodeId) public void GenerateUpsample(uint bufferOffset, UpsamplerInfo upsampler, uint inputCount, Span<byte> inputBufferOffset, uint bufferCountPerSample, uint sampleCount, uint sampleRate, int nodeId)
{ {
UpsampleCommand command = new(bufferOffset, upsampler, inputCount, inputBufferOffset, bufferCountPerSample, sampleCount, sampleRate, nodeId); UpsampleCommand command = _upsampleCommandPool.Allocate().Initialize(bufferOffset, upsampler, inputCount, inputBufferOffset, bufferCountPerSample, sampleCount, sampleRate, nodeId);
command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command); command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command);
@ -682,7 +846,7 @@ namespace Ryujinx.Audio.Renderer.Server
/// <param name="nodeId">The node id associated to this command.</param> /// <param name="nodeId">The node id associated to this command.</param>
public void GenerateDeviceSink(uint bufferOffset, DeviceSink sink, int sessionId, Memory<float> buffer, int nodeId) public void GenerateDeviceSink(uint bufferOffset, DeviceSink sink, int sessionId, Memory<float> buffer, int nodeId)
{ {
DeviceSinkCommand command = new(bufferOffset, sink, sessionId, buffer, nodeId); DeviceSinkCommand command = _deviceSinkCommandPool.Allocate().Initialize(bufferOffset, sink, sessionId, buffer, nodeId);
command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command); command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command);
@ -691,16 +855,7 @@ namespace Ryujinx.Audio.Renderer.Server
public void GenerateFillBuffer(SplitterDestination destination, float value, int length, int nodeId) public void GenerateFillBuffer(SplitterDestination destination, float value, int length, int nodeId)
{ {
FillBufferCommand command; FillBufferCommand command = _fillBufferCommandPool.Allocate().Initialize(destination, length, value, nodeId);
if (Unsafe.IsNullRef(ref destination.GetV2RefOrNull()))
{
command = new(destination.GetV1RefOrNull(), length, value, nodeId);
}
else
{
command = new(destination.GetV2RefOrNull(), length, value, nodeId);
}
command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command); command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command);

View file

@ -1,6 +1,5 @@
using Ryujinx.Audio.Common; using Ryujinx.Audio.Common;
using Ryujinx.Audio.Renderer.Common; using Ryujinx.Audio.Renderer.Common;
using Ryujinx.Audio.Renderer.Dsp;
using Ryujinx.Audio.Renderer.Dsp.Command; using Ryujinx.Audio.Renderer.Dsp.Command;
using Ryujinx.Audio.Renderer.Dsp.State; using Ryujinx.Audio.Renderer.Dsp.State;
using Ryujinx.Audio.Renderer.Parameter; using Ryujinx.Audio.Renderer.Parameter;
@ -339,7 +338,7 @@ namespace Ryujinx.Audio.Renderer.Server
bool performanceInitialized = false; bool performanceInitialized = false;
PerformanceEntryAddresses performanceEntry = new(); PerformanceEntryAddresses performanceEntry = null;
if (_performanceManager != null && _performanceManager.IsTargetNodeId(nodeId) && _performanceManager.GetNextEntry(out performanceEntry, dataSourceDetailType, PerformanceEntryType.Voice, nodeId)) if (_performanceManager != null && _performanceManager.IsTargetNodeId(nodeId) && _performanceManager.GetNextEntry(out performanceEntry, dataSourceDetailType, PerformanceEntryType.Voice, nodeId))
{ {
@ -500,7 +499,7 @@ namespace Ryujinx.Audio.Renderer.Server
{ {
int nodeId = sortedInfo.NodeId; int nodeId = sortedInfo.NodeId;
PerformanceEntryAddresses performanceEntry = new(); PerformanceEntryAddresses performanceEntry = null;
bool performanceInitialized = false; bool performanceInitialized = false;
@ -786,7 +785,7 @@ namespace Ryujinx.Audio.Renderer.Server
bool isFinalMix = mix.MixId == Constants.FinalMixId; bool isFinalMix = mix.MixId == Constants.FinalMixId;
PerformanceEntryAddresses performanceEntry = new(); PerformanceEntryAddresses performanceEntry = null;
bool performanceInitialized = false; bool performanceInitialized = false;
@ -1050,7 +1049,7 @@ namespace Ryujinx.Audio.Renderer.Server
GenerateEffects(ref subMix); GenerateEffects(ref subMix);
PerformanceEntryAddresses performanceEntry = new(); PerformanceEntryAddresses performanceEntry = null;
int nodeId = subMix.NodeId; int nodeId = subMix.NodeId;
@ -1081,7 +1080,7 @@ namespace Ryujinx.Audio.Renderer.Server
{ {
int nodeId = sortedInfo.NodeId; int nodeId = sortedInfo.NodeId;
PerformanceEntryAddresses performanceEntry = new(); PerformanceEntryAddresses performanceEntry = null;
bool performanceInitialized = false; bool performanceInitialized = false;
@ -1115,7 +1114,7 @@ namespace Ryujinx.Audio.Renderer.Server
GenerateEffects(ref finalMix); GenerateEffects(ref finalMix);
PerformanceEntryAddresses performanceEntry = new(); PerformanceEntryAddresses performanceEntry = null;
int nodeId = finalMix.NodeId; int nodeId = finalMix.NodeId;
@ -1164,7 +1163,7 @@ namespace Ryujinx.Audio.Renderer.Server
{ {
int nodeId = _mixContext.GetFinalState().NodeId; int nodeId = _mixContext.GetFinalState().NodeId;
PerformanceEntryAddresses performanceEntry = new(); PerformanceEntryAddresses performanceEntry = null;
bool performanceInitialized = false; bool performanceInitialized = false;
@ -1244,7 +1243,7 @@ namespace Ryujinx.Audio.Renderer.Server
{ {
bool performanceInitialized = false; bool performanceInitialized = false;
PerformanceEntryAddresses performanceEntry = new(); PerformanceEntryAddresses performanceEntry = null;
if (_performanceManager != null && _performanceManager.GetNextEntry(out performanceEntry, PerformanceEntryType.Sink, sink.NodeId)) if (_performanceManager != null && _performanceManager.GetNextEntry(out performanceEntry, PerformanceEntryType.Sink, sink.NodeId))
{ {

View file

@ -174,19 +174,6 @@ namespace Ryujinx.Audio.Renderer.Server.Effect
updateErrorInfo = new ErrorInfo(); updateErrorInfo = new ErrorInfo();
} }
/// <summary>
/// Update the internal state from a user version 3 parameter.
/// </summary>
/// <param name="updateErrorInfo">The possible <see cref="ErrorInfo"/> that was generated.</param>
/// <param name="parameter">The user parameter.</param>
/// <param name="mapper">The mapper to use.</param>
public virtual void Update(out ErrorInfo updateErrorInfo, in EffectInParameterVersion3 parameter, PoolMapper mapper)
{
Debug.Assert(IsTypeValid(in parameter));
updateErrorInfo = new ErrorInfo();
}
/// <summary> /// <summary>
/// Get the work buffer DSP address at the given index. /// Get the work buffer DSP address at the given index.

View file

@ -25,13 +25,19 @@ namespace Ryujinx.Audio.Renderer.Server.Effect
/// </summary> /// </summary>
public Memory<BiquadFilterState> State { get; } public Memory<BiquadFilterState> State { get; }
/// <summary>
/// The biquad filter effect version.
/// </summary>
public int BiquadFilterEffectVersion;
/// <summary> /// <summary>
/// Create a new <see cref="BiquadFilterEffect"/>. /// Create a new <see cref="BiquadFilterEffect"/>.
/// </summary> /// </summary>
public BiquadFilterEffect() public BiquadFilterEffect(int version)
{ {
Parameter = new BiquadFilterEffectParameter2(); Parameter = new BiquadFilterEffectParameter2();
State = new BiquadFilterState[Constants.ChannelCountMax]; State = new BiquadFilterState[Constants.ChannelCountMax];
BiquadFilterEffectVersion = version;
} }
public override EffectType TargetEffectType => EffectType.BiquadFilter; public override EffectType TargetEffectType => EffectType.BiquadFilter;
@ -45,11 +51,6 @@ namespace Ryujinx.Audio.Renderer.Server.Effect
{ {
Update(out updateErrorInfo, in parameter, mapper); Update(out updateErrorInfo, in parameter, mapper);
} }
public override void Update(out BehaviourParameter.ErrorInfo updateErrorInfo, in EffectInParameterVersion3 parameter, PoolMapper mapper)
{
Update(out updateErrorInfo, in parameter, mapper);
}
public void Update<T>(out BehaviourParameter.ErrorInfo updateErrorInfo, in T parameter, PoolMapper mapper) where T : unmanaged, IEffectInParameter public void Update<T>(out BehaviourParameter.ErrorInfo updateErrorInfo, in T parameter, PoolMapper mapper) where T : unmanaged, IEffectInParameter
{ {
@ -57,7 +58,7 @@ namespace Ryujinx.Audio.Renderer.Server.Effect
UpdateParameterBase(in parameter); UpdateParameterBase(in parameter);
if (typeof(T) == typeof(EffectInParameterVersion3)) if (BiquadFilterEffectVersion == 2)
{ {
Parameter = MemoryMarshal.Cast<byte, BiquadFilterEffectParameter2>(parameter.SpecificData)[0]; Parameter = MemoryMarshal.Cast<byte, BiquadFilterEffectParameter2>(parameter.SpecificData)[0];
} }

View file

@ -1,3 +1,4 @@
using Ryujinx.Common;
using System; using System;
namespace Ryujinx.Audio.Renderer.Server.Performance namespace Ryujinx.Audio.Renderer.Server.Performance
@ -7,6 +8,8 @@ namespace Ryujinx.Audio.Renderer.Server.Performance
/// </summary> /// </summary>
public class PerformanceEntryAddresses public class PerformanceEntryAddresses
{ {
public static readonly ObjectPool<PerformanceEntryAddresses> PerformanceEntryAddressesPool = new(() => new PerformanceEntryAddresses());
/// <summary> /// <summary>
/// The memory storing the performance entry. /// The memory storing the performance entry.
/// </summary> /// </summary>
@ -52,5 +55,10 @@ namespace Ryujinx.Audio.Renderer.Server.Performance
{ {
BaseMemory.Span[(int)ProcessingTimeOffset / 4] = (int)(endTimeNano / 1000) - BaseMemory.Span[(int)StartTimeOffset / 4]; BaseMemory.Span[(int)ProcessingTimeOffset / 4] = (int)(endTimeNano / 1000) - BaseMemory.Span[(int)StartTimeOffset / 4];
} }
public void Clear()
{
}
} }
} }

View file

@ -208,11 +208,9 @@ namespace Ryujinx.Audio.Renderer.Server.Performance
public override bool GetNextEntry(out PerformanceEntryAddresses performanceEntry, PerformanceEntryType entryType, int nodeId) public override bool GetNextEntry(out PerformanceEntryAddresses performanceEntry, PerformanceEntryType entryType, int nodeId)
{ {
performanceEntry = new PerformanceEntryAddresses performanceEntry = PerformanceEntryAddresses.PerformanceEntryAddressesPool.Allocate();
{ performanceEntry.BaseMemory = SpanMemoryManager<int>.Cast(CurrentBuffer);
BaseMemory = SpanMemoryManager<int>.Cast(CurrentBuffer), performanceEntry.EntryCountOffset = (uint)CurrentHeader.GetEntryCountOffset();
EntryCountOffset = (uint)CurrentHeader.GetEntryCountOffset(),
};
uint baseEntryOffset = (uint)(Unsafe.SizeOf<THeader>() + Unsafe.SizeOf<TEntry>() * _entryIndex); uint baseEntryOffset = (uint)(Unsafe.SizeOf<THeader>() + Unsafe.SizeOf<TEntry>() * _entryIndex);
@ -238,12 +236,10 @@ namespace Ryujinx.Audio.Renderer.Server.Performance
{ {
return false; return false;
} }
performanceEntry = new PerformanceEntryAddresses performanceEntry = PerformanceEntryAddresses.PerformanceEntryAddressesPool.Allocate();
{ performanceEntry.BaseMemory = SpanMemoryManager<int>.Cast(CurrentBuffer);
BaseMemory = SpanMemoryManager<int>.Cast(CurrentBuffer), performanceEntry.EntryCountOffset = (uint)CurrentHeader.GetEntryCountOffset();
EntryCountOffset = (uint)CurrentHeader.GetEntryCountOffset(),
};
uint baseEntryOffset = (uint)(Unsafe.SizeOf<THeader>() + GetEntriesSize() + Unsafe.SizeOf<TEntryDetail>() * _entryDetailIndex); uint baseEntryOffset = (uint)(Unsafe.SizeOf<THeader>() + GetEntriesSize() + Unsafe.SizeOf<TEntryDetail>() * _entryDetailIndex);

View file

@ -1,4 +1,3 @@
using Ryujinx.Audio.Renderer.Dsp;
using Ryujinx.Audio.Renderer.Parameter; using Ryujinx.Audio.Renderer.Parameter;
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using Ryujinx.Common.Utilities; using Ryujinx.Common.Utilities;

View file

@ -300,7 +300,7 @@ namespace Ryujinx.Audio.Renderer.Server
return ResultCode.Success; return ResultCode.Success;
} }
private static void ResetEffect<T>(ref BaseEffect effect, in T parameter, PoolMapper mapper) where T : unmanaged, IEffectInParameter private void ResetEffect<T>(ref BaseEffect effect, in T parameter, PoolMapper mapper) where T : unmanaged, IEffectInParameter
{ {
effect.ForceUnmapBuffers(mapper); effect.ForceUnmapBuffers(mapper);
@ -312,7 +312,8 @@ namespace Ryujinx.Audio.Renderer.Server
EffectType.Delay => new DelayEffect(), EffectType.Delay => new DelayEffect(),
EffectType.Reverb => new ReverbEffect(), EffectType.Reverb => new ReverbEffect(),
EffectType.Reverb3d => new Reverb3dEffect(), EffectType.Reverb3d => new Reverb3dEffect(),
EffectType.BiquadFilter => new BiquadFilterEffect(), EffectType.BiquadFilter when _behaviourInfo.IsBiquadFilterParameterFloatSupported() => new BiquadFilterEffect(2),
EffectType.BiquadFilter => new BiquadFilterEffect(1),
EffectType.Limiter => new LimiterEffect(), EffectType.Limiter => new LimiterEffect(),
EffectType.CaptureBuffer => new CaptureBufferEffect(), EffectType.CaptureBuffer => new CaptureBufferEffect(),
EffectType.Compressor => new CompressorEffect(), EffectType.Compressor => new CompressorEffect(),
@ -322,11 +323,6 @@ namespace Ryujinx.Audio.Renderer.Server
public ResultCode UpdateEffects(EffectContext context, bool isAudioRendererActive, PoolMapper mapper) public ResultCode UpdateEffects(EffectContext context, bool isAudioRendererActive, PoolMapper mapper)
{ {
if (_behaviourInfo.IsBiquadFilterParameterFloatSupported())
{
return UpdateEffectsVersion3(context, isAudioRendererActive, mapper);
}
if (_behaviourInfo.IsEffectInfoVersion2Supported()) if (_behaviourInfo.IsEffectInfoVersion2Supported())
{ {
return UpdateEffectsVersion2(context, isAudioRendererActive, mapper); return UpdateEffectsVersion2(context, isAudioRendererActive, mapper);
@ -334,60 +330,6 @@ namespace Ryujinx.Audio.Renderer.Server
return UpdateEffectsVersion1(context, isAudioRendererActive, mapper); return UpdateEffectsVersion1(context, isAudioRendererActive, mapper);
} }
public ResultCode UpdateEffectsVersion3(EffectContext context, bool isAudioRendererActive, PoolMapper mapper)
{
if (context.GetCount() * Unsafe.SizeOf<EffectInParameterVersion2>() != _inputHeader.EffectsSize)
{
return ResultCode.InvalidUpdateInfo;
}
int initialOutputSize = _output.Length;
long initialInputConsumed = _inputReader.Consumed;
for (int i = 0; i < context.GetCount(); i++)
{
ref readonly EffectInParameterVersion3 parameter = ref _inputReader.GetRefOrRefToCopy<EffectInParameterVersion3>(out _);
ref EffectOutStatusVersion2 outStatus = ref SpanIOHelper.GetWriteRef<EffectOutStatusVersion2>(ref _output)[0];
ref BaseEffect effect = ref context.GetEffect(i);
if (!effect.IsTypeValid(in parameter))
{
ResetEffect(ref effect, in parameter, mapper);
}
effect.Update(out ErrorInfo updateErrorInfo, in parameter, mapper);
if (updateErrorInfo.ErrorCode != ResultCode.Success)
{
_behaviourInfo.AppendError(ref updateErrorInfo);
}
effect.StoreStatus(ref outStatus, isAudioRendererActive);
if (parameter.IsNew)
{
effect.InitializeResultState(ref context.GetDspState(i));
effect.InitializeResultState(ref context.GetState(i));
}
effect.UpdateResultState(ref outStatus.ResultState, ref context.GetState(i));
}
int currentOutputSize = _output.Length;
OutputHeader.EffectsSize = (uint)(Unsafe.SizeOf<EffectOutStatusVersion2>() * context.GetCount());
OutputHeader.TotalSize += OutputHeader.EffectsSize;
Debug.Assert((initialOutputSize - currentOutputSize) == OutputHeader.EffectsSize);
_inputReader.SetConsumed(initialInputConsumed + _inputHeader.EffectsSize);
return ResultCode.Success;
}
public ResultCode UpdateEffectsVersion2(EffectContext context, bool isAudioRendererActive, PoolMapper mapper) public ResultCode UpdateEffectsVersion2(EffectContext context, bool isAudioRendererActive, PoolMapper mapper)
{ {

View file

@ -4,13 +4,14 @@ using Ryujinx.Audio.Renderer.Dsp;
using Ryujinx.Audio.Renderer.Dsp.State; using Ryujinx.Audio.Renderer.Dsp.State;
using Ryujinx.Audio.Renderer.Parameter; using Ryujinx.Audio.Renderer.Parameter;
using Ryujinx.Audio.Renderer.Server.MemoryPool; using Ryujinx.Audio.Renderer.Server.MemoryPool;
using Ryujinx.Common;
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using Ryujinx.Common.Utilities; using Ryujinx.Common.Utilities;
using System; using System;
using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using static Ryujinx.Audio.Renderer.Common.BehaviourParameter; using static Ryujinx.Audio.Renderer.Common.BehaviourParameter;
using static Ryujinx.Audio.Renderer.Parameter.VoiceInParameter1;
using PlayState = Ryujinx.Audio.Renderer.Server.Types.PlayState; using PlayState = Ryujinx.Audio.Renderer.Server.Types.PlayState;
namespace Ryujinx.Audio.Renderer.Server.Voice namespace Ryujinx.Audio.Renderer.Server.Voice
@ -20,6 +21,8 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
{ {
public const int Alignment = 0x10; public const int Alignment = 0x10;
private static readonly ObjectPool<Memory<VoiceState>[]> voiceStatesPool = new(() => new Memory<VoiceState>[Constants.VoiceChannelCountMax]);
/// <summary> /// <summary>
/// Set to true if the voice is used. /// Set to true if the voice is used.
/// </summary> /// </summary>
@ -568,7 +571,7 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
PoolMapper mapper, PoolMapper mapper,
ref BehaviourInfo behaviourInfo) ref BehaviourInfo behaviourInfo)
{ {
errorInfos = new ErrorInfo[Constants.VoiceWaveBufferCount * 2];
if (parameter.IsNew) if (parameter.IsNew)
{ {
@ -584,11 +587,14 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
Span<WaveBuffer> waveBuffersSpan = WaveBuffers.AsSpan(); Span<WaveBuffer> waveBuffersSpan = WaveBuffers.AsSpan();
Span<WaveBufferInternal> pWaveBuffersSpan = parameter.WaveBuffers.AsSpan(); Span<WaveBufferInternal> pWaveBuffersSpan = parameter.WaveBuffers.AsSpan();
List<ErrorInfo> errorInfosList = [];
for (int i = 0; i < Constants.VoiceWaveBufferCount; i++) for (int i = 0; i < Constants.VoiceWaveBufferCount; i++)
{ {
UpdateWaveBuffer(errorInfos.AsSpan(i * 2, 2), ref waveBuffersSpan[i], ref pWaveBuffersSpan[i], parameter.SampleFormat, voiceState.IsWaveBufferValid[i], mapper, ref behaviourInfo); UpdateWaveBuffer(errorInfosList, ref waveBuffersSpan[i], ref pWaveBuffersSpan[i], parameter.SampleFormat, voiceState.IsWaveBufferValid[i], mapper, ref behaviourInfo);
} }
errorInfos = errorInfosList.ToArray();
} }
/// <summary> /// <summary>
@ -606,7 +612,7 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
PoolMapper mapper, PoolMapper mapper,
ref BehaviourInfo behaviourInfo) ref BehaviourInfo behaviourInfo)
{ {
errorInfos = new ErrorInfo[Constants.VoiceWaveBufferCount * 2];
if (parameter.IsNew) if (parameter.IsNew)
{ {
@ -622,11 +628,14 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
Span<WaveBuffer> waveBuffersSpan = WaveBuffers.AsSpan(); Span<WaveBuffer> waveBuffersSpan = WaveBuffers.AsSpan();
Span<WaveBufferInternal> pWaveBuffersSpan = parameter.WaveBuffers.AsSpan(); Span<WaveBufferInternal> pWaveBuffersSpan = parameter.WaveBuffers.AsSpan();
List<ErrorInfo> errorInfosList = [];
for (int i = 0; i < Constants.VoiceWaveBufferCount; i++) for (int i = 0; i < Constants.VoiceWaveBufferCount; i++)
{ {
UpdateWaveBuffer(errorInfos.AsSpan(i * 2, 2), ref waveBuffersSpan[i], ref pWaveBuffersSpan[i], parameter.SampleFormat, voiceState.IsWaveBufferValid[i], mapper, ref behaviourInfo); UpdateWaveBuffer(errorInfosList, ref waveBuffersSpan[i], ref pWaveBuffersSpan[i], parameter.SampleFormat, voiceState.IsWaveBufferValid[i], mapper, ref behaviourInfo);
} }
errorInfos = errorInfosList.ToArray();
} }
/// <summary> /// <summary>
@ -640,7 +649,7 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
/// <param name="mapper">The mapper to use.</param> /// <param name="mapper">The mapper to use.</param>
/// <param name="behaviourInfo">The behaviour context.</param> /// <param name="behaviourInfo">The behaviour context.</param>
private void UpdateWaveBuffer( private void UpdateWaveBuffer(
Span<ErrorInfo> errorInfos, List<ErrorInfo> errorInfos,
ref WaveBuffer waveBuffer, ref WaveBuffer waveBuffer,
ref WaveBufferInternal inputWaveBuffer, ref WaveBufferInternal inputWaveBuffer,
SampleFormat sampleFormat, SampleFormat sampleFormat,
@ -671,7 +680,10 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
BufferInfoUnmapped = !mapper.TryAttachBuffer(out ErrorInfo bufferInfoError, ref waveBuffer.BufferAddressInfo, inputWaveBuffer.Address, inputWaveBuffer.Size); BufferInfoUnmapped = !mapper.TryAttachBuffer(out ErrorInfo bufferInfoError, ref waveBuffer.BufferAddressInfo, inputWaveBuffer.Address, inputWaveBuffer.Size);
errorInfos[0] = bufferInfoError; if (bufferInfoError.ErrorCode != ResultCode.Success)
{
errorInfos.Add(bufferInfoError);
}
if (sampleFormat == SampleFormat.Adpcm && behaviourInfo.IsAdpcmLoopContextBugFixed() && inputWaveBuffer.ContextAddress != 0) if (sampleFormat == SampleFormat.Adpcm && behaviourInfo.IsAdpcmLoopContextBugFixed() && inputWaveBuffer.ContextAddress != 0)
{ {
@ -680,7 +692,10 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
inputWaveBuffer.ContextAddress, inputWaveBuffer.ContextAddress,
inputWaveBuffer.ContextSize); inputWaveBuffer.ContextSize);
errorInfos[1] = adpcmLoopContextInfoError; if (adpcmLoopContextInfoError.ErrorCode != ResultCode.Success)
{
errorInfos.Add(adpcmLoopContextInfoError);
}
if (!adpcmLoopContextMapped || BufferInfoUnmapped) if (!adpcmLoopContextMapped || BufferInfoUnmapped)
{ {
@ -698,8 +713,11 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
} }
else else
{ {
errorInfos[0].ErrorCode = ResultCode.InvalidAddressInfo; errorInfos.Add(new ErrorInfo
errorInfos[0].ExtraErrorInfo = inputWaveBuffer.Address; {
ErrorCode = ResultCode.InvalidAddressInfo,
ExtraErrorInfo = inputWaveBuffer.Address
});
} }
} }
} }
@ -891,7 +909,7 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
IsNew = false; IsNew = false;
} }
Memory<VoiceState>[] voiceStates = new Memory<VoiceState>[Constants.VoiceChannelCountMax]; Memory<VoiceState>[] voiceStates = voiceStatesPool.Allocate();
Span<int> channelResourceIdsSpan = ChannelResourceIds.AsSpan(); Span<int> channelResourceIdsSpan = ChannelResourceIds.AsSpan();
@ -900,7 +918,12 @@ namespace Ryujinx.Audio.Renderer.Server.Voice
voiceStates[i] = context.GetUpdateStateForDsp(channelResourceIdsSpan[i]); voiceStates[i] = context.GetUpdateStateForDsp(channelResourceIdsSpan[i]);
} }
return UpdateParametersForCommandGeneration(voiceStates); bool result = UpdateParametersForCommandGeneration(voiceStates);
voiceStatesPool.Release(voiceStates);
//might contain garbage data, but said data will never be accessed
return result;
} }
} }
} }

View file

@ -1,31 +0,0 @@
using Ryujinx.Common.Logging.Formatters;
using System;
using System.Text.Json.Serialization;
namespace Ryujinx.Common.Logging
{
internal class LogEventArgsJson
{
public LogLevel Level { get; }
public TimeSpan Time { get; }
public string ThreadName { get; }
public string Message { get; }
public string Data { get; }
[JsonConstructor]
public LogEventArgsJson(LogLevel level, TimeSpan time, string threadName, string message, string data = null)
{
Level = level;
Time = time;
ThreadName = threadName;
Message = message;
Data = data;
}
public static LogEventArgsJson FromLogEventArgs(LogEventArgs args)
{
return new LogEventArgsJson(args.Level, args.Time, args.ThreadName, args.Message, DynamicObjectFormatter.Format(args.Data));
}
}
}

View file

@ -1,9 +0,0 @@
using System.Text.Json.Serialization;
namespace Ryujinx.Common.Logging
{
[JsonSerializable(typeof(LogEventArgsJson))]
internal partial class LogEventJsonSerializerContext : JsonSerializerContext
{
}
}

View file

@ -230,14 +230,14 @@ namespace Ryujinx.Common.Logging
switch (logLevel) switch (logLevel)
{ {
#pragma warning disable IDE0055 // Disable formatting #pragma warning disable IDE0055 // Disable formatting
case LogLevel.Debug : Debug = enabled ? new Log(LogLevel.Debug) : new Log?(); break; case LogLevel.Debug : Debug = enabled ? new Log(LogLevel.Debug) : null; break;
case LogLevel.Info : Info = enabled ? new Log(LogLevel.Info) : new Log?(); break; case LogLevel.Info : Info = enabled ? new Log(LogLevel.Info) : null; break;
case LogLevel.Warning : Warning = enabled ? new Log(LogLevel.Warning) : new Log?(); break; case LogLevel.Warning : Warning = enabled ? new Log(LogLevel.Warning) : null; break;
case LogLevel.Error : Error = enabled ? new Log(LogLevel.Error) : new Log?(); break; case LogLevel.Error : Error = enabled ? new Log(LogLevel.Error) : null; break;
case LogLevel.Guest : Guest = enabled ? new Log(LogLevel.Guest) : new Log?(); break; case LogLevel.Guest : Guest = enabled ? new Log(LogLevel.Guest) : null; break;
case LogLevel.AccessLog : AccessLog = enabled ? new Log(LogLevel.AccessLog) : new Log?(); break; case LogLevel.AccessLog : AccessLog = enabled ? new Log(LogLevel.AccessLog) : null; break;
case LogLevel.Stub : Stub = enabled ? new Log(LogLevel.Stub) : new Log?(); break; case LogLevel.Stub : Stub = enabled ? new Log(LogLevel.Stub) : null; break;
case LogLevel.Trace : Trace = enabled ? new Log(LogLevel.Trace) : new Log?(); break; case LogLevel.Trace : Trace = enabled ? new Log(LogLevel.Trace) : null; break;
case LogLevel.Notice : break; case LogLevel.Notice : break;
default: throw new ArgumentException("Unknown Log Level", nameof(logLevel)); default: throw new ArgumentException("Unknown Log Level", nameof(logLevel));
#pragma warning restore IDE0055 #pragma warning restore IDE0055

View file

@ -1,42 +0,0 @@
using Ryujinx.Common.Utilities;
using System;
using System.IO;
namespace Ryujinx.Common.Logging.Targets
{
public class JsonLogTarget : ILogTarget
{
private readonly Stream _stream;
private readonly bool _leaveOpen;
private readonly string _name;
string ILogTarget.Name { get => _name; }
public JsonLogTarget(Stream stream, string name)
{
_stream = stream;
_name = name;
}
public JsonLogTarget(Stream stream, bool leaveOpen)
{
_stream = stream;
_leaveOpen = leaveOpen;
}
public void Log(object sender, LogEventArgs e)
{
LogEventArgsJson logEventArgsJson = LogEventArgsJson.FromLogEventArgs(e);
JsonHelper.SerializeToStream(_stream, logEventArgsJson, LogEventJsonSerializerContext.Default.LogEventArgsJson);
}
public void Dispose()
{
GC.SuppressFinalize(this);
if (!_leaveOpen)
{
_stream.Dispose();
}
}
}
}

View file

@ -1,67 +1,34 @@
using System; using System;
using System.Threading; using System.Collections.Concurrent;
namespace Ryujinx.Common namespace Ryujinx.Common
{ {
public class ObjectPool<T>(Func<T> factory, int size) public class ObjectPool<T>(Func<T> factory, int size = -1)
where T : class where T : class
{ {
private T _firstItem; private int _size = size;
private readonly T[] _items = new T[size - 1]; private readonly ConcurrentStack<T> _items = new();
public T Allocate() public T Allocate()
{ {
T instance = _firstItem; bool success = _items.TryPop(out T instance);
if (instance == null || instance != Interlocked.CompareExchange(ref _firstItem, null, instance)) if (!success)
{ {
instance = AllocateInternal(); instance = factory();
} }
return instance; return instance;
} }
private T AllocateInternal()
{
T[] items = _items;
for (int i = 0; i < items.Length; i++)
{
T instance = items[i];
if (instance != null && instance == Interlocked.CompareExchange(ref items[i], null, instance))
{
return instance;
}
}
return factory();
}
public void Release(T obj) public void Release(T obj)
{ {
if (_firstItem == null) if (_size < 0 || _items.Count < _size)
{ {
_firstItem = obj; _items.Push(obj);
}
else
{
ReleaseInternal(obj);
}
}
private void ReleaseInternal(T obj)
{
T[] items = _items;
for (int i = 0; i < items.Length; i++)
{
if (items[i] == null)
{
items[i] = obj;
break;
}
} }
} }
public void Clear() => _items.Clear();
} }
} }

View file

@ -1,19 +0,0 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
namespace Ryujinx.Common
{
public class ReferenceEqualityComparer<T> : IEqualityComparer<T>
where T : class
{
public bool Equals(T x, T y)
{
return x == y;
}
public int GetHashCode([DisallowNull] T obj)
{
return obj.GetHashCode();
}
}
}

View file

@ -1,10 +1,5 @@
using Ryujinx.Common.Utilities;
using System; using System;
using System.Net.Http;
using System.Net.Http.Json;
using System.Reflection; using System.Reflection;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
namespace Ryujinx.Common namespace Ryujinx.Common
{ {

View file

@ -1,6 +1,5 @@
using ARMeilleure.State; using ARMeilleure.State;
using System; using System;
using System.Threading;
namespace Ryujinx.Cpu namespace Ryujinx.Cpu
{ {

View file

@ -1,4 +1,3 @@
using ARMeilleure;
using ARMeilleure.Memory; using ARMeilleure.Memory;
using ARMeilleure.State; using ARMeilleure.State;
using System; using System;

View file

@ -1,5 +1,3 @@
using System.Diagnostics.CodeAnalysis;
namespace Ryujinx.Graphics.GAL namespace Ryujinx.Graphics.GAL
{ {
public enum ViewportSwizzle public enum ViewportSwizzle

View file

@ -1,5 +1,3 @@
using System.Diagnostics.CodeAnalysis;
namespace Ryujinx.Graphics.Gpu.Engine.Threed namespace Ryujinx.Graphics.Gpu.Engine.Threed
{ {
/// <summary> /// <summary>

View file

@ -1,4 +1,3 @@
using Ryujinx.Common.Memory;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Gpu.Engine.Types; using Ryujinx.Graphics.Gpu.Engine.Types;
using Ryujinx.Graphics.Gpu.Shader; using Ryujinx.Graphics.Gpu.Shader;

View file

@ -1,4 +1,3 @@
using Ryujinx.Common.Memory;
using Ryujinx.Graphics.Device; using Ryujinx.Graphics.Device;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Gpu.Engine.GPFifo; using Ryujinx.Graphics.Gpu.Engine.GPFifo;

View file

@ -1,6 +1,5 @@
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
namespace Ryujinx.Graphics.Gpu.Image namespace Ryujinx.Graphics.Gpu.Image
{ {

View file

@ -1,7 +1,6 @@
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using Ryujinx.Memory.Range; using Ryujinx.Memory.Range;
using System; using System;
using System.Collections.Generic;
namespace Ryujinx.Graphics.Gpu.Memory namespace Ryujinx.Graphics.Gpu.Memory
{ {

View file

@ -1,6 +1,5 @@
using Ryujinx.Memory.Range; using Ryujinx.Memory.Range;
using System; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
namespace Ryujinx.Graphics.Gpu.Memory namespace Ryujinx.Graphics.Gpu.Memory

View file

@ -1,5 +1,4 @@
using System; using System;
using System.Diagnostics.CodeAnalysis;
namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
{ {

View file

@ -1,5 +1,4 @@
using System; using System;
using System.Diagnostics.CodeAnalysis;
namespace Ryujinx.Graphics.Shader.IntermediateRepresentation namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
{ {

View file

@ -1,5 +1,4 @@
using System; using System;
using System.Diagnostics.CodeAnalysis;
namespace Ryujinx.Graphics.Shader.Translation namespace Ryujinx.Graphics.Shader.Translation
{ {

View file

@ -1,5 +1,4 @@
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Common.Memory;
using Ryujinx.Graphics.Texture; using Ryujinx.Graphics.Texture;
using Ryujinx.Graphics.Vic.Types; using Ryujinx.Graphics.Vic.Types;
using System; using System;

View file

@ -4,7 +4,6 @@ using Ryujinx.Graphics.Shader;
using Ryujinx.Graphics.Shader.Translation; using Ryujinx.Graphics.Shader.Translation;
using Silk.NET.Vulkan; using Silk.NET.Vulkan;
using System; using System;
using System.Collections.Generic;
using System.Numerics; using System.Numerics;
using Buffer = Silk.NET.Vulkan.Buffer; using Buffer = Silk.NET.Vulkan.Buffer;
using CompareOp = Ryujinx.Graphics.GAL.CompareOp; using CompareOp = Ryujinx.Graphics.GAL.CompareOp;

View file

@ -1,6 +1,5 @@
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using System; using System;
using System.Collections.Generic;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace Ryujinx.Graphics.Vulkan namespace Ryujinx.Graphics.Vulkan

View file

@ -1,12 +1,8 @@
using Gommon; using Gommon;
using JetBrains.Annotations;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.HLE.HOS.Kernel.Process;
using Ryujinx.HLE.HOS.Kernel.Threading;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text;
namespace Ryujinx.HLE.Debugger namespace Ryujinx.HLE.Debugger
{ {

View file

@ -5,7 +5,6 @@ using Ryujinx.HLE.HOS.Kernel.Process;
using Ryujinx.HLE.HOS.Kernel.Threading; using Ryujinx.HLE.HOS.Kernel.Threading;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Net.Sockets; using System.Net.Sockets;
using System.Threading; using System.Threading;

View file

@ -49,7 +49,7 @@ namespace Ryujinx.HLE.FileSystem
string ncaId = Convert.ToHexStringLower(entry.NcaId).Replace("-", null); string ncaId = Convert.ToHexStringLower(entry.NcaId).Replace("-", null);
Nca nca = _pfs.GetNca(keySet, $"/{ncaId}.nca"); Nca nca = _pfs.GetNca(keySet, $"/{ncaId}.nca");
if (nca.GetProgramIndex() == programIndex) if (nca.ProgramIndex == programIndex)
{ {
return nca; return nca;
} }

View file

@ -293,7 +293,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
KThread currentThread = KernelStatic.GetCurrentThread(); KThread currentThread = KernelStatic.GetCurrentThread();
KThread selectedThread = _state.SelectedThread; KThread selectedThread = _state.SelectedThread;
if (!currentThread.IsThreadNamed && string.IsNullOrEmpty(currentThread.GetThreadName())) if (!currentThread.IsThreadNamed && !string.IsNullOrEmpty(currentThread.GetThreadName()))
{ {
currentThread.HostThread.Name = $"<{currentThread.GetThreadName()}>"; currentThread.HostThread.Name = $"<{currentThread.GetThreadName()}>";
currentThread.IsThreadNamed = true; currentThread.IsThreadNamed = true;

View file

@ -36,7 +36,7 @@ namespace Ryujinx.HLE.Loaders.Processes.Extensions
public static ProcessResult Load(this IFileSystem exeFs, Switch device, BlitStruct<ApplicationControlProperty> nacpData, MetaLoader metaLoader, byte programIndex, bool isHomebrew = false) public static ProcessResult Load(this IFileSystem exeFs, Switch device, BlitStruct<ApplicationControlProperty> nacpData, MetaLoader metaLoader, byte programIndex, bool isHomebrew = false)
{ {
ulong programId = metaLoader.GetProgramId(); ulong programId = metaLoader.ProgramId;
// Replace the whole ExeFs partition by the modded one. // Replace the whole ExeFs partition by the modded one.
if (device.Configuration.VirtualFileSystem.ModLoader.ReplaceExefsPartition(programId, ref exeFs)) if (device.Configuration.VirtualFileSystem.ModLoader.ReplaceExefsPartition(programId, ref exeFs))
@ -118,13 +118,13 @@ namespace Ryujinx.HLE.Loaders.Processes.Extensions
modLoadResult.Hash, modLoadResult.Hash,
true, true,
programName, programName,
metaLoader.GetProgramId(), programId,
programIndex, programIndex,
null, null,
nsoExecutables); nsoExecutables);
// TODO: This should be stored using ProcessId instead. // TODO: This should be stored using ProcessId instead.
device.System.LibHacHorizonManager.ArpIReader.ApplicationId = new LibHac.ApplicationId(metaLoader.GetProgramId()); device.System.LibHacHorizonManager.ArpIReader.ApplicationId = new LibHac.ApplicationId(programId);
return processResult; return processResult;
} }

View file

@ -13,7 +13,7 @@ namespace Ryujinx.HLE.Loaders.Processes
{ {
MetaLoader metaLoader = exeFs.GetNpdm(); MetaLoader metaLoader = exeFs.GetNpdm();
BlitStruct<ApplicationControlProperty> nacpData = new(1); BlitStruct<ApplicationControlProperty> nacpData = new(1);
ulong programId = metaLoader.GetProgramId(); ulong programId = metaLoader.ProgramId;
device.Configuration.VirtualFileSystem.ModLoader.CollectMods([programId]); device.Configuration.VirtualFileSystem.ModLoader.CollectMods([programId]);

View file

@ -1,61 +1,15 @@
using LibHac.Common;
using LibHac.Fs;
using LibHac.Fs.Fsa;
using LibHac.Loader; using LibHac.Loader;
using LibHac.Util;
using Ryujinx.Common; using Ryujinx.Common;
using System;
namespace Ryujinx.HLE.Loaders.Processes.Extensions namespace Ryujinx.HLE.Loaders.Processes.Extensions
{ {
public static class MetaLoaderExtensions public static class MetaLoaderExtensions
{ {
public static ulong GetProgramId(this MetaLoader metaLoader)
{
metaLoader.GetNpdm(out LibHac.Loader.Npdm npdm).ThrowIfFailure();
return npdm.Aci.ProgramId.Value;
}
public static string GetProgramName(this MetaLoader metaLoader)
{
metaLoader.GetNpdm(out LibHac.Loader.Npdm npdm).ThrowIfFailure();
return StringUtils.Utf8ZToString(npdm.Meta.ProgramName);
}
public static bool IsProgram64Bit(this MetaLoader metaLoader)
{
metaLoader.GetNpdm(out LibHac.Loader.Npdm npdm).ThrowIfFailure();
return (npdm.Meta.Flags & 1) != 0;
}
public static void LoadDefault(this MetaLoader metaLoader) public static void LoadDefault(this MetaLoader metaLoader)
{ {
byte[] npdmBuffer = EmbeddedResources.Read("Ryujinx.HLE/Homebrew.npdm"); byte[] npdmBuffer = EmbeddedResources.Read("Ryujinx.HLE/Homebrew.npdm");
metaLoader.Load(npdmBuffer).ThrowIfFailure(); metaLoader.Load(npdmBuffer).ThrowIfFailure();
} }
public static void LoadFromFile(this MetaLoader metaLoader, IFileSystem fileSystem, string path = "")
{
if (string.IsNullOrEmpty(path))
{
path = ProcessConst.MainNpdmPath;
}
using UniqueRef<IFile> npdmFile = new();
fileSystem.OpenFile(ref npdmFile.Ref, path.ToU8Span(), OpenMode.Read).ThrowIfFailure();
npdmFile.Get.GetSize(out long fileSize).ThrowIfFailure();
Span<byte> npdmBuffer = new byte[fileSize];
npdmFile.Get.Read(out _, 0, npdmBuffer).ThrowIfFailure();
metaLoader.Load(npdmBuffer).ThrowIfFailure();
}
} }
} }

View file

@ -44,7 +44,7 @@ namespace Ryujinx.HLE.Loaders.Processes.Extensions
// Collecting mods related to AocTitleIds and ProgramId. // Collecting mods related to AocTitleIds and ProgramId.
device.Configuration.VirtualFileSystem.ModLoader.CollectMods( device.Configuration.VirtualFileSystem.ModLoader.CollectMods(
device.Configuration.ContentManager.GetAocTitleIds().Prepend(metaLoader.GetProgramId()), device.Configuration.ContentManager.GetAocTitleIds().Prepend(metaLoader.ProgramId),
ModLoader.GetModsBasePath(), ModLoader.GetModsBasePath(),
ModLoader.GetSdModsBasePath()); ModLoader.GetSdModsBasePath());
@ -74,7 +74,7 @@ namespace Ryujinx.HLE.Loaders.Processes.Extensions
*/ */
ProcessResult processResult = exeFs.Load(device, nacpData, metaLoader, (byte)nca.GetProgramIndex()); ProcessResult processResult = exeFs.Load(device, nacpData, metaLoader, (byte)nca.ProgramIndex);
// Load RomFS. // Load RomFS.
if (romFs == null) if (romFs == null)
@ -99,38 +99,6 @@ namespace Ryujinx.HLE.Loaders.Processes.Extensions
return processResult; return processResult;
} }
public static ulong GetProgramIdBase(this Nca nca)
{
return nca.Header.TitleId & ~0x1FFFUL;
}
public static int GetProgramIndex(this Nca nca)
{
return (int)(nca.Header.TitleId & 0xF);
}
public static bool IsProgram(this Nca nca)
{
return nca.Header.ContentType == NcaContentType.Program;
}
public static bool IsMain(this Nca nca)
{
return nca.IsProgram() && !nca.IsPatch();
}
public static bool IsPatch(this Nca nca)
{
int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program);
return nca.IsProgram() && nca.SectionExists(NcaSectionType.Data) && nca.Header.GetFsHeader(dataIndex).IsPatchSection();
}
public static bool IsControl(this Nca nca)
{
return nca.Header.ContentType == NcaContentType.Control;
}
public static (Nca, Nca) GetUpdateData(this Nca mainNca, VirtualFileSystem fileSystem, IntegrityCheckLevel checkLevel, int programIndex, out string updatePath) public static (Nca, Nca) GetUpdateData(this Nca mainNca, VirtualFileSystem fileSystem, IntegrityCheckLevel checkLevel, int programIndex, out string updatePath)
{ {
updatePath = null; updatePath = null;
@ -140,7 +108,7 @@ namespace Ryujinx.HLE.Loaders.Processes.Extensions
Nca updateControlNca = null; Nca updateControlNca = null;
// Clear the program index part. // Clear the program index part.
ulong titleIdBase = mainNca.GetProgramIdBase(); ulong titleIdBase = mainNca.ProgramIdBase;
// Load update information if exists. // Load update information if exists.
string titleUpdateMetadataPath = Path.Combine(AppDataManager.GamesDirPath, titleIdBase.ToString("x16"), "updates.json"); string titleUpdateMetadataPath = Path.Combine(AppDataManager.GamesDirPath, titleIdBase.ToString("x16"), "updates.json");

View file

@ -118,7 +118,7 @@ namespace Ryujinx.HLE.Loaders.Processes.Extensions
device.Configuration.ContentManager.ClearAocData(); device.Configuration.ContentManager.ClearAocData();
// Load DownloadableContents. // Load DownloadableContents.
string addOnContentMetadataPath = System.IO.Path.Combine(AppDataManager.GamesDirPath, mainNca.GetProgramIdBase().ToString("x16"), "dlc.json"); string addOnContentMetadataPath = System.IO.Path.Combine(AppDataManager.GamesDirPath, mainNca.ProgramIdBase.ToString("x16"), "dlc.json");
if (File.Exists(addOnContentMetadataPath)) if (File.Exists(addOnContentMetadataPath))
{ {
List<DownloadableContentContainer> dlcContainerList = JsonHelper.DeserializeFromFile(addOnContentMetadataPath, _contentSerializerContext.ListDownloadableContentContainer); List<DownloadableContentContainer> dlcContainerList = JsonHelper.DeserializeFromFile(addOnContentMetadataPath, _contentSerializerContext.ListDownloadableContentContainer);
@ -149,14 +149,5 @@ namespace Ryujinx.HLE.Loaders.Processes.Extensions
return (false, ProcessResult.Failed); return (false, ProcessResult.Failed);
} }
public static Nca GetNca(this IFileSystem fileSystem, KeySet keySet, string path)
{
using UniqueRef<IFile> ncaFile = new();
fileSystem.OpenFile(ref ncaFile.Ref, path.ToU8Span(), OpenMode.Read).ThrowIfFailure();
return new Nca(keySet, ncaFile.Release().AsStorage());
}
} }
} }

View file

@ -17,7 +17,6 @@ using Ryujinx.HLE.HOS.Kernel.Common;
using Ryujinx.HLE.HOS.Kernel.Memory; using Ryujinx.HLE.HOS.Kernel.Memory;
using Ryujinx.HLE.HOS.Kernel.Process; using Ryujinx.HLE.HOS.Kernel.Process;
using Ryujinx.HLE.Loaders.Executables; using Ryujinx.HLE.Loaders.Executables;
using Ryujinx.HLE.Loaders.Processes.Extensions;
using Ryujinx.Horizon.Common; using Ryujinx.Horizon.Common;
using Ryujinx.Horizon.Sdk.Arp; using Ryujinx.Horizon.Sdk.Arp;
using System; using System;
@ -44,12 +43,12 @@ namespace Ryujinx.HLE.Loaders.Processes
{ {
Nca nca = partitionFileSystem.GetNca(device.FileSystem.KeySet, fileEntry.FullPath); Nca nca = partitionFileSystem.GetNca(device.FileSystem.KeySet, fileEntry.FullPath);
if (!nca.IsProgram()) if (!nca.IsProgram)
{ {
continue; continue;
} }
ulong currentMainProgramId = nca.GetProgramIdBase(); ulong currentMainProgramId = nca.ProgramIdBase;
if (applicationId == 0 && currentMainProgramId != 0) if (applicationId == 0 && currentMainProgramId != 0)
{ {
@ -66,7 +65,7 @@ namespace Ryujinx.HLE.Loaders.Processes
break; break;
} }
hasIndex[nca.GetProgramIndex()] = true; hasIndex[nca.ProgramIndex] = true;
} }
if (programCount == 0) if (programCount == 0)
@ -365,7 +364,7 @@ namespace Ryujinx.HLE.Loaders.Processes
string displayVersion; string displayVersion;
if (metaLoader.GetProgramId() > 0x0100000000007FFF) if (metaLoader.ProgramId > 0x0100000000007FFF)
{ {
displayVersion = applicationControlProperties.Value.DisplayVersionString.ToString(); displayVersion = applicationControlProperties.Value.DisplayVersionString.ToString();
} }

View file

@ -52,7 +52,7 @@ namespace Ryujinx.HLE.Loaders.Processes
if (metaLoader is not null) if (metaLoader is not null)
{ {
ulong programId = metaLoader.GetProgramId(); ulong programId = metaLoader.ProgramId;
Name = ApplicationControlProperties.Title[(int)titleLanguage].NameString.ToString(); Name = ApplicationControlProperties.Title[(int)titleLanguage].NameString.ToString();
@ -70,7 +70,7 @@ namespace Ryujinx.HLE.Loaders.Processes
DisplayVersion = ApplicationControlProperties.DisplayVersionString.ToString(); DisplayVersion = ApplicationControlProperties.DisplayVersionString.ToString();
ProgramId = programId; ProgramId = programId;
ProgramIdText = $"{programId:x16}"; ProgramIdText = $"{programId:x16}";
Is64Bit = metaLoader.IsProgram64Bit(); Is64Bit = metaLoader.IsProgram64Bit;
} }
DiskCacheEnabled = diskCacheEnabled; DiskCacheEnabled = diskCacheEnabled;

View file

@ -1,6 +1,4 @@
using Ryujinx.Common.Configuration.Hid; using Ryujinx.Common.Configuration.Hid;
using Ryujinx.Common.Configuration.Hid.Controller;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Numerics; using System.Numerics;

View file

@ -1,7 +1,7 @@
using Ryujinx.Common;
using Ryujinx.Common.Collections; using Ryujinx.Common.Collections;
using Ryujinx.Common.Memory.PartialUnmaps; using Ryujinx.Common.Memory.PartialUnmaps;
using System; using System;
using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.Versioning; using System.Runtime.Versioning;
@ -9,24 +9,6 @@ using System.Threading;
namespace Ryujinx.Memory.WindowsShared namespace Ryujinx.Memory.WindowsShared
{ {
public class ObjectPool<T>
{
private readonly Stack<T> _objects;
private readonly Func<T> _objectGenerator;
public ObjectPool(Func<T> objectGenerator)
{
_objectGenerator = objectGenerator ?? throw new ArgumentNullException(nameof(objectGenerator));
_objects = new Stack<T>();
}
public T Get() => _objects.Count > 0 ? _objects.Pop() : _objectGenerator();
public void Return(T item) => _objects.Push(item);
public void Clear() => _objects.Clear();
}
/// <summary> /// <summary>
/// Windows memory placeholder manager. /// Windows memory placeholder manager.
/// </summary> /// </summary>
@ -97,7 +79,7 @@ namespace Ryujinx.Memory.WindowsShared
lock (_protections) lock (_protections)
{ {
_protections.Add(_protectionObjectPool.Get().Init(address, address + size, MemoryPermission.None)); _protections.Add(_protectionObjectPool.Allocate().Init(address, address + size, MemoryPermission.None));
} }
} }
@ -650,16 +632,16 @@ namespace Ryujinx.Memory.WindowsShared
{ {
if (startAddress > protAddress) if (startAddress > protAddress)
{ {
_protections.Add(_protectionObjectPool.Get().Init(protAddress, startAddress, protPermission)); _protections.Add(_protectionObjectPool.Allocate().Init(protAddress, startAddress, protPermission));
} }
if (endAddress < protEndAddress) if (endAddress < protEndAddress)
{ {
_protections.Add(_protectionObjectPool.Get().Init(endAddress, protEndAddress, protPermission)); _protections.Add(_protectionObjectPool.Allocate().Init(endAddress, protEndAddress, protPermission));
} }
} }
_protectionObjectPool.Return(protection); _protectionObjectPool.Release(protection);
if (node.End >= endAddress) if (node.End >= endAddress)
{ {
@ -667,7 +649,7 @@ namespace Ryujinx.Memory.WindowsShared
} }
} }
_protections.Add(_protectionObjectPool.Get().Init(startAddress, endAddress, permission)); _protections.Add(_protectionObjectPool.Allocate().Init(startAddress, endAddress, permission));
} }
} }
@ -698,15 +680,15 @@ namespace Ryujinx.Memory.WindowsShared
if (address > protAddress) if (address > protAddress)
{ {
_protections.Add(_protectionObjectPool.Get().Init(protAddress, address, protPermission)); _protections.Add(_protectionObjectPool.Allocate().Init(protAddress, address, protPermission));
} }
if (endAddress < protEndAddress) if (endAddress < protEndAddress)
{ {
_protections.Add(_protectionObjectPool.Get().Init(endAddress, protEndAddress, protPermission)); _protections.Add(_protectionObjectPool.Allocate().Init(endAddress, protEndAddress, protPermission));
} }
_protectionObjectPool.Return(protection); _protectionObjectPool.Release(protection);
if (node.End >= endAddress) if (node.End >= endAddress)
{ {

View file

@ -11,7 +11,6 @@ using Ryujinx.Memory;
using Ryujinx.Memory.Tracking; using Ryujinx.Memory.Tracking;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Runtime.Versioning; using System.Runtime.Versioning;

View file

@ -119,7 +119,6 @@ namespace Ryujinx.Ava
=> ProcessUnhandledException(sender, e.Exception, false); => ProcessUnhandledException(sender, e.Exception, false);
AppDomain.CurrentDomain.ProcessExit += (_, _) => Exit(); AppDomain.CurrentDomain.ProcessExit += (_, _) => Exit();
// Setup base data directory. // Setup base data directory.
AppDataManager.Initialize(CommandLineState.BaseDirPathArg); AppDataManager.Initialize(CommandLineState.BaseDirPathArg);

View file

@ -4,7 +4,6 @@ using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Threading; using Avalonia.Threading;
using DiscordRPC; using DiscordRPC;
using Gommon;
using LibHac.Common; using LibHac.Common;
using LibHac.Ns; using LibHac.Ns;
using Ryujinx.Audio.Backends.Dummy; using Ryujinx.Audio.Backends.Dummy;
@ -480,10 +479,7 @@ namespace Ryujinx.Ava.Systems
Dispatcher.UIThread.InvokeAsync(() => Dispatcher.UIThread.InvokeAsync(() =>
{ {
if (ConfigurationState.Instance.ShowOldUI) _viewModel.Title = TitleHelper.ActiveApplicationTitle(Device.Processes.ActiveApplication, Program.Version, !ConfigurationState.Instance.ShowOldUI);
{
_viewModel.Title = TitleHelper.ActiveApplicationTitle(Device.Processes.ActiveApplication, Program.Version, !ConfigurationState.Instance.ShowOldUI);
}
}); });
_viewModel.SetUiProgressHandlers(Device); _viewModel.SetUiProgressHandlers(Device);
@ -903,10 +899,7 @@ namespace Ryujinx.Ava.Systems
_viewModel.IsPaused = false; _viewModel.IsPaused = false;
_playTimer.Start(); _playTimer.Start();
if (ConfigurationState.Instance.ShowOldUI) _viewModel.Title = TitleHelper.ActiveApplicationTitle(Device?.Processes.ActiveApplication, Program.Version, !ConfigurationState.Instance.ShowOldUI);
{
_viewModel.Title = TitleHelper.ActiveApplicationTitle(Device?.Processes.ActiveApplication, Program.Version, !ConfigurationState.Instance.ShowOldUI);
}
Logger.Info?.Print(LogClass.Emulation, "Emulation was resumed"); Logger.Info?.Print(LogClass.Emulation, "Emulation was resumed");
} }
@ -916,10 +909,7 @@ namespace Ryujinx.Ava.Systems
_viewModel.IsPaused = true; _viewModel.IsPaused = true;
_playTimer.Stop(); _playTimer.Stop();
if (ConfigurationState.Instance.ShowOldUI) _viewModel.Title = TitleHelper.ActiveApplicationTitle(Device?.Processes.ActiveApplication, Program.Version, !ConfigurationState.Instance.ShowOldUI, LocaleManager.Instance[LocaleKeys.Paused]);
{
_viewModel.Title = TitleHelper.ActiveApplicationTitle(Device?.Processes.ActiveApplication, Program.Version, !ConfigurationState.Instance.ShowOldUI, LocaleManager.Instance[LocaleKeys.Paused]);
}
Logger.Info?.Print(LogClass.Emulation, "Emulation was paused"); Logger.Info?.Print(LogClass.Emulation, "Emulation was paused");
} }

View file

@ -1,7 +1,6 @@
using DynamicData; using DynamicData;
using DynamicData.Kernel; using DynamicData.Kernel;
using Gommon; using Gommon;
using LibHac;
using LibHac.Common; using LibHac.Common;
using LibHac.Fs; using LibHac.Fs;
using LibHac.Fs.Fsa; using LibHac.Fs.Fsa;
@ -469,7 +468,7 @@ namespace Ryujinx.Ava.Systems.AppLibrary
Nca nca = new(_virtualFileSystem.KeySet, new FileStream(applicationPath, FileMode.Open, FileAccess.Read).AsStorage()); Nca nca = new(_virtualFileSystem.KeySet, new FileStream(applicationPath, FileMode.Open, FileAccess.Read).AsStorage());
if (!nca.IsProgram() || nca.IsPatch()) if (!nca.IsProgram || nca.IsPatch)
{ {
return false; return false;
} }

View file

@ -1622,6 +1622,7 @@ namespace Ryujinx.Ava.UI.ViewModels
#if RELEASE #if RELEASE
await PerformanceCheck(); await PerformanceCheck();
#endif #endif
PreLaunchNotification();
Logger.RestartTime(); Logger.RestartTime();
@ -1855,6 +1856,48 @@ namespace Ryujinx.Ava.UI.ViewModels
} }
} }
/// <summary>
/// Show non-intrusive notifications for options that may cause side effects.
/// </summary>
public static void PreLaunchNotification()
{
if (ConfigurationState.Instance.Debug.DebuggerSuspendOnStart)
{
NotificationHelper.ShowInformation(
LocaleManager.Instance[LocaleKeys.NotificationLaunchCheckSuspendOnStartTitle],
LocaleManager.Instance[LocaleKeys.NotificationLaunchCheckSuspendOnStartMessage]);
}
if (ConfigurationState.Instance.Debug.EnableGdbStub)
{
NotificationHelper.ShowInformation(
LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.NotificationLaunchCheckGdbStubTitle, ConfigurationState.Instance.Debug.GdbStubPort.Value),
LocaleManager.Instance[LocaleKeys.NotificationLaunchCheckGdbStubMessage]);
}
if (ConfigurationState.Instance.System.DramSize.Value != MemoryConfiguration.MemoryConfiguration4GiB)
{
var memoryConfigurationLocaleKey = ConfigurationState.Instance.System.DramSize.Value switch
{
MemoryConfiguration.MemoryConfiguration4GiB or
MemoryConfiguration.MemoryConfiguration4GiBAppletDev or
MemoryConfiguration.MemoryConfiguration4GiBSystemDev => LocaleKeys.SettingsTabSystemDramSize4GiB,
MemoryConfiguration.MemoryConfiguration6GiB or
MemoryConfiguration.MemoryConfiguration6GiBAppletDev => LocaleKeys.SettingsTabSystemDramSize6GiB,
MemoryConfiguration.MemoryConfiguration8GiB => LocaleKeys.SettingsTabSystemDramSize8GiB,
MemoryConfiguration.MemoryConfiguration12GiB => LocaleKeys.SettingsTabSystemDramSize12GiB,
_ => LocaleKeys.SettingsTabSystemDramSize4GiB,
};
NotificationHelper.ShowWarning(
LocaleManager.Instance.UpdateAndGetDynamicValue(
LocaleKeys.NotificationLaunchCheckDramSizeTitle,
LocaleManager.Instance[memoryConfigurationLocaleKey]
),
LocaleManager.Instance[LocaleKeys.NotificationLaunchCheckDramSizeMessage]);
}
}
public async void ProcessTrimResult(String filename, XCIFileTrimmer.OperationOutcome operationOutcome) public async void ProcessTrimResult(String filename, XCIFileTrimmer.OperationOutcome operationOutcome)
{ {
string notifyUser = operationOutcome.ToLocalisedText(); string notifyUser = operationOutcome.ToLocalisedText();
@ -2308,24 +2351,23 @@ namespace Ryujinx.Ava.UI.ViewModels
Commands.CreateConditional<MainWindowViewModel>(vm => vm?.SelectedApplication != null, Commands.CreateConditional<MainWindowViewModel>(vm => vm?.SelectedApplication != null,
async viewModel => async viewModel =>
{ {
IReadOnlyList<IStorageFolder> result = await viewModel.StorageProvider.OpenFolderPickerAsync( Optional<IStorageFolder> resOpt = await viewModel.StorageProvider.OpenSingleFolderPickerAsync(
new FolderPickerOpenOptions new FolderPickerOpenOptions
{ {
Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle], Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle]
AllowMultiple = false,
}); });
if (result.Count == 0) if (!resOpt.TryGet(out IStorageFolder result))
return; return;
ApplicationHelper.ExtractSection( ApplicationHelper.ExtractSection(
result[0].Path.LocalPath, result.Path.LocalPath,
NcaSectionType.Logo, NcaSectionType.Logo,
viewModel.SelectedApplication.Path, viewModel.SelectedApplication.Path,
viewModel.SelectedApplication.Name); viewModel.SelectedApplication.Name);
IStorageFile iconFile = IStorageFile iconFile =
await result[0].CreateFileAsync($"{viewModel.SelectedApplication.IdString}.png"); await result.CreateFileAsync($"{viewModel.SelectedApplication.IdString}.png");
await using Stream fileStream = await iconFile.OpenWriteAsync(); await using Stream fileStream = await iconFile.OpenWriteAsync();
using SKBitmap bitmap = SKBitmap.Decode(viewModel.SelectedApplication.Icon) using SKBitmap bitmap = SKBitmap.Decode(viewModel.SelectedApplication.Icon)

View file

@ -139,15 +139,13 @@ namespace Ryujinx.Ava.UI.Windows
Executor.ExecuteBackgroundAsync(async () => Executor.ExecuteBackgroundAsync(async () =>
{ {
await ShowIntelMacWarningAsync(); await ShowIntelMacWarningAsync();
FilePath firmwarePath = CommandLineState.FirmwareToInstallPathArg; if (CommandLineState.FirmwareToInstallPathArg.TryGet(out FilePath fwPath))
if (firmwarePath is not null)
{ {
if ((firmwarePath.ExistsAsFile && firmwarePath.Extension is "xci" or "zip") || if (fwPath is { ExistsAsFile: true, Extension: "xci" or "zip" } || fwPath.ExistsAsDirectory)
firmwarePath.ExistsAsDirectory)
{ {
await Dispatcher.UIThread.InvokeAsync(() => await Dispatcher.UIThread.InvokeAsync(() =>
ViewModel.HandleFirmwareInstallation(firmwarePath)); ViewModel.HandleFirmwareInstallation(fwPath));
CommandLineState.FirmwareToInstallPathArg = null; CommandLineState.FirmwareToInstallPathArg = default;
} }
else else
Logger.Notice.Print(LogClass.UI, "Invalid firmware type provided. Path must be a directory, or a .zip or .xci file."); Logger.Notice.Print(LogClass.UI, "Invalid firmware type provided. Path must be a directory, or a .zip or .xci file.");

View file

@ -19,7 +19,7 @@ namespace Ryujinx.Ava.Utilities
public static string OverrideSystemLanguage { get; private set; } public static string OverrideSystemLanguage { get; private set; }
public static string OverrideHideCursor { get; private set; } public static string OverrideHideCursor { get; private set; }
public static string BaseDirPathArg { get; private set; } public static string BaseDirPathArg { get; private set; }
public static FilePath FirmwareToInstallPathArg { get; set; } public static Optional<FilePath> FirmwareToInstallPathArg { get; set; }
public static string Profile { get; private set; } public static string Profile { get; private set; }
public static string LaunchPathArg { get; private set; } public static string LaunchPathArg { get; private set; }
public static string LaunchApplicationId { get; private set; } public static string LaunchApplicationId { get; private set; }