Sign in to follow this  
Tape_Worm

[MDX/C#] Device release issue.

Recommended Posts

Direct3D9: (ERROR) :Final Release for a device can only be called from the thread that the device was created from. That's the error I get from the debug spew from D3D when I close my app. I don't have any extra threads running, nor am I calling any of the create/destroy functions from an event. I'm cleaning up everything that's associated with the device (textures, etc...) but yet that still keeps popping up. To make matters worse, it pops up randomly. Sometimes it exits with the standard MemFini and no errors at all, and other times I get the aforementioned error. Any idea what would cause this? Or is it something I have to live with?

Share this post


Link to post
Share on other sites
Have you already tried just letting the GC take of releasing objects? I'm venturing a guess to say I'm sure you have, but just wanted to throw that out there just in case.

-AJ

Share this post


Link to post
Share on other sites
You can't let the GC release the DirectX objects, because it's not predictable enough.

You get that error when the Device isn't actually properly released when you close your program. Either because you're not calling Device.Dispose(), but more likely because you're not calling Dispose on one of the resources created by the device (mesh, vertex buffer, texture, render target etc).

I've found that the best way to deal with this is to wrap the texture, mesh and other objects I create in a class of my own. This class contains the data needed to re-create the object (file path, typically), and it registers for event callbacks when the device is created and disposed. In fact, I wrap the device class, too, so that the connection is persistent even after destroying the D3D Device.

This way, the system easily deals with devices being created and destroyed; I can easily switch between REF, SWVP and HWVP, etc.

Share this post


Link to post
Share on other sites
Quote:
Original post by hplus0603
You get that error when the Device isn't actually properly released when you close your program. Either because you're not calling Device.Dispose(), but more likely because you're not calling Dispose on one of the resources created by the device (mesh, vertex buffer, texture, render target etc).

I've found that the best way to deal with this is to wrap the texture, mesh and other objects I create in a class of my own. This class contains the data needed to re-create the object (file path, typically), and it registers for event callbacks when the device is created and disposed. In fact, I wrap the device class, too, so that the connection is persistent even after destroying the D3D Device.

This way, the system easily deals with devices being created and destroyed; I can easily switch between REF, SWVP and HWVP, etc.


I don't think it's due to not calling Dispose on the objects, I have wrapped all the objects and they're tracked via collections in the root object and when that root object's Dispose method is called, the collections in turn call the Dispose methods for the objects stored in the collections. I've checked and rechecked and the dispose methods are indeed being called. The really strange thing is that the error shows up randomly, if it were due to a lack of calling Dispose() I think the error would be more consistent, and I'd probably get a ton of memory allocation errors in the debug output (which does happen when I don't call Dispose() on the D3D objects). It's almost as if the Dispose method is being called from an event (which is run from a thread pool), but I can't see any place in the code where this would be happening. The only event that gets called is my FrameBegin event, but there's definitely nothing in there that would release the device object. Is it possible that when I close the window and the execution is still within the event that the device would somehow think it's out of context?

Thanks for the suggestions though.

Share this post


Link to post
Share on other sites
Goddammit I'm dumb.

In an attempt to not be redundant, I was setting my Index buffer to the device but only if the same buffer wasn't already assigned... "how?" you might ask, and you did ask that, I can see you...


if (_device.Indices != IndexBufferWrapper.D3DIndexBuffer)
_device.Indices = IndexBufferWrapper.D3DIndexBuffer;



The retrieving of the Indices I think incremented the reference count somewhere (whether that be on the device or index buffer I don't know) and consequently wasn't allowing the device to be freed up from my application. I commented out the if statement and no more errors. Go figure. (I certainly hope this is the case, else my computer is just being evil by luring me into a false sense of security).


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