About multi-thread when rendering.

Started by
4 comments, last by niexuchina 15 years, 8 months ago
I noticed that D3D's rendering calls, those calls like SetRenderState(), SetTexture(), Draw*() and so on, consume very much time. I think that Draw*() returns only after rendering is completely done. So I wonder whether I can promote performance by doing CPU work and rendering in separate threads. For example, I start a thread to do physics before rendering calls. While the main thread holds in Draw*(), the separate thread goes on its computing. I wonder whether the most time in Draw*() is used for waiting GPU to complete its work.
Advertisement
Draw calls do not generally wait till the actual drawing is done. The graphics driver usually implements a queue which is flushed at the latest possible time - by the time rendering results are actually needed, whether it is for presenting or locking. This can result in a condition called "stalling" where results of an earlier draw operation have to be waited in order to complete the current one, but this is a different issue than call cost.

The API calls are relatively expensive, which is why you should draw your stuff with as large batches as possible, with as few state changes as possible. D3D10 eases this situation somewhat by having lighter call overhead due to improved driver architecture, but it still does not fix the problem entirely.

In current versions of D3D, multi-threading is cumbersome since device calls must be made from a single thread, or request a thread-safe device which slows down performance a lot.

However, in D3D11, it will be possible to manually queue state change calls in a separate thread(s) and flush the queues in the primary drawing thread. The first public preview of D3D11 is slated for release with the November SDK.

Niko Suni

Thank you very much.
Generally speeking, how many times should I draw in a frame? Is 100 to 200 a reasonable count?

[Edited by - niexuchina on August 24, 2008 10:27:28 AM]
100-200 is fine. If you're approaching 500, you may not run well on older hardware, but should be okay on a fast CPU/GPU. But it all depends on your needs (minimum target hardware spec., minimum acceptable frame rate, etc.)

Even without D3D11, you can save time with threading. Hyperthreading was around for a while, now everything is dual or quad core, and consoles are stuffed with cores. Use one thread for rendering and creating GPU resources (textures, shaders, etc). Another can do AI updates, collisions, physics, etc. A third may prepare for the renderer, just figuring out what's visible, and sorting it before passing it off to the renderer. As that thread is already dealing with your world data, perhaps it can also choose which data may need to be streamed in next.

Keeping everything correct while splitting up your work load is where it gets tricky. People are only starting to code this way for games, so there isn't much information out there, and there are no well known common ways of approaching it.

Insomniac posts a fair bit of high-level design on their website, which is natually PS3 based.

The PS3 cell processor handles threading differently than most processors. While you can port the PS3 style architecture to PCs and get good performance, porting typical PC style code to the PS3 doesn't work. Grabbing the cell development kit (it's free I think), may be a good place to begin some research. You can take whatever limitations it's model imposes, and keep those on the PC, and you should have something that will work anywhere. If you have a PS3 you can try it all out in practice with Linux.

Just the other day, Carmack, Intel, and Dreamworks were discussed threading here and here. I haven't had a chance to look at the full article, but I assume there's *something* in there.
Thank you VERY much.

This topic is closed to new replies.

Advertisement