Sorry for the awkward title on this post, but I've been having a hard time solving a Managed Direct3D mystery, and if I can find or figure out the solution, I want the entry to be obvious in Google, because I've been unsuccessful in locating the answer that way myself.
So it seems that people are still reading my managed Direct3D tutorial, because last week I got three questions about it via email. Two of them, surprisingly, were exactly the same. Apparently, if you compile and run the device recovery tutorial, you'll find that everything works great the first time you come back from hitting ctrl-alt-delete. But if you do it again, your application crashes with a Microsoft.DirectX.Direct3D.InvalidCallException during a call to Device.Present. Turning on the DirectX debug spew shows more details about the error:
2300: Direct3D9: (ERROR) :The following D3DPOOL_DEFAULT surfaces/buffers/textures still exist
2300: Direct3D9: (ERROR) : D3DRTYPE_VERTEXBUFFER
2300: Direct3D9: (ERROR) :All user created D3DPOOL_DEFAULT surfaces must be freed before Reset can succeed. Reset Fails.
2300: Direct3D9: (ERROR) :Reset failed and Reset/TestCooperativeLevel/Release are the only legal APIs to be called subsequently
There are several weird things about this:
- It only happens the second time you lose the device.
- It only happens if you lose the device via ctrl-alt-delete; you can alt-tab as many times as you like.
- I'm pretty sure I'm freeing the VertexBuffer correctly.
So far, I've discovered that it only happens if you create the VertexBuffer in the default pool. If you change to using Pool.Managed, the problem goes away. This makes sense, and is a reasonable workaround, but sometimes Pool.Managed isn't an option, so I'd like to figure out how to use Pool.Default.
So far here's what I've tried with no luck:
- Calling Marshal.Release on the VertexBuffer's underlying raw UnmanagedComPointer.
- Calling Device.SetStreamSource(0, null, 0) after every render.
- Calling GC.Collect and GC.WaitForPendingFinalizers after Disposing of the VertexBuffer.
I'm rapidly running out of ideas. But I'll keep searching, and when I figure something out (or someone tells me what I'm doing wrong), I'll post a comment here and update the tutorial.