aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMary <me@thog.eu>2021-02-28 17:20:34 +0100
committerGitHub <noreply@github.com>2021-02-28 17:20:34 +0100
commitd02eeed9c1ba8a8e4d18f18c24588f2953ad7ed6 (patch)
tree2b9b9a56d33210d4e04b6a94b949ef2f1c4af522
parent460a98390eba42262aed3ffcaae72dda7eea5eb5 (diff)
Haydn: Make SoundIO session implementation lock-free (#2068)
* Haydn: Fix race condition in SoundIO Update implementation This should fix weird crashes happening for some people with SoundIO. Fix #2062 * haydn: Make SoundIO session lock-free
-rw-r--r--Ryujinx.Audio.Backends.SoundIo/SoundIoAudioBuffer.cs11
-rw-r--r--Ryujinx.Audio.Backends.SoundIo/SoundIoHardwareDeviceSession.cs57
2 files changed, 28 insertions, 40 deletions
diff --git a/Ryujinx.Audio.Backends.SoundIo/SoundIoAudioBuffer.cs b/Ryujinx.Audio.Backends.SoundIo/SoundIoAudioBuffer.cs
index b43143d6..7f32b953 100644
--- a/Ryujinx.Audio.Backends.SoundIo/SoundIoAudioBuffer.cs
+++ b/Ryujinx.Audio.Backends.SoundIo/SoundIoAudioBuffer.cs
@@ -2,8 +2,15 @@
{
class SoundIoAudioBuffer
{
- public ulong DriverIdentifier;
- public ulong SampleCount;
+ public readonly ulong DriverIdentifier;
+ public readonly ulong SampleCount;
public ulong SamplePlayed;
+
+ public SoundIoAudioBuffer(ulong driverIdentifier, ulong sampleCount)
+ {
+ DriverIdentifier = driverIdentifier;
+ SampleCount = sampleCount;
+ SamplePlayed = 0;
+ }
}
}
diff --git a/Ryujinx.Audio.Backends.SoundIo/SoundIoHardwareDeviceSession.cs b/Ryujinx.Audio.Backends.SoundIo/SoundIoHardwareDeviceSession.cs
index be01ecdc..925a1cb4 100644
--- a/Ryujinx.Audio.Backends.SoundIo/SoundIoHardwareDeviceSession.cs
+++ b/Ryujinx.Audio.Backends.SoundIo/SoundIoHardwareDeviceSession.cs
@@ -3,7 +3,7 @@ using Ryujinx.Audio.Common;
using Ryujinx.Memory;
using SoundIOSharp;
using System;
-using System.Collections.Generic;
+using System.Collections.Concurrent;
using System.Runtime.CompilerServices;
using System.Threading;
@@ -11,10 +11,8 @@ namespace Ryujinx.Audio.Backends.SoundIo
{
class SoundIoHardwareDeviceSession : HardwareDeviceSessionOutputBase
{
- private object _lock = new object();
-
private SoundIoHardwareDeviceDriver _driver;
- private Queue<SoundIoAudioBuffer> _queuedBuffers;
+ private ConcurrentQueue<SoundIoAudioBuffer> _queuedBuffers;
private SoundIOOutStream _outputStream;
private DynamicRingBuffer _ringBuffer;
private ulong _playedSampleCount;
@@ -24,7 +22,7 @@ namespace Ryujinx.Audio.Backends.SoundIo
{
_driver = driver;
_updateRequiredEvent = _driver.GetUpdateRequiredEvent();
- _queuedBuffers = new Queue<SoundIoAudioBuffer>();
+ _queuedBuffers = new ConcurrentQueue<SoundIoAudioBuffer>();
_ringBuffer = new DynamicRingBuffer();
SetupOutputStream();
@@ -42,10 +40,7 @@ namespace Ryujinx.Audio.Backends.SoundIo
public override ulong GetPlayedSampleCount()
{
- lock (_lock)
- {
- return _playedSampleCount;
- }
+ return Interlocked.Read(ref _playedSampleCount);
}
public override float GetVolume()
@@ -57,19 +52,11 @@ namespace Ryujinx.Audio.Backends.SoundIo
public override void QueueBuffer(AudioBuffer buffer)
{
- lock (_lock)
- {
- SoundIoAudioBuffer driverBuffer = new SoundIoAudioBuffer
- {
- DriverIdentifier = buffer.DataPointer,
- SampleCount = GetSampleCount(buffer),
- SamplePlayed = 0,
- };
+ SoundIoAudioBuffer driverBuffer = new SoundIoAudioBuffer(buffer.DataPointer, GetSampleCount(buffer));
- _ringBuffer.Write(buffer.Data, 0, buffer.Data.Length);
+ _ringBuffer.Write(buffer.Data, 0, buffer.Data.Length);
- _queuedBuffers.Enqueue(driverBuffer);
- }
+ _queuedBuffers.Enqueue(driverBuffer);
}
public override void SetVolume(float volume)
@@ -96,15 +83,12 @@ namespace Ryujinx.Audio.Backends.SoundIo
public override bool WasBufferFullyConsumed(AudioBuffer buffer)
{
- lock (_lock)
+ if (!_queuedBuffers.TryPeek(out SoundIoAudioBuffer driverBuffer))
{
- if (!_queuedBuffers.TryPeek(out SoundIoAudioBuffer driverBuffer))
- {
- return true;
- }
-
- return driverBuffer.DriverIdentifier != buffer.DataPointer;
+ return true;
}
+
+ return driverBuffer.DriverIdentifier != buffer.DataPointer;
}
private unsafe void Update(int minFrameCount, int maxFrameCount)
@@ -413,20 +397,20 @@ namespace Ryujinx.Audio.Backends.SoundIo
while (availaibleSampleCount > 0 && _queuedBuffers.TryPeek(out SoundIoAudioBuffer driverBuffer))
{
- ulong sampleStillNeeded = driverBuffer.SampleCount - driverBuffer.SamplePlayed;
+ ulong sampleStillNeeded = driverBuffer.SampleCount - Interlocked.Read(ref driverBuffer.SamplePlayed);
ulong playedAudioBufferSampleCount = Math.Min(sampleStillNeeded, availaibleSampleCount);
- driverBuffer.SamplePlayed += playedAudioBufferSampleCount;
+ Interlocked.Add(ref driverBuffer.SamplePlayed, playedAudioBufferSampleCount);
availaibleSampleCount -= playedAudioBufferSampleCount;
- if (driverBuffer.SamplePlayed == driverBuffer.SampleCount)
+ if (Interlocked.Read(ref driverBuffer.SamplePlayed) == driverBuffer.SampleCount)
{
_queuedBuffers.TryDequeue(out _);
needUpdate = true;
}
- _playedSampleCount += playedAudioBufferSampleCount;
+ Interlocked.Add(ref _playedSampleCount, playedAudioBufferSampleCount);
}
// Notify the output if needed.
@@ -440,15 +424,12 @@ namespace Ryujinx.Audio.Backends.SoundIo
{
if (disposing)
{
- lock (_lock)
- {
- PrepareToClose();
- Stop();
+ PrepareToClose();
+ Stop();
- _outputStream.Dispose();
+ _outputStream.Dispose();
- _driver.Unregister(this);
- }
+ _driver.Unregister(this);
}
}