“MULTITHREADED” Or Not “MULTITHREADED”?
This is the first question that fires your brain’s sensor if you thinking about implementing a multitasking system in your 3D application. “D3DCREATE_MULTITHREADED” is a creation flag that makes the Direct3DDevice9 multithreaded safe. it’s easy. it works but it’s slow! also, this flag will not solve your problems in a multithreaded system. it just makes some functions of the device multithreaded safe (Lock/Unlock for instance).
There are so many problems that still exist and will confront in synchronization between threads and application events. For example, suppose that a thread is decompressing a file to load resource data and copy them to the buffers of a locked surface. at this moment the application tries to release the surface. What we can do? The first answer is shutting the thread down, but it’s worse because terminating a thread is a very dangerous operation. The thread may have allocated a memory block or created events and finally, you may have implemented third-party libraries (zlib to decompression) it would be an unpredicted operation.
Where is the solution?
You have to design a general solution to solve the problems and represent a safe environment to extend and avoid the same problems. I created a Task Manager system that has some internal threads and queues of tasks. for each task, you can specify the destination thread and send it to the task manager. The task manager executes any task in a specified thread. After that, I made some tasks to call Direct3D functions in the main thread. the other threads can send these tasks to the task manager and wait for them to complete. this solution makes the Direct3D function calls safely. also, I made some tasks for destroying objects to solve the mentioned problem above.
The other useful multitasking technique that can implemented by task managers is Self Delayed Task. This is very important to avoid the main thread from waiting. in my application, each task in the queue of the main thread will execute in the main loop of the application. thus some tasks with special missions the other threads can check the flags and add them again to the task manager to execute in the next loop. I used this technique to destroy objects. when an object is going to be destroyed and has some tasks that are executing in other threads at the same time, the destroy task will delay itself to execute in the next loop, instead of waiting for other thread to let the main loop continue running.
Now in SeganX engine, resources can be created and loaded in the background. The other feature is loading specified LOD of objects in the background depending on the distance of the camera. In this feature, every object at a far distance will load a low level of LOD to reduce the time consumption of decompression files, transporting data to buffers, and other operations. For example, to load a texture 1024×1024 of an object in a far distance the system loads the mipmap of 256×256 at first and when the object comes closer, the other mipmap will load consecutively. The other new feature is the resource manager of the device buffers can classify and cache created buffers for reuse later to decrease the number of Direct3D creation operations.
Very nice work and the result is very amazing.
I want this too 😀