Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Frame limiting improvements #15391

Merged
merged 1 commit into from
Jun 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 6 additions & 8 deletions audio/audio_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -797,10 +797,8 @@ bool audio_driver_init_internal(
#endif

/* Threaded driver is initially stopped. */
if (
(audio_driver_st.flags & AUDIO_FLAG_ACTIVE)
&& audio_cb_inited
)
if ( (audio_driver_st.flags & AUDIO_FLAG_ACTIVE)
&& audio_cb_inited)
audio_driver_start(false);

return true;
Expand Down Expand Up @@ -1444,7 +1442,8 @@ void audio_driver_load_system_sounds(void)
task_push_audio_mixer_load(path_ok, NULL, NULL, true, AUDIO_MIXER_SLOT_SELECTION_MANUAL, AUDIO_MIXER_SYSTEM_SLOT_OK);
if (path_cancel && audio_enable_menu_cancel)
task_push_audio_mixer_load(path_cancel, NULL, NULL, true, AUDIO_MIXER_SLOT_SELECTION_MANUAL, AUDIO_MIXER_SYSTEM_SLOT_CANCEL);
if (audio_enable_menu_notice) {
if (audio_enable_menu_notice)
{
if (path_notice)
task_push_audio_mixer_load(path_notice, NULL, NULL, true, AUDIO_MIXER_SLOT_SELECTION_MANUAL, AUDIO_MIXER_SYSTEM_SLOT_NOTICE);
if (path_notice_back)
Expand Down Expand Up @@ -1882,11 +1881,10 @@ void audio_driver_menu_sample(void)
struct retro_system_av_info *av_info = &video_st->av_info;
const struct retro_system_timing *info =
(const struct retro_system_timing*)&av_info->timing;
unsigned sample_count = (info->sample_rate / info->fps) * 2;
unsigned sample_count = floor(info->sample_rate / info->fps) * 2;
audio_driver_state_t *audio_st = &audio_driver_st;
bool check_flush = !(
(runloop_flags & RUNLOOP_FLAG_PAUSED)
|| !(audio_st->flags & AUDIO_FLAG_ACTIVE)
!(audio_st->flags & AUDIO_FLAG_ACTIVE)
|| !audio_st->output_samples_buf);
if ((audio_st->flags & AUDIO_FLAG_SUSPENDED))
check_flush = false;
Expand Down
7 changes: 3 additions & 4 deletions audio/audio_driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ typedef struct
* up to (but excluding) the point where it's converted to 16-bit audio
* to give to the driver.
*/
float *output_samples_buf;
float *output_samples_buf;
size_t output_samples_buf_length;
#ifdef HAVE_REWIND
int16_t *rewind_buf;
Expand Down Expand Up @@ -229,8 +229,7 @@ typedef struct
size_t buffer_size;
size_t data_ptr;

unsigned free_samples_buf[
AUDIO_BUFFER_FREE_SAMPLES_COUNT];
unsigned free_samples_buf[AUDIO_BUFFER_FREE_SAMPLES_COUNT];

#ifdef HAVE_AUDIOMIXER
float mixer_volume_gain;
Expand All @@ -252,7 +251,7 @@ typedef struct
#endif

/* Sample the flush delta-time when fast forwarding to find the correct
ressample ratio. */
resample ratio. */
retro_time_t last_flush_time;
/* Exponential moving average */
retro_time_t avg_flush_delta;
Expand Down
80 changes: 61 additions & 19 deletions gfx/video_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@
#include "../menu/menu_driver.h"
#endif

#ifdef HAVE_NETWORKING
#include "../network/netplay/netplay.h"
#endif

#ifdef _WIN32
#include "common/win32_common.h"
#endif
Expand Down Expand Up @@ -1677,7 +1681,6 @@ void video_driver_set_size(unsigned width, unsigned height)
* false (0) if:
* a) threaded video mode is enabled
* b) less than 2 frame time samples.
* c) FPS monitor enable is off.
**/
bool video_monitor_fps_statistics(double *refresh_rate,
double *deviation, unsigned *sample_points)
Expand Down Expand Up @@ -2525,8 +2528,34 @@ void video_driver_build_info(video_frame_info_t *video_info)
video_info->runloop_is_slowmotion = runloop_st->flags & RUNLOOP_FLAG_SLOWMOTION;
video_info->fastforward_frameskip = settings->bools.fastforward_frameskip;

video_info->input_driver_nonblock_state = input_st
? (input_st->flags & INP_FLAG_NONBLOCKING) : false;
#ifdef _WIN32
#ifdef HAVE_VULKAN
/* Vulkan in Windows does mailbox emulation
* in fullscreen with vsync, effectively
* discarding frames that can't be shown,
* therefore do not do it twice. */
if ( string_is_equal(video_driver_get_ident(), "vulkan")
sonninnos marked this conversation as resolved.
Show resolved Hide resolved
&& settings->bools.video_vsync
&& video_info->fullscreen)
video_info->fastforward_frameskip = false;
#endif
#endif

#ifdef HAVE_MENU
/* Count paused running menu also as paused runloop. */
if (video_info->menu_is_alive)
{
#ifdef HAVE_NETWORKING
video_info->runloop_is_paused |= settings->bools.menu_pause_libretro &&
netplay_driver_ctl(RARCH_NETPLAY_CTL_ALLOW_PAUSE, NULL);
#else
video_info->runloop_is_paused |= settings->bools.menu_pause_libretro;
#endif
video_info->runloop_is_paused |= !video_info->libretro_running;
}
#endif

