mirror of https://github.com/axmolengine/axmol.git
fix: TriangleCommands with custom uniforms can be batched (#16329)
* fix: TriangleCommands with custom uniforms can be batched TriangleCommands with custom uniforms can be batched together. This improves the performance when using custom uniforms without adding any penalties when not using them Github issue #16224 * better tests
This commit is contained in:
parent
0e65025bda
commit
f7464f8de5
|
@ -36,7 +36,6 @@ TrianglesCommand::TrianglesCommand()
|
|||
:_materialID(0)
|
||||
,_textureID(0)
|
||||
,_glProgramState(nullptr)
|
||||
,_glProgram(nullptr)
|
||||
,_blendType(BlendFunc::DISABLE)
|
||||
,_alphaTextureID(0)
|
||||
{
|
||||
|
@ -60,13 +59,11 @@ void TrianglesCommand::init(float globalOrder, GLuint textureID, GLProgramState*
|
|||
_mv = mv;
|
||||
|
||||
if( _textureID != textureID || _blendType.src != blendType.src || _blendType.dst != blendType.dst ||
|
||||
_glProgramState != glProgramState ||
|
||||
_glProgram != glProgramState->getGLProgram())
|
||||
_glProgramState != glProgramState)
|
||||
{
|
||||
_textureID = textureID;
|
||||
_blendType = blendType;
|
||||
_glProgramState = glProgramState;
|
||||
_glProgram = glProgramState->getGLProgram();
|
||||
|
||||
generateMaterialID();
|
||||
}
|
||||
|
@ -89,18 +86,25 @@ TrianglesCommand::~TrianglesCommand()
|
|||
|
||||
void TrianglesCommand::generateMaterialID()
|
||||
{
|
||||
// do not batch if using custom uniforms (since we cannot batch) it
|
||||
if(_glProgramState->getUniformCount() > 0)
|
||||
{
|
||||
_materialID = Renderer::MATERIAL_ID_DO_NOT_BATCH;
|
||||
setSkipBatching(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
int glProgram = (int)_glProgram->getProgram();
|
||||
int intArray[4] = { glProgram, (int)_textureID, (int)_blendType.src, (int)_blendType.dst};
|
||||
_materialID = XXH32((const void*)intArray, sizeof(intArray), 0);
|
||||
}
|
||||
// glProgramState is hashed because it contains:
|
||||
// * uniforms/values
|
||||
// * glProgram
|
||||
//
|
||||
// we safely can when the same glProgramState is being used then they share those states
|
||||
// if they don't have the same glProgramState, they might still have the same
|
||||
// uniforms/values and glProgram, but it would be too expensive to check the uniforms.
|
||||
struct {
|
||||
GLuint textureId;
|
||||
GLenum blendSrc;
|
||||
GLenum blendDst;
|
||||
void* glProgramState;
|
||||
} hashMe;
|
||||
|
||||
hashMe.textureId = _textureID;
|
||||
hashMe.blendSrc = _blendType.src;
|
||||
hashMe.blendDst = _blendType.dst;
|
||||
hashMe.glProgramState = _glProgramState;
|
||||
_materialID = XXH32((const void*)&hashMe, sizeof(hashMe), 0);
|
||||
}
|
||||
|
||||
void TrianglesCommand::useMaterial() const
|
||||
|
|
|
@ -105,8 +105,6 @@ protected:
|
|||
GLuint _textureID;
|
||||
/**GLprogramstate for the command. encapsulate shaders and uniforms.*/
|
||||
GLProgramState* _glProgramState;
|
||||
/**The GLProgram used by GLProgramState*/
|
||||
GLProgram* _glProgram;
|
||||
/**Blend function when rendering the triangles.*/
|
||||
BlendFunc _blendType;
|
||||
/**Rendered triangles.*/
|
||||
|
|
|
@ -38,6 +38,8 @@ NewRendererTests::NewRendererTests()
|
|||
ADD_TEST_CASE(CaptureNodeTest);
|
||||
ADD_TEST_CASE(BugAutoCulling);
|
||||
ADD_TEST_CASE(RendererBatchQuadTri);
|
||||
ADD_TEST_CASE(RendererUniformBatch);
|
||||
ADD_TEST_CASE(RendererUniformBatch2);
|
||||
};
|
||||
|
||||
std::string MultiSceneTest::title() const
|
||||
|
@ -610,3 +612,164 @@ std::string RendererBatchQuadTri::subtitle() const
|
|||
{
|
||||
return "QuadCommand and TriangleCommands are batched together";
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
// RendererUniformBatch
|
||||
//
|
||||
|
||||
RendererUniformBatch::RendererUniformBatch()
|
||||
{
|
||||
Size s = Director::getInstance()->getWinSize();
|
||||
|
||||
auto glBlurState = createBlurGLProgramState();
|
||||
auto glSepiaState = createSepiaGLProgramState();
|
||||
|
||||
auto x_inc = s.width / 20;
|
||||
auto y_inc = s.height / 6;
|
||||
|
||||
for (int y=0; y<6; ++y)
|
||||
{
|
||||
for (int x=0; x<20; ++x)
|
||||
{
|
||||
auto sprite = Sprite::create("Images/grossini.png");
|
||||
sprite->setPosition(Vec2(x * x_inc, y * y_inc));
|
||||
sprite->setScale(0.4);
|
||||
addChild(sprite);
|
||||
|
||||
if (y>=4) {
|
||||
sprite->setGLProgramState(glSepiaState);
|
||||
} else if(y>=2) {
|
||||
sprite->setGLProgramState(glBlurState);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GLProgramState* RendererUniformBatch::createBlurGLProgramState()
|
||||
{
|
||||
#if (CC_TARGET_PLATFORM != CC_PLATFORM_WINRT)
|
||||
const std::string shaderName("Shaders/example_Blur.fsh");
|
||||
#else
|
||||
const std::string shaderName("Shaders/example_Blur_winrt.fsh");
|
||||
#endif
|
||||
// outline shader
|
||||
auto fileUtiles = FileUtils::getInstance();
|
||||
auto fragmentFullPath = fileUtiles->fullPathForFilename(shaderName);
|
||||
auto fragSource = fileUtiles->getStringFromFile(fragmentFullPath);
|
||||
auto glprogram = GLProgram::createWithByteArrays(ccPositionTextureColor_noMVP_vert, fragSource.c_str());
|
||||
auto glprogramstate = (glprogram == nullptr ? nullptr : GLProgramState::getOrCreateWithGLProgram(glprogram));
|
||||
|
||||
glprogramstate->setUniformVec2("resolution", Vec2(85,121));
|
||||
#if (CC_TARGET_PLATFORM != CC_PLATFORM_WINRT)
|
||||
glprogramstate->setUniformFloat("blurRadius", 10);
|
||||
glprogramstate->setUniformFloat("sampleNum", 5);
|
||||
#endif
|
||||
|
||||
return glprogramstate;
|
||||
}
|
||||
|
||||
GLProgramState* RendererUniformBatch::createSepiaGLProgramState()
|
||||
{
|
||||
const std::string shaderName("Shaders/example_Sepia.fsh");
|
||||
|
||||
// outline shader
|
||||
auto fileUtiles = FileUtils::getInstance();
|
||||
auto fragmentFullPath = fileUtiles->fullPathForFilename(shaderName);
|
||||
auto fragSource = fileUtiles->getStringFromFile(fragmentFullPath);
|
||||
auto glprogram = GLProgram::createWithByteArrays(ccPositionTextureColor_noMVP_vert, fragSource.c_str());
|
||||
auto glprogramstate = (glprogram == nullptr ? nullptr : GLProgramState::getOrCreateWithGLProgram(glprogram));
|
||||
|
||||
return glprogramstate;
|
||||
}
|
||||
|
||||
std::string RendererUniformBatch::title() const
|
||||
{
|
||||
return "RendererUniformBatch";
|
||||
}
|
||||
|
||||
std::string RendererUniformBatch::subtitle() const
|
||||
{
|
||||
return "Only 9 draw calls should appear";
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// RendererUniformBatch2
|
||||
//
|
||||
|
||||
RendererUniformBatch2::RendererUniformBatch2()
|
||||
{
|
||||
Size s = Director::getInstance()->getWinSize();
|
||||
|
||||
auto glBlurState = createBlurGLProgramState();
|
||||
auto glSepiaState = createSepiaGLProgramState();
|
||||
|
||||
auto x_inc = s.width / 20;
|
||||
auto y_inc = s.height / 6;
|
||||
|
||||
for (int y=0; y<6; ++y)
|
||||
{
|
||||
for (int x=0; x<20; ++x)
|
||||
{
|
||||
auto sprite = Sprite::create("Images/grossini.png");
|
||||
sprite->setPosition(Vec2(x * x_inc, y * y_inc));
|
||||
sprite->setScale(0.4);
|
||||
addChild(sprite);
|
||||
|
||||
auto r = CCRANDOM_0_1();
|
||||
if (r < 0.33)
|
||||
sprite->setGLProgramState(glSepiaState);
|
||||
else if (r < 0.66)
|
||||
sprite->setGLProgramState(glBlurState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GLProgramState* RendererUniformBatch2::createBlurGLProgramState()
|
||||
{
|
||||
#if (CC_TARGET_PLATFORM != CC_PLATFORM_WINRT)
|
||||
const std::string shaderName("Shaders/example_Blur.fsh");
|
||||
#else
|
||||
const std::string shaderName("Shaders/example_Blur_winrt.fsh");
|
||||
#endif
|
||||
// outline shader
|
||||
auto fileUtiles = FileUtils::getInstance();
|
||||
auto fragmentFullPath = fileUtiles->fullPathForFilename(shaderName);
|
||||
auto fragSource = fileUtiles->getStringFromFile(fragmentFullPath);
|
||||
auto glprogram = GLProgram::createWithByteArrays(ccPositionTextureColor_noMVP_vert, fragSource.c_str());
|
||||
auto glprogramstate = (glprogram == nullptr ? nullptr : GLProgramState::getOrCreateWithGLProgram(glprogram));
|
||||
|
||||
glprogramstate->setUniformVec2("resolution", Vec2(85,121));
|
||||
#if (CC_TARGET_PLATFORM != CC_PLATFORM_WINRT)
|
||||
glprogramstate->setUniformFloat("blurRadius", 10);
|
||||
glprogramstate->setUniformFloat("sampleNum", 5);
|
||||
#endif
|
||||
|
||||
return glprogramstate;
|
||||
}
|
||||
|
||||
GLProgramState* RendererUniformBatch2::createSepiaGLProgramState()
|
||||
{
|
||||
const std::string shaderName("Shaders/example_Sepia.fsh");
|
||||
|
||||
// outline shader
|
||||
auto fileUtiles = FileUtils::getInstance();
|
||||
auto fragmentFullPath = fileUtiles->fullPathForFilename(shaderName);
|
||||
auto fragSource = fileUtiles->getStringFromFile(fragmentFullPath);
|
||||
auto glprogram = GLProgram::createWithByteArrays(ccPositionTextureColor_noMVP_vert, fragSource.c_str());
|
||||
auto glprogramstate = (glprogram == nullptr ? nullptr : GLProgramState::getOrCreateWithGLProgram(glprogram));
|
||||
|
||||
return glprogramstate;
|
||||
}
|
||||
|
||||
std::string RendererUniformBatch2::title() const
|
||||
{
|
||||
return "RendererUniformBatch 2";
|
||||
}
|
||||
|
||||
std::string RendererUniformBatch2::subtitle() const
|
||||
{
|
||||
return "Mixing different shader states should work ok";
|
||||
}
|
||||
|
|
|
@ -166,4 +166,30 @@ protected:
|
|||
RendererBatchQuadTri();
|
||||
};
|
||||
|
||||
class RendererUniformBatch : public MultiSceneTest
|
||||
{
|
||||
public:
|
||||
CREATE_FUNC(RendererUniformBatch);
|
||||
virtual std::string title() const override;
|
||||
virtual std::string subtitle() const override;
|
||||
protected:
|
||||
RendererUniformBatch();
|
||||
|
||||
cocos2d::GLProgramState* createBlurGLProgramState();
|
||||
cocos2d::GLProgramState* createSepiaGLProgramState();
|
||||
};
|
||||
|
||||
class RendererUniformBatch2 : public MultiSceneTest
|
||||
{
|
||||
public:
|
||||
CREATE_FUNC(RendererUniformBatch2);
|
||||
virtual std::string title() const override;
|
||||
virtual std::string subtitle() const override;
|
||||
protected:
|
||||
RendererUniformBatch2();
|
||||
|
||||
cocos2d::GLProgramState* createBlurGLProgramState();
|
||||
cocos2d::GLProgramState* createSepiaGLProgramState();
|
||||
};
|
||||
|
||||
#endif //__NewRendererTest_H_
|
||||
|
|
Loading…
Reference in New Issue