Multithreading XNA + Farseer physics

Topics: Developer Forum, Project Management Forum, User Forum
May 14, 2008 at 7:19 PM
Hi, does anyone try to do multithreading on XNA? And integrate physics into the game?

An idea would be:
1. thread: rendering, UI Logic
2. thread: physics

David
May 15, 2008 at 3:10 PM
Edited May 15, 2008 at 3:20 PM
I'm not an expert and I haven't tried it before, and I'm not sure much benefit you would get out of it. There are probably a couple of ways you could do it. First of all, I think you'd need two copies of your physics simulator and every physics object in it, and some fast way to copy the state of everything from one to the other. Basically, your physics thread is going to work on one copy, and your rendering loop will copy over the state of the physics loop to its own local copy before rendering it. The copy process has to be fast or it won't be worth doing it with threads. Now here is where you can do things differently:

One way to handle it would be to synchronize the physics thread and the rendering thread. The rendering thread renders the current frame and then waits for the physics thread to finish calculating the next frame's state. The physics thread calculates the next frame's state while the rendering thread is rending the current frame's state. After it is done, it will wait for the rendering thread to finish rendering the current frame's state. In between, one of the threads copies over the state from the physics thread to the render thread.

The other way is to let the physics loop update at a higher rate than the render loop, which could increase your physics accuracy a little. Let's say you have a fixed frame rate of up to 60 frames a second. If your physics update step takes a lot less than 1/60th of a second, then it might be possible to run it more than once per frame. The physics thread's copy of the physics simulator is basically the shared resource between the two threads, and must be locked before using it (either by the physics loop to calculate the next step or the rendering loop to copy over the state from the physics thread to the rendering thread). So only one thread can access it at a time.


Here's a quick and dirty template implementation of threaded physics using multiple physics updates per frame, with a limit of 10 physics updates per frame:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FarseerGames.FarseerPhysics;
using FarseerGames.FarseerPhysics.Dynamics;

namespace ThreadTest
{
    public class ThreadTestMain
    {
        private PhysicsSimulator renderSim;
        private PhysicsSimulator physicsSim;
        private object physicsSimLock = new object();

        private bool stillRunning = true;
        private object stillRunningLock = new object();

        private int physicsUpdateCount = 1;
        private object physicsUpdateCountLock = new object();

        /// <summary>
        /// You are probably ok with not limiting the number of physics updates per frame if
        /// you have a dual core processor (if you have a single core processor you shouldn't
        /// be using threads at all). If you have other intense CPU work that you're doing, then
        /// you might consider limiting it as you get diminishing returns with more physics
        /// updates per frame.
        /// </summary>
        private static int PhysicsUpdatePerFrameLimit = 10;
        private static bool UsePhysicsUpdatePerFrameLimit = true;

        ///
        /// Simulate the XNA Update method of your game class or component
        ///
        public void Update()
        {
            // we only need to draw if the physics thread has completed at least one update
            // since the last time we rendered
            // I don't know if this will cause a noticeable pause in the frame rate, so
            // if necessary you can instead just redraw the last state without attempting to lock
            // the physics sim if the physicsUpdateCount < 1
            lock (physicsUpdateCountLock)
            {
                System.Console.WriteLine("Render thread got lock on physicsUpdateCount");
                while (physicsUpdateCount < 1)
                {
                    System.Console.WriteLine("Render thread is waiting for physics update thread to update at least once");
                    System.Threading.Monitor.Wait(physicsUpdateCountLock);
                }
            }

            // now we need to lock physicsSimLock to copy over the state of the last update to render
            // this should be as fast as possible so the physics thread can go on with the next
            // update while we are rendering the current one
            lock (physicsSimLock)
            {
                // copy over physicsSim to renderSim
                System.Console.WriteLine("Render thread is copying physicsSim to renderSim");

                // notify the physics thread that we will be done with the physicsSim momentarily
                System.Threading.Monitor.Pulse(physicsSimLock);
            }
        }

        ///
        /// The main application thread is the "Render Thread",
        /// so this is the Draw method you define for your Game object
        /// or a DrawableGameComponent
        ///
        public void Draw()
        {
            // render from renderSim state
            System.Console.WriteLine("Render thread is rendering renderSim");

            // we've rendered one update (possibly the initial state, before the first physics
            // update), so reset the render count
            lock (physicsUpdateCountLock)
            {
                physicsUpdateCount = 0;
                System.Console.WriteLine("Render thread is resetting physicsUpdateCount");

                // notify physics thread that physicsUpdateCount has changed, if it is in the waiting queue
                System.Threading.Monitor.Pulse(physicsUpdateCountLock);
            }
        }

