Jump to content
  • Advertisement
Sign in to follow this  
Tispe

Where to ResetDevice on WM_ACTIVATEAPP

This topic is 2634 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

Hello

My WindowProc function does not have access to my DX device class since I can't pass it through the arguments. I could make a global variable but I would rather not.

Can I do this instead before translating and dispatching the message?


while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if(msg.message == WM_QUIT)
return FALSE;

if(msg.message == WM_ACTIVATEAPP){
if(msg.wParam)
GraphicsDevice.ResetDevice();
}

TranslateMessage(&msg);
DispatchMessage(&msg);
}



Two more questions :)

1, Should I use "if" or "while" on PeekMessage?
2, Should I pass my device by reference or by pointer? Whats the differance and is it a "big deal"?

GraphicsDevice->ResetDevice();

Share this post


Link to post
Share on other sites
Advertisement
Don't handle a lost device in your window procedure - it will only end in tears.

http://msdn.microsof...v=vs.85%29.aspx

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 addition, any failure from IDirect3DDevice9::Reset puts the device into a lost state.[/quote]

So now that we know that Alt-Tabbing is far from the only event that can cause a lost device/reset scenario, where is the best place to reset it? The link I gave supplies the answer:

In this situation, the error code D3DERR_DEVICELOST is returned by IDirect3DDevice9::Present.[/quote]

So, you check the HRESULT from your Present call, and if you get D3DERR_DEVICELOST, that's the time and place to respond to a lost device.

Typically you'd go into a loop. During each iteration of the loop you call IDirect3DDevice9::TestCooperativeLevel; this will tell you what to do next.

If you get D3DERR_DEVICELOST your device is still lost, so Sleep for a few milliseconds to be kind to your CPU (your user may have Alt-Tabbed from the program to do something else, after all) then go round again.

If you get D3DERR_DEVICENOTRESET you Release all of your unmanaged resources and call Reset. Then just go round the loop again (you might want to Sleep a bit here too).

If you get D3D_OK then the reset has completed so recreate all of your unmanaged resources and exit the loop.

If you get D3DERR_DRIVERINTERNALERROR something bad has happened and the safest behaviour is probably to terminate the program.

If you're using any D3DX interfaces that implement OnLostDevice and OnResetDevice, be sure to call OnLostDevice before resetting in your D3DERR_DEVICENOTRESET condition and OnResetDevice in your D3D_OK condition.

You may also want to run your standard message pump for each iteration through the loop.

Now you've got code that can handle Alt-Tabbing as well as all of the other events that can cause a lost device, as well as terminal errors, all in the one place.

Share this post


Link to post
Share on other sites
Thx for the input.

I am concerned that for functions using the same thread would get blocked. Functions such as logic, network etc. Would it be a bad idea to continue with the main loop instead of getting caught in a loop checking TestCooperativeLevel()? And just TestCooperativeLevel() each frame (frames not actually beeing drawn as the app is minimized).

Also, my two last questions if you can adress them too ;)

Share this post


Link to post
Share on other sites
I am concerned that for functions using the same thread would get blocked. Functions such as logic, network etc. Would it be a bad idea to continue with the main loop instead of getting caught in a loop checking TestCooperativeLevel()? And just TestCooperativeLevel() each frame (frames not actually beeing drawn as the app is minimized)


That's also a valid option; it depends on the requirements of your program. For a game I think it's good form to block sound/logic/etc if you switch away as otherwise you might find yourself having been killed while your were IMing someone, but it really would vary from program to program.

For the PeekMessage question, I've seen loads of message loops written in different ways. Some use if, some while, some if inside an infinite loop, some put the rendering/etc outside of a PeekMessage loop, some put it after each PeekMessage call. I don't believe that there is a single answer that is correct in all circumstances, but I do rather like the example given here: http://www.mvps.org/DirectX/articles/writing_the_game_loop.htm

Your second question is rather obsoleted by not responding to the lost device in your window procedure isn't it? Personally I don't get too hung up on correctness of design (and I'm an old fogey from the days of pure C so I occasionally fail to see why these things are so important); a wise man once said that "the purpose of software is to be useful" and I think that's a good principle.

Share this post


Link to post
Share on other sites
You might want not to use a loop when your device gets lost. You still should run through the main loop to keep processing messages.

If TestCooperativeLevel returns a lost state, simply skip the Direct3d stuff for the current frame.

Share this post


Link to post
Share on other sites

You might want not to use a loop when your device gets lost. You still should run through the main loop to keep processing messages.

If TestCooperativeLevel returns a lost state, simply skip the Direct3d stuff for the current frame.


I took out the loop. I added a bool LostDevice in my device class and added a RecoverDevice function which will run instead of rendering if bool is true. Present() will toggle the bool if it returns D3DERR_DEVICELOST. The RecoverDevice function is dong the TestCooperativeLevel() routine. Now however the v_synch is no longer "pausing" the game between frames and the app takes up 100% of the CPU core the thread is on. I added a Sleep(0) to the Recover routine but the app is still consuming 100% of the core the thread is on (but do yields the CPU to other threads). Sleep(1) puts it down to 0%. Should I stick with Sleep(0) or do Sleep(1) or something else?


void DEVICEOBJECT::RecoverDevice()
{
HRESULT hr = NULL;

hr = d3ddev->TestCooperativeLevel();
switch (hr)
{
case D3D_OK:
LostDevice = false;
return;
case D3DERR_DEVICELOST:
Sleep(0);
break;
case D3DERR_DEVICENOTRESET:
ResetDevice();
break;
default:
MessageBox(NULL, L"TestCooperativeLevel() failed", L"Error", MB_OK);
PostQuitMessage(0);
return;
}
}

Share this post


Link to post
Share on other sites
Sleep (1) is fine and your implementation looks good.

Personally I don't believe there is any one true way of handling this correctly. I suggested a loop because it will pause game logic while switched away (I did also suggest running your standard PeekMessage loop inside it) and this approach works well for my use cases, but other approaches are also valid.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!