From 3d619de114638a9d071a8b913ae879c93b3e1953 Mon Sep 17 00:00:00 2001 From: sonninnos Date: Thu, 9 Jun 2022 01:29:06 +0300 Subject: [PATCH] Automatic Frame Delay improvements --- gfx/video_driver.c | 18 ++++++++++++------ intl/msg_hash_us.h | 10 +++++++++- menu/menu_setting.c | 28 ++++++++++++++++++++++++++++ msg_hash.h | 2 ++ runloop.c | 21 +++++++++++++++++++-- 5 files changed, 70 insertions(+), 9 deletions(-) diff --git a/gfx/video_driver.c b/gfx/video_driver.c index 38c97e190c..972ba89f50 100644 --- a/gfx/video_driver.c +++ b/gfx/video_driver.c @@ -4137,8 +4137,8 @@ void video_frame_delay_auto(video_driver_state_t *video_st, video_frame_delay_au unsigned frame_time_limit_min = frame_time_target * 1.30f; unsigned frame_time_limit_med = frame_time_target * 1.50f; unsigned frame_time_limit_max = frame_time_target * 1.90f; - unsigned frame_time_limit_cap = frame_time_target * 2.50f; - unsigned frame_time_limit_ign = frame_time_target * 3.75f; + unsigned frame_time_limit_cap = frame_time_target * 3.00f; + unsigned frame_time_limit_ign = frame_time_target * 3.50f; unsigned frame_time_min = frame_time_target; unsigned frame_time_max = frame_time_target; unsigned frame_time_count_pos = 0; @@ -4210,9 +4210,14 @@ void video_frame_delay_auto(video_driver_state_t *video_st, video_frame_delay_au /* D3Dx stripe equalizer */ else if ( frame_time_count_pos == frame_time_frames_half - && frame_time_count_min >= 1 - && frame_time_delta > (frame_time_target / 3) - && frame_time_delta < (frame_time_target / 2) + && (( + ( frame_time_count_min > 1 + || frame_time_count_med > 0) + && frame_time_delta > (frame_time_target / 3) + && frame_time_delta < (frame_time_target / 2) + ) + || (frame_time_count_min > 2) + ) && frame_time > frame_time_target ) mode = 3; @@ -4226,7 +4231,8 @@ void video_frame_delay_auto(video_driver_state_t *video_st, video_frame_delay_au ) mode = 4; /* Ignore */ - else if (frame_time_delta > frame_time_target + else if ( + frame_time_delta > frame_time_target && frame_time_count_med == 0 ) mode = -1; diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index 21df6219e1..26fbfbbe45 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -2034,7 +2034,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_VIDEO_FRAME_DELAY, - "Frame Delay" + "Frame Delay (ms)" ) MSG_HASH( MENU_ENUM_SUBLABEL_VIDEO_FRAME_DELAY, @@ -2048,6 +2048,14 @@ MSG_HASH( MENU_ENUM_SUBLABEL_VIDEO_FRAME_DELAY_AUTO, "Decrease effective 'Frame Delay' temporarily to prevent future frame drops. Starting point is half frame time when 'Frame Delay' is 0." ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_VIDEO_FRAME_DELAY_AUTOMATIC, + "Auto" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_VIDEO_FRAME_DELAY_EFFECTIVE, + "effective" + ) MSG_HASH( MENU_ENUM_LABEL_VALUE_VIDEO_HARD_SYNC, "Hard GPU Sync" diff --git a/menu/menu_setting.c b/menu/menu_setting.c index 202016bf1e..d8f34be41e 100644 --- a/menu/menu_setting.c +++ b/menu/menu_setting.c @@ -6355,6 +6355,32 @@ static void setting_get_string_representation_video_swap_interval(rarch_setting_ snprintf(s, len, "%u", *setting->value.target.unsigned_integer); } +static void setting_get_string_representation_video_frame_delay(rarch_setting_t *setting, + char *s, size_t len) +{ + settings_t *settings = config_get_ptr(); + video_driver_state_t *video_st = video_state_get_ptr(); + + if (!setting) + return; + + if (settings && settings->bools.video_frame_delay_auto) + { + if (*setting->value.target.unsigned_integer == 0) + snprintf(s, len, "%s (%u %s)", + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_VIDEO_FRAME_DELAY_AUTOMATIC), + video_st->frame_delay_effective, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_VIDEO_FRAME_DELAY_EFFECTIVE)); + else + snprintf(s, len, "%u (%u %s)", + *setting->value.target.unsigned_integer, + video_st->frame_delay_effective, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_VIDEO_FRAME_DELAY_EFFECTIVE)); + } + 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) { @@ -12588,6 +12614,8 @@ static bool setting_append_list( general_read_handler); (*list)[list_info->index - 1].action_ok = &setting_action_ok_uint; menu_settings_list_current_add_range(list, list_info, 0, MAXIMUM_FRAME_DELAY, 1, true, true); + (*list)[list_info->index - 1].get_string_representation = + &setting_get_string_representation_video_frame_delay; SETTINGS_DATA_LIST_CURRENT_ADD_FLAGS(list, list_info, SD_FLAG_LAKKA_ADVANCED); CONFIG_BOOL( diff --git a/msg_hash.h b/msg_hash.h index 462fffdab1..d58e6efeec 100644 --- a/msg_hash.h +++ b/msg_hash.h @@ -1102,6 +1102,8 @@ enum msg_hash_enums MENU_LABEL(VIDEO_BLACK_FRAME_INSERTION), MENU_LABEL(VIDEO_FRAME_DELAY), MENU_LABEL(VIDEO_FRAME_DELAY_AUTO), + MENU_ENUM_LABEL_VALUE_VIDEO_FRAME_DELAY_AUTOMATIC, + MENU_ENUM_LABEL_VALUE_VIDEO_FRAME_DELAY_EFFECTIVE, MENU_LABEL(VIDEO_SHADER_DELAY), MENU_LABEL(VIDEO_VSYNC), MENU_LABEL(VIDEO_ADAPTIVE_VSYNC), diff --git a/runloop.c b/runloop.c index 4092f01aa8..07e34e4a07 100644 --- a/runloop.c +++ b/runloop.c @@ -7704,6 +7704,8 @@ int runloop_iterate(void) { if (settings->bools.video_frame_delay_auto) { + static bool slowmotion_prev = false; + static unsigned skip_frames = 0; float refresh_rate = settings->floats.video_refresh_rate; unsigned video_swap_interval = runloop_get_video_swap_interval( settings->uints.video_swap_interval); @@ -7714,6 +7716,21 @@ int runloop_iterate(void) video_st->frame_count > frame_time_interval && video_st->frame_count % frame_time_interval == 0; + /* A few frames need to get ignored after slowmotion is disabled */ + if (!runloop_st->slowmotion && slowmotion_prev) + skip_frames = frame_time_interval * 2; + + if (skip_frames) + skip_frames--; + + slowmotion_prev = runloop_st->slowmotion; + /* Always skip when slowmotion is active */ + if (slowmotion_prev) + skip_frames = 1; + + if (skip_frames) + frame_time_update = false; + /* Black frame insertion + swap interval multiplier */ refresh_rate = (refresh_rate / (video_bfi + 1.0f) / video_swap_interval); @@ -7724,7 +7741,7 @@ int runloop_iterate(void) if (video_st->frame_delay_target != video_frame_delay) { video_st->frame_delay_target = video_frame_delay_effective = video_frame_delay; - RARCH_LOG("[Video]: Frame delay reset to %d.\n", video_frame_delay); + RARCH_LOG("[Video]: Frame delay reset to %d ms.\n", video_frame_delay); } if (video_frame_delay_effective > 0 && frame_time_update) @@ -7737,7 +7754,7 @@ int runloop_iterate(void) if (vfda.decrease > 0) { video_frame_delay_effective -= vfda.decrease; - RARCH_LOG("[Video]: Frame delay decrease by %d to %d due to frame time: %d > %d.\n", + RARCH_LOG("[Video]: Frame delay decrease by %d ms to %d ms due to frame time: %d > %d.\n", vfda.decrease, video_frame_delay_effective, vfda.time, vfda.target); } }