From 84b0af8ac57d166bc26cd253ddbc6772ae251aac Mon Sep 17 00:00:00 2001 From: halx99 Date: Fri, 16 Oct 2020 17:48:30 +0800 Subject: [PATCH 1/3] Fix custom program state not applied at cocos2d-x-4.0 --- spine-cocos2dx/src/spine/SkeletonRenderer.cpp | 4 +- spine-cocos2dx/src/spine/v4/SkeletonBatch.cpp | 66 +++++++++++-------- spine-cocos2dx/src/spine/v4/SkeletonBatch.h | 14 +++- 3 files changed, 53 insertions(+), 31 deletions(-) diff --git a/spine-cocos2dx/src/spine/SkeletonRenderer.cpp b/spine-cocos2dx/src/spine/SkeletonRenderer.cpp index 0380fe8f2..dbc521d31 100644 --- a/spine-cocos2dx/src/spine/SkeletonRenderer.cpp +++ b/spine-cocos2dx/src/spine/SkeletonRenderer.cpp @@ -433,7 +433,7 @@ void SkeletonRenderer::draw (Renderer* renderer, const Mat4& transform, uint32_t #if COCOS2D_VERSION < 0x00040000 cocos2d::TrianglesCommand* batchedTriangles = batch->addCommand(renderer, _globalZOrder, attachmentVertices->_texture, _glProgramState, blendFunc, triangles, transform, transformFlags); #else - cocos2d::TrianglesCommand* batchedTriangles = batch->addCommand(renderer, _globalZOrder, attachmentVertices->_texture, blendFunc, triangles, transform, transformFlags); + cocos2d::TrianglesCommand* batchedTriangles = batch->addCommand(renderer, _globalZOrder, attachmentVertices->_texture, _programState, blendFunc, triangles, transform, transformFlags); #endif const float* verts = _clipper->getClippedVertices().buffer(); @@ -465,7 +465,7 @@ void SkeletonRenderer::draw (Renderer* renderer, const Mat4& transform, uint32_t #if COCOS2D_VERSION < 0x00040000 cocos2d::TrianglesCommand* batchedTriangles = batch->addCommand(renderer, _globalZOrder, attachmentVertices->_texture, _glProgramState, blendFunc, triangles, transform, transformFlags); #else - cocos2d::TrianglesCommand* batchedTriangles = batch->addCommand(renderer, _globalZOrder, attachmentVertices->_texture, blendFunc, triangles, transform, transformFlags); + cocos2d::TrianglesCommand* batchedTriangles = batch->addCommand(renderer, _globalZOrder, attachmentVertices->_texture, _programState, blendFunc, triangles, transform, transformFlags); #endif if (_effect) { diff --git a/spine-cocos2dx/src/spine/v4/SkeletonBatch.cpp b/spine-cocos2dx/src/spine/v4/SkeletonBatch.cpp index 2cdf7f017..651e286ca 100644 --- a/spine-cocos2dx/src/spine/v4/SkeletonBatch.cpp +++ b/spine-cocos2dx/src/spine/v4/SkeletonBatch.cpp @@ -40,6 +40,7 @@ using std::max; #include "renderer/ccShaders.h" #include "renderer/backend/Device.h" +#include "renderer/backend/ProgramState.h" namespace spine { @@ -60,22 +61,8 @@ void SkeletonBatch::destroyInstance () { SkeletonBatch::SkeletonBatch () { auto program = backend::Program::getBuiltinProgram(backend::ProgramType::POSITION_TEXTURE_COLOR); - _programState = std::make_shared(program); - - auto vertexLayout = _programState->getVertexLayout(); - - auto locPosition = _programState->getAttributeLocation("a_position"); - auto locTexcoord = _programState->getAttributeLocation("a_texCoord"); - auto locColor = _programState->getAttributeLocation("a_color"); - vertexLayout->setAttribute("a_position", locPosition, backend::VertexFormat::FLOAT3, offsetof(V3F_C4B_T2F, vertices), false); - vertexLayout->setAttribute("a_color", locColor, backend::VertexFormat::UBYTE4, offsetof(V3F_C4B_T2F, colors), true); - vertexLayout->setAttribute("a_texCoord", locTexcoord, backend::VertexFormat::FLOAT2, offsetof(V3F_C4B_T2F, texCoords), false); - vertexLayout->setLayout(sizeof(_vertices[0])); - - - _locMVP = _programState->getUniformLocation("u_MVPMatrix"); - _locTexture = _programState->getUniformLocation("u_texture"); - + _programState = new backend::ProgramState(program); // new default program state + updateProgramStateLayout(_programState); for (unsigned int i = 0; i < INITIAL_SIZE; i++) { _commandsPool.push_back(createNewTrianglesCommand()); } @@ -95,6 +82,25 @@ SkeletonBatch::~SkeletonBatch () { delete _commandsPool[i]; _commandsPool[i] = nullptr; } + + CC_SAFE_RELEASE(_programState); +} + +void SkeletonBatch::updateProgramStateLayout(cocos2d::backend::ProgramState* programState) +{ + auto vertexLayout = programState->getVertexLayout(); + + auto locPosition = programState->getAttributeLocation("a_position"); + auto locTexcoord = programState->getAttributeLocation("a_texCoord"); + auto locColor = programState->getAttributeLocation("a_color"); + vertexLayout->setAttribute("a_position", locPosition, backend::VertexFormat::FLOAT3, offsetof(V3F_C4B_T2F, vertices), false); + vertexLayout->setAttribute("a_color", locColor, backend::VertexFormat::UBYTE4, offsetof(V3F_C4B_T2F, colors), true); + vertexLayout->setAttribute("a_texCoord", locTexcoord, backend::VertexFormat::FLOAT2, offsetof(V3F_C4B_T2F, texCoords), false); + vertexLayout->setLayout(sizeof(_vertices[0])); + + + _locMVP = programState->getUniformLocation("u_MVPMatrix"); + _locTexture = programState->getUniformLocation("u_texture"); } void SkeletonBatch::update (float delta) { @@ -148,15 +154,27 @@ void SkeletonBatch::deallocateIndices(uint32_t numIndices) { } -cocos2d::TrianglesCommand* SkeletonBatch::addCommand(cocos2d::Renderer* renderer, float globalOrder, cocos2d::Texture2D* texture, cocos2d::BlendFunc blendType, const cocos2d::TrianglesCommand::Triangles& triangles, const cocos2d::Mat4& mv, uint32_t flags) { +cocos2d::TrianglesCommand* SkeletonBatch::addCommand(cocos2d::Renderer* renderer, float globalOrder, cocos2d::Texture2D* texture, backend::ProgramState* programState, cocos2d::BlendFunc blendType, const cocos2d::TrianglesCommand::Triangles& triangles, const cocos2d::Mat4& mv, uint32_t flags) { TrianglesCommand* command = nextFreeCommand(); const cocos2d::Mat4& projectionMat = Director::getInstance()->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION); - auto programState = command->getPipelineDescriptor().programState; - CCASSERT(programState, "programState should not be null"); + if (programState == nullptr) + programState = _programState; - programState->setUniform(_locMVP, projectionMat.m, sizeof(projectionMat.m)); - programState->setTexture(_locTexture, 0, texture->getBackendTexture()); + CCASSERT(programState, "programState should not be null"); + + auto& pipelinePS = command->getPipelineDescriptor().programState; + if (pipelinePS != programState) + { + CC_SAFE_RELEASE(pipelinePS); + pipelinePS = programState; + CC_SAFE_RETAIN(pipelinePS); + + updateProgramStateLayout(pipelinePS); + } + + pipelinePS->setUniform(_locMVP, projectionMat.m, sizeof(projectionMat.m)); + pipelinePS->setTexture(_locTexture, 0, texture->getBackendTexture()); command->init(globalOrder, texture, blendType, triangles, mv, flags); renderer->addCommand(command); @@ -177,12 +195,6 @@ cocos2d::TrianglesCommand* SkeletonBatch::nextFreeCommand() { } } auto* command = _commandsPool[_nextFreeCommand++]; - auto& pipelineDescriptor = command->getPipelineDescriptor(); - if (pipelineDescriptor.programState == nullptr) - { - CCASSERT(_programState, "programState should not be null"); - pipelineDescriptor.programState = _programState->clone(); - } return command; } diff --git a/spine-cocos2dx/src/spine/v4/SkeletonBatch.h b/spine-cocos2dx/src/spine/v4/SkeletonBatch.h index d0bae6b5b..7f96ca285 100644 --- a/spine-cocos2dx/src/spine/v4/SkeletonBatch.h +++ b/spine-cocos2dx/src/spine/v4/SkeletonBatch.h @@ -36,6 +36,12 @@ #include #include +namespace cocos2d { + namespace backend { + class ProgramState; + } +} + namespace spine { class SkeletonBatch { @@ -50,8 +56,10 @@ namespace spine { void deallocateVertices(uint32_t numVertices); unsigned short* allocateIndices(uint32_t numIndices); void deallocateIndices(uint32_t numVertices); - cocos2d::TrianglesCommand* addCommand(cocos2d::Renderer* renderer, float globalOrder, cocos2d::Texture2D* texture, cocos2d::BlendFunc blendType, const cocos2d::TrianglesCommand::Triangles& triangles, const cocos2d::Mat4& mv, uint32_t flags); + cocos2d::TrianglesCommand* addCommand(cocos2d::Renderer* renderer, float globalOrder, cocos2d::Texture2D* texture, cocos2d::backend::ProgramState* programState, cocos2d::BlendFunc blendType, const cocos2d::TrianglesCommand::Triangles& triangles, const cocos2d::Mat4& mv, uint32_t flags); + void updateProgramStateLayout(cocos2d::backend::ProgramState* programState); + protected: SkeletonBatch (); virtual ~SkeletonBatch (); @@ -61,7 +69,9 @@ namespace spine { cocos2d::TrianglesCommand* nextFreeCommand (); cocos2d::TrianglesCommand* createNewTrianglesCommand(); - std::shared_ptr _programState = nullptr; + + // the default program state for batch draw + cocos2d::backend::ProgramState* _programState = nullptr; cocos2d::backend::UniformLocation _locMVP; cocos2d::backend::UniformLocation _locTexture; From 5bacfcd733698123667ce2b9abf243686ab8583d Mon Sep 17 00:00:00 2001 From: halx99 Date: Fri, 16 Oct 2020 18:42:45 +0800 Subject: [PATCH 2/3] SkeletonTwoColorBatch also support custom program --- spine-cocos2dx/src/spine/SkeletonRenderer.cpp | 4 +- spine-cocos2dx/src/spine/v4/SkeletonBatch.cpp | 1 - spine-cocos2dx/src/spine/v4/SkeletonBatch.h | 7 +-- .../src/spine/v4/SkeletonTwoColorBatch.cpp | 61 +++++++++++++------ .../src/spine/v4/SkeletonTwoColorBatch.h | 7 ++- 5 files changed, 50 insertions(+), 30 deletions(-) diff --git a/spine-cocos2dx/src/spine/SkeletonRenderer.cpp b/spine-cocos2dx/src/spine/SkeletonRenderer.cpp index dbc521d31..292a16edc 100644 --- a/spine-cocos2dx/src/spine/SkeletonRenderer.cpp +++ b/spine-cocos2dx/src/spine/SkeletonRenderer.cpp @@ -504,7 +504,7 @@ void SkeletonRenderer::draw (Renderer* renderer, const Mat4& transform, uint32_t #if COCOS2D_VERSION < 0x00040000 TwoColorTrianglesCommand* batchedTriangles = lastTwoColorTrianglesCommand = twoColorBatch->addCommand(renderer, _globalZOrder, attachmentVertices->_texture->getName(), _glProgramState, blendFunc, trianglesTwoColor, transform, transformFlags); #else - TwoColorTrianglesCommand* batchedTriangles = lastTwoColorTrianglesCommand = twoColorBatch->addCommand(renderer, _globalZOrder, attachmentVertices->_texture, blendFunc, trianglesTwoColor, transform, transformFlags); + TwoColorTrianglesCommand* batchedTriangles = lastTwoColorTrianglesCommand = twoColorBatch->addCommand(renderer, _globalZOrder, attachmentVertices->_texture, _programState, blendFunc, trianglesTwoColor, transform, transformFlags); #endif const float* verts = _clipper->getClippedVertices().buffer(); @@ -539,7 +539,7 @@ void SkeletonRenderer::draw (Renderer* renderer, const Mat4& transform, uint32_t #if COCOS2D_VERSION < 0x00040000 TwoColorTrianglesCommand* batchedTriangles = lastTwoColorTrianglesCommand = twoColorBatch->addCommand(renderer, _globalZOrder, attachmentVertices->_texture->getName(), _glProgramState, blendFunc, trianglesTwoColor, transform, transformFlags); #else - TwoColorTrianglesCommand* batchedTriangles = lastTwoColorTrianglesCommand = twoColorBatch->addCommand(renderer, _globalZOrder, attachmentVertices->_texture, blendFunc, trianglesTwoColor, transform, transformFlags); + TwoColorTrianglesCommand* batchedTriangles = lastTwoColorTrianglesCommand = twoColorBatch->addCommand(renderer, _globalZOrder, attachmentVertices->_texture, _programState, blendFunc, trianglesTwoColor, transform, transformFlags); #endif if (_effect) { diff --git a/spine-cocos2dx/src/spine/v4/SkeletonBatch.cpp b/spine-cocos2dx/src/spine/v4/SkeletonBatch.cpp index 651e286ca..62e39c192 100644 --- a/spine-cocos2dx/src/spine/v4/SkeletonBatch.cpp +++ b/spine-cocos2dx/src/spine/v4/SkeletonBatch.cpp @@ -40,7 +40,6 @@ using std::max; #include "renderer/ccShaders.h" #include "renderer/backend/Device.h" -#include "renderer/backend/ProgramState.h" namespace spine { diff --git a/spine-cocos2dx/src/spine/v4/SkeletonBatch.h b/spine-cocos2dx/src/spine/v4/SkeletonBatch.h index 7f96ca285..8210521e8 100644 --- a/spine-cocos2dx/src/spine/v4/SkeletonBatch.h +++ b/spine-cocos2dx/src/spine/v4/SkeletonBatch.h @@ -35,12 +35,7 @@ #include #include - -namespace cocos2d { - namespace backend { - class ProgramState; - } -} +#include "renderer/backend/ProgramState.h" namespace spine { diff --git a/spine-cocos2dx/src/spine/v4/SkeletonTwoColorBatch.cpp b/spine-cocos2dx/src/spine/v4/SkeletonTwoColorBatch.cpp index 9dde0ccbc..63a32d0d8 100644 --- a/spine-cocos2dx/src/spine/v4/SkeletonTwoColorBatch.cpp +++ b/spine-cocos2dx/src/spine/v4/SkeletonTwoColorBatch.cpp @@ -99,16 +99,7 @@ namespace { backend::UniformLocation __locPMatrix; backend::UniformLocation __locTexture; - void initTwoColorProgramState() - { - if (__twoColorProgramState) - { - return; - } - auto program = backend::Device::getInstance()->newProgram(TWO_COLOR_TINT_VERTEX_SHADER, TWO_COLOR_TINT_FRAGMENT_SHADER); - auto* programState = new backend::ProgramState(program); - program->autorelease(); - + static void updateProgramStateLayout(backend::ProgramState* programState) { __locPMatrix = programState->getUniformLocation("u_PMatrix"); __locTexture = programState->getUniformLocation("u_texture"); @@ -124,6 +115,19 @@ namespace { layout->setAttribute("a_color2", locColor2, backend::VertexFormat::UBYTE4, offsetof(spine::V3F_C4B_C4B_T2F, color2), true); layout->setAttribute("a_texCoords", locTexcoord, backend::VertexFormat::FLOAT2, offsetof(spine::V3F_C4B_C4B_T2F, texCoords), false); layout->setLayout(sizeof(spine::V3F_C4B_C4B_T2F)); + } + + static void initTwoColorProgramState() + { + if (__twoColorProgramState) + { + return; + } + auto program = backend::Device::getInstance()->newProgram(TWO_COLOR_TINT_VERTEX_SHADER, TWO_COLOR_TINT_FRAGMENT_SHADER); + auto* programState = new backend::ProgramState(program); + program->release(); + + updateProgramStateLayout(programState); __twoColorProgramState = std::shared_ptr(programState); } @@ -136,9 +140,9 @@ TwoColorTrianglesCommand::TwoColorTrianglesCommand() :_materialID(0), _texture(n _type = RenderCommand::Type::CUSTOM_COMMAND; } -void TwoColorTrianglesCommand::init(float globalOrder, cocos2d::Texture2D *texture, BlendFunc blendType, const TwoColorTriangles& triangles, const Mat4& mv, uint32_t flags) { +void TwoColorTrianglesCommand::init(float globalOrder, cocos2d::Texture2D *texture, cocos2d::backend::ProgramState* programState, BlendFunc blendType, const TwoColorTriangles& triangles, const Mat4& mv, uint32_t flags) { - updateCommandPipelineDescriptor(); + updateCommandPipelineDescriptor(programState); const cocos2d::Mat4& projectionMat = Director::getInstance()->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION); auto finalMatrix = projectionMat * mv; @@ -177,18 +181,39 @@ void TwoColorTrianglesCommand::init(float globalOrder, cocos2d::Texture2D *textu -void TwoColorTrianglesCommand::updateCommandPipelineDescriptor() +void TwoColorTrianglesCommand::updateCommandPipelineDescriptor(cocos2d::backend::ProgramState* programState) { + // OPTIMIZE ME: all commands belong a same Node should share a same programState like SkeletonBatch if (!__twoColorProgramState) { initTwoColorProgramState(); } - CC_SAFE_RELEASE_NULL(_programState); - _programState = __twoColorProgramState->clone(); + bool needsUpdateStateLayout = false; + auto& pipelinePS = _pipelineDescriptor.programState; + if (programState != nullptr) + { + if (_programState != programState) { + CC_SAFE_RELEASE(_programState); + _programState = programState; // Because the programState belong to Node, so no need to clone + CC_SAFE_RETAIN(_programState); + needsUpdateStateLayout = true; + } + } + else { + needsUpdateStateLayout = _programState != nullptr && _programState->getProgramType() != __twoColorProgramState->getProgramType(); + CC_SAFE_RELEASE(_programState); + _programState = __twoColorProgramState->clone(); + } + + CCASSERT(_programState, "programState should not be null"); + pipelinePS = _programState; + + if (needsUpdateStateLayout) + updateProgramStateLayout(pipelinePS); + _locPMatrix = __locPMatrix; _locTexture = __locTexture; - _pipelineDescriptor.programState = _programState; } TwoColorTrianglesCommand::~TwoColorTrianglesCommand() @@ -330,9 +355,9 @@ void SkeletonTwoColorBatch::deallocateIndices(uint32_t numIndices) { _indices.setSize(_indices.size() - numIndices, 0); } -TwoColorTrianglesCommand* SkeletonTwoColorBatch::addCommand(cocos2d::Renderer* renderer, float globalOrder, cocos2d::Texture2D* texture, cocos2d::BlendFunc blendType, const TwoColorTriangles& triangles, const cocos2d::Mat4& mv, uint32_t flags) { +TwoColorTrianglesCommand* SkeletonTwoColorBatch::addCommand(cocos2d::Renderer* renderer, float globalOrder, cocos2d::Texture2D* texture, backend::ProgramState* programState, cocos2d::BlendFunc blendType, const TwoColorTriangles& triangles, const cocos2d::Mat4& mv, uint32_t flags) { TwoColorTrianglesCommand* command = nextFreeCommand(); - command->init(globalOrder, texture, blendType, triangles, mv, flags); + command->init(globalOrder, texture, programState, blendType, triangles, mv, flags); command->updateVertexAndIndexBuffer(renderer, triangles.verts, triangles.vertCount, triangles.indices, triangles.indexCount); renderer->addCommand(command); return command; diff --git a/spine-cocos2dx/src/spine/v4/SkeletonTwoColorBatch.h b/spine-cocos2dx/src/spine/v4/SkeletonTwoColorBatch.h index 9d6364b8b..96ec38887 100644 --- a/spine-cocos2dx/src/spine/v4/SkeletonTwoColorBatch.h +++ b/spine-cocos2dx/src/spine/v4/SkeletonTwoColorBatch.h @@ -35,6 +35,7 @@ #include #include +#include "renderer/backend/ProgramState.h" namespace spine { struct V3F_C4B_C4B_T2F { @@ -57,9 +58,9 @@ namespace spine { ~TwoColorTrianglesCommand(); - void init(float globalOrder, cocos2d::Texture2D* texture, cocos2d::BlendFunc blendType, const TwoColorTriangles& triangles, const cocos2d::Mat4& mv, uint32_t flags); + void init(float globalOrder, cocos2d::Texture2D* texture, cocos2d::backend::ProgramState* programState, cocos2d::BlendFunc blendType, const TwoColorTriangles& triangles, const cocos2d::Mat4& mv, uint32_t flags); - void updateCommandPipelineDescriptor(); + void updateCommandPipelineDescriptor(cocos2d::backend::ProgramState* programState); inline cocos2d::backend::TextureBackend* getTexture() const { return _texture; } @@ -118,7 +119,7 @@ namespace spine { unsigned short* allocateIndices(uint32_t numIndices); void deallocateIndices(uint32_t numIndices); - TwoColorTrianglesCommand* addCommand(cocos2d::Renderer* renderer, float globalOrder, cocos2d::Texture2D* texture, cocos2d::BlendFunc blendType, const TwoColorTriangles& triangles, const cocos2d::Mat4& mv, uint32_t flags); + TwoColorTrianglesCommand* addCommand(cocos2d::Renderer* renderer, float globalOrder, cocos2d::Texture2D* texture, cocos2d::backend::ProgramState* programState, cocos2d::BlendFunc blendType, const TwoColorTriangles& triangles, const cocos2d::Mat4& mv, uint32_t flags); void batch(cocos2d::Renderer* renderer, TwoColorTrianglesCommand* command); From 21185a1fc3eeceb89c78caab88e05a9215b0a36f Mon Sep 17 00:00:00 2001 From: halx99 Date: Fri, 16 Oct 2020 18:46:13 +0800 Subject: [PATCH 3/3] fix --- spine-cocos2dx/src/spine/v4/SkeletonTwoColorBatch.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spine-cocos2dx/src/spine/v4/SkeletonTwoColorBatch.cpp b/spine-cocos2dx/src/spine/v4/SkeletonTwoColorBatch.cpp index 63a32d0d8..780274013 100644 --- a/spine-cocos2dx/src/spine/v4/SkeletonTwoColorBatch.cpp +++ b/spine-cocos2dx/src/spine/v4/SkeletonTwoColorBatch.cpp @@ -201,7 +201,7 @@ void TwoColorTrianglesCommand::updateCommandPipelineDescriptor(cocos2d::backend: } } else { - needsUpdateStateLayout = _programState != nullptr && _programState->getProgramType() != __twoColorProgramState->getProgramType(); + needsUpdateStateLayout = _programState != nullptr && _programState->getProgram() != __twoColorProgramState->getProgram(); CC_SAFE_RELEASE(_programState); _programState = __twoColorProgramState->clone(); }