mirror of
https://github.com/libretro/RetroArch.git
synced 2024-11-24 16:39:43 +00:00
Merge pull request #13927 from jdgleaver/auto-video-swap-interval
Enable automatic configuration of 'VSync Swap Interval'
This commit is contained in:
commit
dc0054a747
@ -954,10 +954,10 @@ float audio_driver_monitor_adjust_system_rates(
|
||||
unsigned video_swap_interval,
|
||||
float audio_max_timing_skew)
|
||||
{
|
||||
float inp_sample_rate = input_sample_rate;
|
||||
const float target_video_sync_rate = video_refresh_rate
|
||||
/ video_swap_interval;
|
||||
float timing_skew =
|
||||
float inp_sample_rate = input_sample_rate;
|
||||
float target_video_sync_rate = video_refresh_rate
|
||||
/ (float)video_swap_interval;
|
||||
float timing_skew =
|
||||
fabs(1.0f - input_fps / target_video_sync_rate);
|
||||
if (timing_skew <= audio_max_timing_skew)
|
||||
return (inp_sample_rate * target_video_sync_rate / input_fps);
|
||||
|
@ -1740,7 +1740,7 @@ void command_event_reinit(const int flags)
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
bool video_fullscreen = settings->bools.video_fullscreen;
|
||||
bool adaptive_vsync = settings->bools.video_adaptive_vsync;
|
||||
unsigned swap_interval = settings->uints.video_swap_interval;
|
||||
unsigned swap_interval_config = settings->uints.video_swap_interval;
|
||||
#endif
|
||||
enum input_game_focus_cmd_type
|
||||
game_focus_cmd = GAME_FOCUS_CMD_REAPPLY;
|
||||
@ -1775,6 +1775,6 @@ void command_event_reinit(const int flags)
|
||||
video_st->data, false,
|
||||
video_driver_test_all_flags(GFX_CTX_FLAGS_ADAPTIVE_VSYNC) &&
|
||||
adaptive_vsync,
|
||||
swap_interval);
|
||||
runloop_get_video_swap_interval(swap_interval_config));
|
||||
#endif
|
||||
}
|
||||
|
@ -3520,7 +3520,7 @@ static bool config_load_file(global_t *global,
|
||||
if (settings->uints.video_frame_delay > MAXIMUM_FRAME_DELAY)
|
||||
settings->uints.video_frame_delay = MAXIMUM_FRAME_DELAY;
|
||||
|
||||
settings->uints.video_swap_interval = MAX(settings->uints.video_swap_interval, 1);
|
||||
settings->uints.video_swap_interval = MAX(settings->uints.video_swap_interval, 0);
|
||||
settings->uints.video_swap_interval = MIN(settings->uints.video_swap_interval, 4);
|
||||
|
||||
audio_set_float(AUDIO_ACTION_VOLUME_GAIN, settings->floats.audio_volume);
|
||||
|
16
driver.c
16
driver.c
@ -308,6 +308,18 @@ static void driver_adjust_system_rates(
|
||||
double input_sample_rate = info->sample_rate;
|
||||
double input_fps = info->fps;
|
||||
|
||||
/* Update video swap interval if automatic
|
||||
* switching is enabled */
|
||||
runloop_set_video_swap_interval(
|
||||
vrr_runloop_enable,
|
||||
video_st->crt_switching_active,
|
||||
video_swap_interval,
|
||||
audio_max_timing_skew,
|
||||
video_refresh_rate,
|
||||
input_fps);
|
||||
video_swap_interval = runloop_get_video_swap_interval(
|
||||
video_swap_interval);
|
||||
|
||||
if (input_sample_rate > 0.0)
|
||||
{
|
||||
audio_driver_state_t *audio_st = audio_state_get_ptr();
|
||||
@ -341,6 +353,7 @@ static void driver_adjust_system_rates(
|
||||
video_refresh_rate,
|
||||
vrr_runloop_enable,
|
||||
audio_max_timing_skew,
|
||||
video_swap_interval,
|
||||
input_fps))
|
||||
{
|
||||
/* We won't be able to do VSync reliably
|
||||
@ -389,7 +402,8 @@ void driver_set_nonblock_state(void)
|
||||
bool audio_sync = settings->bools.audio_sync;
|
||||
bool video_vsync = settings->bools.video_vsync;
|
||||
bool adaptive_vsync = settings->bools.video_adaptive_vsync;
|
||||
unsigned swap_interval = settings->uints.video_swap_interval;
|
||||
unsigned swap_interval = runloop_get_video_swap_interval(
|
||||
settings->uints.video_swap_interval);
|
||||
bool video_driver_active = video_st->active;
|
||||
bool audio_driver_active = audio_st->active;
|
||||
bool runloop_force_nonblock = runloop_st->force_nonblock;
|
||||
|
@ -702,7 +702,8 @@ void d3d9_make_d3dpp(d3d9_video_t *d3d,
|
||||
if (info->vsync)
|
||||
{
|
||||
settings_t *settings = config_get_ptr();
|
||||
unsigned video_swap_interval = settings->uints.video_swap_interval;
|
||||
unsigned video_swap_interval = runloop_get_video_swap_interval(
|
||||
settings->uints.video_swap_interval);
|
||||
|
||||
switch (video_swap_interval)
|
||||
{
|
||||
|
@ -584,7 +584,8 @@ static void d3d8_make_d3dpp(void *data,
|
||||
if (info->vsync)
|
||||
{
|
||||
settings_t *settings = config_get_ptr();
|
||||
unsigned video_swap_interval = settings->uints.video_swap_interval;
|
||||
unsigned video_swap_interval = runloop_get_video_swap_interval(
|
||||
settings->uints.video_swap_interval);
|
||||
|
||||
switch (video_swap_interval)
|
||||
{
|
||||
|
@ -894,12 +894,16 @@ bool video_driver_monitor_adjust_system_rates(
|
||||
float video_refresh_rate,
|
||||
bool vrr_runloop_enable,
|
||||
float audio_max_timing_skew,
|
||||
unsigned video_swap_interval,
|
||||
double input_fps)
|
||||
{
|
||||
float target_video_sync_rate = timing_skew_hz
|
||||
/ (float)video_swap_interval;
|
||||
|
||||
if (!vrr_runloop_enable)
|
||||
{
|
||||
float timing_skew = fabs(
|
||||
1.0f - input_fps / timing_skew_hz);
|
||||
1.0f - input_fps / target_video_sync_rate);
|
||||
/* We don't want to adjust pitch too much. If we have extreme cases,
|
||||
* just don't readjust at all. */
|
||||
if (timing_skew <= audio_max_timing_skew)
|
||||
@ -909,7 +913,7 @@ bool video_driver_monitor_adjust_system_rates(
|
||||
video_refresh_rate,
|
||||
(float)input_fps);
|
||||
}
|
||||
return input_fps <= timing_skew_hz;
|
||||
return input_fps <= target_video_sync_rate;
|
||||
}
|
||||
|
||||
void video_driver_reset_custom_viewport(settings_t *settings)
|
||||
@ -1166,7 +1170,8 @@ void video_switch_refresh_rate_maybe(
|
||||
float refresh_rate = *refresh_rate_suggest;
|
||||
float video_refresh_rate = settings->floats.video_refresh_rate;
|
||||
unsigned crt_switch_resolution = settings->uints.crt_switch_resolution;
|
||||
unsigned video_swap_interval = settings->uints.video_swap_interval;
|
||||
unsigned video_swap_interval = runloop_get_video_swap_interval(
|
||||
settings->uints.video_swap_interval);
|
||||
unsigned video_bfi = settings->uints.video_black_frame_insertion;
|
||||
bool video_fullscreen = settings->bools.video_fullscreen;
|
||||
bool video_windowed_full = settings->bools.video_windowed_fullscreen;
|
||||
@ -3432,7 +3437,8 @@ bool video_driver_init_internal(bool *video_is_threaded, bool verbosity_enabled)
|
||||
!runloop_st->force_nonblock;
|
||||
video.force_aspect = settings->bools.video_force_aspect;
|
||||
video.font_enable = settings->bools.video_font_enable;
|
||||
video.swap_interval = settings->uints.video_swap_interval;
|
||||
video.swap_interval = runloop_get_video_swap_interval(
|
||||
settings->uints.video_swap_interval);
|
||||
video.adaptive_vsync = settings->bools.video_adaptive_vsync;
|
||||
#ifdef GEKKO
|
||||
video.viwidth = settings->uints.video_viwidth;
|
||||
|
@ -1177,6 +1177,7 @@ bool video_driver_monitor_adjust_system_rates(
|
||||
float video_refresh_rate,
|
||||
bool vrr_runloop_enable,
|
||||
float audio_max_timing_skew,
|
||||
unsigned video_swap_interval,
|
||||
double input_fps);
|
||||
|
||||
void crt_switch_driver_refresh(void);
|
||||
|
@ -1998,7 +1998,11 @@ MSG_HASH(
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_SUBLABEL_VIDEO_SWAP_INTERVAL,
|
||||
"Use a custom swap interval for VSync. Set this to effectively halve monitor refresh rate."
|
||||
"Use a custom swap interval for VSync. Effectively reduces monitor refresh rate by the specified factor. 'Auto' sets factor based on core-reported frame rate, providing improved frame pacing when running e.g. 30 fps content on a 60 Hz display or 60 fps content on a 120 Hz display."
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_VIDEO_SWAP_INTERVAL_AUTO,
|
||||
"Auto"
|
||||
)
|
||||
MSG_HASH(
|
||||
MENU_ENUM_LABEL_VALUE_VIDEO_ADAPTIVE_VSYNC,
|
||||
|
@ -6726,7 +6726,6 @@ void menu_driver_toggle(
|
||||
bool input_overlay_enable = false;
|
||||
#endif
|
||||
bool video_adaptive_vsync = false;
|
||||
bool video_swap_interval = false;
|
||||
|
||||
if (settings)
|
||||
{
|
||||
@ -6744,7 +6743,6 @@ void menu_driver_toggle(
|
||||
input_overlay_enable = settings->bools.input_overlay_enable;
|
||||
#endif
|
||||
video_adaptive_vsync = settings->bools.video_adaptive_vsync;
|
||||
video_swap_interval = settings->uints.video_swap_interval;
|
||||
}
|
||||
|
||||
if (on)
|
||||
@ -6796,15 +6794,18 @@ void menu_driver_toggle(
|
||||
|
||||
menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh);
|
||||
|
||||
/* Menu should always run with vsync on. */
|
||||
/* Menu should always run with vsync on and
|
||||
* a video swap interval of 1 */
|
||||
if (current_video->set_nonblock_state)
|
||||
{
|
||||
current_video->set_nonblock_state(
|
||||
video_driver_data,
|
||||
false,
|
||||
video_driver_test_all_flags(GFX_CTX_FLAGS_ADAPTIVE_VSYNC) &&
|
||||
video_adaptive_vsync,
|
||||
video_swap_interval
|
||||
1
|
||||
);
|
||||
}
|
||||
/* Stop all rumbling before entering the menu. */
|
||||
command_event(CMD_EVENT_RUMBLE_STOP, NULL);
|
||||
|
||||
|
@ -6319,6 +6319,18 @@ static void setting_get_string_representation_uint_cheat_browse_address(
|
||||
}
|
||||
#endif
|
||||
|
||||
static void setting_get_string_representation_video_swap_interval(rarch_setting_t *setting,
|
||||
char *s, size_t len)
|
||||
{
|
||||
if (!setting)
|
||||
return;
|
||||
|
||||
if (*setting->value.target.unsigned_integer == 0)
|
||||
strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_VIDEO_SWAP_INTERVAL_AUTO), len);
|
||||
else
|
||||
snprintf(s, len, "%u", *setting->value.target.unsigned_integer);
|
||||
}
|
||||
|
||||
static void setting_get_string_representation_uint_video_rotation(rarch_setting_t *setting,
|
||||
char *s, size_t len)
|
||||
{
|
||||
@ -12430,9 +12442,10 @@ static bool setting_append_list(
|
||||
general_write_handler,
|
||||
general_read_handler);
|
||||
(*list)[list_info->index - 1].action_ok = &setting_action_ok_uint;
|
||||
(*list)[list_info->index - 1].offset_by = 1;
|
||||
MENU_SETTINGS_LIST_CURRENT_ADD_CMD(list, list_info, CMD_EVENT_VIDEO_SET_BLOCKING_STATE);
|
||||
menu_settings_list_current_add_range(list, list_info, 1, 4, 1, true, true);
|
||||
(*list)[list_info->index - 1].get_string_representation =
|
||||
&setting_get_string_representation_video_swap_interval;
|
||||
MENU_SETTINGS_LIST_CURRENT_ADD_CMD(list, list_info, CMD_EVENT_REINIT);
|
||||
menu_settings_list_current_add_range(list, list_info, 0, 4, 1, true, true);
|
||||
SETTINGS_DATA_LIST_CURRENT_ADD_FLAGS(list, list_info, SD_FLAG_CMD_APPLY_AUTO);
|
||||
SETTINGS_DATA_LIST_CURRENT_ADD_FLAGS(list, list_info, SD_FLAG_LAKKA_ADVANCED);
|
||||
|
||||
|
@ -1138,6 +1138,8 @@ enum msg_hash_enums
|
||||
MENU_LABEL(VIDEO_THREADED),
|
||||
|
||||
MENU_LABEL(VIDEO_SWAP_INTERVAL),
|
||||
MENU_ENUM_LABEL_VALUE_VIDEO_SWAP_INTERVAL_AUTO,
|
||||
|
||||
MENU_LABEL(VIDEO_FULLSCREEN),
|
||||
MENU_LABEL(VIDEO_MONITOR_INDEX),
|
||||
MENU_LABEL(VIDEO_WIIU_PREFER_DRC),
|
||||
|
@ -2405,7 +2405,8 @@ bool command_event(enum event_command cmd, void *data)
|
||||
case CMD_EVENT_VIDEO_SET_BLOCKING_STATE:
|
||||
{
|
||||
bool adaptive_vsync = settings->bools.video_adaptive_vsync;
|
||||
unsigned swap_interval = settings->uints.video_swap_interval;
|
||||
unsigned swap_interval = runloop_get_video_swap_interval(
|
||||
settings->uints.video_swap_interval);
|
||||
video_driver_state_t
|
||||
*video_st = video_state_get_ptr();
|
||||
|
||||
@ -5786,6 +5787,7 @@ bool retroarch_ctl(enum rarch_ctl_state state, void *data)
|
||||
input_game_focus_free();
|
||||
runloop_fastmotion_override_free();
|
||||
runloop_core_options_cb_free();
|
||||
runloop_st->video_swap_interval_auto = 1;
|
||||
memset(&input_st->analog_requested, 0,
|
||||
sizeof(input_st->analog_requested));
|
||||
}
|
||||
|
74
runloop.c
74
runloop.c
@ -3589,6 +3589,7 @@ static void uninit_libretro_symbols(
|
||||
input_game_focus_free();
|
||||
runloop_fastmotion_override_free();
|
||||
runloop_core_options_cb_free();
|
||||
runloop_st->video_swap_interval_auto = 1;
|
||||
camera_st->active = false;
|
||||
location_st->active = false;
|
||||
|
||||
@ -5210,6 +5211,76 @@ float runloop_get_fastforward_ratio(
|
||||
return settings->floats.fastforward_ratio;
|
||||
}
|
||||
|
||||
void runloop_set_video_swap_interval(
|
||||
bool vrr_runloop_enable,
|
||||
bool crt_switching_active,
|
||||
unsigned swap_interval_config,
|
||||
float audio_max_timing_skew,
|
||||
float video_refresh_rate,
|
||||
double input_fps)
|
||||
{
|
||||
runloop_state_t *runloop_st = &runloop_state;
|
||||
float core_hz = input_fps;
|
||||
float timing_hz = crt_switching_active ?
|
||||
input_fps : video_refresh_rate;
|
||||
float swap_ratio;
|
||||
unsigned swap_integer;
|
||||
float timing_skew;
|
||||
|
||||
/* If automatic swap interval selection is
|
||||
* disabled, just record user-set value */
|
||||
if (swap_interval_config != 0)
|
||||
{
|
||||
runloop_st->video_swap_interval_auto =
|
||||
swap_interval_config;
|
||||
return;
|
||||
}
|
||||
|
||||
/* > If VRR is enabled, swap interval is irrelevant,
|
||||
* just set to 1
|
||||
* > If core fps is higher than display refresh rate,
|
||||
* set swap interval to 1
|
||||
* > If core fps or display refresh rate are zero,
|
||||
* set swap interval to 1 */
|
||||
if (vrr_runloop_enable ||
|
||||
(core_hz > timing_hz) ||
|
||||
(core_hz <= 0.0f) ||
|
||||
(timing_hz <= 0.0f))
|
||||
{
|
||||
runloop_st->video_swap_interval_auto = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check whether display refresh rate is an integer
|
||||
* multiple of core fps (within timing skew tolerance) */
|
||||
swap_ratio = timing_hz / core_hz;
|
||||
swap_integer = (unsigned)(swap_ratio + 0.5f);
|
||||
|
||||
/* > Sanity check: swap interval must be in the
|
||||
* range [1,4] - if we are outside this, then
|
||||
* bail... */
|
||||
if ((swap_integer < 1) || (swap_integer > 4))
|
||||
{
|
||||
runloop_st->video_swap_interval_auto = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
timing_skew = fabs(1.0f - core_hz / (timing_hz / (float)swap_integer));
|
||||
|
||||
runloop_st->video_swap_interval_auto =
|
||||
(timing_skew <= audio_max_timing_skew) ?
|
||||
swap_integer : 1;
|
||||
}
|
||||
|
||||
unsigned runloop_get_video_swap_interval(
|
||||
unsigned swap_interval_config)
|
||||
{
|
||||
runloop_state_t *runloop_st = &runloop_state;
|
||||
return (swap_interval_config == 0) ?
|
||||
runloop_st->video_swap_interval_auto :
|
||||
swap_interval_config;
|
||||
}
|
||||
|
||||
unsigned int retroarch_get_rotation(void)
|
||||
{
|
||||
settings_t *settings = config_get_ptr();
|
||||
@ -7634,7 +7705,8 @@ int runloop_iterate(void)
|
||||
if (settings->bools.video_frame_delay_auto)
|
||||
{
|
||||
float refresh_rate = settings->floats.video_refresh_rate;
|
||||
unsigned video_swap_interval = settings->uints.video_swap_interval;
|
||||
unsigned video_swap_interval = runloop_get_video_swap_interval(
|
||||
settings->uints.video_swap_interval);
|
||||
unsigned video_bfi = settings->uints.video_black_frame_insertion;
|
||||
unsigned frame_time_interval = 8;
|
||||
bool frame_time_update =
|
||||
|
11
runloop.h
11
runloop.h
@ -219,6 +219,7 @@ struct runloop
|
||||
unsigned perf_ptr_libretro;
|
||||
unsigned subsystem_current_count;
|
||||
unsigned entry_state_slot;
|
||||
unsigned video_swap_interval_auto;
|
||||
|
||||
fastmotion_overrides_t fastmotion_override; /* float alignment */
|
||||
|
||||
@ -415,6 +416,16 @@ float runloop_get_fastforward_ratio(
|
||||
settings_t *settings,
|
||||
struct retro_fastforwarding_override *fastmotion_override);
|
||||
|
||||
void runloop_set_video_swap_interval(
|
||||
bool vrr_runloop_enable,
|
||||
bool crt_switching_active,
|
||||
unsigned swap_interval_config,
|
||||
float audio_max_timing_skew,
|
||||
float video_refresh_rate,
|
||||
double input_fps);
|
||||
unsigned runloop_get_video_swap_interval(
|
||||
unsigned swap_interval_config);
|
||||
|
||||
void runloop_task_msg_queue_push(
|
||||
retro_task_t *task, const char *msg,
|
||||
unsigned prio, unsigned duration,
|
||||
|
Loading…
Reference in New Issue
Block a user