Fix frame rate (again) (#537)

This commit is contained in:
PeachyPeach 2024-11-28 23:14:50 +01:00 committed by GitHub
parent fa2ec0957b
commit 7c2f055a86
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -89,9 +89,9 @@ f32 gRenderingDelta = 0;
#define FRAMERATE 30 #define FRAMERATE 30
static const f64 sFrameTime = (1.0 / ((double)FRAMERATE)); static const f64 sFrameTime = (1.0 / ((double)FRAMERATE));
static f64 sFrameTargetTime = 0; static f64 sPeriodTimeStart = 0;
static f64 sFrameTimeStart = 0; static f64 sFrameTimeStart = 0;
static f64 sFrameLastClock = 0; static u32 sDrawnFrames = 0;
bool gGameInited = false; bool gGameInited = false;
bool gGfxInited = false; bool gGfxInited = false;
@ -177,24 +177,41 @@ static inline void patch_interpolations(f32 delta) {
patch_scroll_targets_interpolated(delta); patch_scroll_targets_interpolated(delta);
} }
static void compute_fps(f64 start, f64 end) {
u32 fps = round((f64) sDrawnFrames / MAX(0.001, end - start));
djui_fps_display_update(fps);
sDrawnFrames = 0;
}
void produce_interpolation_frames_and_delay(void) { void produce_interpolation_frames_and_delay(void) {
u64 frames = 0; bool is30Fps = (!configUncappedFramerate && configFrameLimit == FRAMERATE);
f64 curTime = clock_elapsed_f64();
f64 timeStart = curTime;
gRenderingInterpolated = true; gRenderingInterpolated = true;
// sanity check target time to deal with hangs and such // Delta time is based on the remaining number of frames we need to draw during the current second
if (curTime >= sFrameTargetTime) { sFrameTargetTime = curTime - 0.01; } f64 curTime = clock_elapsed_f64();
f64 remainingTime = sPeriodTimeStart + 1.0 - curTime;
f64 targetTime = sFrameTimeStart + sFrameTime;
f64 targetDelta = (
is30Fps ?
targetTime - curTime :
remainingTime / (f64) MAX(1, configFrameLimit - sDrawnFrames)
);
// Account for the actual start of the frame and the time elapsed during the game logic if (!configUncappedFramerate && (remainingTime < 0.0 || sDrawnFrames >= configFrameLimit)) {
f64 targetDelta = ((sFrameTargetTime - curTime + (sFrameLastClock - sFrameTimeStart)) * FRAMERATE) / (f64) configFrameLimit; compute_fps(sPeriodTimeStart, curTime);
sPeriodTimeStart = curTime;
sFrameTimeStart = curTime;
targetTime = curTime + sFrameTime;
targetDelta = 1.0 / (f64) configFrameLimit;
}
// interpolate and render // interpolate and render
while ((curTime = clock_elapsed_f64()) < sFrameTargetTime) { while ((curTime = clock_elapsed_f64()) < targetTime) {
f32 delta = ((!configUncappedFramerate && configFrameLimit == FRAMERATE) f32 delta = (
? 1.0f is30Fps ?
: MAX(MIN((curTime - timeStart) / (sFrameTargetTime - timeStart), 1.0f), 0.0f) 1.0f :
MAX(MIN((curTime - sFrameTimeStart) / (targetTime - sFrameTimeStart), 1.0f), 0.0f)
); );
gRenderingDelta = delta; gRenderingDelta = delta;
@ -203,7 +220,7 @@ void produce_interpolation_frames_and_delay(void) {
send_display_list(gGfxSPTask); send_display_list(gGfxSPTask);
gfx_end_frame(); gfx_end_frame();
frames++; sDrawnFrames++;
if (configUncappedFramerate) { continue; } if (configUncappedFramerate) { continue; }
@ -215,25 +232,18 @@ void produce_interpolation_frames_and_delay(void) {
if (delay > 0.0f) { if (delay > 0.0f) {
WAPI.delay((u32)delay); WAPI.delay((u32)delay);
} }
if (is30Fps) { break; }
} }
static u64 sFramesSinceFpsUpdate = 0; if ((curTime = clock_elapsed_f64()) >= sPeriodTimeStart + 1.0) {
static u64 sLastFpsUpdateTime = 0; compute_fps(sPeriodTimeStart, curTime);
sPeriodTimeStart += 1.0;
sFramesSinceFpsUpdate += frames; sFrameTimeStart = sPeriodTimeStart;
} else {
u64 sCurrentFpsUpdateTime = (u64)clock_elapsed_f64(); sFrameTimeStart += sFrameTime;
if (sLastFpsUpdateTime != sCurrentFpsUpdateTime) {
u32 fps = sFramesSinceFpsUpdate / (sCurrentFpsUpdateTime - sLastFpsUpdateTime);
sLastFpsUpdateTime = sCurrentFpsUpdateTime;
sFramesSinceFpsUpdate = 0;
djui_fps_display_update(fps);
} }
sFrameTimeStart = sFrameTargetTime;
sFrameLastClock = clock_elapsed_f64();
sFrameTargetTime += sFrameTime;
gRenderingInterpolated = false; gRenderingInterpolated = false;
} }