It seems that you're using an outdated browser. Some things may not work as they should (or don't work at all).
We suggest you upgrade newer and better browser like: Chrome, Firefox, Internet Explorer or Opera

×
Important stuff in bold.

avatar
clarry: I don't know if you read the wikipedia article you linked, but what it describes is not a way to stabilize the framerate but to make things move around at a (relatively) constant rate in the face of unstable framerate.

And this mechanism is precisely what leads to rounding errors when framerate is too high (i.e. delta becomes very small and significant digits vanish from the calculations).
Ahhh gotcha, I thought the thread was about that but I took it the wrong way. Thanks for telling me :)!

Perhaps its because I'm not from a english speaking country, but doesn't "but to make things move around at a (relatively) constant rate..." and the term "stabilize" imply a similar thing? never mind I took it the wrong way.

And while delta-timing did fix my issue with "things moving too fast at high FPS" though back when I made a tiny game as a hobbyist project (written in python, perhaps thats important), the issue could be because of something else so it was maybe a placebo effect?

At any case, I won't edit the comment to remove the link since it might still be interesting to some but thanks for telling me.

EDIT: I remember it now, I indeed used something like delta-time to normalize the speed of an entity in accordance to the framerate and not to "keep the framerate under a certain threshhold" so to speak. But beside that, I've played quite many older games that had a way to keep their framerate below a certain threshold so even if there wasn't anything on screen the game didn't run faster compared to stuff happening.

In fact, the only game that I remember that didn't do that is Magic Carpet, which ran way too fast if you looked up in the sky. Does that issue have something to do with "delta-timing" (as you said, this delta mechanism is what causes the issue), so to speak?
Post edited September 16, 2019 by Dray2k
avatar
Dray2k: Important stuff in bold.

avatar
clarry: I don't know if you read the wikipedia article you linked, but what it describes is not a way to stabilize the framerate but to make things move around at a (relatively) constant rate in the face of unstable framerate.

And this mechanism is precisely what leads to rounding errors when framerate is too high (i.e. delta becomes very small and significant digits vanish from the calculations).
avatar
Dray2k: Ahhh gotcha, I thought the thread was about that but I took it the wrong way. Thanks for telling me :)!

Perhaps its because I'm not from a english speaking country, but doesn't "but to make things move around at a (relatively) constant rate..." and the term "stabilize" imply a similar thing?
By things I mean objects in the game world. Their behavior is what delta timing tries to stabilize. However, it does nothing to framerate, which regardless of delta timing is free to fluctuate according to PC specs and scene complexity. If framerate were stable, then there would be no need for delta timing at all. And if delta timing didn't eventually lead to issues with the limits of numerical precision, there would be no pressing need for any mechanism to limit fraterate (except to save power and avoid doing unnecessary work).

And while delta-timing did fix my issue with "things moving too fast at high FPS" though back when I made a tiny game as a hobbyist project (written in python, perhaps thats important), the issue could be because of something else so it was maybe a placebo effect?
It probably worked just fine for you, and it wasn't placebo.

However, when you employ delta timing on a game that (at the time of writing) runs from 30 to 150 FPS, it might be just fine, but 20 years later someone plays it at 5000+ FPS and they may start running into real rounding errors. At the other end of the spectrum, someone suffering lags and very low framerate can also run into big issues with deltas that are suddenly very large. Of course it all depends on the numerical stability of your code and the precision & range of the data types you chose to use. What works for a simple game with small levels and mostly linear motion can break horribly in a game with huge scenes and a complex physics engine.
Post edited September 16, 2019 by clarry
avatar
clarry: *snip*
I've read your comment and just wanted to chime in to say that I've edited my previous comment because I remembered something else that I felt was important. That was like half a minute before you've posted this comment before I published the edited comment.

