Multithreading, swapchains and Present()

Started by
-1 comments, last by Koen 12 years ago
In my (windows) application I want to render in a thread that is not the main gui thread. What would be the best way to 'share pictures' between two threads? My initial plan was to let the renderthread draw to d3d textures, and let the main thread blit the textures using a fullscreen quad. That would mean the renderthread has to wait while the main thread is drawing the fullscreen quad (as in: both threads should not be using the same direct3d device, even when it was created using the multithreading flag).

More context:
I'm writing rendercode for a cad-like application. It will be used to process lots of unstructured triangles. Rendering those takes some time (vertex data might not fit into video ram, multipass techniques are really slow on some hardware,...), but it should not 'block' the application. That's why all 'real' rendering is done on a second thread, and the main thread should only 'blit' (Present, fullscreen quad,...) the results to a window.
So whenever an application generates an event that should trigger a redraw, the renderthread will first draw a 'quick' approximation (using LOD, simpler techniques, or maybe even drawing bounding boxes or nothing at all...) for the application to show. Afterwards it will start rendering a slow high-quality image. To avoid flickering (because of always showing the 'quick' image) the main application thread will always wait some time (eg. 30Hz) before presenting the 'quick' image. If within that time the high-quality image is ready, the 'quick' image will be discarded.
The renderthread on the other hand should have the possibility to interrupt rendering the high-quality image. So that when lots of render requests arrive (eg. the user is interactively rotating the view) it can continuously generate the 'quick' frames for immediate feedback.

An alternative idea to avoid the render-to-texture-combined-with-fullscreen-quad approach is to create swapchains with one backbuffer. The quick image could be rendered directly to the backbuffer. The slow image is still rendered to texture, but the final stage would be to blit the slow image to the backbuffer. That way, the main thread only has to call Present() whenever it wants, and very little locking has to happen. Well, actually lots of locking has to happen, but it will be relatively simple, and the waiting will be limited. I would use a rendercommand queue approach where every rendercommand does some state setting and typically one draw call. Each one of those would then be locked separately, giving the main thread the opportunity to call Present() in between rendercommands.

Thanks for reading!

This topic is closed to new replies.

Advertisement