Improved batching

This commit is contained in:
Nite Luo 2013-11-11 00:14:29 -08:00
parent 5a1d92cbf2
commit f68a2a47e7
6 changed files with 146 additions and 65 deletions

View File

@ -27,8 +27,7 @@ int64_t CustomCommand::generateID()
_id = (int64_t)_viewport << 61
| (int64_t)1 << 60 // translucent
| (int64_t)0 << 59 // is command
| (int64_t)_depth << 35;
| (int64_t)_depth << 36;
return _id;
}

View File

@ -20,8 +20,8 @@ public:
// +----------+----------+-----+-----------------------------------+
// | | | | | |
// | ViewPort | Transluc | Cmd | Depth | |
// | 3 bits | 1 bit | 1 | 24 bits | |
// | ViewPort | Transluc | | Depth | |
// | 3 bits | 1 bit | | 24 bits | |
// +----------+----------+-----+----------------+------------------+
virtual int64_t generateID();
@ -29,9 +29,6 @@ public:
inline bool isTranslucent() { return true; }
//TODO support non-graphical command
inline bool isCommand() { return false; }
public:
function<void()> func;

View File

@ -18,6 +18,7 @@ QuadCommand::QuadCommand(int viewport, int32_t depth, GLuint textureID, GLProgra
{
_type = QUAD_COMMAND;
_shader = shader;
_quadCount = 1;
}
QuadCommand::~QuadCommand()
@ -65,8 +66,7 @@ int64_t QuadCommand::generateID()
//Generate RenderCommandID
_id = (int64_t)_viewport << 61
| (int64_t)1 << 60 //translucent
| (int64_t)0 << 59 //is command
| (int64_t)_depth << 35;
| (int64_t)_depth << 36;
return _id;
}

View File

@ -21,8 +21,8 @@ public:
// +----------+----------+-----+-----------------------------------+
// | | | | | |
// | ViewPort | Transluc | Cmd | Depth | Material ID |
// | 3 bits | 1 bit | 1 | 24 bits | 24 bit2 |
// | ViewPort | Transluc | | Depth | Material ID |
// | 3 bits | 1 bit | | 24 bits | 24 bit2 |
// +----------+----------+-----+----------------+------------------+
virtual int64_t generateID();
@ -31,14 +31,14 @@ public:
//TODO use material to decide if it is translucent
inline bool isTranslucent() { return true; }
inline bool isCommand() { return false; }
inline int32_t getMaterialID() { return _materialID; }
inline GLuint getTextureID() { return _textureID; }
inline V3F_C4B_T2F_Quad* getQuad() { return &_quad; }
inline int getQuadCount() { return _quadCount; }
inline GLProgram* getShader() { return _shader; }
inline BlendFunc getBlendType() { return _blendType; }
@ -61,6 +61,7 @@ protected:
BlendFunc _blendType;
V3F_C4B_T2F_Quad _quad;
int _quadCount;
};
NS_CC_END

View File