At any case, thanks for your insight to the matter and your time.
Post edited September 16, 2019 by Dray2k
avatar
dtgreene: How does v-sync work from the game programmer's perspective, anyway?
avatar
clarry: The call that presents the framebuffer on the screen blocks until the GPU has passed it on.
I'm wondering: How accurate is the timing of the v-sync?
For example, if I have a program that enables v-sync and then just keeps making that call as a timing method:
* Is it good enough for music? (Precise timing is necessary here.)
* If I were making something like TASBot (which plays back a TAS on real hardware by sending to the console a bunch of precisely timed inputs), would v-sync's timing be accurate enough for that?
* Would the timing be good enough to perform time-related exploits like Spectre and Meltdown? (My understanding is that both exploits are performed by measuring how long certain instructions take.)

avatar
clarry: However, when you employ delta timing on a game that (at the time of writing) runs from 30 to 150 FPS, it might be just fine, but 20 years later someone plays it at 5000+ FPS and they may start running into real rounding errors. At the other end of the spectrum, someone suffering lags and very low framerate can also run into big issues with deltas that are suddenly very large. Of course it all depends on the numerical stability of your code and the precision & range of the data types you chose to use. What works for a simple game with small levels and mostly linear motion can break horribly in a game with huge scenes and a complex physics engine.
Or the deltas might become so small that dividing by them yields a huge number, or the delta could end up rounding to zero, causing infinities and NaNs where the game isn't expecting them, or even causing a floating point exception. (If you have Ultima 2, try running it a high number of cycles; there is a good chance that the game will fail to boot with a division by zero error.)

By the way, speaking of numerical (in)stability, one virtual console release of Super Mario 64 had a bug in the floating point emulation which caused certain platforms to slowly move; this allows for beating the second Bowser stage without pressing A, provided you are willing to wait about 72 hours.
https://www.youtube.com/watch?v=Aa_CciaM4aM
Post edited September 17, 2019 by dtgreene
avatar
clarry: The call that presents the framebuffer on the screen blocks until the GPU has passed it on.
avatar
dtgreene: I'm wondering: How accurate is the timing of the v-sync?
It's difficult to find any numbers but if one could assume that it is somehow tied to the pixel clock, then it is very precise. I don't know if that's a good assumption though, the pixel clock could run at more than a hundred MHz (generated by PLL from something like 20-25 MHz) and I'm not sure that'd make a good source for something as low frequency as a a 60Hz interrupt. I don't actually know what mechanism would be used to generate a low frequency clock from a source that is many orders of magnitude larger. A cascade of dividers?!

For example, if I have a program that enables v-sync and then just keeps making that call as a timing method:
* Is it good enough for music? (Precise timing is necessary here.)
I don't understand the requirement here. In music applications, shouldn't the timing be driven by the audio card which eats a block of audio samples at a fixed rate? If that rate is slightly off, it generally doesn't hurt. And if you're talking about a live application, well, that simply requires low latency (from inputs to application as well as application to DAC output, i.e. short buffers and good scheduler), not timing as such.

* If I were making something like TASBot (which plays back a TAS on real hardware by sending to the console a bunch of precisely timed inputs), would v-sync's timing be accurate enough for that?
You probably don't want a low frequency timer like 60Hz for that.

Would the timing be good enough to perform time-related exploits like Spectre and Meltdown? (My understanding is that both exploits are performed by measuring how long certain instructions take.)
You can't use it to measure intervals other than the fixed interval it syncs frames at. I think you should know that interval in advance, and it's not useful for side channel exploits.
Post edited September 17, 2019 by clarry
Because modern developers (and past developers that put thought into this sort of thing like, for example, Doom which was set to 35fps) sync the framerate with code that restricts it. Some past developers (and Bullfrog on Magic Carpet which runs WAY too fast on anything more than a P3 600) didn't put any forward thought into their games being played beyond that point in time or didn't know how to limit the framerate to keep the game from running too fast on computers that came later, or possibly just didn't care.

Here's the code that I use in my C and C++ game engines to limit framerate to whatever I want (usually 60 out of practicality, but there's no reason I couldn't set it to whatever I want) :

// First, get the current clock ticks for delaying until we've hit the target framerate
Last_Frame = clock ();

// Game logic per frame

// Optional timing code to make the program run at a given FPS
while ( (clock () - Last_Frame) < Ticks_Per_Frame);

Earlier in the initialization code, I have the following statement :
Ticks_Per_Frame = CLK_TCK / Target_Framerate;

Where Target_Framerate is typically set to 60. But, the way I have this set up, I can alter it dynamically, but that's beyond the point of your question. What IS important is that this will indeed lock the framerate to whatever is chosen for Target_Framerate and effectively future-proof the game and make it run a consistent speed across computers of varying speed. (Note that this code isn't the best and there's much more accurate ways to get timing that yield MUCH more precise measurements, but it's serviceable for basic use and I haven't needed to change it yet.)

Now, modern games take this MUCH further, doing things like having the physics and movement tied to the actual framerate such that multiplayer games the various players stay in sync (this is just one benefit. If you've ever played a multiplayer game like any of the Quake series and have seen a character that seems to "ice skate" around in rapid jumps, this is partly why (the other part is network speed and latency and also animation speed)).

Modern games also take into account if a frame takes LONGER than a typical frametime. My code above does NOT do this (but I really should add it. It just makes all the movement in the game complicated as I can't just move by a variable and must multiply movement by time). For example, if the Target_Framerate is 60, you have ~16.6 ms per frame. So, what happens if a frame is complicated, has a lot going on, and takes longer than that to render?

In my code, it'd basically just skip a frame. But modern game engines factor this possibility in and have the physics (EG - Player and enemy movement) tied to this framerate such that the game doesn't jump around if frames get dropped so the game speed stays consistent and predictable.

TL;DR : Because modern game developers have trivialities like framerate so figured out that this is just part of their normal development whereas some past developers didn't consider this component and thus the game runs too fast when faced with a computer with a higher clock speed.
Post edited September 18, 2019 by ColJohnMatrix
avatar
ColJohnMatrix: Here's the code that I use in my C and C++ game engines to limit framerate to whatever I want
Does that apply just to your game logic or do you tie the rendering rate to game logic rate?
avatar
dtgreene: I'm wondering: How accurate is the timing of the v-sync?
For example, if I have a program that enables v-sync and then just keeps making that call as a timing method:
* Is it good enough for music? (Precise timing is necessary here.)
* If I were making something like TASBot (which plays back a TAS on real hardware by sending to the console a bunch of precisely timed inputs), would v-sync's timing be accurate enough for that?
* Would the timing be good enough to perform time-related exploits like Spectre and Meltdown? (My understanding is that both exploits are performed by measuring how long certain instructions take.)
As clarry said, the vblank is VERY accurate BUT isn't a good choice for something like audio work. You can only do so much within the Vblank period and trying to do more than copy the offscreen buffer to the video buffer is asking to introduce timing problems with other portions of the game, which would ruin the entire point of it. The Vblank standard practice is to reduce tearing on the screen, not be a timer for the game.

Audio has its own timers and timing which are better to use for that purpose. In general, the Vblank period is VERY short and you really don't want to make it do heavy lifting like being the timekeeper for the entire program.
avatar
ColJohnMatrix: Here's the code that I use in my C and C++ game engines to limit framerate to whatever I want
avatar
clarry: Does that apply just to your game logic or do you tie the rendering rate to game logic rate?
I use it mainly for rendering, though the game logic is technically bound by it; IE - They're tied together as per your latter question. A more advanced design (which I have yet to incorporate) would add deltas for movement of everything (IE - a proper physics model which I do NOT have) to ensure that game logic doesn't impact framerate. That said, if game logic started holding up framerate, I'd obviously have to do some profiling and optimization to assist the framerate being consistent. This just hasn't happened yet. But it could!

This call is made during the game logic which does the rendering :
// Draw the frame
Game_Draw ();
Post edited September 18, 2019 by ColJohnMatrix
avatar
ColJohnMatrix: Here's the code that I use in my C and C++ game engines to limit framerate to whatever I want (usually 60 out of practicality, but there's no reason I couldn't set it to whatever I want) :

// First, get the current clock ticks for delaying until we've hit the target framerate
Last_Frame = clock ();

// Game logic per frame

// Optional timing code to make the program run at a given FPS
while ( (clock () - Last_Frame) < Ticks_Per_Frame);

Earlier in the initialization code, I have the following statement :
Ticks_Per_Frame = CLK_TCK / Target_Framerate;

Where Target_Framerate is typically set to 60. But, the way I have this set up, I can alter it dynamically, but that's beyond the point of your question. What IS important is that this will indeed lock the framerate to whatever is chosen for Target_Framerate and effectively future-proof the game and make it run a consistent speed across computers of varying speed. (Note that this code isn't the best and there's much more accurate ways to get timing that yield MUCH more precise measurements, but it's serviceable for basic use and I haven't needed to change it yet.)
How is CLK_TCK calculated? What if the CPU is so fast that there are more ticks per frame than will fit inside the integer type used?

(I suspect that Ultima 2 malfunctions on fast computers because of this sort of issue; there's a timing look on boot, that at some point divides by the amount of time it takes to loop a certain number of times, and that amount ends up being zero if the computer is too fast.)

There's also another thing: If your program doesn't actually need to be running the CPU and GPU at full blast all the time, it really should yield the CPU time to allow other processes to do work, or to allow the computer to go into a lower power state; this becomes especially apparent if running on battery power or on a machine with thermal issues. (I remember having the La Mulana remake hard lock the computer because of this sort of issue.)

avatar
ColJohnMatrix: As clarry said, the vblank is VERY accurate BUT isn't a good choice for something like audio work. You can only do so much within the Vblank period and trying to do more than copy the offscreen buffer to the video buffer is asking to introduce timing problems with other portions of the game, which would ruin the entire point of it. The Vblank standard practice is to reduce tearing on the screen, not be a timer for the game.
Looking up information on NES development, the standard practice is to do the graphics stuff first, then do everything else so that the graphics gets done during vblank; you then have enough time to do other things before the next vblank interrupt comes in.

One thing that's interesting, however, is that there are games out there, including Super Mario Bros., that actually do everything during the interrupt; the main program just does some initialization, sets up the ISR, and then just spins forever.

Also, it seems that Linux has lots of ways to do timing, perhaps too many (cruft accumulated over the years), including:
* sleep(), usleep(), nanosleep(), clock_nanosleep()
* alarm(), setitimer() with a suitable SIGALRM signal handler
* timer_create() with a suitable signal handler for one of the real time signals
* timerfd_create()
(In other words, there are a lot of options, and the issue is sorting out which one makes the most sense in any given situation.)

(One observation: Some of these are interrupt driven (even in userspace), while others involve a system call that will block until time runs out. There's also the question of thread-safety of some of the methods, particularly how threads and signals interact.)
Post edited September 18, 2019 by dtgreene
Here is a list of games that are sensitive to CPU speeds, the symptoms that occur with from using a faster CPU than recommended, maximum suitable CPU, and potential fixes/patches.

https://www.vogonswiki.com/index.php/List_of_CPU_speed_sensitive_games
avatar
dtgreene: How is CLK_TCK calculated?
CLK_TCK is provided by the compiler and is #defined as 1000 in time.h :
#define CLK_TCK CLOCKS_PER_SEC

which is elsewhere in the file defined as such :
/* Clock ticks macro - ANSI version */

#define CLOCKS_PER_SEC 1000

avatar
dtgreene: What if the CPU is so fast that there are more ticks per frame than will fit inside the integer type used?
The way it's set up doesn't allow for the sort of scenario you're asking about.

long Ticks_Per_Frame = 0; // 1000 / Target_Framerate

That should be more than enough for any scenario, especially since it's just divided by 1000 effectively. Even if you set that to 120 fps (and we're getting crazy now), you'd still have Ticks_Per_Frame set to 8.

Like I said, there's more precise ways to do all this that (as clarry mentioned) use Microsecond timers (Mike Abrash's Graphics Programming Black Book (Alternate) goes into some, but those are surely outdated by now) but they add complication to the engine and I haven't needed to go the extra mile on that sort of thing as of yet.

avatar
dtgreene: (I suspect that Ultima 2 malfunctions on fast computers because of this sort of issue; there's a timing look on boot, that at some point divides by the amount of time it takes to loop a certain number of times, and that amount ends up being zero if the computer is too fast.)

There's also another thing: If your program doesn't actually need to be running the CPU and GPU at full blast all the time, it really should yield the CPU time to allow other processes to do work, or to allow the computer to go into a lower power state; this becomes especially apparent if running on battery power or on a machine with thermal issues. (I remember having the La Mulana remake hard lock the computer because of this sort of issue.)
The latter paragraph IS done, but that's handled by the OS in the energy profiles. The CPU isn't just going to run to the moon by a game engine UNLESS the framerate is uncapped, which would allow it to render the frame as fast as it could and, without delay, do it again and again.

My code above, if you study it, basically renders the frame and THEN waits until the timing/framerate threshold has been reached before it allows the program to continue. It just spins idly in that while loop until it hits that, and only then does the next frame get allowed to progress.
avatar
dtgreene: Looking up information on NES development, the standard practice is to do the graphics stuff first, then do everything else so that the graphics gets done during vblank; you then have enough time to do other things before the next vblank interrupt comes in.
Ok, but that's only proving my point. The Vblank is limited in its application and is best used, especially where there's limited resources and capability as in the NES, strictly for the screen to ensure no graphical tearing.

You're right though on the rest of your comment that there are multiple ways to handle timing. More complex and capable engines surely use the low-level timers on the chip. Mike Abrash talks about these in the book I linked above, but IIRC Intel also does in their optimization manuals :

https://software.intel.com/en-us/articles/intel-sdm

What I use is a good workhorse general case and serves me for the moment (until it doesn't, and then no-retreat-no-surrender sort of optimization and profiling need to be embarked upon). It's obviously serviceable for any realtime loop until more advanced techniques are called for and is really meant to be illustrative of your initial question in how this sort of thing can be employed/solved in practice.
Post edited September 18, 2019 by ColJohnMatrix
avatar
dtgreene: There's also another thing: If your program doesn't actually need to be running the CPU and GPU at full blast all the time, it really should yield the CPU time to allow other processes to do work, or to allow the computer to go into a lower power state; this becomes especially apparent if running on battery power or on a machine with thermal issues. (I remember having the La Mulana remake hard lock the computer because of this sort of issue.)
avatar
ColJohnMatrix: The latter paragraph IS done, but that's handled by the OS in the energy profiles. The CPU isn't just going to run to the moon by a game engine UNLESS the framerate is uncapped, which would allow it to render the frame as fast as it could and, without delay, do it again and again.

My code above, if you study it, basically renders the frame and THEN waits until the timing/framerate threshold has been reached before it allows the program to continue. It just spins idly in that while loop until it hits that, and only then does the next frame get allowed to progress.
It spins, consuming 100% CPU (or as much as the OS lets you consume) to do effectively nothing. That is, unless your clock() call does more than just fetch the current time. Your OS probably doesn't know that it's not performing any useful work, and indeed the CPU could boost its frequency in order to spin faster...

That's not very energy efficient, but sometimes that's the only way to do precise timing.

The other problem here is than since the OS doesn't know the process is doing no useful work, it has no choice but to force it to stop at some point in order to schedule another task on that CPU. This can cause stuttering with a game that by no means is too demanding to be run smoothly for the hardware. That's why you should yield. It matters less on modern multi-core CPUs though.
Post edited September 18, 2019 by clarry
avatar
clarry: It spins, consuming 100% CPU (or as much as the OS lets you consume) to do effectively nothing. That is, unless your clock() call does more than just fetch the current time. Your OS probably doesn't know that it's not performing any useful work, and indeed the CPU could boost its frequency in order to spin faster...

That's not very energy efficient, but sometimes that's the only way to do precise timing.
In theory, yes. In practice, the OS limits it. I've also written a CPU graph for Litestep that displays the current core loads in realtime (which, in itself uses some of the CPU, but it's minor) using the PDH library and the game doesn't spike the CPU too badly.

It's not nothing though, even though that's what it is technically doing as far as productive work at that point. It's waiting to proceed. It serves the purpose of keeping the framerate. But we're getting into semantics at this point. I think we both agree.

Though, if you do want to hear something funny, I just altered the system clock while the game was running and the game had the software equivalent of a mid-life crisis, completely freezing!

With games, you need to address both functionality AND performance, so I don't really think energy efficiency is a concern.

avatar
clarry: The other problem here is than since the OS doesn't know the process is doing no useful work, it has no choice but to force it to stop at some point in order to schedule another task on that CPU. This can cause stuttering with a game that by no means is too demanding to be run smoothly for the hardware. That's why you should yield. It matters less on modern multi-core CPUs though.
Yes. But the OS does manage the CPU priority for a given task.

I think we're getting beyond the point though here. The CPU is meant to serve a purpose in running the software that the user wants. If a game is running in fullscreen, the resources going to the active task the user is using is exactly what it's designed to do. Games tend to be resource intensive (don't get me started though on inefficiencies of engines like Unity, much less web browsers like Chrome). A game waiting in a loop to keep a framerate which serves the user is its best use at that point. So, I don't think there's anything to debate about on this point. We're off in the weeds of the point of this topic.
Post edited September 18, 2019 by ColJohnMatrix
avatar
ColJohnMatrix: In theory, yes. In practice, the OS limits it. I've also written a CPU graph for Litestep that displays the current core loads in realtime (which, in itself uses some of the CPU, but it's minor) using the PDH library and the game doesn't spike the CPU too badly.
What OS? How does it limit it?

I'm not familiar with any OS that peeks into the instruction stream of a running program in order to make scheduling decisions (or measure CPU usage, for that matter). Program is either running, or it's not. If it never yields and isn't forced to stop, it'll use up 100% of the CPU.

If your loop doesn't max out CPU usage, then I suspect you're running into another bottleneck. Or something's wrong with that measurement.

It's not nothing though, even though that's what it is doing at that point. It's waiting to proceed. The code is, but the program isn't/ So, yes and no.
Yielding when you are waiting is how interactive multitasking became practical.

Though, if you do want to hear something funny, I just altered the system clock while the game was running and the game had the software equivalent of a mid-life crisis, completely freezing!
Does your system offer a monotonic clock? That would help...

With games, you need to address both functionality AND performance, so I don't really think energy efficiency is a concern.
Depends on the platform, and depends on what the user wants. Depends on how nice you want to be. I mean my browser could also hog the CPU when it's waiting for me to type letters into this text box but I'm so glad it doesn't :P

And people who play on battery powered devices are surely happy if a game doesn't blast the CPU at full steam just waiting.

I'm happier if I don't need to hear the CPU fan ramp up to cool a game that just spins.

Anyway, yielding is more than just about energy efficiency. On a multitasking OS where CPU time is inherently shared, it's important for performance.
Post edited September 18, 2019 by clarry
avatar
clarry: What OS? How does it limit it?

I'm not familiar with any OS that peeks into the instruction stream of a running program in order to make scheduling decisions (or measure CPU usage, for that matter). Program is either running, or it's not. If it never yields and isn't forced to stop, it'll use up 100% of the CPU.
Oh boy... <facepalm>

There's CPU priority as per the multi-tasking portion of the OS in Windows (I assume, but have less knowledge of, this component exists on other OSes). It doesn't need to "peak into the instruction stream". The rest you're right and I wasn't arguing against any of that. The OS can control (to a point) how much resources go to a task. It can also control it's energy usage (Windows has profiles for this). This is pointless hair-splitting side-aspect of this topic. I'm not sure what you're trying to prove.
Post edited September 18, 2019 by ColJohnMatrix