   (DX9/DX10) Creating 2 or more device at the same time
  The question is simple and short.Do the creation of two or more device at the same time (on different threads, but on the same application on a multicore machine) can create some problems? (the question is related to the creation only, because they actually work fine after created, but i had a while ago a crash I cannot reproduce again on CreateDevice and i'm investigating...)Or should i make this operation serial?   
  In DX9, you must make all D3D calls from the same thread that processes window messages, or you must create a multithreaded device, and then only some functions need to be called from the window pumping thread (See the docs for details on which, but it includes CreateDevice()).There's also a pretty large performance penalty associated with having multiple devices in a single application, but I don't know how that applies to DX10.Are you creating one D3D9 and one D3D10 device, or are you just asking the question about D3D9 and D3D10 separately?   ;  Thanks for the answer. I'm actually trying to reproduce again the problem (happened only one time) even thought i think i found out what was causing that problem and i'll try to avoid it and see what happen. I checked inside the docs and it said that the device creation will fail if the handle I'm sending was still on WM_CREATE. Talking about other things, from what i've read i can execute any kind of operation, and obtain as many device as i want on either DX9/DX10 as long as any operation executed on them (the devices) are thread-safe. (the Multithread flag is NOT required if you do your own synchronization)I'm currently using a thread system like this and it work quite well.Window Thread/Core Thread (that manages window messages and the scheduling of the various engines active)    Engines Thread (one for each engine that create the device and execute if necessary the Reset/TestCooperativeLevel and schedule the various tasks to execute.)   Tasks Threads (at least 3 for engine (Audio, Update (for the next frame draw), Draw (the only one who actually use Direct3D calls except for the engine thread)), but the application can add others if needed with their own timing)Anyway i'm using multiple dx9 device or multiple dx10 device, never mixed. I need them for some advanced editing tools that may require have multiple window with a DirectX surfaced part.   ;Quote:Original post by feal87Talking about other things, from what i've read i can execute any kind of operation, and obtain as many device as i want on either DX9/DX10 as long as any operation executed on them (the devices) are thread-safe. (the Multithread flag is NOT required if you do your own synchronization)Are you sure about that? I know the debug runtimes go totally insane if you go anywhere near a D3D9 device from multiple threads without the multithreaded flag. The driver could well be running another thread and might go horribly wrong if it gets requests from multiple threads unexpectedly. And when you get into areas that aren't properly defined, you end up with code that breaks with weird errors on some drivers or OS's, and might break completely on future versions of Windows.Quote:Original post by feal87Window Thread/Core Thread (that manages window messages and the scheduling of the various engines active)    Engines Thread (one for each engine that create the device and execute if necessary the Reset/TestCooperativeLevel and schedule the various tasks to execute.)If your Engines thread is handling D3D9, then you're in for some headaches - the device must be on the same thread as the one handling window messages, or you must make calls to CreateDevice(), TestCooperativeLevel(), Reset() and Release() from the Window/Core thread and use the multithreaded flag.If I were you, I'd make your main thread process window messages and make all D3D calls, and then spawn other threads for anything else you need.   ;Quote:Original post by Evil SteveQuote:Original post by feal87Talking about other things, from what i've read i can execute any kind of operation, and obtain as many device as i want on either DX9/DX10 as long as any operation executed on them (the devices) are thread-safe. (the Multithread flag is NOT required if you do your own synchronization)Are you sure about that? I know the debug runtimes go insane if you go anywhere near a D3D9 device from multiple threads.Quote:Original post by feal87Window Thread/Core Thread (that manages window messages and the scheduling of the various engines active)    Engines Thread (one for each engine that create the device and execute if necessary the Reset/TestCooperativeLevel and schedule the various tasks to execute.)If your Engines thread is handling D3D9, then you're in for some headaches - the device must be on the same thread as the one handling window messages, or you must make calls to CreateDevice(), TestCooperativeLevel(), Reset() and Release() from the Window/Core thread and use the multithreaded flag.If I were you, I'd make your main thread process window messages and make all D3D calls, and then spawn other threads for anything else you need.1) Well yes, i'm pretty sure, the debug runtime gives you warning each time because you can "potentially" cause race conditions (and deadlocks which are bad :|). I read on a nVidia paper that is preferable to use multithreading WITHOUT the multithread flag because it is bad for performance because add a good amount of overhead due to synchronization functionality. (On DirectX10 they removed altogether the Multithread flag and the notice on the Debug runtime.)2) Not really, my engine works fine even with pretty heavy applications right now (among the various test games, i'm actually working on a interactive Window editor for speeding up the developing of applications with my engine cause making window is so slow by code :(). From what i'm reading the Reset, TestCooperativeLevel and Release must be handled by the SAME thread that created the device, not by the window message handling thread and the CreateDevice can be called everywhere, but only after the handle you are using passed through the WM_CREATE stage. This was was my miss, because Windows Forms on C# doesn't create the handle right away but only when the window is opened, i need to make a fix for it cause i have the HandleCreated event so i can be sure of when it is created instead of hoping it is created fast enough like now :DActually these (CreateDevice, Reset, TestCooperativeLevel, Release) are the only operations I make the engine thread handle (before scheduling the child threads).The Draw thread (one of the child thread) handle the rest. This way synchronization for using Direct3D calls isn't needed. It is exactly like using a single thread (first execute reset if the device is lost etc.. and then the draw thread execute the rest all in a serial manner).quoting the MSDN :"The methods IDirect3DDevice9::Reset, IUnknown, and IDirect3DDevice9::TestCooperativeLevel must be called from the same thread that used this method to create a device."   ;Quote:Original post by feal871) Well yes, i'm pretty sure, the debug runtime gives you warning each time because you can "potentially" cause race conditions (and deadlocks which are bad :|). I read on a nVidia paper that is preferable to use multithreading WITHOUT the multithread flag because it is bad for performance because add a good amount of overhead due to synchronization functionality. (On DirectX10 they removed altogether the Multithread flag and the notice on the Debug runtime.)Interesting. If the NVidia papers say it's ok, then I suppose it should be alright. Personally, I'd still avoid it where possible - there's little point in having multiple threads making D3D calls since it'll just cause a chokepoint as they all try to talk to D3D with the mutex held.Quote:Original post by feal872) Not really, my engine works fine even with pretty heavy applications right now (i'm actually working on a interactive Window editor for speeding up the developing of applications with my engine cause making window is so slow by code :(). From what i'm reading the Reset, TestCooperativeLevel and Release must be handled by the SAME thread that created the device, not by the window message handling thread and the CreateDevice can be called everywhere, but only after the handle you are using passed through the WM_CREATE stage.From Multithreading Issues (Direct3D 9):Quote:For these reasons, Direct3D is designed so that the methods IDirect3DDevice9::Reset, IDirect3D9::CreateDevice, IDirect3DDevice9::TestCooperativeLevel, or the final Release of IDirect3DDevice9 can only be called from the same thread that handles window messages.It may work, but it's still undefined behaviour unfortunately.   ;  Interesting page, still i can't find anything similiar for DX10...someone who has some insight?I'll anyway explain, the problem that the page IMHO (i can't be sure cause i'm not a DX engineer, but reading the paper give me that meaning :D) is talking is about doing Message Processing and DirectX call TOGETHER from two different threads that will sometimes cause deadlock on mode change inducing functions, but that is not my case because i'm managing them anyway in a SERIAL way.This is an example of a frame in my Engine(CORE THREAD)1) Manage all window events.2) Are there any engine active?  If no go to 3a, if yes go to 3b.3a) Sleep for 20 ms and return to 1.3b) Schedule NCPU engines until all engines are completed. (** this execute the ENGINE THREAD that i'll talk later on)4) Wait for all engine to complete their operation and return to 1.(ENGINE THREAD)1) Do we have to reset or create the device? If yes do it. 2) Update the engine clock.3) Schedule NCPU child task until all child task are completed.4) Wait for all child tasks to be completed.5) Synchronize data between each child task.6) Quit the function. (basically making the thread returning to a sleep state cause it go into an WaitHandle until the next frame)(CHILD THREAD)1) Execute the functionality needed depending on the thread.What do you think Evil?EDIT : Anyway i agree with you, in fact i only make Direct3D call only by one thread (the draw one for each engine) except for the create/reset/testcooperativelevel.For being sure anyway i maked sure via mutex that the Enumeration of Direct3D, Creation of device and reset of the device is done sequentially (while still all on their own thread). How they say? Better safe than sorry? :DAfter all these operations will anyway occurs very rarely (especially on Vista+ machines) so they don't make any kind of strain on the system by making them sequential.[Edited by - feal87 on May 12, 2009 6:03:55 PM];Quote:Original post by feal87I'll anyway explain, the problem that the page IMHO (i can't be sure cause i'm not a DX engineer, but reading the paper give me that meaning :D) is talking is about doing Message Processing and DirectX call TOGETHER from two different threads that will sometimes cause deadlock on mode change inducing functions, but that is not my case because i'm managing them anyway in a SERIAL way.[snip]What do you think Evil?If you're making your D3D / window calls in a serial way then I think it's ok - but I'd still be extremely wary of doing it. If you're making D3D and windowing calls in a serial way, then surely it'd be better to do it all from one thread (Although I'm not really sure how well that'd work in practice). Threading issues can be very difficult to track down and reproduce, and it gets worse when you bring video drivers into play.   ;Quote:Original post by feal871) Well yes, i'm pretty sure, the debug runtime gives you warning each time because you can "potentially" cause race conditions (and deadlocks which are bad :|). I read on a nVidia paper that is preferable to use multithreading WITHOUT the multithread flag because it is bad for performance because add a good amount of overhead due to synchronization functionality.That's Microsoft's recommendation, too. A multithreaded D3D9 device adds quite a bit of overhead.Quote:(On DirectX10 they removed altogether the Multithread flag and the notice on the Debug runtime.)That's because the default has changed. The device is multithreaded by default, and you can make it single threaded using a flag.   ;Quote:Original post by ET3DQuote:Original post by feal871) Well yes, i'm pretty sure, the debug runtime gives you warning each time because you can "potentially" cause race conditions (and deadlocks which are bad :|). I read on a nVidia paper that is preferable to use multithreading WITHOUT the multithread flag because it is bad for performance because add a good amount of overhead due to synchronization functionality.That's Microsoft's recommendation, too. A multithreaded D3D9 device adds quite a bit of overhead.So does that mean that it's officially safe to do the synchronization yourself and not use the multithreaded flag?   