video_info->input_driver_nonblock_state = input_st ? (input_st->flags & INP_FLAG_NONBLOCKING) : false;
video_info->input_driver_grab_mouse_state = (input_st->flags & INP_FLAG_GRAB_MOUSE_STATE);
video_info->disp_userdata = disp_get_ptr();

Expand Down Expand Up @@ -3258,6 +3287,7 @@ void video_driver_frame(const void *data, unsigned width,
video_st->frame_cache_width = width;
video_st->frame_cache_height = height;
video_st->frame_cache_pitch = pitch;
video_st->frame_discard = false;

if (
video_st->scaler_ptr
Expand All @@ -3276,23 +3306,30 @@ void video_driver_frame(const void *data, unsigned width,

video_driver_build_info(&video_info);

/* Take target refresh rate as initial FPS value instead of 0.00 */
if (!last_fps)
last_fps = video_info.refresh_rate;

/* If fast forward is active and fast forward
* frame skipping is enabled, drop any frames
* that occur at a rate higher than the core-set
* frame skipping is enabled, and when
* paused or menu active, drop any frames
* that occur at a rate higher than display
* refresh rate. However: We must always render
* the current frame when:
* - The menu is open
* - The last frame was NULL and the
* current frame is not (i.e. if core was
* previously sending duped frames, ensure
* that the next frame update is captured) */
if ( video_info.input_driver_nonblock_state
&& video_info.fastforward_frameskip
&& !(video_info.menu_is_alive
|| (last_frame_duped && !!data)))
if ( ( video_info.input_driver_nonblock_state
&& video_info.fastforward_frameskip
&& !(last_frame_duped && !!data)
)
|| video_info.runloop_is_paused
)
{
retro_time_t frame_time_accumulator_prev = frame_time_accumulator;
retro_time_t frame_time_delta = new_time - last_time;
retro_time_t frame_time_target = 1000000.0f / video_info.refresh_rate;

/* Ignore initial previous frame time
* to prevent rubber band startup */
Expand All @@ -3301,6 +3338,10 @@ void video_driver_frame(const void *data, unsigned width,
else if (nonblock_active < 0)
nonblock_active = 1;

/* Plain paused and unrestricted menu rendering require harsh limiting */
if (video_info.runloop_is_paused)
video_st->frame_discard = true;

/* Accumulate the elapsed time since the
* last frame */
if (nonblock_active > 0)
Expand All @@ -3309,18 +3350,18 @@ void video_driver_frame(const void *data, unsigned width,
/* Render frame if the accumulated time is
* greater than or equal to the expected
* core frame time */
render_frame = frame_time_accumulator >=
video_st->core_frame_time;
render_frame = frame_time_accumulator >= frame_time_target;

/* If frame is to be rendered, subtract
* expected frame time from accumulator */
if (render_frame)
{
frame_time_accumulator -= video_st->core_frame_time;
video_st->frame_discard = false;
frame_time_accumulator -= frame_time_target;

/* Prevent external frame limiters from
* pushing fast forward ratio down to 1x */
if (frame_time_accumulator + frame_time_accumulator_prev < video_st->core_frame_time)
if (frame_time_accumulator + frame_time_accumulator_prev < frame_time_target)
frame_time_accumulator -= frame_time_delta;

/* If fast forward is working correctly,
Expand All @@ -3332,7 +3373,7 @@ void video_driver_frame(const void *data, unsigned width,
* will never empty and may potentially
* overflow. If a 'runaway' accumulator
* is detected, we simply reset it */
if (frame_time_accumulator > video_st->core_frame_time)
if (frame_time_accumulator > frame_time_target)
frame_time_accumulator = 0;
}
}
Expand All @@ -3345,6 +3386,9 @@ void video_driver_frame(const void *data, unsigned width,
last_time = new_time;
last_frame_duped = !data;

if (video_st->frame_discard)
return;

/* Get the amount of frames per seconds. */
if (video_st->frame_count)
{
Expand Down Expand Up @@ -3648,6 +3692,7 @@ void video_driver_frame(const void *data, unsigned width,
audio_stats.close_to_underrun = 0.0f;
audio_stats.close_to_blocking = 0.0f;

audio_compute_buffer_statistics(&audio_stats);
video_monitor_fps_statistics(NULL, &stddev, NULL);

video_info.osd_stat_params.x = 0.008f;
Expand All @@ -3659,10 +3704,7 @@ void video_driver_frame(const void *data, unsigned width,
video_info.osd_stat_params.drop_y = (video_info.font_size / DEFAULT_FONT_SIZE) * -3;
video_info.osd_stat_params.drop_mod = 0.1f;
video_info.osd_stat_params.drop_alpha = 0.9f;
video_info.osd_stat_params.color = COLOR_ABGR(
alpha, blue, green, red);

audio_compute_buffer_statistics(&audio_stats);
video_info.osd_stat_params.color = COLOR_ABGR(alpha, blue, green, red);

latency_stats[0] = '\0';
tmp[0] = '\0';
Expand Down
2 changes: 1 addition & 1 deletion gfx/video_driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -776,7 +776,6 @@ typedef struct
#endif
struct retro_system_av_info av_info; /* double alignment */
retro_time_t frame_time_samples[MEASURE_FRAME_TIME_SAMPLES_COUNT];
retro_time_t core_frame_time;
uint64_t frame_time_count;
uint64_t frame_count;
uint8_t *record_gpu_buffer;
Expand Down Expand Up @@ -868,6 +867,7 @@ typedef struct
uint8_t frame_delay_effective;
bool frame_delay_pause;

bool frame_discard;
bool threaded;
} video_driver_state_t;

Expand Down
Loading
Loading