I'm not sure whether loop is correct […]
What I just mentioned
is not a game loop, but a test program to illustrate the problem with time-consuming SDL event processing caused by using
SDL_Delay, which we should focus on.
My engine has a much more complicated main loop structure which provides a constant number of updates per second (using a constant time delta), allows it to render any number of frames, independent and different from the number of updates, and the rest of the time is given back to the system, ensuring minimal CPU power consumption. In addition, it provides precise measurements of averaged logic update time and renders, performed any number of times per second, expressed with 100-nanosecond precision (measurement results are converted to milliseconds in the form of a floating point number). There are more features — lag prevention, reading events in portions according to the current delta time, ”spiral of death” prevention and more.
Thus, the main game loop ensures that the three mechanisms (logic update, frame rendering and counters refreshing) work independently, at different frequencies, still sequentially (single-threaded), and gives the rest of the free time to the system. For example, it can update logic 60 times per second, render 50 frames per second, and refresh meters with various averaged measurements 7 times per second — each mechanism at equal intervals according to the given settings, which can be freely changed in the runtime. It's just for the record.
[…] but you can try https://wiki.freepascal.org/EpikTimer if there will be difference.
I will not try it, because firstly the results will be the same, and secondly, I will not add more dependencies just to replace simple arithmetic. Using EpikTimer won't do any good for me, because both it and SDL use
QueryPerformanceFrequency and
QueryPerformanceCounter internally (under Windows).
SDL2 timing functions are not reliable for benchmarking or for other purposes that require precision like manual framerate limit via SDL_Delay().
You're wrong. SDL2 functions like
SDL_GetPerformanceFrequency and
SDL_GetPerformanceCounter allow for very precise timing (and these are the ones I use in my engine and in the tester from this thread), because they use platform mechanisms with the highest resolution. On Windows it is
QPF and
QPC, which is a counter that performs millions of ticks per second (on my laptop it is 10 million ticks per second, or 10MHz). On other platforms, SDL2 uses different mechanisms, but also those with the highest resolution.
Secondly, the use of
SDL_Delay (internally:
Sleep on Windows) is the only available solution that allows you to create gaps between frames without using spinlocks (busy waiting), i.e. without using the CPU power to wait a given amount of time. Any serious game engine provides the ability to limit the framerate and thus save energy, so each engine necessarily uses the system's
Sleep function directly or indirectly. For example, see the engine used by the
S.T.A.L.K.E.R. game, whose
sources are on GitHub and which is also based on SDL2.
It is not entirely clear which system clock is being used. Especially on different operating systems.
That is clear, just read the documentation or check the SDL2 sources.
I suggest focusing on the essence of the problem that the thread I set up concerns, i.e. the long processing of SDL events and the times that increase with the increase of the intervals between measurements, and not on the implementation of the main game loop, which I have not shown here at all.