mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-09 17:29:21 -10:00
runloop: audio yields to Scanline Sync
With Scanline Sync and audio_sync both live the loop is held by two display-rate clocks in series: each frame waits for the audio buffer to drain, then for the beam to reach the target. Measured at 25 ms per frame - 40 fps - on a 120 Hz panel with 60 fps content, and the overlay read "Audio+Scanline". At matched refresh the frame rate is fine but the two clocks drift against each other with nothing to arbitrate, the same fight VSync + audio_sync has. When the scanline wait holds the loop it is the pace. Audio goes non-blocking and Dynamic Audio Rate Control tracks the display through the resampler ratio, which is what it exists for. The AUDIO bit is cleared so the overlay reports what is actually holding the loop. Restored through the same call every other blocking transition uses when the scanline wait stops - VRR toggled on, calibration lost, setting turned off. Scoped to Scanline Sync only. VSync + audio_sync is the same conflict with a far larger installed base and is not touched here. runloop.h consumers checked; the one failure, gfx/drivers/rsx_gfx.c, is PS3-only and fails identically on HEAD.
This commit is contained in:
1 parent
abcae92539
commit
e88eea9911
2 files changed
+36
No files matched your search
@@ -8312,6 +8312,41 @@ end:
|
||||
runloop_st->pace |= RUNLOOP_PACE_TIMER;
|
||||
}
|
||||
|
||||
/* One display clock at a time: Scanline Sync and audio backpressure.
|
||||
*
|
||||
* With both blocking, each frame waits for the audio buffer to drain
|
||||
* and then for the beam to reach the target, in series - 25 ms per
|
||||
* frame measured on a 120 Hz panel with 60 fps content, and at
|
||||
* matched refresh the two clocks still drift against each other with
|
||||
* no arbiter. When the scanline wait is live it is the pace; audio
|
||||
* goes non-blocking and Dynamic Audio Rate Control tracks the
|
||||
* display through the resampler, which is exactly what it is for.
|
||||
* Restored when the scanline wait stops holding the loop.
|
||||
*
|
||||
* Deliberately not applied to VSync + audio_sync, which is the same
|
||||
* conflict with a far larger installed base; that one is a separate
|
||||
* decision. */
|
||||
if (runloop_st->pace & RUNLOOP_PACE_SCANLINE)
|
||||
{
|
||||
if ( (runloop_st->pace & RUNLOOP_PACE_AUDIO)
|
||||
&& !runloop_st->audio_yielded_to_scanline)
|
||||
{
|
||||
audio_driver_set_nonblock_state(true);
|
||||
runloop_st->audio_yielded_to_scanline = true;
|
||||
}
|
||||
runloop_st->pace &= ~RUNLOOP_PACE_AUDIO;
|
||||
}
|
||||
else if (runloop_st->audio_yielded_to_scanline)
|
||||
{
|
||||
/* Back to whatever audio_sync asks for, via the same call every
|
||||
* other transition uses. */
|
||||
audio_driver_set_nonblock_state(
|
||||
settings->bools.audio_sync
|
||||
? (input_st->flags & INP_FLAG_NONBLOCKING ? true : false)
|
||||
: true);
|
||||
runloop_st->audio_yielded_to_scanline = false;
|
||||
}
|
||||
|
||||
/* if there's a fast forward limit, inject sleeps to keep from going too fast. */
|
||||
{
|
||||
retro_time_t frame_limit_min = runloop_st->frame_limit_minimum_time;
|
||||
|
||||
@@ -182,6 +182,7 @@ struct runloop
|
||||
retro_time_t frame_limit_minimum_time;
|
||||
retro_time_t frame_limit_last_time;
|
||||
unsigned pace; /* enum runloop_pace_source bits */
|
||||
bool audio_yielded_to_scanline; /* audio set non-blocking because Scanline Sync holds the loop */
|
||||
retro_usec_t frame_time_last; /* int64_t alignment */
|
||||
|
||||
/* Per-frame scalar state. Kept adjacent to the timing block above so the
|
||||
|
||||
Reference in new issue
Block a user