Revert "much better frame pacing"

- No one complained about framerate since several updates now; don't fix what isn't broken
- Too much frames are drawn at low framerates when Vsync is enabled
- FPS and delay calculation are wrong with Vsync: 60 FPS looks like 30 with a 120+Hz monitor
- Fixed Auto mode that was broken
- Kept precise_delay_f64 as I have observed no noticeable impact on CPU
This commit is contained in:
PeachyPeachSM64 2025-07-28 22:31:40 +02:00
parent 593eb9aafc
commit afec9d35b9
3 changed files with 23 additions and 40 deletions

View file

@ -1970,26 +1970,18 @@ void gfx_run(Gfx *commands) {
//double t0 = gfx_wapi->get_time(); //double t0 = gfx_wapi->get_time();
gfx_rapi->start_frame(); gfx_rapi->start_frame();
gfx_run_dl(commands); gfx_run_dl(commands);
}
void gfx_end_frame_render(void) {
gfx_flush(); gfx_flush();
gfx_rapi->end_frame(); gfx_rapi->end_frame();
gfx_wapi->swap_buffers_begin();
} }
void gfx_display_frame(void) { void gfx_end_frame(void) {
gfx_wapi->swap_buffers_begin();
if (!dropped_frame) { if (!dropped_frame) {
gfx_rapi->finish_render(); gfx_rapi->finish_render();
gfx_wapi->swap_buffers_end(); gfx_wapi->swap_buffers_end();
} }
} }
void gfx_end_frame(void) {
gfx_end_frame_render();
gfx_display_frame();
}
void gfx_shutdown(void) { void gfx_shutdown(void) {
if (gfx_rapi) { if (gfx_rapi) {
if (gfx_rapi->shutdown) gfx_rapi->shutdown(); if (gfx_rapi->shutdown) gfx_rapi->shutdown();

View file

@ -21,8 +21,6 @@ void gfx_init(struct GfxWindowManagerAPI *wapi, struct GfxRenderingAPI *rapi, co
struct GfxRenderingAPI *gfx_get_current_rendering_api(void); struct GfxRenderingAPI *gfx_get_current_rendering_api(void);
void gfx_start_frame(void); void gfx_start_frame(void);
void gfx_run(Gfx *commands); void gfx_run(Gfx *commands);
void gfx_end_frame_render(void);
void gfx_display_frame(void);
void gfx_end_frame(void); void gfx_end_frame(void);
void gfx_shutdown(void); void gfx_shutdown(void);
void gfx_pc_precomp_shader(uint32_t rgb1, uint32_t alpha1, uint32_t rgb2, uint32_t alpha2, uint32_t flags); void gfx_pc_precomp_shader(uint32_t rgb1, uint32_t alpha1, uint32_t rgb2, uint32_t alpha2, uint32_t flags);

View file

@ -205,16 +205,20 @@ static s32 get_num_frames_to_draw(f64 t, u32 frameLimit) {
static u32 get_refresh_rate() { static u32 get_refresh_rate() {
if (configFramerateMode == RRM_MANUAL) { return configFrameLimit; } if (configFramerateMode == RRM_MANUAL) { return configFrameLimit; }
if (configFramerateMode == RRM_UNLIMITED) { return 3000; } // Has no effect if (configFramerateMode == RRM_UNLIMITED) { return 3000; } // Has no effect
static u32 refreshRate = 60; static u32 refreshRate = 0;
#ifdef HAVE_SDL2 #ifdef HAVE_SDL2
if (!refreshRate) { if (!refreshRate) {
SDL_DisplayMode mode; SDL_DisplayMode mode;
if (SDL_GetCurrentDisplayMode(0, &mode) == 0) { if (SDL_GetCurrentDisplayMode(0, &mode) == 0) {
refreshRate = (u32) mode.refresh_rate; refreshRate = (u32) mode.refresh_rate;
} else {
refreshRate = 60;
} }
} }
#endif
return refreshRate; return refreshRate;
#else
return 60;
#endif
} }
void produce_interpolation_frames_and_delay(void) { void produce_interpolation_frames_and_delay(void) {
@ -223,53 +227,42 @@ void produce_interpolation_frames_and_delay(void) {
gRenderingInterpolated = true; gRenderingInterpolated = true;
f64 curTime = clock_elapsed_f64();
f64 targetTime = sFrameTimeStart + sFrameTime; f64 targetTime = sFrameTimeStart + sFrameTime;
s32 numFramesToDraw = get_num_frames_to_draw(sFrameTimeStart, refreshRate); s32 numFramesToDraw = get_num_frames_to_draw(sFrameTimeStart, refreshRate);
f64 curTime = clock_elapsed_f64();
f64 loopStartTime = curTime; f64 loopStartTime = curTime;
f64 expectedTime = 0; f64 expectedTime = 0;
u16 frames = 0;
const f64 interpFrameTime = sFrameTime / (f64) numFramesToDraw;
// interpolate and render // interpolate and render
// make sure to draw at least one frame to prevent the game from freezing completely // make sure to draw at least one frame to prevent the game from freezing completely
// (including inputs and window events) if the game update duration is greater than 33ms // (including inputs and window events) if the game update duration is greater than 33ms
do { do {
++frames;
// when we know how many frames to draw, use a precise delta
f64 idealTime = configFramerateMode != RRM_UNLIMITED ? (sFrameTimeStart + interpFrameTime * frames) : curTime;
f32 delta = ( f32 delta = (
is30Fps ? is30Fps ?
1.0f : 1.0f :
clamp((idealTime - sFrameTimeStart) / sFrameTime, 0.f, 1.f) clamp((curTime - sFrameTimeStart) / sFrameTime, 0.f, 1.f)
); );
gRenderingDelta = delta; gRenderingDelta = delta;
// prepare interpolated frame
gfx_start_frame(); gfx_start_frame();
if (!gSkipInterpolationTitleScreen) { patch_interpolations(delta); } if (!gSkipInterpolationTitleScreen) { patch_interpolations(delta); }
send_display_list(gGfxSPTask); send_display_list(gGfxSPTask);
gfx_end_frame_render(); gfx_end_frame();
// delay if our framerate is capped
if (configFramerateMode != RRM_UNLIMITED && !configWindow.vsync) {
f64 now = clock_elapsed_f64();
f64 elapsedTime = now - loopStartTime;
expectedTime += (targetTime - curTime) / (f64) numFramesToDraw;
f64 delay = (expectedTime - elapsedTime);
numFramesToDraw--;
if (delay > 0.0) {
precise_delay_f64(delay);
}
}
// send the frame to the screen (should be directly after the delay for good frame pacing)
gfx_display_frame();
sDrawnFrames++; sDrawnFrames++;
if (!is30Fps && configFramerateMode == RRM_UNLIMITED) { continue; }
// delay if our framerate is capped
f64 now = clock_elapsed_f64();
f64 elapsedTime = now - loopStartTime;
expectedTime += (targetTime - curTime) / (f64) numFramesToDraw;
f64 delay = (expectedTime - elapsedTime);
if (delay > 0.0) {
precise_delay_f64(delay);
}
numFramesToDraw--;
} while ((curTime = clock_elapsed_f64()) < targetTime && numFramesToDraw > 0); } while ((curTime = clock_elapsed_f64()) < targetTime && numFramesToDraw > 0);
// compute and update the frame rate every second // compute and update the frame rate every second