Jump to content
  • Advertisement
Sign in to follow this  
Zerd

Yet another device lost problem

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

Hi there, I have trouble to get the device back after i've lost it. Here is my method which should take care of this problem:
bool Device3D::RestoreDeviceIfLost()
{
    HRESULT hr;
    if(FAILED(hr=D3DDevice->TestCooperativeLevel()))
    {
		if(hr==D3DERR_DEVICELOST) 
		{
			if(logger)
				logger->info("lost device");
			return false;
		}

		// Device is back, and needs a reset.
		if(hr==D3DERR_DEVICENOTRESET)
		{
			if(logger)
				logger->info("reset required");
			
			// Release all resources
			ReleaseDynResources();
			
			// Reset the device
			if(FAILED(hr=D3DDevice->Reset(&present_params))) {
				if(logger)
					logger->info("Device could not be reseted");
				return false;
			}
			
			// Recreate resources
			RecreateDynResources();

		}

		// Test if it works now...
		if(FAILED(hr=D3DDevice->TestCooperativeLevel())) 
		{
			if(logger)
				logger->info("Reset path failed");
			return false;
		}
		
		if(logger)
			logger->info("Reset path succeeded");
	}

	// Everything OK
	return true;
}
Is there anything wrong with this method? The release and recreate functions basicly release or recreate all vertex and indexbuffers and the textures. After I tried this I got such a logfile:
Quote:
INFO: reset required INFO: Device could not be reseted INFO: reset required INFO: Device could not be reseted INFO: reset required INFO: Device could not be reseted INFO: reset required INFO: Device could not be reseted INFO: reset required INFO: Device could not be reseted ...
So the device could not be reseted, but I have no clue why this could happen... Anyone have an idea? Greetings Zerd

Share this post


Link to post
Share on other sites
Advertisement
I just helped a friend debug his engine (he had the same problem at you).
From what MSDN says about lost devices, I get it that you have to Release() and recreate all resources which are allocated in video memory (D3DPOOL_DEFAULT) before Reset()-ing the device, otherwise the Reset() fails.

My friend problem was that he created everything in D3DPOOL_MANAGED but Reset() still failed and after some digging in his code, we found out that if you use D3DXFont you must also destroy and recreate it (because internally it allocates some resources in video memory).

Hope this helps.

Edit:
you must also run the TestCooperativeLevel in a loop. My friend does this:

hr = device->Present(...);
if(hr == D3DERR_DEVICELOST)
{
do {
hr = device->TestCooperativeLevel();
if(hr == D3DERR_DEVICENOTRESET)
{
FreeResources(); device->Reset(); RestoreResources();
}
WindowsMessagePump();
} while (hr != D3DERR_OK);
}


Share this post


Link to post
Share on other sites
Check the return code of reset, it might give a hint.

Additionally switch to the directx debug libs, turn debug output to the max and look in the output window. It should tell you exactly what's wrong.

Share this post


Link to post
Share on other sites
First,

This should be posted in the DirectX Forum.

Quote:
Original post by cobru
you have to Release() and recreate all resources which are allocated in video memory (D3DPOOL_DEFAULT) before Reset()-ing the device, otherwise the Reset() fails.


This is not true. You should recreate your resources (in the default pool after you reset your device) as you are doing. Textures and the buffers created in a managed/sysmem/or dynamic pool do not need to be released and recreated on a lost device.

Quote:
Original post by cobru we found out that if you use D3DXFont you must also destroy and recreate it (because internally it allocates some resources in video memory).


This is very true. And if you use an ID3DXSprite to speed up font rendering then you must release that. Though, for the font and sprite you call onlostdevice and onresetdevice

I would not call TestCooperativeLevel in a loop as suggested above. And definitely don't test for equality with D3DERR_OK. Your method looks fine. As long as it is in a function that is getting called each frame or so then you should be able to recover from it eventually.

Quote:
The release and recreate functions basicly release or recreate all vertex and indexbuffers and the textures.


You should also release the active swapchain, backbuffer and depthstencil before resetting and then recreate them after the device is restored.

You should also be doing what Endurion suggests. You can load the DX debug symbols, use the debug library (via DX control panel) and set the output to max and watch. You will get some help with that.

Hope tihs helps.

Share this post


Link to post
Share on other sites
Quote:
Original post by DeafManNoEars
Quote:
Original post by cobru
you have to Release() and recreate all resources which are allocated in video memory (D3DPOOL_DEFAULT) before Reset()-ing the device, otherwise the Reset() fails.


This is not true. You should recreate your resources (in the default pool after you reset your device) as you are doing. Textures and the buffers created in a managed/sysmem/or dynamic pool do not need to be released and recreated on a lost device.


sorry, I was in a hurry.. I meant detroy before reset and create after reset.

Thanks for clearing that up.
Edit:

As for calling testCoopLevel in a loop: you can do without that, if you call it (as DeafManNoEars suggests) each frame. But, for the example I gave: basically, on lost device, the engine stops doing rendering and everything else (no world update, no nothing) and just waits for the device to be available again (hence: just pause everything else, do windows message processing and wait for the device to be available by calling TestCooperativeLevel).

The advantage (from my point of view) of this approach is that in case of lost device the game effectively pauses (so you don't get surprises like you're about to shoot some monster, some popup windows makes the game loose the device and when you alt+tab you're dead), but this is a matter of personal taste I think.

Share this post


Link to post
Share on other sites
Quote:
Original post by cobru
The advantage (from my point of view) of this approach is that in case of lost device the game effectively pauses (so you don't get surprises like you're about to shoot some monster, some popup windows makes the game loose the device and when you alt+tab you're dead), but this is a matter of personal taste I think.


Not a bad idea. I typically have a flag that lets me know when my device is lost so that I don't update or render. However this even requires an equality test every frame to determine if it is OK to render or update. So even if my device is not lost, I am still taking some performance penalty (albeit most likely unnoticeable). I may consider implementing your method and checking it out. Wouldn't want any suprises like you pointed out above.

Thanks for opening my eyes.
DeafManHasEyesNow.

Share this post


Link to post
Share on other sites
Hi,
thanks for all your help and sorry for posting in the wrong forum.

After I released the backbuffer and depthstencil it works now.

Share this post


Link to post
Share on other sites
What version of Direct3D is that? If it's D3D8 or D3D9, is there a reason you don't let the device create the backbuffer and depth-stencil buffer itself, by setting the appropriate fields of your D3DPRESENT_PARAMETERS structure?

Share this post


Link to post
Share on other sites
I'm using D3D9. You are right, it's not nessecary to create the backbuffer by myself... I think I will change this...



[Edited by - Zerd on February 1, 2007 4:14:38 AM]

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.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!