RenderTarget abstract, in-progress (#210)

RenderTarget abstract
This commit is contained in:
HALX99 2020-09-21 07:10:50 -07:00 committed by GitHub
parent f6d51583a8
commit 5a32bcfdaf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
55 changed files with 1051 additions and 894 deletions

View File

@ -34,6 +34,7 @@ THE SOFTWARE.
#include "renderer/ccShaders.h"
#include "renderer/backend/ProgramState.h"
#include "renderer/backend/Device.h"
#include "renderer/backend/RenderTarget.h"
#include "2d/CCCamera.h"
@ -154,6 +155,8 @@ GridBase::~GridBase()
{
CCLOGINFO("deallocing GridBase: %p", this);
CC_SAFE_RELEASE(_renderTarget);
//TODO: ? why 2.0 comments this line: setActive(false);
CC_SAFE_RELEASE(_texture);
@ -216,16 +219,13 @@ void GridBase::beforeDraw()
Size size = director->getWinSizeInPixels();
renderer->setViewPort(0, 0, (unsigned int)size.width, (unsigned int)size.height);
RenderTargetFlag flags = RenderTargetFlag::COLOR;
_oldColorAttachment = renderer->getColorAttachment();
_oldDepthAttachment = renderer->getDepthAttachment();
_oldStencilAttachment = renderer->getStencilAttachment();
_oldRenderTargetFlag = renderer->getRenderTargetFlag();
renderer->setRenderTarget(flags, _texture, nullptr, nullptr);
_oldRenderTarget = renderer->getRenderTarget();
CC_SAFE_RELEASE(_renderTarget);
_renderTarget = backend::Device::getInstance()->newRenderTarget(TargetBufferFlags::COLOR, _texture->getBackendTexture());
renderer->setRenderTarget(_renderTarget);
renderer->clear(TargetBufferFlags::COLOR, _clearColor, 1, 0, 0.0);
};
renderer->addCommand(&_beforeDrawCommand);
renderer->clear(ClearFlag::COLOR, _clearColor, 1, 0, 0.0);
}
void GridBase::afterDraw(cocos2d::Node * /*target*/)
@ -238,7 +238,7 @@ void GridBase::afterDraw(cocos2d::Node * /*target*/)
director->setProjection(_directorProjection);
const auto& vp = Camera::getDefaultViewport();
renderer->setViewPort(vp.x, vp.y, vp.w, vp.h);
renderer->setRenderTarget(_oldRenderTargetFlag, _oldColorAttachment, _oldDepthAttachment, _oldStencilAttachment);
renderer->setRenderTarget(_oldRenderTarget);
};
renderer->addCommand(&_afterDrawCommand);

View File

@ -40,6 +40,11 @@ class Texture2D;
// class GLProgram;
class Node;
namespace backend
{
class RenderTarget;
}
/**
* @addtogroup _2d
* @{
@ -153,10 +158,10 @@ protected:
CallbackCommand _afterDrawCommand;
CallbackCommand _beforeBlitCommand;
CallbackCommand _afterBlitCommand;
RenderTargetFlag _oldRenderTargetFlag;
Texture2D* _oldColorAttachment = nullptr;
Texture2D* _oldDepthAttachment = nullptr;
Texture2D* _oldStencilAttachment = nullptr;
// New
backend::RenderTarget* _oldRenderTarget = nullptr;
backend::RenderTarget* _renderTarget = nullptr;
backend::UniformLocation _mvpMatrixLocation;
backend::UniformLocation _textureLocation;

View File

@ -38,6 +38,7 @@ THE SOFTWARE.
#include "renderer/CCTextureCache.h"
#include "renderer/backend/Device.h"
#include "renderer/backend/Texture.h"
#include "renderer/backend/RenderTarget.h"
NS_CC_BEGIN
@ -57,6 +58,7 @@ RenderTexture::RenderTexture()
RenderTexture::~RenderTexture()
{
CC_SAFE_RELEASE(_renderTarget);
CC_SAFE_RELEASE(_sprite);
CC_SAFE_RELEASE(_texture2DCopy);
CC_SAFE_RELEASE(_depthStencilTexture);
@ -207,8 +209,6 @@ bool RenderTexture::initWithWidthAndHeight(int w, int h, backend::PixelFormat fo
_renderTargetFlags = RenderTargetFlag::COLOR;
clearColorAttachment();
if (PixelFormat::D24S8 == depthStencilFormat)
{
_renderTargetFlags = RenderTargetFlag::ALL;
@ -228,6 +228,14 @@ bool RenderTexture::initWithWidthAndHeight(int w, int h, backend::PixelFormat fo
texture->release();
}
_renderTarget = backend::Device::getInstance()->newRenderTarget(_renderTargetFlags,
_texture2D ? _texture2D->getBackendTexture() : nullptr,
_depthStencilTexture ? _depthStencilTexture->getBackendTexture() : nullptr,
_depthStencilTexture ? _depthStencilTexture->getBackendTexture() : nullptr
);
clearColorAttachment();
_texture2D->setAntiAliasTexParameters();
if (_texture2DCopy)
{
@ -477,7 +485,7 @@ void RenderTexture::newImage(std::function<void(RefPtr<Image>)> imageCallback, b
int savedBufferHeight = (int)s.height;
bool hasPremultipliedAlpha = _texture2D->hasPremultipliedAlpha();
_director->getRenderer()->readPixels(_texture2D->getBackendTexture(), [=](const backend::PixelBufferDescriptor& pbd) {
_director->getRenderer()->readPixels(_renderTarget, [=](const backend::PixelBufferDescriptor& pbd) {
if(pbd) {
auto image = utils::makeInstance<Image>(&Image::initWithRawData, pbd._data.getBytes(), pbd._data.getSize(), pbd._width, pbd._height, 8, hasPremultipliedAlpha);
imageCallback(image);
@ -548,12 +556,8 @@ void RenderTexture::onBegin()
_oldViewport = renderer->getViewport();
renderer->setViewPort(viewport.origin.x, viewport.origin.y, viewport.size.width, viewport.size.height);
_oldColorAttachment = renderer->getColorAttachment();
_oldDepthAttachment = renderer->getDepthAttachment();
_oldStencilAttachment = renderer->getStencilAttachment();
_oldRenderTargetFlag = renderer->getRenderTargetFlag();
renderer->setRenderTarget(_renderTargetFlags, _texture2D, _depthStencilTexture, _depthStencilTexture);
_oldRenderTarget = renderer->getRenderTarget();
renderer->setRenderTarget(_renderTarget);
}
void RenderTexture::onEnd()
@ -564,7 +568,8 @@ void RenderTexture::onEnd()
Renderer *renderer = Director::getInstance()->getRenderer();
renderer->setViewPort(_oldViewport.x, _oldViewport.y, _oldViewport.w, _oldViewport.h);
renderer->setRenderTarget(_oldRenderTargetFlag, _oldColorAttachment, _oldDepthAttachment, _oldStencilAttachment);
renderer->setRenderTarget(_oldRenderTarget);
}
void RenderTexture::begin()
@ -629,19 +634,10 @@ void RenderTexture::setClearFlags(ClearFlag clearFlags)
void RenderTexture::clearColorAttachment()
{
auto renderer = _director->getRenderer();
_beforeClearAttachmentCommand.func = [=]() -> void {
_oldColorAttachment = renderer->getColorAttachment();
renderer->setRenderTarget(RenderTargetFlag::COLOR, _texture2D, nullptr, nullptr);
};
renderer->addCommand(&_beforeClearAttachmentCommand);
Color4F color(0.f, 0.f, 0.f, 0.f);
renderer->clear(ClearFlag::COLOR, color, 1, 0, _globalZOrder);
_afterClearAttachmentCommand.func = [=]() -> void {
renderer->setRenderTarget(RenderTargetFlag::COLOR, _oldColorAttachment, nullptr, nullptr);
};
renderer->addCommand(&_afterClearAttachmentCommand);
_oldRenderTarget = renderer->getRenderTarget();
renderer->setRenderTarget(_renderTarget);
renderer->clear(TargetBufferFlags::COLOR, Color4F{0.f, 0.f, 0.f, 0.f}, 1, 0, _globalZOrder);
renderer->setRenderTarget(_oldRenderTarget);
}
NS_CC_END

View File

@ -39,6 +39,7 @@ NS_CC_BEGIN
namespace backend
{
class TextureBackend;
class RenderTarget;
}
class EventCustom;
@ -358,11 +359,11 @@ protected:
Texture2D* _texture2D = nullptr;
Texture2D* _depthStencilTexture = nullptr;
Texture2D* _texture2DCopy = nullptr; // a copy of _texture
Texture2D* _oldColorAttachment = nullptr;
Texture2D* _oldDepthAttachment = nullptr;
Texture2D* _oldStencilAttachment = nullptr;
RenderTargetFlag _renderTargetFlags;
RenderTargetFlag _oldRenderTargetFlag;
backend::RenderTarget* _renderTarget = nullptr;
backend::RenderTarget* _oldRenderTarget = nullptr;
RenderTargetFlag _renderTargetFlags{};
Image* _UITextureImage = nullptr;
backend::PixelFormat _pixelFormat = backend::PixelFormat::RGBA8888;

View File

@ -388,13 +388,13 @@ void Director::setOpenGLView(GLView *openGLView)
_isStatusLabelUpdated = true;
_renderer->init();
if (_openGLView)
{
setGLDefaultValues();
}
_renderer->init();
if (_eventDispatcher)
{
_eventDispatcher->setEnabled(true);

View File

@ -66,16 +66,11 @@ Copyright (c) 2020 c4games.com.
return static_cast<_BITMASK>(~static_cast<_IntTy>(_Left)); \
} \
\
constexpr bool _Bitmask_includes( \
_BITMASK _Left, _BITMASK _Elements) noexcept { /* return (_Left & _Elements) != _BITMASK{} */ \
return (_Left & _Elements) != _BITMASK{}; \
} \
\
constexpr bool _Bitmask_includes_all( \
_BITMASK _Left, _BITMASK _Elements) noexcept { /* return (_Left & _Elements) == _Elements */ \
return (_Left & _Elements) == _Elements; \
constexpr bool operator!(_BITMASK _Left) noexcept { /* return ~_Left */ \
using _IntTy = _STD underlying_type<_BITMASK>::type; \
return !static_cast<_IntTy>(_Left); \
}
// BITSHIFT OPERATIONS, inspired from msvc++ <type_traits>.
#define CC_ENABLE_BITSHIFT_OPS(_BITMASK) \
constexpr _BITMASK operator>>(_BITMASK _Left, _BITMASK _Right) noexcept { /* return _Left & _Right */ \
@ -87,3 +82,20 @@ Copyright (c) 2020 c4games.com.
using _IntTy = _STD underlying_type<_BITMASK>::type; \
return static_cast<_BITMASK>(static_cast<_IntTy>(_Left) << static_cast<_IntTy>(_Right)); \
}
namespace bitmask {
template<typename _BITMASK>
constexpr bool none(_BITMASK _Left, _BITMASK _Elements) noexcept {
return !(_Left & _Elements);
}
template<typename _BITMASK>
constexpr bool any(_BITMASK _Left, _BITMASK _Elements) noexcept {
return !!(_Left & _Elements);
}
template<typename _BITMASK>
constexpr bool only(_BITMASK _Left, _BITMASK _Elements) noexcept {
return (_Left & _Elements) == _Elements;
}
} // namespace bitmask

View File

@ -634,6 +634,7 @@ struct CC_DLL ScissorRect
float height = 0;
};
// TODO: Move to renderer/backend/Types.h
struct TextureFormatEXT
{
enum {
@ -652,27 +653,13 @@ struct TextureFlag
};
};
enum class ClearFlag : uint8_t
{
NONE = 0,
COLOR = 1,
DEPTH = 1 << 1,
STENCIL = 1 << 2,
ALL = COLOR | DEPTH | STENCIL
};
CC_ENABLE_BITMASK_OPS(ClearFlag)
enum class RenderTargetFlag : uint8_t
{
COLOR = 1,
DEPTH = 1 << 1,
STENCIL = 1 << 2,
ALL = COLOR | DEPTH | STENCIL
};
CC_ENABLE_BITMASK_OPS(RenderTargetFlag)
using TextureUsage = backend::TextureUsage;
using PixelFormat = backend::PixelFormat;
using TargetBufferFlags = backend::TargetBufferFlags;
using RenderTargetFlag = backend::RenderTargetFlag;
using ClearFlag = backend::ClearFlag;
NS_CC_END
// end group
/// @}

View File

