I'm working on a very simple game, and one of the project goals is to minimise the use of libraries.
I'm drawing every frame into a buffer, which is then displayed using XPutImage
(see the code of the main loop). This simple code is used to limit FPS:
// Limit FPS
{
u64 current_timestamp = LinuxGetWallClock();
u64 ns_elapsed = LinuxGetWallClock() - last_timestamp;
if (ns_elapsed < target_nspf) {
struct timespec ts;
ts.tv_sec = 0;
ts.tv_nsec = target_nspf - ns_elapsed; // time to sleep
clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);
while (ns_elapsed < target_nspf) {
ns_elapsed = LinuxGetWallClock() - last_timestamp;
}
} else {
// printf("Frame missed\n");
}
last_timestamp = LinuxGetWallClock();
}
Everything works fine and as expected, but every now and then the image stutters, as if the X server has buffered up a few frames' worth of images and then flushed them all in a single go. This happens irrespective of frame misses.
Note: I'm not talking about image tearing here.
I realise that the code above is not supposed to provide a stable frame rate, and occasionally one frame might be displayed for too long, and another frame might get lost and never displayed, but I don't see how that thing alone can cause the terrible occasional stuttering.
My only guess would be that clock_nanosleep
may sleep for longer than I asked for.
Questions:
- Is my guess above correct?
- If not, what might be the reason?
- Are there any ways to address this problem without having to use OpenGL to wait on vblank?
Thanks.
CLOCK_MONOTONIC_RAW
in yourclock_gettime()
call? If you look at the manpage forclock_gettime()
, it states the following forCLOCK_MONOTONIC_RAW
:Similar to CLOCK_MONOTONIC, but provides access to a raw hardware-based time that is not subject to NTP adjustments or the incremental adjustments performed by adjtime(3).
So it could cause slight issues with your times, but it's probably very unlikely. But it would be nice to try in order to rule that out. \$\endgroup\$