Archived

This topic is now archived and is closed to further replies.

Chaucer

multi-threaded rendering problem

Recommended Posts

I''m using dx8.1 I''ve got my main thread rendering a loading screen. I''ve got a second thread doing initialization. The problem is that I need to render to a texture during initialization. I''m getting a problem rendering to the screen in one thread and rendering to a texture in the other at the same time. I''m using 1 device in both threads. Does anyone here know if using a device in each thread would solve the problem? If so, would I still be able to render the texture on my 1st device that was rendered to in my 2nd device? Any ideas on how to solve the problem if a second device won''t work or textures are device dependent? Thanks.

Share this post


Link to post
Share on other sites
Use a single device and pass the threading flag on device creation.


Development Lead
Windows Graphics & Gaming Technology

Share this post


Link to post
Share on other sites
Make sure your CreateDevice() call is on the same thread as your window creation and window proc.

IMO it's best to keep ALL D3D calls and Windows UI calls on the same thread with worker threads working only on providing data for those calls.


EDIT:

Oh yeah, you don't have a multiprocessor system do you?

Also, conceptually, rendering to a texture and to the screen at the SAME time doesn't seem right to me - there's only ONE display device - so surely one of those threads must need to block until the other has finished with the display device.

Herb: is the DDI command queue thread safe for this kind of thing? - I have a horrible picture in my mind of commands for one target interleaved with commands for the other and the driver not knowing which commands are for which target. Assuming each thread had more data than it can send in its quantum.



--
Simon O'Connor
Creative Asylum Ltd
www.creative-asylum.com

[edited by - S1CA on May 8, 2003 7:32:59 AM]

Share this post


Link to post
Share on other sites
No multiprocessor system. CreateDevice() is in same thread as windowproc and window creation.

The error I''m seeing doesn''t occur every time either. Usually, on the 2nd or 3rd try, everything will work fine.

Share this post


Link to post
Share on other sites
I''m just stumbling upon the same problem.
I''m using DirectShow to render into a texture (taken from Texture3d-Sample) and using this texture during display.
I use D3DCREATE_MULTITHREADED, which keeps all the stuff from flickering, and everything worked fine on my developer pc and other pcs (using NVidia gfx cards).
It would not work on another Intel based gfx card, which would sometimes show a white box (instead of the texture).
Now i''m resorting to some kind of caching and updating the texture itself after the displaying (hurray, triple copy).

Share this post


Link to post
Share on other sites
[To Chaucer:]

Hmmm, so what's the actual error?

- crash?
- lock up?
- bad return code from D3D? (which?, any debug spew?)
- corrupted rendered result?
- unexpected render order?



Intermittent problems with multithreaded apps are very often down to only a few areas (or at least every time I've experienced any):

- Bad synchronisation (e.g. missing critical sections etc)
- Bad thread priorities (e.g. deadlocks between interdependent threads with the same priority)
- Not using thread safe versions of API calls (D3D, CRT, Win32)
- Using multiple threads to try concurrent access to something where it isn't safe to do that (Herb should be able to confirm whether what's under the covers is or not).

--
Simon O'Connor
Creative Asylum Ltd
www.creative-asylum.com

[edited by - S1CA on May 8, 2003 12:18:05 PM]

Share this post


Link to post
Share on other sites
D3DCREATE_MULTITHREADED is just the first part of using a single Direct3D device in a multithreaded environment. This flag ensures that only one thread enters the API at any one point in time.

The catch is that there is only one set of device state per Direct3D device, not one set of device state per thread. If you have two threads accessing the device, you must prevent each thread from messing up the device state for the other threads.

Here''s an example that''s still possible even with D3DCREATE_MULTITHREADED set:

Thread 1: SetRenderTarget(RT Texture #1)
Thread 1: DrawPrimitive(Some initialization geometry)
Thread 2: SetRenderTarget(BackBuffer #1)
Thread 2: DrawPrimitive(Loading screen geometry)
Thread 1: DrawPrimitive(Rest of initialization geometry)
***Thread 1 just rendered onto BackBuffer #1, not RT Texture #1
Thread 2: Present
***Thread 2 just presented the garbage drawn by Thread 1

You''d need a lock in your application to solve this. To render in a given thread, grab the lock and set all the device state to what you need. Release the lock when the thread is finished rendering. The next time the thread acquires the lock to render you can not assume any device state remains the same since another rendering thread may have come along and changed it.

Is there another solution that isn''t as convoluted? It depends on what you''re doing with the initialization rendering. If you''re just building some procedural textures or something like that, then you can create a second device and build the textures there. Since it is not valid to use resources created on one device in another device, you''ll have to lock and manually memcpy the data into a texture created on the other device.

Share this post


Link to post
Share on other sites