Add a pool for GroupCommand rendering commands (#969)

* Committing genbindings changes

* Use a pool of GroupCommand entries to avoid multiple entries of the same group in the render queue in certain scenarios

* Ensure captureNode works as expected.

* Set member variables to default values when init method is called on the GroupCommand

* Explicitly reset the command state when retrieving a GroupCommand from the pool
This commit is contained in:
RH 2022-11-28 11:37:22 +11:00 committed by GitHub
parent ed4d2251df
commit 2e30b51ab7
21 changed files with 110 additions and 64 deletions

View File

@ -164,14 +164,14 @@ void CameraBackgroundDepthBrush::initBuffer()
void CameraBackgroundDepthBrush::drawBackground(Camera* /*camera*/)
{
auto* renderer = Director::getInstance()->getRenderer();
// `clear screen` should be executed before other commands
_groupCommand.init(-1.0f);
auto* groupCommand = renderer->getNextGroupCommand();
groupCommand->init(-1.0f);
_customCommand.init(0.0f);
auto* renderer = Director::getInstance()->getRenderer();
renderer->addCommand(&_groupCommand);
renderer->pushGroup(_groupCommand.getRenderQueueID());
renderer->addCommand(groupCommand);
renderer->pushGroup(groupCommand->getRenderQueueID());
auto& pipelineDescriptor = _customCommand.getPipelineDescriptor();
auto& blend = pipelineDescriptor.blendDescriptor;
@ -337,8 +337,10 @@ CameraBackgroundSkyBoxBrush* CameraBackgroundSkyBoxBrush::create()
void CameraBackgroundSkyBoxBrush::drawBackground(Camera* camera)
{
auto* renderer = Director::getInstance()->getRenderer();
// `clear screen` should be executed before other commands
_groupCommand.init(-1.0f);
auto* groupCommand = renderer->getNextGroupCommand();
groupCommand->init(-1.0f);
_customCommand.init(0.0f);
if (!_actived)
@ -355,10 +357,9 @@ void CameraBackgroundSkyBoxBrush::drawBackground(Camera* camera)
_programState->setUniform(_uniformColorLoc, &color, sizeof(color));
_programState->setUniform(_uniformCameraRotLoc, cameraModelMat.m, sizeof(cameraModelMat.m));
auto* renderer = Director::getInstance()->getRenderer();
renderer->addCommand(&_groupCommand);
renderer->pushGroup(_groupCommand.getRenderQueueID());
renderer->addCommand(groupCommand);
renderer->pushGroup(groupCommand->getRenderQueueID());
renderer->addCommand(&_customCommand);

View File

@ -176,7 +176,6 @@ protected:
float _depth;
backend::UniformLocation _locDepth;
CustomCommand _customCommand;
GroupCommand _groupCommand;
bool _clearColor;
std::vector<V3F_C4B_T2F> _vertices;
@ -307,7 +306,6 @@ private:
bool _textureValid;
CustomCommand _customCommand;
GroupCommand _groupCommand;
backend::UniformLocation _uniformColorLoc;
backend::UniformLocation _uniformCameraRotLoc;

View File

@ -147,10 +147,11 @@ void ClippingNode::visit(Renderer* renderer, const Mat4& parentTransform, uint32
// Add group command
_groupCommandStencil.init(_globalZOrder);
renderer->addCommand(&_groupCommandStencil);
auto* groupCommandStencil = renderer->getNextGroupCommand();
groupCommandStencil->init(_globalZOrder);
renderer->addCommand(groupCommandStencil);
renderer->pushGroup(_groupCommandStencil.getRenderQueueID());
renderer->pushGroup(groupCommandStencil->getRenderQueueID());
// _beforeVisitCmd.init(_globalZOrder);
// _beforeVisitCmd.func = AX_CALLBACK_0(StencilStateManager::onBeforeVisit, _stencilStateManager);
@ -180,10 +181,12 @@ void ClippingNode::visit(Renderer* renderer, const Mat4& parentTransform, uint32
// `_groupCommandChildren` is used as a barrier
// to ensure commands above be executed before children nodes
_groupCommandChildren.init(_globalZOrder);
renderer->addCommand(&_groupCommandChildren);
auto* groupCommandChildren = renderer->getNextGroupCommand();
renderer->pushGroup(_groupCommandChildren.getRenderQueueID());
groupCommandChildren->init(_globalZOrder);
renderer->addCommand(groupCommandChildren);
renderer->pushGroup(groupCommandChildren->getRenderQueueID());
if (!_children.empty())
{

View File

@ -159,8 +159,6 @@ protected:
Node* _stencil = nullptr;
StencilStateManager* _stencilStateManager = nullptr;
GroupCommand _groupCommandStencil;
GroupCommand _groupCommandChildren;
//CallbackCommand _afterDrawStencilCmd;
//CallbackCommand _afterVisitCmd;
std::unordered_map<Node*, backend::ProgramState*> _originalStencilProgramState;

View File

@ -203,10 +203,10 @@ void GridBase::beforeDraw()
// save projection
Director* director = Director::getInstance();
auto renderer = director->getRenderer();
renderer->addCommand(&_groupCommand);
renderer->pushGroup(_groupCommand.getRenderQueueID());
auto* renderer = director->getRenderer();
auto* groupCommand = renderer->getNextGroupCommand();
renderer->addCommand(groupCommand);
renderer->pushGroup(groupCommand->getRenderQueueID());
auto beforeDrawCommandFunc = [=, this]() -> void {
_directorProjection = director->getProjection();

View File

@ -153,7 +153,6 @@ protected:
Color4F _clearColor = {0, 0, 0, 0};
GroupCommand _groupCommand;
CustomCommand _drawCommand;
//CallbackCommand _beforeDrawCommand;
//CallbackCommand _afterDrawCommand;

View File

@ -97,7 +97,6 @@ protected:
Node* _gridTarget = nullptr;
GridBase* _nodeGrid = nullptr;
GroupCommand _groupCommand;
CustomCommand _gridBeginCommand;
CustomCommand _gridEndCommand;

View File

@ -611,11 +611,12 @@ void RenderTexture::begin()
_director->multiplyMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION, orthoMatrix);
}
_groupCommand.init(_globalZOrder);
Renderer* renderer = _director->getRenderer();
renderer->addCommand(&_groupCommand);
renderer->pushGroup(_groupCommand.getRenderQueueID());
auto* groupCommand = renderer->getNextGroupCommand();
groupCommand->init(_globalZOrder);
renderer->addCommand(groupCommand);
renderer->pushGroup(groupCommand->getRenderQueueID());
auto beginCommand = renderer->nextCallbackCommand();
beginCommand->init(_globalZOrder);

View File

@ -413,7 +413,6 @@ protected:
*/
Sprite* _sprite = nullptr;
GroupCommand _groupCommand;
//CallbackCommand _beginCommand;
//CallbackCommand _endCommand;

View File

@ -134,7 +134,8 @@ void captureNode(Node* startNode, std::function<void(RefPtr<Image>)> imageCallba
RenderTexture* finalRtx = nullptr;
auto rtx = RenderTexture::create(size.width, size.height, backend::PixelFormat::RGBA8, PixelFormat::D24S8);
auto rtx =
RenderTexture::create(size.width, size.height, backend::PixelFormat::RGBA8, PixelFormat::D24S8, false);
// rtx->setKeepMatrix(true);
Point savedPos = startNode->getPosition();
Point anchor;
@ -158,7 +159,7 @@ void captureNode(Node* startNode, std::function<void(RefPtr<Image>)> imageCallba
sprite->setAnchorPoint(Point(0, 0));
sprite->setFlippedY(true);
finalRtx = RenderTexture::create(size.width * scale, size.height * scale, backend::PixelFormat::RGBA8,
PixelFormat::D24S8);
PixelFormat::D24S8, false);
sprite->setScale(scale); // or use finalRtx->setKeepMatrix(true);
finalRtx->begin();

View File

@ -79,6 +79,16 @@ void GroupCommand::init(float globalOrder)
_renderQueueID = manager->getGroupID();
}
void GroupCommand::reset()
{
_globalOrder = 0.0f;
_isTransparent = true;
_skipBatching = false;
_is3D = false;
_depth = 0.0f;
_isWireframe = false;
}
GroupCommand::~GroupCommand()
{
Director::getInstance()->getRenderer()->getGroupCommandManager()->releaseGroupID(_renderQueueID);

View File

@ -75,6 +75,12 @@ public:
/**called by renderer, get the group ID.*/
int getRenderQueueID() const { return _renderQueueID; }
/**
* @brief Reset the command state for reuse
*
*/
void reset();
protected:
int _renderQueueID;
};

View File

@ -176,12 +176,17 @@ Renderer::Renderer()
Renderer::~Renderer()
{
_renderGroups.clear();
_groupCommandManager->release();
for (auto&& clearCommand : _callbackCommandsPool)
delete clearCommand;
_callbackCommandsPool.clear();
for (auto&& clearCommand : _groupCommandPool)
delete clearCommand;
_groupCommandPool.clear();
_groupCommandManager->release();
free(_triBatchesToDraw);
AX_SAFE_RELEASE(_depthStencilState);
@ -240,6 +245,20 @@ void Renderer::addCommand(RenderCommand* command, int renderQueueID)
_renderGroups[renderQueueID].emplace_back(command);
}
GroupCommand* Renderer::getNextGroupCommand()
{
if (_groupCommandPool.empty())
{
return new GroupCommand();
}
auto* command = _groupCommandPool.back();
_groupCommandPool.pop_back();
command->reset();
return command;
}
void Renderer::pushGroup(int renderQueueID)
{
AXASSERT(!_isRendering, "Cannot change render queue while rendering");
@ -321,6 +340,7 @@ void Renderer::processRenderCommand(RenderCommand* command)
break;
case RenderCommand::Type::GROUP_COMMAND:
processGroupCommand(static_cast<GroupCommand*>(command));
_groupCommandPool.emplace_back(static_cast<GroupCommand*>(command));
break;
case RenderCommand::Type::CUSTOM_COMMAND:
flush();

View File

@ -155,6 +155,9 @@ public:
/** Adds a `RenderComamnd` into the renderer specifying a particular render queue ID */
void addCommand(RenderCommand* command, int renderQueueID);
/** Get a `GroupCommand` from a GroupCommand pool or creates a new command if the pool is empty */
GroupCommand* getNextGroupCommand();
/** Pushes a group into the render queue */
void pushGroup(int renderQueueID);
@ -507,6 +510,8 @@ protected:
// the pool for callback commands
std::vector<CallbackCommand*> _callbackCommandsPool;
std::vector<GroupCommand*> _groupCommandPool;
// for TrianglesCommand
V3F_C4B_T2F _verts[VBO_SIZE];
unsigned short _indices[INDEX_VBO_SIZE];

View File

@ -248,10 +248,10 @@ void Layout::stencilClippingVisit(Renderer* renderer, const Mat4& parentTransfor
_director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, _modelViewTransform);
// Add group command
_groupCommand.init(_globalZOrder);
renderer->addCommand(&_groupCommand);
renderer->pushGroup(_groupCommand.getRenderQueueID());
auto* groupCommand = renderer->getNextGroupCommand();
groupCommand->init(_globalZOrder);
renderer->addCommand(groupCommand);
renderer->pushGroup(groupCommand->getRenderQueueID());
// _beforeVisitCmdStencil.init(_globalZOrder);
// _beforeVisitCmdStencil.func = AX_CALLBACK_0(StencilStateManager::onBeforeVisit, _stencilStateManager);
@ -369,9 +369,10 @@ void Layout::scissorClippingVisit(Renderer* renderer, const Mat4& parentTransfor
_director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
_director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, _modelViewTransform);
_groupCommand.init(_globalZOrder);
renderer->addCommand(&_groupCommand);
renderer->pushGroup(_groupCommand.getRenderQueueID());
auto* groupCommand = renderer->getNextGroupCommand();
groupCommand->init(_globalZOrder);
renderer->addCommand(groupCommand);
renderer->pushGroup(groupCommand->getRenderQueueID());
auto beforeVisitCmdScissor = renderer->nextCallbackCommand();
beforeVisitCmdScissor->init(_globalZOrder);

View File

@ -640,7 +640,6 @@ protected:
// clipping
StencilStateManager* _stencilStateManager;
GroupCommand _groupCommand;
//CallbackCommand _beforeVisitCmdStencil;
//CallbackCommand _afterDrawStencilCmd;
//CallbackCommand _afterVisitCmdStencil;

View File

@ -43,10 +43,9 @@ BatchNode* BatchNode::create()
AX_SAFE_DELETE(batchNode);
return nullptr;
}
BatchNode::BatchNode() : _groupCommand(nullptr) {}
BatchNode::BatchNode() /*: _groupCommand(nullptr)*/ {}
BatchNode::~BatchNode()
{
AX_SAFE_DELETE(_groupCommand);
}
bool BatchNode::init()
@ -62,10 +61,6 @@ void BatchNode::addChild(Node* child, int zOrder, int tag)
if (armature != nullptr)
{
armature->setBatchNode(this);
if (_groupCommand == nullptr)
{
_groupCommand = new GroupCommand();
}
}
}
@ -76,10 +71,6 @@ void BatchNode::addChild(ax::Node* child, int zOrder, std::string_view name)
if (armature != nullptr)
{
armature->setBatchNode(this);
if (_groupCommand == nullptr)
{
_groupCommand = new GroupCommand();
}
}
}
@ -160,10 +151,11 @@ void BatchNode::draw(Renderer* renderer, const Mat4& transform, uint32_t flags)
void BatchNode::generateGroupCommand()
{
Renderer* renderer = Director::getInstance()->getRenderer();
_groupCommand->init(_globalZOrder);
renderer->addCommand(_groupCommand);
auto* groupCommand = renderer->getNextGroupCommand();
groupCommand->init(_globalZOrder);
renderer->addCommand(groupCommand);
renderer->pushGroup(_groupCommand->getRenderQueueID());
renderer->pushGroup(groupCommand->getRenderQueueID());
}
} // namespace cocostudio

View File

@ -69,7 +69,6 @@ public:
protected:
void generateGroupCommand();
ax::GroupCommand* _groupCommand;
};
} // namespace cocostudio

