how to coordinate physics part with rendering part with multithreading ?

Started by
2 comments, last by scratt 15 years, 2 months ago
Hi ! I have a little engine with rendering and physics parts (monothreaded) and i try to make threads : one for rendering, one for physics. But as we don't know when one thread would finidh relative to the other, i wondered how to do to coordinate them ? Can you explain me ? And do you know a good article about this problem ? Thanks !
Advertisement
here is a good article, not on threading, but how to sync rendering and physics.

As you can see, they store physics into a 'state' object, transition from state to state, and the rendering uses an interpolation of those states.

    float t = 0.0f;    const float dt = 0.01f;    float currentTime = time();    float accumulator = 0.0f;    State previous;    State current;    while (!quit)    {         float newTime = time();         float deltaTime = newTime - currentTime;         currentTime = newTime;         accumulator += deltaTime;         while (accumulator>=dt)         {              previousState = currentState;              integrate(currentState, t, dt);              t += dt;              accumulator -= dt;         }         const float alpha = accumulator / dt;         State state = currentState*alpha + previousState*(1.0f-alpha);         render(state);    }


The discussion goes on a bit further.


Everything is better with Metal.

it's not about timestep that i wonder how to do, though it will come later (so thanks for it), but more about how to manage this both threads in the infinite main loop.
Quote:Original post by blueShadow
it's not about timestep that i wonder how to do, though it will come later (so thanks for it), but more about how to manage this both threads in the infinite main loop.


I just finished implementing this for ordinance and AI in my engine.

My threading is using p_threads. There is a very good web page showing how to implement them:
http://www.llnl.gov/computing/tutorials/pthreads/

My method at the moment is to have a thread which updates the base class of any active object in the sim.
That thread keeps track of those objects with a std::map.
The base class is simply for 3D physics, and is always the same type of object.
The derived class implements drawing and specific logic for that type of object.
The derived class is the actual descriptor for the object, and is referenced via the base class from the processing thread: I use void* for functions to enable any compliant derived class function to be called from the processing thread, via it's base class, and virtual destructors to make sure when the base class is killed off, it's parent dies also.

I use a condition mutex in each object which lets the main thread know it's being updated.
The main thread simply does drawing, and usual housekeeping. If it hits an object that is being updated it has only 'try-ed' the mutex so does not stall, and just defers that object. Conversely my processing thread will block when it hits an object which is being read by the main thread. That's not such a problem because the processing thread is not time critical like the main thread, and typically the main thread is simply retrieving some data very quickly.

There is also a small interface which allows the main thread to add or delete objects from the processing thread. Objects being added or deleted get pushed onto a std::list which is processed and integrated into the main std::map periodically. There is some handshaking to keep that tidy with mutexes again. So for example, if the processing thread is integrating from the std::list the main thread defers and tries again later. If the main thread is pumping the std::list the processing thread just defers for one loop and then tries again to grab things.

You can go further and have sync mutexes to make sure that your proceesing thred runs once per frame, and only when it's not likely to be touched by the main thread.

Another approach is to not bother with syncing but have two work places for the logic, which you handshake and double buffer. But I prefer the first approach.

mutexs, and conditional mutexes are explained very well in the link above.

Hope that helps.
Feel free to 'rate me down', especially when I prove you wrong, because it will make you feel better for a second....

This topic is closed to new replies.

Advertisement