   engine architecture
  hiI'm trying to figure out the basic architecture for my game engine.I will start using open source components like ogre3d and bullet.My question here is how to organize the engine.The first option is to have just one thread running the big game loop doing the rendering, the physic and the game logic all in one. This seems to not to be the best choice.Actually, I'm thinking into have at least three main threads, one for the rendering, one for the physics and one for the game's background process.I just want to get some comments about this, just to check if I am in the right way.One question is, if the physic thread is able to modify the status on the rendering thread, for example changing the transformation of an object, can this cause a real problem on the render engine? I think probably yes, then, I should start using locks and mutex. So, here is another question, will these mutex kill the performance? Then, would it be better to have the same thread for physic and rendering, to be executed in sequence and not in parallel?Well, I think I will start with some tests, but, if you have any comment I will thank you so much.Thanks,nh   
Quote:Original post by naherThe first option is to have just one thread running the big game loop doing the rendering, the physic and the game logic all in one. This seems to not to be the best choice.This is the classic single-threaded game loop. Modern PCs and game consoles aren't designed for this any more though - threading is required ;)Quote:Actually, I'm thinking into have at least three main threads, one for the rendering, one for the physics and one for the game's background process.I just want to get some comments about this, just to check if I am in the right way.This is the next step from a single-threaded game loop.This is called "coarse-grained" parallelism, because you're defining the parallel sections of code as very large chunks.This is a common approach, but it's not future proof. You're targeting a fixed number of CPU cores with this approach (e.g. 3 threads). If your users upgrade to an 8-core CPU, they aren't going to get any performance boosts.The alternative method is called "fine-grained" parallelism, where you break up the code into much smaller parallel tasks (e.g. 1000 different tasks per frame).On a 4-core CPU, each core might run 250 tasks. On an 8-core each core only runs 125 tasks, giving the user better performance.You can see "fine grained" methods are more scalable, but they are also much harder to write! For example, if you're using a very slow mutex object for every tasks, then 1000 tasks might be a lot slower (1000 lock+unlock operations) than only running 3 large tasks (3 lock+unlock operations)...Quote:One question is, if the physic thread is able to modify the status on the rendering thread, for example changing the transformation of an object, can this cause a real problem on the render engine?Yes!Quote:then, I should start using locks and mutex. So, here is another question, will these mutex kill the performance?Yes, mutexes are generally quite slow, so you need to be careful how you use them.One way to solve this "Data sharing" problem is to implement "double buffering", where you keep two copies of the data.The 'producer' thread can be writing to one buffer, while the 'consumer' thread can be reading from the other buffer. When the 'consumer' is idle, the 'producer' can copy over it's version of the data to 'consumer' thread.In this example, I'm using an atomic variable instead of a mutex for performance reasons. An atomic variable is basically just an integer that inserts memory fence instructions when read or written to. This implements the idea of "Do Work, Then Publish"struct Data{ ...};Data m_ActualData;Data m_ReadOnlyData;Atomic<int> m_CanReadData = 0;void UpdateLoop(){  while( true )  {    m_ActualData = DoWork(); //Check if the render thread is working or idle    if( m_CanReadData == 0 )    { //renderer is idle, safe to copy over new data: m_ReadOnlyData = m_ActualData; //Signal that this data is safe to read now: m_CanReadData = 1;    }    Sleep(0);  }}void RenderLoop(){  while( true )  {    //wait for update thread to signal that the data is ready    while( m_CanReadData != 1 )    { Sleep(0);    }    //Use the shared data    DoRender( m_ReadOnlyData );    //Signal that we're done with the data    m_CanReadData = 0;  }}More info on thread-communication techniques:http://download.microsoft.com/download/c/f/8/cf8d0552-5e8c-4501-a52e-0986a9295821/Multicore%20Programming%20Two%20Years%20Later.zipGeneral concurrency advice and theory:http://herbsutter.wordpress.com/   ;  Good question, and I like Hodgman's answer.I usually ask myself these questions: - what processing is going to consume a lot of CPU? - what is likely to block on hardware? - what is likely to block on disk or network i/o?And then thread appropriately.  For instance, putting graphics rendering on its own thread is probably a good idea, since it'll (usually) block on the vertical retrace, and you'd rather not just lose those cycles.Likewise, you don't want to put any disk access on the main thread, because it is dog slow.  Any loading should happen on background threads.The physics engine likely won't block or wait.  It will just churn through CPU!  So in my eyes it is a good candidate for the main thread.You may want to keep just one or two long-lived threads (the main execution thread and maybe a rendering thread), and then spin off threads as needed from a pool for any background loading etc.;  Thanks guys,I will start with multiple threads then, I will spend some time to have a good thinking and understanding about the way these threads will communicate.I had the idea about double buffering, at the beginning I was afraid about the memory consumption, but, I think I will use it since it will help the performance. And maybe I will use double buffering for highly shared memory structures and mutex for less shared structures. But, anyway, I will start doing some tests and the I will decide.Thanks Hodgman, thanks tomva,Hernan;  I'd advice against separating physics/simulation and graphics in separate threads. It may seem like a good idea at first, but you'll run into all sorts of not-so-fun problems. For example, the GUI. When a user clicks a button, you may want to do an action in the simulation thread and display the button being pushed down in the graphics thread. That means you have to duplicate everything and using a GUI library that does both at the same time will fail. Also, duplicated memory could also mean more cache misses, which will hurt your performance and negate the benefits of threading.And then, when 8-core CPUs become mainstream, you are left with a number of unused cores. You can have your threads spawn a number of threads to occupy the cores, but that will introduce the complexity of a task based system to an already complex system that allows simulation and rendering to work in separate threads. Might as well go with the task based system from the start.   