Is it maybe because of VSync and particles ? Probably not.
Anyway a while ago I moved simulation to 2nd thread (but in Stunt Rally).
And I did it even so that both threads aren't even synchronized (no mutex lock). We used boost but I'm sure the SDL threads are ok too.
My main reason was to have more cpu time for graphics (draw calls are on cpu) and have graphics independent of simulation time (we have 160Hz on game thread, doesn't slow down because the game is gpu bound on drawing). We did get few fps more on graphics. I also had to separate the camera code.
Here is what I did.
I made a structure for car position data (can be just position and rotation for start).
Then a simple array of eg. 8 of those structs (can't use std::queue since its not thread safe)
also an int for current index (so graphics thread knows which data from array is last valid and meant for render).
In sim thread when new data is computed it is filled in next position in this array,
and then the index is increased. This operation is atomic, can be done from both threads without sync.
So just for reference, from OgreGame.h:
Code:
const int CarPosCnt = 8; // size of poses queue
// This list holds new positions info for every CarModel
PosInfo carPoses[CarPosCnt][8]; // max 8 cars
int iCurPoses[8]; // current index for carPoses queue
and in UpdatePoses.cpp, sim thread after tick, when new poses are available
Code:
/// store new pos info in queue _________
PosInfo pi;
pi.bNew = true; // new data
// .... fill pos, rot, etc.
int qn = (iCurPoses[c] + 1) % CarPosCnt; // next index in queue
carPoses[qn][c] = pi;
// update camera
if (carM->fCam)
carM->fCam->update(time, pi, &carPoses[qn][c], &pGame->collision);
iCurPoses[c] = qn; // atomic, set new index in queue
}
and in graphics update just read the current index
Code:
int q = iCurPoses[c]; // c is car index
carM->Update(carPoses[q][c], time);
// and inside it just check if there are new positions available
if (!posInfo.bNew) return; // new only
posInfo.bNew = false;
Hope it helps anyhow.