From f556c80d0230056335632b60c71f1567e177239e Mon Sep 17 00:00:00 2001 From: Mary Date: Fri, 26 Feb 2021 01:11:56 +0100 Subject: Haydn: Part 1 (#2007) * Haydn: Part 1 Based on my reverse of audio 11.0.0. As always, core implementation under LGPLv3 for the same reasons as for Amadeus. This place the bases of a more flexible audio system while making audout & audin accurate. This have the following improvements: - Complete reimplementation of audout and audin. - Audin currently only have a dummy backend. - Dramatically reduce CPU usage by up to 50% in common cases (SoundIO and OpenAL). - Audio Renderer now can output to 5.1 devices when supported. - Audio Renderer init its backend on demand instead of keeping two up all the time. - All backends implementation are now in their own project. - Ryujinx.Audio.Renderer was renamed Ryujinx.Audio and was refactored because of this. As a note, games having issues with OpenAL haven't improved and will not because of OpenAL design (stopping when buffers finish playing causing possible audio "pops" when buffers are very small). * Update for latest hexkyz's edits on Switchbrew * audren: Rollback channel configuration changes * Address gdkchan's comments * Fix typo in OpenAL backend driver * Address last comments * Fix a nit * Address gdkchan's comments --- .../Server/MemoryPool/PoolMapper.cs | 383 --------------------- 1 file changed, 383 deletions(-) delete mode 100644 Ryujinx.Audio.Renderer/Server/MemoryPool/PoolMapper.cs (limited to 'Ryujinx.Audio.Renderer/Server/MemoryPool/PoolMapper.cs') diff --git a/Ryujinx.Audio.Renderer/Server/MemoryPool/PoolMapper.cs b/Ryujinx.Audio.Renderer/Server/MemoryPool/PoolMapper.cs deleted file mode 100644 index b255960c..00000000 --- a/Ryujinx.Audio.Renderer/Server/MemoryPool/PoolMapper.cs +++ /dev/null @@ -1,383 +0,0 @@ -// -// Copyright (c) 2019-2021 Ryujinx -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with this program. If not, see . -// - -using Ryujinx.Audio.Renderer.Common; -using Ryujinx.Audio.Renderer.Parameter; -using Ryujinx.Audio.Renderer.Utils; -using Ryujinx.Common.Logging; -using System; -using static Ryujinx.Audio.Renderer.Common.BehaviourParameter; - -using CpuAddress = System.UInt64; -using DspAddress = System.UInt64; - -namespace Ryujinx.Audio.Renderer.Server.MemoryPool -{ - /// - /// Memory pool mapping helper. - /// - public class PoolMapper - { - const uint CurrentProcessPseudoHandle = 0xFFFF8001; - - /// - /// The result of . - /// - public enum UpdateResult : uint - { - /// - /// No error reported. - /// - Success = 0, - - /// - /// The user parameters were invalid. - /// - InvalidParameter = 1, - - /// - /// mapping failed. - /// - MapError = 2, - - /// - /// unmapping failed. - /// - UnmapError = 3 - } - - /// - /// The handle of the process owning the CPU memory manipulated. - /// - private uint _processHandle; - - /// - /// The that will be manipulated. - /// - private Memory _memoryPools; - - /// - /// If set to true, this will try to force map memory pool even if their state are considered invalid. - /// - private bool _isForceMapEnabled; - - /// - /// Create a new used for system mapping. - /// - /// The handle of the process owning the CPU memory manipulated. - /// If set to true, this will try to force map memory pool even if their state are considered invalid. - public PoolMapper(uint processHandle, bool isForceMapEnabled) - { - _processHandle = processHandle; - _isForceMapEnabled = isForceMapEnabled; - _memoryPools = Memory.Empty; - } - - /// - /// Create a new used for user mapping. - /// - /// The handle of the process owning the CPU memory manipulated. - /// The user memory pools. - /// If set to true, this will try to force map memory pool even if their state are considered invalid. - public PoolMapper(uint processHandle, Memory memoryPool, bool isForceMapEnabled) - { - _processHandle = processHandle; - _memoryPools = memoryPool; - _isForceMapEnabled = isForceMapEnabled; - } - - /// - /// Initialize the for system use. - /// - /// The for system use. - /// The to assign. - /// The size to assign. - /// Returns true if mapping on the succeeded. - public bool InitializeSystemPool(ref MemoryPoolState memoryPool, CpuAddress cpuAddress, ulong size) - { - if (memoryPool.Location != MemoryPoolState.LocationType.Dsp) - { - return false; - } - - return InitializePool(ref memoryPool, cpuAddress, size); - } - - /// - /// Initialize the . - /// - /// The . - /// The to assign. - /// The size to assign. - /// Returns true if mapping on the succeeded. - public bool InitializePool(ref MemoryPoolState memoryPool, CpuAddress cpuAddress, ulong size) - { - memoryPool.SetCpuAddress(cpuAddress, size); - - return Map(ref memoryPool) != 0; - } - - /// - /// Get the process handle associated to the . - /// - /// The . - /// Returns the process handle associated to the . - public uint GetProcessHandle(ref MemoryPoolState memoryPool) - { - if (memoryPool.Location == MemoryPoolState.LocationType.Cpu) - { - return CurrentProcessPseudoHandle; - } - else if (memoryPool.Location == MemoryPoolState.LocationType.Dsp) - { - return _processHandle; - } - - return 0; - } - - /// - /// Map the on the . - /// - /// The to map. - /// Returns the DSP address mapped. - public DspAddress Map(ref MemoryPoolState memoryPool) - { - DspAddress result = AudioProcessorMemoryManager.Map(GetProcessHandle(ref memoryPool), memoryPool.CpuAddress, memoryPool.Size); - - if (result != 0) - { - memoryPool.DspAddress = result; - } - - return result; - } - - /// - /// Unmap the from the . - /// - /// The to unmap. - /// Returns true if unmapped. - public bool Unmap(ref MemoryPoolState memoryPool) - { - if (memoryPool.IsUsed) - { - return false; - } - - AudioProcessorMemoryManager.Unmap(GetProcessHandle(ref memoryPool), memoryPool.CpuAddress, memoryPool.Size); - - memoryPool.SetCpuAddress(0, 0); - memoryPool.DspAddress = 0; - - return true; - } - - /// - /// Find a associated to the region given. - /// - /// The region . - /// The region size. - /// Returns the found or if not found. - private Span FindMemoryPool(CpuAddress cpuAddress, ulong size) - { - if (!_memoryPools.IsEmpty && _memoryPools.Length > 0) - { - for (int i = 0; i < _memoryPools.Length; i++) - { - if (_memoryPools.Span[i].Contains(cpuAddress, size)) - { - return _memoryPools.Span.Slice(i, 1); - } - } - } - - return Span.Empty; - } - - /// - /// Force unmap the given . - /// - /// The to force unmap - public void ForceUnmap(ref AddressInfo addressInfo) - { - if (_isForceMapEnabled) - { - Span memoryPool = FindMemoryPool(addressInfo.CpuAddress, addressInfo.Size); - - if (!memoryPool.IsEmpty) - { - AudioProcessorMemoryManager.Unmap(_processHandle, memoryPool[0].CpuAddress, memoryPool[0].Size); - - return; - } - - AudioProcessorMemoryManager.Unmap(_processHandle, addressInfo.CpuAddress, 0); - } - } - - /// - /// Try to attach the given region to the . - /// - /// The error information if an error was generated. - /// The to attach the region to. - /// The region . - /// The region size. - /// Returns true if mapping was performed. - public bool TryAttachBuffer(out ErrorInfo errorInfo, ref AddressInfo addressInfo, CpuAddress cpuAddress, ulong size) - { - errorInfo = new ErrorInfo(); - - addressInfo.Setup(cpuAddress, size); - - if (AssignDspAddress(ref addressInfo)) - { - errorInfo.ErrorCode = 0x0; - errorInfo.ExtraErrorInfo = 0x0; - - return true; - } - else - { - errorInfo.ErrorCode = ResultCode.InvalidAddressInfo; - errorInfo.ExtraErrorInfo = addressInfo.CpuAddress; - - return _isForceMapEnabled; - } - } - - /// - /// Update a using user parameters. - /// - /// The to update. - /// Input user parameter. - /// Output user parameter. - /// Returns the of the operations performed. - public UpdateResult Update(ref MemoryPoolState memoryPool, ref MemoryPoolInParameter inParameter, ref MemoryPoolOutStatus outStatus) - { - MemoryPoolUserState inputState = inParameter.State; - - MemoryPoolUserState outputState; - - const uint pageSize = 0x1000; - - if (inputState != MemoryPoolUserState.RequestAttach && inputState != MemoryPoolUserState.RequestDetach) - { - return UpdateResult.Success; - } - - if (inParameter.CpuAddress == 0 || (inParameter.CpuAddress & (pageSize - 1)) != 0) - { - return UpdateResult.InvalidParameter; - } - - if (inParameter.Size == 0 || (inParameter.Size & (pageSize - 1)) != 0) - { - return UpdateResult.InvalidParameter; - } - - if (inputState == MemoryPoolUserState.RequestAttach) - { - bool initializeSuccess = InitializePool(ref memoryPool, inParameter.CpuAddress, inParameter.Size); - - if (!initializeSuccess) - { - memoryPool.SetCpuAddress(0, 0); - - Logger.Error?.Print(LogClass.AudioRenderer, $"Map of memory pool (address: 0x{inParameter.CpuAddress:x}, size 0x{inParameter.Size:x}) failed!"); - return UpdateResult.MapError; - } - - outputState = MemoryPoolUserState.Attached; - } - else - { - if (memoryPool.CpuAddress != inParameter.CpuAddress || memoryPool.Size != inParameter.Size) - { - return UpdateResult.InvalidParameter; - } - - if (!Unmap(ref memoryPool)) - { - Logger.Error?.Print(LogClass.AudioRenderer, $"Unmap of memory pool (address: 0x{memoryPool.CpuAddress:x}, size 0x{memoryPool.Size:x}) failed!"); - return UpdateResult.UnmapError; - } - - outputState = MemoryPoolUserState.Detached; - } - - outStatus.State = outputState; - - return UpdateResult.Success; - } - - /// - /// Map the to the . - /// - /// The to map. - /// Returns true if mapping was performed. - private bool AssignDspAddress(ref AddressInfo addressInfo) - { - if (addressInfo.CpuAddress == 0) - { - return false; - } - - if (_memoryPools.Length > 0) - { - Span memoryPool = FindMemoryPool(addressInfo.CpuAddress, addressInfo.Size); - - if (!memoryPool.IsEmpty) - { - addressInfo.SetupMemoryPool(memoryPool); - - return true; - } - } - - if (_isForceMapEnabled) - { - DspAddress dspAddress = AudioProcessorMemoryManager.Map(_processHandle, addressInfo.CpuAddress, addressInfo.Size); - - addressInfo.ForceMappedDspAddress = dspAddress; - - AudioProcessorMemoryManager.Map(_processHandle, addressInfo.CpuAddress, addressInfo.Size); - } - else - { - unsafe - { - addressInfo.SetupMemoryPool(MemoryPoolState.Null); - } - } - - return false; - } - - /// - /// Remove the usage flag from all the . - /// - /// The to reset. - public static void ClearUsageState(Memory memoryPool) - { - foreach (ref MemoryPoolState info in memoryPool.Span) - { - info.IsUsed = false; - } - } - } -} -- cgit v1.2.3