#1 Members - Reputation: 368
Posted 08 November 2012 - 01:15 AM
My program is using DX9 and can't share the Device among multiple threads. Which means I can't create resources on other threads.
I wanted to know if it is possible to create vertex, index buffers and textures on the main thread and then pass those resources to a worker thread that lock/read/write/unlock/release these resources while the main thread is rendering? These resources sent to the worker thread will not be in use intil the worker thread has finished and sent those resources back to the main thread.
Will this type of multithreading work for DX9? Or are resources created with the device unsafe for other threads?
Cheers!
#2 GDNet+ - Reputation: 1731
Posted 08 November 2012 - 01:51 AM
Yes, it's not supposed to happen. They're also not supposed to garble textures nor to crash but sometimes it happens and if you're dealing with people still on D3D9, I'd give up every thing I consider certain.
Now, I have been told this is fixed but multithreading was in its early ages and the official documentation about D3DCREATE_MULTITHREADED isn't very encouraging. D3D9 was way, way crude in its effective multi-threading capability.
Personally I would map/unmap/interact with D3D9 in the main thread and then pass the raw memory blob to the worker thread. This way D3D9 is out of the equation.
#4 Members - Reputation: 368
Posted 08 November 2012 - 02:20 AM
In my head I create a texture or a vertex buffer on the main thread, then push a pointer to the resource to a Critical_Section vector, retrieve that from the worker thread, copy data over send it back.
Some code might help me understand ;)
EDIT: Is it as simple as Addref(), Release() when sending and retrieving it?
Edited by Tispe, 08 November 2012 - 02:34 AM.
#5 Senior Moderators - Reputation: 3113
Posted 08 November 2012 - 02:40 AM
In time the project grows, the ignorance of its devs it shows, with many a convoluted function, it plunges into deep compunction, the price of failure is high, Washu's mirth is nigh.
ScapeCode - Blog | SlimDX
#6 Moderators - Reputation: 13554
Posted 08 November 2012 - 02:45 AM
e.g.
D3DLOCKED_RECT result = {};
texture->LockRect(0, &result, NULL, D3DLOCK_DISCARD);
SignalWorkerThreadToGenerateData( result );
... later ...
if( WorkerThreadIsDone() )
texture->UnlockRect(0);
void* result = 0;
buffer->Lock(0, 0, &result, 0);
SignalWorkerThreadToGenerateData( result );
... later ...
if( WorkerThreadIsDone() )
buffer->Unlock();
Edited by Hodgman, 08 November 2012 - 02:47 AM.
#7 Members - Reputation: 368
Posted 08 November 2012 - 03:11 AM
Will it also work with the ID3DXBaseMesh::LockVertexBuffer method if I use the ID3DXMesh wrapper?
#8 Moderators - Reputation: 1918
Posted 08 November 2012 - 05:38 AM
You can then implement your class to store the ARGB pixel data internally, and then after calling D3DXLoadSurfaceFromMemory(), you can copy that ARGB data into the real surface (Which should be locked in the D3D thread and the pointer passed to the worker thread).
Or, just not use D3DXLoadSurfaceFromMemory()
Steve Macpherson
Senior programmer, Firebrand Games
#9 Members - Reputation: 368
Posted 08 November 2012 - 05:57 AM
Baw, it seems Microsoft didn't have multithreading in mind when implementng D3DXLoadSurfaceFromMemory(). I hope I can get away with calling this a few times each frame.
It seems that I will have to scrap the whole idea of passing mapped/locked resource pointers to worker threads to keep things simple. I guess I can use GetTickCount() after each resource I process and check if elapsed time is not too much, that way I can skip processing to next frame to avoid huge drops in frame rate.