@ -36,27 +36,18 @@ void Renderer::destroyInstance()
Renderer::Renderer()
:_lastMaterialID(0)
,_numQuads(0)
,_firstCommand(0)
,_lastCommand(0)
{
}
Renderer::~Renderer()
{
free(_quads);
}
bool Renderer::init()
{
_quads = (V3F_C4B_T2F_Quad*)malloc(sizeof(V3F_C4B_T2F_Quad) * VBO_SIZE);
_indices = (GLushort*) malloc(sizeof(GLushort) * 6 * VBO_SIZE);
if( ! ( _quads && _indices) )
{
//not enough memory
CC_SAFE_FREE(_quads);
CC_SAFE_FREE(_indices);
return false;
}
setupIndices();
setupVBOAndVAO();
@ -132,57 +123,145 @@ void Renderer::render()
//1. Sort render commands based on ID
stable_sort(_renderQueue.begin(), _renderQueue.end(), compareRenderCommand);
//2. Process commands
for(auto it = _renderQueue.begin(); it != _renderQueue.end(); ++it)
size_t len = _renderQueue.size();
for (size_t i = 0; i < len; i++)
{
//TODO: Perform Sprite batching here
auto command = *it;
auto command = _renderQueue[i];
switch(command->getType())
if( command->getType() == QUAD_COMMAND )
{
case QUAD_COMMAND:
QuadCommand* cmd = static_cast<QuadCommand*>(command);
//
if(_numQuads + cmd->getQuadCount() < VBO_SIZE)
{
QuadCommand* cmd = static_cast<QuadCommand*>(command);
if(_lastMaterialID != cmd->getMaterialID() || _numQuads >= VBO_SIZE)
{
//Draw batched data
drawQuads();
}
//Reset material if needed.
if(_lastMaterialID != cmd->getMaterialID())
{
//Set new material
_lastMaterialID = cmd->getMaterialID();
//Set Shader
cmd->useMaterial();
}
batchQuads(cmd);
break;
memcpy(_quads + _numQuads - 1, cmd->getQuad(), sizeof(V3F_C4B_T2F_Quad) * cmd->getQuadCount());
_numQuads += cmd->getQuadCount();
_lastCommand = i;
}
case CUSTOM_COMMAND:
else
{
flush();
CustomCommand* cmd = static_cast<CustomCommand*>(command);
cmd->execute();
break;
//Draw batched quads if VBO is full
drawBatchedQuads();
}
default:
break;
}
else
{
//Draw batched quads if we encountered a different command
drawBatchedQuads();
}
delete command;
}
drawQuads();
//Draw the batched quads
drawBatchedQuads();
_firstCommand = _lastCommand = 0;
_lastMaterialID = 0;
_renderQueue.clear();
// //2. Process commands
// for(auto it = _renderQueue.begin(); it != _renderQueue.end(); ++it)
// {
// //TODO: Perform Sprite batching here
// auto command = *it;
//
// switch(command->getType())
// {
// case QUAD_COMMAND:
// {
// QuadCommand* cmd = static_cast<QuadCommand*>(command);
//
// if(_lastMaterialID != cmd->getMaterialID() || _numQuads >= VBO_SIZE)
// {
// //Draw batched data
// drawQuads();
// }
//
// //Reset material if needed.
// if(_lastMaterialID != cmd->getMaterialID())
// {
// //Set new material
// _lastMaterialID = cmd->getMaterialID();
//
// //Set Shader
// cmd->useMaterial();
// }
//
// batchQuads(cmd);
//
// break;
// }
// case CUSTOM_COMMAND:
// {
// flush();
// CustomCommand* cmd = static_cast<CustomCommand*>(command);
// cmd->execute();
//
// break;
// }
// default:
// break;
// }
//
// delete command;
// }
//
// drawQuads();
//
// _renderQueue.clear();
}
void Renderer::drawBatchedQuads()
{
int quadsToDraw = 0;
int startQuad = 0;
//Upload buffer to VBO
if(_numQuads <= 0)
return;
//Set VBO data
glBindBuffer(GL_ARRAY_BUFFER, _buffersVBO[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(_quads[0]) * (_numQuads), NULL, GL_DYNAMIC_DRAW);
void *buf = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
memcpy(buf, _quads, sizeof(_quads[0])* (_numQuads));
glUnmapBuffer(GL_ARRAY_BUFFER);
glBindBuffer(GL_ARRAY_BUFFER, 0);
//Bind VAO
GL::bindVAO(_VAOname);
for(size_t i = _firstCommand; i <= _lastCommand; i++)
{
RenderCommand* command = _renderQueue[i];
if (command->getType() == QUAD_COMMAND)
{
QuadCommand* cmd = static_cast<QuadCommand*>(command);
if(_lastMaterialID != cmd->getMaterialID())
{
//Draw quads
if(quadsToDraw > 0)
{
glDrawElements(GL_TRIANGLES, (GLsizei) quadsToDraw*6, GL_UNSIGNED_SHORT, (GLvoid*) (startQuad*6*sizeof(_indices[0])) );
startQuad += quadsToDraw;
quadsToDraw = 0;
}
//Use new material
cmd->useMaterial();
_lastMaterialID = cmd->getMaterialID();
}
quadsToDraw += cmd->getQuadCount();
}
}
_firstCommand = _lastCommand;
_numQuads = 0;
}
void Renderer::drawQuads()

View File

@ -47,12 +47,17 @@ protected:
vector<RenderCommand*> _renderQueue;
int _lastMaterialID;
V3F_C4B_T2F_Quad*_quads;
GLushort* _indices;
size_t _firstCommand;
size_t _lastCommand;
V3F_C4B_T2F_Quad _quads[VBO_SIZE];
GLushort _indices[6 * VBO_SIZE];
GLuint _VAOname;
GLuint _buffersVBO[2]; //0: vertex 1: indices
int _numQuads;
void drawBatchedQuads();
};
NS_CC_END