Sign in to follow this  
hegel

load and render at the same time

Recommended Posts

My program render .x animation in a thread called render. at the same time, another thread called loader is loading other .x files in the background. when the loader thread finished, the render thread crashes. I went through the debug information, and I think the reason is as follows: My x file loading engine uses effects to create textures. So if the loader thread creates new effects on the device when the render thread is processing effect passes to draw a subset, the render thread will crash. The reason is that these 2 threads share the same device and all effects are bound to this device. An obvious solution is to create and use another device for the loader thread. My question is that is there any solution, which can make these two threads both work well with only one shared device.

Share this post


Link to post
Share on other sites
Crashes caused by D3DX functions that are called from another thread are a common problem. Microsoft is working on this but AFAIK there is no real solution available yet.

Calling functions that don’t use the device seems to be safe.

Share this post


Link to post
Share on other sites
Quote:
Original post by hegel
Poor Microsoft. In OpenGL, this can be solved simply. But directx makes it really a mess. It seems that I have to go with multiple devices.


These will not necessary help you as you can’t use resources create from one device with another one. The common multi thread praxis for Direct3D is to load and parse/compile on one thread but create on the main thread. And don’t use D3DCREATE_MULTITHREADED. It has a bad Performance behavior.

Direct3D 9 was never really build for multi threading as usual system at this time have one CPU with one Core. Direct3D 10 will behave better as the D3DX functions are already have build in multi threading loading. Maybe we will see this in the D3DX version for D3D9, too.

Share this post


Link to post
Share on other sites
I had a similar problem in my MFC app. I would be applying some editing modification to the mesh (changing the vertex and index buffers) when windows would send another call to OnPaint(), and it would attempt to render the mesh I was in the middle of modifying. So, I just added a flag that would stop rendering that mesh until I was done with it.

I can't see MS ever fixing all possible multithreading issues. So, as a programmer it is a good idea to understand them. There are various ways to keep threads from banging into each other. For example, you could make sure that the rendering thread does not see the mesh until the loader thread is done with it. Flags can be dangerous, because you have to be sure to handle them correctly in all possible error paths, or you may end up leaving a flag ON that locks out another thread.

And to top it off, multi-threading also creates new problems with multi-processors, since the processors can have their own cache.

Share this post


Link to post
Share on other sites
Quote:
Original post by DXnut
I can't see MS ever fixing all possible multithreading issues.

This is being worked on for D3D10. There will be new and improved multithreaded D3DX function calls. For example, you will be able to pass a function like D3DXCreateTextureFromFile() an array of filenames, and it will go out, create a bunch of threads, and automatically load all of the textures in a multithreaded manner. So that is pretty nice.

However, the D3D device itself should still be single-threaded, at least until new features in the hardware come along. All flagging the device creation with D3DCREATE_MULTITHREADED does is force it into a bazillion critical sections, so that is why there are massive performance hits.

As far as loading & rendering goes, you can adopt a few strategies:

(a) Render your stuff in-between loading resources. So it would go like this:


- Render loading screen
- Load resource (1)
- Render loading screen
- Load resource (2)
...


(b) Load the files into memory in a separate thread. Then use the D3DX*InMemory() functions (from within your graphics thread) that will load a resource from a buffer already placed in memory. Tthis easy to multithread and will save a lot of time.

Share this post


Link to post
Share on other sites
There should be some strategy for a single device to seperate resources created from multiple threads. If the device can't do this smoothly, its multithread creation flag is misleading in a sense.

I uses two devices now to solve this problem, and the loading thread didn't interrupt the rendering thread. I think I'd better go with this solution.

If microsoft wanna occupy 3d engine market, this multithread problem should be solved in the first hand. Expecting directx 10.

Share this post


Link to post
Share on other sites
Well, having worked for 14 years in a mainframe environment that uses multi-threading and multi-processors, and where performance is extremely critical (10s of millions spent each year to handle demand), I am used to having to think out the issues involved when you have a multi-threaded application. But if MS is really going to design DX10 to inherently provide all of the mechanisms necessary to protect the programmer from all the potential pitfalls they could encounter using DirectX resources with multiple threads in a multi-CPU environment, then they are going to somehow have to deal with the severe impact to system performance and overhead that such a generic black box solution would cause.

