Renderer: Don't sort z=0 Commands

If Command has z==0, then those elements won't be sorted.
Only Z !=0 will be sorted, and it will use `sort` instead of `stable_sort`
for z!=0, since it is faster
This commit is contained in:
Ricardo Quesada 2014-01-17 23:10:04 -08:00
parent ca58cc06b7
commit 069a4fb170
11 changed files with 98 additions and 30 deletions

View File

@ -17,10 +17,11 @@ cocos2d-x-3.0final ?.? ?
[FIX] ControlSlider doesn't support to set selected thumb sprite.
[FIX] ControlButton doesn't support to set scale ratio of touchdown state.
[FIX] Particles: Crash was triggered if there is not `textureFileName`section in particle plist file.
[FIX] Renderer: QuadCommand::init() does not copy the Quads, it only store a reference making the code faster
[FIX] Renderer: Performance improved in Sprite and SpriteBatchNode (and subclasses) sprites in about 20%
[FIX] Renderer: When note using VAO, call glBufferData() instead of glBufferSubData().
[FIX] Renderer: Uses a float as key with only the depth. Viewport, opaque are not needed now
[FIX] Renderer Performance Fix: QuadCommand::init() does not copy the Quads, it only store a reference making the code faster
[FIX] Renderer Performance Fix: Sprite and SpriteBatchNode (and subclasses) has much better performance
[FIX] Renderer Performance Fix: When note using VAO, call glBufferData() instead of glBufferSubData().
[FIX] Renderer Performance Fix: Doesn't sort z=0 elements. It also uses sort() instead of stable_sort() for z!=0.
[FIX] Sprite: removed _hasChildren optimization. It uses !_children.empty() now which is super fast as well
[FIX] Tests: TestCpp works with CMake on Windows.
[FIX] Tests: Sprites Performance Test has 4 new tests

View File

