So today I have found a bug in my game where if I minimized the game window, all the of my textures that use RenderTarget2D disappear. So naturally I went and googled the problem and I found this very interesting post on Stackoverflow that talks about this issue. If your an XNA/MonoGame game developer I encourage you to read it.

 

So why was I using RenderTarget2D and how did i fix this issue?

 

Well right now I have a 100×100 tile map that get drawn every single frame. That is 10,000 tiles or textures that should be drawn every single frame. Even with my 3930K clocked at 4.5Ghz and my AMD 7970 I was barely getting 60FPS !! Now if you have read my post about How to overcome the performance issues in a tile based engine? you would know that drawing more than 200-400 objects (Textures – 3D object etc…) is very bad thing to do. Both AMD and Nvidia recommends to not have more than 600 draw calls. Imagine 10,000 draw calls !! So I found a solution to draw all 10,000 tiles and get more than 1600FPS !! How? using RenderTarget2D.

So basically what I did was, I have drawn all 10,000 tiles once to a RenderTarget2D and then I saved the RenderTarget2D to a Texture2D. This way instead of drawing 10,000 tiles I could just draw one big texture. Here is a snippet of my code.

 

void ConvertMapToTexture2D(SpriteBatch spriteBatch, Vector2 MapOffset)
{
renderTarget = new RenderTarget2D(Graphics.GraphicsDevice, (int)MaxTextureSize, (int)MaxTextureSize);

Graphics.GraphicsDevice.SetRenderTarget(renderTarget);

Graphics.GraphicsDevice.Clear(Color.White * 0f);

DrawTiles(spriteBatch, MapOffset);

Graphics.GraphicsDevice.SetRenderTarget(null);

MapTexture = renderTarget;
}

 

Now if you went and read the post at Stackoverflow you would know that when using RenderTarget2D all the textures get saved on the GPU Vram and when you minimize your XNA game window you will receive a “Device Lost” error. This means all the data on the GPU Vram will be lost. That includes the RenderTarget2D and Texture2D. However when you load a texture from the Content Pipeline or by using Texture2D.FromStream(), the CPU will have a copy of that texture in the RAM just in-case all the data on the GPU Vram get erased.

So How to solve this issue? Well in the post at Stackoverflow there were few solution. One of them said to use Texture2D.Setdata() and Texture2D.GetData(). and this was a great solution. Because this way even if you minimize the game window and all your data in the GPU Vram get lost, you will still have a copy of that texture and you can then redraw it again.

 

void ConvertMapToTexture2D(SpriteBatch spriteBatch, Vector2 MapOffset)
{
renderTarget = new RenderTarget2D(Graphics.GraphicsDevice, (int)MaxTextureSize, (int)MaxTextureSize);

Graphics.GraphicsDevice.SetRenderTarget(renderTarget);

Graphics.GraphicsDevice.Clear(Color.White * 0f);

DrawTiles(spriteBatch, MapOffset);

Graphics.GraphicsDevice.SetRenderTarget(null);

Color[] data = new Color[renderTarget.Width * renderTarget.Height];

renderTarget.GetData<Color>(data);

MapTexture = new Texture2D(Graphics.GraphicsDevice, (int)MaxTextureSize, (int)MaxTextureSize);

MapTexture.SetData<Color>(data);
}

 

I hope that helped 🙂