Sign in to follow this  

Reseting a dynamic vertex buffer after lost device

This topic is 2541 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm using a dynamic vertex buffer to render some terrain. As all resources that use the `D3DPOOL_DEFAULT` flag need to be released before you can reset the device, I have a method that takes care of calling the `Release` function on my vertex buffer.
Hi,
The thing is, my buffer is then no longer usable since it's been released, and calling `CreateVertexBuffer` to recreate it after the device was reset causes my app to crash.
How can I recreate my vertex buffer after I've reset the device?

I've also noticed that after I release the buffer, I can still use it even though I set the pointer to 0 after releasing it.

Here is the code I'm using:

Before I call `Reset` on the D3D device, I call `onLostDevice` for all resources that need to be released:

void Water::onLostDevice()
{
this->mVertexBuffer->Release();
this->mVertexBuffer = 0;
}

And after `Reset` was called on the device, I call `onResetDevice` on all the resources in the default mem pool:

void Water::onResetDevice(IDirect3DDevice9 *device)
{
device->CreateVertexBuffer(totalVertices * sizeof(d3df::VertexPositionColor),
D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &mVertexBuffer, 0);
}

The `onResetDevice` call causes the crash, yet I do need a way to get my vertex buffer back so that I can use it.

By the way, it crashes when I resize the window or go fullscreen.

Share this post


Link to post
Share on other sites
I'm pretty sure it's not the device that fails, since when I resize or go fullscreen I'm also calling OnLostDevice/OnResetDevice on some ID3DXFont and textures.
It only crashes if I call the CreateVertexBuffer inside my Water::onResetDevice() method.

Share this post


Link to post
Share on other sites
First, every DirectX function call gives some indication of success or failure. It appears you don't test any return values from those functions. Rather than guessing ("I'm pretty sure..."), use the SUCCEEDED() and FAILED() macros to see if functions work before you use the results. You can get information about failures by using DXGetErrorDescription(...) for the returned values from DirectX functions that return HRESULT indications.

When you get an error, you should take appropriate action to prevent your program from "crashing." And "crash" doesn't provide information with which to help you. Describe what problem you're having - other than "it doesn't work."

As mentioned above, use the Debug Runtime to give yourself information about what's going on.
Quote:
when I resize or go fullscreen I'm also calling OnLostDevice/OnResetDevice on some ID3DXFont and textures

It sounds like you're calling those functions on specific events. As belfegor mentions, you should be using device->TestCooperativeLevel() to determine when to call OnResetDevice and OnLostDevice.

Share this post


Link to post
Share on other sites
I removed the error checking to make it shorter. All calls succeed, but when I call the CreateVertexBuffer in the Water::onResetDevice, I get a runtime error that points to some code in a disassembly file and traces back up to the messageProc.
The only message I got from the d3d debug runtime is "Direct3D9: (ERROR) :All user created D3DPOOL_DEFAULT surfaces must be freed before ResetEx can succeed. ResetEx Fails." which is odd since I released my only dynamic instance in my call to onLostDevice().
Every time I call Reset on my device, I have a call to "onLostDevice" right before in which I release the resources that need released, then call Reset on the device and then "onResetDevice" on all resource that need it.
I'm releasing and reseting some ID3DXFonts and I have no probleme there, it's only when I try and re-create my vertex buffer that I get a crash (if I release the buffer and don't recreate it, I don't get that error, I do get an error for using a null pointer as excepted).

Share this post


Link to post
Share on other sites
Some clarification is needed.

Are you using IDirect3DDevice9 or IDirect3DDevice9Ex? The error referring to ResetEx doesn't look right at all. You certainly shouldn't be getting messages about extended objects if you're not using them.
Quote:
I get a runtime error that points to some code in a disassembly file and traces back up to the messageProc.

Are you calling your reset function from the Window procedure? If you're breaking on the error and going into debug, the output window in the IDE should give you a stack trace that, according to your description, should go back through your general OnResetDevice function, from which your water->OnResetDevice gets called. Does it?

If not, you need to determine how your water->onResetDevice gets called.

Suggestion: Don't concentrate on the fact that other calls (e.g., your font object) succeed. Concentrate on the errors you're getting.

Also, it would help a lot if you post the actual error output from your output window rather than describing it. [code][/code] and [source][/source] tags are your friend.

Share this post


Link to post
Share on other sites
The error that you stated indicates that the problem is that a surface wasn't released, not a vertex buffer. Make sure you have released your render target surfaces (including those that may have been acquired from textures).

Share this post


Link to post
Share on other sites
@Buckeye: I'm using IDirect3DDevice9.
The call stack is pretty minimal:

KernelBase.dll!75f722a1()
[Frames below may be incorrect and/or missing, no symbols loaded for KernelBase.dll]
Mod1.exe!DXTraceA(const char * strFile, unsigned long dwLine, HRESULT hr, const char * strMsg, int bPopMsgBox) Line 4852 C++
74636570()



And the ouptut I get is this:

D3DApp.cpp(131): md3dDevice->Reset(&md3dpp) hr=D3DERR_INVALIDCALL (0x8876086c)
Mod1.exe has triggered a breakpoint



But maybe I'm just not reseting the buffer the right way ? If I remove my call to CreateVertexBuffer, everything is fine.

@Magius3: I'm not using any surfaces, all I have are a few vertex buffers and some fonts.
But maybe you mean that I need to release the render target too ?

Share this post


Link to post
Share on other sites
Cheers for the link. I've read through it, but I'm still confused since I'm not using any calls to CreateRenderTarget and CreateDepthStencilSurface. CreateVertexBuffer is the only call I'm making, and I as I said, if I remove my dynamic vertex buffer, I don't get the runtime error.

Share this post


Link to post
Share on other sites
In my main application class:


// before I call device->Reset();
void Mod1::onLostDevice()
{
this->_water->onLostDevice();
this->_stats->onLostDevice();
this->_shader->OnLostDevice();
}

// after I call device->Reset();
void Mod1::onResetDevice()
{
this->_stats->onResetDevice();
this->_shader->OnResetDevice();
this->_water->onResetDevice();
this->buildProjectionMatrix();
}



In my water class:

void Water::onLostDevice()
{
this->mVertexBuffer->Release();
this->mVertexBuffer = 0;
}

void Water::onResetDevice()
{
// causes a crash.
// if I comment this out, the app doesn't crash.
HR(device->CreateVertexBuffer(totalVertices * sizeof(d3df::VertexPositionNormal),
D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, 0, D3DPOOL_DEFAULT, &mVertexBuffer, 0));
}



The vertex buffer was created in the same way as in the Water::onResetDevice method.

And this is how I check to see if I can use the device or not:

bool D3DApp::isDeviceLost()
{
HRESULT hr = md3dDevice->TestCooperativeLevel();
switch (hr)
{
case D3DERR_DEVICELOST:
MessageBox(0, "[error] d3df::D3DApp: Device lost", "Error", MB_OK | MB_ICONERROR);
Sleep(20);
return true;
case D3DERR_DRIVERINTERNALERROR:
MessageBox(0, "[error] d3df::D3DApp: Internal driver error", "Error", MB_OK | MB_ICONERROR);
PostQuitMessage(0);
return true;
case D3DERR_DEVICENOTRESET:
MessageBox(0, "[error] d3df::D3DApp: Device not reset", "Error", MB_OK | MB_ICONERROR);
onLostDevice();
md3dDevice->Reset(&md3dpp);
onResetDevice();
return true;
default:
return false;
}
}



And before each call to device->Reset() I call onLostDevice on all resources in the default mem pool, and onResetDevice after the device->Reset() call.

I've done this before using Sufaces and other resources that need released before Reset can be called, this is the first time I get that error using a dynamic vertex buffer.

I've found a hack to make it work, it's ugly but it does the trick. I would still like to understand what I'm doing wrong so that I can avoid this kind of problem in the future.

Share this post


Link to post
Share on other sites
A few things that might help:

1. Try switching to the debug runtimes - often you will get th exact reason why something failed (Buckeye suggested this also, hopefully you've taken a look at it already).
2. D3DERR_INVALIDCALL typically means that parameters are incorrect - I don't know where your present parameters variable (md3dpp), but make sure there is nothing wrong with the way you are populating that structure.
3. I don't see anywhere the fonts being reset. You say you do that in a previous post, but worth making sure those are all happening as well.

If your code base isn't too large, it's probably worth posting it in its entirety.

By the way, based on what you've indicated, the reason that it crashes when you keep in the call to CreateVertexBuffer call is because the reset failed with a D3DERR_INVALIDCALL. Obviously, the device isn't fully reset at the time you go to recreate the vertex buffer. Commenting it out is only masking the problem - you need to solve the reset invalid call issue you are getting first.

Share this post


Link to post
Share on other sites
Yep I'm already using the debug runtime, it wasn't outputing very useful messages.
The font reseting happens in the this->_stats->onResetDevice() call.

Anyway, I got to the bottom of it, so happens I was doing something wrong in my window proc. I've been using the same "app" class for a few months now and this is the first time I have a problem with it. It's all fixed now, thanks for the help and tips.

Share this post


Link to post
Share on other sites

This topic is 2541 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

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