@ -75,7 +75,6 @@ namespace utils
* Capture screen interface
*/
static EventListenerCustom* s_captureScreenListener;
static CallbackCommand s_captureScreenCommand;
void captureScreen(std::function<void(RefPtr<Image>)> imageCallback)
{
if (s_captureScreenListener)
@ -91,9 +90,8 @@ void captureScreen(std::function<void(RefPtr<Image>)> imageCallback)
s_captureScreenListener = eventDispatcher->addCustomEventListener(Director::EVENT_AFTER_DRAW, [=](EventCustom* /*event*/) {
eventDispatcher->removeEventListener(s_captureScreenListener);
s_captureScreenListener = nullptr;
// !!!GL: AFTER_DRAW and BEFORE_END_FRAME
renderer->readPixels(nullptr, [=](const backend::PixelBufferDescriptor& pbd) {
renderer->readPixels(renderer->getDefaultRenderTarget(), [=](const backend::PixelBufferDescriptor& pbd) {
if (pbd) {
auto image = utils::makeInstance<Image>(&Image::initWithRawData, pbd._data.getBytes(), pbd._data.getSize(), pbd._width, pbd._height, 8, false);
imageCallback(image);

View File

@ -33,6 +33,8 @@ THE SOFTWARE.
#define glUnmapBuffer glUnmapBufferOES
#define GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8_OES
#define GL_DEPTH_STENCIL GL_DEPTH_STENCIL_OES
#define GL_UNSIGNED_INT_24_8 GL_UNSIGNED_INT_24_8_OES
#define GL_WRITE_ONLY GL_WRITE_ONLY_OES
// GL_GLEXT_PROTOTYPES isn't defined in glplatform.h on android ndk r7

View File

@ -38,6 +38,8 @@ THE SOFTWARE.
#define glUnmapBuffer glUnmapBufferOES
#define GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8_OES
#define GL_DEPTH_STENCIL GL_DEPTH_STENCIL_OES
#define GL_UNSIGNED_INT_24_8 GL_UNSIGNED_INT_24_8_OES
#define GL_WRITE_ONLY GL_WRITE_ONLY_OES
#include <OpenGLES/ES2/gl.h>

View File

@ -32,6 +32,9 @@ THE SOFTWARE.
#include "glad/glad.h"
#if defined(CC_USE_GLES)
#undef GL_DEPTH_STENCIL
#undef GL_DEPTH24_STENCIL8
#undef GL_UNSIGNED_INT_24_8
#undef glClearDepth
#undef glMapBuffer
#undef glUnmapBuffer
@ -57,6 +60,9 @@ THE SOFTWARE.
#undef glGenerateMipmap
#endif
#define GL_DEPTH_STENCIL GL_DEPTH_STENCIL_OES
#define GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8_OES
#define GL_UNSIGNED_INT_24_8 GL_UNSIGNED_INT_24_8_OES
#define glClearDepth glClearDepthf
#define glMapBuffer glMapBufferOES
#define glUnmapBuffer glUnmapBufferOES
@ -84,6 +90,4 @@ THE SOFTWARE.
#endif
#define CC_GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8
#endif // CC_TARGET_PLATFORM == CC_PLATFORM_WIN32

View File

@ -27,7 +27,7 @@
#include "renderer/backend/DepthStencilState.h"
#include "renderer/backend/Texture.h"
#include "renderer/backend/VertexLayout.h"
#include "renderer/backend/RenderPassDescriptor.h"
#include "renderer/backend/RenderPassParams.h"
#include "renderer/backend/ProgramState.h"
#include <string>

View File

@ -47,6 +47,7 @@
#include "xxhash.h"
#include "renderer/backend/Backend.h"
#include "renderer/backend/RenderTarget.h"
NS_CC_BEGIN
@ -180,6 +181,7 @@ Renderer::~Renderer()
CC_SAFE_RELEASE(_commandBuffer);
CC_SAFE_RELEASE(_renderPipeline);
CC_SAFE_RELEASE(_defaultRT);
}
void Renderer::init()
@ -191,6 +193,9 @@ void Renderer::init()
auto device = backend::Device::getInstance();
_commandBuffer = device->newCommandBuffer();
// MTL: default render target flags should have DEPTH_AND_STENCIL make sure further clear could set pipeline state properly
_defaultRT = device->newDefaultRenderTarget(TargetBufferFlags::COLOR | TargetBufferFlags::DEPTH_AND_STENCIL);
_currentRT = _defaultRT;
_renderPipeline = device->newRenderPipeline();
_commandBuffer->setRenderPipeline(_renderPipeline);
}
@ -404,7 +409,8 @@ void Renderer::clean()
void Renderer::setDepthTest(bool value)
{
_depthStencilDescriptor.depthTestEnabled = value;
_renderPassDescriptor.depthTestEnabled = value;
_currentRT->modifyTargetFlags(value ? TargetBufferFlags::DEPTH : TargetBufferFlags::NONE,
value ? TargetBufferFlags::NONE : TargetBufferFlags::DEPTH);
}
void Renderer::setDepthWrite(bool value)
@ -435,7 +441,9 @@ bool Renderer::getDepthWrite() const
void Renderer::setStencilTest(bool value)
{
_depthStencilDescriptor.stencilTestEnabled = value;
_renderPassDescriptor.stencilTestEnabled = value;
_currentRT->modifyTargetFlags(value ? TargetBufferFlags::STENCIL : TargetBufferFlags::NONE,
value ? TargetBufferFlags::NONE : TargetBufferFlags::STENCIL);
}
void Renderer::setStencilCompareFunction(backend::CompareFunction func, unsigned int ref, unsigned int readMask)
@ -615,24 +623,30 @@ void Renderer::drawBatchedTriangles()
_vertexBuffer->updateData(_verts, _filledVertex * sizeof(_verts[0]));
_indexBuffer->updateData(_indices, _filledIndex * sizeof(_indices[0]));
#endif
/************** 2: Draw *************/
beginRenderPass();
for (int i = 0; i < batchesTotal; ++i)
{
beginRenderPass(_triBatchesToDraw[i].cmd);
auto& drawInfo = _triBatchesToDraw[i];
setRenderPipeline(drawInfo.cmd->getPipelineDescriptor(), _renderPassParams);
_commandBuffer->setVertexBuffer(_vertexBuffer);
_commandBuffer->setIndexBuffer(_indexBuffer);
auto& pipelineDescriptor = _triBatchesToDraw[i].cmd->getPipelineDescriptor();
auto& pipelineDescriptor = drawInfo.cmd->getPipelineDescriptor();
_commandBuffer->setProgramState(pipelineDescriptor.programState);
_commandBuffer->drawElements(backend::PrimitiveType::TRIANGLE,
backend::IndexFormat::U_SHORT,
_triBatchesToDraw[i].indicesToDraw,
_triBatchesToDraw[i].offset * sizeof(_indices[0]));
_commandBuffer->endRenderPass();
drawInfo.indicesToDraw,
drawInfo.offset * sizeof(_indices[0]));
_drawnBatches++;
_drawnVertices += _triBatchesToDraw[i].indicesToDraw;
}
_commandBuffer->endRenderPass();
/************** 3: Cleanup *************/
_queuedTriangleCommands.clear();
@ -649,7 +663,8 @@ void Renderer::drawCustomCommand(RenderCommand *command)
if (cmd->getBeforeCallback()) cmd->getBeforeCallback()();
beginRenderPass(command);
beginRenderPass();
setRenderPipeline(cmd->getPipelineDescriptor(), _renderPassParams);
_commandBuffer->setVertexBuffer(cmd->getVertexBuffer());
_commandBuffer->setProgramState(cmd->getPipelineDescriptor().programState);
@ -738,21 +753,24 @@ bool Renderer::checkVisibility(const Mat4 &transform, const Size &size)
return ret;
}
void Renderer::readPixels(backend::TextureBackend* texture, std::function<void(const backend::PixelBufferDescriptor&)> callback)
void Renderer::readPixels(backend::RenderTarget* rt, std::function<void(const backend::PixelBufferDescriptor&)> callback)
{
if(!texture) // read pixels from screen, metal renderer backend: screen texture must not be a framebufferOnly
assert(!!rt);
if(rt == _defaultRT) // read pixels from screen, metal renderer backend: screen texture must not be a framebufferOnly
backend::Device::getInstance()->setFrameBufferOnly(false);
_commandBuffer->capture(texture, std::move(callback));
_commandBuffer->readPixels(rt, std::move(callback));
}
void Renderer::setRenderPipeline(const PipelineDescriptor& pipelineDescriptor, const backend::RenderPassDescriptor& renderPassDescriptor)
void Renderer::setRenderPipeline(const PipelineDescriptor& pipelineDescriptor, const backend::RenderPassParams& renderPassParams)
{
auto device = backend::Device::getInstance();
_renderPipeline->update(pipelineDescriptor, renderPassDescriptor);
_renderPipeline->update(pipelineDescriptor, _currentRT, renderPassParams);
backend::DepthStencilState* depthStencilState = nullptr;
auto needDepthStencilAttachment = renderPassDescriptor.depthTestEnabled || renderPassDescriptor.stencilTestEnabled;
if (needDepthStencilAttachment)
if (bitmask::any(_currentRT->getTargetFlags(), RenderTargetFlag::DEPTH_AND_STENCIL))
{
// FIXME: don't use autorelease at draw frame
// Now the depthStencilState is in autoreleasepool
depthStencilState = device->createDepthStencilState(_depthStencilDescriptor);
}
_commandBuffer->setDepthStencilState(depthStencilState);
@ -761,125 +779,36 @@ void Renderer::setRenderPipeline(const PipelineDescriptor& pipelineDescriptor, c
#endif
}
void Renderer::beginRenderPass(RenderCommand* cmd)
void Renderer::beginRenderPass()
{
_commandBuffer->beginRenderPass(_renderPassDescriptor);
_commandBuffer->setViewport(_viewport.x, _viewport.y, _viewport.w, _viewport.h);
_commandBuffer->setCullMode(_cullMode);
_commandBuffer->setWinding(_winding);
_commandBuffer->setScissorRect(_scissorState.isEnabled, _scissorState.rect.x, _scissorState.rect.y, _scissorState.rect.width, _scissorState.rect.height);
setRenderPipeline(cmd->getPipelineDescriptor(), _renderPassDescriptor);
_commandBuffer->beginRenderPass(_currentRT, _renderPassParams);
_commandBuffer->setViewport(_viewport.x, _viewport.y, _viewport.w, _viewport.h);
_commandBuffer->setCullMode(_cullMode);
_commandBuffer->setWinding(_winding);
_commandBuffer->setScissorRect(_scissorState.isEnabled, _scissorState.rect.x, _scissorState.rect.y, _scissorState.rect.width, _scissorState.rect.height);
_commandBuffer->setStencilReferenceValue(_stencilRef);
}
void Renderer::setRenderTarget(RenderTargetFlag flags, Texture2D* colorAttachment, Texture2D* depthAttachment, Texture2D* stencilAttachment)
{
_renderTargetFlag = flags;
if (_Bitmask_includes(RenderTargetFlag::COLOR, flags))
{
_renderPassDescriptor.needColorAttachment = true;
if (colorAttachment)
_renderPassDescriptor.colorAttachmentsTexture[0] = colorAttachment->getBackendTexture();
else
_renderPassDescriptor.colorAttachmentsTexture[0] = nullptr;
_colorAttachment = colorAttachment;
}
else
{
_colorAttachment = nullptr;
_renderPassDescriptor.needColorAttachment = false;
_renderPassDescriptor.colorAttachmentsTexture[0] = nullptr;
}
if (_Bitmask_includes(RenderTargetFlag::DEPTH, flags))
{
_renderPassDescriptor.depthTestEnabled = true;
if (depthAttachment)
_renderPassDescriptor.depthAttachmentTexture = depthAttachment->getBackendTexture();
else
_renderPassDescriptor.depthAttachmentTexture = nullptr;
_depthAttachment = depthAttachment;
}
else
{
_renderPassDescriptor.depthTestEnabled = false;
_renderPassDescriptor.depthAttachmentTexture = nullptr;
_depthAttachment = nullptr;
}
if (_Bitmask_includes(RenderTargetFlag::STENCIL, flags))
{
_stencilAttachment = stencilAttachment;
_renderPassDescriptor.stencilTestEnabled = true;
if (_stencilAttachment)
_renderPassDescriptor.stencilAttachmentTexture = stencilAttachment->getBackendTexture();
else
_renderPassDescriptor.stencilAttachmentTexture = nullptr;
}
else
{
_stencilAttachment = nullptr;
_renderPassDescriptor.stencilTestEnabled = false;
_renderPassDescriptor.stencilAttachmentTexture = nullptr;
}
}
void Renderer::clear(ClearFlag flags, const Color4F& color, float depth, unsigned int stencil, float globalOrder)
{
_clearFlag = flags;
CallbackCommand* command = new CallbackCommand();
command->init(globalOrder);
command->func = [=]() -> void {
backend::RenderPassDescriptor descriptor;
backend::RenderPassParams descriptor;
if (_Bitmask_includes(ClearFlag::COLOR, flags))
{
_clearColor = color;
descriptor.clearColorValue = {color.r, color.g, color.b, color.a};
descriptor.needClearColor = true;
descriptor.needColorAttachment = true;
descriptor.colorAttachmentsTexture[0] = _renderPassDescriptor.colorAttachmentsTexture[0];
}
if (_Bitmask_includes(ClearFlag::DEPTH, flags))
{
descriptor.clearDepthValue = depth;
descriptor.needClearDepth = true;
descriptor.depthTestEnabled = true;
descriptor.depthAttachmentTexture = _renderPassDescriptor.depthAttachmentTexture;
}
if (_Bitmask_includes(ClearFlag::STENCIL, flags))
{
descriptor.clearStencilValue = stencil;
descriptor.needClearStencil = true;
descriptor.stencilTestEnabled = true;
descriptor.stencilAttachmentTexture = _renderPassDescriptor.stencilAttachmentTexture;
}
descriptor.flags.clear = flags;
if (bitmask::any(flags, ClearFlag::COLOR)) {
_clearColor = color;
descriptor.clearColorValue = { color.r, color.g, color.b, color.a };
}
_commandBuffer->beginRenderPass(descriptor);
_commandBuffer->endRenderPass();
if(bitmask::any(flags, ClearFlag::DEPTH))
descriptor.clearDepthValue = depth;
delete command;
};
addCommand(command);
}
if(bitmask::any(flags, ClearFlag::STENCIL))
descriptor.clearStencilValue = stencil;
Texture2D* Renderer::getColorAttachment() const
{
return _colorAttachment;
}
Texture2D* Renderer::getDepthAttachment() const
{
return _depthAttachment;
}
Texture2D* Renderer::getStencilAttachment() const
{
return _stencilAttachment;
_commandBuffer->beginRenderPass(_currentRT, descriptor);
_commandBuffer->endRenderPass();
}
const Color4F& Renderer::getClearColor() const
@ -889,12 +818,12 @@ const Color4F& Renderer::getClearColor() const
float Renderer::getClearDepth() const
{
return _renderPassDescriptor.clearDepthValue;
return _renderPassParams.clearDepthValue;
}
unsigned int Renderer::getClearStencil() const
{
return _renderPassDescriptor.clearStencilValue;
return _renderPassParams.clearStencilValue;
}
ClearFlag Renderer::getClearFlag() const
@ -904,7 +833,7 @@ ClearFlag Renderer::getClearFlag() const
RenderTargetFlag Renderer::getRenderTargetFlag() const
{
return _renderTargetFlag;
return _currentRT->getTargetFlags();
}
void Renderer::setScissorTest(bool enabled)

View File

@ -50,6 +50,7 @@ class CommandBuffer;
class RenderPipeline;
class RenderPass;
class TextureBackend;
class RenderTarget;
struct RenderPipelineDescriptor;
struct PixelBufferDescriptor;
}
@ -187,7 +188,11 @@ public:
@stencilAttachment The value to replace stencil attachment. Depth attachment and stencil attachment
can be the same value.
*/
void setRenderTarget(RenderTargetFlag flags, Texture2D* colorAttachment, Texture2D* depthAttachment, Texture2D* stencilAttachment);
backend::RenderTarget* getRenderTarget() const { return _currentRT; }
void setRenderTarget(backend::RenderTarget* rt) { _currentRT = rt; };
backend::RenderTarget* getDefaultRenderTarget() const { return _defaultRT; }
/**
Set clear values for each attachment.
@flags Flags to indicate which attachment clear value to be modified.
@ -197,24 +202,6 @@ public:
*/
void clear(ClearFlag flags, const Color4F& color, float depth, unsigned int stencil, float globalOrder);
/**
* Get color attachment.
* @return Color attachment.
*/
Texture2D* getColorAttachment() const;
/**
* Get depth attachment.
* @return Depth attachment.
*/
Texture2D* getDepthAttachment() const;
/**
* Get stencil attachment.
* @return Stencil attachment.
*/
Texture2D* getStencilAttachment() const;
/**
* Get color clear value.
* @return Color clear value.
@ -407,8 +394,8 @@ public:
/** returns whether or not a rectangle is visible or not */
bool checkVisibility(const Mat4& transform, const Size& size);
/** read pixels from texture or screen framebuffer */
void readPixels(backend::TextureBackend* texture, std::function<void(const backend::PixelBufferDescriptor&)> callback);
/** read pixels from RenderTarget or screen framebuffer */
void readPixels(backend::RenderTarget* rt, std::function<void(const backend::PixelBufferDescriptor&)> callback);
protected:
friend class Director;
@ -474,15 +461,15 @@ protected:
void doVisitRenderQueue(const std::vector<RenderCommand*>&);
void fillVerticesAndIndices(const TrianglesCommand* cmd, unsigned int vertexBufferOffset);
void beginRenderPass(RenderCommand*); /// Begin a render pass.
void beginRenderPass(); /// Begin a render pass.
/**
* Building a programmable pipeline involves an expensive evaluation of GPU state.
* So a new render pipeline object will be created only if it hasn't been created before.
* @param pipelineDescriptor Specifies the pipeline descriptor.
* @param renderPassDescriptor Specifies the render pass descriptor.
* @param renderPassParams Specifies the render pass descriptor.
*/
void setRenderPipeline(const PipelineDescriptor&, const backend::RenderPassDescriptor&);
void setRenderPipeline(const PipelineDescriptor&, const backend::RenderPassParams&);
void pushStateBlock();
@ -508,7 +495,7 @@ protected:
TriangleCommandBufferManager _triangleCommandBufferManager;
backend::CommandBuffer* _commandBuffer = nullptr;
backend::RenderPassDescriptor _renderPassDescriptor;
backend::RenderPassParams _renderPassParams;
backend::DepthStencilDescriptor _depthStencilDescriptor;
// Internal structure that has the information for the batches
@ -541,13 +528,11 @@ protected:
unsigned int _stencilRef = 0;
// weak reference
Texture2D* _colorAttachment = nullptr;
Texture2D* _depthAttachment = nullptr;
Texture2D* _stencilAttachment = nullptr;
backend::RenderTarget* _defaultRT = nullptr;
backend::RenderTarget* _currentRT = nullptr; // weak ref
Color4F _clearColor = Color4F::BLACK;
ClearFlag _clearFlag;
RenderTargetFlag _renderTargetFlag = RenderTargetFlag::COLOR;
struct ScissorState
{

View File

@ -28,7 +28,7 @@ set(COCOS_RENDERER_HEADER
renderer/backend/Program.h
renderer/backend/ProgramCache.h
renderer/backend/Macros.h
renderer/backend/RenderPassDescriptor.h
renderer/backend/RenderPassParams.h
renderer/backend/RenderPipeline.h
renderer/backend/RenderPipelineDescriptor.h
renderer/backend/ShaderModule.h
@ -74,7 +74,7 @@ set(COCOS_RENDERER_SRC
renderer/backend/ProgramState.cpp
renderer/backend/ProgramStateRegistry.cpp
renderer/backend/ShaderCache.cpp
renderer/backend/RenderPassDescriptor.cpp
renderer/backend/RenderPassParams.cpp
)
if(ANDROID OR WINDOWS OR LINUX OR (IOS AND CC_FORCE_USE_GLES))
@ -90,6 +90,7 @@ list(APPEND COCOS_RENDERER_HEADER
renderer/backend/opengl/TextureGL.h
renderer/backend/opengl/UtilsGL.h
renderer/backend/opengl/DeviceInfoGL.h
renderer/backend/opengl/RenderTargetGL.h
)
list(APPEND COCOS_RENDERER_SRC
@ -103,6 +104,7 @@ list(APPEND COCOS_RENDERER_SRC
renderer/backend/opengl/TextureGL.cpp
renderer/backend/opengl/UtilsGL.cpp
renderer/backend/opengl/DeviceInfoGL.cpp
renderer/backend/opengl/RenderTargetGL.cpp
)
else()
@ -111,6 +113,7 @@ list(APPEND COCOS_RENDERER_HEADER
renderer/backend/metal/BufferMTL.h
renderer/backend/metal/BufferManager.h
renderer/backend/metal/CommandBufferMTL.h
renderer/backend/metal/RenderTargetMTL.h
renderer/backend/metal/DepthStencilStateMTL.h
renderer/backend/metal/DeviceMTL.h
renderer/backend/metal/RenderPipelineMTL.h
@ -125,6 +128,7 @@ list(APPEND COCOS_RENDERER_SRC
renderer/backend/metal/BufferMTL.mm
renderer/backend/metal/BufferManager.mm
renderer/backend/metal/CommandBufferMTL.mm
renderer/backend/metal/RenderTargetMTL.mm
renderer/backend/metal/DepthStencilStateMTL.mm
renderer/backend/metal/DeviceMTL.mm
renderer/backend/metal/RenderPipelineMTL.mm

View File

@ -24,7 +24,7 @@
#pragma once
#include "renderer/backend/RenderPassDescriptor.h"
#include "renderer/backend/RenderPassParams.h"
#include "renderer/backend/RenderPipeline.h"
#include "renderer/backend/RenderPipelineDescriptor.h"
#include "renderer/backend/Device.h"

View File

@ -31,7 +31,7 @@
#include "Macros.h"
#include "Types.h"
#include "RenderPassDescriptor.h"
#include "RenderPassParams.h"
#include "PixelBufferDescriptor.h"
#include "CCStdC.h"
#include "ProgramState.h"
@ -47,6 +47,7 @@ class RenderPipeline;
class Buffer;
class DepthStencilState;
class TextureBackend;
class RenderTarget;
/**
* @addtogroup _backend
@ -70,7 +71,7 @@ public:
* Begin a render pass, initial color, depth and stencil attachment.
* @param descriptor Specifies a group of render targets that hold the results of a render pass.
*/
virtual void beginRenderPass(const RenderPassDescriptor& descriptor) = 0;
virtual void beginRenderPass(const RenderTarget* renderTarget, const RenderPassParams& descriptor) = 0;
/**
* Sets the current render pipeline state object.
@ -172,7 +173,7 @@ public:
* Get a screen snapshot
* @param callback A callback to deal with screen snapshot image.
*/
virtual void capture(TextureBackend* texture, std::function<void(const PixelBufferDescriptor&)> callback) = 0;
virtual void readPixels(RenderTarget* rt, std::function<void(const PixelBufferDescriptor&)> callback) = 0;
/**
* Update both front and back stencil reference value.

View File

@ -27,7 +27,7 @@
#include "Macros.h"
#include "Types.h"
#include "RenderPipelineDescriptor.h"
#include "RenderPassDescriptor.h"
#include "RenderPassParams.h"
#include "Texture.h"
#include "DepthStencilState.h"
#include "ProgramCache.h"
@ -45,6 +45,7 @@ class Buffer;
class ShaderModule;
class RenderPipeline;
class RenderPass;
class RenderTarget;
/**
* @addtogroup _backend
@ -89,6 +90,13 @@ public:
*/
virtual TextureBackend* newTexture(const TextureDescriptor& descriptor) = 0;
virtual RenderTarget* newDefaultRenderTarget(TargetBufferFlags rtf) = 0;
virtual RenderTarget* newRenderTarget(TargetBufferFlags rtf,
TextureBackend* colorAttachment = nullptr,
TextureBackend* depthAttachment = nullptr,
TextureBackend* stencilAttachhment = nullptr) = 0;
/**
* Create an auto released DepthStencilState object.
* @param descriptor Specifies depth and stencil description.

View File

@ -27,7 +27,7 @@
#define CC_BACKEND_BEGIN namespace cocos2d{ namespace backend{
#define CC_BACKEND_END }}
#define MAX_COLOR_ATTCHMENT 1
#define MAX_COLOR_ATTCHMENT 4
#define MAX_INFLIGHT_BUFFER 3

View File

@ -1,70 +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 "RenderPassDescriptor.h"
CC_BACKEND_BEGIN
RenderPassDescriptor& RenderPassDescriptor::operator=(const RenderPassDescriptor& descriptor)
{
clearDepthValue = descriptor.clearDepthValue;
clearStencilValue = descriptor.clearStencilValue;
clearColorValue = descriptor.clearColorValue;
needColorAttachment = descriptor.needColorAttachment;
depthTestEnabled = descriptor.depthTestEnabled;
stencilTestEnabled = descriptor.stencilTestEnabled;
needClearColor = descriptor.needClearColor;
needClearDepth = descriptor.needClearDepth;
needClearStencil = descriptor.needClearStencil;
depthAttachmentTexture = descriptor.depthAttachmentTexture;
stencilAttachmentTexture = descriptor.stencilAttachmentTexture;
colorAttachmentsTexture[0] = descriptor.colorAttachmentsTexture[0];
return *this;
}
bool RenderPassDescriptor::operator==(const RenderPassDescriptor& descriptor) const
{
if( clearDepthValue == descriptor.clearDepthValue &&
clearStencilValue == descriptor.clearStencilValue &&
clearColorValue == descriptor.clearColorValue &&
needColorAttachment == descriptor.needColorAttachment &&
depthTestEnabled == descriptor.depthTestEnabled &&
stencilTestEnabled == descriptor.stencilTestEnabled &&
needClearColor == descriptor.needClearColor &&
needClearDepth == descriptor.needClearDepth &&
needClearStencil == descriptor.needClearStencil &&
depthAttachmentTexture == descriptor.depthAttachmentTexture &&
stencilAttachmentTexture == descriptor.stencilAttachmentTexture &&
colorAttachmentsTexture[0] == descriptor.colorAttachmentsTexture[0])
{
return true;
}
else
{
return false;
}
}
CC_BACKEND_END

View File

@ -0,0 +1,42 @@
/****************************************************************************
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 "RenderPassParams.h"
CC_BACKEND_BEGIN
bool RenderPassParams::operator==(const RenderPassParams& descriptor) const
{
return (clearDepthValue == descriptor.clearDepthValue &&
clearStencilValue == descriptor.clearStencilValue &&
clearColorValue == descriptor.clearColorValue &&
// needColorAttachment == descriptor.needColorAttachment &&
// depthTestEnabled == descriptor.depthTestEnabled &&
// stencilTestEnabled == descriptor.stencilTestEnabled &&
flags.clear == descriptor.flags.clear &&
flags.discardStart == descriptor.flags.discardStart &&
flags.discardEnd == descriptor.flags.discardEnd);
}
CC_BACKEND_END

View File

@ -38,28 +38,43 @@ class TextureBackend;
* @{
*/
struct RenderPassFlags {
/**
* bitmask indicating which buffers to clear at the beginning of a render pass.
* This implies discard.
*/
TargetBufferFlags clear;
/**
* bitmask indicating which buffers to discard at the beginning of a render pass.
* Discarded buffers have uninitialized content, they must be entirely drawn over or cleared.
*/
TargetBufferFlags discardStart;
/**
* bitmask indicating which buffers to discard at the end of a render pass.
* Discarded buffers' content becomes invalid, they must not be read from again.
*/
TargetBufferFlags discardEnd;
};
/**
* Store values about color, depth and stencil attachment.
*/
struct RenderPassDescriptor
struct RenderPassParams
{
RenderPassDescriptor& operator=(const RenderPassDescriptor& descriptor);
bool operator==(const RenderPassDescriptor& descriptor) const;
bool needDepthStencilAttachment() const { return depthTestEnabled || stencilTestEnabled; }
RenderPassParams& operator=(const RenderPassParams& descriptor) = default;
bool operator==(const RenderPassParams& descriptor) const;
float clearDepthValue = 0.f;
float clearStencilValue = 0.f;
std::array<float, 4> clearColorValue {{0.f, 0.f, 0.f, 0.f}}; // double-braces required in C++11
bool needColorAttachment = true;
bool depthTestEnabled = false;
bool stencilTestEnabled = false;
bool needClearColor = false;
bool needClearDepth = false;
bool needClearStencil = false;
TextureBackend* depthAttachmentTexture = nullptr;
TextureBackend* stencilAttachmentTexture = nullptr;
TextureBackend* colorAttachmentsTexture[MAX_COLOR_ATTCHMENT] = { nullptr };
// Now, only clear flag used
RenderPassFlags flags{};
};
typedef RenderPassParams RenderPassParams;
//end of _backend group
/// @}

View File

@ -28,13 +28,14 @@
#include "Types.h"
#include "base/CCRef.h"
#include "renderer/CCPipelineDescriptor.h"
#include "renderer/backend/RenderPassDescriptor.h"
#include "renderer/backend/RenderPassParams.h"
CC_BACKEND_BEGIN
/**
* @addtogroup _backend
* @{
*/
class RenderTarget;
/**
* Render pipeline
@ -42,7 +43,7 @@ CC_BACKEND_BEGIN
class RenderPipeline : public cocos2d::Ref
{
public:
virtual void update(const PipelineDescriptor & pipelineDescirptor, const RenderPassDescriptor& renderpassDescriptor) = 0;
virtual void update(const PipelineDescriptor & pipelineDescirptor, const RenderTarget* renderTarget, const RenderPassParams& renderPassParams) = 0;
protected:
virtual ~RenderPipeline() = default;

View File

@ -0,0 +1,72 @@
#pragma once
#include "base/CCRef.h"
#include "Texture.h"
#include <assert.h>
CC_BACKEND_BEGIN
class RenderTarget : public cocos2d::Ref {
public:
struct RenderBuffer {
TextureBackend* texture = nullptr;
uint8_t level = 0; // level when attached to a texture
explicit operator bool() const {
return texture != nullptr;
}
};
typedef RenderBuffer ColorAttachment[MAX_COLOR_ATTCHMENT];
RenderTarget(bool defaultRenderTarget) : _defaultRenderTarget(defaultRenderTarget) {}
virtual ~RenderTarget()
{
for (auto colorItem : _color)
CC_SAFE_RELEASE(colorItem.texture);
CC_SAFE_RELEASE(_depth.texture);
CC_SAFE_RELEASE(_stencil.texture);
}
void setTargetFlags(TargetBufferFlags flags) { _flags = flags; }
TargetBufferFlags getTargetFlags() const { return _flags; }
void modifyTargetFlags(TargetBufferFlags flagsToAdd, TargetBufferFlags flagsToRemove)
{
_flags |= flagsToAdd;
_flags &= ~flagsToRemove;
}
virtual void bindFrameBuffer() const {};
virtual void unbindFrameBuffer() const {};
virtual void setColorAttachment(ColorAttachment attachment) {
for (auto colorItem : _color)
CC_SAFE_RELEASE(colorItem.texture);
memcpy(_color, attachment, sizeof(ColorAttachment));
for (auto colorItem : _color)
CC_SAFE_RETAIN(colorItem.texture);
};
virtual void setDepthAttachment(TextureBackend* attachment, int level = 0)
{
CC_SAFE_RELEASE(_depth.texture);
_depth.texture = attachment;
_depth.level = level;
CC_SAFE_RETAIN(_depth.texture);
};
virtual void setStencilAttachment(TextureBackend* attachment, int level = 0) {
CC_SAFE_RELEASE(_stencil.texture);
_stencil.texture = attachment;
_stencil.level = level;
CC_SAFE_RETAIN(_stencil.texture);
};
bool isDefaultRenderTarget() const { return _defaultRenderTarget; }
bool _defaultRenderTarget = false;
ColorAttachment _color{};
RenderBuffer _depth{};
RenderBuffer _stencil{};
TargetBufferFlags _flags{};
// uint8_t samples = 1;
};
CC_BACKEND_END

View File

@ -51,14 +51,11 @@ struct TextureDescriptor
SamplerDescriptor samplerDescriptor;
};
struct UtilsGL;
/**
* A base texture
*/
class TextureBackend : public Ref
{
friend struct UtilsGL;
public:
/**
* Update sampler
@ -106,6 +103,8 @@ public:
int getWidth() const { return _width; }
int getHeight() const { return _height; }
int getBytesPerRow() const { return _width * _bitsPerElement / 8; }
protected:
/**
* @param descriptor Specifies the texture descirptor.

View File

@ -27,6 +27,7 @@
#include "Macros.h"
#include <assert.h>
#include <cstdint>
#include <string>
#include "base/bitmask.h"
@ -258,6 +259,33 @@ enum class ColorWriteMask : uint32_t
CC_ENABLE_BITMASK_OPS(ColorWriteMask)
CC_ENABLE_BITSHIFT_OPS(ColorWriteMask)
/**
* Bitmask for selecting render buffers
*/
enum class TargetBufferFlags : uint8_t {
NONE = 0x0u, //!< No buffer selected.
COLOR0 = 0x1u, //!< Color buffer selected.
COLOR1 = 0x2u, //!< Color buffer selected.
COLOR2 = 0x4u, //!< Color buffer selected.
COLOR3 = 0x8u, //!< Color buffer selected.
COLOR = COLOR0, //!< \deprecated
COLOR_ALL = COLOR0 | COLOR1 | COLOR2 | COLOR3,
DEPTH = 0x10u, //!< Depth buffer selected.
STENCIL = 0x20u, //!< Stencil buffer selected.
DEPTH_AND_STENCIL = DEPTH | STENCIL, //!< depth and stencil buffer selected.
ALL = COLOR_ALL | DEPTH | STENCIL //!< Color, depth and stencil buffer selected.
};
CC_ENABLE_BITMASK_OPS(TargetBufferFlags)
inline TargetBufferFlags getMRTColorFlag(size_t index) noexcept {
assert(index < 4);
return TargetBufferFlags(1u << index);
}
typedef TargetBufferFlags ClearFlag;
typedef TargetBufferFlags RenderTargetFlag;
struct SamplerDescriptor
{
SamplerFilter magFilter = SamplerFilter::LINEAR;
@ -418,4 +446,6 @@ struct BlendDescriptor
BlendFactor sourceAlphaBlendFactor = BlendFactor::ONE;
BlendFactor destinationAlphaBlendFactor = BlendFactor::ZERO;
};
CC_BACKEND_END

View File

@ -61,11 +61,11 @@ public:
virtual void beginFrame() override;
/**
* Create a MTLRenderCommandEncoder object for graphics rendering to an attachment in a RenderPassDescriptor.
* MTLRenderCommandEncoder is cached if current RenderPassDescriptor is identical to previous one.
* Create a MTLRenderCommandEncoder object for graphics rendering to an attachment in a RenderPassParams.
* MTLRenderCommandEncoder is cached if current RenderPassParams is identical to previous one.
* @param descriptor Specifies a group of render targets that hold the results of a render pass.
*/
virtual void beginRenderPass(const RenderPassDescriptor& descriptor) override;
virtual void beginRenderPass(const RenderTarget* renderTarget, const RenderPassParams& descriptor) override;
/**
* Sets the current render pipeline state object.
@ -166,10 +166,22 @@ public:
virtual void setDepthStencilState(DepthStencilState* depthStencilState) override;
/**
* Get a screen snapshot
* @param callback A callback to deal with screen snapshot image.
* Read pixels from RenderTarget
* @param callback A callback to deal with pixel data read.
*/
virtual void capture(TextureBackend* texture, std::function<void(const PixelBufferDescriptor&)> callback) override;
virtual void readPixels(RenderTarget* rt, std::function<void(const PixelBufferDescriptor&)> callback) override;
protected:
/**
* Read a block of pixels from the given texture
* @param texture Specifies the texture to get the image.
* @param origX,origY Specify the window coordinates of the first pixel that is read from the given texture. This location is the lower left corner of a rectangular block of pixels.
* @param rectWidth,rectHeight Specify the dimensions of the pixel rectangle. rectWidth and rectHeight of one correspond to a single pixel.
* @param pbd, the output buffer for fill texels data
* @remark: !!!this function only can call after endFrame, then it's could be works well.
*/
static void readPixels(TextureBackend* texture, std::size_t origX, std::size_t origY, std::size_t rectWidth, std::size_t rectHeight, PixelBufferDescriptor& pbd);
static void readPixels(id<MTLTexture> texture, std::size_t origX, std::size_t origY, std::size_t rectWidth, std::size_t rectHeight, PixelBufferDescriptor& pbd);
private:
void prepareDrawing() const;
@ -179,7 +191,7 @@ private:
void afterDraw();
void flush();
void flushCaptureCommands();
id<MTLRenderCommandEncoder> getRenderCommandEncoder(const RenderPassDescriptor& renderPassDescriptor);
id<MTLRenderCommandEncoder> getRenderCommandEncoder(const RenderTarget* renderTarget, const RenderPassParams& renderPassParams);
id<MTLCommandBuffer> _mtlCommandBuffer = nil;
id<MTLCommandQueue> _mtlCommandQueue = nil;
@ -195,7 +207,8 @@ private:
unsigned int _renderTargetHeight = 0;
dispatch_semaphore_t _frameBoundarySemaphore;
RenderPassDescriptor _prevRenderPassDescriptor;
const RenderTarget* _currentRenderTarget = nil; // weak ref
RenderPassParams _currentRenderPassParams;
NSAutoreleasePool* _autoReleasePool = nil;
std::vector<std::pair<TextureBackend*,std::function<void(const PixelBufferDescriptor&)>>> _captureCallbacks;

View File

@ -32,12 +32,46 @@
#include "../Macros.h"
#include "BufferManager.h"
#include "DepthStencilStateMTL.h"
#include "RenderTargetMTL.h"
CC_BACKEND_BEGIN
namespace
{
MTLWinding toMTLWinding(Winding winding)
#define byte(n) ((n) * 8)
#define bit(n) (n)
static uint8_t getBitsPerElementMTL(MTLPixelFormat pixleFormat)
{
switch (pixleFormat)
{
case MTLPixelFormatDepth32Float_Stencil8:
return byte(8);
case MTLPixelFormatBGRA8Unorm:
case MTLPixelFormatRGBA8Unorm:
case MTLPixelFormatDepth32Float:
return byte(4);
#if (CC_TARGET_PLATFORM == CC_PLATFORM_MAC)
case MTLPixelFormatDepth24Unorm_Stencil8:
return byte(4);
#else
case MTLPixelFormatABGR4Unorm:
case MTLPixelFormatBGR5A1Unorm:
case MTLPixelFormatB5G6R5Unorm:
case MTLPixelFormatA1BGR5Unorm:
return byte(2);
#endif
case MTLPixelFormatA8Unorm:
case MTLPixelFormatR8Unorm:
return byte(1);
default:
assert(false);
break;
}
return 0;
}
static MTLWinding toMTLWinding(Winding winding)
{
if (Winding::CLOCK_WISE == winding)
return MTLWindingClockwise;
@ -45,7 +79,7 @@ namespace
return MTLWindingCounterClockwise;
}
MTLPrimitiveType toMTLPrimitive(PrimitiveType primitiveType)
static MTLPrimitiveType toMTLPrimitive(PrimitiveType primitiveType)
{
MTLPrimitiveType ret = MTLPrimitiveTypeTriangle;
switch (primitiveType)
@ -71,7 +105,7 @@ namespace
return ret;
}
MTLIndexType toMTLIndexType(IndexFormat indexFormat)
static MTLIndexType toMTLIndexType(IndexFormat indexFormat)
{
if (IndexFormat::U_SHORT == indexFormat)
return MTLIndexTypeUInt16;
@ -79,7 +113,7 @@ namespace
return MTLIndexTypeUInt32;
}
MTLCullMode toMTLCullMode(CullMode mode)
static MTLCullMode toMTLCullMode(CullMode mode)
{
switch (mode) {
case CullMode::NONE:
@ -91,109 +125,21 @@ namespace
}
}
MTLRenderPassDescriptor* toMTLRenderPassDescriptor(const RenderPassDescriptor& descriptor)
static MTLRenderPassDescriptor* toMTLRenderPassDescriptor(const RenderTarget* rt, const RenderPassParams& params)
{
MTLRenderPassDescriptor* mtlDescritpor = [MTLRenderPassDescriptor renderPassDescriptor];
// Set color attachments.
if (descriptor.needColorAttachment)
{
bool hasCustomColorAttachment = false;
for (int i = 0; i < MAX_COLOR_ATTCHMENT; ++i)
{
if (! descriptor.colorAttachmentsTexture[i])
continue;
mtlDescritpor.colorAttachments[i].texture = static_cast<TextureMTL*>(descriptor.colorAttachmentsTexture[i])->getMTLTexture();
if (descriptor.needClearColor)
{
mtlDescritpor.colorAttachments[i].loadAction = MTLLoadActionClear;
mtlDescritpor.colorAttachments[i].clearColor = MTLClearColorMake(descriptor.clearColorValue[0],
descriptor.clearColorValue[1],
descriptor.clearColorValue[2],
descriptor.clearColorValue[3]);
}
else
mtlDescritpor.colorAttachments[i].loadAction = MTLLoadActionLoad;
hasCustomColorAttachment = true;
}
if (!hasCustomColorAttachment)
{
mtlDescritpor.colorAttachments[0].texture = DeviceMTL::getCurrentDrawable().texture;
if (descriptor.needClearColor)
{
mtlDescritpor.colorAttachments[0].loadAction = MTLLoadActionClear;
mtlDescritpor.colorAttachments[0].clearColor = MTLClearColorMake(descriptor.clearColorValue[0],
descriptor.clearColorValue[1],
descriptor.clearColorValue[2],
descriptor.clearColorValue[3]);
}
else
mtlDescritpor.colorAttachments[0].loadAction = MTLLoadActionLoad;
}
mtlDescritpor.colorAttachments[0].storeAction = MTLStoreActionStore;
}
if(descriptor.needDepthStencilAttachment())
{
// Set depth attachment
{
if (descriptor.depthAttachmentTexture)
mtlDescritpor.depthAttachment.texture = static_cast<TextureMTL*>(descriptor.depthAttachmentTexture)->getMTLTexture();
else
mtlDescritpor.depthAttachment.texture = UtilsMTL::getDefaultDepthStencilTexture();
if (descriptor.needClearDepth)
{
mtlDescritpor.depthAttachment.loadAction = MTLLoadActionClear;
mtlDescritpor.depthAttachment.clearDepth = descriptor.clearDepthValue;
}
else
mtlDescritpor.depthAttachment.loadAction = MTLLoadActionLoad;
mtlDescritpor.depthAttachment.storeAction = MTLStoreActionStore;
}
// Set stencil attachment
{
if (descriptor.stencilAttachmentTexture)
mtlDescritpor.stencilAttachment.texture = static_cast<TextureMTL*>(descriptor.stencilAttachmentTexture)->getMTLTexture();
else
mtlDescritpor.stencilAttachment.texture = UtilsMTL::getDefaultDepthStencilTexture();
if (descriptor.needClearStencil)
{
mtlDescritpor.stencilAttachment.loadAction = MTLLoadActionClear;
mtlDescritpor.stencilAttachment.clearStencil = descriptor.clearStencilValue;
}
else
mtlDescritpor.stencilAttachment.loadAction = MTLLoadActionLoad;
mtlDescritpor.stencilAttachment.storeAction = MTLStoreActionStore;
}
}
auto rtMTL = static_cast<const RenderTargetMTL*>(rt);
rtMTL->applyRenderPassAttachments(params, mtlDescritpor);
return mtlDescritpor;
}
id<MTLTexture> getMTLTexture(TextureBackend* texture, int index = 0)
static id<MTLTexture> getMTLTexture(TextureBackend* texture, int index)
{
switch (texture->getTextureType())
{
case TextureType::TEXTURE_2D:
return static_cast<TextureMTL*>(texture)->getMTLTexture(index);
case TextureType::TEXTURE_CUBE:
return static_cast<TextureCubeMTL*>(texture)->getMTLTexture(index);
default:
assert(false);
return nil;
}
return reinterpret_cast<id<MTLTexture>>(texture->getHandler(index));
}
id<MTLSamplerState> getMTLSamplerState(TextureBackend* texture)
static id<MTLSamplerState> getMTLSamplerState(TextureBackend* texture)
{
switch (texture->getTextureType())
{
@ -242,15 +188,16 @@ void CommandBufferMTL::beginFrame()
BufferManager::beginFrame();
}
id<MTLRenderCommandEncoder> CommandBufferMTL::getRenderCommandEncoder(const RenderPassDescriptor& renderPassDescriptor)
id<MTLRenderCommandEncoder> CommandBufferMTL::getRenderCommandEncoder(const RenderTarget* renderTarget, const RenderPassParams& renderPassParams)
{
if(_mtlRenderEncoder != nil && _prevRenderPassDescriptor == renderPassDescriptor)
if(_mtlRenderEncoder != nil && _currentRenderPassParams == renderPassParams && _currentRenderTarget == renderTarget)
{
return _mtlRenderEncoder;
}
else
{
_prevRenderPassDescriptor = renderPassDescriptor;
_currentRenderTarget = renderTarget;
_currentRenderPassParams = renderPassParams;
}
if(_mtlRenderEncoder != nil)
@ -260,7 +207,7 @@ id<MTLRenderCommandEncoder> CommandBufferMTL::getRenderCommandEncoder(const Rend
_mtlRenderEncoder = nil;
}
auto mtlDescriptor = toMTLRenderPassDescriptor(renderPassDescriptor);
auto mtlDescriptor = toMTLRenderPassDescriptor(renderTarget, renderPassParams);
_renderTargetWidth = (unsigned int)mtlDescriptor.colorAttachments[0].texture.width;
_renderTargetHeight = (unsigned int)mtlDescriptor.colorAttachments[0].texture.height;
id<MTLRenderCommandEncoder> mtlRenderEncoder = [_mtlCommandBuffer renderCommandEncoderWithDescriptor:mtlDescriptor];
@ -269,9 +216,9 @@ id<MTLRenderCommandEncoder> CommandBufferMTL::getRenderCommandEncoder(const Rend
return mtlRenderEncoder;
}
void CommandBufferMTL::beginRenderPass(const RenderPassDescriptor& descriptor)
void CommandBufferMTL::beginRenderPass(const RenderTarget* renderTarget, const RenderPassParams& descriptor)
{
_mtlRenderEncoder = getRenderCommandEncoder(descriptor);
_mtlRenderEncoder = getRenderCommandEncoder(renderTarget, descriptor);
// [_mtlRenderEncoder setFrontFacingWinding:MTLWindingCounterClockwise];
}
@ -355,8 +302,13 @@ void CommandBufferMTL::endRenderPass()
}
void CommandBufferMTL::capture(TextureBackend* texture, std::function<void(const PixelBufferDescriptor&)> callback)
void CommandBufferMTL::readPixels(RenderTarget* rt, std::function<void(const PixelBufferDescriptor&)> callback)
{
auto rtMTL = static_cast<RenderTargetMTL*>(rt);
// we only read form color attachment 0
// if it's nullptr, will regard as screen to perform capture
auto texture = rtMTL->_color[0].texture;
CC_SAFE_RETAIN(texture);
_captureCallbacks.emplace_back(texture, std::move(callback));
}
@ -407,7 +359,7 @@ void CommandBufferMTL::flushCaptureCommands()
for(auto& cb : _captureCallbacks) {
if(cb.first == nil) { // screen capture
if(!screenPixelData) {
UtilsMTL::readPixels(_drawableTexture, 0, 0, [_drawableTexture width], [_drawableTexture height], screenPixelData);
CommandBufferMTL::readPixels(_drawableTexture, 0, 0, [_drawableTexture width], [_drawableTexture height], screenPixelData);
// screen framebuffer copied, restore screen framebuffer only to true
backend::Device::getInstance()->setFrameBufferOnly(true);
}
@ -417,7 +369,7 @@ void CommandBufferMTL::flushCaptureCommands()
PixelBufferDescriptor pixelData;
auto texture = cb.first;
assert(texture != nullptr);
UtilsMTL::readPixels(texture, 0, 0, texture->getWidth(), texture->getHeight(), pixelData);
CommandBufferMTL::readPixels(texture, 0, 0, texture->getWidth(), texture->getHeight(), pixelData);
CC_SAFE_RELEASE(texture);
cb.second(pixelData);
}
@ -570,5 +522,52 @@ void CommandBufferMTL::setScissorRect(bool isEnabled, float x, float y, float wi
[_mtlRenderEncoder setScissorRect:scissorRect];
}
void CommandBufferMTL::readPixels(TextureBackend* texture, std::size_t origX, std::size_t origY, std::size_t rectWidth, std::size_t rectHeight, PixelBufferDescriptor& pbd)
{
CommandBufferMTL::readPixels(reinterpret_cast<id<MTLTexture>>(texture->getHandler()), origX, origY, rectWidth, rectHeight, pbd);
}
void CommandBufferMTL::readPixels(id<MTLTexture> texture, std::size_t origX, std::size_t origY, std::size_t rectWidth, std::size_t rectHeight, PixelBufferDescriptor& pbd)
{
NSUInteger texWidth = texture.width;
NSUInteger texHeight = texture.height;
MTLRegion region = MTLRegionMake2D(0, 0, texWidth, texHeight);
MTLRegion imageRegion = MTLRegionMake2D(origX, origY, rectWidth, rectHeight);
MTLTextureDescriptor* textureDescriptor =
[MTLTextureDescriptor texture2DDescriptorWithPixelFormat:[texture pixelFormat]
width:texWidth
height:texHeight
mipmapped:NO];
id<MTLDevice> device = static_cast<DeviceMTL*>(DeviceMTL::getInstance())->getMTLDevice();
id<MTLTexture> readPixelsTexture = [device newTextureWithDescriptor:textureDescriptor];
id<MTLCommandQueue> commandQueue = static_cast<DeviceMTL*>(DeviceMTL::getInstance())->getMTLCommandQueue();
auto commandBuffer = [commandQueue commandBuffer];
// [commandBuffer enqueue];
id<MTLBlitCommandEncoder> blitCommandEncoder = [commandBuffer blitCommandEncoder];
[blitCommandEncoder copyFromTexture:texture sourceSlice:0 sourceLevel:0 sourceOrigin:region.origin sourceSize:region.size toTexture:readPixelsTexture destinationSlice:0 destinationLevel:0 destinationOrigin:region.origin];
#if (CC_TARGET_PLATFORM == CC_PLATFORM_MAC)
[blitCommandEncoder synchronizeResource:readPixelsTexture];
#endif
[blitCommandEncoder endEncoding];
[commandBuffer addCompletedHandler:^(id<MTLCommandBuffer> commandBufferMTL) {
auto bytePerRow = rectWidth * getBitsPerElementMTL(texture.pixelFormat) / 8;
auto texelData = pbd._data.resize(bytePerRow * rectHeight);
if(texelData != nullptr)
{
[readPixelsTexture getBytes:texelData bytesPerRow:bytePerRow fromRegion:imageRegion mipmapLevel:0];
UtilsMTL::swizzleImage(texelData, rectWidth, rectHeight, readPixelsTexture.pixelFormat);
pbd._width = rectWidth;
pbd._height = rectHeight;
}
[readPixelsTexture release];
}];
[commandBuffer commit];
[commandBuffer waitUntilCompleted];
}
CC_BACKEND_END

View File

@ -95,6 +95,12 @@ public:
* @return A TextureBackend object.
*/
virtual TextureBackend* newTexture(const TextureDescriptor& descriptor) override;
RenderTarget* newDefaultRenderTarget(TargetBufferFlags rtf) override;
RenderTarget* newRenderTarget(TargetBufferFlags rtf,
TextureBackend* colorAttachment,
TextureBackend* depthAttachment,
TextureBackend* stencilAttachhment) override;
/**
* Create a DepthStencilState object.

View File

@ -31,6 +31,7 @@
#include "TextureMTL.h"
#include "ProgramMTL.h"
#include "DeviceInfoMTL.h"
#include "RenderTargetMTL.h"
#include "base/ccMacros.h"
@ -108,6 +109,27 @@ TextureBackend* DeviceMTL::newTexture(const TextureDescriptor& descriptor)
}
}
RenderTarget* DeviceMTL::newDefaultRenderTarget(TargetBufferFlags rtf)
{
auto rtGL = new RenderTargetMTL(true);
rtGL->setTargetFlags(rtf);
return rtGL;
}
RenderTarget* DeviceMTL::newRenderTarget(TargetBufferFlags rtf,
TextureBackend* colorAttachment,
TextureBackend* depthAttachment,
TextureBackend* stencilAttachhment)
{
auto rtGL = new RenderTargetMTL(false);
rtGL->setTargetFlags(rtf);
rtGL->bindFrameBuffer();
rtGL->setColorAttachment(RenderTarget::ColorAttachment{ { colorAttachment, 0 } });
rtGL->setDepthAttachment(depthAttachment);
rtGL->setStencilAttachment(stencilAttachhment);
return rtGL;
}
ShaderModule* DeviceMTL::newShaderModule(ShaderStage stage, const std::string& source)
{
return new (std::nothrow) ShaderModuleMTL(_mtlDevice, stage, source);

View File

@ -49,7 +49,7 @@ public:
*/
RenderPipelineMTL(id<MTLDevice> mtlDevice);
~RenderPipelineMTL();
virtual void update(const PipelineDescriptor&, const RenderPassDescriptor&) override;
virtual void update(const PipelineDescriptor&, const RenderTarget* renderTarget, const RenderPassParams& renderPassParams) override;
/**
* Get a MTLRenderPipelineState object.
@ -61,14 +61,14 @@ private:
void setVertexLayout(MTLRenderPipelineDescriptor*, const PipelineDescriptor&);
void setBlendState(MTLRenderPipelineColorAttachmentDescriptor*, const BlendDescriptor&);
void setShaderModules(const PipelineDescriptor&);
void setBlendStateAndFormat(const BlendDescriptor&, const RenderPassDescriptor&);
void getAttachmentFormat(const RenderPassDescriptor&, PixelFormat&, PixelFormat&, PixelFormat&);
void setBlendStateAndFormat(const BlendDescriptor&);
void getAttachmentFormat(const RenderTarget* renderTarget, const RenderPassParams& renderPassParams, PixelFormat colorAttachmentsFormat[MAX_COLOR_ATTCHMENT], PixelFormat&, PixelFormat&);
id<MTLRenderPipelineState> _mtlRenderPipelineState = nil;
id<MTLDevice> _mtlDevice = nil;
MTLRenderPipelineDescriptor* _mtlRenderPipelineDescriptor = nil;
PixelFormat _colorAttachmentsFormat[MAX_COLOR_ATTCHMENT] = { PixelFormat::DEFAULT };
PixelFormat _colorAttachmentsFormat[MAX_COLOR_ATTCHMENT] = { PixelFormat::NONE };
PixelFormat _depthAttachmentFormat = PixelFormat::NONE;
PixelFormat _stencilAttachmentFormat = PixelFormat::NONE;
NSMutableDictionary* _mtlRenderPipelineStateCache = nil;

View File

@ -24,6 +24,7 @@
#include "RenderPipelineMTL.h"
#include "DeviceMTL.h"
#include "RenderTargetMTL.h"
#include "ShaderModuleMTL.h"
#include "DepthStencilStateMTL.h"
#include "UtilsMTL.h"
@ -163,14 +164,15 @@ RenderPipelineMTL::RenderPipelineMTL(id<MTLDevice> mtlDevice)
}
void RenderPipelineMTL::update(const PipelineDescriptor & pipelineDescirptor,
const RenderPassDescriptor& renderPassDescriptor)
const RenderTarget* renderTarget,
const RenderPassParams& renderPassParams)
{
struct
{
size_t vertexShaderHash;
size_t fragmentShaderHash;
unsigned int vertexLayoutInfo[32];
backend::PixelFormat colorAttachment;
backend::PixelFormat colorAttachment[MAX_COLOR_ATTCHMENT];
backend::PixelFormat depthAttachment;
backend::PixelFormat stencilAttachment;
bool blendEnabled;
@ -185,11 +187,11 @@ void RenderPipelineMTL::update(const PipelineDescriptor & pipelineDescirptor,
memset(&hashMe, 0, sizeof(hashMe));
const auto& blendDescriptor = pipelineDescirptor.blendDescriptor;
getAttachmentFormat(renderPassDescriptor, _colorAttachmentsFormat[0], _depthAttachmentFormat, _stencilAttachmentFormat);
getAttachmentFormat(renderTarget, renderPassParams, _colorAttachmentsFormat, _depthAttachmentFormat, _stencilAttachmentFormat);
auto program = static_cast<ProgramMTL*>(pipelineDescirptor.programState->getProgram());
hashMe.vertexShaderHash = program->getVertexShader()->getHashValue();
hashMe.fragmentShaderHash = program->getFragmentShader()->getHashValue();
hashMe.colorAttachment = _colorAttachmentsFormat[0];
memcpy(&hashMe.colorAttachment, &_colorAttachmentsFormat, sizeof(_colorAttachmentsFormat));
hashMe.depthAttachment = _depthAttachmentFormat;
hashMe.stencilAttachment =_stencilAttachmentFormat;
hashMe.blendEnabled = blendDescriptor.blendEnabled;
@ -232,7 +234,7 @@ void RenderPipelineMTL::update(const PipelineDescriptor & pipelineDescirptor,
setShaderModules(pipelineDescirptor);
setVertexLayout(_mtlRenderPipelineDescriptor, pipelineDescirptor);
setBlendStateAndFormat(pipelineDescirptor.blendDescriptor, renderPassDescriptor);
setBlendStateAndFormat(pipelineDescirptor.blendDescriptor);
NSError *error = nil;
_mtlRenderPipelineState = [_mtlDevice newRenderPipelineStateWithDescriptor:_mtlRenderPipelineDescriptor error:&error];
@ -299,43 +301,29 @@ void RenderPipelineMTL::setShaderModules(const PipelineDescriptor& descriptor)
_mtlRenderPipelineDescriptor.fragmentFunction = fragShaderModule->getMTLFunction();
}
void RenderPipelineMTL::getAttachmentFormat(const RenderPassDescriptor& descriptor,
PixelFormat& colorFormat,
void RenderPipelineMTL::getAttachmentFormat(const RenderTarget* renderTarget,
const RenderPassParams& params,
PixelFormat colorAttachmentsFormat[MAX_COLOR_ATTCHMENT],
PixelFormat& depthFormat,
PixelFormat& stencilFormat)
{
if (descriptor.needColorAttachment)
{
// FIXME: now just handle color attachment 0.
if (descriptor.colorAttachmentsTexture[0])
colorFormat = descriptor.colorAttachmentsTexture[0]->getTextureFormat();
auto rtMTL = static_cast<const RenderTargetMTL*>(renderTarget);
auto rtflags = rtMTL->getTargetFlags();
for(auto i = 0; i < MAX_COLOR_ATTCHMENT; ++i) {
if (bitmask::any(rtflags, getMRTColorFlag(i)))
{
colorAttachmentsFormat[i] = rtMTL->getColorAttachmentPixelFormat(i);
}
else
colorFormat = PixelFormat::DEFAULT;
}
else
{
colorFormat = PixelFormat::DEFAULT;
{
colorAttachmentsFormat[i] = PixelFormat::NONE;
}
}
if (descriptor.needDepthStencilAttachment())
if (bitmask::any(rtflags, RenderTargetFlag::DEPTH_AND_STENCIL))
{
if(descriptor.depthAttachmentTexture)
{
depthFormat = descriptor.depthAttachmentTexture->getTextureFormat();
}
else
{
depthFormat = PixelFormat::D24S8;
}
if (descriptor.stencilAttachmentTexture)
{
stencilFormat = descriptor.stencilAttachmentTexture->getTextureFormat();
}
else
{
stencilFormat = PixelFormat::D24S8;
}
depthFormat = rtMTL->getDepthAttachmentPixelFormat();
stencilFormat =rtMTL->getStencilAttachmentPixelFormat();
}
else
{
@ -343,13 +331,14 @@ void RenderPipelineMTL::getAttachmentFormat(const RenderPassDescriptor& descript
}
}
void RenderPipelineMTL::setBlendStateAndFormat(const BlendDescriptor& blendDescriptor,
const RenderPassDescriptor& renderPassDescriptor)
void RenderPipelineMTL::setBlendStateAndFormat(const BlendDescriptor& blendDescriptor)
{
for (int i = 0; i < MAX_COLOR_ATTCHMENT; ++i)
{
if (PixelFormat::NONE == _colorAttachmentsFormat[i])
if (PixelFormat::NONE == _colorAttachmentsFormat[i]) {
_mtlRenderPipelineDescriptor.colorAttachments[i].pixelFormat = MTLPixelFormat::MTLPixelFormatInvalid;
continue;
}
_mtlRenderPipelineDescriptor.colorAttachments[i].pixelFormat = UtilsMTL::toMTLPixelFormat(_colorAttachmentsFormat[i]);
setBlendState(_mtlRenderPipelineDescriptor.colorAttachments[i], blendDescriptor);

View File

@ -0,0 +1,48 @@
#pragma once
#include "../RenderTarget.h"
#include "CommandBufferMTL.h"
CC_BACKEND_BEGIN
class RenderTargetMTL : public RenderTarget
{
public:
struct Attachment {
id<MTLTexture> texture = nil;
int level = 0;
explicit operator bool() const {
return texture != nullptr;
}
};
/*
* generateFBO, false, use for screen framebuffer
*/
RenderTargetMTL(bool defaultRenderTarget);
~RenderTargetMTL();
void bindFrameBuffer() const override;
void unbindFrameBuffer() const override;
void setColorAttachment(ColorAttachment attachment) override;
void setDepthAttachment(TextureBackend* attachment, int level = 0) override;
void setStencilAttachment(TextureBackend* attachment, int level = 0) override;
void applyRenderPassAttachments(const RenderPassParams& parmas, MTLRenderPassDescriptor* descriptor) const;
Attachment getColorAttachment(int index) const;
Attachment getDepthAttachment() const;
Attachment getStencilAttachment() const;
PixelFormat getColorAttachmentPixelFormat(int index) const;
PixelFormat getDepthAttachmentPixelFormat() const;
PixelFormat getStencilAttachmentPixelFormat() const;
public:
// "Sidecar" textures used to implement automatic MSAA resolve.
// id<MTLTexture> multisampledColor[MRT::TARGET_COUNT] = { 0 };
// id<MTLTexture> multisampledDepth = nil;
// MetalContext*, DeviceMTL*
};
CC_BACKEND_END

View File

@ -0,0 +1,184 @@
#include "RenderTargetMTL.h"
#include "UtilsMTL.h"
CC_BACKEND_BEGIN
static MTLLoadAction getLoadAction(const RenderPassParams& params,
TargetBufferFlags buffer) {
const auto clearFlags = (TargetBufferFlags) params.flags.clear;
const auto discardStartFlags = params.flags.discardStart;
if (bitmask::any(clearFlags, buffer)) {
return MTLLoadActionClear;
} else if (bitmask::any(discardStartFlags, buffer)) {
return MTLLoadActionDontCare;
}
return MTLLoadActionLoad;
}
static MTLStoreAction getStoreAction(const RenderPassParams& params,
TargetBufferFlags buffer) {
const auto discardEndFlags = params.flags.discardEnd;
if (bitmask::any(discardEndFlags, buffer)) {
return MTLStoreActionDontCare;
}
return MTLStoreActionStore;
}
RenderTargetMTL::RenderTargetMTL(bool defaultRenderTarget) : RenderTarget(defaultRenderTarget)
{
}
RenderTargetMTL::~RenderTargetMTL()
{
}
void RenderTargetMTL::bindFrameBuffer() const
{
}
void RenderTargetMTL::unbindFrameBuffer() const
{
}
void RenderTargetMTL::setColorAttachment(ColorAttachment attachment)
{
RenderTarget::setColorAttachment(attachment);
}
void RenderTargetMTL::setDepthAttachment(TextureBackend* attachment, int level)
{
RenderTarget::setDepthAttachment(attachment, level);
}
void RenderTargetMTL::setStencilAttachment(TextureBackend* attachment, int level)
{
RenderTarget::setStencilAttachment(attachment, level);
}
void RenderTargetMTL::applyRenderPassAttachments(const RenderPassParams& params, MTLRenderPassDescriptor* descriptor) const
{
const auto discardFlags = params.flags.discardEnd;
for (size_t i = 0; i < MAX_COLOR_ATTCHMENT; i++) {
auto attachment = getColorAttachment(i);
if (!attachment) {
continue;
}
descriptor.colorAttachments[i].texture = attachment.texture;
descriptor.colorAttachments[i].level = attachment.level;
// descriptor.colorAttachments[i].slice = attachment.layer;
descriptor.colorAttachments[i].loadAction = getLoadAction(params, getMRTColorFlag(i));
descriptor.colorAttachments[i].storeAction = getStoreAction(params, getMRTColorFlag(i));
descriptor.colorAttachments[i].clearColor = MTLClearColorMake(
params.clearColorValue[0], params.clearColorValue[1], params.clearColorValue[2], params.clearColorValue[3]);
#if 0
if (multisampledColor[i]) {
// We're rendering into our temporary MSAA texture and doing an automatic resolve.
// We should not be attempting to load anything into the MSAA texture.
assert(descriptor.colorAttachments[i].loadAction != MTLLoadActionLoad);
descriptor.colorAttachments[i].texture = multisampledColor[i];
descriptor.colorAttachments[i].level = 0;
descriptor.colorAttachments[i].slice = 0;
const bool discard = any(discardFlags & getMRTColorFlag(i));
if (!discard) {
descriptor.colorAttachments[i].resolveTexture = attachment.texture;
descriptor.colorAttachments[i].resolveLevel = attachment.level;
descriptor.colorAttachments[i].resolveSlice = attachment.layer;
descriptor.colorAttachments[i].storeAction = MTLStoreActionMultisampleResolve;
}
}
#endif
}
auto depthAttachment = getDepthAttachment();
if(depthAttachment){
descriptor.depthAttachment.texture = depthAttachment.texture;
descriptor.depthAttachment.level = depthAttachment.level;
// descriptor.depthAttachment.slice = depthAttachment.layer;
descriptor.depthAttachment.loadAction = getLoadAction(params, TargetBufferFlags::DEPTH);
descriptor.depthAttachment.storeAction = getStoreAction(params, TargetBufferFlags::DEPTH);
descriptor.depthAttachment.clearDepth = params.clearDepthValue;
}
auto stencilAttachment = getStencilAttachment();
if(stencilAttachment) {
descriptor.stencilAttachment.texture = stencilAttachment.texture;
descriptor.stencilAttachment.level = depthAttachment.level;
// descriptor.stencilAttachment.slice = depthAttachment.layer;
descriptor.stencilAttachment.loadAction = getLoadAction(params, TargetBufferFlags::STENCIL);
descriptor.stencilAttachment.storeAction = getStoreAction(params, TargetBufferFlags::STENCIL);
descriptor.stencilAttachment.clearStencil= params.clearStencilValue;
}
#if 0
if (multisampledDepth) {
// We're rendering into our temporary MSAA texture and doing an automatic resolve.
// We should not be attempting to load anything into the MSAA texture.
assert(descriptor.depthAttachment.loadAction != MTLLoadActionLoad);
descriptor.depthAttachment.texture = multisampledDepth;
descriptor.depthAttachment.level = 0;
descriptor.depthAttachment.slice = 0;
const bool discard = any(discardFlags & TargetBufferFlags::DEPTH);
if (!discard) {
descriptor.depthAttachment.resolveTexture = depthAttachment.texture;
descriptor.depthAttachment.resolveLevel = depthAttachment.level;
descriptor.depthAttachment.resolveSlice = depthAttachment.layer;
descriptor.depthAttachment.storeAction = MTLStoreActionMultisampleResolve;
}
}
#endif
}
RenderTargetMTL::Attachment RenderTargetMTL::getColorAttachment(int index) const
{
if(isDefaultRenderTarget() && index == 0)
return {DeviceMTL::getCurrentDrawable().texture, 0};
auto& rb = this->_color[index];
return RenderTargetMTL::Attachment{static_cast<bool>(rb) ? (id<MTLTexture>)(rb.texture->getHandler()) : nil, rb.level};
}
RenderTargetMTL::Attachment RenderTargetMTL::getDepthAttachment() const
{
if(isDefaultRenderTarget())
return {UtilsMTL::getDefaultDepthStencilTexture(), 0};
auto& rb = this->_depth;
return RenderTargetMTL::Attachment{!!rb ? (id<MTLTexture>)(rb.texture->getHandler()) : nil, rb.level};
}
RenderTargetMTL::Attachment RenderTargetMTL::getStencilAttachment() const
{
if(isDefaultRenderTarget())
return {UtilsMTL::getDefaultDepthStencilTexture(), 0};
auto& rb = this->_stencil;
return RenderTargetMTL::Attachment{!!rb ? (id<MTLTexture>)(rb.texture->getHandler()) : nil, rb.level};
}
PixelFormat RenderTargetMTL::getColorAttachmentPixelFormat(int index) const
{
if(isDefaultRenderTarget() && index == 0)
return PixelFormat::DEFAULT;
auto& rb = this->_color[index];
return rb ? rb.texture->getTextureFormat() : PixelFormat::NONE;
}
PixelFormat RenderTargetMTL::getDepthAttachmentPixelFormat() const
{ // FIXME: egnx only support D24S8
if(isDefaultRenderTarget() || !_depth)
return PixelFormat::D24S8;
return _depth.texture->getTextureFormat();
}
PixelFormat RenderTargetMTL::getStencilAttachmentPixelFormat() const
{ // FIXME: egnx only support D24S8
if(isDefaultRenderTarget() || !_stencil)
return PixelFormat::D24S8;
return _stencil.texture->getTextureFormat();
}
CC_BACKEND_END

View File

@ -147,10 +147,12 @@ public:
int getCount() const override { return _textureInfo._maxIdx + 1; }
/**
* Get MTLTexture object.
* Get MTLTexture object. reinterpret_cast<id<MTLTexture>>(handler);
* @return A MTLTexture object.
*/
inline id<MTLTexture> getMTLTexture(int index = 0) const { return _textureInfo._mtlTextures[index]; }
uintptr_t getHandler(int index = 0) const override {
return reinterpret_cast<uintptr_t>((void*)_textureInfo._mtlTextures[index]);
}
/**
* Get MTLSamplerState object
@ -201,13 +203,11 @@ public:
virtual void updateTextureDescriptor(const cocos2d::backend::TextureDescriptor &descriptor, int index = 0) override;
int getCount() const override { return _textureInfo._maxIdx + 1; }
/**
* Get MTLTexture object.
* @return A MTLTexture object.
*/
inline id<MTLTexture> getMTLTexture(int index = 0) const { return _textureInfo._mtlTextures[index]; }
uintptr_t getHandler(int index = 0) const override {
return reinterpret_cast<uintptr_t>((void*)_textureInfo._mtlTextures[index]);
}
/**
* Get MTLSamplerState object
* @return A MTLSamplerState object.

View File

@ -194,7 +194,8 @@ namespace
return bytesPerRow;
}
std::size_t getBytesPerRow(PixelFormat textureFormat, std::size_t width, std::size_t bitsPerElement)
// TODO: tidy APIs, compression pixelFormat and non-compression pixelFormat
std::size_t getBytesPerRowMTL(PixelFormat textureFormat, std::size_t width, std::size_t bitsPerElement)
{
MTLPixelFormat pixelFormat = UtilsMTL::toMTLPixelFormat(textureFormat);
std::size_t bytesPerRow = 0;
@ -361,7 +362,7 @@ void TextureMTL::updateSubData(std::size_t xoffset, std::size_t yoffset, std::si
width * height,
_textureFormat, &convertedData);
std::size_t bytesPerRow = getBytesPerRow(_textureFormat, width, _bitsPerElement);
std::size_t bytesPerRow = getBytesPerRowMTL(_textureFormat, width, _bitsPerElement);
[mtlTexture replaceRegion:region
mipmapLevel:level
@ -393,7 +394,7 @@ void TextureMTL::generateMipmaps()
if(!_hasMipmaps)
{
_hasMipmaps = true;
UtilsMTL::generateMipmaps(this->getMTLTexture());
UtilsMTL::generateMipmaps(reinterpret_cast<id<MTLTexture>>(this->getHandler()));
}
}
@ -454,7 +455,7 @@ void TextureCubeMTL::generateMipmaps()
if(!_hasMipmaps)
{
_hasMipmaps = true;
UtilsMTL::generateMipmaps(this->getMTLTexture());
UtilsMTL::generateMipmaps(reinterpret_cast<id<MTLTexture>>(this->getHandler()));
}
}

View File

@ -83,18 +83,7 @@ struct UtilsMTL
* @param texture Specifies a texture to generate mipmap.
*/
static void generateMipmaps(id<MTLTexture> texture);
/**
* Read a block of pixels from the given texture
* @param texture Specifies the texture to get the image.
* @param origX,origY Specify the window coordinates of the first pixel that is read from the given texture. This location is the lower left corner of a rectangular block of pixels.
* @param rectWidth,rectHeight Specify the dimensions of the pixel rectangle. rectWidth and rectHeight of one correspond to a single pixel.
* @param pbd, the output buffer for fill texels data
* @remark: !!!this function only can call after endFrame, then it's could be works well.
*/
static void readPixels(TextureBackend* texture, std::size_t origX, std::size_t origY, std::size_t rectWidth, std::size_t rectHeight, PixelBufferDescriptor& pbd);
static void readPixels(id<MTLTexture> texture, std::size_t origX, std::size_t origY, std::size_t rectWidth, std::size_t rectHeight, PixelBufferDescriptor& pbd);
/**
* Swizzle the iamge form the given format to MTLPixelFormatRGBA8Unorm.
* @param image Specifies the image to be swizzled.

View File

@ -36,39 +36,6 @@ id<MTLTexture> UtilsMTL::_defaultColorAttachmentTexture = nil;
id<MTLTexture> UtilsMTL::_defaultDepthStencilAttachmentTexture = nil;
namespace {
#define byte(n) ((n) * 8)
#define bit(n) (n)
uint8_t getBitsPerElement(MTLPixelFormat pixleFormat)
{
switch (pixleFormat)
{
case MTLPixelFormatDepth32Float_Stencil8:
return byte(8);
case MTLPixelFormatBGRA8Unorm:
case MTLPixelFormatRGBA8Unorm:
case MTLPixelFormatDepth32Float:
return byte(4);
#if (CC_TARGET_PLATFORM == CC_PLATFORM_MAC)
case MTLPixelFormatDepth24Unorm_Stencil8:
return byte(4);
#else
case MTLPixelFormatABGR4Unorm:
case MTLPixelFormatBGR5A1Unorm:
case MTLPixelFormatB5G6R5Unorm:
case MTLPixelFormatA1BGR5Unorm:
return byte(2);
#endif
case MTLPixelFormatA8Unorm:
case MTLPixelFormatR8Unorm:
return byte(1);
default:
assert(false);
break;
}
return 0;
}
MTLPixelFormat getSupportedDepthStencilFormat()
{
MTLPixelFormat pixelFormat = MTLPixelFormatDepth32Float_Stencil8;
@ -217,59 +184,4 @@ void UtilsMTL::swizzleImage(unsigned char *image, std::size_t width, std::size_t
}
}
void UtilsMTL::readPixels(TextureBackend* texture, std::size_t origX, std::size_t origY, std::size_t rectWidth, std::size_t rectHeight, PixelBufferDescriptor& pbd)
{
switch(texture->getTextureType()){
case TextureType::TEXTURE_2D:
UtilsMTL::readPixels(static_cast<TextureMTL*>(texture)->getMTLTexture(), origX, origY, rectWidth, rectHeight, pbd);
break;
case TextureType::TEXTURE_CUBE:
UtilsMTL::readPixels(static_cast<TextureCubeMTL*>(texture)->getMTLTexture(), origX, origY, rectWidth, rectHeight, pbd);
break;
}
}
void UtilsMTL::readPixels(id<MTLTexture> texture, std::size_t origX, std::size_t origY, std::size_t rectWidth, std::size_t rectHeight, PixelBufferDescriptor& pbd)
{
NSUInteger texWidth = texture.width;
NSUInteger texHeight = texture.height;
MTLRegion region = MTLRegionMake2D(0, 0, texWidth, texHeight);
MTLRegion imageRegion = MTLRegionMake2D(origX, origY, rectWidth, rectHeight);
MTLTextureDescriptor* textureDescriptor =
[MTLTextureDescriptor texture2DDescriptorWithPixelFormat:[texture pixelFormat]
width:texWidth
height:texHeight
mipmapped:NO];
id<MTLDevice> device = static_cast<DeviceMTL*>(DeviceMTL::getInstance())->getMTLDevice();
id<MTLTexture> readPixelsTexture = [device newTextureWithDescriptor:textureDescriptor];
id<MTLCommandQueue> commandQueue = static_cast<DeviceMTL*>(DeviceMTL::getInstance())->getMTLCommandQueue();
auto commandBuffer = [commandQueue commandBuffer];
// [commandBuffer enqueue];
id<MTLBlitCommandEncoder> blitCommandEncoder = [commandBuffer blitCommandEncoder];
[blitCommandEncoder copyFromTexture:texture sourceSlice:0 sourceLevel:0 sourceOrigin:region.origin sourceSize:region.size toTexture:readPixelsTexture destinationSlice:0 destinationLevel:0 destinationOrigin:region.origin];
#if (CC_TARGET_PLATFORM == CC_PLATFORM_MAC)
[blitCommandEncoder synchronizeResource:readPixelsTexture];
#endif
[blitCommandEncoder endEncoding];
[commandBuffer addCompletedHandler:^(id<MTLCommandBuffer> commandBufferMTL) {
auto bytePerRow = rectWidth * getBitsPerElement(texture.pixelFormat) / 8;
auto texelData = pbd._data.resize(bytePerRow * rectHeight);
if(texelData != nullptr)
{
[readPixelsTexture getBytes:texelData bytesPerRow:bytePerRow fromRegion:imageRegion mipmapLevel:0];
swizzleImage(texelData, rectWidth, rectHeight, readPixelsTexture.pixelFormat);
pbd._width = rectWidth;
pbd._height = rectHeight;
}
[readPixelsTexture release];
}];
[commandBuffer commit];
[commandBuffer waitUntilCompleted];
}
CC_BACKEND_END

View File

@ -33,27 +33,13 @@
#include "base/CCEventType.h"
#include "base/CCDirector.h"
#include "renderer/backend/opengl/UtilsGL.h"
#include "RenderTargetGL.h"
#include <algorithm>
CC_BACKEND_BEGIN
namespace
{
GLuint getHandler(TextureBackend *texture)
{
switch (texture->getTextureType())
{
case TextureType::TEXTURE_2D:
return static_cast<Texture2DGL*>(texture)->getHandler();
case TextureType::TEXTURE_CUBE:
return static_cast<TextureCubeGL*>(texture)->getHandler();
default:
assert(false);
return 0;
}
}
void applyTexture(TextureBackend* texture, int slot, int index)
{
switch (texture->getTextureType())
@ -101,199 +87,66 @@ void CommandBufferGL::beginFrame()
{
}
void CommandBufferGL::beginRenderPass(const RenderPassDescriptor& descirptor)
void CommandBufferGL::beginRenderPass(const RenderTarget* rt, const RenderPassParams& descirptor)
{
applyRenderPassDescriptor(descirptor);
}
void CommandBufferGL::applyRenderPassDescriptor(const RenderPassDescriptor& descirptor)
{
bool useColorAttachmentExternal = descirptor.needColorAttachment && descirptor.colorAttachmentsTexture[0];
bool useDepthAttachmentExternal = descirptor.depthTestEnabled && descirptor.depthAttachmentTexture;
bool useStencilAttachmentExternal = descirptor.stencilTestEnabled && descirptor.stencilAttachmentTexture;
bool useGeneratedFBO = false;
if (useColorAttachmentExternal || useDepthAttachmentExternal || useStencilAttachmentExternal)
{
if(_generatedFBO == 0)
{
glGenFramebuffers(1, &_generatedFBO);
}
_currentFBO = _generatedFBO;
useGeneratedFBO = true;
}
else
{
_currentFBO = _defaultFBO;
}
glBindFramebuffer(GL_FRAMEBUFFER, _currentFBO);
auto rtGL = static_cast<const RenderTargetGL*>(rt);
if (useDepthAttachmentExternal)
{
glFramebufferTexture2D(GL_FRAMEBUFFER,
GL_DEPTH_ATTACHMENT,
GL_TEXTURE_2D,
getHandler(descirptor.depthAttachmentTexture),
0);
CHECK_GL_ERROR_DEBUG();
rtGL->bindFrameBuffer();
auto clearFlags = descirptor.flags.clear;
_generatedFBOBindDepth = true;
}
else
{
if (_generatedFBOBindDepth && useGeneratedFBO)
{
glFramebufferTexture2D(GL_FRAMEBUFFER,
GL_DEPTH_ATTACHMENT,
GL_TEXTURE_2D,
0,
0);
CHECK_GL_ERROR_DEBUG();
_generatedFBOBindDepth = false;
}
}
if (useStencilAttachmentExternal)
{
glFramebufferTexture2D(GL_FRAMEBUFFER,
GL_STENCIL_ATTACHMENT,
GL_TEXTURE_2D,
getHandler(descirptor.stencilAttachmentTexture),
0);
CHECK_GL_ERROR_DEBUG();
_generatedFBOBindStencil = true;
}
else
{
if (_generatedFBOBindStencil && useGeneratedFBO)
{
glFramebufferTexture2D(GL_FRAMEBUFFER,
GL_STENCIL_ATTACHMENT,
GL_TEXTURE_2D,
0,
0);
CHECK_GL_ERROR_DEBUG();
_generatedFBOBindStencil = false;
}
}
if (descirptor.needColorAttachment)
{
int i = 0;
for (const auto& texture : descirptor.colorAttachmentsTexture)
{
if (texture)
{
// TODO: support texture cube
glFramebufferTexture2D(GL_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0 + i,
GL_TEXTURE_2D,
getHandler(texture),
0);
}
CHECK_GL_ERROR_DEBUG();
++i;
}
if (useGeneratedFBO)
_generatedFBOBindColor = true;
#if CC_TARGET_PLATFORM == CC_PLATFORM_WIN32 || CC_TARGET_PLATFORM == CC_PLATFORM_LINUX
if (_framebufferReadWriteDisabled)
{
if (useGeneratedFBO) //user-defined framebuffer
{
glDrawBuffer(GL_COLOR_ATTACHMENT0);
glReadBuffer(GL_COLOR_ATTACHMENT0);
}
else //default framebuffer
{
glDrawBuffer(GL_BACK);
glReadBuffer(GL_BACK);
}
_framebufferReadWriteDisabled = false;
}
#endif
}
else
{
if (_generatedFBOBindColor && useGeneratedFBO)
{
// FIXME: Now only support attaching to attachment 0.
glFramebufferTexture2D(GL_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D,
0,
0);
_generatedFBOBindColor = false;
}
// If not draw buffer is needed, should invoke this line explicitly, or it will cause
// GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER and GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER error.
// https://stackoverflow.com/questions/28313782/porting-opengl-es-framebuffer-to-opengl
#if CC_TARGET_PLATFORM == CC_PLATFORM_WIN32 || CC_TARGET_PLATFORM == CC_PLATFORM_LINUX
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
_framebufferReadWriteDisabled = true;
#endif
}
CHECK_GL_ERROR_DEBUG();
// set clear color, depth and stencil
GLbitfield mask = 0;
if (descirptor.needClearColor)
if (bitmask::any(clearFlags, TargetBufferFlags::COLOR))
{
mask |= GL_COLOR_BUFFER_BIT;
const auto& clearColor = descirptor.clearColorValue;
glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
}
CHECK_GL_ERROR_DEBUG();
GLboolean oldDepthWrite = GL_FALSE;
GLboolean oldDepthTest = GL_FALSE;
GLfloat oldDepthClearValue = 0.f;
GLint oldDepthFunc = GL_LESS;
if (descirptor.needClearDepth)
if (bitmask::any(clearFlags, TargetBufferFlags::DEPTH))
{
glGetBooleanv(GL_DEPTH_WRITEMASK, &oldDepthWrite);
glGetBooleanv(GL_DEPTH_TEST, &oldDepthTest);
glGetFloatv(GL_DEPTH_CLEAR_VALUE, &oldDepthClearValue);
glGetIntegerv(GL_DEPTH_FUNC, &oldDepthFunc);
mask |= GL_DEPTH_BUFFER_BIT;
glClearDepth(descirptor.clearDepthValue);
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
glDepthFunc(GL_ALWAYS);
}
CHECK_GL_ERROR_DEBUG();
if (descirptor.needClearStencil)
if (bitmask::any(clearFlags, TargetBufferFlags::STENCIL))
{
mask |= GL_STENCIL_BUFFER_BIT;
glClearStencil(descirptor.clearStencilValue);
}
if(mask) glClear(mask);
if (mask) glClear(mask);
CHECK_GL_ERROR_DEBUG();
// restore depth test
if (descirptor.needClearDepth)
if (bitmask::any(clearFlags, TargetBufferFlags::DEPTH))
{
if (!oldDepthTest)
glDisable(GL_DEPTH_TEST);
glDepthMask(oldDepthWrite);
glDepthFunc(oldDepthFunc);
glClearDepth(oldDepthClearValue);
}
CHECK_GL_ERROR_DEBUG();
}
@ -379,7 +232,6 @@ void CommandBufferGL::endRenderPass()
void CommandBufferGL::endFrame()
{
// executeGpuCommandsCompleteOps();
}
void CommandBufferGL::setDepthStencilState(DepthStencilState* depthStencilState)
@ -630,14 +482,64 @@ void CommandBufferGL::setScissorRect(bool isEnabled, float x, float y, float wid
}
}
void CommandBufferGL::capture(TextureBackend* texture, std::function<void(const PixelBufferDescriptor&)> callback)
void CommandBufferGL::readPixels(RenderTarget* rt, std::function<void(const PixelBufferDescriptor&)> callback)
{
PixelBufferDescriptor pbd;
if (!texture)
UtilsGL::readPixels(nullptr, _viewPort.x, _viewPort.y, _viewPort.w, _viewPort.h, pbd);
else
UtilsGL::readPixels(texture, 0, 0, texture->getWidth(), texture->getHeight(), pbd);
if(rt->isDefaultRenderTarget())
{ // read pixels from screen
readPixels(rt, _viewPort.x, _viewPort.y, _viewPort.w, _viewPort.h, _viewPort.w * 4, pbd);
}
else {
// we only readPixels from the COLOR0 attachment.
auto colorAttachment = rt->_color[0].texture;
if(colorAttachment) {
readPixels(rt, 0, 0, colorAttachment->getWidth(),colorAttachment->getHeight(), colorAttachment->getBytesPerRow(), pbd);
}
}
callback(pbd);
}
void CommandBufferGL::readPixels(RenderTarget* rt, int x, int y, uint32_t width, uint32_t height, uint32_t bytesPerRow, PixelBufferDescriptor& pbd)
{
rt->bindFrameBuffer();
glPixelStorei(GL_PACK_ALIGNMENT, 1);
auto bufferSize = bytesPerRow * height;
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32 && defined(GL_ES_VERSION_3_0)) || \
(CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID && defined(GL_PIXEL_PACK_BUFFER))
GLuint pbo;
glGenBuffers(1, &pbo);
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
glBufferData(GL_PIXEL_PACK_BUFFER, bufferSize, nullptr, GL_STATIC_DRAW);
glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
auto buffer = (uint8_t*)glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, bufferSize, GL_MAP_READ_BIT);
#else
std::unique_ptr<uint8_t[]> bufferStorage(new uint8_t[bufferSize]);
auto buffer = bufferStorage.get();
memset(buffer, 0, bufferSize);
glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
#endif
uint8_t* wptr = nullptr;
if (buffer && (wptr = pbd._data.resize(bufferSize))) {
auto rptr = buffer + (height - 1) * bytesPerRow;
for (int row = 0; row < height; ++row) {
memcpy(wptr, rptr, bytesPerRow);
wptr += bytesPerRow;
rptr -= bytesPerRow;
}
pbd._width = width;
pbd._height = height;
}
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32 && defined(GL_ES_VERSION_3_0)) || \
(CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID && defined(GL_PIXEL_PACK_BUFFER))
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
glDeleteBuffers(1, &pbo);
#endif
if (!rt->isDefaultRenderTarget())
rt->unbindFrameBuffer();
}
CC_BACKEND_END

View File

@ -65,7 +65,7 @@ public:
* Begin a render pass, initial color, depth and stencil attachment.
* @param descriptor Specifies a group of render targets that hold the results of a render pass.
*/
virtual void beginRenderPass(const RenderPassDescriptor& descriptor) override;
virtual void beginRenderPass(const RenderTarget* rt, const RenderPassParams& descriptor) override;
/**
* Sets the current render pipeline state object.
@ -167,7 +167,10 @@ public:
* Get a screen snapshot
* @param callback A callback to deal with screen snapshot image.
*/
virtual void capture(TextureBackend* texture, std::function<void(const PixelBufferDescriptor&)> callback) override;
virtual void readPixels(RenderTarget* rt, std::function<void(const PixelBufferDescriptor&)> callback) override;
protected:
void readPixels(RenderTarget* rt, int x, int y, uint32_t width, uint32_t height, uint32_t bytesPerRow, PixelBufferDescriptor& pbd);
private:
struct Viewport
@ -183,7 +186,6 @@ private:
void setUniforms(ProgramGL* program) const;
void setUniform(bool isArray, GLuint location, unsigned int size, GLenum uniformType, void* data) const;
void cleanResources();
void applyRenderPassDescriptor(const RenderPassDescriptor& descirptor);
// The frame buffer generated by engine. All frame buffer other than default frame buffer share it.
GLuint _generatedFBO = 0;

View File

@ -31,6 +31,7 @@
#include "DepthStencilStateGL.h"
#include "ProgramGL.h"
#include "DeviceInfoGL.h"
#include "RenderTargetGL.h"
CC_BACKEND_BEGIN
@ -82,6 +83,27 @@ TextureBackend* DeviceGL::newTexture(const TextureDescriptor& descriptor)
}
}
RenderTarget* DeviceGL::newDefaultRenderTarget(TargetBufferFlags rtf)
{
auto rtGL = new RenderTargetGL(true);
rtGL->setTargetFlags(rtf);
return rtGL;
}
RenderTarget* DeviceGL::newRenderTarget(TargetBufferFlags rtf,
TextureBackend* colorAttachment,
TextureBackend* depthAttachment,
TextureBackend* stencilAttachhment)
{
auto rtGL = new RenderTargetGL(false);
rtGL->setTargetFlags(rtf);
rtGL->bindFrameBuffer();
rtGL->setColorAttachment({ RenderTarget::ColorAttachment{ {colorAttachment, 0} } });
rtGL->setDepthAttachment(depthAttachment);
rtGL->setStencilAttachment(stencilAttachhment);
return rtGL;
}
ShaderModule* DeviceGL::newShaderModule(ShaderStage stage, const std::string& source)
{
return new (std::nothrow) ShaderModuleGL(stage, source);

View File

@ -61,6 +61,12 @@ public:
*/
virtual TextureBackend* newTexture(const TextureDescriptor& descriptor) override;
RenderTarget* newDefaultRenderTarget(TargetBufferFlags rtf) override;
RenderTarget* newRenderTarget(TargetBufferFlags rtf,
TextureBackend* colorAttachment,
TextureBackend* depthAttachment,
TextureBackend* stencilAttachhment) override;
/**
* Create an auto released DepthStencilState object.
* @param descriptor Specifies depth and stencil description.

View File

@ -33,7 +33,7 @@ Copyright (c) 2020 c4games.com.
CC_BACKEND_BEGIN
void RenderPipelineGL::update(const PipelineDescriptor& pipelineDescirptor, const RenderPassDescriptor& renderpassDescriptor)
void RenderPipelineGL::update(const PipelineDescriptor& pipelineDescirptor, const RenderTarget*, const RenderPassParams&)
{
if(_programGL != pipelineDescirptor.programState->getProgram())
{
@ -54,10 +54,10 @@ void RenderPipelineGL::updateBlendState(const BlendDescriptor& descriptor)
auto destinationRGBBlendFactor = UtilsGL::toGLBlendFactor(descriptor.destinationRGBBlendFactor);
auto sourceAlphaBlendFactor = UtilsGL::toGLBlendFactor(descriptor.sourceAlphaBlendFactor);
auto destinationAlphaBlendFactor = UtilsGL::toGLBlendFactor(descriptor.destinationAlphaBlendFactor);
GLboolean writeMaskRed = _Bitmask_includes(descriptor.writeMask, ColorWriteMask::RED);
GLboolean writeMaskGreen = _Bitmask_includes(descriptor.writeMask, ColorWriteMask::GREEN);
GLboolean writeMaskBlue = _Bitmask_includes(descriptor.writeMask, ColorWriteMask::BLUE);
GLboolean writeMaskAlpha = _Bitmask_includes(descriptor.writeMask, ColorWriteMask::ALPHA);
GLboolean writeMaskRed = bitmask::any(descriptor.writeMask, ColorWriteMask::RED);
GLboolean writeMaskGreen = bitmask::any(descriptor.writeMask, ColorWriteMask::GREEN);
GLboolean writeMaskBlue = bitmask::any(descriptor.writeMask, ColorWriteMask::BLUE);
GLboolean writeMaskAlpha = bitmask::any(descriptor.writeMask, ColorWriteMask::ALPHA);
if (blendEnabled)
{

View File

@ -51,7 +51,7 @@ public:
RenderPipelineGL() = default;
~RenderPipelineGL();
virtual void update(const PipelineDescriptor & pipelineDescirptor, const RenderPassDescriptor& renderpassDescriptor) override;
virtual void update(const PipelineDescriptor & pipelineDescirptor, const RenderTarget* renderTarget, const RenderPassParams& renderParams) override;
/**
* Get program instance.
* @return Program instance.

View File

@ -0,0 +1,109 @@
#include "RenderTargetGL.h"
#include "base/ccMacros.h"
CC_BACKEND_BEGIN
RenderTargetGL::RenderTargetGL(bool defaultRenderTarget) : RenderTarget(defaultRenderTarget)
{
if (!defaultRenderTarget) {
glGenFramebuffers(1, &_FBO);
}
else {
_FBO = 0;
}
}
RenderTargetGL::~RenderTargetGL()
{
if (!_defaultRenderTarget) {
bindFrameBuffer();
for (auto slot = 0; slot < MAX_COLOR_ATTCHMENT; ++slot)
glFramebufferTexture2D(GL_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0 + slot,
GL_TEXTURE_2D,
0,
0);
glFramebufferTexture2D(GL_FRAMEBUFFER,
GL_DEPTH_ATTACHMENT,
GL_TEXTURE_2D,
0,
0);
glFramebufferTexture2D(GL_FRAMEBUFFER,
GL_STENCIL_ATTACHMENT,
GL_TEXTURE_2D,
0,
0);
unbindFrameBuffer();
glDeleteFramebuffers(1, &_FBO);
CHECK_GL_ERROR_DEBUG();
}
}
void RenderTargetGL::bindFrameBuffer() const
{
glBindFramebuffer(GL_FRAMEBUFFER, _FBO);
}
void RenderTargetGL::unbindFrameBuffer() const
{
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
void RenderTargetGL::setColorAttachment(ColorAttachment attachment)
{
RenderTarget::setColorAttachment(attachment);
if (!_defaultRenderTarget && bitmask::any(_flags, TargetBufferFlags::COLOR_ALL)) {
GLenum bufs[MAX_COLOR_ATTCHMENT] = { GL_NONE };
for (size_t i = 0; i < MAX_COLOR_ATTCHMENT; ++i) {
if (bitmask::any(_flags, getMRTColorFlag(i))) {
auto textureInfo = attachment[i];
auto textureHandler = textureInfo.texture != nullptr ? textureInfo.texture->getHandler() : 0;
glFramebufferTexture2D(GL_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0 + i,
GL_TEXTURE_2D,
textureHandler,
textureInfo.level);
bufs[i] = GL_COLOR_ATTACHMENT0 + i;
}
}
#if CC_TARGET_PLATFORM == CC_PLATFORM_WIN32 || CC_TARGET_PLATFORM == CC_PLATFORM_LINUX
glDrawBuffers(MAX_COLOR_ATTCHMENT, bufs);
#endif
CHECK_GL_ERROR_DEBUG();
}
}
void RenderTargetGL::setDepthAttachment(TextureBackend* attachment, int level)
{
RenderTarget::setDepthAttachment(attachment, level);
if (!_defaultRenderTarget) {
glFramebufferTexture2D(GL_FRAMEBUFFER,
GL_DEPTH_ATTACHMENT,
GL_TEXTURE_2D,
attachment != nullptr ? attachment->getHandler() : 0,
level);
CHECK_GL_ERROR_DEBUG();
}
}
void RenderTargetGL::setStencilAttachment(TextureBackend* attachment, int level)
{
RenderTarget::setStencilAttachment(attachment, level);
if (!_defaultRenderTarget) {
glFramebufferTexture2D(GL_FRAMEBUFFER,
GL_STENCIL_ATTACHMENT,
GL_TEXTURE_2D,
attachment != nullptr ? attachment->getHandler() : 0,
level);
CHECK_GL_ERROR_DEBUG();
}
}
CC_BACKEND_END

View File

@ -0,0 +1,26 @@
#pragma once
#include "../RenderTarget.h"
#include "platform/CCGL.h"
CC_BACKEND_BEGIN
class RenderTargetGL : public RenderTarget
{
public:
/*
* generateFBO, false, use for screen framebuffer
*/
RenderTargetGL(bool defaultRenderTarget);
~RenderTargetGL();
void bindFrameBuffer() const override;
void unbindFrameBuffer() const override;
void setColorAttachment(ColorAttachment attachment) override;
void setDepthAttachment(TextureBackend* attachment, int level = 0) override;
void setStencilAttachment(TextureBackend* attachment, int level = 0) override;
public:
GLuint _FBO = 0;
};
CC_BACKEND_END

View File

@ -151,10 +151,10 @@ Texture2DGL::Texture2DGL(const TextureDescriptor& descriptor)
void Texture2DGL::initWithZeros()
{
// Ensure the final data size at least 1 byte
// Ensure the final data size at least 4 byte
_width = (std::max)(_width, (uint32_t)1);
_height = (std::max)(_height, (uint32_t)1);
_bitsPerElement = (std::max)(_bitsPerElement, (uint8_t)8);
_bitsPerElement = (std::max)(_bitsPerElement, (uint8_t)(8 * 4));
auto size = _width * _height * _bitsPerElement / 8;
uint8_t* data = (uint8_t*)malloc(size);

View File

@ -385,15 +385,9 @@ void UtilsGL::toGLTypes(PixelFormat textureFormat, GLint &internalFormat, GLuint
// internalFormat = GL_DEPTH_COMPONENT;
// type = GL_UNSIGNED_INT;
case PixelFormat::D24S8:
#ifdef CC_USE_GLES
format = GL_DEPTH_STENCIL_OES;
internalFormat = GL_DEPTH_STENCIL_OES;
type = GL_UNSIGNED_INT_24_8_OES;
#else
format = GL_DEPTH_STENCIL;
internalFormat = GL_DEPTH24_STENCIL8;
type = GL_UNSIGNED_INT_24_8;
#endif
break;
default:
break;
@ -592,79 +586,4 @@ GLenum UtilsGL::toGLCullMode(CullMode mode)
return GL_FRONT;
}
void UtilsGL::readPixels(TextureBackend* texture, GLint x, GLint y, std::size_t width, std::size_t height, PixelBufferDescriptor& pbd)
{
GLint defaultFBO = 0;
GLuint frameBuffer = 0;
std::size_t bytesPerRow = 0;
if (UTILS_LIKELY(!texture)) // read pixels from screen
bytesPerRow = width * 4;
else { // read pixels from GPU texture
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFBO);
glGenFramebuffers(1, &frameBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
/** Notes from cocos2d-x v3
// TODO: move this to configuration, so we don't check it every time
// Certain Qualcomm Adreno GPU's will retain data in memory after a frame buffer switch which corrupts the render to the texture. The solution is to clear the frame buffer before rendering to the texture. However, calling glClear has the unintended result of clearing the current texture. Create a temporary texture to overcome this. At the end of RenderTexture::begin(), switch the attached texture to the second one, call glClear, and then switch back to the original texture. This solution is unnecessary for other devices as they don't have the same issue with switching frame buffers.
if (Configuration::getInstance()->checkForGLExtension("GL_QCOM"))
{
// -- bind a temporary texture so we can clear the render buffer without losing our texture
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _textureCopy->getName(), 0);
CHECK_GL_ERROR_DEBUG();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _texture->getName(), 0);
}
*/
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
texture->getTextureType() == TextureType::TEXTURE_2D ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP,
static_cast<GLuint>(texture->getHandler()),
0);
bytesPerRow = width * texture->_bitsPerElement / 8;
}
glPixelStorei(GL_PACK_ALIGNMENT, 1);
auto bufferSize = bytesPerRow * height;
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32 && defined(GL_ES_VERSION_3_0)) || \
(CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID && defined(GL_PIXEL_PACK_BUFFER))
GLuint pbo;
glGenBuffers(1, &pbo);
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
glBufferData(GL_PIXEL_PACK_BUFFER, bufferSize, nullptr, GL_STATIC_DRAW);
glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
auto buffer = (uint8_t*)glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, bufferSize, GL_MAP_READ_BIT);
#else
std::unique_ptr<uint8_t[]> bufferStorage(new uint8_t[bufferSize]);
auto buffer = bufferStorage.get();
glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
#endif
uint8_t* wptr = pbd._data.resize(bufferSize);
if (buffer && wptr) {
auto rptr = buffer + (height - 1) * bytesPerRow;
for (int row = 0; row < height; ++row) {
memcpy(wptr, rptr, bytesPerRow);
wptr += bytesPerRow;
rptr -= bytesPerRow;
}
pbd._width = width;
pbd._height = height;
}
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32 && defined(GL_ES_VERSION_3_0)) || \
(CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID && defined(GL_PIXEL_PACK_BUFFER))
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
glDeleteBuffers(1, &pbo);
#endif
if (UTILS_UNLIKELY(frameBuffer)) {
glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO);
glDeleteFramebuffers(1, &frameBuffer);
}
}
CC_BACKEND_END

View File

@ -34,9 +34,6 @@ CC_BACKEND_BEGIN
* @addtogroup _opengl
* @{
*/
class TextureBackend;
/**
* Convert backend enum class to corresponding opengl defined value.
*/
@ -154,16 +151,6 @@ struct UtilsGL
* @return Cull mode.
*/
static GLenum toGLCullMode(CullMode mode);
/**
* Read a block of pixels from the given texture
* @param texture Specifies the texture to get the image, nullptr: read pixels from screen framebuffer
* @param origX,origY Specify the window coordinates of the first pixel that is read from the given texture. This location is the lower left corner of a rectangular block of pixels.
* @param rectWidth,rectHeight Specify the dimensions of the pixel rectangle. rectWidth and rectHeight of one correspond to a single pixel.
* @param pbd, the output pixel buffer for fill texels data
* @remark: !!!this function only can call after endFrame, then it's could be works well.
*/
static void readPixels(TextureBackend* texture, GLint x, GLint y, std::size_t width, std::size_t height, PixelBufferDescriptor& pbd);
};
//end of _opengl group
/// @}

View File

@ -91251,9 +91251,9 @@ int lua_cocos2dx_Renderer_getStencilAttachment(lua_State* tolua_S)
tolua_error(tolua_S,"invalid arguments in function 'lua_cocos2dx_Renderer_getStencilAttachment'", nullptr);
return 0;
}
cocos2d::Texture2D* ret = cobj->getStencilAttachment();
object_to_luaval<cocos2d::Texture2D>(tolua_S, "cc.Texture2D",(cocos2d::Texture2D*)ret);
return 1;
// cocos2d::Texture2D* ret = cobj->getStencilAttachment();
// object_to_luaval<cocos2d::Texture2D>(tolua_S, "cc.Texture2D",(cocos2d::Texture2D*)ret);
return 0;
}
luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "cc.Renderer:getStencilAttachment",argc, 0);
return 0;
@ -91698,9 +91698,9 @@ int lua_cocos2dx_Renderer_getColorAttachment(lua_State* tolua_S)
tolua_error(tolua_S,"invalid arguments in function 'lua_cocos2dx_Renderer_getColorAttachment'", nullptr);
return 0;
}
cocos2d::Texture2D* ret = cobj->getColorAttachment();
object_to_luaval<cocos2d::Texture2D>(tolua_S, "cc.Texture2D",(cocos2d::Texture2D*)ret);
return 1;
// cocos2d::Texture2D* ret = cobj->getColorAttachment();
// object_to_luaval<cocos2d::Texture2D>(tolua_S, "cc.Texture2D",(cocos2d::Texture2D*)ret);
return 0;
}
luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "cc.Renderer:getColorAttachment",argc, 0);
return 0;
@ -93060,7 +93060,8 @@ int lua_cocos2dx_Renderer_setRenderTarget(lua_State* tolua_S)
tolua_error(tolua_S,"invalid arguments in function 'lua_cocos2dx_Renderer_setRenderTarget'", nullptr);
return 0;
}
cobj->setRenderTarget(arg0, arg1, arg2, arg3);
// TODO:
// cobj->setRenderTarget(arg0, arg1, arg2, arg3);
lua_settop(tolua_S, 1);
return 1;
}
@ -93107,9 +93108,9 @@ int lua_cocos2dx_Renderer_getDepthAttachment(lua_State* tolua_S)
tolua_error(tolua_S,"invalid arguments in function 'lua_cocos2dx_Renderer_getDepthAttachment'", nullptr);
return 0;
}
cocos2d::Texture2D* ret = cobj->getDepthAttachment();
object_to_luaval<cocos2d::Texture2D>(tolua_S, "cc.Texture2D",(cocos2d::Texture2D*)ret);
return 1;
// cocos2d::Texture2D* ret = cobj->getDepthAttachment();
// object_to_luaval<cocos2d::Texture2D>(tolua_S, "cc.Texture2D",(cocos2d::Texture2D*)ret);
return 0;
}
luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "cc.Renderer:getDepthAttachment",argc, 0);
return 0;