View File

@ -386,11 +386,16 @@ void FUIContainer::visit(ax::Renderer * renderer, const ax::Mat4 & parentTransfo
director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, _modelViewTransform);
//Add group command
#if defined(AX_VERSION)
auto* stencilGroupCommand = renderer->getNextGroupCommand();
stencilGroupCommand->init(_globalZOrder);
renderer->addCommand(stencilGroupCommand);
renderer->pushGroup(stencilGroupCommand->getRenderQueueID());
#else
_stencilClippingSupport->_groupCommand.init(_globalZOrder);
renderer->addCommand(&_stencilClippingSupport->_groupCommand);
renderer->pushGroup(_stencilClippingSupport->_groupCommand.getRenderQueueID());
#endif
#if COCOS2D_VERSION >= 0x00040000
_stencilClippingSupport->_stencilStateManager->onBeforeVisit(_globalZOrder);
@ -476,11 +481,19 @@ void FUIContainer::visit(ax::Renderer * renderer, const ax::Mat4 & parentTransfo
{
_rectClippingSupport->_clippingRectDirty = true;
}
#if COCOS2D_VERSION >= 0x00040000
#if defined(AX_VERSION)
auto* rectClippingGroupCommand = renderer->getNextGroupCommand();
rectClippingGroupCommand->init(_globalZOrder);
renderer->addCommand(rectClippingGroupCommand);
renderer->pushGroup(rectClippingGroupCommand->getRenderQueueID());
#else
# if COCOS2D_VERSION >= 0x00040000
_rectClippingSupport->_groupCommand.init(_globalZOrder);
renderer->addCommand(&_rectClippingSupport->_groupCommand);
renderer->pushGroup(_rectClippingSupport->_groupCommand.getRenderQueueID());
# endif
#endif
auto beforeVisitCmdScissor = renderer->nextCallbackCommand();
beforeVisitCmdScissor->init(_globalZOrder);
beforeVisitCmdScissor->func = AX_CALLBACK_0(FUIContainer::onBeforeVisitScissor, this);

View File

@ -21,7 +21,9 @@ public:
bool _clippingRectDirty;
#if COCOS2D_VERSION >= 0x00040000
#if !defined(AX_VERSION)
ax::GroupCommand _groupCommand;
#endif
//ax::CallbackCommand _beforeVisitCmdScissor;
//ax::CallbackCommand _afterVisitCmdScissor;
#else
@ -37,7 +39,9 @@ public:
ax::Node* _stencil;
ax::StencilStateManager* _stencilStateManager;
#if !defined(AX_VERSION)
ax::GroupCommand _groupCommand;
#endif
#if COCOS2D_VERSION >= 0x00040000
ax::backend::ProgramState* _originStencilProgram;
//ax::CallbackCommand _beforeVisitCmd;

View File

@ -196,9 +196,6 @@ std::string NewSpriteTest::subtitle() const
class SpriteInGroupCommand : public Sprite
{
protected:
GroupCommand _spriteWrapperCommand;
public:
static SpriteInGroupCommand* create(std::string_view filename);
@ -216,9 +213,10 @@ SpriteInGroupCommand* SpriteInGroupCommand::create(std::string_view filename)
void SpriteInGroupCommand::draw(Renderer* renderer, const Mat4& transform, uint32_t flags)
{
AXASSERT(renderer, "Render is null");
_spriteWrapperCommand.init(_globalZOrder);
renderer->addCommand(&_spriteWrapperCommand);
renderer->pushGroup(_spriteWrapperCommand.getRenderQueueID());
auto * spriteWrapperCommand = renderer->getNextGroupCommand();
spriteWrapperCommand->init(_globalZOrder);
renderer->addCommand(spriteWrapperCommand);
renderer->pushGroup(spriteWrapperCommand->getRenderQueueID());
Sprite::draw(renderer, transform, flags);
renderer->popGroup();
}
@ -744,7 +742,7 @@ void CaptureNodeTest::onCaptured(Ref*)
sp->setPosition(s.width / 2, s.height / 2);
// store to disk
image->saveToFile(_filename);
image->saveToFile(_filename, false);
};
auto callbackFunction = std::bind(callback, std::placeholders::_1);