   [MDX, C#] Handling DeviceLost
  I've discovered a problem with how my game handles lost devices. Originally, when a "DeviceLostException" occured, I'd simply reload all the graphics and the device, but this isn't working.I did some googling, but didn't find any tutorials that explained it in terms that I could understand.Anyone care to give me a run down on how to handle lost devices? [smile]   
  Hmm, do you handle both device lost and device reset?graphics = new Direct3D.Device(...)graphics.DeviceLost += new EventHandler(this.InvalidateObjects() );graphics.DeviceReset += new EventHandler(this.RestoreDeviceObjects() );Hope this helps.   ;  Handling a lost device is a pretty straight forward process, but can get complex the more the application gets.When the device is lost, all Default pool resources are lost with it. This includes VBs, IBs, Textures, Effects, etc. In addition, all set renderstates are lost.Now, you'll need to Reset() the device to get it working again (theres no need to recreate it completely). You also don't need to recreate anything in the Managed pool, those just keep working like before.The problem is, before you can Reset the device, you need to Release() anything created in the default pool. Only when all those resources have been released, will the Reset work. Once you've done that, you'll need to recreate all the resources you just released.After you do that, you only need to set all the renderstates you need to the correct values, and you should be good to start the next frame. I think that's about it :)MDX makes this extra easy with event handlers, so I'd recommend you at least start with using those.Hope this helps.   ;  I'm still not following. Here is some code I hacked togethor to see if you could pinpoint what I'm not doing (Its from my MapEditor).    public void sOnDeviceLost(object sender, EventArgs e)    {   /* Free up everything. */   MySprite.Dispose();   MyFont.Dispose();   MyTileTex.Dispose();   try   {  MyDevice.Reset(MyPresentation);   }   catch (Exception)   {  System.Threading.Thread.Sleep(50);   }    }    public void sOnDeviceReset(object sender, EventArgs e)    {   /* Start the sprite. */   MySprite = new Sprite(MyDevice);   /* Configure the font. */   MyFont = new Microsoft.DirectX.Direct3D.Font(MyDevice, -9, 4, FontWeight.Normal, 1, false, CharacterSet.Default, Precision.Default,  FontQuality.NonAntiAliased,  PitchAndFamily.DefaultPitch | PitchAndFamily.FamilyDoNotCare, "Small Fonts");   //Register our event handlers for Lost Devices   MyDevice.DeviceLost += new EventHandler(sOnDeviceLost);   MyDevice.DeviceReset += new EventHandler(sOnDeviceReset);   /* Load in all the textures that we need. */   MyTileTex = TextureLoader.FromFile(MyDevice, "Data\\Tiles.png");    }I get a stackoverflow in my sOnDeviceLost() procedure. [depressed]   ;  The error (And another theory of mine on how to solve the problem).;  Heres some MDX2 code I whipped up, should make it a bit clearer:*note the use of a while loop, to avoid the stack overflow if there's a long time until you can reset*  while (!m_Device.CheckCooperativeLevel()) System.Threading.Thread.Sleep(50);  try  { m_Device.Reset();  }  catch  {  }This doesn't have any error checking or anything, but should give you the basic idea.Hope this helps :).   ;    public void sOnDeviceLost(object sender, EventArgs e)    {   MyFont.Dispose();   MySprite.Dispose();   MyTileTex.Dispose();   while (!MyDevice.CheckCooperativeLevel())  System.Threading.Thread.Sleep(50);   try   {  MyDevice.Reset(MyPresentation);   }   catch   {   }    }It never succeeds in resetting the device; it stays in the infinite loop. =/   ;  You may not be able to reset devices all the time; you're supposed to test once a frame, and if you can't reset it, ignore that frame and go back to processing events. You can test whether the device is lost by calling TestCooperativeLevel().However, there allegedly exist some drivers which don't do Reset very well. To work around those drivers, you're supposed to totally close the device, and re-create a new device instead. Given that you may need that work-around, you could just ignore reset entirely, and tear down and re-create the device when you lose it.It's actually quite easy to re-create a device if you structure your asset management correctly. For each asset (animation, mesh, texture, etc) you want to deal with in your program, you have to create a wrapper class over the D3D object. The wrapper class should know how to "fill" the asset (i e, load texture from disk, or whatnot). You then use a wrapper around Device, on which you create these wrapper assets. When the device wrapper creates a new device instance, it just loops over all the asset wrappers and calls Load() on them. In fact, you don't need any other mechanism for loading asset data; regular asset loading should go through the same path as well.Doing it this way also allows you to switch to REF in the middle of a game, or switch between antialiased/non-anti-aliased back buffers, etc.;Quote:Original post by hplus0603You may not be able to reset devices all the time; you're supposed to test once a frame, and if you can't reset it, ignore that frame and go back to processing events. You can test whether the device is lost by calling TestCooperativeLevel().However, there allegedly exist some drivers which don't do Reset very well. To work around those drivers, you're supposed to totally close the device, and re-create a new device instead. Given that you may need that work-around, you could just ignore reset entirely, and tear down and re-create the device when you lose it.It's actually quite easy to re-create a device if you structure your asset management correctly. For each asset (animation, mesh, texture, etc) you want to deal with in your program, you have to create a wrapper class over the D3D object. The wrapper class should know how to "fill" the asset (i e, load texture from disk, or whatnot). You then use a wrapper around Device, on which you create these wrapper assets. When the device wrapper creates a new device instance, it just loops over all the asset wrappers and calls Load() on them. In fact, you don't need any other mechanism for loading asset data; regular asset loading should go through the same path as well.Doing it this way also allows you to switch to REF in the middle of a game, or switch between antialiased/non-anti-aliased back buffers, etc.The wrapper sounds like a great idea, but first I need to understand why I can't get this thing to stop throwing errors at me... [bawling]I'm using a Texture, a Sprite (C# version of D3DSprite), a font, and a device. How can I make it so that losing my device doesn't screw this up?Here is my DirectX class.using System;using System.Drawing;using System.Windows.Forms;using Microsoft.DirectX;using Microsoft.DirectX.Direct3D;public class cDirectXWrap{    private AdapterInformation MyAdapter = Manager.Adapters.Default;    private PresentParameters MyPresentation = new PresentParameters();    private Caps MyCapatibilties = Manager.GetDeviceCaps(0, DeviceType.Hardware);    Control MyRenderWindow = null;    public Device MyDevice = null;    public Sprite MySprite = null;    /* This texture holds the bitmap containing all tiles in Fleurin. */    public Texture MyTileTex = null;    /* This texture holds the minimap of Fleurin. */    public Texture[] MyMinimap =  new Texture[4];    /* This font is the primary font of all Fleurin. */    public Microsoft.DirectX.Direct3D.Font MyFont = null;    /* When instantiated, create the device. */    public cDirectXWrap(Control MyRenderWindow)    {   /* Congifure the presentation settings. */   this.MyRenderWindow = MyRenderWindow;   MyPresentation.BackBufferFormat = MyAdapter.CurrentDisplayMode.Format;   MyPresentation.BackBufferWidth = MyRenderWindow.ClientSize.Width;   MyPresentation.BackBufferHeight = MyRenderWindow.ClientSize.Height;   MyPresentation.SwapEffect = SwapEffect.Flip;   MyPresentation.Windowed = true;   //MyPresentation.PresentationInterval = PresentInterval.Immediate;   /* Create the devices and surfaces. */   sInitializeDirectX();    }    /* This procedure builds all the surfaces and devices needed. And is also  recalled in the case of a device being lost. */    public void sInitializeDirectX()    {   /* Setup the render device. */   MyDevice = new Device(MyAdapter.Adapter,   DeviceType.Hardware, MyRenderWindow,   CreateFlags.HardwareVertexProcessing,   MyPresentation);   /* Start the sprite. */   MySprite = new Sprite(MyDevice);   /* Configure the font. */   MyFont = new Microsoft.DirectX.Direct3D.Font(MyDevice, -9, 4, FontWeight.Normal, 1, false, CharacterSet.Default, Precision.Default,  FontQuality.NonAntiAliased,  PitchAndFamily.DefaultPitch | PitchAndFamily.FamilyDoNotCare, "Small Fonts");   /* Load in all the textures that we need. */   MyTileTex = TextureLoader.FromFile(MyDevice, "Data\\Tiles.png");    }    /* This procedure prepares the device for drawing. */    public void sPrepareDraw()    {   MyDevice.Clear(ClearFlags.Target, Color.Navy, 0.0f, 0);   MyDevice.BeginScene();   MySprite.Begin(SpriteFlags.AlphaBlend);   MyDevice.SamplerState[0].MagFilter = TextureFilter.Point;   MyDevice.SamplerState[0].MinFilter = TextureFilter.Point;   MyDevice.SamplerState[0].MipFilter = TextureFilter.Point;    }    /* This procedure ends the device from drawing. */    public void sEndDraw()    {   MySprite.End();   MyDevice.EndScene();   MyDevice.Present();    }};  Oh, doh, I should have remembered this sooner.Both the sprite and font interfaces have a OnLostDevice, and OnResetDevice method. You need to call those when the device is lost and after you reset the device. These tell the interfaces to release (the first call) and recreate (the second one) their internal resources.Try using those instead of disposing of both the font and sprite. Should've thought of that sooner :(.   