From 81f1a4dc3161882b0385c9d4752fbba84b9eca96 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Fri, 9 Sep 2022 22:16:24 -0300 Subject: [PATCH] Allocate work buffer for audio renderer instead of using guest supplied memory (#3276) * Allocate work buffer for audio renderer instead of using guest supplied memory * Typo * Use GC.AllocateArray to allocate pinned array --- .../Renderer/Server/AudioRenderSystem.cs | 19 ++++++++------ .../Renderer/Server/AudioRendererManager.cs | 25 +++++++++++++++++-- .../Services/Audio/AudioRendererManager.cs | 19 ++++++++++++-- .../Audio/AudioRendererManagerServer.cs | 9 ++++++- 4 files changed, 60 insertions(+), 12 deletions(-) diff --git a/Ryujinx.Audio/Renderer/Server/AudioRenderSystem.cs b/Ryujinx.Audio/Renderer/Server/AudioRenderSystem.cs index 904b56f65..af163ae04 100644 --- a/Ryujinx.Audio/Renderer/Server/AudioRenderSystem.cs +++ b/Ryujinx.Audio/Renderer/Server/AudioRenderSystem.cs @@ -55,7 +55,6 @@ namespace Ryujinx.Audio.Renderer.Server private uint _processHandle; private ulong _appletResourceId; - private WritableRegion _workBufferRegion; private MemoryHandle _workBufferMemoryPin; private Memory _mixBuffer; @@ -98,7 +97,15 @@ namespace Ryujinx.Audio.Renderer.Server _sessionId = 0; } - public ResultCode Initialize(ref AudioRendererConfiguration parameter, uint processHandle, CpuAddress workBuffer, ulong workBufferSize, int sessionId, ulong appletResourceId, IVirtualMemoryManager memoryManager) + public ResultCode Initialize( + ref AudioRendererConfiguration parameter, + uint processHandle, + Memory workBufferMemory, + CpuAddress workBuffer, + ulong workBufferSize, + int sessionId, + ulong appletResourceId, + IVirtualMemoryManager memoryManager) { if (!BehaviourContext.CheckValidRevision(parameter.Revision)) { @@ -134,11 +141,10 @@ namespace Ryujinx.Audio.Renderer.Server WorkBufferAllocator workBufferAllocator; - _workBufferRegion = MemoryManager.GetWritableRegion(workBuffer, (int)workBufferSize); - _workBufferRegion.Memory.Span.Fill(0); - _workBufferMemoryPin = _workBufferRegion.Memory.Pin(); + workBufferMemory.Span.Fill(0); + _workBufferMemoryPin = workBufferMemory.Pin(); - workBufferAllocator = new WorkBufferAllocator(_workBufferRegion.Memory); + workBufferAllocator = new WorkBufferAllocator(workBufferMemory); PoolMapper poolMapper = new PoolMapper(processHandle, false); poolMapper.InitializeSystemPool(ref _dspMemoryPoolState, workBuffer, workBufferSize); @@ -841,7 +847,6 @@ namespace Ryujinx.Audio.Renderer.Server _manager.Unregister(this); _terminationEvent.Dispose(); _workBufferMemoryPin.Dispose(); - _workBufferRegion.Dispose(); if (MemoryManager is IRefCounted rc) { diff --git a/Ryujinx.Audio/Renderer/Server/AudioRendererManager.cs b/Ryujinx.Audio/Renderer/Server/AudioRendererManager.cs index 3fbdc58de..4de0ad166 100644 --- a/Ryujinx.Audio/Renderer/Server/AudioRendererManager.cs +++ b/Ryujinx.Audio/Renderer/Server/AudioRendererManager.cs @@ -305,13 +305,34 @@ namespace Ryujinx.Audio.Renderer.Server /// The guest work buffer size. /// The process handle of the application. /// A reporting an error or a success. - public ResultCode OpenAudioRenderer(out AudioRenderSystem renderer, IVirtualMemoryManager memoryManager, ref AudioRendererConfiguration parameter, ulong appletResourceUserId, ulong workBufferAddress, ulong workBufferSize, uint processHandle, float volume) + public ResultCode OpenAudioRenderer( + out AudioRenderSystem renderer, + IVirtualMemoryManager memoryManager, + ref AudioRendererConfiguration parameter, + ulong appletResourceUserId, + ulong workBufferAddress, + ulong workBufferSize, + uint processHandle, + float volume) { int sessionId = AcquireSessionId(); AudioRenderSystem audioRenderer = new AudioRenderSystem(this, _sessionsSystemEvent[sessionId]); - ResultCode result = audioRenderer.Initialize(ref parameter, processHandle, workBufferAddress, workBufferSize, sessionId, appletResourceUserId, memoryManager); + // TODO: Eventually, we should try to use the guest supplied work buffer instead of allocating + // our own. However, it was causing problems on some applications that would unmap the memory + // before the audio renderer was fully disposed. + Memory workBufferMemory = GC.AllocateArray((int)workBufferSize, pinned: true); + + ResultCode result = audioRenderer.Initialize( + ref parameter, + processHandle, + workBufferMemory, + workBufferAddress, + workBufferSize, + sessionId, + appletResourceUserId, + memoryManager); if (result == ResultCode.Success) { diff --git a/Ryujinx.HLE/HOS/Services/Audio/AudioRendererManager.cs b/Ryujinx.HLE/HOS/Services/Audio/AudioRendererManager.cs index 62bd0ba6c..40e71a43b 100644 --- a/Ryujinx.HLE/HOS/Services/Audio/AudioRendererManager.cs +++ b/Ryujinx.HLE/HOS/Services/Audio/AudioRendererManager.cs @@ -31,11 +31,26 @@ namespace Ryujinx.HLE.HOS.Services.Audio return AudioRendererManagerImpl.GetWorkBufferSize(ref parameter); } - public ResultCode OpenAudioRenderer(ServiceCtx context, out IAudioRenderer obj, ref AudioRendererConfiguration parameter, ulong workBufferSize, ulong appletResourceUserId, KTransferMemory workBufferTransferMemory, uint processHandle) + public ResultCode OpenAudioRenderer( + ServiceCtx context, + out IAudioRenderer obj, + ref AudioRendererConfiguration parameter, + ulong workBufferSize, + ulong appletResourceUserId, + KTransferMemory workBufferTransferMemory, + uint processHandle) { var memoryManager = context.Process.HandleTable.GetKProcess((int)processHandle).CpuMemory; - ResultCode result = (ResultCode)_impl.OpenAudioRenderer(out AudioRenderSystem renderer, memoryManager, ref parameter, appletResourceUserId, workBufferTransferMemory.Address, workBufferTransferMemory.Size, processHandle, context.Device.Configuration.AudioVolume); + ResultCode result = (ResultCode)_impl.OpenAudioRenderer( + out AudioRenderSystem renderer, + memoryManager, + ref parameter, + appletResourceUserId, + workBufferTransferMemory.Address, + workBufferTransferMemory.Size, + processHandle, + context.Device.Configuration.AudioVolume); if (result == ResultCode.Success) { diff --git a/Ryujinx.HLE/HOS/Services/Audio/AudioRendererManagerServer.cs b/Ryujinx.HLE/HOS/Services/Audio/AudioRendererManagerServer.cs index a82e0fe8a..c9591c06b 100644 --- a/Ryujinx.HLE/HOS/Services/Audio/AudioRendererManagerServer.cs +++ b/Ryujinx.HLE/HOS/Services/Audio/AudioRendererManagerServer.cs @@ -34,7 +34,14 @@ namespace Ryujinx.HLE.HOS.Services.Audio KTransferMemory workBufferTransferMemory = context.Process.HandleTable.GetObject(transferMemoryHandle); uint processHandle = (uint)context.Request.HandleDesc.ToCopy[1]; - ResultCode result = _impl.OpenAudioRenderer(context, out IAudioRenderer renderer, ref parameter, workBufferSize, appletResourceUserId, workBufferTransferMemory, processHandle); + ResultCode result = _impl.OpenAudioRenderer( + context, + out IAudioRenderer renderer, + ref parameter, + workBufferSize, + appletResourceUserId, + workBufferTransferMemory, + processHandle); if (result == ResultCode.Success) {