Updating and Drawing at Different Framerates (CPU Issues)

Started by
11 comments, last by nife87 12 years, 10 months ago

Hi,
I think that the discussion here got a bit side tracked.

I haven't seen in this thread any actual referenced how frame rate capping can be done accurately in the case where vertical sync isn't enabled.

Actually one could argue that if "wait vertical refresh" is enabled, you shouldn't try to cap your frame rate. Consider case where your monitor frequency is 60hz and you try to cap to 45fps. Every 4th frame on screen would be the same as the frame before which in my opinion could look like stuttering. Or your cap is at 30fps and your monitor works at 75hz.

However, for the original question:

[color="#1C2837"][color="#000000"]mUpdateTimer[color="#666600"].[color="#660066"]TimeElapsed[color="#666600"]()

Does the above function return floats or integer numbers. In case of integers, the integer rounding will make your program run slightly faster than you think. It may or may not be a problem. However, if vertical sync is enabled, your calculations may interfere and possibly cause stuttering.

Usually the update frequency is less than the drawing frequency (ie. drawing at 60fps and updating at 30fps).
In this case, for the frames between updates you'll need to interpolate positions and rotations etc.


In my current project I haven't implemented explicit frame rate capping, but logic updates are running at 30fps, which saves a huge deal of calculations and actually increases the drawn frames. Even if I don't cap anything, my processor is running at ~10% load (4 cores with HT) since my GPU is the bottleneck.

Cheers!


Thank you. It actually does return integers, but it wouldn't be a problem to make it return floats. The reason I was minimizing the rendering is because I've read that rendering takes much more time and processing power than updating does. I'm just trying to get on the right track to making a game that runs equally well on all pc's so that I can stop worrying about the boring engine stuff and start doing the fun logic stuff.

P.S. can you post an article link on interpolation or a tutorial or something to help me with it?
Advertisement
On windows? use MsgWaitForMultipleObjects with a timeout, when enough time has elapsed run whichever of two major update functions you need to process.

If you get a timeout, do your update or render.
If you got a message, process the message, then re-run MsgWaitForMultipleObjects with an updated timeout (based on how much time has elapsed).

This has a bonus of not using 100% cpu unless its falling behind (at which point you need probably need to run some ratio of updates vs rendering (2:1 3:2 etc).

The only real trick is to also track how much time was spent in the update or rendering phase, and reduce the timeout for the next iteration by that amount.


stay away from timeGetTime as the granularity will not be good enough for this (and calling timeBeginPeriod(1) at startup is pretty much essential for a game)


Bonus: if you thread the renderer, then you can still use MsgWaitForMultipleObjects, and have it process 'rendering completed' events from the rendering thread, so you can figure out when the next time a good time to wake up the rendering thread will be.
http://www.gearboxsoftware.com/
Is it just me, or does a certain cvar named fps_max come to mind? fps_max is often limited to range from like 10 to 1000 fps.


while (!TimeForShutdown())
{
Input(); // Process input (however you choose do it)

while (NeedsUpdate())
Update(); // As many times as needed for the sim. to be in sync.

if (!AltTabActive() && !NeedsUpdate() && frames_this_second < fps_max)
Render(); // As many times per second as fps_max allows, whilst not exceeding the next update time.

if (!NeedsUpdate())
Sleep(0); // If sim. is still in sync. and rendering is complete.
}


Perhaps, you could measure the use of Sleep(0) the first couple of seconds, and if it continuously slows down the message loop (you have to run Update() multiple times each iteration), just abandon it entirely for that run/match.

This topic is closed to new replies.

Advertisement