        ///
        /// This is the physics thread.
        ///
        public void PhysicsThreadProc(object ThreadArgs)
        {
            // make a local copy of stillRunning, then update it each time through the loop
            bool localStillRunning;
            lock (stillRunningLock)
            {
                localStillRunning = stillRunning;
            }

            // run while we are still running
            while (localStillRunning)
            {
                // if we've updated too many times, wait for renderer to catch up
                if (UsePhysicsUpdatePerFrameLimit)
                {
                    lock (physicsUpdateCountLock)
                    {
                        while (physicsUpdateCount >= PhysicsUpdatePerFrameLimit)
                        {
                            System.Console.WriteLine("Physics thread is waiting for render thread to catch up");
                            System.Threading.Monitor.Wait(physicsUpdateCountLock);
                        }
                    }
                }

                // now we need to get a lock on physicsSimLock and do an update
                lock (physicsSimLock)
                {
                    System.Console.WriteLine("Physics thread locked physicsSim and is updating.");
                   
                    // update physicsSim

                    // notify the renderer that the physics thread will be releasing physicsSimLock momentarily
                    System.Threading.Monitor.Pulse(physicsSimLock);
                }

                // update the physicsUpdateCount since we have done an update
                lock (physicsUpdateCountLock)
                {
                    physicsUpdateCount++;
                    System.Console.WriteLine("Physics thread is incrementing physicsUpdateCount to {0}",
                        physicsUpdateCount);

                    // notify renderer thread that physics thread has completed an update
                    System.Threading.Monitor.Pulse(physicsUpdateCountLock);
                }

                // check if we are still running
                lock (stillRunningLock)
                {
                    localStillRunning = stillRunning;
                }
            } // end while
        } // end PhysicsThreadProc

        public void Start()
        {
            // simulate the XNA game loop
            for (int i = 0; i < 10; i++)
            {
                this.Update();
                this.Draw();
            }

            // indicate to the physics thread that we are no longer running
            lock (stillRunningLock)
            {
                stillRunning = false;
                System.Threading.Monitor.Pulse(stillRunningLock);
            }
        }

        public static void Main(string[] args)
        {
            ThreadTestMain mainThread = new ThreadTestMain();
            System.Threading.Thread physicsThread = new System.Threading.Thread(mainThread.PhysicsThreadProc);
            physicsThread.Start();
            mainThread.Start();
            physicsThread.Join();
        }
    } // end class ThreadTestMain class
} // end namespace ThreadTest

May 20, 2008 at 2:28 PM
I've run the physics on a separate core and it seemed to work well. It definitely requires a little care with synchronization, but I think its worth it.

 As a test, change the stacking demo gravity to be large and the frame rate will bottom out. When you run the same demo with the physics simulator in a different thread it stays reasonable.
May 20, 2008 at 11:35 PM
just thought of this: If you don't use any drawing methods that draw directly from the physics simulator (unfortunately, that means the debug view from the demos), then all you need to copy over is body position and rotation for everything you want to draw. Plus, if you have static objects you don't need to copy those over. That would greatly speed up the marshaling between threads.
May 21, 2008 at 3:09 AM
I agree with you - you can get away without having to sync the threads in certain cases. All I needed was information related to angular and linear velocity and position. I didn't experiment too much with trying to get synchronization issues to occur, but in most cases I think you can run the physics simulator on a separate core a simply read values from the main UI thread on a per-body basis. As long as your not looping over the physics simulator lists or depending on it for anything other than to update your target bodies the worse case scenario is a dirty read every so often. In your average game, those would likely be smoothed out and unnoticeable.

There may be more serious issues with event handling on bodies, but it would probably be worthwhile to synchronize these, as they should occur less frequently. Anyone else played with this at all?
Developer
May 27, 2008 at 12:54 PM
Edited May 27, 2008 at 12:56 PM
Hmm. Somehow I don't think that multi-threading is a good idea. I thought about it and ... it seems to make things complicated :P ... Not everyone has a multi-core CPU, so you'll have to optimize the game for both CPU types?

I think I'll spend that time on thinking about the game and neat details in it, or create graphics oO ... ? And when I'm done Í'll think about optimizing it.

I mean: I'm not going to waste time optimizing the game before I know that the game is worth it ;D ...

Edit: Oh, but maybe your games are already complete?
May 27, 2008 at 1:42 PM
I agree that you don't need to optimize until you need to, especially if it's going to add complexity without much gain.

