   XNA - SpriteBatch.Draw terribly slow *Fixed*
  I'm trying to draw a large tilemap of 1024 tiles (each tile being 32x33 pixel) for an editor. The editor is a Windows Form Application using the .Net Framework and C#. I initially tried this using GDI+ but any tilemaps bigger then 8x8 would take seconds to draw and just got worse with larger maps. So, after researching Graphics.DrawImage here I read a few suggestions for using XNA. I switched the drawing of the tiles to use XNA but I'm seeing very little improvements.Is this not the intended functionality of the XNA framework? I have done an editor years ago using bitblt with no trouble on large maps. I find it hard to believe that hardware accelerated drawing is slower then the deprecated Win32 GDI. The managed environment of C# is just wonderful to work with, but if need be I will bite the bullet and restart using MFC and DirectX.Below; the drawing code used to render the tilemap. Also, I'm using XNA 3.0 CTP.   private void DrawMap()   {  gfxDevice.Clear(Microsoft.Xna.Framework.Graphics.Color.Blue);  sprSprites.Begin(SpriteBlendMode.None, SpriteSortMode.Texture, SaveStateMode.SaveState);  //Draw each rect's data  Vector2 vec = new Vector2();  Microsoft.Xna.Framework.Rectangle sourceRect;  for (int i = 0; i < (nMapRows * nMapCollums); ++i)  { vec.X = (float)rectMap.X; vec.Y = (float)rectMap.Y; sourceRect.X = rectTileset[nMapData].X; sourceRect.Y = rectTileset[nMapData].Y; sourceRect.Width = rectTileset[nMapData].Width; sourceRect.Height = rectTileset[nMapData].Height; sprSprites.Draw(txtTileset, vec, sourceRect, Microsoft.Xna.Framework.Graphics.Color.White); //e.Graphics.DrawImage(imgTileset, rectMap.X - nScrollMapX, rectMap.Y - nScrollMapY, rectTileset[nMapData], GraphicsUnit.Pixel);  }  //Draw the grid over the map  //for (int i = 0; i < nMapCollums; ++i)  //    e.Graphics.DrawLine(Pens.Black, (i * nTileSize) - nScrollMapX, 0 - nScrollMapY, (i * nTileSize) - nScrollMapX, (nTileSize * nMapRows) - nScrollMapY);  //for (int i = 0; i < nMapRows; ++i)  //    e.Graphics.DrawLine(Pens.Black, 0 - nScrollMapX, (i * nTileSize) - nScrollMapY, (nTileSize * nMapCollums) - nScrollMapX, (i * nTileSize) - nScrollMapY);  sprSprites.End();  gfxDevice.Present();   }[Edited by - LaZZer on August 16, 2008 12:43:25 PM]
  Are you drawing the tiles that are outside of your current viewport? If so you might want to add some checks in that ensure that you only draw the tiles you are looking at, rather than the tiles that are outside of the viewable area.If I had more time I'd write up an example for you, I'll come back to this later.-SD   ;  I'm drawing all the tiles. Mainly because they are all visible. Even on a small tilemap that's 12x12 it's still horribly slow. I do plan on 'culling' the tiles that are offscreen, but until I can get the ones onscreen drawing at a respectable rate I'm not concerned with it. Thank you for the suggestion though.   ;  I don't see what might be wrong with the code. XNA should internally batch the draw calls to improve performance.Do you do anything else complex in the code you didn't post yet?   ;  Nothing at all complex. The form itself is still a skeleton with only a handful of controls. Here's the Init. Nothing major in here. Just setting up the GraphicsDevice and a few other variables. Only concern here is the calls to Setstyle but with or without them I see no difference. I'm not doing any GDI+ draw calls anyway.   public Form1()   {  InitializeComponent();  PresentationParameters pp = new PresentationParameters();  pp.IsFullScreen = false;  pp.SwapEffect = SwapEffect.Flip;  gfxDevice = new GraphicsDevice(GraphicsAdapter.DefaultAdapter, DeviceType.Reference, this.pnlMap.Handle, pp);  sprSprites = new SpriteBatch(gfxDevice);  //Variable init  bTilesetLoaded = false;  nScrollTilesetX = nScrollTilesetY = 0;  nTilesetRows = nTilesetCollums = 0;  nTileSize = 32; //Defualt tile size  nScrollMapX = nScrollMapY = 0;  nSelectedTile = 0;  //Other init  vscrollMap.Enabled = false; //Disable scroll bars until everything is loaded  hscrollMap.Enabled = false;  vscrollTileset.Enabled = false;  hscrollTileset.Enabled = false;  this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);  this.SetStyle(ControlStyles.UserPaint, true);  this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);   }I'm loading in the bitmap for the tiles in another function. Here I setup an array of Rectangles. Load in bitmap and that's about it.    private void OpenTileset()   {  //Open the file dialog to browse for a tileset  if (ofdOpen.ShowDialog(this) == DialogResult.OK)  { //imgTileset = Image.FromFile(ofdOpen.FileName);    //Open the file bTilesetLoaded = true;  //We now have a valid tileset //Setup the scroll bars hscrollTileset.Enabled = true; vscrollTileset.Enabled = true; nScrollTilesetX = nScrollTilesetY = 0; hscrollTileset.Minimum = (-1 * imgTileset.Width); hscrollTileset.Maximum = imgTileset.Width; vscrollTileset.Minimum = (-1 * imgTileset.Height); vscrollTileset.Maximum = imgTileset.Height; //Grab some information from the bitmap nTilesetRows = (int)(imgTileset.Height / nTileSize); nTilesetCollums = (int)(imgTileset.Width / nTileSize); //Setup the rects rectTileset = new System.Drawing.Rectangle[(nTilesetCollums * nTilesetRows)]; int count = 0; for (int i = 0; i < nTilesetCollums; ++i) {for (int j = 0; j < nTilesetRows; ++j)  //Setup the rect array{    rectTileset[count].X = (nTileSize * j);    rectTileset[count].Width = nTileSize;    rectTileset[count].Y = (nTileSize * i);    rectTileset[count].Height = nTileSize;    ++count;} } txtTileset = Texture2D.FromFile(gfxDevice, ofdOpen.FileName); //load the texture pnlTileset.Invalidate(); //Force a redraw of the tileset pnlMap.Invalidate();  //Force a redraw of the map  }   }I am using Windows Vista x86 and Visual Studio 2008. I don't see how that would affect me, but just trying to give as much information as possible.   ;gfxDevice = new GraphicsDevice(GraphicsAdapter.DefaultAdapter, DeviceType.Reference, this.pnlMap.Handle, pp);You're using the reference device, which will operate in software mode and only work on computers with the DX SDK installed. Set it to DeviceType.Hardwareregards   ;  Thank you FoxHunter2 that did the trick! Thats the kind of fix I like; a single parameter.   ;  changing SaveStateMode to None will also result in a large increase in FPS.   ;  Right, and here is the explanation why this is the case, it's worth reading.   