fix render pipeline (#20041)

This commit is contained in:
coulsonwang 2019-08-19 10:12:00 +08:00 committed by minggo
parent 3c08471bab
commit 1e8f6d24ac
28 changed files with 299 additions and 647 deletions

View File

@ -25,7 +25,6 @@
#include "platform/CCPlatformMacros.h" #include "platform/CCPlatformMacros.h"
#include "renderer/backend/DepthStencilState.h" #include "renderer/backend/DepthStencilState.h"
#include "renderer/backend/BlendState.h"
#include "renderer/backend/Texture.h" #include "renderer/backend/Texture.h"
#include "renderer/backend/VertexLayout.h" #include "renderer/backend/VertexLayout.h"
#include "renderer/backend/RenderPassDescriptor.h" #include "renderer/backend/RenderPassDescriptor.h"

View File

@ -168,8 +168,6 @@ Renderer::Renderer()
// for the batched TriangleCommand // for the batched TriangleCommand
_triBatchesToDraw = (TriBatchToDraw*) malloc(sizeof(_triBatchesToDraw[0]) * _triBatchesToDrawCapacity); _triBatchesToDraw = (TriBatchToDraw*) malloc(sizeof(_triBatchesToDraw[0]) * _triBatchesToDrawCapacity);
_renderPipelineCache.reserve(100);
} }
Renderer::~Renderer() Renderer::~Renderer()
@ -180,12 +178,7 @@ Renderer::~Renderer()
free(_triBatchesToDraw); free(_triBatchesToDraw);
CC_SAFE_RELEASE(_commandBuffer); CC_SAFE_RELEASE(_commandBuffer);
CC_SAFE_RELEASE(_renderPipeline);
for (auto pipeline :_renderPipelineCache)
{
pipeline.second->release();
}
_renderPipelineCache.clear();
} }
void Renderer::init() void Renderer::init()
@ -197,6 +190,8 @@ void Renderer::init()
auto device = backend::Device::getInstance(); auto device = backend::Device::getInstance();
_commandBuffer = device->newCommandBuffer(); _commandBuffer = device->newCommandBuffer();
_renderPipeline = device->newRenderPipeline();
_commandBuffer->setRenderPipeline(_renderPipeline);
} }
void Renderer::addCommand(RenderCommand* command) void Renderer::addCommand(RenderCommand* command)
@ -752,113 +747,20 @@ bool Renderer::checkVisibility(const Mat4 &transform, const Size &size)
return ret; return ret;
} }
backend::RenderPipeline* Renderer::getRenderPipeline(const backend::RenderPipelineDescriptor& renderPipelineDescriptor, const backend::BlendDescriptor blendDescriptor)
{
struct
{
void* program;
unsigned int vertexLayoutInfo[32];
backend::PixelFormat colorAttachment;
backend::PixelFormat depthAttachment;
backend::PixelFormat stencilAttachment;
bool blendEnabled;
unsigned int writeMask;
unsigned int rgbBlendOperation;
unsigned int alphaBlendOperation;
unsigned int sourceRGBBlendFactor;
unsigned int destinationRGBBlendFactor;
unsigned int sourceAlphaBlendFactor;
unsigned int destinationAlphaBlendFactor;
}hashMe;
memset(&hashMe, 0, sizeof(hashMe));
hashMe.program = renderPipelineDescriptor.programState->getProgram();
hashMe.colorAttachment = renderPipelineDescriptor.colorAttachmentsFormat[0];
hashMe.depthAttachment = renderPipelineDescriptor.depthAttachmentFormat;
hashMe.stencilAttachment = renderPipelineDescriptor.stencilAttachmentFormat;
hashMe.blendEnabled = blendDescriptor.blendEnabled;
hashMe.writeMask = (unsigned int)blendDescriptor.writeMask;
hashMe.rgbBlendOperation = (unsigned int)blendDescriptor.rgbBlendOperation;
hashMe.alphaBlendOperation = (unsigned int)blendDescriptor.alphaBlendOperation;
hashMe.sourceRGBBlendFactor = (unsigned int)blendDescriptor.sourceRGBBlendFactor;
hashMe.destinationRGBBlendFactor = (unsigned int)blendDescriptor.destinationRGBBlendFactor;
hashMe.sourceAlphaBlendFactor = (unsigned int)blendDescriptor.sourceAlphaBlendFactor;
hashMe.destinationAlphaBlendFactor = (unsigned int)blendDescriptor.destinationAlphaBlendFactor;
int index = 0;
auto vertexLayout = renderPipelineDescriptor.programState->getVertexLayout();
const auto& attributes = vertexLayout->getAttributes();
for (const auto& it : attributes)
{
auto &attribute = it.second;
/*
stepFunction:1 stride:15 offest:10 format:5 needNormalized:1
bit31 bit30 ~ bit16 bit15 ~ bit6 bit5 ~ bit1 bit0
*/
hashMe.vertexLayoutInfo[index++] =
((unsigned int)vertexLayout->getVertexStepMode() & 0x1) << 31 |
((unsigned int)(vertexLayout->getStride() & 0x7FFF)) << 16 |
((unsigned int)attribute.offset & 0x3FF) << 6 |
((unsigned int)attribute.format & 0x1F) << 1 |
((unsigned int)attribute.needToBeNormallized & 0x1);
}
unsigned int hash = XXH32((const void*)&hashMe, sizeof(hashMe), 0);
auto iter = _renderPipelineCache.find(hash);
if (_renderPipelineCache.end() == iter)
{
auto renderPipeline = backend::Device::getInstance()->newRenderPipeline(renderPipelineDescriptor);
_renderPipelineCache.emplace(hash, renderPipeline);
return renderPipeline;
}
else
{
return iter->second;
}
}
void Renderer::setRenderPipeline(const PipelineDescriptor& pipelineDescriptor, const backend::RenderPassDescriptor& renderPassDescriptor) void Renderer::setRenderPipeline(const PipelineDescriptor& pipelineDescriptor, const backend::RenderPassDescriptor& renderPassDescriptor)
{ {
backend::RenderPipelineDescriptor renderPipelineDescriptor;
renderPipelineDescriptor.programState = pipelineDescriptor.programState;
auto device = backend::Device::getInstance(); auto device = backend::Device::getInstance();
auto blendState = device->createBlendState(pipelineDescriptor.blendDescriptor); _renderPipeline->update(pipelineDescriptor, renderPassDescriptor);
renderPipelineDescriptor.blendState = blendState;
if (renderPassDescriptor.needColorAttachment)
{
// FIXME: now just handle color attachment 0.
if (renderPassDescriptor.colorAttachmentsTexture[0])
renderPipelineDescriptor.colorAttachmentsFormat[0] = renderPassDescriptor.colorAttachmentsTexture[0]->getTextureFormat();
}
backend::DepthStencilState* depthStencilState = nullptr; backend::DepthStencilState* depthStencilState = nullptr;
auto needDepthStencilAttachment = renderPassDescriptor.depthTestEnabled || renderPassDescriptor.stencilTestEnabled; auto needDepthStencilAttachment = renderPassDescriptor.depthTestEnabled || renderPassDescriptor.stencilTestEnabled;
if (needDepthStencilAttachment) if (needDepthStencilAttachment)
{ {
depthStencilState = device->createDepthStencilState(_depthStencilDescriptor); depthStencilState = device->createDepthStencilState(_depthStencilDescriptor);
if(renderPassDescriptor.depthAttachmentTexture)
{
renderPipelineDescriptor.depthAttachmentFormat = renderPassDescriptor.depthAttachmentTexture->getTextureFormat();
}
else
{
renderPipelineDescriptor.depthAttachmentFormat = PixelFormat::D24S8;
}
if (renderPassDescriptor.stencilAttachmentTexture)
{
renderPipelineDescriptor.stencilAttachmentFormat = renderPassDescriptor.stencilAttachmentTexture->getTextureFormat();
}
else
{
renderPipelineDescriptor.stencilAttachmentFormat = PixelFormat::D24S8;
}
} }
_commandBuffer->setRenderPipeline(getRenderPipeline(renderPipelineDescriptor, pipelineDescriptor.blendDescriptor));
_commandBuffer->setDepthStencilState(depthStencilState); _commandBuffer->setDepthStencilState(depthStencilState);
#ifdef CC_USE_METAL
_commandBuffer->setRenderPipeline(_renderPipeline);
#endif
} }
void Renderer::beginRenderPass(RenderCommand* cmd) void Renderer::beginRenderPass(RenderCommand* cmd)

