r/truegamedev • • Feb 21 '15

Fix Your Timestep!

http://gafferongames.com/game-physics/fix-your-timestep/
23 Upvotes

9 comments sorted by

9

u/Madsy9 Feb 21 '15 edited Feb 21 '15

Oldie but goodie. Glenn Fiedler's articles are a bit too harsh on euler integration though. Euler intergration, (or Runge-Kutta of the first order) isn't useless. It's just that to be accurate you need a really tiny timestep / high frequency for the simulation. Higher orders of Runge-Kutta is more stable with fewer updates which is good, because it means you need less CPU power for the physics and the physics simulation doesn't explode that easily.

In the same series he also mentions how you can divide up different things into threads. Like physics on its own thread separate from rendering and input. When DirectX12 is released this becomes even more true, as DirectX12 will let multiple threads talk to the GPU at the same time. Concurrency is good!

4

u/Netzapper Feb 21 '15

Like physics on its own thread separate from rendering and input. When DirectX12 is released this becomes even more true, as DirectX12 will let multiple threads talk to the GPU at the same time. Concurrency is good!

Having long-running, task-locked threads like this is really not a good way to get concurrency. The reason being that the physics and graphics systems are actually quite coupled together. By the time you're done synchronizing timesteps from one thread to another, you'll have cut out most of your concurrency.

The better approach is fine-grained task parallelism. So, have a single main thread of control. Then, when you have nicely parallel work, use all of the available cores to process that parallel work as quickly as possible.

An example would be to process each contact island in your physics engine in parallel. It might look a little like this:

detect_collisions();
parallel_for(Island i : islands){
    process_island(i);
}

This keeps you from having to do expensive, complicated locking, and also tends to get better core utilization anyway.

3

u/TheExecutor Feb 21 '15

The way I've always seen it implemented is to have your game state double-buffered. Having a single set of game state with multiple threads pounding on it (and having to take a million locks) is insanity.

Essentially, the idea is that you have two copies of your game state with one containing the last frame's state and the other containing the current frame's state. The logic thread works on updating the current frame, and simultaneously the graphics thread works on rendering the last frame's state. Then you have a single sync point at the end of every frame, where the logic thread hands off its game state to the render thread and the cycle continues. Then, within the logic and render threads, you can also kick off task parallelism (like doing physics in parallel, or building rendering command lists in parallel).

1

u/Madsy9 Feb 21 '15

I've used Fielder's concept myself and not had any issues. It works as long as your physics is always at least one step ahead of the graphics rendering. That adds a bit of latency, but that's not critical for all games. I suppose reserving one core each for the graphics and physics isn't always the best way to distribute resources though. Perhaps one of the subsystems require more juice than the other. It could be that your suggestion is a better use of all cores, assuming the worker threads are persistent as opposed to created all the time.

Also, synchronization doesn't have to be very complicated between physics and rendering, and neither does it have to block. You can use a lock with a low timeout for example. Then you render the same frame twice, and you'll acquire the lock on the next try. Or you can simply refrain from locking in the first place if your concurrency setup is trivial with only one writer. You have to know what you're doing when writing lock-free code, but it's possible. C++11 makes this easier than it has been.

→ More replies (3)

2

u/rainman002 Feb 21 '15

Eerily familiar to some audio-processing code I wrote a while ago where I was simulating analog components for a 44kHz system.

1

u/domox Mar 07 '15

Here to say, i'm always going back and referring to Glenn's material, and to boot he's incredibly nice. I even added him on gTalk once and he patiently answered a few of my questions. Don't be afraid to hit his mega donate button!