Page 1 of 1

how to recover from d3d device lost

Posted: Wed Feb 01, 2006 5:56 am
by vitek
When using render to texture, if the window is resized or whatever, a call to IDirect3DDevice9::Reset will not succeed until the render target texture is returned to the system.

I haven't really looked, but it appears that there is no notification being sent to anyone that the device was lost, so there is no way to know to release the render target. How are we supposed to know to release the render target texture?

I guess a simple way is to check the result of beginRender and assume failure means we need to deallocate the render target and try to re-create it again later? Or just unload the whole device and everything and try to start over...

Code: Select all

   // d3d8/9 drivers loop forever trying to reset device...
   irr::video::ITexture* rtt = driver->createRenderTargetTexture( irr::core::dimension2d<irr::s32>(512, 512) );
   while(Device->run() && Driver)
   {
      if (Device->isWindowActive())
      {
         driver->beginScene(true, true, video::SColor(255,50,50,50));

         driver->setRenderTarget(rtt, true, true, irr::video::SColor(120,50,50,50)); 
         smgr->drawAll();
         env ->drawAll();
         
         driver->setRenderTarget(0);
         smgr->drawAll();
         env ->drawAll();

         driver->endScene();

Posted: Fri Feb 17, 2006 7:50 am
by Xaron
I have the same problem but no solution yet...

Regards - Xaron

Posted: Sun Sep 03, 2006 3:09 pm
by Xaron
Any news regarding this problem?

I still don't have a solution yet. :(

Thanks and regards - Xaron

Posted: Wed Sep 06, 2006 7:11 pm
by Xaron
Hmm... This seems to be a difficult topic. ;)

Come on. Does noone use the fullscreen? Have you ever tried to press Alt-Tab? :lol:

Regards - Xaron

Posted: Wed Sep 06, 2006 9:04 pm
by vitek
Currently there is no system for you to be notified that the device is lost. There are several ways that you could solve the problem.

You could just extend the hack that is SEvent and add a device lost event type. Your event receiver could respond to that and forward the message on to other systems that might need to know about the problem. You would need to modify the D3D drivers to send this notification.

You could add an method to the IVideoDriver that allows you to set a callback or register a device lost listener. The derived drivers would use the callback or listener when the device was lost. This is basically the same as above, but doesn't require extending the SEvent type list and is also a more correct solution imo. Of course you still need to modify the drivers to send the notification.

Of course you could write something outside Irrlicht that would periodically check the driver state [which can be accessed via getExposedVideoData().D3D9.D3DDev9->TestCooperativeLevel() and send a notification when the device state changes.

Posted: Fri Sep 08, 2006 6:48 am
by Xaron
Thank you vitek! :) I think that should be integrated into Irrlicht, shouldn't it? ;)

Regards - Xaron

Posted: Fri Sep 08, 2006 7:37 am
by vitek
Something should probably be done. It would be nice if Irrlicht just provided a single hook to know when the device is lost and when it is reset. That single hook could be used by us to do cleanup and reinitialization as necessary.

Travis

Posted: Fri Sep 08, 2006 12:42 pm
by funcdoobiest
Sorry to go slightly off topic but I had a couple of related questions one of you maybe able to answer? I was just looking in to resetting the device the other day and was wondering just how I make sure all neccesary resources (as it says in the docs, below) have been released in Irrlicht?
release any explicit render targets, depth stencil surfaces, additional swap chains, state blocks, and D3DPOOL_DEFAULT resources associated with the device.
and also how I would go about doing it, I know I could use the exposed video data and do it directly throught the device? However, I was looking at the reset() functioned defined in the DX9 driver class and it resets some things in the engine which i guess i would want to do. Plus I don't really like using the exposed data unless I really have to.

I had considered making a public reset() which will take present parameters , do some checking that the rendertargets ahve been released and also reset the Irrlicht stuff. (I just wasnt to be able to change the depth of the various buffers at runtime)

I agree with you Vitek on the device lost issue, it seems there is never any explicit notification that the device has been lost just the possibilty depending on the value retruned by beginScene(), it would be nice to know!

Posted: Sun Sep 10, 2006 7:35 am
by Xaron
I think this is more an advanced topic and should be moved to the advanced forum?

@Devs: Any thoughts about that topic? How would you handle that? And could you please extend Irrlicht with that "feature"? ;)

