Explorar o código

Merge branch 'custom-program-state' of https://github.com/halx99/spine-runtimes into halx99-custom-program-state

badlogic %!s(int64=4) %!d(string=hai) anos
pai
achega
6cdbcf5c6d

+ 4 - 4
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) {
@@ -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) {

+ 38 - 27
spine-cocos2dx/src/spine/v4/SkeletonBatch.cpp

@@ -60,22 +60,8 @@ void SkeletonBatch::destroyInstance () {
 SkeletonBatch::SkeletonBatch () {
 
     auto program = backend::Program::getBuiltinProgram(backend::ProgramType::POSITION_TEXTURE_COLOR);
-    _programState = std::make_shared<backend::ProgramState>(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 +81,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 +153,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;
+
+	CCASSERT(programState, "programState should not be null");
 
-    programState->setUniform(_locMVP, projectionMat.m, sizeof(projectionMat.m));
-    programState->setTexture(_locTexture, 0, texture->getBackendTexture());
+	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 +194,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;
 }
 

+ 7 - 2
spine-cocos2dx/src/spine/v4/SkeletonBatch.h

@@ -35,6 +35,7 @@
 
 #include <spine/spine.h>
 #include <vector>
+#include "renderer/backend/ProgramState.h"
 
 namespace spine {
     
@@ -50,8 +51,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 +64,9 @@ namespace spine {
 		cocos2d::TrianglesCommand* nextFreeCommand ();
 
         cocos2d::TrianglesCommand* createNewTrianglesCommand();
-        std::shared_ptr<cocos2d::backend::ProgramState>     _programState = nullptr;
+
+        // the default program state for batch draw
+        cocos2d::backend::ProgramState*                     _programState = nullptr;
         cocos2d::backend::UniformLocation                   _locMVP;
         cocos2d::backend::UniformLocation                   _locTexture;
 		

+ 43 - 18
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<backend::ProgramState>(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->getProgram() != __twoColorProgramState->getProgram();
+        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;

+ 4 - 3
spine-cocos2dx/src/spine/v4/SkeletonTwoColorBatch.h

@@ -35,6 +35,7 @@
 
 #include <spine/spine.h>
 #include <vector>
+#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);