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
This commit is contained in:
gdkchan 2022-09-09 22:16:24 -03:00 committed by GitHub
parent c64524a240
commit 81f1a4dc31
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 60 additions and 12 deletions

View file

@ -55,7 +55,6 @@ namespace Ryujinx.Audio.Renderer.Server
private uint _processHandle; private uint _processHandle;
private ulong _appletResourceId; private ulong _appletResourceId;
private WritableRegion _workBufferRegion;
private MemoryHandle _workBufferMemoryPin; private MemoryHandle _workBufferMemoryPin;
private Memory<float> _mixBuffer; private Memory<float> _mixBuffer;
@ -98,7 +97,15 @@ namespace Ryujinx.Audio.Renderer.Server
_sessionId = 0; _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<byte> workBufferMemory,
CpuAddress workBuffer,
ulong workBufferSize,
int sessionId,
ulong appletResourceId,
IVirtualMemoryManager memoryManager)
{ {
if (!BehaviourContext.CheckValidRevision(parameter.Revision)) if (!BehaviourContext.CheckValidRevision(parameter.Revision))
{ {
@ -134,11 +141,10 @@ namespace Ryujinx.Audio.Renderer.Server
WorkBufferAllocator workBufferAllocator; WorkBufferAllocator workBufferAllocator;
_workBufferRegion = MemoryManager.GetWritableRegion(workBuffer, (int)workBufferSize); workBufferMemory.Span.Fill(0);
_workBufferRegion.Memory.Span.Fill(0); _workBufferMemoryPin = workBufferMemory.Pin();
_workBufferMemoryPin = _workBufferRegion.Memory.Pin();
workBufferAllocator = new WorkBufferAllocator(_workBufferRegion.Memory); workBufferAllocator = new WorkBufferAllocator(workBufferMemory);
PoolMapper poolMapper = new PoolMapper(processHandle, false); PoolMapper poolMapper = new PoolMapper(processHandle, false);
poolMapper.InitializeSystemPool(ref _dspMemoryPoolState, workBuffer, workBufferSize); poolMapper.InitializeSystemPool(ref _dspMemoryPoolState, workBuffer, workBufferSize);
@ -841,7 +847,6 @@ namespace Ryujinx.Audio.Renderer.Server
_manager.Unregister(this); _manager.Unregister(this);
_terminationEvent.Dispose(); _terminationEvent.Dispose();
_workBufferMemoryPin.Dispose(); _workBufferMemoryPin.Dispose();
_workBufferRegion.Dispose();
if (MemoryManager is IRefCounted rc) if (MemoryManager is IRefCounted rc)
{ {

View file

@ -305,13 +305,34 @@ namespace Ryujinx.Audio.Renderer.Server
/// <param name="workBufferSize">The guest work buffer size.</param> /// <param name="workBufferSize">The guest work buffer size.</param>
/// <param name="processHandle">The process handle of the application.</param> /// <param name="processHandle">The process handle of the application.</param>
/// <returns>A <see cref="ResultCode"/> reporting an error or a success.</returns> /// <returns>A <see cref="ResultCode"/> reporting an error or a success.</returns>
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(); int sessionId = AcquireSessionId();
AudioRenderSystem audioRenderer = new AudioRenderSystem(this, _sessionsSystemEvent[sessionId]); 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<byte> workBufferMemory = GC.AllocateArray<byte>((int)workBufferSize, pinned: true);
ResultCode result = audioRenderer.Initialize(
ref parameter,
processHandle,
workBufferMemory,
workBufferAddress,
workBufferSize,
sessionId,
appletResourceUserId,
memoryManager);
if (result == ResultCode.Success) if (result == ResultCode.Success)
{ {

View file

@ -31,11 +31,26 @@ namespace Ryujinx.HLE.HOS.Services.Audio
return AudioRendererManagerImpl.GetWorkBufferSize(ref parameter); 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; 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) if (result == ResultCode.Success)
{ {

View file

@ -34,7 +34,14 @@ namespace Ryujinx.HLE.HOS.Services.Audio
KTransferMemory workBufferTransferMemory = context.Process.HandleTable.GetObject<KTransferMemory>(transferMemoryHandle); KTransferMemory workBufferTransferMemory = context.Process.HandleTable.GetObject<KTransferMemory>(transferMemoryHandle);
uint processHandle = (uint)context.Request.HandleDesc.ToCopy[1]; 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) if (result == ResultCode.Success)
{ {