Hello. I was wondering if there were any optimization benefits with drawing textures with only calling spritebatch.Begin() and spritebatch.End() once, as opposed to calling .Begin() and .End() for each texture.
I understand there are limitations to using this approach, such as not being able to change the SpriteSortMode and BlendState, but I am not worried about that. I am only curious about whether or not designing a drawing system like this would have a significant affect on a game's performance.
An explanation regarding the "expense" of calling a spritebatch's .Begin() and .End() functions would be appreciated!
Thanks!
Any benefits to drawing textures in one spritebatch.Begin() & End() call?
Copy paste from http://gamedev.stackexchange.com/questions/21220/how-exactly-does-xnas-spritebatch-work:
I have sort of replicated the behaviour of SpriteBatch in deferred mode for a cross-platform engine I'm working on, so here are the steps I have reverse engineered so far:
SpriteBatch constructor: creates a DynamicIndexBuffer, DynamicVertexBuffer and array of VertexPositionColorTexture of fixed size (in this case, the maximum batch size - 2048 for sprites and 8192 for vertices).
The index buffer is filled with the vertex indices of the quads that will be drawn (0-1-2, 0-2-3, 4-5-6, 4-6-7 and so on).
An internal array of SpriteInfo structs is created, too. This will store temporal sprite settings to be used when batching.
SpriteBatch.Begin: internally stores the values of BlendState, SamplerState, etc. specified and checks if it has been called twice without a SpriteBatch.End in between.
SpriteBatch.Draw: takes all the sprite info (texture, position, color) and copies it to a SpriteInfo. If the max batch size is reached, the entire batch is drawn to make room for new sprites.
SpriteBatch.DrawString just issues a Draw for each character of the string, taking into account kerning and spacing.
SpriteBatch.End: does the following operations:
Sets the render states specified in Begin.
Creates the orthographic projection matrix.
Applies the SpriteBatch shader.
Binds the DynamicVertexBuffer and DynamicIndexBuffer.
Performs the following batching operation:
startingOffset = 0;
currentTexture, oldTexture = null;
// Iterate through all sprites
foreach SpriteInfo in SpriteBuffer
{
// Store sprite index and texture
spriteIndex = SpriteBuffer.IndexOf(SpriteInfo);
currentTexture = SpriteInfo.Texture;
// Issue draw call if batch count > 0 and there is a texture change
if (currentTexture != oldTexture)
{
if (spriteIndex > startingOffset)
{
RenderBatch(currentTexture, SpriteBuffer, startingOffset,
spriteIndex - startingOffset);
}
startingOffset = spriteIndex;
oldTexture = currentTexture;
}
}
// Draw remaining batch and clear the sprite data
RenderBatch(currentTexture, SpriteBuffer, startingOffset,
SpriteBuffer.Count - startingOffset);
SpriteBuffer.Clear();
SpriteBatch.RenderBatch: executes the following operations for each of the SpriteInfo in the batch:
Takes the position of the sprite and calculates the final position of the four vertices according to the origin and size. Applies existing rotation.
Calculates the UV coordinates and applies specified SpriteEffects to them.
Copies the sprite color.
These values are then stored in the array of VertexPositionColorTexture elements previously created. When all sprites have been calculated, SetData is called on the DynamicVertexBuffer and a DrawIndexedPrimitives call is issued.
The vertex shader only performs a tranform operation, and the pixel shader applies the tinting on the color fetched from the texture.
I have sort of replicated the behaviour of SpriteBatch in deferred mode for a cross-platform engine I'm working on, so here are the steps I have reverse engineered so far:
SpriteBatch constructor: creates a DynamicIndexBuffer, DynamicVertexBuffer and array of VertexPositionColorTexture of fixed size (in this case, the maximum batch size - 2048 for sprites and 8192 for vertices).
The index buffer is filled with the vertex indices of the quads that will be drawn (0-1-2, 0-2-3, 4-5-6, 4-6-7 and so on).
An internal array of SpriteInfo structs is created, too. This will store temporal sprite settings to be used when batching.
SpriteBatch.Begin: internally stores the values of BlendState, SamplerState, etc. specified and checks if it has been called twice without a SpriteBatch.End in between.
SpriteBatch.Draw: takes all the sprite info (texture, position, color) and copies it to a SpriteInfo. If the max batch size is reached, the entire batch is drawn to make room for new sprites.
SpriteBatch.DrawString just issues a Draw for each character of the string, taking into account kerning and spacing.
SpriteBatch.End: does the following operations:
Sets the render states specified in Begin.
Creates the orthographic projection matrix.
Applies the SpriteBatch shader.
Binds the DynamicVertexBuffer and DynamicIndexBuffer.
Performs the following batching operation:
startingOffset = 0;
currentTexture, oldTexture = null;
// Iterate through all sprites
foreach SpriteInfo in SpriteBuffer
{
// Store sprite index and texture
spriteIndex = SpriteBuffer.IndexOf(SpriteInfo);
currentTexture = SpriteInfo.Texture;
// Issue draw call if batch count > 0 and there is a texture change
if (currentTexture != oldTexture)
{
if (spriteIndex > startingOffset)
{
RenderBatch(currentTexture, SpriteBuffer, startingOffset,
spriteIndex - startingOffset);
}
startingOffset = spriteIndex;
oldTexture = currentTexture;
}
}
// Draw remaining batch and clear the sprite data
RenderBatch(currentTexture, SpriteBuffer, startingOffset,
SpriteBuffer.Count - startingOffset);
SpriteBuffer.Clear();
SpriteBatch.RenderBatch: executes the following operations for each of the SpriteInfo in the batch:
Takes the position of the sprite and calculates the final position of the four vertices according to the origin and size. Applies existing rotation.
Calculates the UV coordinates and applies specified SpriteEffects to them.
Copies the sprite color.
These values are then stored in the array of VertexPositionColorTexture elements previously created. When all sprites have been calculated, SetData is called on the DynamicVertexBuffer and a DrawIndexedPrimitives call is issued.
The vertex shader only performs a tranform operation, and the pixel shader applies the tinting on the color fetched from the texture.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement