From fd07453887fccd2be285ae26ad7db44505898113 Mon Sep 17 00:00:00 2001 From: LotP <22-lotp@users.noreply.git.ryujinx.app> Date: Sat, 25 Oct 2025 21:07:10 -0500 Subject: [PATCH 1/3] audio effects fix and audio object pooling (ryubing/ryujinx!192) See merge request ryubing/ryujinx!192 --- .../Command/AdpcmDataSourceCommandVersion1.cs | 27 +- .../Dsp/Command/AuxiliaryBufferCommand.cs | 29 ++- .../Dsp/Command/BiquadFilterAndMixCommand.cs | 33 ++- .../Dsp/Command/BiquadFilterCommand.cs | 19 +- .../Dsp/Command/CaptureBufferCommand.cs | 27 +- .../Dsp/Command/CircularBufferSinkCommand.cs | 20 +- .../Dsp/Command/ClearMixBufferCommand.cs | 11 +- .../Renderer/Dsp/Command/CommandList.cs | 7 +- .../Renderer/Dsp/Command/CompressorCommand.cs | 21 +- .../Dsp/Command/CopyMixBufferCommand.cs | 15 +- .../Dsp/Command/DataSourceVersion2Command.cs | 38 +-- .../Renderer/Dsp/Command/DelayCommand.cs | 21 +- .../Dsp/Command/DepopForMixBuffersCommand.cs | 19 +- .../Dsp/Command/DepopPrepareCommand.cs | 19 +- .../Renderer/Dsp/Command/DeviceSinkCommand.cs | 21 +- .../Command/DownMixSurroundToStereoCommand.cs | 17 +- .../Renderer/Dsp/Command/FillBufferCommand.cs | 39 +-- .../Dsp/Command/LimiterCommandVersion1.cs | 21 +- .../Dsp/Command/LimiterCommandVersion2.cs | 23 +- .../Renderer/Dsp/Command/MixCommand.cs | 17 +- .../Renderer/Dsp/Command/MixRampCommand.cs | 23 +- .../Dsp/Command/MixRampGroupedCommand.cs | 23 +- .../MultiTapBiquadFilterAndMixCommand.cs | 39 +-- .../Command/MultiTapBiquadFilterCommand.cs | 47 ++-- .../PcmFloatDataSourceCommandVersion1.cs | 27 +- .../PcmInt16DataSourceCommandVersion1.cs | 27 +- .../Dsp/Command/PerformanceCommand.cs | 18 +- .../Renderer/Dsp/Command/Reverb3dCommand.cs | 25 +- .../Renderer/Dsp/Command/ReverbCommand.cs | 23 +- .../Renderer/Dsp/Command/UpsampleCommand.cs | 23 +- .../Renderer/Dsp/Command/VolumeCommand.cs | 17 +- .../Renderer/Dsp/Command/VolumeRampCommand.cs | 19 +- .../Parameter/EffectInParameterVersion3.cs | 97 ------- .../Renderer/Server/CommandBuffer.cs | 236 +++++++++++++++--- .../Renderer/Server/CommandGenerator.cs | 16 +- .../Renderer/Server/Effect/BaseEffect.cs | 13 - .../Server/Effect/BiquadFilterEffect.cs | 15 +- .../Performance/PerformanceEntryAddresses.cs | 8 + .../Performance/PerformanceManagerGeneric.cs | 18 +- .../Renderer/Server/StateUpdater.cs | 64 +---- .../Renderer/Server/Voice/VoiceInfo.cs | 46 +++- src/Ryujinx.Common/Pools/ObjectPool.cs | 54 +--- .../HOS/Kernel/Threading/KScheduler.cs | 2 +- .../WindowsShared/PlaceholderManager.cs | 35 +-- 44 files changed, 764 insertions(+), 595 deletions(-) delete mode 100644 src/Ryujinx.Audio/Renderer/Parameter/EffectInParameterVersion3.cs diff --git a/src/Ryujinx.Audio/Renderer/Dsp/Command/AdpcmDataSourceCommandVersion1.cs b/src/Ryujinx.Audio/Renderer/Dsp/Command/AdpcmDataSourceCommandVersion1.cs index 60161ee7a..6993ce0b2 100644 --- a/src/Ryujinx.Audio/Renderer/Dsp/Command/AdpcmDataSourceCommandVersion1.cs +++ b/src/Ryujinx.Audio/Renderer/Dsp/Command/AdpcmDataSourceCommandVersion1.cs @@ -11,27 +11,32 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command { public bool Enabled { get; set; } - public int NodeId { get; } + public int NodeId { get; private set; } public CommandType CommandType => CommandType.AdpcmDataSourceVersion1; public uint EstimatedProcessingTime { get; set; } - public ushort OutputBufferIndex { get; } - public uint SampleRate { get; } + public ushort OutputBufferIndex { get; private set; } + public uint SampleRate { get; private set; } - public float Pitch { get; } + public float Pitch { get; private set; } public WaveBuffer[] WaveBuffers { get; } - public Memory State { get; } + public Memory State { get; private set; } - public ulong AdpcmParameter { get; } - public ulong AdpcmParameterSize { get; } + public ulong AdpcmParameter { get; private set; } + public ulong AdpcmParameterSize { get; private set; } - public DecodingBehaviour DecodingBehaviour { get; } + public DecodingBehaviour DecodingBehaviour { get; private set; } - public AdpcmDataSourceCommandVersion1(ref VoiceInfo serverInfo, Memory state, ushort outputBufferIndex, int nodeId) + public AdpcmDataSourceCommandVersion1() + { + WaveBuffers = new WaveBuffer[Constants.VoiceWaveBufferCount]; + } + + public AdpcmDataSourceCommandVersion1 Initialize(ref VoiceInfo serverInfo, Memory state, ushort outputBufferIndex, int nodeId) { Enabled = true; NodeId = nodeId; @@ -42,8 +47,6 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command Span waveBufferSpan = serverInfo.WaveBuffers.AsSpan(); - WaveBuffers = new WaveBuffer[Constants.VoiceWaveBufferCount]; - for (int i = 0; i < WaveBuffers.Length; i++) { ref Server.Voice.WaveBuffer voiceWaveBuffer = ref waveBufferSpan[i]; @@ -55,6 +58,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command AdpcmParameterSize = serverInfo.DataSourceStateAddressInfo.Size; State = state; DecodingBehaviour = serverInfo.DecodingBehaviour; + + return this; } public void Process(CommandList context) diff --git a/src/Ryujinx.Audio/Renderer/Dsp/Command/AuxiliaryBufferCommand.cs b/src/Ryujinx.Audio/Renderer/Dsp/Command/AuxiliaryBufferCommand.cs index 73d66dcf4..adc20cb4f 100644 --- a/src/Ryujinx.Audio/Renderer/Dsp/Command/AuxiliaryBufferCommand.cs +++ b/src/Ryujinx.Audio/Renderer/Dsp/Command/AuxiliaryBufferCommand.cs @@ -12,26 +12,31 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command { public bool Enabled { get; set; } - public int NodeId { get; } + public int NodeId { get; private set; } public CommandType CommandType => CommandType.AuxiliaryBuffer; public uint EstimatedProcessingTime { get; set; } - public uint InputBufferIndex { get; } - public uint OutputBufferIndex { get; } + public uint InputBufferIndex { get; private set; } + public uint OutputBufferIndex { get; private set; } - public AuxiliaryBufferAddresses BufferInfo { get; } + public AuxiliaryBufferAddresses BufferInfo { get; private set; } - public CpuAddress InputBuffer { get; } - public CpuAddress OutputBuffer { get; } - public uint CountMax { get; } - public uint UpdateCount { get; } - public uint WriteOffset { get; } + public CpuAddress InputBuffer { get; private set; } + public CpuAddress OutputBuffer { get; private set; } + public uint CountMax { get; private set; } + public uint UpdateCount { get; private set; } + 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, byte inputBufferOffset, byte outputBufferOffset, @@ -55,6 +60,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command UpdateCount = updateCount; WriteOffset = writeOffset; IsEffectEnabled = isEnabled; + + return this; } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/Ryujinx.Audio/Renderer/Dsp/Command/BiquadFilterAndMixCommand.cs b/src/Ryujinx.Audio/Renderer/Dsp/Command/BiquadFilterAndMixCommand.cs index 624c0d55b..6fb6ebdc9 100644 --- a/src/Ryujinx.Audio/Renderer/Dsp/Command/BiquadFilterAndMixCommand.cs +++ b/src/Ryujinx.Audio/Renderer/Dsp/Command/BiquadFilterAndMixCommand.cs @@ -9,32 +9,37 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command { public bool Enabled { get; set; } - public int NodeId { get; } + public int NodeId { get; private set; } public CommandType CommandType => CommandType.BiquadFilterAndMix; public uint EstimatedProcessingTime { get; set; } - public ushort InputBufferIndex { get; } - public ushort OutputBufferIndex { get; } + public ushort InputBufferIndex { get; private set; } + public ushort OutputBufferIndex { get; private set; } private BiquadFilterParameter2 _parameter; - public Memory BiquadFilterState { get; } - public Memory PreviousBiquadFilterState { get; } + public Memory BiquadFilterState { get; private set; } + public Memory PreviousBiquadFilterState { get; private set; } - public Memory State { get; } + public Memory State { get; private set; } - public int LastSampleIndex { get; } + public int LastSampleIndex { get; private set; } - public float Volume0 { get; } - public float Volume1 { get; } + public float Volume0 { get; private set; } + public float Volume1 { get; private set; } - public bool NeedInitialization { get; } - public bool HasVolumeRamp { get; } - public bool IsFirstMixBuffer { get; } + public bool NeedInitialization { get; private set; } + public bool HasVolumeRamp { get; private set; } + public bool IsFirstMixBuffer { get; private set; } - public BiquadFilterAndMixCommand( + public BiquadFilterAndMixCommand() + { + + } + + public BiquadFilterAndMixCommand Initialize( float volume0, float volume1, uint inputBufferIndex, @@ -68,6 +73,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command NeedInitialization = needInitialization; HasVolumeRamp = hasVolumeRamp; IsFirstMixBuffer = isFirstMixBuffer; + + return this; } public void Process(CommandList context) diff --git a/src/Ryujinx.Audio/Renderer/Dsp/Command/BiquadFilterCommand.cs b/src/Ryujinx.Audio/Renderer/Dsp/Command/BiquadFilterCommand.cs index a8c996428..496c83a58 100644 --- a/src/Ryujinx.Audio/Renderer/Dsp/Command/BiquadFilterCommand.cs +++ b/src/Ryujinx.Audio/Renderer/Dsp/Command/BiquadFilterCommand.cs @@ -8,20 +8,25 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command { public bool Enabled { get; set; } - public int NodeId { get; } + public int NodeId { get; private set; } public CommandType CommandType => CommandType.BiquadFilter; public uint EstimatedProcessingTime { get; set; } - public Memory BiquadFilterState { get; } - public int InputBufferIndex { get; } - public int OutputBufferIndex { get; } - public bool NeedInitialization { get; } + public Memory BiquadFilterState { get; private set; } + public int InputBufferIndex { get; private set; } + public int OutputBufferIndex { get; private set; } + public bool NeedInitialization { get; private set; } private BiquadFilterParameter2 _parameter; - public BiquadFilterCommand( + public BiquadFilterCommand() + { + + } + + public BiquadFilterCommand Initialize( int baseIndex, ref BiquadFilterParameter2 filter, Memory biquadFilterStateMemory, @@ -38,6 +43,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command Enabled = true; NodeId = nodeId; + + return this; } public void Process(CommandList context) diff --git a/src/Ryujinx.Audio/Renderer/Dsp/Command/CaptureBufferCommand.cs b/src/Ryujinx.Audio/Renderer/Dsp/Command/CaptureBufferCommand.cs index 01bff1e7d..a3b8b37da 100644 --- a/src/Ryujinx.Audio/Renderer/Dsp/Command/CaptureBufferCommand.cs +++ b/src/Ryujinx.Audio/Renderer/Dsp/Command/CaptureBufferCommand.cs @@ -12,25 +12,30 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command { public bool Enabled { get; set; } - public int NodeId { get; } + public int NodeId { get; private set; } public CommandType CommandType => CommandType.CaptureBuffer; public uint EstimatedProcessingTime { get; set; } - public uint InputBufferIndex { get; } + public uint InputBufferIndex { get; private set; } - public ulong CpuBufferInfoAddress { get; } - public ulong DspBufferInfoAddress { get; } + public ulong CpuBufferInfoAddress { get; private set; } + public ulong DspBufferInfoAddress { get; private set; } - public CpuAddress OutputBuffer { get; } - public uint CountMax { get; } - public uint UpdateCount { get; } - public uint WriteOffset { get; } + public CpuAddress OutputBuffer { get; private set; } + public uint CountMax { get; private set; } + public uint UpdateCount { get; private set; } + 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) { Enabled = true; @@ -43,6 +48,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command UpdateCount = updateCount; WriteOffset = writeOffset; IsEffectEnabled = isEnabled; + + return this; } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/Ryujinx.Audio/Renderer/Dsp/Command/CircularBufferSinkCommand.cs b/src/Ryujinx.Audio/Renderer/Dsp/Command/CircularBufferSinkCommand.cs index d5488b321..dc319e560 100644 --- a/src/Ryujinx.Audio/Renderer/Dsp/Command/CircularBufferSinkCommand.cs +++ b/src/Ryujinx.Audio/Renderer/Dsp/Command/CircularBufferSinkCommand.cs @@ -9,25 +9,29 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command { public bool Enabled { get; set; } - public int NodeId { get; } + public int NodeId { get; private set; } public CommandType CommandType => CommandType.CircularBufferSink; public uint EstimatedProcessingTime { get; set; } public ushort[] Input { get; } - public uint InputCount { get; } + public uint InputCount { get; private set; } - public ulong CircularBuffer { get; } - public ulong CircularBufferSize { get; } - public ulong CurrentOffset { get; } + public ulong CircularBuffer { get; private set; } + public ulong CircularBufferSize { get; private set; } + 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; NodeId = nodeId; - Input = new ushort[Constants.ChannelCountMax]; InputCount = parameter.InputCount; Span inputSpan = parameter.Input.AsSpan(); @@ -42,6 +46,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command CurrentOffset = currentOffset; Debug.Assert(CircularBuffer != 0); + + return this; } public void Process(CommandList context) diff --git a/src/Ryujinx.Audio/Renderer/Dsp/Command/ClearMixBufferCommand.cs b/src/Ryujinx.Audio/Renderer/Dsp/Command/ClearMixBufferCommand.cs index f0f85b0b2..b8a7efd1f 100644 --- a/src/Ryujinx.Audio/Renderer/Dsp/Command/ClearMixBufferCommand.cs +++ b/src/Ryujinx.Audio/Renderer/Dsp/Command/ClearMixBufferCommand.cs @@ -4,16 +4,23 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command { public bool Enabled { get; set; } - public int NodeId { get; } + public int NodeId { get; private set; } public CommandType CommandType => CommandType.ClearMixBuffer; public uint EstimatedProcessingTime { get; set; } - public ClearMixBufferCommand(int nodeId) + public ClearMixBufferCommand() + { + + } + + public ClearMixBufferCommand Initialize(int nodeId) { Enabled = true; NodeId = nodeId; + + return this; } public void Process(CommandList context) diff --git a/src/Ryujinx.Audio/Renderer/Dsp/Command/CommandList.cs b/src/Ryujinx.Audio/Renderer/Dsp/Command/CommandList.cs index 9abd6a18a..f29e8218e 100644 --- a/src/Ryujinx.Audio/Renderer/Dsp/Command/CommandList.cs +++ b/src/Ryujinx.Audio/Renderer/Dsp/Command/CommandList.cs @@ -20,6 +20,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command public Memory Buffers { get; } public uint BufferCount { get; } + private readonly static ObjectPool> CommandsListPool = new(() => new List(256)); public List Commands { get; } public IVirtualMemoryManager MemoryManager { get; } @@ -46,7 +47,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command SampleRate = sampleRate; BufferCount = mixBufferCount + voiceChannelCountMax; Buffers = mixBuffer; - Commands = []; + Commands = CommandsListPool.Allocate(); MemoryManager = memoryManager; _buffersEntryCount = Buffers.Length; @@ -142,6 +143,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command } } } + + CommandBuffer.ReleaseCommand(command); } EndTime = (ulong)PerformanceCounter.ElapsedNanoseconds; @@ -149,6 +152,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command public void Dispose() { + Commands.Clear(); + CommandsListPool.Release(Commands); GC.SuppressFinalize(this); _buffersMemoryHandle.Dispose(); } diff --git a/src/Ryujinx.Audio/Renderer/Dsp/Command/CompressorCommand.cs b/src/Ryujinx.Audio/Renderer/Dsp/Command/CompressorCommand.cs index a668155f8..0267ab239 100644 --- a/src/Ryujinx.Audio/Renderer/Dsp/Command/CompressorCommand.cs +++ b/src/Ryujinx.Audio/Renderer/Dsp/Command/CompressorCommand.cs @@ -15,22 +15,28 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command public bool Enabled { get; set; } - public int NodeId { get; } + public int NodeId { get; private set; } public CommandType CommandType => CommandType.Compressor; public uint EstimatedProcessingTime { get; set; } public CompressorParameter Parameter => _parameter; - public Memory State { get; } - public Memory ResultState { get; } + public Memory State { get; private set; } + public Memory ResultState { get; private set; } public ushort[] OutputBufferIndices { get; } public ushort[] InputBufferIndices { get; } - public bool IsEffectEnabled { get; } + public bool IsEffectEnabled { get; private set; } private CompressorParameter _parameter; - public CompressorCommand(uint bufferOffset, CompressorParameter parameter, Memory state, Memory 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 state, Memory resultState, bool isEnabled, int nodeId) { Enabled = true; NodeId = nodeId; @@ -39,9 +45,6 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command ResultState = resultState; IsEffectEnabled = isEnabled; - - InputBufferIndices = new ushort[Constants.VoiceChannelCountMax]; - OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax]; Span inputSpan = _parameter.Input.AsSpan(); Span outputSpan = _parameter.Output.AsSpan(); @@ -51,6 +54,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command InputBufferIndices[i] = (ushort)(bufferOffset + inputSpan[i]); OutputBufferIndices[i] = (ushort)(bufferOffset + outputSpan[i]); } + + return this; } public void Process(CommandList context) diff --git a/src/Ryujinx.Audio/Renderer/Dsp/Command/CopyMixBufferCommand.cs b/src/Ryujinx.Audio/Renderer/Dsp/Command/CopyMixBufferCommand.cs index 3f6aa8390..5fc8e7258 100644 --- a/src/Ryujinx.Audio/Renderer/Dsp/Command/CopyMixBufferCommand.cs +++ b/src/Ryujinx.Audio/Renderer/Dsp/Command/CopyMixBufferCommand.cs @@ -4,22 +4,29 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command { public bool Enabled { get; set; } - public int NodeId { get; } + public int NodeId { get; private set; } public CommandType CommandType => CommandType.CopyMixBuffer; public uint EstimatedProcessingTime { get; set; } - public ushort InputBufferIndex { get; } - public ushort OutputBufferIndex { get; } + public ushort InputBufferIndex { get; private set; } + 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; NodeId = nodeId; InputBufferIndex = (ushort)inputBufferIndex; OutputBufferIndex = (ushort)outputBufferIndex; + + return this; } public void Process(CommandList context) diff --git a/src/Ryujinx.Audio/Renderer/Dsp/Command/DataSourceVersion2Command.cs b/src/Ryujinx.Audio/Renderer/Dsp/Command/DataSourceVersion2Command.cs index 1fbd95c32..8b72687da 100644 --- a/src/Ryujinx.Audio/Renderer/Dsp/Command/DataSourceVersion2Command.cs +++ b/src/Ryujinx.Audio/Renderer/Dsp/Command/DataSourceVersion2Command.cs @@ -3,6 +3,7 @@ using Ryujinx.Audio.Renderer.Common; using Ryujinx.Audio.Renderer.Server.Voice; using System; using Ryujinx.Audio.Renderer.Parameter; +using Ryujinx.Memory; using WaveBuffer = Ryujinx.Audio.Renderer.Common.WaveBuffer; namespace Ryujinx.Audio.Renderer.Dsp.Command @@ -11,35 +12,40 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command { 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 ushort OutputBufferIndex { get; } - public uint SampleRate { get; } + public ushort OutputBufferIndex { get; private set; } + public uint SampleRate { get; private set; } - public float Pitch { get; } + public float Pitch { get; private set; } public WaveBuffer[] WaveBuffers { get; } - public Memory State { get; } + public Memory State { get; private set; } - public ulong ExtraParameter { get; } - public ulong ExtraParameterSize { get; } + public ulong ExtraParameter { get; private set; } + 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 state, ushort outputBufferIndex, ushort channelIndex, int nodeId) + public DataSourceVersion2Command() + { + WaveBuffers = new WaveBuffer[Constants.VoiceWaveBufferCount]; + } + + public DataSourceVersion2Command Initialize(ref VoiceInfo serverInfo, Memory state, ushort outputBufferIndex, ushort channelIndex, int nodeId) { Enabled = true; NodeId = nodeId; @@ -55,8 +61,6 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command Span waveBufferSpan = serverInfo.WaveBuffers.AsSpan(); - WaveBuffers = new WaveBuffer[Constants.VoiceWaveBufferCount]; - for (int i = 0; i < WaveBuffers.Length; i++) { ref Server.Voice.WaveBuffer voiceWaveBuffer = ref waveBufferSpan[i]; @@ -72,6 +76,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command State = state; DecodingBehaviour = serverInfo.DecodingBehaviour; + + return this; } private static CommandType GetCommandTypeBySampleFormat(SampleFormat sampleFormat) diff --git a/src/Ryujinx.Audio/Renderer/Dsp/Command/DelayCommand.cs b/src/Ryujinx.Audio/Renderer/Dsp/Command/DelayCommand.cs index 491233770..295278dc6 100644 --- a/src/Ryujinx.Audio/Renderer/Dsp/Command/DelayCommand.cs +++ b/src/Ryujinx.Audio/Renderer/Dsp/Command/DelayCommand.cs @@ -13,24 +13,30 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command { public bool Enabled { get; set; } - public int NodeId { get; } + public int NodeId { get; private set; } public CommandType CommandType => CommandType.Delay; public uint EstimatedProcessingTime { get; set; } public DelayParameter Parameter => _parameter; - public Memory State { get; } - public ulong WorkBuffer { get; } + public Memory State { get; private set; } + public ulong WorkBuffer { get; private set; } public ushort[] OutputBufferIndices { get; } public ushort[] InputBufferIndices { get; } - public bool IsEffectEnabled { get; } + public bool IsEffectEnabled { get; private set; } private DelayParameter _parameter; private const int FixedPointPrecision = 14; - public DelayCommand(uint bufferOffset, DelayParameter parameter, Memory 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 state, bool isEnabled, ulong workBuffer, int nodeId, bool newEffectChannelMappingSupported) { Enabled = true; NodeId = nodeId; @@ -39,9 +45,6 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command WorkBuffer = workBuffer; IsEffectEnabled = isEnabled; - - InputBufferIndices = new ushort[Constants.VoiceChannelCountMax]; - OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax]; Span inputSpan = Parameter.Input.AsSpan(); Span outputSpan = Parameter.Output.AsSpan(); @@ -54,6 +57,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command DataSourceHelper.RemapLegacyChannelEffectMappingToChannelResourceMapping(newEffectChannelMappingSupported, InputBufferIndices, Parameter.ChannelCount); DataSourceHelper.RemapLegacyChannelEffectMappingToChannelResourceMapping(newEffectChannelMappingSupported, OutputBufferIndices, Parameter.ChannelCount); + + return this; } [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] diff --git a/src/Ryujinx.Audio/Renderer/Dsp/Command/DepopForMixBuffersCommand.cs b/src/Ryujinx.Audio/Renderer/Dsp/Command/DepopForMixBuffersCommand.cs index ff38f38ca..6986043c7 100644 --- a/src/Ryujinx.Audio/Renderer/Dsp/Command/DepopForMixBuffersCommand.cs +++ b/src/Ryujinx.Audio/Renderer/Dsp/Command/DepopForMixBuffersCommand.cs @@ -7,21 +7,26 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command { public bool Enabled { get; set; } - public int NodeId { get; } + public int NodeId { get; private set; } public CommandType CommandType => CommandType.DepopForMixBuffers; 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 DepopBuffer { get; } + public Memory DepopBuffer { get; private set; } - public DepopForMixBuffersCommand(Memory depopBuffer, uint bufferOffset, uint mixBufferCount, int nodeId, uint sampleRate) + public DepopForMixBuffersCommand() + { + + } + + public DepopForMixBuffersCommand Initialize(Memory depopBuffer, uint bufferOffset, uint mixBufferCount, int nodeId, uint sampleRate) { Enabled = true; NodeId = nodeId; @@ -37,6 +42,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command { Decay = 0.943695f; } + + return this; } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/Ryujinx.Audio/Renderer/Dsp/Command/DepopPrepareCommand.cs b/src/Ryujinx.Audio/Renderer/Dsp/Command/DepopPrepareCommand.cs index 18ae11eb4..24af18ea5 100644 --- a/src/Ryujinx.Audio/Renderer/Dsp/Command/DepopPrepareCommand.cs +++ b/src/Ryujinx.Audio/Renderer/Dsp/Command/DepopPrepareCommand.cs @@ -7,27 +7,30 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command { public bool Enabled { get; set; } - public int NodeId { get; } + public int NodeId { get; private set; } public CommandType CommandType => CommandType.DepopPrepare; public uint EstimatedProcessingTime { get; set; } - public uint MixBufferCount { get; } + public uint MixBufferCount { get; private set; } public ushort[] OutputBufferIndices { get; } - public Memory State { get; } - public Memory DepopBuffer { get; } + public Memory State { get; private set; } + public Memory DepopBuffer { get; private set; } - public DepopPrepareCommand(Memory state, Memory depopBuffer, uint mixBufferCount, uint bufferOffset, int nodeId, bool enabled) + public DepopPrepareCommand() + { + OutputBufferIndices = new ushort[Constants.MixBufferCountMax]; + } + + public DepopPrepareCommand Initialize(Memory state, Memory depopBuffer, uint mixBufferCount, uint bufferOffset, int nodeId, bool enabled) { Enabled = enabled; NodeId = nodeId; MixBufferCount = mixBufferCount; - OutputBufferIndices = new ushort[Constants.MixBufferCountMax]; - for (int i = 0; i < Constants.MixBufferCountMax; i++) { OutputBufferIndices[i] = (ushort)(bufferOffset + i); @@ -35,6 +38,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command State = state; DepopBuffer = depopBuffer; + + return this; } public void Process(CommandList context) diff --git a/src/Ryujinx.Audio/Renderer/Dsp/Command/DeviceSinkCommand.cs b/src/Ryujinx.Audio/Renderer/Dsp/Command/DeviceSinkCommand.cs index b0e4b3c99..aeb187b41 100644 --- a/src/Ryujinx.Audio/Renderer/Dsp/Command/DeviceSinkCommand.cs +++ b/src/Ryujinx.Audio/Renderer/Dsp/Command/DeviceSinkCommand.cs @@ -10,22 +10,27 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command { public bool Enabled { get; set; } - public int NodeId { get; } + public int NodeId { get; private set; } public CommandType CommandType => CommandType.DeviceSink; 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 ushort[] InputBufferIndices { get; } + public uint InputCount { get; private set; } + public ushort[] InputBufferIndices { get; private set; } - public Memory Buffers { get; } + public Memory Buffers { get; private set; } - public DeviceSinkCommand(uint bufferOffset, DeviceSink sink, int sessionId, Memory buffers, int nodeId) + public DeviceSinkCommand() + { + + } + + public DeviceSinkCommand Initialize(uint bufferOffset, DeviceSink sink, int sessionId, Memory buffers, int nodeId) { Enabled = true; NodeId = nodeId; @@ -50,6 +55,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command { Buffers = buffers; } + + return this; } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/Ryujinx.Audio/Renderer/Dsp/Command/DownMixSurroundToStereoCommand.cs b/src/Ryujinx.Audio/Renderer/Dsp/Command/DownMixSurroundToStereoCommand.cs index 8997b0dbd..751954fc8 100644 --- a/src/Ryujinx.Audio/Renderer/Dsp/Command/DownMixSurroundToStereoCommand.cs +++ b/src/Ryujinx.Audio/Renderer/Dsp/Command/DownMixSurroundToStereoCommand.cs @@ -7,7 +7,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command { public bool Enabled { get; set; } - public int NodeId { get; } + public int NodeId { get; private set; } public CommandType CommandType => CommandType.DownMixSurroundToStereo; @@ -16,16 +16,19 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command public ushort[] InputBufferIndices { get; } public ushort[] OutputBufferIndices { get; } - public float[] Coefficients { get; } + public float[] Coefficients { get; private set; } - public DownMixSurroundToStereoCommand(uint bufferOffset, Span inputBufferOffset, Span outputBufferOffset, float[] downMixParameter, int nodeId) + public DownMixSurroundToStereoCommand() + { + InputBufferIndices = new ushort[Constants.VoiceChannelCountMax]; + OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax]; + } + + public DownMixSurroundToStereoCommand Initialize(uint bufferOffset, Span inputBufferOffset, Span outputBufferOffset, float[] downMixParameter, int nodeId) { Enabled = true; NodeId = nodeId; - InputBufferIndices = new ushort[Constants.VoiceChannelCountMax]; - OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax]; - for (int i = 0; i < Constants.VoiceChannelCountMax; i++) { InputBufferIndices[i] = (ushort)(bufferOffset + inputBufferOffset[i]); @@ -33,6 +36,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command } Coefficients = downMixParameter; + + return this; } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/Ryujinx.Audio/Renderer/Dsp/Command/FillBufferCommand.cs b/src/Ryujinx.Audio/Renderer/Dsp/Command/FillBufferCommand.cs index ca5428c56..15ccd5239 100644 --- a/src/Ryujinx.Audio/Renderer/Dsp/Command/FillBufferCommand.cs +++ b/src/Ryujinx.Audio/Renderer/Dsp/Command/FillBufferCommand.cs @@ -8,38 +8,43 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command { public bool Enabled { get; set; } - public int NodeId { get; } + public int NodeId { get; private set; } public CommandType CommandType => CommandType.FillBuffer; public uint EstimatedProcessingTime { get; set; } - public SplitterDestinationVersion1 Destination1 { get; } - public SplitterDestinationVersion2 Destination2 { get; } - public bool IsV2 { get; } - public int Length { get; } - public float Value { get; } + public SplitterDestinationVersion1 Destination1 { get; private set; } + public SplitterDestinationVersion2 Destination2 { get; private set; } + public bool IsV2 { get; private set; } + public int Length { get; private set; } + 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; 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; Value = value; + + return this; } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/Ryujinx.Audio/Renderer/Dsp/Command/LimiterCommandVersion1.cs b/src/Ryujinx.Audio/Renderer/Dsp/Command/LimiterCommandVersion1.cs index b0a0183f8..115f494d2 100644 --- a/src/Ryujinx.Audio/Renderer/Dsp/Command/LimiterCommandVersion1.cs +++ b/src/Ryujinx.Audio/Renderer/Dsp/Command/LimiterCommandVersion1.cs @@ -10,22 +10,28 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command { public bool Enabled { get; set; } - public int NodeId { get; } + public int NodeId { get; private set; } public CommandType CommandType => CommandType.LimiterVersion1; public uint EstimatedProcessingTime { get; set; } public LimiterParameter Parameter => _parameter; - public Memory State { get; } - public ulong WorkBuffer { get; } + public Memory State { get; private set; } + public ulong WorkBuffer { get; private set; } public ushort[] OutputBufferIndices { get; } public ushort[] InputBufferIndices { get; } - public bool IsEffectEnabled { get; } + public bool IsEffectEnabled { get; private set; } private LimiterParameter _parameter; - public LimiterCommandVersion1(uint bufferOffset, LimiterParameter parameter, Memory 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 state, bool isEnabled, ulong workBuffer, int nodeId) { Enabled = true; NodeId = nodeId; @@ -35,9 +41,6 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command IsEffectEnabled = isEnabled; - InputBufferIndices = new ushort[Constants.VoiceChannelCountMax]; - OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax]; - Span inputSpan = _parameter.Input.AsSpan(); Span outputSpan = _parameter.Output.AsSpan(); @@ -46,6 +49,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command InputBufferIndices[i] = (ushort)(bufferOffset + inputSpan[i]); OutputBufferIndices[i] = (ushort)(bufferOffset + outputSpan[i]); } + + return this; } public void Process(CommandList context) diff --git a/src/Ryujinx.Audio/Renderer/Dsp/Command/LimiterCommandVersion2.cs b/src/Ryujinx.Audio/Renderer/Dsp/Command/LimiterCommandVersion2.cs index 36cc0e768..f00529925 100644 --- a/src/Ryujinx.Audio/Renderer/Dsp/Command/LimiterCommandVersion2.cs +++ b/src/Ryujinx.Audio/Renderer/Dsp/Command/LimiterCommandVersion2.cs @@ -12,23 +12,29 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command { public bool Enabled { get; set; } - public int NodeId { get; } + public int NodeId { get; private set; } public CommandType CommandType => CommandType.LimiterVersion2; public uint EstimatedProcessingTime { get; set; } public LimiterParameter Parameter => _parameter; - public Memory State { get; } - public Memory ResultState { get; } - public ulong WorkBuffer { get; } + public Memory State { get; private set; } + public Memory ResultState { get; private set; } + public ulong WorkBuffer { get; private set; } public ushort[] OutputBufferIndices { get; } public ushort[] InputBufferIndices { get; } - public bool IsEffectEnabled { get; } + public bool IsEffectEnabled { get; private set; } private LimiterParameter _parameter; - public LimiterCommandVersion2( + public LimiterCommandVersion2() + { + InputBufferIndices = new ushort[Constants.VoiceChannelCountMax]; + OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax]; + } + + public LimiterCommandVersion2 Initialize( uint bufferOffset, LimiterParameter parameter, Memory state, @@ -45,9 +51,6 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command WorkBuffer = workBuffer; IsEffectEnabled = isEnabled; - - InputBufferIndices = new ushort[Constants.VoiceChannelCountMax]; - OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax]; Span inputSpan = _parameter.Input.AsSpan(); Span outputSpan = _parameter.Output.AsSpan(); @@ -57,6 +60,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command InputBufferIndices[i] = (ushort)(bufferOffset + inputSpan[i]); OutputBufferIndices[i] = (ushort)(bufferOffset + outputSpan[i]); } + + return this; } public void Process(CommandList context) diff --git a/src/Ryujinx.Audio/Renderer/Dsp/Command/MixCommand.cs b/src/Ryujinx.Audio/Renderer/Dsp/Command/MixCommand.cs index c701f80eb..0dca27bca 100644 --- a/src/Ryujinx.Audio/Renderer/Dsp/Command/MixCommand.cs +++ b/src/Ryujinx.Audio/Renderer/Dsp/Command/MixCommand.cs @@ -11,18 +11,23 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command { public bool Enabled { get; set; } - public int NodeId { get; } + public int NodeId { get; private set; } public CommandType CommandType => CommandType.Mix; public uint EstimatedProcessingTime { get; set; } - public ushort InputBufferIndex { get; } - public ushort OutputBufferIndex { get; } + public ushort InputBufferIndex { get; private set; } + 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; NodeId = nodeId; @@ -31,6 +36,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command OutputBufferIndex = (ushort)outputBufferIndex; Volume = volume; + + return this; } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/Ryujinx.Audio/Renderer/Dsp/Command/MixRampCommand.cs b/src/Ryujinx.Audio/Renderer/Dsp/Command/MixRampCommand.cs index 6c5f7628c..be6aec5a6 100644 --- a/src/Ryujinx.Audio/Renderer/Dsp/Command/MixRampCommand.cs +++ b/src/Ryujinx.Audio/Renderer/Dsp/Command/MixRampCommand.cs @@ -8,23 +8,28 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command { public bool Enabled { get; set; } - public int NodeId { get; } + public int NodeId { get; private set; } public CommandType CommandType => CommandType.MixRamp; public uint EstimatedProcessingTime { get; set; } - public ushort InputBufferIndex { get; } - public ushort OutputBufferIndex { get; } + public ushort InputBufferIndex { get; private set; } + public ushort OutputBufferIndex { get; private set; } - public float Volume0 { get; } - public float Volume1 { get; } + public float Volume0 { get; private set; } + public float Volume1 { get; private set; } - public Memory State { get; } + public Memory 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 state, int nodeId) + public MixRampCommand() + { + + } + + public MixRampCommand Initialize(float volume0, float volume1, uint inputBufferIndex, uint outputBufferIndex, int lastSampleIndex, Memory state, int nodeId) { Enabled = true; NodeId = nodeId; @@ -37,6 +42,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command State = state; LastSampleIndex = lastSampleIndex; + + return this; } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/Ryujinx.Audio/Renderer/Dsp/Command/MixRampGroupedCommand.cs b/src/Ryujinx.Audio/Renderer/Dsp/Command/MixRampGroupedCommand.cs index 0d732c3fa..b08a78ee6 100644 --- a/src/Ryujinx.Audio/Renderer/Dsp/Command/MixRampGroupedCommand.cs +++ b/src/Ryujinx.Audio/Renderer/Dsp/Command/MixRampGroupedCommand.cs @@ -8,23 +8,28 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command { public bool Enabled { get; set; } - public int NodeId { get; } + public int NodeId { get; private set; } public CommandType CommandType => CommandType.MixRampGrouped; public uint EstimatedProcessingTime { get; set; } - public uint MixBufferCount { get; } + public uint MixBufferCount { get; private set; } - public ushort[] InputBufferIndices { get; } - public ushort[] OutputBufferIndices { get; } + public ushort[] InputBufferIndices { get; private set; } + public ushort[] OutputBufferIndices { get; private set; } - public float[] Volume0 { get; } - public float[] Volume1 { get; } + public float[] Volume0 { get; private set; } + public float[] Volume1 { get; private set; } - public Memory State { get; } + public Memory State { get; private set; } - public MixRampGroupedCommand( + public MixRampGroupedCommand() + { + + } + + public MixRampGroupedCommand Initialize( uint mixBufferCount, uint inputBufferIndex, uint outputBufferIndex, @@ -52,6 +57,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command } State = state; + + return this; } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/Ryujinx.Audio/Renderer/Dsp/Command/MultiTapBiquadFilterAndMixCommand.cs b/src/Ryujinx.Audio/Renderer/Dsp/Command/MultiTapBiquadFilterAndMixCommand.cs index ee28ce2fb..6cc6b4897 100644 --- a/src/Ryujinx.Audio/Renderer/Dsp/Command/MultiTapBiquadFilterAndMixCommand.cs +++ b/src/Ryujinx.Audio/Renderer/Dsp/Command/MultiTapBiquadFilterAndMixCommand.cs @@ -9,36 +9,41 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command { public bool Enabled { get; set; } - public int NodeId { get; } + public int NodeId { get; private set; } public CommandType CommandType => CommandType.MultiTapBiquadFilterAndMix; public uint EstimatedProcessingTime { get; set; } - public ushort InputBufferIndex { get; } - public ushort OutputBufferIndex { get; } + public ushort InputBufferIndex { get; private set; } + public ushort OutputBufferIndex { get; private set; } private BiquadFilterParameter2 _parameter0; private BiquadFilterParameter2 _parameter1; - public Memory BiquadFilterState0 { get; } - public Memory BiquadFilterState1 { get; } - public Memory PreviousBiquadFilterState0 { get; } - public Memory PreviousBiquadFilterState1 { get; } + public Memory BiquadFilterState0 { get; private set; } + public Memory BiquadFilterState1 { get; private set; } + public Memory PreviousBiquadFilterState0 { get; private set; } + public Memory PreviousBiquadFilterState1 { get; private set; } - public Memory State { get; } + public Memory State { get; private set; } - public int LastSampleIndex { get; } + public int LastSampleIndex { get; private set; } - public float Volume0 { get; } - public float Volume1 { get; } + public float Volume0 { get; private set; } + public float Volume1 { get; private set; } - public bool NeedInitialization0 { get; } - public bool NeedInitialization1 { get; } - public bool HasVolumeRamp { get; } - public bool IsFirstMixBuffer { get; } + public bool NeedInitialization0 { get; private set; } + public bool NeedInitialization1 { get; private set; } + public bool HasVolumeRamp { get; private set; } + public bool IsFirstMixBuffer { get; private set; } - public MultiTapBiquadFilterAndMixCommand( + public MultiTapBiquadFilterAndMixCommand() + { + + } + + public MultiTapBiquadFilterAndMixCommand Initialize( float volume0, float volume1, uint inputBufferIndex, @@ -80,6 +85,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command NeedInitialization1 = needInitialization1; HasVolumeRamp = hasVolumeRamp; IsFirstMixBuffer = isFirstMixBuffer; + + return this; } private void UpdateState(Memory state, Memory previousState, bool needInitialization) diff --git a/src/Ryujinx.Audio/Renderer/Dsp/Command/MultiTapBiquadFilterCommand.cs b/src/Ryujinx.Audio/Renderer/Dsp/Command/MultiTapBiquadFilterCommand.cs index 84998056f..fad864982 100644 --- a/src/Ryujinx.Audio/Renderer/Dsp/Command/MultiTapBiquadFilterCommand.cs +++ b/src/Ryujinx.Audio/Renderer/Dsp/Command/MultiTapBiquadFilterCommand.cs @@ -8,40 +8,47 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command { public bool Enabled { get; set; } - public int NodeId { get; } + public int NodeId { get; private set; } public CommandType CommandType => CommandType.MultiTapBiquadFilter; public uint EstimatedProcessingTime { get; set; } - private readonly BiquadFilterParameter2[] _parameters; - private readonly Memory _biquadFilterStates; - private readonly int _inputBufferIndex; - private readonly int _outputBufferIndex; - private readonly bool[] _isInitialized; + public BiquadFilterParameter2[] Parameters { get; private set; } + public Memory BiquadFilterStates { get; private set; } + public int InputBufferIndex { get; private set; } + public int OutputBufferIndex { get; private set; } + public bool[] IsInitialized { get; private set; } - public MultiTapBiquadFilterCommand(int baseIndex, ReadOnlySpan filters, Memory biquadFilterStateMemory, int inputBufferOffset, int outputBufferOffset, ReadOnlySpan isInitialized, int nodeId) + public MultiTapBiquadFilterCommand() { - _parameters = filters.ToArray(); - _biquadFilterStates = biquadFilterStateMemory; - _inputBufferIndex = baseIndex + inputBufferOffset; - _outputBufferIndex = baseIndex + outputBufferOffset; - _isInitialized = isInitialized.ToArray(); + + } + + public MultiTapBiquadFilterCommand Initialize(int baseIndex, ReadOnlySpan filters, Memory biquadFilterStateMemory, int inputBufferOffset, int outputBufferOffset, ReadOnlySpan isInitialized, int nodeId) + { + Parameters = filters.ToArray(); + BiquadFilterStates = biquadFilterStateMemory; + InputBufferIndex = baseIndex + inputBufferOffset; + OutputBufferIndex = baseIndex + outputBufferOffset; + IsInitialized = isInitialized.ToArray(); Enabled = true; NodeId = nodeId; + + return this; } public void Process(CommandList context) { - Span states = _biquadFilterStates.Span; + Span states = BiquadFilterStates.Span; - ReadOnlySpan inputBuffer = context.GetBuffer(_inputBufferIndex); - Span outputBuffer = context.GetBuffer(_outputBufferIndex); + ReadOnlySpan inputBuffer = context.GetBuffer(InputBufferIndex); + Span 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(); } @@ -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. // 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 { - BiquadFilterHelper.ProcessBiquadFilter(_parameters, states, outputBuffer, inputBuffer, context.SampleCount); + BiquadFilterHelper.ProcessBiquadFilter(Parameters, states, outputBuffer, inputBuffer, context.SampleCount); } } } diff --git a/src/Ryujinx.Audio/Renderer/Dsp/Command/PcmFloatDataSourceCommandVersion1.cs b/src/Ryujinx.Audio/Renderer/Dsp/Command/PcmFloatDataSourceCommandVersion1.cs index d54158541..5bf003dfb 100644 --- a/src/Ryujinx.Audio/Renderer/Dsp/Command/PcmFloatDataSourceCommandVersion1.cs +++ b/src/Ryujinx.Audio/Renderer/Dsp/Command/PcmFloatDataSourceCommandVersion1.cs @@ -11,26 +11,31 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command { public bool Enabled { get; set; } - public int NodeId { get; } + public int NodeId { get; private set; } public CommandType CommandType => CommandType.PcmFloatDataSourceVersion1; public uint EstimatedProcessingTime { get; set; } - public ushort OutputBufferIndex { get; } - public uint SampleRate { get; } - public uint ChannelIndex { get; } + public ushort OutputBufferIndex { get; private set; } + public uint SampleRate { get; private set; } + 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 Memory State { get; } - public DecodingBehaviour DecodingBehaviour { get; } + public Memory State { get; private set; } + public DecodingBehaviour DecodingBehaviour { get; private set; } - public PcmFloatDataSourceCommandVersion1(ref VoiceInfo serverInfo, Memory state, ushort outputBufferIndex, ushort channelIndex, int nodeId) + public PcmFloatDataSourceCommandVersion1() + { + WaveBuffers = new WaveBuffer[Constants.VoiceWaveBufferCount]; + } + + public PcmFloatDataSourceCommandVersion1 Initialize(ref VoiceInfo serverInfo, Memory state, ushort outputBufferIndex, ushort channelIndex, int nodeId) { Enabled = true; NodeId = nodeId; @@ -40,8 +45,6 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command ChannelIndex = channelIndex; ChannelCount = serverInfo.ChannelsCount; Pitch = serverInfo.Pitch; - - WaveBuffers = new WaveBuffer[Constants.VoiceWaveBufferCount]; Span waveBufferSpan = serverInfo.WaveBuffers.AsSpan(); @@ -54,6 +57,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command State = state; DecodingBehaviour = serverInfo.DecodingBehaviour; + + return this; } public void Process(CommandList context) diff --git a/src/Ryujinx.Audio/Renderer/Dsp/Command/PcmInt16DataSourceCommandVersion1.cs b/src/Ryujinx.Audio/Renderer/Dsp/Command/PcmInt16DataSourceCommandVersion1.cs index 91619d80f..2bcffa59b 100644 --- a/src/Ryujinx.Audio/Renderer/Dsp/Command/PcmInt16DataSourceCommandVersion1.cs +++ b/src/Ryujinx.Audio/Renderer/Dsp/Command/PcmInt16DataSourceCommandVersion1.cs @@ -11,26 +11,31 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command { public bool Enabled { get; set; } - public int NodeId { get; } + public int NodeId { get; private set; } public CommandType CommandType => CommandType.PcmInt16DataSourceVersion1; public uint EstimatedProcessingTime { get; set; } - public ushort OutputBufferIndex { get; } - public uint SampleRate { get; } - public uint ChannelIndex { get; } + public ushort OutputBufferIndex { get; private set; } + public uint SampleRate { get; private set; } + 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 Memory State { get; } - public DecodingBehaviour DecodingBehaviour { get; } + public Memory State { get; private set; } + public DecodingBehaviour DecodingBehaviour { get; private set; } - public PcmInt16DataSourceCommandVersion1(ref VoiceInfo serverInfo, Memory state, ushort outputBufferIndex, ushort channelIndex, int nodeId) + public PcmInt16DataSourceCommandVersion1() + { + WaveBuffers = new WaveBuffer[Constants.VoiceWaveBufferCount]; + } + + public PcmInt16DataSourceCommandVersion1 Initialize(ref VoiceInfo serverInfo, Memory state, ushort outputBufferIndex, ushort channelIndex, int nodeId) { Enabled = true; NodeId = nodeId; @@ -40,8 +45,6 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command ChannelIndex = channelIndex; ChannelCount = serverInfo.ChannelsCount; Pitch = serverInfo.Pitch; - - WaveBuffers = new WaveBuffer[Constants.VoiceWaveBufferCount]; Span waveBufferSpan = serverInfo.WaveBuffers.AsSpan(); @@ -54,6 +57,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command State = state; DecodingBehaviour = serverInfo.DecodingBehaviour; + + return this; } public void Process(CommandList context) diff --git a/src/Ryujinx.Audio/Renderer/Dsp/Command/PerformanceCommand.cs b/src/Ryujinx.Audio/Renderer/Dsp/Command/PerformanceCommand.cs index d3d2ee306..c5d7d8ef1 100644 --- a/src/Ryujinx.Audio/Renderer/Dsp/Command/PerformanceCommand.cs +++ b/src/Ryujinx.Audio/Renderer/Dsp/Command/PerformanceCommand.cs @@ -13,22 +13,34 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command public bool Enabled { get; set; } - public int NodeId { get; } + public int NodeId { get; private set; } public CommandType CommandType => CommandType.Performance; public uint EstimatedProcessingTime { get; set; } - public PerformanceEntryAddresses PerformanceEntryAddresses { get; } + public PerformanceEntryAddresses PerformanceEntryAddresses { get; private 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; PerformanceEntryAddresses = performanceEntryAddresses; PerformanceType = performanceType; NodeId = nodeId; + + return this; } public void Process(CommandList context) diff --git a/src/Ryujinx.Audio/Renderer/Dsp/Command/Reverb3dCommand.cs b/src/Ryujinx.Audio/Renderer/Dsp/Command/Reverb3dCommand.cs index f183641cd..56b5ef313 100644 --- a/src/Ryujinx.Audio/Renderer/Dsp/Command/Reverb3dCommand.cs +++ b/src/Ryujinx.Audio/Renderer/Dsp/Command/Reverb3dCommand.cs @@ -35,26 +35,32 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command public bool Enabled { get; set; } - public int NodeId { get; } + public int NodeId { get; private set; } public CommandType CommandType => CommandType.Reverb3d; public uint EstimatedProcessingTime { get; set; } - public ushort InputBufferIndex { get; } - public ushort OutputBufferIndex { get; } + public ushort InputBufferIndex { get; private set; } + public ushort OutputBufferIndex { get; private set; } public Reverb3dParameter Parameter => _parameter; - public Memory State { get; } - public ulong WorkBuffer { get; } + public Memory State { get; private set; } + public ulong WorkBuffer { get; private set; } public ushort[] OutputBufferIndices { get; } public ushort[] InputBufferIndices { get; } - public bool IsEffectEnabled { get; } + public bool IsEffectEnabled { get; private set; } private Reverb3dParameter _parameter; - public Reverb3dCommand(uint bufferOffset, Reverb3dParameter parameter, Memory 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 state, bool isEnabled, ulong workBuffer, int nodeId, bool newEffectChannelMappingSupported) { Enabled = true; IsEffectEnabled = isEnabled; @@ -62,9 +68,6 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command _parameter = parameter; State = state; WorkBuffer = workBuffer; - - InputBufferIndices = new ushort[Constants.VoiceChannelCountMax]; - OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax]; Span inputSpan = Parameter.Input.AsSpan(); Span 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. DataSourceHelper.RemapChannelResourceMappingToLegacy(newEffectChannelMappingSupported, InputBufferIndices, Parameter.ChannelCount); DataSourceHelper.RemapChannelResourceMappingToLegacy(newEffectChannelMappingSupported, OutputBufferIndices, Parameter.ChannelCount); + + return this; } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/Ryujinx.Audio/Renderer/Dsp/Command/ReverbCommand.cs b/src/Ryujinx.Audio/Renderer/Dsp/Command/ReverbCommand.cs index 20a8422d1..b99cb551b 100644 --- a/src/Ryujinx.Audio/Renderer/Dsp/Command/ReverbCommand.cs +++ b/src/Ryujinx.Audio/Renderer/Dsp/Command/ReverbCommand.cs @@ -33,26 +33,32 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command public bool Enabled { get; set; } - public int NodeId { get; } + public int NodeId { get; private set; } public CommandType CommandType => CommandType.Reverb; public uint EstimatedProcessingTime { get; set; } public ReverbParameter Parameter => _parameter; - public Memory State { get; } - public ulong WorkBuffer { get; } + public Memory State { get; private set; } + public ulong WorkBuffer { get; private set; } public ushort[] OutputBufferIndices { 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 const int FixedPointPrecision = 14; - public ReverbCommand(uint bufferOffset, ReverbParameter parameter, Memory 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 state, bool isEnabled, ulong workBuffer, int nodeId, bool isLongSizePreDelaySupported, bool newEffectChannelMappingSupported) { Enabled = true; IsEffectEnabled = isEnabled; @@ -60,9 +66,6 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command _parameter = parameter; State = state; WorkBuffer = workBuffer; - - InputBufferIndices = new ushort[Constants.VoiceChannelCountMax]; - OutputBufferIndices = new ushort[Constants.VoiceChannelCountMax]; Span inputSpan = Parameter.Input.AsSpan(); Span outputSpan = Parameter.Output.AsSpan(); @@ -79,6 +82,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command // TODO: Update reverb processing and remove this to use RemapLegacyChannelEffectMappingToChannelResourceMapping. DataSourceHelper.RemapChannelResourceMappingToLegacy(newEffectChannelMappingSupported, InputBufferIndices, Parameter.ChannelCount); DataSourceHelper.RemapChannelResourceMappingToLegacy(newEffectChannelMappingSupported, OutputBufferIndices, Parameter.ChannelCount); + + return this; } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/Ryujinx.Audio/Renderer/Dsp/Command/UpsampleCommand.cs b/src/Ryujinx.Audio/Renderer/Dsp/Command/UpsampleCommand.cs index 5d23addae..f9c17863f 100644 --- a/src/Ryujinx.Audio/Renderer/Dsp/Command/UpsampleCommand.cs +++ b/src/Ryujinx.Audio/Renderer/Dsp/Command/UpsampleCommand.cs @@ -7,22 +7,27 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command { public bool Enabled { get; set; } - public int NodeId { get; } + public int NodeId { get; private set; } public CommandType CommandType => CommandType.Upsample; public uint EstimatedProcessingTime { get; set; } - public uint BufferCount { get; } - public uint InputBufferIndex { get; } - public uint InputSampleCount { get; } - public uint InputSampleRate { get; } + public uint BufferCount { get; private set; } + public uint InputBufferIndex { get; private set; } + public uint InputSampleCount { get; private set; } + public uint InputSampleRate { get; private set; } - public UpsamplerInfo UpsamplerInfo { get; } + public UpsamplerInfo UpsamplerInfo { get; private set; } - public Memory OutBuffer { get; } + public Memory OutBuffer { get; private set; } - public UpsampleCommand(uint bufferOffset, UpsamplerInfo info, uint inputCount, Span inputBufferOffset, uint bufferCount, uint sampleCount, uint sampleRate, int nodeId) + public UpsampleCommand() + { + + } + + public UpsampleCommand Initialize(uint bufferOffset, UpsamplerInfo info, uint inputCount, Span inputBufferOffset, uint bufferCount, uint sampleCount, uint sampleRate, int nodeId) { Enabled = true; NodeId = nodeId; @@ -47,6 +52,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command } UpsamplerInfo = info; + + return this; } private Span GetBuffer(int index, int sampleCount) diff --git a/src/Ryujinx.Audio/Renderer/Dsp/Command/VolumeCommand.cs b/src/Ryujinx.Audio/Renderer/Dsp/Command/VolumeCommand.cs index 5deeb07f1..ef5a28bd2 100644 --- a/src/Ryujinx.Audio/Renderer/Dsp/Command/VolumeCommand.cs +++ b/src/Ryujinx.Audio/Renderer/Dsp/Command/VolumeCommand.cs @@ -11,18 +11,23 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command { public bool Enabled { get; set; } - public int NodeId { get; } + public int NodeId { get; private set; } public CommandType CommandType => CommandType.Volume; public uint EstimatedProcessingTime { get; set; } - public ushort InputBufferIndex { get; } - public ushort OutputBufferIndex { get; } + public ushort InputBufferIndex { get; private set; } + 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; NodeId = nodeId; @@ -31,6 +36,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command OutputBufferIndex = (ushort)bufferIndex; Volume = volume; + + return this; } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/Ryujinx.Audio/Renderer/Dsp/Command/VolumeRampCommand.cs b/src/Ryujinx.Audio/Renderer/Dsp/Command/VolumeRampCommand.cs index bffbcbc63..47753dc79 100644 --- a/src/Ryujinx.Audio/Renderer/Dsp/Command/VolumeRampCommand.cs +++ b/src/Ryujinx.Audio/Renderer/Dsp/Command/VolumeRampCommand.cs @@ -7,19 +7,24 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command { public bool Enabled { get; set; } - public int NodeId { get; } + public int NodeId { get; private set; } public CommandType CommandType => CommandType.VolumeRamp; public uint EstimatedProcessingTime { get; set; } - public ushort InputBufferIndex { get; } - public ushort OutputBufferIndex { get; } + public ushort InputBufferIndex { get; private set; } + public ushort OutputBufferIndex { get; private set; } - public float Volume0 { get; } - public float Volume1 { get; } + public float Volume0 { get; private set; } + 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; NodeId = nodeId; @@ -29,6 +34,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command Volume0 = volume0; Volume1 = volume1; + + return this; } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/Ryujinx.Audio/Renderer/Parameter/EffectInParameterVersion3.cs b/src/Ryujinx.Audio/Renderer/Parameter/EffectInParameterVersion3.cs deleted file mode 100644 index 2cf4911a6..000000000 --- a/src/Ryujinx.Audio/Renderer/Parameter/EffectInParameterVersion3.cs +++ /dev/null @@ -1,97 +0,0 @@ -using Ryujinx.Audio.Renderer.Common; -using Ryujinx.Common.Utilities; -using System; -using System.Runtime.InteropServices; - -namespace Ryujinx.Audio.Renderer.Parameter -{ - /// - /// Input information for an effect version 2. (added with REV9) - /// - [StructLayout(LayoutKind.Sequential, Pack = 1)] - public struct EffectInParameterVersion3 : IEffectInParameter - { - /// - /// Type of the effect. - /// - public EffectType Type; - - /// - /// Set to true if the effect is new. - /// - [MarshalAs(UnmanagedType.I1)] - public bool IsNew; - - /// - /// Set to true if the effect must be active. - /// - [MarshalAs(UnmanagedType.I1)] - public bool IsEnabled; - - /// - /// Reserved/padding. - /// - private readonly byte _reserved1; - - /// - /// The target mix id of the effect. - /// - public int MixId; - - /// - /// Address of the processing workbuffer. - /// - /// This is additional data that could be required by the effect processing. - public ulong BufferBase; - - /// - /// Size of the processing workbuffer. - /// - /// This is additional data that could be required by the effect processing. - public ulong BufferSize; - - /// - /// Position of the effect while processing effects. - /// - public uint ProcessingOrder; - - /// - /// Reserved/padding. - /// - private readonly uint _reserved2; - - /// - /// Specific data storage. - /// - private SpecificDataStruct _specificDataStart; - - [StructLayout(LayoutKind.Sequential, Size = 0xA0, Pack = 1)] - private struct SpecificDataStruct { } - - public Span SpecificData => SpanHelpers.AsSpan(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; - - /// - /// Check if the given channel count is valid. - /// - /// The channel count to check - /// Returns true if the channel count is valid. - public static bool IsChannelCountValid(int channelCount) - { - return channelCount is 1 or 2 or 4 or 6; - } - } -} diff --git a/src/Ryujinx.Audio/Renderer/Server/CommandBuffer.cs b/src/Ryujinx.Audio/Renderer/Server/CommandBuffer.cs index 62380f926..70564ace9 100644 --- a/src/Ryujinx.Audio/Renderer/Server/CommandBuffer.cs +++ b/src/Ryujinx.Audio/Renderer/Server/CommandBuffer.cs @@ -8,6 +8,7 @@ using Ryujinx.Audio.Renderer.Server.Sink; using Ryujinx.Audio.Renderer.Server.Splitter; using Ryujinx.Audio.Renderer.Server.Upsampler; using Ryujinx.Audio.Renderer.Server.Voice; +using Ryujinx.Common; using System; using System.Runtime.CompilerServices; using CpuAddress = System.UInt64; @@ -34,6 +35,170 @@ namespace Ryujinx.Audio.Renderer.Server /// public CommandList CommandList { get; } + private readonly static ObjectPool _pcmInt16DataSourceCommandVersion1Pool = new(() => new PcmInt16DataSourceCommandVersion1()); + private readonly static ObjectPool _pcmFloatDataSourceCommandVersion1Pool = new(() => new PcmFloatDataSourceCommandVersion1()); + private readonly static ObjectPool _adpcmDataSourceCommandVersion1Pool = new(() => new AdpcmDataSourceCommandVersion1()); + private readonly static ObjectPool _dataSourceVersion2CommandPool = new(() => new DataSourceVersion2Command()); + private readonly static ObjectPool _volumeCommandPool = new(() => new VolumeCommand()); + private readonly static ObjectPool _volumeRampCommandPool = new(() => new VolumeRampCommand()); + private readonly static ObjectPool _biquadFilterCommandPool = new(() => new BiquadFilterCommand()); + private readonly static ObjectPool _mixCommandPool = new(() => new MixCommand()); + private readonly static ObjectPool _mixRampCommandPool = new(() => new MixRampCommand()); + private readonly static ObjectPool _mixRampGroupedCommandPool = new(() => new MixRampGroupedCommand()); + private readonly static ObjectPool _depopPrepareCommandPool = new(() => new DepopPrepareCommand()); + private readonly static ObjectPool _depopForMixBuffersCommandPool = new(() => new DepopForMixBuffersCommand()); + private readonly static ObjectPool _delayCommandPool = new(() => new DelayCommand()); + private readonly static ObjectPool _upsampleCommandPool = new(() => new UpsampleCommand()); + private readonly static ObjectPool _downMixSurroundToStereoCommandPool = new(() => new DownMixSurroundToStereoCommand()); + private readonly static ObjectPool _auxiliaryBufferCommandPool = new(() => new AuxiliaryBufferCommand()); + private readonly static ObjectPool _deviceSinkCommandPool = new(() => new DeviceSinkCommand()); + private readonly static ObjectPool _circularBufferSinkCommandPool = new(() => new CircularBufferSinkCommand()); + private readonly static ObjectPool _reverbCommandPool = new(() => new ReverbCommand()); + private readonly static ObjectPool _reverb3dCommandPool = new(() => new Reverb3dCommand()); + private readonly static ObjectPool _performanceCommandPool = new(() => new PerformanceCommand()); + private readonly static ObjectPool _clearMixBufferCommandPool = new(() => new ClearMixBufferCommand()); + private readonly static ObjectPool _copyMixBufferCommandPool = new(() => new CopyMixBufferCommand()); + private readonly static ObjectPool _limiterCommandVersion1Pool = new(() => new LimiterCommandVersion1()); + private readonly static ObjectPool _limiterCommandVersion2Pool = new(() => new LimiterCommandVersion2()); + private readonly static ObjectPool _multiTapBiquadFilterCommandPool = new(() => new MultiTapBiquadFilterCommand()); + private readonly static ObjectPool _captureBufferCommandPool = new(() => new CaptureBufferCommand()); + private readonly static ObjectPool _compressorCommandPool = new(() => new CompressorCommand()); + private readonly static ObjectPool _biquadFilterAndMixCommandPool = new(() => new BiquadFilterAndMixCommand()); + private readonly static ObjectPool _multiTapBiquadFilterAndMixCommandPool = new(() => new MultiTapBiquadFilterAndMixCommand()); + private readonly static ObjectPool _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(); + } + } + /// /// Create a new . /// @@ -63,7 +228,7 @@ namespace Ryujinx.Audio.Renderer.Server /// The node id associated to this command. public void GenerateClearMixBuffer(int nodeId) { - ClearMixBufferCommand command = new(nodeId); + ClearMixBufferCommand command = _clearMixBufferCommandPool.Allocate().Initialize(nodeId); command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command); @@ -81,7 +246,7 @@ namespace Ryujinx.Audio.Renderer.Server /// Set to true if the voice was playing previously. public void GenerateDepopPrepare(Memory state, Memory 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); @@ -96,7 +261,7 @@ namespace Ryujinx.Audio.Renderer.Server /// The node id associated to this command. 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); @@ -112,7 +277,7 @@ namespace Ryujinx.Audio.Renderer.Server /// The node id associated to this command. 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); @@ -129,7 +294,7 @@ namespace Ryujinx.Audio.Renderer.Server /// The node id associated to this command. public void GenerateDataSourceVersion2(ref VoiceInfo voiceInfo, Memory 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); @@ -146,7 +311,7 @@ namespace Ryujinx.Audio.Renderer.Server /// The node id associated to this command. public void GeneratePcmInt16DataSourceVersion1(ref VoiceInfo voiceInfo, Memory 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); @@ -163,7 +328,7 @@ namespace Ryujinx.Audio.Renderer.Server /// The node id associated to this command. public void GeneratePcmFloatDataSourceVersion1(ref VoiceInfo voiceInfo, Memory 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); @@ -179,7 +344,7 @@ namespace Ryujinx.Audio.Renderer.Server /// The node id associated to this command. public void GenerateAdpcmDataSourceVersion1(ref VoiceInfo voiceInfo, Memory 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); @@ -198,7 +363,7 @@ namespace Ryujinx.Audio.Renderer.Server /// The node id associated to this command. public void GenerateBiquadFilter(int baseIndex, ref BiquadFilterParameter2 filter, Memory 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); @@ -217,7 +382,7 @@ namespace Ryujinx.Audio.Renderer.Server /// The node id associated to this command. public void GenerateMultiTapBiquadFilter(int baseIndex, ReadOnlySpan filters, Memory biquadFilterStatesMemory, int inputBufferOffset, int outputBufferOffset, ReadOnlySpan 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); @@ -236,7 +401,7 @@ namespace Ryujinx.Audio.Renderer.Server /// The node id associated to this command. public void GenerateMixRampGrouped(uint mixBufferCount, uint inputBufferIndex, uint outputBufferIndex, ReadOnlySpan previousVolume, ReadOnlySpan volume, Memory 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); @@ -255,7 +420,7 @@ namespace Ryujinx.Audio.Renderer.Server /// The node id associated to this command. public void GenerateMixRamp(float previousVolume, float volume, uint inputBufferIndex, uint outputBufferIndex, int lastSampleIndex, Memory 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); @@ -293,7 +458,7 @@ namespace Ryujinx.Audio.Renderer.Server bool isFirstMixBuffer, int nodeId) { - BiquadFilterAndMixCommand command = new( + BiquadFilterAndMixCommand command = _biquadFilterAndMixCommandPool.Allocate().Initialize( previousVolume, volume, inputBufferIndex, @@ -352,7 +517,7 @@ namespace Ryujinx.Audio.Renderer.Server bool isFirstMixBuffer, int nodeId) { - MultiTapBiquadFilterAndMixCommand command = new( + MultiTapBiquadFilterAndMixCommand command = _multiTapBiquadFilterAndMixCommandPool.Allocate().Initialize( previousVolume, volume, inputBufferIndex, @@ -386,7 +551,7 @@ namespace Ryujinx.Audio.Renderer.Server /// The target sample rate in use. public void GenerateDepopForMixBuffers(Memory 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); @@ -401,7 +566,7 @@ namespace Ryujinx.Audio.Renderer.Server /// The node id associated to this command. 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); @@ -417,7 +582,7 @@ namespace Ryujinx.Audio.Renderer.Server /// The mix 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); @@ -439,7 +604,7 @@ namespace Ryujinx.Audio.Renderer.Server { 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); @@ -461,7 +626,7 @@ namespace Ryujinx.Audio.Renderer.Server { 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); @@ -483,7 +648,7 @@ namespace Ryujinx.Audio.Renderer.Server { 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); @@ -504,7 +669,7 @@ namespace Ryujinx.Audio.Renderer.Server { 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); @@ -526,7 +691,7 @@ namespace Ryujinx.Audio.Renderer.Server { 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); @@ -552,7 +717,7 @@ namespace Ryujinx.Audio.Renderer.Server { 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); @@ -576,7 +741,7 @@ namespace Ryujinx.Audio.Renderer.Server { 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); @@ -597,7 +762,7 @@ namespace Ryujinx.Audio.Renderer.Server { 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); @@ -613,7 +778,7 @@ namespace Ryujinx.Audio.Renderer.Server /// The node id associated to this command. 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); @@ -628,7 +793,7 @@ namespace Ryujinx.Audio.Renderer.Server /// The node id associated to this command. 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); @@ -645,7 +810,7 @@ namespace Ryujinx.Audio.Renderer.Server /// The node id associated to this command. public void GenerateDownMixSurroundToStereo(uint bufferOffset, Span inputBufferOffset, Span 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); @@ -665,7 +830,7 @@ namespace Ryujinx.Audio.Renderer.Server /// The node id associated to this command. public void GenerateUpsample(uint bufferOffset, UpsamplerInfo upsampler, uint inputCount, Span 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); @@ -682,7 +847,7 @@ namespace Ryujinx.Audio.Renderer.Server /// The node id associated to this command. public void GenerateDeviceSink(uint bufferOffset, DeviceSink sink, int sessionId, Memory 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); @@ -691,16 +856,7 @@ namespace Ryujinx.Audio.Renderer.Server public void GenerateFillBuffer(SplitterDestination destination, float value, int length, int nodeId) { - FillBufferCommand command; - - if (Unsafe.IsNullRef(ref destination.GetV2RefOrNull())) - { - command = new(destination.GetV1RefOrNull(), length, value, nodeId); - } - else - { - command = new(destination.GetV2RefOrNull(), length, value, nodeId); - } + FillBufferCommand command = _fillBufferCommandPool.Allocate().Initialize(destination, length, value, nodeId); command.EstimatedProcessingTime = _commandProcessingTimeEstimator.Estimate(command); diff --git a/src/Ryujinx.Audio/Renderer/Server/CommandGenerator.cs b/src/Ryujinx.Audio/Renderer/Server/CommandGenerator.cs index c88aa51f2..600f51576 100644 --- a/src/Ryujinx.Audio/Renderer/Server/CommandGenerator.cs +++ b/src/Ryujinx.Audio/Renderer/Server/CommandGenerator.cs @@ -339,7 +339,7 @@ namespace Ryujinx.Audio.Renderer.Server bool performanceInitialized = false; - PerformanceEntryAddresses performanceEntry = new(); + PerformanceEntryAddresses performanceEntry = null; if (_performanceManager != null && _performanceManager.IsTargetNodeId(nodeId) && _performanceManager.GetNextEntry(out performanceEntry, dataSourceDetailType, PerformanceEntryType.Voice, nodeId)) { @@ -500,7 +500,7 @@ namespace Ryujinx.Audio.Renderer.Server { int nodeId = sortedInfo.NodeId; - PerformanceEntryAddresses performanceEntry = new(); + PerformanceEntryAddresses performanceEntry = null; bool performanceInitialized = false; @@ -786,7 +786,7 @@ namespace Ryujinx.Audio.Renderer.Server bool isFinalMix = mix.MixId == Constants.FinalMixId; - PerformanceEntryAddresses performanceEntry = new(); + PerformanceEntryAddresses performanceEntry = null; bool performanceInitialized = false; @@ -1050,7 +1050,7 @@ namespace Ryujinx.Audio.Renderer.Server GenerateEffects(ref subMix); - PerformanceEntryAddresses performanceEntry = new(); + PerformanceEntryAddresses performanceEntry = null; int nodeId = subMix.NodeId; @@ -1081,7 +1081,7 @@ namespace Ryujinx.Audio.Renderer.Server { int nodeId = sortedInfo.NodeId; - PerformanceEntryAddresses performanceEntry = new(); + PerformanceEntryAddresses performanceEntry = null; bool performanceInitialized = false; @@ -1115,7 +1115,7 @@ namespace Ryujinx.Audio.Renderer.Server GenerateEffects(ref finalMix); - PerformanceEntryAddresses performanceEntry = new(); + PerformanceEntryAddresses performanceEntry = null; int nodeId = finalMix.NodeId; @@ -1164,7 +1164,7 @@ namespace Ryujinx.Audio.Renderer.Server { int nodeId = _mixContext.GetFinalState().NodeId; - PerformanceEntryAddresses performanceEntry = new(); + PerformanceEntryAddresses performanceEntry = null; bool performanceInitialized = false; @@ -1244,7 +1244,7 @@ namespace Ryujinx.Audio.Renderer.Server { bool performanceInitialized = false; - PerformanceEntryAddresses performanceEntry = new(); + PerformanceEntryAddresses performanceEntry = null; if (_performanceManager != null && _performanceManager.GetNextEntry(out performanceEntry, PerformanceEntryType.Sink, sink.NodeId)) { diff --git a/src/Ryujinx.Audio/Renderer/Server/Effect/BaseEffect.cs b/src/Ryujinx.Audio/Renderer/Server/Effect/BaseEffect.cs index 6324689e4..77d9b5c29 100644 --- a/src/Ryujinx.Audio/Renderer/Server/Effect/BaseEffect.cs +++ b/src/Ryujinx.Audio/Renderer/Server/Effect/BaseEffect.cs @@ -174,19 +174,6 @@ namespace Ryujinx.Audio.Renderer.Server.Effect updateErrorInfo = new ErrorInfo(); } - - /// - /// Update the internal state from a user version 3 parameter. - /// - /// The possible that was generated. - /// The user parameter. - /// The mapper to use. - public virtual void Update(out ErrorInfo updateErrorInfo, in EffectInParameterVersion3 parameter, PoolMapper mapper) - { - Debug.Assert(IsTypeValid(in parameter)); - - updateErrorInfo = new ErrorInfo(); - } /// /// Get the work buffer DSP address at the given index. diff --git a/src/Ryujinx.Audio/Renderer/Server/Effect/BiquadFilterEffect.cs b/src/Ryujinx.Audio/Renderer/Server/Effect/BiquadFilterEffect.cs index f920c6873..55a898529 100644 --- a/src/Ryujinx.Audio/Renderer/Server/Effect/BiquadFilterEffect.cs +++ b/src/Ryujinx.Audio/Renderer/Server/Effect/BiquadFilterEffect.cs @@ -25,13 +25,19 @@ namespace Ryujinx.Audio.Renderer.Server.Effect /// public Memory State { get; } + /// + /// The biquad filter effect version. + /// + public int BiquadFilterEffectVersion; + /// /// Create a new . /// - public BiquadFilterEffect() + public BiquadFilterEffect(int version) { Parameter = new BiquadFilterEffectParameter2(); State = new BiquadFilterState[Constants.ChannelCountMax]; + BiquadFilterEffectVersion = version; } public override EffectType TargetEffectType => EffectType.BiquadFilter; @@ -45,11 +51,6 @@ namespace Ryujinx.Audio.Renderer.Server.Effect { 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(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); - if (typeof(T) == typeof(EffectInParameterVersion3)) + if (BiquadFilterEffectVersion == 2) { Parameter = MemoryMarshal.Cast(parameter.SpecificData)[0]; } diff --git a/src/Ryujinx.Audio/Renderer/Server/Performance/PerformanceEntryAddresses.cs b/src/Ryujinx.Audio/Renderer/Server/Performance/PerformanceEntryAddresses.cs index d24b96a27..d59cc01a1 100644 --- a/src/Ryujinx.Audio/Renderer/Server/Performance/PerformanceEntryAddresses.cs +++ b/src/Ryujinx.Audio/Renderer/Server/Performance/PerformanceEntryAddresses.cs @@ -1,3 +1,4 @@ +using Ryujinx.Common; using System; namespace Ryujinx.Audio.Renderer.Server.Performance @@ -7,6 +8,8 @@ namespace Ryujinx.Audio.Renderer.Server.Performance /// public class PerformanceEntryAddresses { + public static readonly ObjectPool PerformanceEntryAddressesPool = new(() => new PerformanceEntryAddresses()); + /// /// The memory storing the performance entry. /// @@ -52,5 +55,10 @@ namespace Ryujinx.Audio.Renderer.Server.Performance { BaseMemory.Span[(int)ProcessingTimeOffset / 4] = (int)(endTimeNano / 1000) - BaseMemory.Span[(int)StartTimeOffset / 4]; } + + public void Clear() + { + + } } } diff --git a/src/Ryujinx.Audio/Renderer/Server/Performance/PerformanceManagerGeneric.cs b/src/Ryujinx.Audio/Renderer/Server/Performance/PerformanceManagerGeneric.cs index 2e5d25b9c..8881c7243 100644 --- a/src/Ryujinx.Audio/Renderer/Server/Performance/PerformanceManagerGeneric.cs +++ b/src/Ryujinx.Audio/Renderer/Server/Performance/PerformanceManagerGeneric.cs @@ -208,11 +208,9 @@ namespace Ryujinx.Audio.Renderer.Server.Performance public override bool GetNextEntry(out PerformanceEntryAddresses performanceEntry, PerformanceEntryType entryType, int nodeId) { - performanceEntry = new PerformanceEntryAddresses - { - BaseMemory = SpanMemoryManager.Cast(CurrentBuffer), - EntryCountOffset = (uint)CurrentHeader.GetEntryCountOffset(), - }; + performanceEntry = PerformanceEntryAddresses.PerformanceEntryAddressesPool.Allocate(); + performanceEntry.BaseMemory = SpanMemoryManager.Cast(CurrentBuffer); + performanceEntry.EntryCountOffset = (uint)CurrentHeader.GetEntryCountOffset(); uint baseEntryOffset = (uint)(Unsafe.SizeOf() + Unsafe.SizeOf() * _entryIndex); @@ -238,12 +236,10 @@ namespace Ryujinx.Audio.Renderer.Server.Performance { return false; } - - performanceEntry = new PerformanceEntryAddresses - { - BaseMemory = SpanMemoryManager.Cast(CurrentBuffer), - EntryCountOffset = (uint)CurrentHeader.GetEntryCountOffset(), - }; + + performanceEntry = PerformanceEntryAddresses.PerformanceEntryAddressesPool.Allocate(); + performanceEntry.BaseMemory = SpanMemoryManager.Cast(CurrentBuffer); + performanceEntry.EntryCountOffset = (uint)CurrentHeader.GetEntryCountOffset(); uint baseEntryOffset = (uint)(Unsafe.SizeOf() + GetEntriesSize() + Unsafe.SizeOf() * _entryDetailIndex); diff --git a/src/Ryujinx.Audio/Renderer/Server/StateUpdater.cs b/src/Ryujinx.Audio/Renderer/Server/StateUpdater.cs index a02d70240..917d63716 100644 --- a/src/Ryujinx.Audio/Renderer/Server/StateUpdater.cs +++ b/src/Ryujinx.Audio/Renderer/Server/StateUpdater.cs @@ -300,7 +300,7 @@ namespace Ryujinx.Audio.Renderer.Server return ResultCode.Success; } - private static void ResetEffect(ref BaseEffect effect, in T parameter, PoolMapper mapper) where T : unmanaged, IEffectInParameter + private void ResetEffect(ref BaseEffect effect, in T parameter, PoolMapper mapper) where T : unmanaged, IEffectInParameter { effect.ForceUnmapBuffers(mapper); @@ -312,7 +312,8 @@ namespace Ryujinx.Audio.Renderer.Server EffectType.Delay => new DelayEffect(), EffectType.Reverb => new ReverbEffect(), 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.CaptureBuffer => new CaptureBufferEffect(), EffectType.Compressor => new CompressorEffect(), @@ -322,11 +323,6 @@ namespace Ryujinx.Audio.Renderer.Server public ResultCode UpdateEffects(EffectContext context, bool isAudioRendererActive, PoolMapper mapper) { - if (_behaviourInfo.IsBiquadFilterParameterFloatSupported()) - { - return UpdateEffectsVersion3(context, isAudioRendererActive, mapper); - } - if (_behaviourInfo.IsEffectInfoVersion2Supported()) { return UpdateEffectsVersion2(context, isAudioRendererActive, mapper); @@ -334,60 +330,6 @@ namespace Ryujinx.Audio.Renderer.Server return UpdateEffectsVersion1(context, isAudioRendererActive, mapper); } - - public ResultCode UpdateEffectsVersion3(EffectContext context, bool isAudioRendererActive, PoolMapper mapper) - { - if (context.GetCount() * Unsafe.SizeOf() != _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(out _); - - ref EffectOutStatusVersion2 outStatus = ref SpanIOHelper.GetWriteRef(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() * 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) { diff --git a/src/Ryujinx.Audio/Renderer/Server/Voice/VoiceInfo.cs b/src/Ryujinx.Audio/Renderer/Server/Voice/VoiceInfo.cs index ba6158b71..c6a4149f8 100644 --- a/src/Ryujinx.Audio/Renderer/Server/Voice/VoiceInfo.cs +++ b/src/Ryujinx.Audio/Renderer/Server/Voice/VoiceInfo.cs @@ -4,9 +4,11 @@ using Ryujinx.Audio.Renderer.Dsp; using Ryujinx.Audio.Renderer.Dsp.State; using Ryujinx.Audio.Renderer.Parameter; using Ryujinx.Audio.Renderer.Server.MemoryPool; +using Ryujinx.Common; using Ryujinx.Common.Memory; using Ryujinx.Common.Utilities; using System; +using System.Collections.Generic; using System.Diagnostics; using System.Runtime.InteropServices; using static Ryujinx.Audio.Renderer.Common.BehaviourParameter; @@ -20,6 +22,8 @@ namespace Ryujinx.Audio.Renderer.Server.Voice { public const int Alignment = 0x10; + private static readonly ObjectPool[]> voiceStatesPool = new(() => new Memory[Constants.VoiceChannelCountMax]); + /// /// Set to true if the voice is used. /// @@ -568,7 +572,7 @@ namespace Ryujinx.Audio.Renderer.Server.Voice PoolMapper mapper, ref BehaviourInfo behaviourInfo) { - errorInfos = new ErrorInfo[Constants.VoiceWaveBufferCount * 2]; + if (parameter.IsNew) { @@ -584,11 +588,14 @@ namespace Ryujinx.Audio.Renderer.Server.Voice Span waveBuffersSpan = WaveBuffers.AsSpan(); Span pWaveBuffersSpan = parameter.WaveBuffers.AsSpan(); + List errorInfosList = []; 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(); } /// @@ -606,7 +613,7 @@ namespace Ryujinx.Audio.Renderer.Server.Voice PoolMapper mapper, ref BehaviourInfo behaviourInfo) { - errorInfos = new ErrorInfo[Constants.VoiceWaveBufferCount * 2]; + if (parameter.IsNew) { @@ -622,11 +629,14 @@ namespace Ryujinx.Audio.Renderer.Server.Voice Span waveBuffersSpan = WaveBuffers.AsSpan(); Span pWaveBuffersSpan = parameter.WaveBuffers.AsSpan(); + List errorInfosList = []; 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(); } /// @@ -640,7 +650,7 @@ namespace Ryujinx.Audio.Renderer.Server.Voice /// The mapper to use. /// The behaviour context. private void UpdateWaveBuffer( - Span errorInfos, + List errorInfos, ref WaveBuffer waveBuffer, ref WaveBufferInternal inputWaveBuffer, SampleFormat sampleFormat, @@ -671,7 +681,10 @@ namespace Ryujinx.Audio.Renderer.Server.Voice 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) { @@ -680,7 +693,10 @@ namespace Ryujinx.Audio.Renderer.Server.Voice inputWaveBuffer.ContextAddress, inputWaveBuffer.ContextSize); - errorInfos[1] = adpcmLoopContextInfoError; + if (adpcmLoopContextInfoError.ErrorCode != ResultCode.Success) + { + errorInfos.Add(adpcmLoopContextInfoError); + } if (!adpcmLoopContextMapped || BufferInfoUnmapped) { @@ -698,8 +714,11 @@ namespace Ryujinx.Audio.Renderer.Server.Voice } else { - errorInfos[0].ErrorCode = ResultCode.InvalidAddressInfo; - errorInfos[0].ExtraErrorInfo = inputWaveBuffer.Address; + errorInfos.Add(new ErrorInfo + { + ErrorCode = ResultCode.InvalidAddressInfo, + ExtraErrorInfo = inputWaveBuffer.Address + }); } } } @@ -891,7 +910,7 @@ namespace Ryujinx.Audio.Renderer.Server.Voice IsNew = false; } - Memory[] voiceStates = new Memory[Constants.VoiceChannelCountMax]; + Memory[] voiceStates = voiceStatesPool.Allocate(); Span channelResourceIdsSpan = ChannelResourceIds.AsSpan(); @@ -900,7 +919,12 @@ namespace Ryujinx.Audio.Renderer.Server.Voice 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; } } } diff --git a/src/Ryujinx.Common/Pools/ObjectPool.cs b/src/Ryujinx.Common/Pools/ObjectPool.cs index c4610a59c..65baa00f9 100644 --- a/src/Ryujinx.Common/Pools/ObjectPool.cs +++ b/src/Ryujinx.Common/Pools/ObjectPool.cs @@ -1,67 +1,35 @@ using System; +using System.Collections.Concurrent; using System.Threading; namespace Ryujinx.Common { - public class ObjectPool(Func factory, int size) + public class ObjectPool(Func factory, int size = -1) where T : class { - private T _firstItem; - private readonly T[] _items = new T[size - 1]; + private int _size = size; + private readonly ConcurrentStack _items = new(); 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; } - 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) { - if (_firstItem == null) + if (_size < 0 || _items.Count < _size) { - _firstItem = 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; - } + _items.Push(obj); } } + + public void Clear() => _items.Clear(); } } diff --git a/src/Ryujinx.HLE/HOS/Kernel/Threading/KScheduler.cs b/src/Ryujinx.HLE/HOS/Kernel/Threading/KScheduler.cs index fa81ef983..b97ba705c 100644 --- a/src/Ryujinx.HLE/HOS/Kernel/Threading/KScheduler.cs +++ b/src/Ryujinx.HLE/HOS/Kernel/Threading/KScheduler.cs @@ -293,7 +293,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading KThread currentThread = KernelStatic.GetCurrentThread(); KThread selectedThread = _state.SelectedThread; - if (!currentThread.IsThreadNamed && string.IsNullOrEmpty(currentThread.GetThreadName())) + if (!currentThread.IsThreadNamed && !string.IsNullOrEmpty(currentThread.GetThreadName())) { currentThread.HostThread.Name = $"<{currentThread.GetThreadName()}>"; currentThread.IsThreadNamed = true; diff --git a/src/Ryujinx.Memory/WindowsShared/PlaceholderManager.cs b/src/Ryujinx.Memory/WindowsShared/PlaceholderManager.cs index 436efe98b..6ae540178 100644 --- a/src/Ryujinx.Memory/WindowsShared/PlaceholderManager.cs +++ b/src/Ryujinx.Memory/WindowsShared/PlaceholderManager.cs @@ -1,3 +1,4 @@ +using Ryujinx.Common; using Ryujinx.Common.Collections; using Ryujinx.Common.Memory.PartialUnmaps; using System; @@ -9,24 +10,6 @@ using System.Threading; namespace Ryujinx.Memory.WindowsShared { - public class ObjectPool - { - private readonly Stack _objects; - private readonly Func _objectGenerator; - - public ObjectPool(Func objectGenerator) - { - _objectGenerator = objectGenerator ?? throw new ArgumentNullException(nameof(objectGenerator)); - _objects = new Stack(); - } - - public T Get() => _objects.Count > 0 ? _objects.Pop() : _objectGenerator(); - - public void Return(T item) => _objects.Push(item); - - public void Clear() => _objects.Clear(); - } - /// /// Windows memory placeholder manager. /// @@ -97,7 +80,7 @@ namespace Ryujinx.Memory.WindowsShared lock (_protections) { - _protections.Add(_protectionObjectPool.Get().Init(address, address + size, MemoryPermission.None)); + _protections.Add(_protectionObjectPool.Allocate().Init(address, address + size, MemoryPermission.None)); } } @@ -650,16 +633,16 @@ namespace Ryujinx.Memory.WindowsShared { if (startAddress > protAddress) { - _protections.Add(_protectionObjectPool.Get().Init(protAddress, startAddress, protPermission)); + _protections.Add(_protectionObjectPool.Allocate().Init(protAddress, startAddress, protPermission)); } 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) { @@ -667,7 +650,7 @@ namespace Ryujinx.Memory.WindowsShared } } - _protections.Add(_protectionObjectPool.Get().Init(startAddress, endAddress, permission)); + _protections.Add(_protectionObjectPool.Allocate().Init(startAddress, endAddress, permission)); } } @@ -698,15 +681,15 @@ namespace Ryujinx.Memory.WindowsShared if (address > protAddress) { - _protections.Add(_protectionObjectPool.Get().Init(protAddress, address, protPermission)); + _protections.Add(_protectionObjectPool.Allocate().Init(protAddress, address, protPermission)); } 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) { From 7175da8621cfddea0ff31b54da3a83e566fdc67c Mon Sep 17 00:00:00 2001 From: Coxxs <58-coxxs@users.noreply.git.ryujinx.app> Date: Sun, 26 Oct 2025 00:29:38 -0500 Subject: [PATCH 2/3] UI: [ci skip] Show notifications for options that may cause side effects (ryubing/ryujinx!193) See merge request ryubing/ryujinx!193 --- assets/locales.json | 150 ++++++++++++++++++ .../UI/ViewModels/MainWindowViewModel.cs | 42 +++++ 2 files changed, 192 insertions(+) diff --git a/assets/locales.json b/assets/locales.json index 406e6b646..9da7fe28c 100644 --- a/assets/locales.json +++ b/assets/locales.json @@ -14643,6 +14643,156 @@ "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", "Translations": { diff --git a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs index bab09efc4..7f12a6119 100644 --- a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs @@ -1622,6 +1622,7 @@ namespace Ryujinx.Ava.UI.ViewModels #if RELEASE await PerformanceCheck(); #endif + PreLaunchNotification(); Logger.RestartTime(); @@ -1855,6 +1856,47 @@ namespace Ryujinx.Ava.UI.ViewModels } } + /// + /// Show non-intrusive notifications for options that may cause side effects. + /// + public static void PreLaunchNotification() + { + if (ConfigurationState.Instance.Debug.DebuggerSuspendOnStart.Value) + { + NotificationHelper.ShowInformation( + LocaleManager.Instance[LocaleKeys.NotificationLaunchCheckSuspendOnStartTitle], + LocaleManager.Instance[LocaleKeys.NotificationLaunchCheckSuspendOnStartMessage]); + } + + if (ConfigurationState.Instance.Debug.EnableGdbStub.Value) + { + 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, + }; + + var MemoryConfigurationLocale = LocaleManager.Instance[MemoryConfigurationLocaleKey]; + + NotificationHelper.ShowWarning( + LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.NotificationLaunchCheckDramSizeTitle, MemoryConfigurationLocale), + LocaleManager.Instance[LocaleKeys.NotificationLaunchCheckDramSizeMessage]); + } + } + public async void ProcessTrimResult(String filename, XCIFileTrimmer.OperationOutcome operationOutcome) { string notifyUser = operationOutcome.ToLocalisedText(); From c8959afa3d0e2bfa9f5b73ac8cad4c35a307ce79 Mon Sep 17 00:00:00 2001 From: GreemDev Date: Sun, 26 Oct 2025 00:58:47 -0500 Subject: [PATCH 3/3] chore: Overall code cleanup Update NuGet packages, fix version string in plist for macOS --- Directory.Packages.props | 12 ++--- distribution/macos/Info.plist | 6 +-- src/ARMeilleure/CodeGen/X86/AssemblerTable.cs | 1 - src/ARMeilleure/CodeGen/X86/CodeGenContext.cs | 1 - src/ARMeilleure/CodeGen/X86/X86Register.cs | 2 - src/ARMeilleure/Instructions/InstEmitMul.cs | 1 - .../IntermediateRepresentation/Intrinsic.cs | 1 - .../Dsp/Command/DataSourceVersion2Command.cs | 1 - .../Renderer/Dsp/Command/FillBufferCommand.cs | 1 - .../Renderer/Parameter/VoiceInParameter2.cs | 3 -- .../Renderer/Server/CommandBuffer.cs | 1 - .../Renderer/Server/CommandGenerator.cs | 1 - .../Splitter/SplitterDestinationVersion2.cs | 1 - .../Renderer/Server/Voice/VoiceInfo.cs | 1 - .../Logging/LogEventArgsJson.cs | 31 ------------- .../Logging/LogEventJsonSerializerContext.cs | 9 ---- src/Ryujinx.Common/Logging/Logger.cs | 16 +++---- .../Logging/Targets/JsonLogTarget.cs | 42 ----------------- src/Ryujinx.Common/Pools/ObjectPool.cs | 1 - .../ReferenceEqualityComparer.cs | 19 -------- src/Ryujinx.Common/ReleaseInformation.cs | 5 -- src/Ryujinx.Cpu/IExecutionContext.cs | 1 - .../LightningJit/State/ExecutionContext.cs | 1 - src/Ryujinx.Graphics.GAL/ViewportSwizzle.cs | 2 - .../Engine/Threed/IndirectDrawType.cs | 2 - .../Threed/SpecializationStateUpdater.cs | 1 - .../Engine/Threed/ThreedClass.cs | 1 - src/Ryujinx.Graphics.Gpu/Image/FormatTable.cs | 1 - .../Memory/BufferBackingState.cs | 1 - .../Memory/BufferModifiedRangeList.cs | 1 - .../CodeGen/Glsl/Instructions/InstType.cs | 1 - .../TextureFlags.cs | 1 - .../Translation/AggregateType.cs | 1 - .../Image/SurfaceReader.cs | 1 - src/Ryujinx.Graphics.Vulkan/HelperShader.cs | 1 - .../IndexBufferPattern.cs | 1 - src/Ryujinx.HLE/Debugger/Debugger.Rcmd.cs | 4 -- src/Ryujinx.HLE/Debugger/Debugger.cs | 1 - src/Ryujinx.HLE/FileSystem/ContentMetaData.cs | 2 +- .../Extensions/FileSystemExtensions.cs | 6 +-- .../Extensions/LocalFileSystemExtensions.cs | 2 +- .../Extensions/MetaLoaderExtensions.cs | 46 ------------------- .../Processes/Extensions/NcaExtensions.cs | 38 ++------------- .../PartitionFileSystemExtensions.cs | 11 +---- .../Loaders/Processes/ProcessLoaderHelper.cs | 9 ++-- .../Loaders/Processes/ProcessResult.cs | 4 +- src/Ryujinx.Input.SDL2/SDL2JoyConPair.cs | 2 - .../WindowsShared/PlaceholderManager.cs | 1 - src/Ryujinx.Tests/Memory/PartialUnmaps.cs | 1 - src/Ryujinx/Program.cs | 1 - src/Ryujinx/Systems/AppHost.cs | 16 ++----- .../Systems/AppLibrary/ApplicationLibrary.cs | 3 +- .../UI/ViewModels/MainWindowViewModel.cs | 24 +++++----- src/Ryujinx/UI/Windows/MainWindow.axaml.cs | 10 ++-- src/Ryujinx/Utilities/CommandLineState.cs | 2 +- 55 files changed, 53 insertions(+), 303 deletions(-) delete mode 100644 src/Ryujinx.Common/Logging/LogEventArgsJson.cs delete mode 100644 src/Ryujinx.Common/Logging/LogEventJsonSerializerContext.cs delete mode 100644 src/Ryujinx.Common/Logging/Targets/JsonLogTarget.cs delete mode 100644 src/Ryujinx.Common/ReferenceEqualityComparer.cs diff --git a/Directory.Packages.props b/Directory.Packages.props index 4c3d5bcd3..b2a838496 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -14,10 +14,10 @@ - - + + - + @@ -40,11 +40,11 @@ - + - + @@ -59,4 +59,4 @@ - + \ No newline at end of file diff --git a/distribution/macos/Info.plist b/distribution/macos/Info.plist index 2602f9905..7f7fe0dd4 100644 --- a/distribution/macos/Info.plist +++ b/distribution/macos/Info.plist @@ -34,7 +34,7 @@ CFBundleInfoDictionaryVersion 6.0 CFBundleLongVersionString - %%RYUJINX_BUILD_VERSION%%-%%RYUJINX_BUILD_GIT_HASH%%" + %%RYUJINX_BUILD_VERSION%%-%%RYUJINX_BUILD_GIT_HASH%% CFBundleName Ryujinx CFBundlePackageType @@ -44,13 +44,13 @@ CFBundleSignature ???? CFBundleVersion - 1.2.0 + %%RYUJINX_BUILD_VERSION%% NSHighResolutionCapable CSResourcesFileMapped NSHumanReadableCopyright - Copyright © 2018 - 2023 Ryujinx Team and Contributors. + Copyright © 2018 - 2024 Ryujinx Team and Contributors. Copyright © 2024 - 2025 Ryubing and Contributors. LSApplicationCategoryType public.app-category.games LSMinimumSystemVersion diff --git a/src/ARMeilleure/CodeGen/X86/AssemblerTable.cs b/src/ARMeilleure/CodeGen/X86/AssemblerTable.cs index 4b226803b..ddceae057 100644 --- a/src/ARMeilleure/CodeGen/X86/AssemblerTable.cs +++ b/src/ARMeilleure/CodeGen/X86/AssemblerTable.cs @@ -1,5 +1,4 @@ using System; -using System.Diagnostics.CodeAnalysis; namespace ARMeilleure.CodeGen.X86 { diff --git a/src/ARMeilleure/CodeGen/X86/CodeGenContext.cs b/src/ARMeilleure/CodeGen/X86/CodeGenContext.cs index afae3211f..6d72e0aff 100644 --- a/src/ARMeilleure/CodeGen/X86/CodeGenContext.cs +++ b/src/ARMeilleure/CodeGen/X86/CodeGenContext.cs @@ -2,7 +2,6 @@ using ARMeilleure.CodeGen.RegisterAllocators; using ARMeilleure.IntermediateRepresentation; using Microsoft.IO; using Ryujinx.Common.Memory; -using System.IO; using System.Numerics; namespace ARMeilleure.CodeGen.X86 diff --git a/src/ARMeilleure/CodeGen/X86/X86Register.cs b/src/ARMeilleure/CodeGen/X86/X86Register.cs index bcce4f974..d1394deaa 100644 --- a/src/ARMeilleure/CodeGen/X86/X86Register.cs +++ b/src/ARMeilleure/CodeGen/X86/X86Register.cs @@ -1,5 +1,3 @@ -using System.Diagnostics.CodeAnalysis; - namespace ARMeilleure.CodeGen.X86 { enum X86Register diff --git a/src/ARMeilleure/Instructions/InstEmitMul.cs b/src/ARMeilleure/Instructions/InstEmitMul.cs index cb48deb03..bd2ac8d64 100644 --- a/src/ARMeilleure/Instructions/InstEmitMul.cs +++ b/src/ARMeilleure/Instructions/InstEmitMul.cs @@ -2,7 +2,6 @@ using ARMeilleure.Decoders; using ARMeilleure.IntermediateRepresentation; using ARMeilleure.Translation; using System; -using System.Diagnostics.CodeAnalysis; using static ARMeilleure.Instructions.InstEmitHelper; namespace ARMeilleure.Instructions diff --git a/src/ARMeilleure/IntermediateRepresentation/Intrinsic.cs b/src/ARMeilleure/IntermediateRepresentation/Intrinsic.cs index 9d87c13b3..31dc97bd6 100644 --- a/src/ARMeilleure/IntermediateRepresentation/Intrinsic.cs +++ b/src/ARMeilleure/IntermediateRepresentation/Intrinsic.cs @@ -1,5 +1,4 @@ using System; -using System.Diagnostics.CodeAnalysis; namespace ARMeilleure.IntermediateRepresentation { diff --git a/src/Ryujinx.Audio/Renderer/Dsp/Command/DataSourceVersion2Command.cs b/src/Ryujinx.Audio/Renderer/Dsp/Command/DataSourceVersion2Command.cs index 8b72687da..10723b3db 100644 --- a/src/Ryujinx.Audio/Renderer/Dsp/Command/DataSourceVersion2Command.cs +++ b/src/Ryujinx.Audio/Renderer/Dsp/Command/DataSourceVersion2Command.cs @@ -3,7 +3,6 @@ using Ryujinx.Audio.Renderer.Common; using Ryujinx.Audio.Renderer.Server.Voice; using System; using Ryujinx.Audio.Renderer.Parameter; -using Ryujinx.Memory; using WaveBuffer = Ryujinx.Audio.Renderer.Common.WaveBuffer; namespace Ryujinx.Audio.Renderer.Dsp.Command diff --git a/src/Ryujinx.Audio/Renderer/Dsp/Command/FillBufferCommand.cs b/src/Ryujinx.Audio/Renderer/Dsp/Command/FillBufferCommand.cs index 15ccd5239..c14eeac2b 100644 --- a/src/Ryujinx.Audio/Renderer/Dsp/Command/FillBufferCommand.cs +++ b/src/Ryujinx.Audio/Renderer/Dsp/Command/FillBufferCommand.cs @@ -1,5 +1,4 @@ using Ryujinx.Audio.Renderer.Server.Splitter; -using System; using System.Runtime.CompilerServices; namespace Ryujinx.Audio.Renderer.Dsp.Command diff --git a/src/Ryujinx.Audio/Renderer/Parameter/VoiceInParameter2.cs b/src/Ryujinx.Audio/Renderer/Parameter/VoiceInParameter2.cs index 78e47b69a..bc047759b 100644 --- a/src/Ryujinx.Audio/Renderer/Parameter/VoiceInParameter2.cs +++ b/src/Ryujinx.Audio/Renderer/Parameter/VoiceInParameter2.cs @@ -1,9 +1,6 @@ using Ryujinx.Audio.Common; using Ryujinx.Audio.Renderer.Common; -using Ryujinx.Audio.Renderer.Dsp; using Ryujinx.Common.Memory; -using System; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace Ryujinx.Audio.Renderer.Parameter diff --git a/src/Ryujinx.Audio/Renderer/Server/CommandBuffer.cs b/src/Ryujinx.Audio/Renderer/Server/CommandBuffer.cs index 70564ace9..a2901baf0 100644 --- a/src/Ryujinx.Audio/Renderer/Server/CommandBuffer.cs +++ b/src/Ryujinx.Audio/Renderer/Server/CommandBuffer.cs @@ -10,7 +10,6 @@ using Ryujinx.Audio.Renderer.Server.Upsampler; using Ryujinx.Audio.Renderer.Server.Voice; using Ryujinx.Common; using System; -using System.Runtime.CompilerServices; using CpuAddress = System.UInt64; namespace Ryujinx.Audio.Renderer.Server diff --git a/src/Ryujinx.Audio/Renderer/Server/CommandGenerator.cs b/src/Ryujinx.Audio/Renderer/Server/CommandGenerator.cs index 600f51576..9651d204f 100644 --- a/src/Ryujinx.Audio/Renderer/Server/CommandGenerator.cs +++ b/src/Ryujinx.Audio/Renderer/Server/CommandGenerator.cs @@ -1,6 +1,5 @@ using Ryujinx.Audio.Common; using Ryujinx.Audio.Renderer.Common; -using Ryujinx.Audio.Renderer.Dsp; using Ryujinx.Audio.Renderer.Dsp.Command; using Ryujinx.Audio.Renderer.Dsp.State; using Ryujinx.Audio.Renderer.Parameter; diff --git a/src/Ryujinx.Audio/Renderer/Server/Splitter/SplitterDestinationVersion2.cs b/src/Ryujinx.Audio/Renderer/Server/Splitter/SplitterDestinationVersion2.cs index 7fb455241..cc4cf4466 100644 --- a/src/Ryujinx.Audio/Renderer/Server/Splitter/SplitterDestinationVersion2.cs +++ b/src/Ryujinx.Audio/Renderer/Server/Splitter/SplitterDestinationVersion2.cs @@ -1,4 +1,3 @@ -using Ryujinx.Audio.Renderer.Dsp; using Ryujinx.Audio.Renderer.Parameter; using Ryujinx.Common.Memory; using Ryujinx.Common.Utilities; diff --git a/src/Ryujinx.Audio/Renderer/Server/Voice/VoiceInfo.cs b/src/Ryujinx.Audio/Renderer/Server/Voice/VoiceInfo.cs index c6a4149f8..558a66baa 100644 --- a/src/Ryujinx.Audio/Renderer/Server/Voice/VoiceInfo.cs +++ b/src/Ryujinx.Audio/Renderer/Server/Voice/VoiceInfo.cs @@ -12,7 +12,6 @@ using System.Collections.Generic; using System.Diagnostics; using System.Runtime.InteropServices; using static Ryujinx.Audio.Renderer.Common.BehaviourParameter; -using static Ryujinx.Audio.Renderer.Parameter.VoiceInParameter1; using PlayState = Ryujinx.Audio.Renderer.Server.Types.PlayState; namespace Ryujinx.Audio.Renderer.Server.Voice diff --git a/src/Ryujinx.Common/Logging/LogEventArgsJson.cs b/src/Ryujinx.Common/Logging/LogEventArgsJson.cs deleted file mode 100644 index 7c745d63e..000000000 --- a/src/Ryujinx.Common/Logging/LogEventArgsJson.cs +++ /dev/null @@ -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)); - } - } -} diff --git a/src/Ryujinx.Common/Logging/LogEventJsonSerializerContext.cs b/src/Ryujinx.Common/Logging/LogEventJsonSerializerContext.cs deleted file mode 100644 index ac63d9a10..000000000 --- a/src/Ryujinx.Common/Logging/LogEventJsonSerializerContext.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Text.Json.Serialization; - -namespace Ryujinx.Common.Logging -{ - [JsonSerializable(typeof(LogEventArgsJson))] - internal partial class LogEventJsonSerializerContext : JsonSerializerContext - { - } -} diff --git a/src/Ryujinx.Common/Logging/Logger.cs b/src/Ryujinx.Common/Logging/Logger.cs index 0d8bd3ac3..64a76a3e4 100644 --- a/src/Ryujinx.Common/Logging/Logger.cs +++ b/src/Ryujinx.Common/Logging/Logger.cs @@ -230,14 +230,14 @@ namespace Ryujinx.Common.Logging switch (logLevel) { #pragma warning disable IDE0055 // Disable formatting - case LogLevel.Debug : Debug = enabled ? new Log(LogLevel.Debug) : new Log?(); break; - case LogLevel.Info : Info = enabled ? new Log(LogLevel.Info) : new Log?(); break; - case LogLevel.Warning : Warning = enabled ? new Log(LogLevel.Warning) : new Log?(); break; - case LogLevel.Error : Error = enabled ? new Log(LogLevel.Error) : new Log?(); break; - case LogLevel.Guest : Guest = enabled ? new Log(LogLevel.Guest) : new Log?(); break; - case LogLevel.AccessLog : AccessLog = enabled ? new Log(LogLevel.AccessLog) : new Log?(); break; - case LogLevel.Stub : Stub = enabled ? new Log(LogLevel.Stub) : new Log?(); break; - case LogLevel.Trace : Trace = enabled ? new Log(LogLevel.Trace) : new Log?(); break; + case LogLevel.Debug : Debug = enabled ? new Log(LogLevel.Debug) : null; break; + case LogLevel.Info : Info = enabled ? new Log(LogLevel.Info) : null; break; + case LogLevel.Warning : Warning = enabled ? new Log(LogLevel.Warning) : null; break; + case LogLevel.Error : Error = enabled ? new Log(LogLevel.Error) : null; break; + case LogLevel.Guest : Guest = enabled ? new Log(LogLevel.Guest) : null; break; + case LogLevel.AccessLog : AccessLog = enabled ? new Log(LogLevel.AccessLog) : null; break; + case LogLevel.Stub : Stub = enabled ? new Log(LogLevel.Stub) : null; break; + case LogLevel.Trace : Trace = enabled ? new Log(LogLevel.Trace) : null; break; case LogLevel.Notice : break; default: throw new ArgumentException("Unknown Log Level", nameof(logLevel)); #pragma warning restore IDE0055 diff --git a/src/Ryujinx.Common/Logging/Targets/JsonLogTarget.cs b/src/Ryujinx.Common/Logging/Targets/JsonLogTarget.cs deleted file mode 100644 index 88b324a36..000000000 --- a/src/Ryujinx.Common/Logging/Targets/JsonLogTarget.cs +++ /dev/null @@ -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(); - } - } - } -} diff --git a/src/Ryujinx.Common/Pools/ObjectPool.cs b/src/Ryujinx.Common/Pools/ObjectPool.cs index 65baa00f9..ad56a04a2 100644 --- a/src/Ryujinx.Common/Pools/ObjectPool.cs +++ b/src/Ryujinx.Common/Pools/ObjectPool.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Concurrent; -using System.Threading; namespace Ryujinx.Common { diff --git a/src/Ryujinx.Common/ReferenceEqualityComparer.cs b/src/Ryujinx.Common/ReferenceEqualityComparer.cs deleted file mode 100644 index 714a967a4..000000000 --- a/src/Ryujinx.Common/ReferenceEqualityComparer.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; - -namespace Ryujinx.Common -{ - public class ReferenceEqualityComparer : IEqualityComparer - where T : class - { - public bool Equals(T x, T y) - { - return x == y; - } - - public int GetHashCode([DisallowNull] T obj) - { - return obj.GetHashCode(); - } - } -} diff --git a/src/Ryujinx.Common/ReleaseInformation.cs b/src/Ryujinx.Common/ReleaseInformation.cs index a5beb1009..530dc369e 100644 --- a/src/Ryujinx.Common/ReleaseInformation.cs +++ b/src/Ryujinx.Common/ReleaseInformation.cs @@ -1,10 +1,5 @@ -using Ryujinx.Common.Utilities; using System; -using System.Net.Http; -using System.Net.Http.Json; using System.Reflection; -using System.Text.Json.Serialization; -using System.Threading.Tasks; namespace Ryujinx.Common { diff --git a/src/Ryujinx.Cpu/IExecutionContext.cs b/src/Ryujinx.Cpu/IExecutionContext.cs index c3ebe5aa5..004451f6d 100644 --- a/src/Ryujinx.Cpu/IExecutionContext.cs +++ b/src/Ryujinx.Cpu/IExecutionContext.cs @@ -1,6 +1,5 @@ using ARMeilleure.State; using System; -using System.Threading; namespace Ryujinx.Cpu { diff --git a/src/Ryujinx.Cpu/LightningJit/State/ExecutionContext.cs b/src/Ryujinx.Cpu/LightningJit/State/ExecutionContext.cs index a1ba0002e..27ce0c4a8 100644 --- a/src/Ryujinx.Cpu/LightningJit/State/ExecutionContext.cs +++ b/src/Ryujinx.Cpu/LightningJit/State/ExecutionContext.cs @@ -1,4 +1,3 @@ -using ARMeilleure; using ARMeilleure.Memory; using ARMeilleure.State; using System; diff --git a/src/Ryujinx.Graphics.GAL/ViewportSwizzle.cs b/src/Ryujinx.Graphics.GAL/ViewportSwizzle.cs index 69de93ad5..79fed54e7 100644 --- a/src/Ryujinx.Graphics.GAL/ViewportSwizzle.cs +++ b/src/Ryujinx.Graphics.GAL/ViewportSwizzle.cs @@ -1,5 +1,3 @@ -using System.Diagnostics.CodeAnalysis; - namespace Ryujinx.Graphics.GAL { public enum ViewportSwizzle diff --git a/src/Ryujinx.Graphics.Gpu/Engine/Threed/IndirectDrawType.cs b/src/Ryujinx.Graphics.Gpu/Engine/Threed/IndirectDrawType.cs index 402e3ff80..5260c9233 100644 --- a/src/Ryujinx.Graphics.Gpu/Engine/Threed/IndirectDrawType.cs +++ b/src/Ryujinx.Graphics.Gpu/Engine/Threed/IndirectDrawType.cs @@ -1,5 +1,3 @@ -using System.Diagnostics.CodeAnalysis; - namespace Ryujinx.Graphics.Gpu.Engine.Threed { /// diff --git a/src/Ryujinx.Graphics.Gpu/Engine/Threed/SpecializationStateUpdater.cs b/src/Ryujinx.Graphics.Gpu/Engine/Threed/SpecializationStateUpdater.cs index db8bde751..2fb8de920 100644 --- a/src/Ryujinx.Graphics.Gpu/Engine/Threed/SpecializationStateUpdater.cs +++ b/src/Ryujinx.Graphics.Gpu/Engine/Threed/SpecializationStateUpdater.cs @@ -1,4 +1,3 @@ -using Ryujinx.Common.Memory; using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.Gpu.Engine.Types; using Ryujinx.Graphics.Gpu.Shader; diff --git a/src/Ryujinx.Graphics.Gpu/Engine/Threed/ThreedClass.cs b/src/Ryujinx.Graphics.Gpu/Engine/Threed/ThreedClass.cs index 409dbab41..99cd0c2b2 100644 --- a/src/Ryujinx.Graphics.Gpu/Engine/Threed/ThreedClass.cs +++ b/src/Ryujinx.Graphics.Gpu/Engine/Threed/ThreedClass.cs @@ -1,4 +1,3 @@ -using Ryujinx.Common.Memory; using Ryujinx.Graphics.Device; using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.Gpu.Engine.GPFifo; diff --git a/src/Ryujinx.Graphics.Gpu/Image/FormatTable.cs b/src/Ryujinx.Graphics.Gpu/Image/FormatTable.cs index 8d8b00719..8bfebe8a1 100644 --- a/src/Ryujinx.Graphics.Gpu/Image/FormatTable.cs +++ b/src/Ryujinx.Graphics.Gpu/Image/FormatTable.cs @@ -1,6 +1,5 @@ using Ryujinx.Graphics.GAL; using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; namespace Ryujinx.Graphics.Gpu.Image { diff --git a/src/Ryujinx.Graphics.Gpu/Memory/BufferBackingState.cs b/src/Ryujinx.Graphics.Gpu/Memory/BufferBackingState.cs index 186bea77b..a81e7e98f 100644 --- a/src/Ryujinx.Graphics.Gpu/Memory/BufferBackingState.cs +++ b/src/Ryujinx.Graphics.Gpu/Memory/BufferBackingState.cs @@ -1,7 +1,6 @@ using Ryujinx.Graphics.GAL; using Ryujinx.Memory.Range; using System; -using System.Collections.Generic; namespace Ryujinx.Graphics.Gpu.Memory { diff --git a/src/Ryujinx.Graphics.Gpu/Memory/BufferModifiedRangeList.cs b/src/Ryujinx.Graphics.Gpu/Memory/BufferModifiedRangeList.cs index cd9043059..fee4b11c0 100644 --- a/src/Ryujinx.Graphics.Gpu/Memory/BufferModifiedRangeList.cs +++ b/src/Ryujinx.Graphics.Gpu/Memory/BufferModifiedRangeList.cs @@ -1,6 +1,5 @@ using Ryujinx.Memory.Range; using System; -using System.Collections.Generic; using System.Linq; namespace Ryujinx.Graphics.Gpu.Memory diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstType.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstType.cs index 43ff12168..217c6ae73 100644 --- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstType.cs +++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstType.cs @@ -1,5 +1,4 @@ using System; -using System.Diagnostics.CodeAnalysis; namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions { diff --git a/src/Ryujinx.Graphics.Shader/IntermediateRepresentation/TextureFlags.cs b/src/Ryujinx.Graphics.Shader/IntermediateRepresentation/TextureFlags.cs index 61e6ecf5a..3b0e38542 100644 --- a/src/Ryujinx.Graphics.Shader/IntermediateRepresentation/TextureFlags.cs +++ b/src/Ryujinx.Graphics.Shader/IntermediateRepresentation/TextureFlags.cs @@ -1,5 +1,4 @@ using System; -using System.Diagnostics.CodeAnalysis; namespace Ryujinx.Graphics.Shader.IntermediateRepresentation { diff --git a/src/Ryujinx.Graphics.Shader/Translation/AggregateType.cs b/src/Ryujinx.Graphics.Shader/Translation/AggregateType.cs index 496fbc235..85d58bb0a 100644 --- a/src/Ryujinx.Graphics.Shader/Translation/AggregateType.cs +++ b/src/Ryujinx.Graphics.Shader/Translation/AggregateType.cs @@ -1,5 +1,4 @@ using System; -using System.Diagnostics.CodeAnalysis; namespace Ryujinx.Graphics.Shader.Translation { diff --git a/src/Ryujinx.Graphics.Vic/Image/SurfaceReader.cs b/src/Ryujinx.Graphics.Vic/Image/SurfaceReader.cs index 2747ae805..1411ec939 100644 --- a/src/Ryujinx.Graphics.Vic/Image/SurfaceReader.cs +++ b/src/Ryujinx.Graphics.Vic/Image/SurfaceReader.cs @@ -1,5 +1,4 @@ using Ryujinx.Common.Logging; -using Ryujinx.Common.Memory; using Ryujinx.Graphics.Texture; using Ryujinx.Graphics.Vic.Types; using System; diff --git a/src/Ryujinx.Graphics.Vulkan/HelperShader.cs b/src/Ryujinx.Graphics.Vulkan/HelperShader.cs index c75561690..a60e060c0 100644 --- a/src/Ryujinx.Graphics.Vulkan/HelperShader.cs +++ b/src/Ryujinx.Graphics.Vulkan/HelperShader.cs @@ -4,7 +4,6 @@ using Ryujinx.Graphics.Shader; using Ryujinx.Graphics.Shader.Translation; using Silk.NET.Vulkan; using System; -using System.Collections.Generic; using System.Numerics; using Buffer = Silk.NET.Vulkan.Buffer; using CompareOp = Ryujinx.Graphics.GAL.CompareOp; diff --git a/src/Ryujinx.Graphics.Vulkan/IndexBufferPattern.cs b/src/Ryujinx.Graphics.Vulkan/IndexBufferPattern.cs index 9054b2e71..852634513 100644 --- a/src/Ryujinx.Graphics.Vulkan/IndexBufferPattern.cs +++ b/src/Ryujinx.Graphics.Vulkan/IndexBufferPattern.cs @@ -1,6 +1,5 @@ using Ryujinx.Graphics.GAL; using System; -using System.Collections.Generic; using System.Runtime.InteropServices; namespace Ryujinx.Graphics.Vulkan diff --git a/src/Ryujinx.HLE/Debugger/Debugger.Rcmd.cs b/src/Ryujinx.HLE/Debugger/Debugger.Rcmd.cs index 1dcc0a622..d3094d842 100644 --- a/src/Ryujinx.HLE/Debugger/Debugger.Rcmd.cs +++ b/src/Ryujinx.HLE/Debugger/Debugger.Rcmd.cs @@ -1,12 +1,8 @@ using Gommon; -using JetBrains.Annotations; using Ryujinx.Common.Logging; -using Ryujinx.HLE.HOS.Kernel.Process; -using Ryujinx.HLE.HOS.Kernel.Threading; using System; using System.Collections.Generic; using System.Linq; -using System.Text; namespace Ryujinx.HLE.Debugger { diff --git a/src/Ryujinx.HLE/Debugger/Debugger.cs b/src/Ryujinx.HLE/Debugger/Debugger.cs index 5ffb71ca8..ff928aa90 100644 --- a/src/Ryujinx.HLE/Debugger/Debugger.cs +++ b/src/Ryujinx.HLE/Debugger/Debugger.cs @@ -5,7 +5,6 @@ using Ryujinx.HLE.HOS.Kernel.Process; using Ryujinx.HLE.HOS.Kernel.Threading; using System; using System.Collections.Concurrent; -using System.Diagnostics; using System.Linq; using System.Net.Sockets; using System.Threading; diff --git a/src/Ryujinx.HLE/FileSystem/ContentMetaData.cs b/src/Ryujinx.HLE/FileSystem/ContentMetaData.cs index a1f29bd13..d9699ce5c 100644 --- a/src/Ryujinx.HLE/FileSystem/ContentMetaData.cs +++ b/src/Ryujinx.HLE/FileSystem/ContentMetaData.cs @@ -49,7 +49,7 @@ namespace Ryujinx.HLE.FileSystem string ncaId = Convert.ToHexStringLower(entry.NcaId).Replace("-", null); Nca nca = _pfs.GetNca(keySet, $"/{ncaId}.nca"); - if (nca.GetProgramIndex() == programIndex) + if (nca.ProgramIndex == programIndex) { return nca; } diff --git a/src/Ryujinx.HLE/Loaders/Processes/Extensions/FileSystemExtensions.cs b/src/Ryujinx.HLE/Loaders/Processes/Extensions/FileSystemExtensions.cs index b043f29ef..7373e2f45 100644 --- a/src/Ryujinx.HLE/Loaders/Processes/Extensions/FileSystemExtensions.cs +++ b/src/Ryujinx.HLE/Loaders/Processes/Extensions/FileSystemExtensions.cs @@ -36,7 +36,7 @@ namespace Ryujinx.HLE.Loaders.Processes.Extensions public static ProcessResult Load(this IFileSystem exeFs, Switch device, BlitStruct 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. if (device.Configuration.VirtualFileSystem.ModLoader.ReplaceExefsPartition(programId, ref exeFs)) @@ -118,13 +118,13 @@ namespace Ryujinx.HLE.Loaders.Processes.Extensions modLoadResult.Hash, true, programName, - metaLoader.GetProgramId(), + programId, programIndex, null, nsoExecutables); // 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; } diff --git a/src/Ryujinx.HLE/Loaders/Processes/Extensions/LocalFileSystemExtensions.cs b/src/Ryujinx.HLE/Loaders/Processes/Extensions/LocalFileSystemExtensions.cs index 140be91b5..94a76e12b 100644 --- a/src/Ryujinx.HLE/Loaders/Processes/Extensions/LocalFileSystemExtensions.cs +++ b/src/Ryujinx.HLE/Loaders/Processes/Extensions/LocalFileSystemExtensions.cs @@ -13,7 +13,7 @@ namespace Ryujinx.HLE.Loaders.Processes { MetaLoader metaLoader = exeFs.GetNpdm(); BlitStruct nacpData = new(1); - ulong programId = metaLoader.GetProgramId(); + ulong programId = metaLoader.ProgramId; device.Configuration.VirtualFileSystem.ModLoader.CollectMods([programId]); diff --git a/src/Ryujinx.HLE/Loaders/Processes/Extensions/MetaLoaderExtensions.cs b/src/Ryujinx.HLE/Loaders/Processes/Extensions/MetaLoaderExtensions.cs index f6dab1583..87713a2f7 100644 --- a/src/Ryujinx.HLE/Loaders/Processes/Extensions/MetaLoaderExtensions.cs +++ b/src/Ryujinx.HLE/Loaders/Processes/Extensions/MetaLoaderExtensions.cs @@ -1,61 +1,15 @@ -using LibHac.Common; -using LibHac.Fs; -using LibHac.Fs.Fsa; using LibHac.Loader; -using LibHac.Util; using Ryujinx.Common; -using System; namespace Ryujinx.HLE.Loaders.Processes.Extensions { 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) { byte[] npdmBuffer = EmbeddedResources.Read("Ryujinx.HLE/Homebrew.npdm"); metaLoader.Load(npdmBuffer).ThrowIfFailure(); } - - public static void LoadFromFile(this MetaLoader metaLoader, IFileSystem fileSystem, string path = "") - { - if (string.IsNullOrEmpty(path)) - { - path = ProcessConst.MainNpdmPath; - } - - using UniqueRef npdmFile = new(); - - fileSystem.OpenFile(ref npdmFile.Ref, path.ToU8Span(), OpenMode.Read).ThrowIfFailure(); - - npdmFile.Get.GetSize(out long fileSize).ThrowIfFailure(); - - Span npdmBuffer = new byte[fileSize]; - - npdmFile.Get.Read(out _, 0, npdmBuffer).ThrowIfFailure(); - - metaLoader.Load(npdmBuffer).ThrowIfFailure(); - } } } diff --git a/src/Ryujinx.HLE/Loaders/Processes/Extensions/NcaExtensions.cs b/src/Ryujinx.HLE/Loaders/Processes/Extensions/NcaExtensions.cs index be37078f5..f2dddc866 100644 --- a/src/Ryujinx.HLE/Loaders/Processes/Extensions/NcaExtensions.cs +++ b/src/Ryujinx.HLE/Loaders/Processes/Extensions/NcaExtensions.cs @@ -44,7 +44,7 @@ namespace Ryujinx.HLE.Loaders.Processes.Extensions // Collecting mods related to AocTitleIds and ProgramId. device.Configuration.VirtualFileSystem.ModLoader.CollectMods( - device.Configuration.ContentManager.GetAocTitleIds().Prepend(metaLoader.GetProgramId()), + device.Configuration.ContentManager.GetAocTitleIds().Prepend(metaLoader.ProgramId), ModLoader.GetModsBasePath(), 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. if (romFs == null) @@ -99,38 +99,6 @@ namespace Ryujinx.HLE.Loaders.Processes.Extensions 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) { updatePath = null; @@ -140,7 +108,7 @@ namespace Ryujinx.HLE.Loaders.Processes.Extensions Nca updateControlNca = null; // Clear the program index part. - ulong titleIdBase = mainNca.GetProgramIdBase(); + ulong titleIdBase = mainNca.ProgramIdBase; // Load update information if exists. string titleUpdateMetadataPath = Path.Combine(AppDataManager.GamesDirPath, titleIdBase.ToString("x16"), "updates.json"); diff --git a/src/Ryujinx.HLE/Loaders/Processes/Extensions/PartitionFileSystemExtensions.cs b/src/Ryujinx.HLE/Loaders/Processes/Extensions/PartitionFileSystemExtensions.cs index 798b1f86f..3e7408194 100644 --- a/src/Ryujinx.HLE/Loaders/Processes/Extensions/PartitionFileSystemExtensions.cs +++ b/src/Ryujinx.HLE/Loaders/Processes/Extensions/PartitionFileSystemExtensions.cs @@ -118,7 +118,7 @@ namespace Ryujinx.HLE.Loaders.Processes.Extensions device.Configuration.ContentManager.ClearAocData(); // 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)) { List dlcContainerList = JsonHelper.DeserializeFromFile(addOnContentMetadataPath, _contentSerializerContext.ListDownloadableContentContainer); @@ -149,14 +149,5 @@ namespace Ryujinx.HLE.Loaders.Processes.Extensions return (false, ProcessResult.Failed); } - - public static Nca GetNca(this IFileSystem fileSystem, KeySet keySet, string path) - { - using UniqueRef ncaFile = new(); - - fileSystem.OpenFile(ref ncaFile.Ref, path.ToU8Span(), OpenMode.Read).ThrowIfFailure(); - - return new Nca(keySet, ncaFile.Release().AsStorage()); - } } } diff --git a/src/Ryujinx.HLE/Loaders/Processes/ProcessLoaderHelper.cs b/src/Ryujinx.HLE/Loaders/Processes/ProcessLoaderHelper.cs index 7f0c6b3f5..afd8ebffc 100644 --- a/src/Ryujinx.HLE/Loaders/Processes/ProcessLoaderHelper.cs +++ b/src/Ryujinx.HLE/Loaders/Processes/ProcessLoaderHelper.cs @@ -17,7 +17,6 @@ using Ryujinx.HLE.HOS.Kernel.Common; using Ryujinx.HLE.HOS.Kernel.Memory; using Ryujinx.HLE.HOS.Kernel.Process; using Ryujinx.HLE.Loaders.Executables; -using Ryujinx.HLE.Loaders.Processes.Extensions; using Ryujinx.Horizon.Common; using Ryujinx.Horizon.Sdk.Arp; using System; @@ -44,12 +43,12 @@ namespace Ryujinx.HLE.Loaders.Processes { Nca nca = partitionFileSystem.GetNca(device.FileSystem.KeySet, fileEntry.FullPath); - if (!nca.IsProgram()) + if (!nca.IsProgram) { continue; } - ulong currentMainProgramId = nca.GetProgramIdBase(); + ulong currentMainProgramId = nca.ProgramIdBase; if (applicationId == 0 && currentMainProgramId != 0) { @@ -66,7 +65,7 @@ namespace Ryujinx.HLE.Loaders.Processes break; } - hasIndex[nca.GetProgramIndex()] = true; + hasIndex[nca.ProgramIndex] = true; } if (programCount == 0) @@ -365,7 +364,7 @@ namespace Ryujinx.HLE.Loaders.Processes string displayVersion; - if (metaLoader.GetProgramId() > 0x0100000000007FFF) + if (metaLoader.ProgramId > 0x0100000000007FFF) { displayVersion = applicationControlProperties.Value.DisplayVersionString.ToString(); } diff --git a/src/Ryujinx.HLE/Loaders/Processes/ProcessResult.cs b/src/Ryujinx.HLE/Loaders/Processes/ProcessResult.cs index 18b2b78d1..d6e492317 100644 --- a/src/Ryujinx.HLE/Loaders/Processes/ProcessResult.cs +++ b/src/Ryujinx.HLE/Loaders/Processes/ProcessResult.cs @@ -52,7 +52,7 @@ namespace Ryujinx.HLE.Loaders.Processes if (metaLoader is not null) { - ulong programId = metaLoader.GetProgramId(); + ulong programId = metaLoader.ProgramId; Name = ApplicationControlProperties.Title[(int)titleLanguage].NameString.ToString(); @@ -70,7 +70,7 @@ namespace Ryujinx.HLE.Loaders.Processes DisplayVersion = ApplicationControlProperties.DisplayVersionString.ToString(); ProgramId = programId; ProgramIdText = $"{programId:x16}"; - Is64Bit = metaLoader.IsProgram64Bit(); + Is64Bit = metaLoader.IsProgram64Bit; } DiskCacheEnabled = diskCacheEnabled; diff --git a/src/Ryujinx.Input.SDL2/SDL2JoyConPair.cs b/src/Ryujinx.Input.SDL2/SDL2JoyConPair.cs index be70cc4f9..dce767523 100644 --- a/src/Ryujinx.Input.SDL2/SDL2JoyConPair.cs +++ b/src/Ryujinx.Input.SDL2/SDL2JoyConPair.cs @@ -1,6 +1,4 @@ using Ryujinx.Common.Configuration.Hid; -using Ryujinx.Common.Configuration.Hid.Controller; -using System; using System.Collections.Generic; using System.Linq; using System.Numerics; diff --git a/src/Ryujinx.Memory/WindowsShared/PlaceholderManager.cs b/src/Ryujinx.Memory/WindowsShared/PlaceholderManager.cs index 6ae540178..344a48be6 100644 --- a/src/Ryujinx.Memory/WindowsShared/PlaceholderManager.cs +++ b/src/Ryujinx.Memory/WindowsShared/PlaceholderManager.cs @@ -2,7 +2,6 @@ using Ryujinx.Common; using Ryujinx.Common.Collections; using Ryujinx.Common.Memory.PartialUnmaps; using System; -using System.Collections.Generic; using System.Diagnostics; using System.Runtime.CompilerServices; using System.Runtime.Versioning; diff --git a/src/Ryujinx.Tests/Memory/PartialUnmaps.cs b/src/Ryujinx.Tests/Memory/PartialUnmaps.cs index 1a01a36bc..73a7f7dfc 100644 --- a/src/Ryujinx.Tests/Memory/PartialUnmaps.cs +++ b/src/Ryujinx.Tests/Memory/PartialUnmaps.cs @@ -11,7 +11,6 @@ using Ryujinx.Memory; using Ryujinx.Memory.Tracking; using System; using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; diff --git a/src/Ryujinx/Program.cs b/src/Ryujinx/Program.cs index 509a9f18e..f0e0c2ec3 100644 --- a/src/Ryujinx/Program.cs +++ b/src/Ryujinx/Program.cs @@ -119,7 +119,6 @@ namespace Ryujinx.Ava => ProcessUnhandledException(sender, e.Exception, false); AppDomain.CurrentDomain.ProcessExit += (_, _) => Exit(); - // Setup base data directory. AppDataManager.Initialize(CommandLineState.BaseDirPathArg); diff --git a/src/Ryujinx/Systems/AppHost.cs b/src/Ryujinx/Systems/AppHost.cs index da2b5c80c..0aca8d3a4 100644 --- a/src/Ryujinx/Systems/AppHost.cs +++ b/src/Ryujinx/Systems/AppHost.cs @@ -4,7 +4,6 @@ using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Input; using Avalonia.Threading; using DiscordRPC; -using Gommon; using LibHac.Common; using LibHac.Ns; using Ryujinx.Audio.Backends.Dummy; @@ -480,10 +479,7 @@ namespace Ryujinx.Ava.Systems 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); @@ -903,10 +899,7 @@ namespace Ryujinx.Ava.Systems _viewModel.IsPaused = false; _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"); } @@ -916,10 +909,7 @@ namespace Ryujinx.Ava.Systems _viewModel.IsPaused = true; _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"); } diff --git a/src/Ryujinx/Systems/AppLibrary/ApplicationLibrary.cs b/src/Ryujinx/Systems/AppLibrary/ApplicationLibrary.cs index 7cf111017..2831802fe 100644 --- a/src/Ryujinx/Systems/AppLibrary/ApplicationLibrary.cs +++ b/src/Ryujinx/Systems/AppLibrary/ApplicationLibrary.cs @@ -1,7 +1,6 @@ using DynamicData; using DynamicData.Kernel; using Gommon; -using LibHac; using LibHac.Common; using LibHac.Fs; 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()); - if (!nca.IsProgram() || nca.IsPatch()) + if (!nca.IsProgram || nca.IsPatch) { return false; } diff --git a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs index 7f12a6119..e2aaf60af 100644 --- a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs @@ -1861,14 +1861,14 @@ namespace Ryujinx.Ava.UI.ViewModels /// public static void PreLaunchNotification() { - if (ConfigurationState.Instance.Debug.DebuggerSuspendOnStart.Value) + if (ConfigurationState.Instance.Debug.DebuggerSuspendOnStart) { NotificationHelper.ShowInformation( LocaleManager.Instance[LocaleKeys.NotificationLaunchCheckSuspendOnStartTitle], LocaleManager.Instance[LocaleKeys.NotificationLaunchCheckSuspendOnStartMessage]); } - if (ConfigurationState.Instance.Debug.EnableGdbStub.Value) + if (ConfigurationState.Instance.Debug.EnableGdbStub) { NotificationHelper.ShowInformation( LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.NotificationLaunchCheckGdbStubTitle, ConfigurationState.Instance.Debug.GdbStubPort.Value), @@ -1877,7 +1877,7 @@ namespace Ryujinx.Ava.UI.ViewModels if (ConfigurationState.Instance.System.DramSize.Value != MemoryConfiguration.MemoryConfiguration4GiB) { - var MemoryConfigurationLocaleKey = ConfigurationState.Instance.System.DramSize.Value switch + var memoryConfigurationLocaleKey = ConfigurationState.Instance.System.DramSize.Value switch { MemoryConfiguration.MemoryConfiguration4GiB or MemoryConfiguration.MemoryConfiguration4GiBAppletDev or @@ -1889,10 +1889,11 @@ namespace Ryujinx.Ava.UI.ViewModels _ => LocaleKeys.SettingsTabSystemDramSize4GiB, }; - var MemoryConfigurationLocale = LocaleManager.Instance[MemoryConfigurationLocaleKey]; - NotificationHelper.ShowWarning( - LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.NotificationLaunchCheckDramSizeTitle, MemoryConfigurationLocale), + LocaleManager.Instance.UpdateAndGetDynamicValue( + LocaleKeys.NotificationLaunchCheckDramSizeTitle, + LocaleManager.Instance[memoryConfigurationLocaleKey] + ), LocaleManager.Instance[LocaleKeys.NotificationLaunchCheckDramSizeMessage]); } } @@ -2348,24 +2349,23 @@ namespace Ryujinx.Ava.UI.ViewModels Commands.CreateConditional(vm => vm?.SelectedApplication != null, async viewModel => { - IReadOnlyList result = await viewModel.StorageProvider.OpenFolderPickerAsync( + Optional resOpt = await viewModel.StorageProvider.OpenSingleFolderPickerAsync( new FolderPickerOpenOptions { - Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle], - AllowMultiple = false, + Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle] }); - if (result.Count == 0) + if (!resOpt.TryGet(out IStorageFolder result)) return; ApplicationHelper.ExtractSection( - result[0].Path.LocalPath, + result.Path.LocalPath, NcaSectionType.Logo, viewModel.SelectedApplication.Path, viewModel.SelectedApplication.Name); IStorageFile iconFile = - await result[0].CreateFileAsync($"{viewModel.SelectedApplication.IdString}.png"); + await result.CreateFileAsync($"{viewModel.SelectedApplication.IdString}.png"); await using Stream fileStream = await iconFile.OpenWriteAsync(); using SKBitmap bitmap = SKBitmap.Decode(viewModel.SelectedApplication.Icon) diff --git a/src/Ryujinx/UI/Windows/MainWindow.axaml.cs b/src/Ryujinx/UI/Windows/MainWindow.axaml.cs index 2a7bfa8ef..e363ee2cd 100644 --- a/src/Ryujinx/UI/Windows/MainWindow.axaml.cs +++ b/src/Ryujinx/UI/Windows/MainWindow.axaml.cs @@ -139,15 +139,13 @@ namespace Ryujinx.Ava.UI.Windows Executor.ExecuteBackgroundAsync(async () => { await ShowIntelMacWarningAsync(); - FilePath firmwarePath = CommandLineState.FirmwareToInstallPathArg; - if (firmwarePath is not null) + if (CommandLineState.FirmwareToInstallPathArg.TryGet(out FilePath fwPath)) { - if ((firmwarePath.ExistsAsFile && firmwarePath.Extension is "xci" or "zip") || - firmwarePath.ExistsAsDirectory) + if (fwPath is { ExistsAsFile: true, Extension: "xci" or "zip" } || fwPath.ExistsAsDirectory) { await Dispatcher.UIThread.InvokeAsync(() => - ViewModel.HandleFirmwareInstallation(firmwarePath)); - CommandLineState.FirmwareToInstallPathArg = null; + ViewModel.HandleFirmwareInstallation(fwPath)); + CommandLineState.FirmwareToInstallPathArg = default; } else Logger.Notice.Print(LogClass.UI, "Invalid firmware type provided. Path must be a directory, or a .zip or .xci file."); diff --git a/src/Ryujinx/Utilities/CommandLineState.cs b/src/Ryujinx/Utilities/CommandLineState.cs index f156792a1..28f302e9d 100644 --- a/src/Ryujinx/Utilities/CommandLineState.cs +++ b/src/Ryujinx/Utilities/CommandLineState.cs @@ -19,7 +19,7 @@ namespace Ryujinx.Ava.Utilities public static string OverrideSystemLanguage { get; private set; } public static string OverrideHideCursor { get; private set; } public static string BaseDirPathArg { get; private set; } - public static FilePath FirmwareToInstallPathArg { get; set; } + public static Optional FirmwareToInstallPathArg { get; set; } public static string Profile { get; private set; } public static string LaunchPathArg { get; private set; } public static string LaunchApplicationId { get; private set; }