View File

@ -480,13 +480,11 @@ protected:
*/ */
void setRenderPipeline(const PipelineDescriptor&, const backend::RenderPassDescriptor&); void setRenderPipeline(const PipelineDescriptor&, const backend::RenderPassDescriptor&);
backend::RenderPipeline* getRenderPipeline(const backend::RenderPipelineDescriptor& renderPipelineDescriptor, const backend::BlendDescriptor blendDescriptor);
void pushStateBlock(); void pushStateBlock();
void popStateBlock(); void popStateBlock();
std::unordered_map<unsigned int, backend::RenderPipeline*> _renderPipelineCache; backend::RenderPipeline* _renderPipeline = nullptr;
Viewport _viewport; Viewport _viewport;
CullMode _cullMode = CullMode::NONE; CullMode _cullMode = CullMode::NONE;

View File

@ -21,7 +21,6 @@ set(COCOS_RENDERER_HEADER
renderer/ccShaders.h renderer/ccShaders.h
renderer/backend/Backend.h renderer/backend/Backend.h
renderer/backend/BlendState.h
renderer/backend/Buffer.h renderer/backend/Buffer.h
renderer/backend/CommandBuffer.h renderer/backend/CommandBuffer.h
renderer/backend/DepthStencilState.h renderer/backend/DepthStencilState.h
@ -61,7 +60,6 @@ set(COCOS_RENDERER_SRC
renderer/CCTrianglesCommand.cpp renderer/CCTrianglesCommand.cpp
renderer/ccShaders.cpp renderer/ccShaders.cpp
renderer/backend/BlendState.cpp
renderer/backend/CommandBuffer.cpp renderer/backend/CommandBuffer.cpp
renderer/backend/DepthStencilState.cpp renderer/backend/DepthStencilState.cpp
renderer/backend/Device.cpp renderer/backend/Device.cpp
@ -92,7 +90,6 @@ list(APPEND COCOS_RENDERER_HEADER
) )
list(APPEND COCOS_RENDERER_SRC list(APPEND COCOS_RENDERER_SRC
renderer/backend/opengl/BlendStateGL.cpp
renderer/backend/opengl/BufferGL.cpp renderer/backend/opengl/BufferGL.cpp
renderer/backend/opengl/CommandBufferGL.cpp renderer/backend/opengl/CommandBufferGL.cpp
renderer/backend/opengl/DepthStencilStateGL.cpp renderer/backend/opengl/DepthStencilStateGL.cpp
@ -108,7 +105,6 @@ list(APPEND COCOS_RENDERER_SRC
else() else()
list(APPEND COCOS_RENDERER_HEADER list(APPEND COCOS_RENDERER_HEADER
renderer/backend/metal/BlendStateMTL.h
renderer/backend/metal/BufferMTL.h renderer/backend/metal/BufferMTL.h
renderer/backend/metal/BufferManager.h renderer/backend/metal/BufferManager.h
renderer/backend/metal/CommandBufferMTL.h renderer/backend/metal/CommandBufferMTL.h
@ -123,7 +119,6 @@ list(APPEND COCOS_RENDERER_HEADER
) )
list(APPEND COCOS_RENDERER_SRC list(APPEND COCOS_RENDERER_SRC
renderer/backend/metal/BlendStateMTL.mm
renderer/backend/metal/BufferMTL.mm renderer/backend/metal/BufferMTL.mm
renderer/backend/metal/BufferManager.mm renderer/backend/metal/BufferManager.mm
renderer/backend/metal/CommandBufferMTL.mm renderer/backend/metal/CommandBufferMTL.mm

View File

@ -34,4 +34,3 @@
#include "renderer/backend/VertexLayout.h" #include "renderer/backend/VertexLayout.h"
#include "renderer/backend/Texture.h" #include "renderer/backend/Texture.h"
#include "renderer/backend/DepthStencilState.h" #include "renderer/backend/DepthStencilState.h"
#include "renderer/backend/BlendState.h"

View File

@ -1,29 +0,0 @@
/****************************************************************************
Copyright (c) 2018-2019 Xiamen Yaji Software Co., Ltd.
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "BlendState.h"
CC_BACKEND_BEGIN
CC_BACKEND_END

View File

@ -1,68 +0,0 @@
/****************************************************************************
Copyright (c) 2018-2019 Xiamen Yaji Software Co., Ltd.
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "Macros.h"
#include "Types.h"
#include "base/CCRef.h"
CC_BACKEND_BEGIN
/**
* @addtogroup _backend
* @{
*/
/**
* @brief a structor to store blend descriptor
*/
struct BlendDescriptor
{
ColorWriteMask writeMask = ColorWriteMask::ALL;
bool blendEnabled = false;
BlendOperation rgbBlendOperation = BlendOperation::ADD;
BlendOperation alphaBlendOperation = BlendOperation::ADD;
BlendFactor sourceRGBBlendFactor = BlendFactor::ONE;
BlendFactor destinationRGBBlendFactor = BlendFactor::ZERO;
BlendFactor sourceAlphaBlendFactor = BlendFactor::ONE;
BlendFactor destinationAlphaBlendFactor = BlendFactor::ZERO;
};
/**
* @brief a class of blend state
*/
class BlendState : public cocos2d::Ref
{
protected:
/// @name Constructor, Destructor and Initializers
virtual ~BlendState() = default;
};
// end of _backend group
/// @}
CC_BACKEND_END

View File

@ -30,7 +30,6 @@
#include "RenderPassDescriptor.h" #include "RenderPassDescriptor.h"
#include "Texture.h" #include "Texture.h"
#include "DepthStencilState.h" #include "DepthStencilState.h"
#include "BlendState.h"
#include "ProgramCache.h" #include "ProgramCache.h"
#include "ShaderCache.h" #include "ShaderCache.h"
#include "DeviceInfo.h" #include "DeviceInfo.h"
@ -97,19 +96,12 @@ public:
*/ */
virtual DepthStencilState* createDepthStencilState(const DepthStencilDescriptor& descriptor) = 0; virtual DepthStencilState* createDepthStencilState(const DepthStencilDescriptor& descriptor) = 0;
/**
* Create an auto released BlendState object.
* @param descriptor Specifies blend description.
* @return An auto release BlendState object.
*/
virtual BlendState* createBlendState(const BlendDescriptor& descriptor) = 0;
/** /**
* New a RenderPipeline object, not auto released. * New a RenderPipeline object, not auto released.
* @param descriptor Specifies render pipeline description. * @param descriptor Specifies render pipeline description.
* @return A RenderPipeline object. * @return A RenderPipeline object.
*/ */
virtual RenderPipeline* newRenderPipeline(const RenderPipelineDescriptor& descriptor) = 0; virtual RenderPipeline* newRenderPipeline() = 0;
/** /**
* This property controls whether or not the drawables' * This property controls whether or not the drawables'

View File

@ -39,6 +39,7 @@
CC_BACKEND_BEGIN CC_BACKEND_BEGIN
class TextureBackend; class TextureBackend;
class VertexLayout;
/** /**
* @addtogroup _backend * @addtogroup _backend

View File

@ -45,6 +45,7 @@ struct RenderPassDescriptor
{ {
RenderPassDescriptor& operator=(const RenderPassDescriptor& descriptor); RenderPassDescriptor& operator=(const RenderPassDescriptor& descriptor);
bool operator==(const RenderPassDescriptor& descriptor) const; bool operator==(const RenderPassDescriptor& descriptor) const;
bool needDepthStencilAttachment() const { return depthTestEnabled || stencilTestEnabled; }
float clearDepthValue = 0.f; float clearDepthValue = 0.f;
float clearStencilValue = 0.f; float clearStencilValue = 0.f;

View File

@ -27,9 +27,10 @@
#include "Macros.h" #include "Macros.h"
#include "Types.h" #include "Types.h"
#include "base/CCRef.h" #include "base/CCRef.h"
#include "renderer/CCPipelineDescriptor.h"
#include "renderer/backend/RenderPassDescriptor.h"
CC_BACKEND_BEGIN CC_BACKEND_BEGIN
/** /**
* @addtogroup _backend * @addtogroup _backend
* @{ * @{
@ -40,6 +41,9 @@ CC_BACKEND_BEGIN
*/ */
class RenderPipeline : public cocos2d::Ref class RenderPipeline : public cocos2d::Ref
{ {
public:
virtual void update(const PipelineDescriptor & pipelineDescirptor, const RenderPassDescriptor& renderpassDescriptor) = 0;
protected: protected:
virtual ~RenderPipeline() = default; virtual ~RenderPipeline() = default;
}; };

View File

@ -365,4 +365,22 @@ static const char* ATTRIBUTE_NAME_TEXCOORD = "a_texCoord";
static const char* ATTRIBUTE_NAME_TEXCOORD1 = "a_texCoord1"; static const char* ATTRIBUTE_NAME_TEXCOORD1 = "a_texCoord1";
static const char* ATTRIBUTE_NAME_TEXCOORD2 = "a_texCoord2"; static const char* ATTRIBUTE_NAME_TEXCOORD2 = "a_texCoord2";
static const char* ATTRIBUTE_NAME_TEXCOORD3 = "a_texCoord3"; static const char* ATTRIBUTE_NAME_TEXCOORD3 = "a_texCoord3";
/**
* @brief a structor to store blend descriptor
*/
struct BlendDescriptor
{
ColorWriteMask writeMask = ColorWriteMask::ALL;
bool blendEnabled = false;
BlendOperation rgbBlendOperation = BlendOperation::ADD;
BlendOperation alphaBlendOperation = BlendOperation::ADD;
BlendFactor sourceRGBBlendFactor = BlendFactor::ONE;
BlendFactor destinationRGBBlendFactor = BlendFactor::ZERO;
BlendFactor sourceAlphaBlendFactor = BlendFactor::ONE;
BlendFactor destinationAlphaBlendFactor = BlendFactor::ZERO;
};
CC_BACKEND_END CC_BACKEND_END

View File

@ -1,78 +0,0 @@
/****************************************************************************
Copyright (c) 2018-2019 Xiamen Yaji Software Co., Ltd.
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "../BlendState.h"
#import <Metal/Metal.h>
CC_BACKEND_BEGIN
/**
* @addtogroup _metal
* @{
*/
/**
* @brief Blend descriptor
*/
struct BlendDescriptorMTL
{
MTLColorWriteMask writeMask = MTLColorWriteMaskAll;
bool blendEnabled = false;
MTLBlendOperation rgbBlendOperation = MTLBlendOperationAdd;
MTLBlendOperation alphaBlendOperation = MTLBlendOperationAdd;
MTLBlendFactor sourceRGBBlendFactor = MTLBlendFactorOne;
MTLBlendFactor destinationRGBBlendFactor = MTLBlendFactorZero;
MTLBlendFactor sourceAlphaBlendFactor = MTLBlendFactorOne;
MTLBlendFactor destinationAlphaBlendFactor = MTLBlendFactorZero;
};
/**
* @brief a class of BlendStateMTL
*/
class BlendStateMTL : public BlendState
{
public:
/// @name Constructor, Destructor and Initializers
BlendStateMTL(const BlendDescriptor& descriptor);
/// @name Setters & Getters
/**
* @brief get blend descritptor
* @return return a const reference of BlendDescriptorMTL
*/
inline const BlendDescriptorMTL& getBlendDescriptorMTL() const { return _blendDescriptorMTL; }
private:
BlendDescriptorMTL _blendDescriptorMTL;
};
// end of metal group
/** @}*/
CC_BACKEND_END

View File

@ -1,107 +0,0 @@
/****************************************************************************
Copyright (c) 2018-2019 Xiamen Yaji Software Co., Ltd.
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "BlendStateMTL.h"
CC_BACKEND_BEGIN
namespace
{
MTLColorWriteMask toMTLColorWriteMask(ColorWriteMask mask)
{
switch (mask) {
case ColorWriteMask::NONE:
return MTLColorWriteMaskNone;
case ColorWriteMask::RED:
return MTLColorWriteMaskRed;
case ColorWriteMask::GREEN:
return MTLColorWriteMaskGreen;
case ColorWriteMask::BLUE:
return MTLColorWriteMaskBlue;
case ColorWriteMask::ALPHA:
return MTLColorWriteMaskAlpha;
case ColorWriteMask::ALL:
return MTLColorWriteMaskAll;
}
}
MTLBlendFactor toMTLBlendFactor(BlendFactor factor)
{
switch (factor) {
case BlendFactor::ZERO:
return MTLBlendFactorZero;
case BlendFactor::ONE:
return MTLBlendFactorOne;
case BlendFactor::SRC_COLOR:
return MTLBlendFactorSourceColor;
case BlendFactor::ONE_MINUS_SRC_COLOR:
return MTLBlendFactorOneMinusSourceColor;
case BlendFactor::SRC_ALPHA:
return MTLBlendFactorSourceAlpha;
case BlendFactor::ONE_MINUS_SRC_ALPHA:
return MTLBlendFactorOneMinusSourceAlpha;
case BlendFactor::DST_COLOR:
return MTLBlendFactorDestinationColor;
case BlendFactor::ONE_MINUS_DST_COLOR:
return MTLBlendFactorOneMinusDestinationColor;
case BlendFactor::DST_ALPHA:
return MTLBlendFactorDestinationAlpha;
case BlendFactor::ONE_MINUS_DST_ALPHA:
return MTLBlendFactorOneMinusDestinationAlpha;
case BlendFactor::SRC_ALPHA_SATURATE:
return MTLBlendFactorSourceAlphaSaturated;
case BlendFactor::BLEND_CLOLOR:
return MTLBlendFactorBlendColor;
}
}
MTLBlendOperation toMTLBlendOperation(BlendOperation operation)
{
switch (operation) {
case BlendOperation::ADD:
return MTLBlendOperationAdd;
case BlendOperation::SUBTRACT:
return MTLBlendOperationSubtract;
case BlendOperation::RESERVE_SUBTRACT:
return MTLBlendOperationReverseSubtract;
}
}
}
BlendStateMTL::BlendStateMTL(const BlendDescriptor& descriptor)
{
_blendDescriptorMTL.writeMask = toMTLColorWriteMask(descriptor.writeMask);
_blendDescriptorMTL.blendEnabled = descriptor.blendEnabled;
_blendDescriptorMTL.rgbBlendOperation = toMTLBlendOperation(descriptor.rgbBlendOperation);
_blendDescriptorMTL.alphaBlendOperation = toMTLBlendOperation(descriptor.alphaBlendOperation);
_blendDescriptorMTL.sourceRGBBlendFactor = toMTLBlendFactor(descriptor.sourceRGBBlendFactor);
_blendDescriptorMTL.destinationRGBBlendFactor = toMTLBlendFactor(descriptor.destinationRGBBlendFactor);
_blendDescriptorMTL.sourceAlphaBlendFactor = toMTLBlendFactor(descriptor.sourceAlphaBlendFactor);
_blendDescriptorMTL.destinationAlphaBlendFactor = toMTLBlendFactor(descriptor.destinationAlphaBlendFactor);
}
CC_BACKEND_END

View File

@ -136,7 +136,7 @@ namespace
mtlDescritpor.colorAttachments[0].storeAction = MTLStoreActionStore; mtlDescritpor.colorAttachments[0].storeAction = MTLStoreActionStore;
} }
if(descriptor.depthTestEnabled || descriptor.stencilTestEnabled) if(descriptor.needDepthStencilAttachment())
{ {
// Set depth attachment // Set depth attachment
{ {

View File

@ -103,19 +103,12 @@ public:
*/ */
virtual DepthStencilState* createDepthStencilState(const DepthStencilDescriptor& descriptor) override; virtual DepthStencilState* createDepthStencilState(const DepthStencilDescriptor& descriptor) override;
/**
* Create a BlendState object.
* @param descriptor Specifies blend description.
* @return An auto release BlendState object.
*/
virtual BlendState* createBlendState(const BlendDescriptor& descriptor) override;
/** /**
* New a RenderPipeline object. * New a RenderPipeline object.
* @param descriptor Specifies render pipeline description. * @param descriptor Specifies render pipeline description.
* @return A RenderPipeline object. * @return A RenderPipeline object.
*/ */
virtual RenderPipeline* newRenderPipeline(const RenderPipelineDescriptor& descriptor) override; virtual RenderPipeline* newRenderPipeline() override;
/** /**
* This property controls whether or not the drawables' * This property controls whether or not the drawables'

View File

@ -29,7 +29,6 @@
#include "ShaderModuleMTL.h" #include "ShaderModuleMTL.h"
#include "DepthStencilStateMTL.h" #include "DepthStencilStateMTL.h"
#include "TextureMTL.h" #include "TextureMTL.h"
#include "BlendStateMTL.h"
#include "Utils.h" #include "Utils.h"
#include "ProgramMTL.h" #include "ProgramMTL.h"
#include "DeviceInfoMTL.h" #include "DeviceInfoMTL.h"
@ -124,18 +123,9 @@ DepthStencilState* DeviceMTL::createDepthStencilState(const DepthStencilDescript
return ret; return ret;
} }
BlendState* DeviceMTL::createBlendState(const BlendDescriptor& descriptor) RenderPipeline* DeviceMTL::newRenderPipeline()
{ {
auto ret = new (std::nothrow) BlendStateMTL(descriptor); return new (std::nothrow) RenderPipelineMTL(_mtlDevice);
if (ret)
ret->autorelease();
return ret;
}
RenderPipeline* DeviceMTL::newRenderPipeline(const RenderPipelineDescriptor& descriptor)
{
return new (std::nothrow) RenderPipelineMTL(_mtlDevice, descriptor);
} }
Program* DeviceMTL::newProgram(const std::string& vertexShader, const std::string& fragmentShader) Program* DeviceMTL::newProgram(const std::string& vertexShader, const std::string& fragmentShader)

View File

@ -26,7 +26,6 @@
#include "../RenderPipeline.h" #include "../RenderPipeline.h"
#include "../RenderPipelineDescriptor.h" #include "../RenderPipelineDescriptor.h"
#include "BlendStateMTL.h"
#include <string> #include <string>
#include <vector> #include <vector>
#include <memory> #include <memory>
@ -48,8 +47,9 @@ public:
* @param mtlDevice The device for which MTLRenderPipelineState object was created. * @param mtlDevice The device for which MTLRenderPipelineState object was created.
* @param descriptor Specify the render pipeline description. * @param descriptor Specify the render pipeline description.
*/ */
RenderPipelineMTL(id<MTLDevice> mtlDevice, const RenderPipelineDescriptor& descriptor); RenderPipelineMTL(id<MTLDevice> mtlDevice);
~RenderPipelineMTL(); ~RenderPipelineMTL();
virtual void update(const PipelineDescriptor&, const RenderPassDescriptor&) override;
/** /**
* Get a MTLRenderPipelineState object. * Get a MTLRenderPipelineState object.
@ -58,16 +58,20 @@ public:
inline id<MTLRenderPipelineState> getMTLRenderPipelineState() const { return _mtlRenderPipelineState; } inline id<MTLRenderPipelineState> getMTLRenderPipelineState() const { return _mtlRenderPipelineState; }
private: private:
void setVertexLayout(MTLRenderPipelineDescriptor*, const RenderPipelineDescriptor&); void setVertexLayout(MTLRenderPipelineDescriptor*, const PipelineDescriptor&);
void setBlendState(MTLRenderPipelineColorAttachmentDescriptor*); void setBlendState(MTLRenderPipelineColorAttachmentDescriptor*, const BlendDescriptor&);
void setShaderModules(const RenderPipelineDescriptor&); void setShaderModules(const PipelineDescriptor&);
void setBlendStateAndFormat(const RenderPipelineDescriptor&); void setBlendStateAndFormat(const BlendDescriptor&, const RenderPassDescriptor&);
void getAttachmentFormat(const RenderPassDescriptor&, PixelFormat&, PixelFormat&, PixelFormat&);
id<MTLRenderPipelineState> _mtlRenderPipelineState = nil; id<MTLRenderPipelineState> _mtlRenderPipelineState = nil;
id<MTLDevice> _mtlDevice = nil; id<MTLDevice> _mtlDevice = nil;
MTLRenderPipelineDescriptor* _mtlRenderPipelineDescriptor = nil; MTLRenderPipelineDescriptor* _mtlRenderPipelineDescriptor = nil;
BlendDescriptorMTL _blendDescriptorMTL; PixelFormat _colorAttachmentsFormat[MAX_COLOR_ATTCHMENT] = { PixelFormat::DEFAULT };
PixelFormat _depthAttachmentFormat = PixelFormat::NONE;
PixelFormat _stencilAttachmentFormat = PixelFormat::NONE;
NSMutableDictionary* _mtlRenderPipelineStateCache = nil;
}; };
// end of _metal group // end of _metal group

View File

@ -28,6 +28,7 @@
#include "DepthStencilStateMTL.h" #include "DepthStencilStateMTL.h"
#include "Utils.h" #include "Utils.h"
#include "ProgramMTL.h" #include "ProgramMTL.h"
#include "xxhash.h"
CC_BACKEND_BEGIN CC_BACKEND_BEGIN
@ -88,36 +89,164 @@ namespace
} }
return ret; return ret;
} }
MTLColorWriteMask toMTLColorWriteMask(ColorWriteMask mask)
{
switch (mask) {
case ColorWriteMask::NONE:
return MTLColorWriteMaskNone;
case ColorWriteMask::RED:
return MTLColorWriteMaskRed;
case ColorWriteMask::GREEN:
return MTLColorWriteMaskGreen;
case ColorWriteMask::BLUE:
return MTLColorWriteMaskBlue;
case ColorWriteMask::ALPHA:
return MTLColorWriteMaskAlpha;
case ColorWriteMask::ALL:
return MTLColorWriteMaskAll;
}
}
MTLBlendFactor toMTLBlendFactor(BlendFactor factor)
{
switch (factor) {
case BlendFactor::ZERO:
return MTLBlendFactorZero;
case BlendFactor::ONE:
return MTLBlendFactorOne;
case BlendFactor::SRC_COLOR:
return MTLBlendFactorSourceColor;
case BlendFactor::ONE_MINUS_SRC_COLOR:
return MTLBlendFactorOneMinusSourceColor;
case BlendFactor::SRC_ALPHA:
return MTLBlendFactorSourceAlpha;
case BlendFactor::ONE_MINUS_SRC_ALPHA:
return MTLBlendFactorOneMinusSourceAlpha;
case BlendFactor::DST_COLOR:
return MTLBlendFactorDestinationColor;
case BlendFactor::ONE_MINUS_DST_COLOR:
return MTLBlendFactorOneMinusDestinationColor;
case BlendFactor::DST_ALPHA:
return MTLBlendFactorDestinationAlpha;
case BlendFactor::ONE_MINUS_DST_ALPHA:
return MTLBlendFactorOneMinusDestinationAlpha;
case BlendFactor::SRC_ALPHA_SATURATE:
return MTLBlendFactorSourceAlphaSaturated;
case BlendFactor::BLEND_CLOLOR:
return MTLBlendFactorBlendColor;
}
}
MTLBlendOperation toMTLBlendOperation(BlendOperation operation)
{
switch (operation) {
case BlendOperation::ADD:
return MTLBlendOperationAdd;
case BlendOperation::SUBTRACT:
return MTLBlendOperationSubtract;
case BlendOperation::RESERVE_SUBTRACT:
return MTLBlendOperationReverseSubtract;
}
}
} }
RenderPipelineMTL::RenderPipelineMTL(id<MTLDevice> mtlDevice, const RenderPipelineDescriptor& descriptor) RenderPipelineMTL::RenderPipelineMTL(id<MTLDevice> mtlDevice)
: _mtlDevice(mtlDevice) : _mtlDevice(mtlDevice)
{ {
_mtlRenderPipelineStateCache = [NSMutableDictionary dictionaryWithCapacity:100];
[_mtlRenderPipelineStateCache retain];
}
void RenderPipelineMTL::update(const PipelineDescriptor & pipelineDescirptor,
const RenderPassDescriptor& renderPassDescriptor)
{
struct
{
void* program;
unsigned int vertexLayoutInfo[32];
backend::PixelFormat colorAttachment;
backend::PixelFormat depthAttachment;
backend::PixelFormat stencilAttachment;
bool blendEnabled;
unsigned int writeMask;
unsigned int rgbBlendOperation;
unsigned int alphaBlendOperation;
unsigned int sourceRGBBlendFactor;
unsigned int destinationRGBBlendFactor;
unsigned int sourceAlphaBlendFactor;
unsigned int destinationAlphaBlendFactor;
}hashMe;
memset(&hashMe, 0, sizeof(hashMe));
const auto& blendDescriptor = pipelineDescirptor.blendDescriptor;
getAttachmentFormat(renderPassDescriptor, _colorAttachmentsFormat[0], _depthAttachmentFormat, _stencilAttachmentFormat);
hashMe.program = pipelineDescirptor.programState->getProgram();
hashMe.colorAttachment = _colorAttachmentsFormat[0];
hashMe.depthAttachment = _depthAttachmentFormat;
hashMe.stencilAttachment =_stencilAttachmentFormat;
hashMe.blendEnabled = blendDescriptor.blendEnabled;
hashMe.writeMask = (unsigned int)blendDescriptor.writeMask;
hashMe.rgbBlendOperation = (unsigned int)blendDescriptor.rgbBlendOperation;
hashMe.alphaBlendOperation = (unsigned int)blendDescriptor.alphaBlendOperation;
hashMe.sourceRGBBlendFactor = (unsigned int)blendDescriptor.sourceRGBBlendFactor;
hashMe.destinationRGBBlendFactor = (unsigned int)blendDescriptor.destinationRGBBlendFactor;
hashMe.sourceAlphaBlendFactor = (unsigned int)blendDescriptor.sourceAlphaBlendFactor;
hashMe.destinationAlphaBlendFactor = (unsigned int)blendDescriptor.destinationAlphaBlendFactor;
int index = 0;
auto vertexLayout = pipelineDescirptor.programState->getVertexLayout();
const auto& attributes = vertexLayout->getAttributes();
for (const auto& it : attributes)
{
auto &attribute = it.second;
/*
stepFunction:1 stride:15 offest:10 format:5 needNormalized:1
bit31 bit30 ~ bit16 bit15 ~ bit6 bit5 ~ bit1 bit0
*/
hashMe.vertexLayoutInfo[index++] =
((unsigned int)vertexLayout->getVertexStepMode() & 0x1) << 31 |
((unsigned int)(vertexLayout->getStride() & 0x7FFF)) << 16 |
((unsigned int)attribute.offset & 0x3FF) << 6 |
((unsigned int)attribute.format & 0x1F) << 1 |
((unsigned int)attribute.needToBeNormallized & 0x1);
}
NSUInteger hash = XXH32((const void*)&hashMe, sizeof(hashMe), 0);
NSNumber* key = [[NSNumber numberWithUnsignedInteger:hash] autorelease];
id obj = [_mtlRenderPipelineStateCache objectForKey:key];
if (obj != nil)
{
_mtlRenderPipelineState = obj;
return;
}
_mtlRenderPipelineDescriptor = [[MTLRenderPipelineDescriptor alloc] init]; _mtlRenderPipelineDescriptor = [[MTLRenderPipelineDescriptor alloc] init];
setShaderModules(descriptor); setShaderModules(pipelineDescirptor);
setVertexLayout(_mtlRenderPipelineDescriptor, descriptor); setVertexLayout(_mtlRenderPipelineDescriptor, pipelineDescirptor);
auto blendState = static_cast<BlendStateMTL*>(descriptor.blendState); setBlendStateAndFormat(pipelineDescirptor.blendDescriptor, renderPassDescriptor);
if (blendState)
_blendDescriptorMTL = blendState->getBlendDescriptorMTL();
setBlendStateAndFormat(descriptor);
NSError *error = nil; NSError *error = nil;
_mtlRenderPipelineState = [_mtlDevice newRenderPipelineStateWithDescriptor:_mtlRenderPipelineDescriptor error:&error]; _mtlRenderPipelineState = [_mtlDevice newRenderPipelineStateWithDescriptor:_mtlRenderPipelineDescriptor error:&error];
if (error) if (error)
NSLog(@"Can not create renderpipeline state: %@", error); NSLog(@"Can not create renderpipeline state: %@", error);
[_mtlRenderPipelineDescriptor release]; [_mtlRenderPipelineDescriptor release];
[_mtlRenderPipelineStateCache setObject:_mtlRenderPipelineState forKey:key];
} }
RenderPipelineMTL::~RenderPipelineMTL() RenderPipelineMTL::~RenderPipelineMTL()
{ {
[_mtlRenderPipelineState release]; NSArray* values = [_mtlRenderPipelineStateCache allValues];
for(id value in values)
{
[value release];
}
[_mtlRenderPipelineStateCache release];
} }
void RenderPipelineMTL::setVertexLayout(MTLRenderPipelineDescriptor* mtlDescriptor, const RenderPipelineDescriptor& descriptor) void RenderPipelineMTL::setVertexLayout(MTLRenderPipelineDescriptor* mtlDescriptor, const PipelineDescriptor& descriptor)
{ {
int vertexIndex = 0; int vertexIndex = 0;
auto vertexLayout = descriptor.programState->getVertexLayout(); auto vertexLayout = descriptor.programState->getVertexLayout();
@ -139,21 +268,22 @@ void RenderPipelineMTL::setVertexLayout(MTLRenderPipelineDescriptor* mtlDescript
} }
void RenderPipelineMTL::setBlendState(MTLRenderPipelineColorAttachmentDescriptor* colorAttachmentDescriptor) void RenderPipelineMTL::setBlendState(MTLRenderPipelineColorAttachmentDescriptor* colorAttachmentDescriptor,
const BlendDescriptor& blendDescriptor)
{ {
colorAttachmentDescriptor.blendingEnabled = _blendDescriptorMTL.blendEnabled; colorAttachmentDescriptor.blendingEnabled = blendDescriptor.blendEnabled;
colorAttachmentDescriptor.writeMask = _blendDescriptorMTL.writeMask; colorAttachmentDescriptor.writeMask = toMTLColorWriteMask(blendDescriptor.writeMask);
colorAttachmentDescriptor.rgbBlendOperation = _blendDescriptorMTL.rgbBlendOperation; colorAttachmentDescriptor.rgbBlendOperation = toMTLBlendOperation(blendDescriptor.rgbBlendOperation);
colorAttachmentDescriptor.alphaBlendOperation = _blendDescriptorMTL.alphaBlendOperation; colorAttachmentDescriptor.alphaBlendOperation = toMTLBlendOperation(blendDescriptor.alphaBlendOperation);
colorAttachmentDescriptor.sourceRGBBlendFactor = _blendDescriptorMTL.sourceRGBBlendFactor; colorAttachmentDescriptor.sourceRGBBlendFactor = toMTLBlendFactor(blendDescriptor.sourceRGBBlendFactor);
colorAttachmentDescriptor.destinationRGBBlendFactor = _blendDescriptorMTL.destinationRGBBlendFactor; colorAttachmentDescriptor.destinationRGBBlendFactor = toMTLBlendFactor(blendDescriptor.destinationRGBBlendFactor);
colorAttachmentDescriptor.sourceAlphaBlendFactor = _blendDescriptorMTL.sourceAlphaBlendFactor; colorAttachmentDescriptor.sourceAlphaBlendFactor = toMTLBlendFactor(blendDescriptor.sourceAlphaBlendFactor);
colorAttachmentDescriptor.destinationAlphaBlendFactor = _blendDescriptorMTL.destinationAlphaBlendFactor; colorAttachmentDescriptor.destinationAlphaBlendFactor = toMTLBlendFactor(blendDescriptor.destinationAlphaBlendFactor);
} }
void RenderPipelineMTL::setShaderModules(const RenderPipelineDescriptor& descriptor) void RenderPipelineMTL::setShaderModules(const PipelineDescriptor& descriptor)
{ {
auto vertexShaderModule = static_cast<ProgramMTL*>(descriptor.programState->getProgram())->getVertexShader(); auto vertexShaderModule = static_cast<ProgramMTL*>(descriptor.programState->getProgram())->getVertexShader();
_mtlRenderPipelineDescriptor.vertexFunction = vertexShaderModule->getMTLFunction(); _mtlRenderPipelineDescriptor.vertexFunction = vertexShaderModule->getMTLFunction();
@ -162,18 +292,61 @@ void RenderPipelineMTL::setShaderModules(const RenderPipelineDescriptor& descrip
_mtlRenderPipelineDescriptor.fragmentFunction = fragShaderModule->getMTLFunction(); _mtlRenderPipelineDescriptor.fragmentFunction = fragShaderModule->getMTLFunction();
} }
void RenderPipelineMTL::setBlendStateAndFormat(const RenderPipelineDescriptor& descriptor) void RenderPipelineMTL::getAttachmentFormat(const RenderPassDescriptor& descriptor,
PixelFormat& colorFormat,
PixelFormat& depthFormat,
PixelFormat& stencilFormat)
{
if (descriptor.needColorAttachment)
{
// FIXME: now just handle color attachment 0.
if (descriptor.colorAttachmentsTexture[0])
colorFormat = descriptor.colorAttachmentsTexture[0]->getTextureFormat();
}
else
{
colorFormat = PixelFormat::DEFAULT;
}
if (descriptor.needDepthStencilAttachment())
{
if(descriptor.depthAttachmentTexture)
{
depthFormat = descriptor.depthAttachmentTexture->getTextureFormat();
}
else
{
depthFormat = PixelFormat::D24S8;
}
if (descriptor.stencilAttachmentTexture)
{
stencilFormat = descriptor.stencilAttachmentTexture->getTextureFormat();
}
else
{
stencilFormat = PixelFormat::D24S8;
}
}
else
{
depthFormat = stencilFormat = PixelFormat::NONE;
}
}
void RenderPipelineMTL::setBlendStateAndFormat(const BlendDescriptor& blendDescriptor,
const RenderPassDescriptor& renderPassDescriptor)
{ {
for (int i = 0; i < MAX_COLOR_ATTCHMENT; ++i) for (int i = 0; i < MAX_COLOR_ATTCHMENT; ++i)
{ {
if (PixelFormat::NONE == descriptor.colorAttachmentsFormat[i]) if (PixelFormat::NONE == _colorAttachmentsFormat[i])
continue; continue;
_mtlRenderPipelineDescriptor.colorAttachments[i].pixelFormat = Utils::toMTLPixelFormat(descriptor.colorAttachmentsFormat[i]); _mtlRenderPipelineDescriptor.colorAttachments[i].pixelFormat = Utils::toMTLPixelFormat(_colorAttachmentsFormat[i]);
setBlendState(_mtlRenderPipelineDescriptor.colorAttachments[i]); setBlendState(_mtlRenderPipelineDescriptor.colorAttachments[i], blendDescriptor);
} }
_mtlRenderPipelineDescriptor.depthAttachmentPixelFormat = Utils::toMTLPixelFormat(descriptor.depthAttachmentFormat); _mtlRenderPipelineDescriptor.depthAttachmentPixelFormat = Utils::toMTLPixelFormat(_depthAttachmentFormat);
_mtlRenderPipelineDescriptor.stencilAttachmentPixelFormat = Utils::toMTLPixelFormat(descriptor.stencilAttachmentFormat); _mtlRenderPipelineDescriptor.stencilAttachmentPixelFormat = Utils::toMTLPixelFormat(_stencilAttachmentFormat);
} }
CC_BACKEND_END CC_BACKEND_END

View File

@ -1,67 +0,0 @@
/****************************************************************************
Copyright (c) 2018-2019 Xiamen Yaji Software Co., Ltd.
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "BlendStateGL.h"
#include "renderer/backend/opengl/UtilsGL.h"
CC_BACKEND_BEGIN
void BlendStateGL::reset()
{
glDisable(GL_BLEND);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
}
BlendStateGL::BlendStateGL(const BlendDescriptor& descriptor)
: _blendEnabled(descriptor.blendEnabled)
, _rgbBlendOperation(UtilsGL::toGLBlendOperation(descriptor.rgbBlendOperation))
, _alphaBlendOperation(UtilsGL::toGLBlendOperation(descriptor.alphaBlendOperation))
, _sourceRGBBlendFactor(UtilsGL::toGLBlendFactor(descriptor.sourceRGBBlendFactor))
, _destinationRGBBlendFactor(UtilsGL::toGLBlendFactor(descriptor.destinationRGBBlendFactor))
, _sourceAlphaBlendFactor(UtilsGL::toGLBlendFactor(descriptor.sourceAlphaBlendFactor))
, _destinationAlphaBlendFactor(UtilsGL::toGLBlendFactor(descriptor.destinationAlphaBlendFactor))
, _writeMaskRed((uint32_t)descriptor.writeMask & (uint32_t)ColorWriteMask::RED)
, _writeMaskGreen((uint32_t)descriptor.writeMask & (uint32_t)ColorWriteMask::GREEN)
, _writeMaskBlue((uint32_t)descriptor.writeMask & (uint32_t)ColorWriteMask::BLUE)
, _writeMaskAlpha((uint32_t)descriptor.writeMask & (uint32_t)ColorWriteMask::ALPHA)
{
}
void BlendStateGL::apply() const
{
if (_blendEnabled)
{
glEnable(GL_BLEND);
glBlendEquationSeparate(_rgbBlendOperation, _alphaBlendOperation);
glBlendFuncSeparate(_sourceRGBBlendFactor,
_destinationRGBBlendFactor,
_sourceAlphaBlendFactor,
_destinationAlphaBlendFactor);
}
else
glDisable(GL_BLEND);
glColorMask(_writeMaskRed, _writeMaskGreen, _writeMaskBlue, _writeMaskAlpha);
}
CC_BACKEND_END

View File

@ -1,71 +0,0 @@
/****************************************************************************
Copyright (c) 2018-2019 Xiamen Yaji Software Co., Ltd.
http://www.cocos2d-x.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "../BlendState.h"
#include "platform/CCGL.h"
CC_BACKEND_BEGIN
/**
* @addtogroup _opengl
* @{
*/
/**
* Set blend state to pipeline
*/
class BlendStateGL : public BlendState
{
public:
/// Reset to default state.
static void reset();
/**
* @descriptor Specifies the blend descriptor.
*/
BlendStateGL(const BlendDescriptor& descriptor);
/// Set blend status to pipeline.
void apply() const;
private:
GLboolean _writeMaskRed = GL_TRUE;
GLboolean _writeMaskGreen = GL_TRUE;
GLboolean _writeMaskBlue = GL_TRUE;
GLboolean _writeMaskAlpha = GL_TRUE;
bool _blendEnabled = false;
GLenum _rgbBlendOperation = GL_FUNC_ADD;
GLenum _alphaBlendOperation = GL_FUNC_ADD;
GLenum _sourceRGBBlendFactor = GL_ONE;
GLenum _destinationRGBBlendFactor = GL_ZERO;
GLenum _sourceAlphaBlendFactor = GL_ONE;
GLenum _destinationAlphaBlendFactor = GL_ZERO;
};
//end of _opengl group
/// @}
CC_BACKEND_END

View File

@ -28,7 +28,6 @@
#include "TextureGL.h" #include "TextureGL.h"
#include "DepthStencilStateGL.h" #include "DepthStencilStateGL.h"
#include "ProgramGL.h" #include "ProgramGL.h"
#include "BlendStateGL.h"
#include "base/ccMacros.h" #include "base/ccMacros.h"
#include "base/CCEventDispatcher.h" #include "base/CCEventDispatcher.h"
#include "base/CCEventType.h" #include "base/CCEventType.h"
@ -88,6 +87,8 @@ CommandBufferGL::CommandBufferGL()
CommandBufferGL::~CommandBufferGL() CommandBufferGL::~CommandBufferGL()
{ {
glDeleteFramebuffers(1, &_generatedFBO); glDeleteFramebuffers(1, &_generatedFBO);
CC_SAFE_RELEASE_NULL(_renderPipeline);
cleanResources(); cleanResources();
#if CC_ENABLE_CACHE_TEXTURE_DATA #if CC_ENABLE_CACHE_TEXTURE_DATA
@ -390,12 +391,6 @@ void CommandBufferGL::prepareDrawing() const
else else
DepthStencilStateGL::reset(); DepthStencilStateGL::reset();
// Set blend state.
if (_renderPipeline->getBlendState())
_renderPipeline->getBlendState()->apply();
else
BlendStateGL::reset();
// Set cull mode. // Set cull mode.
if (CullMode::NONE == _cullMode) if (CullMode::NONE == _cullMode)
{ {
@ -582,7 +577,6 @@ void CommandBufferGL::setUniform(bool isArray, GLuint location, unsigned int siz
void CommandBufferGL::cleanResources() void CommandBufferGL::cleanResources()
{ {
CC_SAFE_RELEASE_NULL(_indexBuffer); CC_SAFE_RELEASE_NULL(_indexBuffer);
CC_SAFE_RELEASE_NULL(_renderPipeline);
CC_SAFE_RELEASE_NULL(_programState); CC_SAFE_RELEASE_NULL(_programState);
CC_SAFE_RELEASE_NULL(_vertexBuffer); CC_SAFE_RELEASE_NULL(_vertexBuffer);
} }

View File

@ -29,7 +29,6 @@
#include "CommandBufferGL.h" #include "CommandBufferGL.h"
#include "TextureGL.h" #include "TextureGL.h"
#include "DepthStencilStateGL.h" #include "DepthStencilStateGL.h"
#include "BlendStateGL.h"
#include "ProgramGL.h" #include "ProgramGL.h"
#include "DeviceInfoGL.h" #include "DeviceInfoGL.h"
@ -97,18 +96,9 @@ DepthStencilState* DeviceGL::createDepthStencilState(const DepthStencilDescripto
return ret; return ret;
} }
BlendState* DeviceGL::createBlendState(const BlendDescriptor& descriptor) RenderPipeline* DeviceGL::newRenderPipeline()
{ {
auto ret = new (std::nothrow) BlendStateGL(descriptor); return new (std::nothrow) RenderPipelineGL();
if (ret)
ret->autorelease();
return ret;
}
RenderPipeline* DeviceGL::newRenderPipeline(const RenderPipelineDescriptor& descriptor)
{
return new (std::nothrow) RenderPipelineGL(descriptor);
} }
Program* DeviceGL::newProgram(const std::string& vertexShader, const std::string& fragmentShader) Program* DeviceGL::newProgram(const std::string& vertexShader, const std::string& fragmentShader)

View File

@ -68,19 +68,12 @@ public:
*/ */
virtual DepthStencilState* createDepthStencilState(const DepthStencilDescriptor& descriptor) override; virtual DepthStencilState* createDepthStencilState(const DepthStencilDescriptor& descriptor) override;
/**
* Create an auto released BlendState object.
* @param descriptor Specifies blend description.
* @return An auto release BlendState object.
*/
virtual BlendState* createBlendState(const BlendDescriptor& descriptor) override;
/** /**
* New a RenderPipeline object, not auto released. * New a RenderPipeline object, not auto released.
* @param descriptor Specifies render pipeline description. * @param descriptor Specifies render pipeline description.
* @return A RenderPipeline object. * @return A RenderPipeline object.
*/ */
virtual RenderPipeline* newRenderPipeline(const RenderPipelineDescriptor& descriptor) override; virtual RenderPipeline* newRenderPipeline() override;
/** /**
* Design for metal. * Design for metal.

View File

@ -335,7 +335,7 @@ int ProgramGL::getOriginalLocation(int location) const
const UniformInfo& ProgramGL::getActiveUniformInfo(ShaderStage stage, int location) const const UniformInfo& ProgramGL::getActiveUniformInfo(ShaderStage stage, int location) const
{ {
return UniformInfo{}; return std::move(UniformInfo{});
} }
const std::unordered_map<std::string, UniformInfo>& ProgramGL::getAllActiveUniformInfo(ShaderStage stage) const const std::unordered_map<std::string, UniformInfo>& ProgramGL::getAllActiveUniformInfo(ShaderStage stage) const

View File

@ -149,7 +149,7 @@ public:
* @param location Specifies the uniform locaion. * @param location Specifies the uniform locaion.
* @return The uniformInfo. * @return The uniformInfo.
*/ */
virtual const UniformInfo& getActiveUniformInfo(ShaderStage stage, int location) const; virtual const UniformInfo& getActiveUniformInfo(ShaderStage stage, int location) const override;
/** /**
* Get all uniformInfos. * Get all uniformInfos.

View File

@ -26,26 +26,56 @@
#include "ShaderModuleGL.h" #include "ShaderModuleGL.h"
#include "DepthStencilStateGL.h" #include "DepthStencilStateGL.h"
#include "ProgramGL.h" #include "ProgramGL.h"
#include "BlendStateGL.h" #include "UtilsGL.h"
#include <assert.h> #include <assert.h>
CC_BACKEND_BEGIN CC_BACKEND_BEGIN
RenderPipelineGL::RenderPipelineGL(const RenderPipelineDescriptor& descriptor) void RenderPipelineGL::update(const PipelineDescriptor& pipelineDescirptor, const RenderPassDescriptor& renderpassDescriptor)
{ {
_programGL = static_cast<ProgramGL*>(descriptor.programState->getProgram()); if(_programGL != pipelineDescirptor.programState->getProgram())
CC_SAFE_RETAIN(_programGL); {
CC_SAFE_RELEASE(_programGL);
_programGL = static_cast<ProgramGL*>(pipelineDescirptor.programState->getProgram());
CC_SAFE_RETAIN(_programGL);
}
updateBlendState(pipelineDescirptor.blendDescriptor);
}
const auto& blendState = descriptor.blendState; void RenderPipelineGL::updateBlendState(const BlendDescriptor& descriptor)
CC_SAFE_RETAIN(blendState); {
_blendState = static_cast<BlendStateGL*>(blendState); auto blendEnabled = descriptor.blendEnabled;
auto rgbBlendOperation = UtilsGL::toGLBlendOperation(descriptor.rgbBlendOperation);
auto alphaBlendOperation = UtilsGL::toGLBlendOperation(descriptor.alphaBlendOperation);
auto sourceRGBBlendFactor = UtilsGL::toGLBlendFactor(descriptor.sourceRGBBlendFactor);
auto destinationRGBBlendFactor = UtilsGL::toGLBlendFactor(descriptor.destinationRGBBlendFactor);
auto sourceAlphaBlendFactor = UtilsGL::toGLBlendFactor(descriptor.sourceAlphaBlendFactor);
auto destinationAlphaBlendFactor = UtilsGL::toGLBlendFactor(descriptor.destinationAlphaBlendFactor);
auto writeMaskRed = (uint32_t)descriptor.writeMask & (uint32_t)ColorWriteMask::RED;
auto writeMaskGreen = (uint32_t)descriptor.writeMask & (uint32_t)ColorWriteMask::GREEN;
auto writeMaskBlue = (uint32_t)descriptor.writeMask & (uint32_t)ColorWriteMask::BLUE;
auto writeMaskAlpha = (uint32_t)descriptor.writeMask & (uint32_t)ColorWriteMask::ALPHA;
if (blendEnabled)
{
glEnable(GL_BLEND);
glBlendEquationSeparate(rgbBlendOperation, alphaBlendOperation);
glBlendFuncSeparate(sourceRGBBlendFactor,
destinationRGBBlendFactor,
sourceAlphaBlendFactor,
destinationAlphaBlendFactor);
}
else
glDisable(GL_BLEND);
glColorMask(writeMaskRed, writeMaskGreen, writeMaskBlue, writeMaskAlpha);
} }
RenderPipelineGL::~RenderPipelineGL() RenderPipelineGL::~RenderPipelineGL()
{ {
CC_SAFE_RELEASE(_programGL); CC_SAFE_RELEASE(_programGL);
CC_SAFE_RELEASE(_blendState);
} }
CC_BACKEND_END CC_BACKEND_END

View File

@ -34,7 +34,6 @@
CC_BACKEND_BEGIN CC_BACKEND_BEGIN
class ProgramGL; class ProgramGL;
class BlendStateGL;
/** /**
* @addtogroup _opengl * @addtogroup _opengl
* @{ * @{
@ -49,23 +48,20 @@ public:
/** /**
* @param descriptor Specifies render pipeline descriptor. * @param descriptor Specifies render pipeline descriptor.
*/ */
RenderPipelineGL(const RenderPipelineDescriptor& descriptor); RenderPipelineGL() = default;
~RenderPipelineGL(); ~RenderPipelineGL();
virtual void update(const PipelineDescriptor & pipelineDescirptor, const RenderPassDescriptor& renderpassDescriptor) override;
/** /**
* Get program instance. * Get program instance.
* @return Program instance. * @return Program instance.
*/ */
inline ProgramGL* getProgram() const { return _programGL; } inline ProgramGL* getProgram() const { return _programGL; }
/**
* Get blend state.
* @return Blend state.
*/
inline BlendStateGL* getBlendState() const { return _blendState; }
private: private:
void updateBlendState(const BlendDescriptor& descriptor);
ProgramGL* _programGL = nullptr; ProgramGL* _programGL = nullptr;
BlendStateGL* _blendState = nullptr;
}; };
// end of _opengl group // end of _opengl group
/// @} /// @}