I just did a small benchmark. To my surprise batching sprites into a single draw call doesn't give any significant performance boost. Following are my results:
Hardware: iPod touch 4
Extra info: OpenGL ES 2.0. 1 sprite (64x64) having some transparency (smiley face with drop shadow). NO rotation, NO scale. (Texture is bound only once at the start in the init function). Compiled in "Release" mode.
The first column labeled 'N' shows number of sprites being tested. Second column shows FPS when sprites are batched in a huge vertex array (only 1 draw call). Third column shows FPS on multi draw calls, eg: 5000 draw calls for 5000 sprites.
Benchmark 1: Alpha blending off
Benchmark 2: Alpha blending ON
Smiley image used:
Source code:
For single draw call:
Vertex hugeArray[SPRITE_COUNT*6];
GLsizei stride = sizeof(Vertex);
int drawCallCount = 0;
const GLvoid* pCoords = &hugeArray[0].Position[0];
const GLvoid* pColors = &hugeArray[0].Color[0];
const GLvoid* pTexCoords = &hugeArray[0].Texture[0];
glVertexAttribPointer(positionSlot, 2, GL_FLOAT, GL_FALSE, stride, pCoords);
glVertexAttribPointer(colorSlot, 4, GL_FLOAT, GL_FALSE, stride, pColors);
glVertexAttribPointer(textureSlot, 2, GL_FLOAT, GL_FALSE, stride, pTexCoords);
GLsizei vertexCount = sizeof(hugeArray) / sizeof(Vertex);
glDrawArrays(GL_TRIANGLES, 0, vertexCount);
drawCallCount++;
cout << "DrawCall Count: " << drawCallCount << endl;
For multiple draw calls:
Vertex hugeArray[SPRITE_COUNT*6];
GLsizei stride = sizeof(Vertex);
int drawCallCount = 0;
for(int i = 0; i < SPRITE_COUNT; i++){
const GLvoid* pCoords = &hugeArray[i*6].Position[0];
const GLvoid* pColors = &hugeArray[i*6].Color[0];
const GLvoid* pTexCoords = &hugeArray[i*6].Texture[0];
glVertexAttribPointer(positionSlot, 2, GL_FLOAT, GL_FALSE, stride, pCoords);
glVertexAttribPointer(colorSlot, 4, GL_FLOAT, GL_FALSE, stride, pColors);
glVertexAttribPointer(textureSlot, 2, GL_FLOAT, GL_FALSE, stride, pTexCoords);
GLsizei vertexCount = 6;
glDrawArrays(GL_TRIANGLES, 0, vertexCount);
drawCallCount++;
}
cout << "DrawCall Count: " << drawCallCount << endl;
I thought that batching sprites into a huge array resulting in a single draw call would give a HUGE performance gain but benchmarks show otherwise. Any ideas what is going on here?
Thanks for reading the question :)