I am working on a simple game in OpenGL, using SDL for display initialization and input, and it appears in terms of timing I have two options available to me. Number one being just sleeping for the optimalTimePerFrame - theTimeTakenToRender, when the optimalTimePerFrame in seconds = 1/theFramerateCap. (I'm not entirely sure if this is necessary, as it is equivalent to using vsync, which may be more accurate. If my assumption is correct then please tell me wheter or not SDL + OpenGL has vsync by default, and if not how to enable it.) The other is to measure the time since the last frame was rendered, and merely adjust movement accordingly. (The shorter time taken to render a frame, the less far entities move in that frame). In terms of performance, and decreasing flicker etc, what are the advantages and disadvantages of these two methods?
5 Answers
If your frame time is unpredictable (whether or not this is your fault; the OS may be using resources occasionally, etc), capping to a predictable frame rate that is somewhat lower than your achievable framerate will do a lot for predictable latency, which can make the game feel a lot better.
Changing how long between when you process input and render changes related to that input can feel bad -- even if on average you're achieving less latency between the two, the "jitter" can be noticeable to humans (consciously or unconsciously).
See the Microsoft GameFest presentation What's In a Frame: Tearing, Latency, and Frame Rate for some insight here. Carmack also has a series of blog posts that are useful in this.
Also be aware that some math can break down when you run frames using low deltaT
values -- or even when you use variable deltaT
at all (things can become harder or even intractable to do in a "stable" and predictable manner, which is important for things like replays and some forms of network synchronization). See Fix Your Timestep for some insight here.
-
1\$\begingroup\$ (By the way, I'd highly recommend not capping by way of "sleep"; figure out what your vsync situation is on your platform and use vsync to drive you. It's much more predictable and usually uses less resources.) \$\endgroup\$– leanderSep 16, 2013 at 17:58
-
\$\begingroup\$ Thanks, I will definitely try to cap the framerate. Do you know how to enable vsync using SDL? \$\endgroup\$ Sep 16, 2013 at 19:24
-
2\$\begingroup\$ In SDL 2.0, you can enable vsync by passing the flag SDL_RENDERER_PRESENTVSYNC to SDL_CreateRenderer call, e.g.
SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
\$\endgroup\$– TJSSep 17, 2013 at 15:59
You will end up using a lot less CPU (multi taskers will thank you) and people on mobile devices will appreciate this, too.
-
6\$\begingroup\$ Not to mention lower power usage (important for mobile devices/laptops), and less heat generation. \$\endgroup\$– zeelSep 16, 2013 at 18:12
-
\$\begingroup\$ It reminds me of some games issue, when FPS in menus was unlimited and insanely high, alike 900fps, and that really stressed the CPU/GPU -> higher temp -> more noise. \$\endgroup\$– KromsterSep 17, 2013 at 4:08
You should never, ever, ever, ever, ever use Sleep to control framerate.
This has been gone over before and I'll refer you to the other question for discussion of the reasons why. One thing not mentioned there is that at the typical modern refresh rate of 60Hz, and with the typical 1 millisecond granularity of Sleep calls, it's actually impossible to Sleep for the correct amount of time between frames.
I'm not saying that yielding CPU if you've nothing to do is a bad thing; far from it. But it's not the same thing as controlling framerate and Sleep is a solution that's appropriate for the former but not the latter.
Instead check for time elapsed, and if it's time to run a frame, then do so, otherwise - and if you want to yield some CPU - Sleep for the bare minimum of time - 1 millisecond. Also ensure that your sleep timer is set up appropriately for your platform so as to give you good resolution; i.e. that when you issue that "Sleep (1)" call you actually stand a chance of really Sleeping for 1 millisecond, rather than something like 15, 20 or 30 (which would be the case otherwise). I believe that SDL will do this automatically for you.
You can also build some slack into it, so that if it's getting near time to run a frame, you stop Sleeping and start running flat-out until the frame runs, which can help you hit your desired frame interval more accurately.
What this ends up looking like is a whole bunch of Sleep (1) calls interspersed with the occasional frame, and that's OK. You're still giving up CPU when you don't need it, but your frames will still be able to run on time.
Probably the most important benefit of capping frame rate is that it can help to prevent literal physical damage to the machine. They forgot to do this on Starcraft II, which turned out to be very problematic (and expensive) for some users until they patched it.
As was mentioned earlier, it lowers CPU usage. On the flipside, and increasingly important, that also drains battery life. As a good example, FTL runs at nearly 100% CPU on my MBA. As a result, it drains the battery in > 2 hours and runs very hot. ( As a more direct result, I uninstalled and no longer play it... ). A frame cap would have prevented this.
Another unmentioned advantage is, if its a multiplayer game, you also level the playing field by giving everyone the same experience.
-
\$\begingroup\$ Your framerate and game update loop don't have to be running at the same speed, so giving people the same experience doesn't rely on framerate alone. \$\endgroup\$– ThomasSep 17, 2013 at 17:22