Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Add PSSuite specific SpriteBatcher that does one VertexBuffer upload …

…per render for much better performance.
  • Loading branch information...
commit 9c0cf3967c651067ca5231f30c59e9c65986415b 1 parent 3abecf2
Dave Leaver danzel authored
4 MonoGame.Framework/MonoGame.Framework.PSSuite.csproj
@@ -305,7 +305,7 @@
305 305 <Compile Include="Graphics\Effect\EffectAnnotationCollection.cs" />
306 306 <Compile Include="Graphics\Effect\EffectAnnotation.cs" />
307 307 <Compile Include="Graphics\Vertices\VertexDeclaration.cs" />
308   - <Compile Include="Graphics\Vertices\VertexDeclarationCache.cs" />
  308 + <Compile Include="Graphics\Vertices\VertexDeclarationCache.cs" />
309 309 <Compile Include="Graphics\RenderTarget2D.cs" />
310 310 <Compile Include="Audio\AudioCategory.cs" />
311 311 <Compile Include="Graphics\SpriteBatch.cs" />
@@ -318,7 +318,6 @@
318 318 <Compile Include="GameWindow.cs" />
319 319 <Compile Include="GraphicsDeviceManager.cs" />
320 320 <Compile Include="Graphics\PresentInterval.cs" />
321   - <Compile Include="Graphics\SpriteBatcher.cs" />
322 321 <Compile Include="Graphics\CubeMapFace.cs" />
323 322 <Compile Include="Storage\StorageDeviceHelper.cs" />
324 323 <Compile Include="Content\ContentReaders\BasicEffectReader.cs" />
@@ -344,6 +343,7 @@
344 343 <Compile Include="PSSuite\PSSHelper.cs" />
345 344 <Compile Include="PSSuite\PSSExtensions.cs" />
346 345 <Compile Include="Graphics\Effect\ConstantBuffer.cs" />
  346 + <Compile Include="PSSuite\Graphics\SpriteBatcher.cs" />
