[DirectX 9] Mesh gone after device reset

Started by
16 comments, last by Tispe 13 years, 1 month ago

As an aside, you shouldn't be performing lost device handling in response to WM_ messages. It will only end in tears.

To quote from the SDK:
By design, the full set of scenarios that can cause a device to become lost is not specified. Some typical examples include loss of focus, such as when the user presses ALT+TAB or when a system dialog is initialized. Devices can also be lost due to a power management event, or when another application assumes full-screen operation.

In other words, you aren't capturing all events that can cause a device to become lost, and the time will come when it bites you. Check the HRESULT of your IDirect3DDevice9::Present (or IDirect3DSwapChain9::Present) call for D3DERR_DEVICELOST instead.
[/quote]

hmm, I tried this:


if(d3ddev->Present(NULL, NULL, NULL, NULL) != D3D_OK)
ResetDevice();


ResetDevice() is the same function called when WM_ACTIVATEAPP is recieved. But the screen is blank after I ALT-TAB out and back in.I have to remove the whole WM_ messages routine to make it work.

Do I need to stop rendering when the app no longer has focus? Seems to me Present() will be ran in the background and I "reset" the device 60 times/sec while the app is minimized
Advertisement
In general, you would be better off not performing any device/rendering functions in response to window messages.

I would suggest you call ResetDevice() at only one location in your code (other than in your CreateDevice() routine), probably in your run loop after you call dev->TestCooperativeLevel, and the result of TestCooperativeLevel indicates that's the appropriate action to take.

With regard to what you tried: if dev->Present fails, ResetDevice() may not be the proper thing to do. The failure may not be a result of the device needing to be reset.

With regard to gaining/losing focus, it's possible to have your application run in background if there's an overriding reason. However, it would be probably be better to pause your app when it loses focus. That's an indication that the user (for the moment) isn't interested in your window.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.


hmm, I tried this:


if(d3ddev->Present(NULL, NULL, NULL, NULL) != D3D_OK)
ResetDevice();


ResetDevice() is the same function called when WM_ACTIVATEAPP is recieved. But the screen is blank after I ALT-TAB out and back in.I have to remove the whole WM_ messages routine to make it work.

Do I need to stop rendering when the app no longer has focus? Seems to me Present() will be ran in the background and I "reset" the device 60 times/sec while the app is minimized


Try something like this instead:
hr = d3ddev->Present (NULL, NULL, NULL, NULL);
if (hr == D3DERR_DEVICELOST)
{
while (1)
{
hr = d3ddev->TestCooperativeLevel ();
switch (hr)
{
case D3D_OK:
// device is no longer lost and reset has completed successfully; recover resources here
return; // note: this assumes that this test is the last thing in the function it's being called from
case D3DERR_DEVICELOST:
// device is still lost; can't do anything so do nothing
break;
case D3DERR_DEVICENOTRESET:
// device is ready to be reset; Release resources here and then Reset it
// (be sure to test the hr from your Reset call too!)
break;
default:
// something bad happened! quit the program.
break;
}
Sleep (5); // yield some CPU
}
}

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.


With regard to what you tried: if dev->Present fails, ResetDevice() may not be the proper thing to do. The failure may not be a result of the device needing to be reset.


Now I only reset if its lost


if(d3ddev->Present(NULL, NULL, NULL, NULL) == D3DERR_DEVICELOST)
ResetDevice();


where ResetDevice():


void ResetDevice()
{
if(d3ddev)
{
MSG msg;
while(d3ddev->TestCooperativeLevel() != D3DERR_DEVICENOTRESET)
{
//WaitMessage();
PeekMessage( &msg, NULL, 0, 0, PM_REMOVE );
TranslateMessage(&msg);
DispatchMessage(&msg);
Sleep(5);
}

if(FAILED(d3dspt->OnLostDevice()))
ErrorMessage(L"The d3dspt->OnLostDevice function failed");
if(FAILED(dxfont->OnLostDevice()))
ErrorMessage(L"The dxfont->OnLostDevice function failed");

if(FAILED(d3ddev->Reset(&d3dpp)))
ErrorMessage(L"The d3ddev->Reset function failed");

if(FAILED(d3dspt->OnResetDevice()))
ErrorMessage(L"The d3dspt->OnResetDevice function failed");
if(FAILED(dxfont->OnResetDevice()))
ErrorMessage(L"The dxfont->OnResetDevice function failed");
DeviceSettings();
}
}


Proper enough?
Proper enough?[/quote]
Wow. Actually, no. It appears you're just trying to patch things together.

First - the general principle of checking whether the device is valid after you've gone through updating and rendering, as a personal opinion, is backwards. Testing for a properly setup device should be done before it's needed for updating/creating objects/rendering/etc.

Second - I would suggest you separate windows messaging and DirecxtX processing to the greatest degree possible.

Take a look at the general arrangement of message processing, device status testing, updating, etc., in some of the SDK examples. Examing the flow Microsoft takes sounds like your best bet.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

So don't use Present() to check if the device is lost? Should I TestCooperativeLevel() each time I enter my rendering function and "abort" if there is an error?

In response to windows messaging, I do have the outer layer of the main loop seperate from DX stuff. This function however is just a secondary message handler for when the device is lost, I read that you should take care of messages while you try to reset the device.

So don't use Present() to check if the device is lost?

I wouldn't check for a specific error, no. I would use the FAILED macro to check it, if I needed to use the device before I call TestCooperativeLevel the next time, or, if for some other reason, I needed to know that the buffer had been successfully presented before continuing.

Should I TestCooperativeLevel() each time I enter my rendering function and "abort" if there is an error?[/quote]
First, TestCooperativeLevel doesn't return an "error" code, per se. It provides information about the status of the device. Some of the conditions indicated are actually to be expected.

Second, why even enter the rendering function if there's a problem?

In response to windows messaging, I do have the outer layer of the main loop seperate from DX stuff. This function however is just a secondary message handler for when the device is lost,[/quote]

Have you reviewed the general flow in some of the SDK examples as suggested? Look at EmptyProject, for instance. It sounds like you need a structured approach to your loop and you could probably do worse than follow the same flow shown in an SDK example.

I read that you should take care of messages while you try to reset the device.[/quote]
Sounds like a good idea - but not mixed in with DirectX functions.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

To be honest I have not used DXUT before. The concept of CALLBACKS are still strange to me. I read up on it and understand that you provide a pointer to a function as argument to another function. I get the basics but when looking at the EmptyProject.cpp code it is stange why you need to "Set the callback functions" when you can just have prototypes and call the functions as I need them.

You talk about the "flow" of a typical SDK example, but reading the forums it is said that using DXUT for a release is not used much, if at all. So I need my own structute and I have one. DXUT and CALLBACKS as I understand it is just a generalisation that can be replaced by simple functions and their prototypes.

I want to alt-tab, toggle fullscreen or change resolution mid-game so I want to call a function to do that, it should be simple. How my loop is built should be irrelevant. We can discuss later how we can optimize it.

This topic is closed to new replies.

Advertisement