The revolution is upon us all! The future is multi-core/CPU systems and that future is now, as such we should prepare to shed our single CPU bodies and prepare to ascend to the kingdom of the Thread!
OK, enuff of the sillyness I think, heh
On sunday I finaly got around to doing something I'd been meaning todo for a while now. Reminded by Superpig's journal entry and initally inspired by his post in the thread on console multi-processor programming, I set about creating my own system where the updates where separate from the rendering in their own thread.
I picked boost::thread for the threading as I quite like it and I've got a fair amount of experience with it and ofcourse I picked my own windowing framework as part of its design is to allow you to handle messages in one thread and initalise a context in another thread to render from.
The inital code was an adaption of my test programs, just 8 spinning cubes with the scene code adapted so that one thread pumped the update and the 2nd rendered it. I based the basic loop on the canonical game loop with some minor adjustments.
The inital test was a success, the update thread ran every 10ms (100hz) and the rendering thread rendered stuff, I was a happy phantom :)
Next step, converting it so that the renderer interpolated between two frames (named 'old' and 'current') and that it switched between frames at the right point.
The update data was a simple structure with the new x and y rotations and the time stamp for when the update was generated. The scene holds 3 of these structures and at the correct time moves everyone down the line (current becomes old, new becomes current).
My intial method was setup so the renderer locked the resources while it was working and the update thread was free to update the new frame data and then when the mutex was released it could swap the data over and the mutex would stop the data getting swapped out while a frame was being rendered.
While this seemed like a good idea at this point my scene stopped working for some crazy reason, at which point it was the early hours of monday morning and I'd had enuff [grin] so I PM'd Superpig and asked for some guideance.
I woke up later that day to a message from him pointing out that the mutex was going to hurt me (figeratively I assumed) and was convinced to change to a different lockless method.
This involved moving responciblity for changing the frame from the update thread to the scene its self (and, in a final game the game objects). This was just a simple matter of checking the current time and if it was great or equal to the time stamp on the current frame swapping the data over.
It was at this point I started to suspect my timings were wonky (the update thread was using the real 'current time' for its updating where as the rendering threads time was a whole time step behind) and spent far too long trying to debug the timing errors to fix the rendering bug.
At 7:30pm that night I went out and as I was walking to my destination I was going over the problem in my head. About 8pm I realised my linear intergration was totally wrong and treated the world to a vast amount of explitives. I realised I wasnt adding the interpolated value to my 'old' frame position, totally throwing things out of wack. I made a note of this on my phone and when I returned home that night I fixed the code and it worked just as I had expected it to, yay! [grin]
I've since added an fps counter (I plan on adding a world update counter, just to make sure its ticking as often as I think it is and maybe a 'frame time' output as well as with high fps a frame time would be a better guide), which led to an hour and a half of fun debugging due to me forgetting to zero a structure before useage (it was a problem in my Freetype based renderer but as I only tested in debug I didnt notice the problem).
The current version can be found here, its statically linked so should run anywhere and with any reasonable hardwar (Win32 only atm)
If people do run it I'd be intrested in the inital FPS results on your hardware and an idea of how smooth it runs.
Its not completely finished, Superpig gave me some good ideas for correcting the data updating incase the rendering thread gets behind, I also wanted to see about going from a constant loop/yeild system for the update to a sleep() base one, as I'm using a 1ms resolution timer sleeping for 10ms (or maybe 5ms) might be worth a try, with the self correction stuff mentioned by Superpig it might work out better.