However, I think your missing the point when it comes to threading. Creating a thread in XNA on an 360 is not a whole lot different than on Windows - no different code is required. The call to set core affinity will be ignored if you are running windows with 1 CPU, and you will still gain the benefits of having your game multi-threaded, albeit not as performant as a multi CPU machine (obviously) or on the xbox.

To clarify, you do not need to change your threading to support different CPUs. As always, its a cost-benefit balance and it really depends on what you're comfortable with and what works best. And no, my game is not complete - it may never be :)
Developer
May 28, 2008 at 8:43 AM
The call to set core affinity will be ignored if you are running windows with 1 CPU, and you will still gain the benefits of having your game multi-threaded,

I don't see a benefit on a single core CPU in multi-threading when it comes to split the physics from the rest. If you lock / unlock and copy states that's actually not so good. As far as I can imagine. (Didn't test it yet. I just played with two threads to see how it works and didn't apply it to my game.)

Also, I'm wondering why a second thread for physics? Why not for ... a particle engine or other effects that require CPU calculations. That would be a lot easier oO. Won't your game make any use of such effects? They can be pretty CPU consuming :). Especially if you are insane enough to let the particles move over bezier curves like I'm planning on to do xD.

OT: Well, I'm going to use threading for networking and I don't worry about running my game on a 360, because I don't care about the 360 ;). Coding a game for the 360 is a joke anyway. AFAIK you can't just burn that game and play it, you have to connect your 360 to a PC ... wow -.- ... ... what's the point of that? Just plug you controller into your PC and play it on your PC with better performance oO!? That's so ridiculous xD ... And people pay for that, roflmao.
May 28, 2008 at 12:55 PM
In the words of Ace Ventura,
allllrighty then ...
May 30, 2008 at 12:38 PM
OT: Sick Battery.... The new creators beta, means that soon people will be able to publish games that anyone with a 360 and an internet connection can play.
(as far as I understand anyway).

"Starting this holiday, all Xbox LIVE users in selected regions will be able to download and play community games. For now, playing community games on Xbox LIVE starts with a Premium membership in the XNA Creators Club."