Game programming is kinda like the environment I came from. They are constantly trying to max out what the current hardware is capable of. That is why I would see such a black box solution by MS as being a fools dream. They have purposely developed DX to be an extremely efficient solution for 3D hardware accelleration, where the programmers still have a large responsibility in learning how to design applications that work (don't crash) and offer the best performance possible. For example, I cannot see Valve relying on MS to ensure thread safety in Half Like 2.

MS has put in mechanisms to ensure that you can lock and access a buffer that is currently being rendered by the GPU by including the appropriate locking options, but handling the CPU/GPU concurrent processing is very different than handling multiple resource conflicts that you may cause using mulitiple threads in a multi-CPU system.

I could be wrong. Maybe MS has decided that the average game programmer cannot be expected to understand the issues and has decided to provide some kind of panacea. However, the real pros will care about the dramatic performance impact that such a solution would cause, and will prefer to have total control over how their programs manage their resources. Of course, if they see DX10 as being married to the .NET format, then the future of DX is rather bleak.

I doubt they would do that.

Share this post


Link to post
Share on other sites
Generally, what developers want out of a multithreaded device is to be able to load resources in a threaded manner (which I mentioned that D3DX10 will have APIs for). After that, there is usually a single, dedicated rendering thread that does all of the graphics work. There are additional threads for AI, physics, and game updates, and possibly more (or less), depending on the capabilities of the system.

There is a short article on Gamasutra in this realm - Threading 3D Engine Basics.

Share this post


Link to post
Share on other sites
That makes sense. I saw that the DXUT stuff can be made to use a mutex (or something) when locking a resource for updating. So I was trying to imagine what would happen if MS built that kind of thing into the entire SDK so that any attempt to alter a resource used one of the multi-threading things (like a mutex) to prevent clashes. That would be ugly!

Share this post


Link to post
Share on other sites
Nice gamasutra article, thanks ,I will use it too :)

Yet I'd advise you (OP) not to create your device with a multithread flag. Sure you could loose performance but on top of that you could be mislead into thinking that you could do anything anytime with the device.

A nice approach imho is the one suggested by circle soft. Consider your 'rendering' thread not really as such, but as the 'dx thread' or something, to which you could ask a variety of services like creating a texture, creating a vertex buffer, or whatever, and of course 95% of the time, render the scene.

Share this post


Link to post
Share on other sites
Quote:
Original post by DXnut
I saw that the DXUT stuff can be made to use a mutex (or something) when locking a resource for updating. So I was trying to imagine what would happen if MS built that kind of thing into the entire SDK so that any attempt to alter a resource used one of the multi-threading things (like a mutex) to prevent clashes. That would be ugly!

This is essentially what the D3DCREATE_MULTITHREADED flag does. Any time you attempt to make modifications to a resource, it wraps it in a critical section (or one of those objects). The same goes for making state changes and submitting calls to the driver (like DrawIndexedPrimitive()).

Share this post


Link to post
Share on other sites
I am using the D3DCREATE_MULTITHREADED option when I create the device for my MFC app. I wasn't sure what it actually did, but decided to include it since an MFC app is multi-threaded by default and cannot be changed.

I was still getting problems though when I would be tracing a routine in the debugger that was making changes to the mesh's vertex and/or index buffer, and a the OnPaint() would get called by windows due to the window getting invalidated somehow. So I added a pause flag that I can check in OnPaint to suppress it when I am making such a change.

So, although it may prevent two threads from attempting to lock and update a buffer at the same time, it does not stop your program from attempting to draw the mesh while another thread is updating it.

So, if you have one thread rendering a mesh when it sees that the ID3DXMesh interface is non-zero, but another thread prematurely set that pointer before it was done loading and possibly changing the mesh for the game to use, then you will have problems.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this