mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-07 08:36:02 -10:00
runloop: hold the content rate where Driver Pacing has no backend
With Driver Pacing on and nothing else holding the loop, the backend's release keeps the content's frame period. On a driver without a backend - gl, glcore, or a GPU without the extension - the setting did nothing, and with vsync and audio sync off the loop ran unthrottled. The frame limiter now holds the content's period in exactly the iterations a backend would have owned: a content frame at normal speed, focused, the menu down, and nothing else pacing. Driver Pacing off is unchanged.
This commit is contained in:
1 parent
8ca610dc6e
commit
23f465bf2d
3 files changed
+71
-1
No files matched your search
@@ -6157,9 +6157,11 @@ static runloop_pace_facts_t runloop_driver_pacing_gather(settings_t *settings,
|
||||
{
|
||||
unsigned want = settings->uints.video_driver_pacing;
|
||||
unsigned reason = VIDEO_DRIVER_PACING_REASON_NONE;
|
||||
bool asked;
|
||||
const video_poke_interface_t *poke = video_st->poke;
|
||||
if (want >= VIDEO_DRIVER_PACING_LAST)
|
||||
want = VIDEO_DRIVER_PACING_OFF;
|
||||
asked = want != VIDEO_DRIVER_PACING_OFF;
|
||||
if (!want)
|
||||
reason = VIDEO_DRIVER_PACING_REASON_OFF;
|
||||
else if (!poke || !poke->driver_pacing_set || !video_st->data)
|
||||
@@ -6190,6 +6192,13 @@ static runloop_pace_facts_t runloop_driver_pacing_gather(settings_t *settings,
|
||||
f |= PACE_FACT_DRIVER_PACING;
|
||||
else
|
||||
{
|
||||
/* nothing could take it: runloop_pace_driver_fallback() */
|
||||
if (asked && ( reason == VIDEO_DRIVER_PACING_REASON_DRIVER
|
||||
|| reason == VIDEO_DRIVER_PACING_REASON_DEVICE
|
||||
|| reason == VIDEO_DRIVER_PACING_REASON_SWAPCHAIN
|
||||
|| reason == VIDEO_DRIVER_PACING_REASON_FAILED
|
||||
|| reason == VIDEO_DRIVER_PACING_REASON_CORE))
|
||||
f |= PACE_FACT_DRIVER_PACING_MISSING;
|
||||
runloop_st->driver_pacing_frame_id = 0;
|
||||
video_st->driver_pacing_id = 0;
|
||||
video_st->driver_pacing_interval_us = 0;
|
||||
@@ -10319,6 +10328,14 @@ end:
|
||||
? video_st->video_refresh_rate_original
|
||||
: settings->floats.video_refresh_rate);
|
||||
}
|
||||
else if (runloop_pace_driver_fallback(pace_facts, runloop_st->pace))
|
||||
{
|
||||
runloop_st->pace |= RUNLOOP_PACE_TIMER;
|
||||
pace_limit_min = runloop_content_frame_time_us(
|
||||
video_st->core_hz);
|
||||
pace_limit_ns = runloop_content_frame_time_ns(
|
||||
video_st->core_hz);
|
||||
}
|
||||
|
||||
/* The low-latency backend releases the next frame: the hold is the
|
||||
* driver's signal, taken here where the frame delay would have
|
||||
|
||||
@@ -766,7 +766,10 @@ enum runloop_pace_fact
|
||||
PACE_FACT_FRAME_LIMIT = (1 << 17), /* frame_limit_minimum_time != 0 */
|
||||
PACE_FACT_DRIVER_PACING = (1 << 18), /* the driver's low-latency backend
|
||||
is up and took the mode */
|
||||
PACE_FACT_CORE_RAN = (1 << 19) /* this iteration ran the core */
|
||||
PACE_FACT_CORE_RAN = (1 << 19), /* this iteration ran the core */
|
||||
PACE_FACT_DRIVER_PACING_MISSING = (1 << 20) /* Driver Pacing is on, but
|
||||
the driver has no backend
|
||||
that took it */
|
||||
};
|
||||
|
||||
typedef unsigned runloop_pace_facts_t;
|
||||
@@ -825,6 +828,18 @@ static INLINE unsigned runloop_pace_driver_interval(unsigned pace,
|
||||
return (unsigned)content_period;
|
||||
}
|
||||
|
||||
/* Driver Pacing on a driver with no backend for it (gl, glcore, a GPU
|
||||
* without the extension): where the backend would have owned the
|
||||
* release with nothing else holding the loop, the timer holds it to
|
||||
* the content's period, the interval the backend would have kept. */
|
||||
static INLINE bool runloop_pace_driver_fallback(runloop_pace_facts_t f,
|
||||
unsigned pace)
|
||||
{
|
||||
return (f & PACE_FACT_DRIVER_PACING_MISSING)
|
||||
&& pace == RUNLOOP_PACE_NONE
|
||||
&& runloop_pace_driver_owns(f | PACE_FACT_DRIVER_PACING, pace);
|
||||
}
|
||||
|
||||
static INLINE unsigned runloop_pace_sources(runloop_pace_facts_t f)
|
||||
{
|
||||
unsigned pace = RUNLOOP_PACE_NONE;
|
||||
@@ -896,6 +911,8 @@ static INLINE unsigned runloop_pace_decide(runloop_pace_facts_t f)
|
||||
(f & PACE_FACT_SCANLINE_SYNC) != 0,
|
||||
(f & PACE_FACT_RATE_CONTROL) != 0))
|
||||
pace |= RUNLOOP_PACE_TIMER;
|
||||
else if (runloop_pace_driver_fallback(f, pace))
|
||||
pace |= RUNLOOP_PACE_TIMER;
|
||||
return pace;
|
||||
}
|
||||
|
||||
|
||||
@@ -197,6 +197,41 @@ static void test_driver_pacing(void)
|
||||
"scanline sync, never as a clock\n");
|
||||
}
|
||||
|
||||
/* Driver Pacing on, but nothing that could take it - gl, glcore, a GPU
|
||||
* without the extension: the timer holds the loop where the backend
|
||||
* would have, else vsync off and audio sync off run it unthrottled. */
|
||||
static void test_driver_fallback(void)
|
||||
{
|
||||
runloop_pace_facts_t m = PACE_FACT_FOCUSED | PACE_FACT_CORE_RAN
|
||||
| PACE_FACT_DRIVER_PACING_MISSING | PACE_FACT_PRESENTABLE;
|
||||
|
||||
DRIVER_ROW(m, RUNLOOP_PACE_TIMER,
|
||||
"no backend, nothing else: the timer at the content's period");
|
||||
DRIVER_ROW(m | PACE_FACT_WRAPPER, RUNLOOP_PACE_TIMER,
|
||||
"no backend, threaded, no display pacing: the timer");
|
||||
DRIVER_ROW(m & ~PACE_FACT_DRIVER_PACING_MISSING, RUNLOOP_PACE_NONE,
|
||||
"Driver Pacing off: unthrottled, as before");
|
||||
DRIVER_ROW(m | PACE_FACT_VSYNC, RUNLOOP_PACE_VSYNC,
|
||||
"no backend, vsync: VSync alone");
|
||||
DRIVER_ROW(m | PACE_FACT_AUDIO_HOLDING, RUNLOOP_PACE_AUDIO,
|
||||
"no backend, audio sync: Audio alone");
|
||||
DRIVER_ROW(m | PACE_FACT_WRAPPER | PACE_FACT_DISPLAY_PACING,
|
||||
RUNLOOP_PACE_DISPLAY,
|
||||
"no backend, display pacing: the hold alone");
|
||||
DRIVER_ROW(m | PACE_FACT_RATE_CONTROL, RUNLOOP_PACE_TIMER,
|
||||
"no backend, rate control: the gap limiter");
|
||||
DRIVER_ROW(m | PACE_FACT_MENU_ALIVE, RUNLOOP_PACE_NONE,
|
||||
"no backend, menu up: the menu's own pacing");
|
||||
DRIVER_ROW(m | PACE_FACT_FASTMOTION | PACE_FACT_NONBLOCKING,
|
||||
RUNLOOP_PACE_NONE,
|
||||
"no backend, fast-forward: unthrottled");
|
||||
DRIVER_ROW(m & ~PACE_FACT_FOCUSED, RUNLOOP_PACE_NONE,
|
||||
"no backend, unfocused: as with a backend");
|
||||
|
||||
printf(" driver pacing without a backend: the timer holds the "
|
||||
"content's period exactly where a backend would have\n");
|
||||
}
|
||||
|
||||
/* The interval each owned release hands the driver, from the whole
|
||||
* decision: a release with nothing else holding the loop keeps the
|
||||
* content's rate rather than none. */
|
||||
@@ -911,6 +946,7 @@ int main(void)
|
||||
test_menu_table();
|
||||
test_driver_pacing();
|
||||
test_driver_interval();
|
||||
test_driver_fallback();
|
||||
|
||||
if (failures)
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user