@ -54,7 +54,7 @@ BatchCommand::~BatchCommand()
{
}
void BatchCommand::execute()
void BatchCommand::execute() const
{
// Set material
_shader->use();

View File

@ -45,7 +45,7 @@ public:
void init(float depth, GLuint texutreID, GLProgram* shader, BlendFunc blendType, TextureAtlas *textureAtlas, const kmMat4& modelViewTransform);
void execute();
void execute() const;
protected:
int32_t _materialID;

View File

@ -42,7 +42,7 @@ CustomCommand::~CustomCommand()
}
void CustomCommand::execute()
void CustomCommand::execute() const
{
if(func)
{

View File

@ -41,7 +41,7 @@ public:
void init(float depth);
void execute();
void execute() const;
inline bool isTranslucent() { return true; }
std::function<void()> func;

View File

@ -56,12 +56,9 @@ public:
GroupCommand();
~GroupCommand();
public:
void init(float depth);
inline bool isTranslucent() {return true;}
inline int getRenderQueueID() {return _renderQueueID;}
inline int getRenderQueueID() const {return _renderQueueID;}
protected:
int _renderQueueID;

View File

@ -101,7 +101,7 @@ void QuadCommand::generateMaterialID()
| (uint32_t)_textureID << 0;
}
void QuadCommand::useMaterial()
void QuadCommand::useMaterial() const
{
_shader->use();

View File

@ -44,7 +44,7 @@ public:
void init(float depth, GLuint texutreID, GLProgram* shader, BlendFunc blendType, V3F_C4B_T2F_Quad* quads, ssize_t quadCount,
const kmMat4& mv);
void useMaterial();
void useMaterial() const;
//TODO use material to decide if it is translucent
inline bool isTranslucent() const { return true; }

View File

@ -50,10 +50,10 @@ public:
};
/** Get Render Command Id */
inline float getDepth() { return _depth; }
inline float getDepth() const { return _depth; }
/** Returns the Command type */
inline Type getType() { return _type; }
inline Type getType() const { return _type; }
protected:
RenderCommand();

View File

@ -37,9 +37,65 @@
#include <algorithm> // for std::stable_sort
NS_CC_BEGIN
using namespace std;
bool compareRenderCommand(RenderCommand* a, RenderCommand* b)
{
return a->getDepth() < b->getDepth();
}
void RenderQueue::push_back(RenderCommand* command)
{
float z = command->getDepth();
if(z < 0)
_queueNegZ.push_back(command);
if(z > 0)
_queuePosZ.push_back(command);
else
_queue0.push_back(command);
}
ssize_t RenderQueue::size() const
{
return _queueNegZ.size() + _queue0.size() + _queuePosZ.size();
}
void RenderQueue::sort()
{
// Don't sort _queue0, it already comes sorted
std::sort(std::begin(_queueNegZ), std::end(_queueNegZ), compareRenderCommand);
std::sort(std::begin(_queuePosZ), std::end(_queuePosZ), compareRenderCommand);
}
const RenderCommand* RenderQueue::operator[](ssize_t index) const
{
if(index < _queueNegZ.size())
return _queueNegZ[index];
index -= _queueNegZ.size();
if(index < _queue0.size())
return _queue0[index];
index -= _queue0.size();
if(index < _queuePosZ.size())
return _queuePosZ[index];
CCASSERT(false, "invalid index");
return nullptr;
}
void RenderQueue::clear()
{
_queueNegZ.clear();
_queue0.clear();
_queuePosZ.clear();
}
//
//
//
#define DEFAULT_RENDER_QUEUE 0
Renderer::Renderer()
@ -205,11 +261,6 @@ int Renderer::createRenderQueue()
return (int)_renderGroups.size() - 1;
}
bool compareRenderCommand(RenderCommand* a, RenderCommand* b)
{
return a->getDepth() < b->getDepth();
}
void Renderer::render()
{
//Uncomment this once everything is rendered by new renderer
@ -221,9 +272,9 @@ void Renderer::render()
{
//Process render commands
//1. Sort render commands based on ID
for (auto it = _renderGroups.begin(); it != _renderGroups.end(); ++it)
for (auto &renderqueue : _renderGroups)
{
std::stable_sort((*it).begin(), (*it).end(), compareRenderCommand);
renderqueue.sort();
}
while(!_renderStack.empty())
@ -244,7 +295,7 @@ void Renderer::render()
if(commandType == RenderCommand::Type::QUAD_COMMAND)
{
QuadCommand* cmd = static_cast<QuadCommand*>(command);
auto cmd = static_cast<const QuadCommand*>(command);
ssize_t cmdQuadCount = cmd->getQuadCount();
//Batch quads
@ -266,19 +317,19 @@ void Renderer::render()
else if(commandType == RenderCommand::Type::CUSTOM_COMMAND)
{
flush();
CustomCommand* cmd = static_cast<CustomCommand*>(command);
auto cmd = static_cast<const CustomCommand*>(command);
cmd->execute();
}
else if(commandType == RenderCommand::Type::BATCH_COMMAND)
{
flush();
BatchCommand* cmd = static_cast<BatchCommand*>(command);
auto cmd = static_cast<const BatchCommand*>(command);
cmd->execute();
}
else if(commandType == RenderCommand::Type::GROUP_COMMAND)
{
flush();
GroupCommand* cmd = static_cast<GroupCommand*>(command);
auto cmd = static_cast<const GroupCommand*>(command);
_renderStack.top().currentIndex = i + 1;
@ -413,10 +464,10 @@ void Renderer::drawBatchedQuads()
//Start drawing verties in batch
for(ssize_t i = _firstCommand; i <= _lastCommand; i++)
{
RenderCommand* command = _renderGroups[_renderStack.top().renderQueueID][i];
auto command = _renderGroups[_renderStack.top().renderQueueID][i];
if (command->getType() == RenderCommand::Type::QUAD_COMMAND)
{
QuadCommand* cmd = static_cast<QuadCommand*>(command);
auto cmd = static_cast<const QuadCommand*>(command);
if(_lastMaterialID != cmd->getMaterialID())
{
//Draw quads

View File

@ -37,7 +37,26 @@ NS_CC_BEGIN
class EventListenerCustom;
typedef std::vector<RenderCommand*> RenderQueue;
/** Class that knows how to sort the Commands.
Since the commands that have z==0 are "pushed back" in
the correct order, the only Commands that need to be sorted,
are the ones that have z <0 and z >0.
And that is what this class does.
*/
class RenderQueue {
public:
void push_back(RenderCommand* command);
ssize_t size() const;
void sort();
const RenderCommand* operator[](ssize_t index) const;
void clear();
protected:
std::vector<RenderCommand*> _queueNegZ;
std::vector<RenderCommand*> _queue0;
std::vector<RenderCommand*> _queuePosZ;
};
struct RenderStackElement
{