From ecd626ec5e300be4651f2756783775320a0597c4 Mon Sep 17 00:00:00 2001 From: sonninnos <45124675+sonninnos@users.noreply.github.com> Date: Sat, 28 Sep 2024 00:37:11 +0300 Subject: [PATCH] Automatic Frame Delay: More improvements (#17041) --- gfx/video_driver.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/gfx/video_driver.c b/gfx/video_driver.c index 2e7657e85c..4e00db3288 100644 --- a/gfx/video_driver.c +++ b/gfx/video_driver.c @@ -4121,6 +4121,7 @@ static void video_frame_delay_leftover(video_driver_state_t *video_st, uint8_t *skip_update, uint8_t *video_frame_delay_effective) { + retro_time_t time_now = cpu_features_get_time_usec(); static retro_time_t time_prev = 0; retro_time_t core_run_time = (runloop_st->core_run_time) ? runloop_st->core_run_time : 500; static int16_t frame_time_dev = 0; @@ -4150,8 +4151,8 @@ static void video_frame_delay_leftover(video_driver_state_t *video_st, overtime_count = 0; /* Calibration levels */ - frame_time = cpu_features_get_time_usec() - time_prev; - time_prev = cpu_features_get_time_usec(); + frame_time = (*skip_update) ? frame_time_target : time_now - time_prev; + time_prev = time_now; frame_time_over = frame_time > frame_time_target * 1.75f || core_run_time >= frame_time_target; frame_time_near = abs(frame_time - frame_time_target) < frame_time_target * 0.125f; @@ -4160,9 +4161,12 @@ static void video_frame_delay_leftover(video_driver_state_t *video_st, *skip_update = frame_time_interval; /* No increasing allowed unless safe */ - if (!frame_time_near && frame_delay_cur) + if (!frame_time_near) hold_count += (frame_time > frame_time_target) ? 2 : 1; + if (frame_time_over) + hold_count += frame_time_interval; + /* Overflow looping */ if (hold_count > refresh_rate * 3) hold_count = refresh_rate * 2; @@ -4203,19 +4207,13 @@ static void video_frame_delay_leftover(video_driver_state_t *video_st, if (core_run_time < frame_time_target / 1.5f) hold_count = refresh_rate * 2; } - else if (frame_time_over && core_run_time > frame_time_target * 1.5f) - hold_count = refresh_rate; /* Reserve can't exceed frame time target */ if (video_st->frame_time_reserve > frame_time_target) video_st->frame_time_reserve = (frame_time_target / 1000) * 1000; /* New delay */ - frame_delay_new = (frame_time_target - MAX(video_st->frame_time_reserve, core_run_time)) / 1000; - - /* Limit by target */ - if (frame_delay_new > video_st->frame_delay_target) - frame_delay_new = video_st->frame_delay_target; + frame_delay_new = (frame_time_target - core_run_time - video_st->frame_time_reserve) / 1000; /* Previous frame time excess compensation */ if ( video_st->frame_count > refresh_rate @@ -4224,9 +4222,12 @@ static void video_frame_delay_leftover(video_driver_state_t *video_st, && frame_delay_cur && frame_delay_new && frame_time > frame_time_target + && (abs(frame_time - frame_time_target) >= 1000) && !*skip_update) { - frame_delay_new = frame_delay_cur - ((frame_time - frame_time_target) / 1000); + int delay_delta = round((frame_time - frame_time_target) / 1000.0f); + *skip_update = frame_time_interval; + frame_delay_new -= delay_delta; if (frame_delay_new < 0) frame_delay_new = 0; } @@ -4272,8 +4273,8 @@ static void video_frame_delay_leftover(video_driver_state_t *video_st, /* Make sure leftover never goes below reserve */ if ( frame_delay_cur && frame_delay_new - && core_run_time <= video_st->frame_delay_target * 1000 - && frame_time_target - core_run_time - (frame_delay_new * 1000) < video_st->frame_time_reserve) + && frame_time_target - core_run_time - (frame_delay_new * 1000) < video_st->frame_time_reserve + ) { frame_delay_new--; if (frame_delay_cur != frame_delay_new) @@ -4282,9 +4283,14 @@ static void video_frame_delay_leftover(video_driver_state_t *video_st, /* Decrease hold faster if there is enough leftover */ if ( hold_count + && !frame_time_over && frame_time_target - core_run_time - (frame_delay_new * 1000) > video_st->frame_time_reserve + core_run_time) hold_count--; + /* Limit by target */ + if (frame_delay_new > video_st->frame_delay_target) + frame_delay_new = video_st->frame_delay_target; + /* Reset cumulative frame time deviation count */ if (frame_time_over || frame_delay_new != frame_delay_cur || abs(frame_time_dev) > 1000) frame_time_dev = 0;