diff options
| author | 2023-03-26 20:21:04 +0100 | |
|---|---|---|
| committer | 2023-03-27 22:01:41 +0100 | |
| commit | 530fe24768357d4151ac6c6aca4a0e122ef8260a (patch) | |
| tree | 8c00084bd414502b7f911274b7ac6bd61626b37c /src | |
| parent | Run clang-format (diff) | |
| download | yuzu-530fe24768357d4151ac6c6aca4a0e122ef8260a.tar.gz yuzu-530fe24768357d4151ac6c6aca4a0e122ef8260a.tar.xz yuzu-530fe24768357d4151ac6c6aca4a0e122ef8260a.zip | |
audio_core: No longer stall when sink queue is full
Now the audout and audren update rates are tied to the sink status stalling is no longer necessary.
Diffstat (limited to 'src')
| -rw-r--r-- | src/audio_core/sink/cubeb_sink.cpp | 4 | ||||
| -rw-r--r-- | src/audio_core/sink/sdl2_sink.cpp | 2 | ||||
| -rw-r--r-- | src/audio_core/sink/sink_stream.cpp | 43 | ||||
| -rw-r--r-- | src/audio_core/sink/sink_stream.h | 16 |
4 files changed, 1 insertions, 64 deletions
diff --git a/src/audio_core/sink/cubeb_sink.cpp b/src/audio_core/sink/cubeb_sink.cpp index 9133f5388..9a0801888 100644 --- a/src/audio_core/sink/cubeb_sink.cpp +++ b/src/audio_core/sink/cubeb_sink.cpp | |||
| @@ -101,8 +101,6 @@ public: | |||
| 101 | ~CubebSinkStream() override { | 101 | ~CubebSinkStream() override { |
| 102 | LOG_DEBUG(Service_Audio, "Destructing cubeb stream {}", name); | 102 | LOG_DEBUG(Service_Audio, "Destructing cubeb stream {}", name); |
| 103 | 103 | ||
| 104 | Unstall(); | ||
| 105 | |||
| 106 | if (!ctx) { | 104 | if (!ctx) { |
| 107 | return; | 105 | return; |
| 108 | } | 106 | } |
| @@ -143,8 +141,6 @@ public: | |||
| 143 | * Stop the sink stream. | 141 | * Stop the sink stream. |
| 144 | */ | 142 | */ |
| 145 | void Stop() override { | 143 | void Stop() override { |
| 146 | Unstall(); | ||
| 147 | |||
| 148 | if (!ctx || paused) { | 144 | if (!ctx || paused) { |
| 149 | return; | 145 | return; |
| 150 | } | 146 | } |
diff --git a/src/audio_core/sink/sdl2_sink.cpp b/src/audio_core/sink/sdl2_sink.cpp index c138dc628..ee1a0652f 100644 --- a/src/audio_core/sink/sdl2_sink.cpp +++ b/src/audio_core/sink/sdl2_sink.cpp | |||
| @@ -88,7 +88,6 @@ public: | |||
| 88 | * Finalize the sink stream. | 88 | * Finalize the sink stream. |
| 89 | */ | 89 | */ |
| 90 | void Finalize() override { | 90 | void Finalize() override { |
| 91 | Unstall(); | ||
| 92 | if (device == 0) { | 91 | if (device == 0) { |
| 93 | return; | 92 | return; |
| 94 | } | 93 | } |
| @@ -116,7 +115,6 @@ public: | |||
| 116 | * Stop the sink stream. | 115 | * Stop the sink stream. |
| 117 | */ | 116 | */ |
| 118 | void Stop() override { | 117 | void Stop() override { |
| 119 | Unstall(); | ||
| 120 | if (device == 0 || paused) { | 118 | if (device == 0 || paused) { |
| 121 | return; | 119 | return; |
| 122 | } | 120 | } |
diff --git a/src/audio_core/sink/sink_stream.cpp b/src/audio_core/sink/sink_stream.cpp index 084ac5edf..f99dbd8ec 100644 --- a/src/audio_core/sink/sink_stream.cpp +++ b/src/audio_core/sink/sink_stream.cpp | |||
| @@ -151,10 +151,6 @@ void SinkStream::ProcessAudioIn(std::span<const s16> input_buffer, std::size_t n | |||
| 151 | return; | 151 | return; |
| 152 | } | 152 | } |
| 153 | 153 | ||
| 154 | if (queued_buffers > max_queue_size) { | ||
| 155 | Stall(); | ||
| 156 | } | ||
| 157 | |||
| 158 | while (frames_written < num_frames) { | 154 | while (frames_written < num_frames) { |
| 159 | // If the playing buffer has been consumed or has no frames, we need a new one | 155 | // If the playing buffer has been consumed or has no frames, we need a new one |
| 160 | if (playing_buffer.consumed || playing_buffer.frames == 0) { | 156 | if (playing_buffer.consumed || playing_buffer.frames == 0) { |
| @@ -189,10 +185,6 @@ void SinkStream::ProcessAudioIn(std::span<const s16> input_buffer, std::size_t n | |||
| 189 | } | 185 | } |
| 190 | 186 | ||
| 191 | std::memcpy(&last_frame[0], &input_buffer[(frames_written - 1) * frame_size], frame_size_bytes); | 187 | std::memcpy(&last_frame[0], &input_buffer[(frames_written - 1) * frame_size], frame_size_bytes); |
| 192 | |||
| 193 | if (queued_buffers <= max_queue_size) { | ||
| 194 | Unstall(); | ||
| 195 | } | ||
| 196 | } | 188 | } |
| 197 | 189 | ||
| 198 | void SinkStream::ProcessAudioOutAndRender(std::span<s16> output_buffer, std::size_t num_frames) { | 190 | void SinkStream::ProcessAudioOutAndRender(std::span<s16> output_buffer, std::size_t num_frames) { |
| @@ -216,20 +208,6 @@ void SinkStream::ProcessAudioOutAndRender(std::span<s16> output_buffer, std::siz | |||
| 216 | return; | 208 | return; |
| 217 | } | 209 | } |
| 218 | 210 | ||
| 219 | // Due to many frames being queued up with nvdec (5 frames or so?), a lot of buffers also get | ||
| 220 | // queued up (30+) but not all at once, which causes constant stalling here, so just let the | ||
| 221 | // video play out without attempting to stall. | ||
| 222 | // Can hopefully remove this later with a more complete NVDEC implementation. | ||
| 223 | const auto nvdec_active{system.AudioCore().IsNVDECActive()}; | ||
| 224 | |||
| 225 | // Core timing cannot be paused in single-core mode, so Stall ends up being called over and over | ||
| 226 | // and never recovers to a normal state, so just skip attempting to sync things on single-core. | ||
| 227 | if (system.IsMulticore() && !nvdec_active && queued_buffers > max_queue_size) { | ||
| 228 | Stall(); | ||
| 229 | } else if (system.IsMulticore() && queued_buffers <= max_queue_size) { | ||
| 230 | Unstall(); | ||
| 231 | } | ||
| 232 | |||
| 233 | while (frames_written < num_frames) { | 211 | while (frames_written < num_frames) { |
| 234 | // If the playing buffer has been consumed or has no frames, we need a new one | 212 | // If the playing buffer has been consumed or has no frames, we need a new one |
| 235 | if (playing_buffer.consumed || playing_buffer.frames == 0) { | 213 | if (playing_buffer.consumed || playing_buffer.frames == 0) { |
| @@ -279,27 +257,6 @@ void SinkStream::ProcessAudioOutAndRender(std::span<s16> output_buffer, std::siz | |||
| 279 | min_played_sample_count = max_played_sample_count; | 257 | min_played_sample_count = max_played_sample_count; |
| 280 | max_played_sample_count += actual_frames_written; | 258 | max_played_sample_count += actual_frames_written; |
| 281 | } | 259 | } |
| 282 | |||
| 283 | if (system.IsMulticore() && queued_buffers <= max_queue_size) { | ||
| 284 | Unstall(); | ||
| 285 | } | ||
| 286 | } | ||
| 287 | |||
| 288 | void SinkStream::Stall() { | ||
| 289 | std::scoped_lock lk{stall_guard}; | ||
| 290 | if (stalled_lock) { | ||
| 291 | return; | ||
| 292 | } | ||
| 293 | stalled_lock = system.StallApplication(); | ||
| 294 | } | ||
| 295 | |||
| 296 | void SinkStream::Unstall() { | ||
| 297 | std::scoped_lock lk{stall_guard}; | ||
| 298 | if (!stalled_lock) { | ||
| 299 | return; | ||
| 300 | } | ||
| 301 | system.UnstallApplication(); | ||
| 302 | stalled_lock.unlock(); | ||
| 303 | } | 260 | } |
| 304 | 261 | ||
| 305 | u64 SinkStream::GetExpectedPlayedSampleCount() { | 262 | u64 SinkStream::GetExpectedPlayedSampleCount() { |
diff --git a/src/audio_core/sink/sink_stream.h b/src/audio_core/sink/sink_stream.h index 9806e6d98..23e289c7b 100644 --- a/src/audio_core/sink/sink_stream.h +++ b/src/audio_core/sink/sink_stream.h | |||
| @@ -55,9 +55,7 @@ struct SinkBuffer { | |||
| 55 | class SinkStream { | 55 | class SinkStream { |
| 56 | public: | 56 | public: |
| 57 | explicit SinkStream(Core::System& system_, StreamType type_) : system{system_}, type{type_} {} | 57 | explicit SinkStream(Core::System& system_, StreamType type_) : system{system_}, type{type_} {} |
| 58 | virtual ~SinkStream() { | 58 | virtual ~SinkStream() {} |
| 59 | Unstall(); | ||
| 60 | } | ||
| 61 | 59 | ||
| 62 | /** | 60 | /** |
| 63 | * Finalize the sink stream. | 61 | * Finalize the sink stream. |
| @@ -203,16 +201,6 @@ public: | |||
| 203 | void ProcessAudioOutAndRender(std::span<s16> output_buffer, std::size_t num_frames); | 201 | void ProcessAudioOutAndRender(std::span<s16> output_buffer, std::size_t num_frames); |
| 204 | 202 | ||
| 205 | /** | 203 | /** |
| 206 | * Stall core processes if the audio thread falls too far behind. | ||
| 207 | */ | ||
| 208 | void Stall(); | ||
| 209 | |||
| 210 | /** | ||
| 211 | * Unstall core processes. | ||
| 212 | */ | ||
| 213 | void Unstall(); | ||
| 214 | |||
| 215 | /** | ||
| 216 | * Get the total number of samples expected to have been played by this stream. | 204 | * Get the total number of samples expected to have been played by this stream. |
| 217 | * | 205 | * |
| 218 | * @return The number of samples. | 206 | * @return The number of samples. |
| @@ -266,8 +254,6 @@ private: | |||
| 266 | /// Signalled when ring buffer entries are consumed | 254 | /// Signalled when ring buffer entries are consumed |
| 267 | std::condition_variable release_cv; | 255 | std::condition_variable release_cv; |
| 268 | std::mutex release_mutex; | 256 | std::mutex release_mutex; |
| 269 | std::mutex stall_guard; | ||
| 270 | std::unique_lock<std::mutex> stalled_lock; | ||
| 271 | }; | 257 | }; |
| 272 | 258 | ||
| 273 | using SinkStreamPtr = std::unique_ptr<SinkStream>; | 259 | using SinkStreamPtr = std::unique_ptr<SinkStream>; |