Regards - Xaron

Posted: Sun Sep 10, 2006 9:12 am
by hybrid
Sorry, I don't know D3Dx that much, I cannot help here in any way. I couldn't even check a given patch. But if there's a working patch without side effects I guess this will make it into Irrlicht core.
So what is actually the problem--Irrlicht's ressource management or D3D's incorrect state changes?

Posted: Sun Sep 10, 2006 10:23 am
by vitek
When you create a resource that is not managed by the device, it must be destroyed and recreated when the D3D device is lost. Irrlicht provides no real notification that the device is lost. Irrlicht does return false from beginScene() when something is wrong, but there is no way to tell what the problem was without writing D3D specific code.

What is needed is some sort of way to tell that the device reset is about to happen and when it is over. When this the pre-reset happens some resources would need to be released. After the reset has completed, the resources would need to be reallocated.

Unfortunately this is specific to D3D. There is no problem if the window size is fixed and not full screen. Obviously this is a way to work around the issue, but it is not a great solution.

The below test case will cause problems on a windows machine when you alt-tab out of the application.

Code: Select all

#include <irrlicht.h> 
#pragma comment(lib, "Irrlicht.lib") 

using namespace irr; 

int main() 
{
   // problem occurs when using a resource that is not managed by the device
   // and the resource is not released when the device is lost or reset. the
   // device is reset when you alt-tab out of full screen mode or when the
   // window is resized.
   IrrlichtDevice *device = createDevice(video::EDT_DIRECT3D8, core::dimension2d<s32>(1024, 768), 16, true, false, false);
   if (device == 0) 
      return 1;

   // this is for the second issue mentioned below. change the createDevice
   // call above so that the window is not fullscreen and comment this in...
   //device->setResizeAble(true);

   video::IVideoDriver* driver = device->getVideoDriver(); 
   scene::ISceneManager* smgr = device->getSceneManager(); 

   driver->setAmbientLight(video::SColorf(.5f, .5f, .5f, 1.f)); 

   smgr->loadScene("../../media/example.irr");

   smgr->addCameraSceneNodeMaya();

   video::ITexture* rtt = 0;

   if (driver->queryFeature(video::EVDF_RENDER_TO_TARGET))
      rtt = driver->createRenderTargetTexture( core::dimension2d<s32>(256, 256) );

   while(device->run()) 
   {
      if (device->isWindowActive()) 
      {
         if (driver->beginScene(true, true, video::SColor(255, 32, 32, 32)))
         {
            smgr->drawAll(); 

            driver->endScene(); 
         }
      }
   }

   if (rtt)
      rtt->drop();

   device->drop();

   return 0; 
}
There is another small, but related bug in here. In CD3D?Driver::reset(), the DeviceLost flag should get set when the pID3DDevice->Reset() call fails with D3DERR_DEVICELOST. If this is not set, I get a crash after resizing the Irrlicht window with the above test case.

Posted: Sun Sep 10, 2006 10:25 am
by vitek
Pertinent documenation is available here.

Travis

Posted: Thu Sep 14, 2006 7:44 pm
by hybrid
I've added the reset handling fix to correctly update the DeviceLost variable. I'll consider the rest too much Win32 for me :wink:

Posted: Sun Sep 24, 2006 12:26 pm
by Pr3t3nd3r
True! this is the problem. And not even that. I think is causing random game freeze when the device is temporary lost. ( not necesarly alt+tab )

Let me understand.
Any one found any solution(hack) for this ? ? ?

Posted: Sat Jun 30, 2007 3:18 pm
by xDan
So is there a solution for this?

From what I read it seems I have to drop my render target textures *before* the game gets minimised? But I don't really understand how... It would seem when isWindowActive() returns false it is too late and the device thing has already been lost.

At the moment after alt+tabbing or minimising my game, restoring it causes a crash. I'm using Irrlicht 1.3. With direct3d8.

Note: I get errors in this order:
DIRECT3D8 device lost.
DIRECT3D8 end scene failed.

Help!