J.
Developer
May 30, 2008 at 4:34 PM
Edited May 30, 2008 at 4:43 PM
OT: No, no, no ... I'm sure Microsoft sells Developer SDKs to companies that develop games for the 360. Do you really think they'll release XNA for free, for commercial use (atm you are allowed to sell your game, if it's for pc), for the 360? I don't think so. The whole thing about connecting the 360 to your pc is because of that. They want make sure that you won't sell your XNA game for the 360 and they want - of course they want, who wouldn't want - money.

Also, beeing able to download a game doesn't mean that you won't need VS2005 + XNA + 360 connected to PC.

I don't know how much the XBOX360 SDK costs but the PS3 SDK dropped six months ago from 20.000 to 10.000 USD.
http://www.neoseeker.com/news/7337-sony-woos-development-with-ps3-sdk-price-cut/

What ever.

May 30, 2008 at 7:12 PM
Nothing in this post is remotely related to threading.

sickbattery: you have contributed so much helpful and useful content to this discussion. Please continue to enlighten us with your thoughts.

I am fairly certain MS does intend to let people develop games for the price of the creator's club membership and have them available on Live. I am certain that most of these games will be free, i.e. the creator will not make any money.  Here's why: the biggest issue with the current game market is that the only content guaranteed to draw people to a platform are the giant Halo 3s and GTA 4s - commercial projects that cost millions of dollars and take years to develop. And while those are great, they are few and far between, relatively speaking. If MS gets a thousand game submissions from people in their basements via creator's club, 9000 of those will be crap, some will be OK, and a few will be great. My guess is that the few that have potential will get a commercial development offer, and the rest that are OK will be free. Why? User generated content driving people to the 360 - MS spent nothing to push out a game that is providing income and drawing an audience. If MS finds 10 games like that in the entire year it will be worth it.

MS is not doing this out of the goodness of their heart - they see a potential market, and are testing the waters. If it fails, oh well, at least we had a chance to develop a game that can reach a significant market. Spending $100 on creator's club beats the hell out of spending 10k.

Also, physics is a fine candidate for threading, whereas the special effects you speak of should be off-loaded to the GPU as much as possible (had to get something on topic in here).
Jun 1, 2008 at 5:20 AM
Edited Jun 1, 2008 at 5:21 AM
Theoretical comparison: threaded vs unthreaded:
Let's say, one physics update takes 10 units of time.
One render takes 15 units of time.
One data marshalling takes 2 units of time (copy over positions/rotations for rendering).
There are 30 units of time between frames (aprox. constant framerate)


Threaded:
time -->
frame start: [x                              x
                              x                              x              ]
Physics:     [---------|---------|  ---------|---------|---------|  ---------|---------|---------|  ----------            ]
Marshalling: [                    --                              --                              --                      ]
Rendering:   [---------------                ---------------                ---------------                ---------------]


Totals:
four frames
three marshalling steps
9 physics updates

Unthreaded (no marshalling required, but can't do physics update and render at the same time):

time-->
frame start: [x                              x                              x                              x              ]
Physics:     [               ----------                     ----------                     ----------                     ]
Rendering:   [---------------                ---------------                ---------------                ---------------
]

Totals:
four frames
no marshalling steps
3 physics updates

Other comparisons:
We know that physics updates and renders can be variable. If you have a complex scene or a lot of collisions in the same frame, even with threading you may only have time to do one physics update per frame, just like with unthreaded. The difference in our situation is, that with threading you have much more time to complete your physics update before the rendering thread needs to marshall and render.

Threading: Physics thread has to complete with time left to marshall the data. In our example, the marshalling takes 2 units, so the physics thread has 28 units of time that it can use for a single update, if it needs to. Or, you can also use that time for AI, animation, etc... Without threading, the physics update and the rendering share the time between frames. So in our example, even though the unthreaded version doesn't require marshalling, the physics update gets a maximum of 15 units of time to complete, which only leaves 5 left over for AI and other CPU tasks.

Now, if you only have one CPU core, even if you use threads, they only run one at a time, so the time you spend marshalling and context switching is wasted. My recomendation is to have your physics thread setup as a simple loop that calls an update method. When you run on a single core machine, just call the update method in the main thread, and render from the physics sim directly rather than copy the positions/rotations.
Aug 18, 2008 at 8:57 PM

I'm just close to finish my game for the DBP competition using the Farseer for physics. For the competition it is running on Xbox as well on PC. I'm running the physics on a separate thread as the Xbox has 4 of them to use (so you can run your particle simulation on the third one) and I've got a speed increase of 100-150% by doing so. I have a similar rendering thread as JeroMiya with a few differences. I'm only syncing the dynamic objects position and rotation before drawing. There is really no need to synchronize anything else (except for example some speed dependant effects for an object if you have something like this).

I've been playing with how many physics update should I allow and now I've been end up with one. There is no need to advance the simulator two times between two frames as you will only going to see the results of the last one. Farseer is quite good in advancing the simulator at variable time steps (grat for that) as long as they are under ms which is 10fps. When a lag occurs and I am limiting the simulator advance to ms, so as a lagy frame comes, the scene time slows down for a while. This works really well because at first nobody is playing at constant 10fps, and when a lag comes (my game runs at 50-60fps now), the player is getting frustrated because of the lag and now the slowdown. I myself prefer some scene slowdown instead of dying between two frames.

So this is how it works for me.

Some thoughts for the meaning of developing for the Xbox. That gives you some serious background when for example you try to get a game programmer job at a game developer company (this applies for designing, testing, drawing, whatever in an XNA project for a similar job).For a programmer it is really doesn't matter if your game is written in C#, Java or any language (as long as you can reproduce the same functionality in C++ or any language that company prefers) as the language itself really doesn't matter. What matters is that you can write working and quite optimal code (if you have a working .NET game for Xbox, then I'm sure you can), you know what makes a complete game (not just tech demos), and most importantly you have console programming experience (programming the Xbox developer kits in C++ is really not different from programming a retail kit in XNA, trust me) what is getting more and more important for the developer companies (you wouldn't believe how much).

I'm sure that now the community can make games to the LIVE and earn money by that, there will be smaller causal game creating companies making games for LIVE. Even you can make such a company. You don't have to buy Xbox developer kits for 10k dollars per kit (and just money doesn't enough, you have to have some serious background to become an Xbox developer and be able to buy those kits), you only have to buy some retail kits. You don't have to buy Visual Studios for another big amount of money (yes, it isn't free), you only have to download the Express version, and with a great idea you can still make excellent games.

You can try and get your game to internet sites, but on the LIVE, there is more than 15 million people for one reason: to play games. On a PC, the people has to download and install the XNA runtime, DirectX runtime, your game... This is too much trouble for most people and they will end up playing quick flash games. And even if one bother, he isn't going to pay for it.

After some successful XNA LIVE games you can start thinking about stepping forward to be a registered Xbox developer (being able to buy those devkits and develop retail games), but you need that background the XNA development gave you. Or you can just take a job at a bigger company. With a few working game behind you, there will be no problem getting a job in the industry.

Ugh. I'm talking too much... :) These are just my thoughts (and what I'm seeing around me) but it is worth thinking about it before saying the Xbox XNA development is meaningless.