347 347 </ItemGroup>
348 348 <ItemGroup>
349 349 <Folder Include="PSSuite\" />
230 MonoGame.Framework/PSSuite/Graphics/SpriteBatcher.cs
... ... @@ -0,0 +1,230 @@
  1 +// #region License
  2 +// /*
  3 +// Microsoft Public License (Ms-PL)
  4 +// MonoGame - Copyright © 2009 The MonoGame Team
  5 +//
  6 +// All rights reserved.
  7 +//
  8 +// This license governs use of the accompanying software. If you use the software, you accept this license. If you do not
  9 +// accept the license, do not use the software.
  10 +//
  11 +// 1. Definitions
  12 +// The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under
  13 +// U.S. copyright law.
  14 +//
  15 +// A "contribution" is the original software, or any additions or changes to the software.
  16 +// A "contributor" is any person that distributes its contribution under this license.
  17 +// "Licensed patents" are a contributor's patent claims that read directly on its contribution.
  18 +//
  19 +// 2. Grant of Rights
  20 +// (A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3,
  21 +// each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create.
  22 +// (B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3,
  23 +// each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software.
  24 +//
  25 +// 3. Conditions and Limitations
  26 +// (A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks.
  27 +// (B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software,
  28 +// your patent license from such contributor to the software ends automatically.
  29 +// (C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution
  30 +// notices that are present in the software.
  31 +// (D) If you distribute any portion of the software in source code form, you may do so only under this license by including
  32 +// a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object
  33 +// code form, you may only do so under a license that complies with this license.
  34 +// (E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees
  35 +// or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent
  36 +// permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular
  37 +// purpose and non-infringement.
  38 +// */
  39 +// #endregion License
  40 +//
  41 +using System;
  42 +using System.Runtime.InteropServices;
  43 +using System.Collections.Generic;
  44 +using System.Text;
  45 +using Microsoft.Xna.Framework;
  46 +
  47 +using Sce.Pss.Core.Graphics;
  48 +using PssVertexBuffer = Sce.Pss.Core.Graphics.VertexBuffer;
  49 +
  50 +namespace Microsoft.Xna.Framework.Graphics
  51 +{
  52 + internal class SpriteBatcher
  53 + {
  54 + private const int InitialBatchSize = 256;
  55 + private const int InitialVertexArraySize = 256;
  56 + List<SpriteBatchItem> _batchItemList;
  57 + Queue<SpriteBatchItem> _freeBatchItemQueue;
  58 +
  59 + GraphicsDevice _device;
  60 +
  61 + ushort[] _index;
  62 + PssVertexBuffer _vertexBuffer;
  63 + VertexPosition2ColorTexture[] _vertexArray;
  64 +
  65 + public SpriteBatcher (GraphicsDevice device)
  66 + {
  67 + _device = device;
  68 +
  69 + _batchItemList = new List<SpriteBatchItem>(InitialBatchSize);
  70 + _freeBatchItemQueue = new Queue<SpriteBatchItem>(InitialBatchSize);
  71 +
  72 + _index = new ushort[6 * InitialVertexArraySize];
  73 + for (int i = 0; i < InitialVertexArraySize; i++)
  74 + {
  75 + _index[i * 6 + 0] = (ushort)(i * 4);
  76 + _index[i * 6 + 1] = (ushort)(i * 4 + 1);
  77 + _index[i * 6 + 2] = (ushort)(i * 4 + 2);
  78 + _index[i * 6 + 3] = (ushort)(i * 4 + 1);
  79 + _index[i * 6 + 4] = (ushort)(i * 4 + 3);
  80 + _index[i * 6 + 5] = (ushort)(i * 4 + 2);
  81 + }
  82 +
  83 + _vertexArray = new VertexPosition2ColorTexture[4 * InitialVertexArraySize];
  84 + _vertexBuffer = new PssVertexBuffer(4 * InitialVertexArraySize, 6 * InitialVertexArraySize, VertexFormat.Float2, VertexFormat.UByte4N, VertexFormat.Float2);
  85 + _vertexBuffer.SetIndices(_index, 0, 0, 6 * InitialVertexArraySize);
  86 + }
  87 +
  88 + public SpriteBatchItem CreateBatchItem()
  89 + {
  90 + SpriteBatchItem item;
  91 + if ( _freeBatchItemQueue.Count > 0 )
  92 + item = _freeBatchItemQueue.Dequeue();
  93 + else
  94 + item = new SpriteBatchItem();
  95 + _batchItemList.Add(item);
  96 + return item;
  97 + }
  98 +
  99 + int CompareTexture ( SpriteBatchItem a, SpriteBatchItem b )
  100 + {
  101 + return ReferenceEquals( a.Texture, b.Texture ) ? 0 : 1;
  102 + }
  103 +
  104 + int CompareDepth ( SpriteBatchItem a, SpriteBatchItem b )
  105 + {
  106 + return a.Depth.CompareTo(b.Depth);
  107 + }
  108 +
  109 + int CompareReverseDepth ( SpriteBatchItem a, SpriteBatchItem b )
  110 + {
  111 + return b.Depth.CompareTo(a.Depth);
  112 + }
  113 +
  114 + public void DrawBatch ( SpriteSortMode sortMode, SamplerState samplerState)
  115 + {
  116 + // nothing to do
  117 + if ( _batchItemList.Count == 0 )
  118 + return;
  119 + // sort the batch items
  120 + switch ( sortMode )
  121 + {
  122 + case SpriteSortMode.Texture :
  123 + _batchItemList.Sort( CompareTexture );
  124 + break;
  125 + case SpriteSortMode.FrontToBack :
  126 + _batchItemList.Sort ( CompareDepth );
  127 + break;
  128 + case SpriteSortMode.BackToFront :
  129 + _batchItemList.Sort ( CompareReverseDepth );
  130 + break;
  131 + }
  132 +
  133 + // setup the vertexArray array
  134 + int startIndex = 0;
  135 + int index = 0;
  136 + Texture2D tex = null;
  137 +
  138 + // make sure the vertexArray has enough space
  139 + if ( _batchItemList.Count*4 > _vertexArray.Length )
  140 + ExpandVertexArray( _batchItemList.Count );
  141 +
  142 + _device._graphics.SetVertexBuffer(0, _vertexBuffer);
  143 +
  144 + //Populate the vertexArray
  145 + for (int i = 0; i < _batchItemList.Count; i++)
  146 + {
  147 + var item = _batchItemList[i];
  148 +
  149 + // store the SpriteBatchItem data in our vertexArray
  150 + _vertexArray[index++] = item.vertexTL;
  151 + _vertexArray[index++] = item.vertexTR;
  152 + _vertexArray[index++] = item.vertexBL;
  153 + _vertexArray[index++] = item.vertexBR;
  154 +
  155 + _freeBatchItemQueue.Enqueue ( item );
  156 + }
  157 +
  158 + FlushVertexArray(index);
  159 + startIndex = index = 0;
  160 +
  161 + //Draw each batch in the sprite batch (based on texture changes)
  162 + for (int i = 0; i < _batchItemList.Count; i++)
  163 + {
  164 + var item = _batchItemList[i];
  165 + // if the texture changed, we need to draw and bind the new texture
  166 + bool shouldFlush = item.Texture != tex;
  167 + if ( shouldFlush )
  168 + {
  169 + DrawVertexArray( startIndex, index );
  170 + startIndex = index;
  171 + tex = item.Texture;
  172 +
  173 + _device._graphics.SetTexture(0, tex._texture2D);
  174 + }
  175 + index += 4;
  176 + }
  177 +
  178 + // flush the remaining vertexArray data
  179 + DrawVertexArray(startIndex, index);
  180 +
  181 + _batchItemList.Clear();
  182 + }
  183 +
  184 + void ExpandVertexArray( int batchSize )
  185 + {
  186 + // increase the size of the vertexArray
  187 + var newCount = _vertexArray.Length / 4;
  188 +
  189 + while ( batchSize*4 > newCount )
  190 + newCount += 128;
  191 +
  192 + _index = new ushort[6 * newCount];
  193 + for (int i = 0; i < newCount; i++)
  194 + {
  195 + _index[i * 6 + 0] = (ushort)(i * 4);
  196 + _index[i * 6 + 1] = (ushort)(i * 4 + 1);
  197 + _index[i * 6 + 2] = (ushort)(i * 4 + 2);
  198 + _index[i * 6 + 3] = (ushort)(i * 4 + 1);
  199 + _index[i * 6 + 4] = (ushort)(i * 4 + 3);
  200 + _index[i * 6 + 5] = (ushort)(i * 4 + 2);
  201 + }
  202 +
  203 + _vertexBuffer.Dispose();
  204 + _vertexBuffer = new PssVertexBuffer(4 * newCount, 6 * newCount, VertexFormat.Float2, VertexFormat.UByte4N, VertexFormat.Float2);
  205 +
  206 + _vertexArray = new VertexPosition2ColorTexture[4 * newCount];
  207 + _vertexBuffer.SetIndices(_index, 0, 0, 6 * newCount);
  208 + }
  209 +
  210 + void FlushVertexArray(int count)
  211 + {
  212 + _vertexBuffer.SetVertices(_vertexArray, 0, 0, count);
  213 + }
  214 +
  215 + void DrawVertexArray ( int start, int end )
  216 + {
  217 + if ( start == end )
  218 + return;
  219 +
  220 + var vertexCount = end - start;
  221 +
  222 +#warning this should be applied somewhere else
  223 + _device._graphics.Enable(EnableMode.Blend);
  224 + _device._graphics.SetBlendFunc(BlendFuncMode.Add, BlendFuncFactor.SrcAlpha, BlendFuncFactor.OneMinusSrcAlpha);
  225 +
  226 + _device._graphics.DrawArrays(DrawMode.Triangles, start / 2 * 3, vertexCount / 2 * 3);
  227 + }
  228 + }
  229 +}
  230 +

0 comments on commit 9c0cf39

Please sign in to comment.
Something went wrong with that request. Please try again.