View File

@ -116,12 +116,12 @@ namespace ui {
/**
@brief Open keyboard and receive input text.
*/
virtual bool attachWithIME();
virtual bool attachWithIME() override;
/**
@brief End text input and close keyboard.
*/
virtual bool detachWithIME();
virtual bool detachWithIME() override;
void keyboardDidShow(IMEKeyboardNotificationInfo& /*info*/) override;
void keyboardDidHide(IMEKeyboardNotificationInfo& /*info*/) override;

View File

@ -195,6 +195,7 @@ void ImGuiEXT::loadCustomFonts(void* ud)
case CHS_GLYPH_RANGE::FULL:
imChars = imFonts->GetGlyphRangesChineseFull();
break;
default:;
}
imFonts->AddFontFromFileTTF(fontInfo.first.c_str(), fontInfo.second.fontSize * contentZoomFactor, nullptr, imChars);

View File

@ -366,10 +366,6 @@ void DataReaderHelper::addDataFromFileAsync(const std::string& imagePath, const
{
basefilePath = basefilePath.substr(0, pos + 1);
}
else
{
basefilePath;
}
// lazy init

View File

@ -1037,8 +1037,8 @@
"cocos/renderer/backend/ProgramCache.h",
"cocos/renderer/backend/ProgramState.cpp",
"cocos/renderer/backend/ProgramState.h",
"cocos/renderer/backend/RenderPassDescriptor.cpp",
"cocos/renderer/backend/RenderPassDescriptor.h",
"cocos/renderer/backend/RenderPassParams.cpp",
"cocos/renderer/backend/RenderPassParams.h",
"cocos/renderer/backend/RenderPipeline.h",
"cocos/renderer/backend/RenderPipelineDescriptor.h",
"cocos/renderer/backend/ShaderCache.cpp",

View File

@ -50,7 +50,7 @@ function build_mac_cmake()
cd $COCOS2DX_ROOT
mkdir -p build
cmake -S . -B build -GXcode -DBUILD_EXTENSION_IMGUI=ON
cmake --build build --config Release -- -quiet
cmake --build build --config Release --target cpp-tests -- -quiet
#xcodebuild -project Cocos2d-x.xcodeproj -alltargets -jobs $NUM_OF_CORES build | xcpretty
##the following commands must not be removed
#xcodebuild -project Cocos2d-x.xcodeproj -alltargets -jobs $NUM_OF_CORES build