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

View File

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

View File

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

View File

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

View File

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

View File

@ -66,16 +66,11 @@ Copyright (c) 2020 c4games.com.
return static_cast<_BITMASK>(~static_cast<_IntTy>(_Left)); \ return static_cast<_BITMASK>(~static_cast<_IntTy>(_Left)); \
} \ } \
\ \
constexpr bool _Bitmask_includes( \ constexpr bool operator!(_BITMASK _Left) noexcept { /* return ~_Left */ \
_BITMASK _Left, _BITMASK _Elements) noexcept { /* return (_Left & _Elements) != _BITMASK{} */ \ using _IntTy = _STD underlying_type<_BITMASK>::type; \
return (_Left & _Elements) != _BITMASK{}; \ return !static_cast<_IntTy>(_Left); \
} \
\
constexpr bool _Bitmask_includes_all( \
_BITMASK _Left, _BITMASK _Elements) noexcept { /* return (_Left & _Elements) == _Elements */ \
return (_Left & _Elements) == _Elements; \
} }
// BITSHIFT OPERATIONS, inspired from msvc++ <type_traits>. // BITSHIFT OPERATIONS, inspired from msvc++ <type_traits>.
#define CC_ENABLE_BITSHIFT_OPS(_BITMASK) \ #define CC_ENABLE_BITSHIFT_OPS(_BITMASK) \
constexpr _BITMASK operator>>(_BITMASK _Left, _BITMASK _Right) noexcept { /* return _Left & _Right */ \ 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; \ using _IntTy = _STD underlying_type<_BITMASK>::type; \
return static_cast<_BITMASK>(static_cast<_IntTy>(_Left) << static_cast<_IntTy>(_Right)); \ 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; float height = 0;
}; };
// TODO: Move to renderer/backend/Types.h
struct TextureFormatEXT struct TextureFormatEXT
{ {
enum { 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 TextureUsage = backend::TextureUsage;
using PixelFormat = backend::PixelFormat; using PixelFormat = backend::PixelFormat;
using TargetBufferFlags = backend::TargetBufferFlags;
using RenderTargetFlag = backend::RenderTargetFlag;
using ClearFlag = backend::ClearFlag;
NS_CC_END NS_CC_END
// end group // end group
/// @} /// @}

View File

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

View File

@ -33,6 +33,8 @@ THE SOFTWARE.
#define glUnmapBuffer glUnmapBufferOES #define glUnmapBuffer glUnmapBufferOES
#define GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8_OES #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 #define GL_WRITE_ONLY GL_WRITE_ONLY_OES
// GL_GLEXT_PROTOTYPES isn't defined in glplatform.h on android ndk r7 // 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 glUnmapBuffer glUnmapBufferOES
#define GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8_OES #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 #define GL_WRITE_ONLY GL_WRITE_ONLY_OES
#include <OpenGLES/ES2/gl.h> #include <OpenGLES/ES2/gl.h>

View File

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

View File

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

View File

@ -47,6 +47,7 @@
#include "xxhash.h" #include "xxhash.h"
#include "renderer/backend/Backend.h" #include "renderer/backend/Backend.h"
#include "renderer/backend/RenderTarget.h"
NS_CC_BEGIN NS_CC_BEGIN
@ -180,6 +181,7 @@ Renderer::~Renderer()
CC_SAFE_RELEASE(_commandBuffer); CC_SAFE_RELEASE(_commandBuffer);
CC_SAFE_RELEASE(_renderPipeline); CC_SAFE_RELEASE(_renderPipeline);
CC_SAFE_RELEASE(_defaultRT);
} }
void Renderer::init() void Renderer::init()
@ -191,6 +193,9 @@ void Renderer::init()
auto device = backend::Device::getInstance(); auto device = backend::Device::getInstance();
_commandBuffer = device->newCommandBuffer(); _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(); _renderPipeline = device->newRenderPipeline();
_commandBuffer->setRenderPipeline(_renderPipeline); _commandBuffer->setRenderPipeline(_renderPipeline);
} }
@ -404,7 +409,8 @@ void Renderer::clean()
void Renderer::setDepthTest(bool value) void Renderer::setDepthTest(bool value)
{ {
_depthStencilDescriptor.depthTestEnabled = value; _depthStencilDescriptor.depthTestEnabled = value;
_renderPassDescriptor.depthTestEnabled = value; _currentRT->modifyTargetFlags(value ? TargetBufferFlags::DEPTH : TargetBufferFlags::NONE,
value ? TargetBufferFlags::NONE : TargetBufferFlags::DEPTH);
} }
void Renderer::setDepthWrite(bool value) void Renderer::setDepthWrite(bool value)
@ -435,7 +441,9 @@ bool Renderer::getDepthWrite() const
void Renderer::setStencilTest(bool value) void Renderer::setStencilTest(bool value)
{ {
_depthStencilDescriptor.stencilTestEnabled = 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) 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])); _vertexBuffer->updateData(_verts, _filledVertex * sizeof(_verts[0]));
_indexBuffer->updateData(_indices, _filledIndex * sizeof(_indices[0])); _indexBuffer->updateData(_indices, _filledIndex * sizeof(_indices[0]));
#endif #endif
/************** 2: Draw *************/ /************** 2: Draw *************/
beginRenderPass();
for (int i = 0; i < batchesTotal; ++i) for (int i = 0; i < batchesTotal; ++i)
{ {
beginRenderPass(_triBatchesToDraw[i].cmd);
auto& drawInfo = _triBatchesToDraw[i];
setRenderPipeline(drawInfo.cmd->getPipelineDescriptor(), _renderPassParams);
_commandBuffer->setVertexBuffer(_vertexBuffer); _commandBuffer->setVertexBuffer(_vertexBuffer);
_commandBuffer->setIndexBuffer(_indexBuffer); _commandBuffer->setIndexBuffer(_indexBuffer);
auto& pipelineDescriptor = _triBatchesToDraw[i].cmd->getPipelineDescriptor(); auto& pipelineDescriptor = drawInfo.cmd->getPipelineDescriptor();
_commandBuffer->setProgramState(pipelineDescriptor.programState); _commandBuffer->setProgramState(pipelineDescriptor.programState);
_commandBuffer->drawElements(backend::PrimitiveType::TRIANGLE, _commandBuffer->drawElements(backend::PrimitiveType::TRIANGLE,
backend::IndexFormat::U_SHORT, backend::IndexFormat::U_SHORT,
_triBatchesToDraw[i].indicesToDraw, drawInfo.indicesToDraw,
_triBatchesToDraw[i].offset * sizeof(_indices[0])); drawInfo.offset * sizeof(_indices[0]));
_commandBuffer->endRenderPass();
_drawnBatches++; _drawnBatches++;
_drawnVertices += _triBatchesToDraw[i].indicesToDraw; _drawnVertices += _triBatchesToDraw[i].indicesToDraw;
} }
_commandBuffer->endRenderPass();
/************** 3: Cleanup *************/ /************** 3: Cleanup *************/
_queuedTriangleCommands.clear(); _queuedTriangleCommands.clear();
@ -649,7 +663,8 @@ void Renderer::drawCustomCommand(RenderCommand *command)
if (cmd->getBeforeCallback()) cmd->getBeforeCallback()(); if (cmd->getBeforeCallback()) cmd->getBeforeCallback()();
beginRenderPass(command); beginRenderPass();
setRenderPipeline(cmd->getPipelineDescriptor(), _renderPassParams);
_commandBuffer->setVertexBuffer(cmd->getVertexBuffer()); _commandBuffer->setVertexBuffer(cmd->getVertexBuffer());
_commandBuffer->setProgramState(cmd->getPipelineDescriptor().programState); _commandBuffer->setProgramState(cmd->getPipelineDescriptor().programState);
@ -738,21 +753,24 @@ bool Renderer::checkVisibility(const Mat4 &transform, const Size &size)
return ret; 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); 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(); auto device = backend::Device::getInstance();
_renderPipeline->update(pipelineDescriptor, renderPassDescriptor); _renderPipeline->update(pipelineDescriptor, _currentRT, renderPassParams);
backend::DepthStencilState* depthStencilState = nullptr; backend::DepthStencilState* depthStencilState = nullptr;
auto needDepthStencilAttachment = renderPassDescriptor.depthTestEnabled || renderPassDescriptor.stencilTestEnabled; if (bitmask::any(_currentRT->getTargetFlags(), RenderTargetFlag::DEPTH_AND_STENCIL))
if (needDepthStencilAttachment)
{ {
// FIXME: don't use autorelease at draw frame
// Now the depthStencilState is in autoreleasepool
depthStencilState = device->createDepthStencilState(_depthStencilDescriptor); depthStencilState = device->createDepthStencilState(_depthStencilDescriptor);
} }
_commandBuffer->setDepthStencilState(depthStencilState); _commandBuffer->setDepthStencilState(depthStencilState);
@ -761,125 +779,36 @@ void Renderer::setRenderPipeline(const PipelineDescriptor& pipelineDescriptor, c
#endif #endif
} }
void Renderer::beginRenderPass(RenderCommand* cmd) void Renderer::beginRenderPass()
{ {
_commandBuffer->beginRenderPass(_renderPassDescriptor); _commandBuffer->beginRenderPass(_currentRT, _renderPassParams);
_commandBuffer->setViewport(_viewport.x, _viewport.y, _viewport.w, _viewport.h); _commandBuffer->setViewport(_viewport.x, _viewport.y, _viewport.w, _viewport.h);
_commandBuffer->setCullMode(_cullMode); _commandBuffer->setCullMode(_cullMode);
_commandBuffer->setWinding(_winding); _commandBuffer->setWinding(_winding);
_commandBuffer->setScissorRect(_scissorState.isEnabled, _scissorState.rect.x, _scissorState.rect.y, _scissorState.rect.width, _scissorState.rect.height); _commandBuffer->setScissorRect(_scissorState.isEnabled, _scissorState.rect.x, _scissorState.rect.y, _scissorState.rect.width, _scissorState.rect.height);
setRenderPipeline(cmd->getPipelineDescriptor(), _renderPassDescriptor);
_commandBuffer->setStencilReferenceValue(_stencilRef); _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) void Renderer::clear(ClearFlag flags, const Color4F& color, float depth, unsigned int stencil, float globalOrder)
{ {
_clearFlag = flags; _clearFlag = flags;
CallbackCommand* command = new CallbackCommand(); backend::RenderPassParams descriptor;
command->init(globalOrder);
command->func = [=]() -> void {
backend::RenderPassDescriptor descriptor;
if (_Bitmask_includes(ClearFlag::COLOR, flags)) descriptor.flags.clear = flags;
{ if (bitmask::any(flags, ClearFlag::COLOR)) {
_clearColor = color; _clearColor = color;
descriptor.clearColorValue = {color.r, color.g, color.b, color.a}; 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;
}
_commandBuffer->beginRenderPass(descriptor); if(bitmask::any(flags, ClearFlag::DEPTH))
_commandBuffer->endRenderPass(); descriptor.clearDepthValue = depth;
delete command; if(bitmask::any(flags, ClearFlag::STENCIL))
}; descriptor.clearStencilValue = stencil;
addCommand(command);
}
Texture2D* Renderer::getColorAttachment() const _commandBuffer->beginRenderPass(_currentRT, descriptor);
{ _commandBuffer->endRenderPass();
return _colorAttachment;
}
Texture2D* Renderer::getDepthAttachment() const
{
return _depthAttachment;
}
Texture2D* Renderer::getStencilAttachment() const
{
return _stencilAttachment;
} }
const Color4F& Renderer::getClearColor() const const Color4F& Renderer::getClearColor() const
@ -889,12 +818,12 @@ const Color4F& Renderer::getClearColor() const
float Renderer::getClearDepth() const float Renderer::getClearDepth() const
{ {
return _renderPassDescriptor.clearDepthValue; return _renderPassParams.clearDepthValue;
} }
unsigned int Renderer::getClearStencil() const unsigned int Renderer::getClearStencil() const
{ {
return _renderPassDescriptor.clearStencilValue; return _renderPassParams.clearStencilValue;
} }
ClearFlag Renderer::getClearFlag() const ClearFlag Renderer::getClearFlag() const
@ -904,7 +833,7 @@ ClearFlag Renderer::getClearFlag() const
RenderTargetFlag Renderer::getRenderTargetFlag() const RenderTargetFlag Renderer::getRenderTargetFlag() const
{ {
return _renderTargetFlag; return _currentRT->getTargetFlags();
} }
void Renderer::setScissorTest(bool enabled) void Renderer::setScissorTest(bool enabled)

View File

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

View File

@ -28,7 +28,7 @@ set(COCOS_RENDERER_HEADER
renderer/backend/Program.h renderer/backend/Program.h
renderer/backend/ProgramCache.h renderer/backend/ProgramCache.h
renderer/backend/Macros.h renderer/backend/Macros.h
renderer/backend/RenderPassDescriptor.h renderer/backend/RenderPassParams.h
renderer/backend/RenderPipeline.h renderer/backend/RenderPipeline.h
renderer/backend/RenderPipelineDescriptor.h renderer/backend/RenderPipelineDescriptor.h
renderer/backend/ShaderModule.h renderer/backend/ShaderModule.h
@ -74,7 +74,7 @@ set(COCOS_RENDERER_SRC
renderer/backend/ProgramState.cpp renderer/backend/ProgramState.cpp
renderer/backend/ProgramStateRegistry.cpp renderer/backend/ProgramStateRegistry.cpp
renderer/backend/ShaderCache.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)) 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/TextureGL.h
renderer/backend/opengl/UtilsGL.h renderer/backend/opengl/UtilsGL.h
renderer/backend/opengl/DeviceInfoGL.h renderer/backend/opengl/DeviceInfoGL.h
renderer/backend/opengl/RenderTargetGL.h
) )
list(APPEND COCOS_RENDERER_SRC list(APPEND COCOS_RENDERER_SRC
@ -103,6 +104,7 @@ list(APPEND COCOS_RENDERER_SRC
renderer/backend/opengl/TextureGL.cpp renderer/backend/opengl/TextureGL.cpp
renderer/backend/opengl/UtilsGL.cpp renderer/backend/opengl/UtilsGL.cpp
renderer/backend/opengl/DeviceInfoGL.cpp renderer/backend/opengl/DeviceInfoGL.cpp
renderer/backend/opengl/RenderTargetGL.cpp
) )
else() else()
@ -111,6 +113,7 @@ list(APPEND COCOS_RENDERER_HEADER
renderer/backend/metal/BufferMTL.h renderer/backend/metal/BufferMTL.h
renderer/backend/metal/BufferManager.h renderer/backend/metal/BufferManager.h
renderer/backend/metal/CommandBufferMTL.h renderer/backend/metal/CommandBufferMTL.h
renderer/backend/metal/RenderTargetMTL.h
renderer/backend/metal/DepthStencilStateMTL.h renderer/backend/metal/DepthStencilStateMTL.h
renderer/backend/metal/DeviceMTL.h renderer/backend/metal/DeviceMTL.h
renderer/backend/metal/RenderPipelineMTL.h renderer/backend/metal/RenderPipelineMTL.h
@ -125,6 +128,7 @@ list(APPEND COCOS_RENDERER_SRC
renderer/backend/metal/BufferMTL.mm renderer/backend/metal/BufferMTL.mm
renderer/backend/metal/BufferManager.mm renderer/backend/metal/BufferManager.mm
renderer/backend/metal/CommandBufferMTL.mm renderer/backend/metal/CommandBufferMTL.mm
renderer/backend/metal/RenderTargetMTL.mm
renderer/backend/metal/DepthStencilStateMTL.mm renderer/backend/metal/DepthStencilStateMTL.mm
renderer/backend/metal/DeviceMTL.mm renderer/backend/metal/DeviceMTL.mm
renderer/backend/metal/RenderPipelineMTL.mm renderer/backend/metal/RenderPipelineMTL.mm

View File

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

View File

@ -31,7 +31,7 @@
#include "Macros.h" #include "Macros.h"
#include "Types.h" #include "Types.h"
#include "RenderPassDescriptor.h" #include "RenderPassParams.h"
#include "PixelBufferDescriptor.h" #include "PixelBufferDescriptor.h"
#include "CCStdC.h" #include "CCStdC.h"
#include "ProgramState.h" #include "ProgramState.h"
@ -47,6 +47,7 @@ class RenderPipeline;
class Buffer; class Buffer;
class DepthStencilState; class DepthStencilState;
class TextureBackend; class TextureBackend;
class RenderTarget;
/** /**
* @addtogroup _backend * @addtogroup _backend
@ -70,7 +71,7 @@ public:
* Begin a render pass, initial color, depth and stencil attachment. * 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. * @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. * Sets the current render pipeline state object.
@ -172,7 +173,7 @@ public:
* Get a screen snapshot * Get a screen snapshot
* @param callback A callback to deal with screen snapshot image. * @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. * Update both front and back stencil reference value.

View File

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

View File

@ -27,7 +27,7 @@
#define CC_BACKEND_BEGIN namespace cocos2d{ namespace backend{ #define CC_BACKEND_BEGIN namespace cocos2d{ namespace backend{
#define CC_BACKEND_END }} #define CC_BACKEND_END }}
#define MAX_COLOR_ATTCHMENT 1 #define MAX_COLOR_ATTCHMENT 4
#define MAX_INFLIGHT_BUFFER 3 #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. * Store values about color, depth and stencil attachment.
*/ */
struct RenderPassDescriptor struct RenderPassParams
{ {
RenderPassDescriptor& operator=(const RenderPassDescriptor& descriptor); RenderPassParams& operator=(const RenderPassParams& descriptor) = default;
bool operator==(const RenderPassDescriptor& descriptor) const; bool operator==(const RenderPassParams& descriptor) const;
bool needDepthStencilAttachment() const { return depthTestEnabled || stencilTestEnabled; }
float clearDepthValue = 0.f; float clearDepthValue = 0.f;
float clearStencilValue = 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 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; // Now, only clear flag used
bool stencilTestEnabled = false; RenderPassFlags flags{};
bool needClearColor = false;
bool needClearDepth = false;
bool needClearStencil = false;
TextureBackend* depthAttachmentTexture = nullptr;
TextureBackend* stencilAttachmentTexture = nullptr;
TextureBackend* colorAttachmentsTexture[MAX_COLOR_ATTCHMENT] = { nullptr };
}; };
typedef RenderPassParams RenderPassParams;
//end of _backend group //end of _backend group
/// @} /// @}

View File

@ -28,13 +28,14 @@
#include "Types.h" #include "Types.h"
#include "base/CCRef.h" #include "base/CCRef.h"
#include "renderer/CCPipelineDescriptor.h" #include "renderer/CCPipelineDescriptor.h"
#include "renderer/backend/RenderPassDescriptor.h" #include "renderer/backend/RenderPassParams.h"
CC_BACKEND_BEGIN CC_BACKEND_BEGIN
/** /**
* @addtogroup _backend * @addtogroup _backend
* @{ * @{
*/ */
class RenderTarget;
/** /**
* Render pipeline * Render pipeline
@ -42,7 +43,7 @@ CC_BACKEND_BEGIN
class RenderPipeline : public cocos2d::Ref class RenderPipeline : public cocos2d::Ref
{ {
public: 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: protected:
virtual ~RenderPipeline() = default; 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; SamplerDescriptor samplerDescriptor;
}; };
struct UtilsGL;
/** /**
* A base texture * A base texture
*/ */
class TextureBackend : public Ref class TextureBackend : public Ref
{ {
friend struct UtilsGL;
public: public:
/** /**
* Update sampler * Update sampler
@ -106,6 +103,8 @@ public:
int getWidth() const { return _width; } int getWidth() const { return _width; }
int getHeight() const { return _height; } int getHeight() const { return _height; }
int getBytesPerRow() const { return _width * _bitsPerElement / 8; }
protected: protected:
/** /**
* @param descriptor Specifies the texture descirptor. * @param descriptor Specifies the texture descirptor.

View File

@ -27,6 +27,7 @@
#include "Macros.h" #include "Macros.h"
#include <assert.h>
#include <cstdint> #include <cstdint>
#include <string> #include <string>
#include "base/bitmask.h" #include "base/bitmask.h"
@ -258,6 +259,33 @@ enum class ColorWriteMask : uint32_t
CC_ENABLE_BITMASK_OPS(ColorWriteMask) CC_ENABLE_BITMASK_OPS(ColorWriteMask)
CC_ENABLE_BITSHIFT_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 struct SamplerDescriptor
{ {
SamplerFilter magFilter = SamplerFilter::LINEAR; SamplerFilter magFilter = SamplerFilter::LINEAR;
@ -418,4 +446,6 @@ struct BlendDescriptor
BlendFactor sourceAlphaBlendFactor = BlendFactor::ONE; BlendFactor sourceAlphaBlendFactor = BlendFactor::ONE;
BlendFactor destinationAlphaBlendFactor = BlendFactor::ZERO; BlendFactor destinationAlphaBlendFactor = BlendFactor::ZERO;
}; };
CC_BACKEND_END CC_BACKEND_END

View File

@ -61,11 +61,11 @@ public:
virtual void beginFrame() override; virtual void beginFrame() override;
/** /**
* Create a MTLRenderCommandEncoder object for graphics rendering to an attachment in a RenderPassDescriptor. * Create a MTLRenderCommandEncoder object for graphics rendering to an attachment in a RenderPassParams.
* MTLRenderCommandEncoder is cached if current RenderPassDescriptor is identical to previous one. * 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. * @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. * Sets the current render pipeline state object.
@ -166,10 +166,22 @@ public:
virtual void setDepthStencilState(DepthStencilState* depthStencilState) override; virtual void setDepthStencilState(DepthStencilState* depthStencilState) override;
/** /**
* Get a screen snapshot * Read pixels from RenderTarget
* @param callback A callback to deal with screen snapshot image. * @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: private:
void prepareDrawing() const; void prepareDrawing() const;
@ -179,7 +191,7 @@ private:
void afterDraw(); void afterDraw();
void flush(); void flush();
void flushCaptureCommands(); void flushCaptureCommands();
id<MTLRenderCommandEncoder> getRenderCommandEncoder(const RenderPassDescriptor& renderPassDescriptor); id<MTLRenderCommandEncoder> getRenderCommandEncoder(const RenderTarget* renderTarget, const RenderPassParams& renderPassParams);
id<MTLCommandBuffer> _mtlCommandBuffer = nil; id<MTLCommandBuffer> _mtlCommandBuffer = nil;
id<MTLCommandQueue> _mtlCommandQueue = nil; id<MTLCommandQueue> _mtlCommandQueue = nil;
@ -195,7 +207,8 @@ private:
unsigned int _renderTargetHeight = 0; unsigned int _renderTargetHeight = 0;
dispatch_semaphore_t _frameBoundarySemaphore; dispatch_semaphore_t _frameBoundarySemaphore;
RenderPassDescriptor _prevRenderPassDescriptor; const RenderTarget* _currentRenderTarget = nil; // weak ref
RenderPassParams _currentRenderPassParams;
NSAutoreleasePool* _autoReleasePool = nil; NSAutoreleasePool* _autoReleasePool = nil;
std::vector<std::pair<TextureBackend*,std::function<void(const PixelBufferDescriptor&)>>> _captureCallbacks; std::vector<std::pair<TextureBackend*,std::function<void(const PixelBufferDescriptor&)>>> _captureCallbacks;

View File

@ -32,12 +32,46 @@
#include "../Macros.h" #include "../Macros.h"
#include "BufferManager.h" #include "BufferManager.h"
#include "DepthStencilStateMTL.h" #include "DepthStencilStateMTL.h"
#include "RenderTargetMTL.h"
CC_BACKEND_BEGIN CC_BACKEND_BEGIN
namespace 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) if (Winding::CLOCK_WISE == winding)
return MTLWindingClockwise; return MTLWindingClockwise;
@ -45,7 +79,7 @@ namespace
return MTLWindingCounterClockwise; return MTLWindingCounterClockwise;
} }
MTLPrimitiveType toMTLPrimitive(PrimitiveType primitiveType) static MTLPrimitiveType toMTLPrimitive(PrimitiveType primitiveType)
{ {
MTLPrimitiveType ret = MTLPrimitiveTypeTriangle; MTLPrimitiveType ret = MTLPrimitiveTypeTriangle;
switch (primitiveType) switch (primitiveType)
@ -71,7 +105,7 @@ namespace
return ret; return ret;
} }
MTLIndexType toMTLIndexType(IndexFormat indexFormat) static MTLIndexType toMTLIndexType(IndexFormat indexFormat)
{ {
if (IndexFormat::U_SHORT == indexFormat) if (IndexFormat::U_SHORT == indexFormat)
return MTLIndexTypeUInt16; return MTLIndexTypeUInt16;
@ -79,7 +113,7 @@ namespace
return MTLIndexTypeUInt32; return MTLIndexTypeUInt32;
} }
MTLCullMode toMTLCullMode(CullMode mode) static MTLCullMode toMTLCullMode(CullMode mode)
{ {
switch (mode) { switch (mode) {
case CullMode::NONE: 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]; MTLRenderPassDescriptor* mtlDescritpor = [MTLRenderPassDescriptor renderPassDescriptor];
// Set color attachments. auto rtMTL = static_cast<const RenderTargetMTL*>(rt);
if (descriptor.needColorAttachment) rtMTL->applyRenderPassAttachments(params, mtlDescritpor);
{
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;
}
}
return mtlDescritpor; return mtlDescritpor;
} }
id<MTLTexture> getMTLTexture(TextureBackend* texture, int index = 0) static id<MTLTexture> getMTLTexture(TextureBackend* texture, int index)
{ {
switch (texture->getTextureType()) return reinterpret_cast<id<MTLTexture>>(texture->getHandler(index));
{
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;
}
} }
id<MTLSamplerState> getMTLSamplerState(TextureBackend* texture) static id<MTLSamplerState> getMTLSamplerState(TextureBackend* texture)
{ {
switch (texture->getTextureType()) switch (texture->getTextureType())
{ {
@ -242,15 +188,16 @@ void CommandBufferMTL::beginFrame()
BufferManager::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; return _mtlRenderEncoder;
} }
else else
{ {
_prevRenderPassDescriptor = renderPassDescriptor; _currentRenderTarget = renderTarget;
_currentRenderPassParams = renderPassParams;
} }
if(_mtlRenderEncoder != nil) if(_mtlRenderEncoder != nil)
@ -260,7 +207,7 @@ id<MTLRenderCommandEncoder> CommandBufferMTL::getRenderCommandEncoder(const Rend
_mtlRenderEncoder = nil; _mtlRenderEncoder = nil;
} }
auto mtlDescriptor = toMTLRenderPassDescriptor(renderPassDescriptor); auto mtlDescriptor = toMTLRenderPassDescriptor(renderTarget, renderPassParams);
_renderTargetWidth = (unsigned int)mtlDescriptor.colorAttachments[0].texture.width; _renderTargetWidth = (unsigned int)mtlDescriptor.colorAttachments[0].texture.width;
_renderTargetHeight = (unsigned int)mtlDescriptor.colorAttachments[0].texture.height; _renderTargetHeight = (unsigned int)mtlDescriptor.colorAttachments[0].texture.height;
id<MTLRenderCommandEncoder> mtlRenderEncoder = [_mtlCommandBuffer renderCommandEncoderWithDescriptor:mtlDescriptor]; id<MTLRenderCommandEncoder> mtlRenderEncoder = [_mtlCommandBuffer renderCommandEncoderWithDescriptor:mtlDescriptor];
@ -269,9 +216,9 @@ id<MTLRenderCommandEncoder> CommandBufferMTL::getRenderCommandEncoder(const Rend
return mtlRenderEncoder; 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]; // [_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); CC_SAFE_RETAIN(texture);
_captureCallbacks.emplace_back(texture, std::move(callback)); _captureCallbacks.emplace_back(texture, std::move(callback));
} }
@ -407,7 +359,7 @@ void CommandBufferMTL::flushCaptureCommands()
for(auto& cb : _captureCallbacks) { for(auto& cb : _captureCallbacks) {
if(cb.first == nil) { // screen capture if(cb.first == nil) { // screen capture
if(!screenPixelData) { 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 // screen framebuffer copied, restore screen framebuffer only to true
backend::Device::getInstance()->setFrameBufferOnly(true); backend::Device::getInstance()->setFrameBufferOnly(true);
} }
@ -417,7 +369,7 @@ void CommandBufferMTL::flushCaptureCommands()
PixelBufferDescriptor pixelData; PixelBufferDescriptor pixelData;
auto texture = cb.first; auto texture = cb.first;
assert(texture != nullptr); 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); CC_SAFE_RELEASE(texture);
cb.second(pixelData); cb.second(pixelData);
} }
@ -570,5 +522,52 @@ void CommandBufferMTL::setScissorRect(bool isEnabled, float x, float y, float wi
[_mtlRenderEncoder setScissorRect:scissorRect]; [_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 CC_BACKEND_END

View File

@ -95,6 +95,12 @@ public:
* @return A TextureBackend object. * @return A TextureBackend object.
*/ */
virtual TextureBackend* newTexture(const TextureDescriptor& descriptor) override; 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. * Create a DepthStencilState object.

View File

@ -31,6 +31,7 @@
#include "TextureMTL.h" #include "TextureMTL.h"
#include "ProgramMTL.h" #include "ProgramMTL.h"
#include "DeviceInfoMTL.h" #include "DeviceInfoMTL.h"
#include "RenderTargetMTL.h"
#include "base/ccMacros.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) ShaderModule* DeviceMTL::newShaderModule(ShaderStage stage, const std::string& source)
{ {
return new (std::nothrow) ShaderModuleMTL(_mtlDevice, stage, source); return new (std::nothrow) ShaderModuleMTL(_mtlDevice, stage, source);

View File

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

View File

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

View File

@ -194,7 +194,8 @@ namespace
return bytesPerRow; 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); MTLPixelFormat pixelFormat = UtilsMTL::toMTLPixelFormat(textureFormat);
std::size_t bytesPerRow = 0; std::size_t bytesPerRow = 0;
@ -361,7 +362,7 @@ void TextureMTL::updateSubData(std::size_t xoffset, std::size_t yoffset, std::si
width * height, width * height,
_textureFormat, &convertedData); _textureFormat, &convertedData);
std::size_t bytesPerRow = getBytesPerRow(_textureFormat, width, _bitsPerElement); std::size_t bytesPerRow = getBytesPerRowMTL(_textureFormat, width, _bitsPerElement);
[mtlTexture replaceRegion:region [mtlTexture replaceRegion:region
mipmapLevel:level mipmapLevel:level
@ -393,7 +394,7 @@ void TextureMTL::generateMipmaps()
if(!_hasMipmaps) if(!_hasMipmaps)
{ {
_hasMipmaps = true; _hasMipmaps = true;
UtilsMTL::generateMipmaps(this->getMTLTexture()); UtilsMTL::generateMipmaps(reinterpret_cast<id<MTLTexture>>(this->getHandler()));
} }
} }
@ -454,7 +455,7 @@ void TextureCubeMTL::generateMipmaps()
if(!_hasMipmaps) if(!_hasMipmaps)
{ {
_hasMipmaps = true; _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. * @param texture Specifies a texture to generate mipmap.
*/ */
static void generateMipmaps(id<MTLTexture> texture); 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. * Swizzle the iamge form the given format to MTLPixelFormatRGBA8Unorm.
* @param image Specifies the image to be swizzled. * @param image Specifies the image to be swizzled.

View File

@ -36,39 +36,6 @@ id<MTLTexture> UtilsMTL::_defaultColorAttachmentTexture = nil;
id<MTLTexture> UtilsMTL::_defaultDepthStencilAttachmentTexture = nil; id<MTLTexture> UtilsMTL::_defaultDepthStencilAttachmentTexture = nil;
namespace { 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 getSupportedDepthStencilFormat()
{ {
MTLPixelFormat pixelFormat = MTLPixelFormatDepth32Float_Stencil8; 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 CC_BACKEND_END

View File

@ -33,27 +33,13 @@
#include "base/CCEventType.h" #include "base/CCEventType.h"
#include "base/CCDirector.h" #include "base/CCDirector.h"
#include "renderer/backend/opengl/UtilsGL.h" #include "renderer/backend/opengl/UtilsGL.h"
#include "RenderTargetGL.h"
#include <algorithm> #include <algorithm>
CC_BACKEND_BEGIN CC_BACKEND_BEGIN
namespace 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) void applyTexture(TextureBackend* texture, int slot, int index)
{ {
switch (texture->getTextureType()) 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); auto rtGL = static_cast<const RenderTargetGL*>(rt);
}
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);
if (useDepthAttachmentExternal) rtGL->bindFrameBuffer();
{
glFramebufferTexture2D(GL_FRAMEBUFFER, auto clearFlags = descirptor.flags.clear;
GL_DEPTH_ATTACHMENT,
GL_TEXTURE_2D,
getHandler(descirptor.depthAttachmentTexture),
0);
CHECK_GL_ERROR_DEBUG();
_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 // set clear color, depth and stencil
GLbitfield mask = 0; GLbitfield mask = 0;
if (descirptor.needClearColor) if (bitmask::any(clearFlags, TargetBufferFlags::COLOR))
{ {
mask |= GL_COLOR_BUFFER_BIT; mask |= GL_COLOR_BUFFER_BIT;
const auto& clearColor = descirptor.clearColorValue; const auto& clearColor = descirptor.clearColorValue;
glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]); glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
} }
CHECK_GL_ERROR_DEBUG(); CHECK_GL_ERROR_DEBUG();
GLboolean oldDepthWrite = GL_FALSE; GLboolean oldDepthWrite = GL_FALSE;
GLboolean oldDepthTest = GL_FALSE; GLboolean oldDepthTest = GL_FALSE;
GLfloat oldDepthClearValue = 0.f; GLfloat oldDepthClearValue = 0.f;
GLint oldDepthFunc = GL_LESS; GLint oldDepthFunc = GL_LESS;
if (descirptor.needClearDepth) if (bitmask::any(clearFlags, TargetBufferFlags::DEPTH))
{ {
glGetBooleanv(GL_DEPTH_WRITEMASK, &oldDepthWrite); glGetBooleanv(GL_DEPTH_WRITEMASK, &oldDepthWrite);
glGetBooleanv(GL_DEPTH_TEST, &oldDepthTest); glGetBooleanv(GL_DEPTH_TEST, &oldDepthTest);
glGetFloatv(GL_DEPTH_CLEAR_VALUE, &oldDepthClearValue); glGetFloatv(GL_DEPTH_CLEAR_VALUE, &oldDepthClearValue);
glGetIntegerv(GL_DEPTH_FUNC, &oldDepthFunc); glGetIntegerv(GL_DEPTH_FUNC, &oldDepthFunc);
mask |= GL_DEPTH_BUFFER_BIT; mask |= GL_DEPTH_BUFFER_BIT;
glClearDepth(descirptor.clearDepthValue); glClearDepth(descirptor.clearDepthValue);
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE); glDepthMask(GL_TRUE);
glDepthFunc(GL_ALWAYS); glDepthFunc(GL_ALWAYS);
} }
CHECK_GL_ERROR_DEBUG(); CHECK_GL_ERROR_DEBUG();
if (descirptor.needClearStencil) if (bitmask::any(clearFlags, TargetBufferFlags::STENCIL))
{ {
mask |= GL_STENCIL_BUFFER_BIT; mask |= GL_STENCIL_BUFFER_BIT;
glClearStencil(descirptor.clearStencilValue); glClearStencil(descirptor.clearStencilValue);
} }
if(mask) glClear(mask); if (mask) glClear(mask);
CHECK_GL_ERROR_DEBUG(); CHECK_GL_ERROR_DEBUG();
// restore depth test // restore depth test
if (descirptor.needClearDepth) if (bitmask::any(clearFlags, TargetBufferFlags::DEPTH))
{ {
if (!oldDepthTest) if (!oldDepthTest)
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
glDepthMask(oldDepthWrite); glDepthMask(oldDepthWrite);
glDepthFunc(oldDepthFunc); glDepthFunc(oldDepthFunc);
glClearDepth(oldDepthClearValue); glClearDepth(oldDepthClearValue);
} }
CHECK_GL_ERROR_DEBUG(); CHECK_GL_ERROR_DEBUG();
} }
@ -379,7 +232,6 @@ void CommandBufferGL::endRenderPass()
void CommandBufferGL::endFrame() void CommandBufferGL::endFrame()
{ {
// executeGpuCommandsCompleteOps();
} }
void CommandBufferGL::setDepthStencilState(DepthStencilState* depthStencilState) 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; PixelBufferDescriptor pbd;
if (!texture) if(rt->isDefaultRenderTarget())
UtilsGL::readPixels(nullptr, _viewPort.x, _viewPort.y, _viewPort.w, _viewPort.h, pbd); { // read pixels from screen
else readPixels(rt, _viewPort.x, _viewPort.y, _viewPort.w, _viewPort.h, _viewPort.w * 4, pbd);
UtilsGL::readPixels(texture, 0, 0, texture->getWidth(), texture->getHeight(), 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); 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 CC_BACKEND_END

View File

@ -65,7 +65,7 @@ public:
* Begin a render pass, initial color, depth and stencil attachment. * 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. * @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. * Sets the current render pipeline state object.
@ -167,7 +167,10 @@ public:
* Get a screen snapshot * Get a screen snapshot
* @param callback A callback to deal with screen snapshot image. * @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: private:
struct Viewport struct Viewport
@ -183,7 +186,6 @@ private:
void setUniforms(ProgramGL* program) const; void setUniforms(ProgramGL* program) const;
void setUniform(bool isArray, GLuint location, unsigned int size, GLenum uniformType, void* data) const; void setUniform(bool isArray, GLuint location, unsigned int size, GLenum uniformType, void* data) const;
void cleanResources(); void cleanResources();
void applyRenderPassDescriptor(const RenderPassDescriptor& descirptor);
// The frame buffer generated by engine. All frame buffer other than default frame buffer share it. // The frame buffer generated by engine. All frame buffer other than default frame buffer share it.
GLuint _generatedFBO = 0; GLuint _generatedFBO = 0;

View File

@ -31,6 +31,7 @@
#include "DepthStencilStateGL.h" #include "DepthStencilStateGL.h"
#include "ProgramGL.h" #include "ProgramGL.h"
#include "DeviceInfoGL.h" #include "DeviceInfoGL.h"
#include "RenderTargetGL.h"
CC_BACKEND_BEGIN 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) ShaderModule* DeviceGL::newShaderModule(ShaderStage stage, const std::string& source)
{ {
return new (std::nothrow) ShaderModuleGL(stage, source); return new (std::nothrow) ShaderModuleGL(stage, source);

View File

@ -61,6 +61,12 @@ public:
*/ */
virtual TextureBackend* newTexture(const TextureDescriptor& descriptor) override; 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. * Create an auto released DepthStencilState object.
* @param descriptor Specifies depth and stencil description. * @param descriptor Specifies depth and stencil description.

View File

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

View File

@ -51,7 +51,7 @@ public:
RenderPipelineGL() = default; RenderPipelineGL() = default;
~RenderPipelineGL(); ~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. * Get program instance.
* @return 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() 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); _width = (std::max)(_width, (uint32_t)1);
_height = (std::max)(_height, (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; auto size = _width * _height * _bitsPerElement / 8;
uint8_t* data = (uint8_t*)malloc(size); 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; // internalFormat = GL_DEPTH_COMPONENT;
// type = GL_UNSIGNED_INT; // type = GL_UNSIGNED_INT;
case PixelFormat::D24S8: case PixelFormat::D24S8:
#ifdef CC_USE_GLES
format = GL_DEPTH_STENCIL_OES; format = GL_DEPTH_STENCIL_OES;
internalFormat = GL_DEPTH_STENCIL_OES; internalFormat = GL_DEPTH_STENCIL_OES;
type = GL_UNSIGNED_INT_24_8_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; break;
default: default:
break; break;
@ -592,79 +586,4 @@ GLenum UtilsGL::toGLCullMode(CullMode mode)
return GL_FRONT; 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 CC_BACKEND_END

View File

@ -34,9 +34,6 @@ CC_BACKEND_BEGIN
* @addtogroup _opengl * @addtogroup _opengl
* @{ * @{
*/ */
class TextureBackend;
/** /**
* Convert backend enum class to corresponding opengl defined value. * Convert backend enum class to corresponding opengl defined value.
*/ */
@ -154,16 +151,6 @@ struct UtilsGL
* @return Cull mode. * @return Cull mode.
*/ */
static GLenum toGLCullMode(CullMode 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 //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); tolua_error(tolua_S,"invalid arguments in function 'lua_cocos2dx_Renderer_getStencilAttachment'", nullptr);
return 0; return 0;
} }
cocos2d::Texture2D* ret = cobj->getStencilAttachment(); // cocos2d::Texture2D* ret = cobj->getStencilAttachment();
object_to_luaval<cocos2d::Texture2D>(tolua_S, "cc.Texture2D",(cocos2d::Texture2D*)ret); // object_to_luaval<cocos2d::Texture2D>(tolua_S, "cc.Texture2D",(cocos2d::Texture2D*)ret);
return 1; return 0;
} }
luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "cc.Renderer:getStencilAttachment",argc, 0); luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "cc.Renderer:getStencilAttachment",argc, 0);
return 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); tolua_error(tolua_S,"invalid arguments in function 'lua_cocos2dx_Renderer_getColorAttachment'", nullptr);
return 0; return 0;
} }
cocos2d::Texture2D* ret = cobj->getColorAttachment(); // cocos2d::Texture2D* ret = cobj->getColorAttachment();
object_to_luaval<cocos2d::Texture2D>(tolua_S, "cc.Texture2D",(cocos2d::Texture2D*)ret); // object_to_luaval<cocos2d::Texture2D>(tolua_S, "cc.Texture2D",(cocos2d::Texture2D*)ret);
return 1; return 0;
} }
luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "cc.Renderer:getColorAttachment",argc, 0); luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "cc.Renderer:getColorAttachment",argc, 0);
return 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); tolua_error(tolua_S,"invalid arguments in function 'lua_cocos2dx_Renderer_setRenderTarget'", nullptr);
return 0; return 0;
} }
cobj->setRenderTarget(arg0, arg1, arg2, arg3); // TODO:
// cobj->setRenderTarget(arg0, arg1, arg2, arg3);
lua_settop(tolua_S, 1); lua_settop(tolua_S, 1);
return 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); tolua_error(tolua_S,"invalid arguments in function 'lua_cocos2dx_Renderer_getDepthAttachment'", nullptr);
return 0; return 0;
} }
cocos2d::Texture2D* ret = cobj->getDepthAttachment(); // cocos2d::Texture2D* ret = cobj->getDepthAttachment();
object_to_luaval<cocos2d::Texture2D>(tolua_S, "cc.Texture2D",(cocos2d::Texture2D*)ret); // object_to_luaval<cocos2d::Texture2D>(tolua_S, "cc.Texture2D",(cocos2d::Texture2D*)ret);
return 1; return 0;
} }
luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "cc.Renderer:getDepthAttachment",argc, 0); luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "cc.Renderer:getDepthAttachment",argc, 0);
return 0; return 0;

View File

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

View File

@ -195,6 +195,7 @@ void ImGuiEXT::loadCustomFonts(void* ud)
case CHS_GLYPH_RANGE::FULL: case CHS_GLYPH_RANGE::FULL:
imChars = imFonts->GetGlyphRangesChineseFull(); imChars = imFonts->GetGlyphRangesChineseFull();
break; break;
default:;
} }
imFonts->AddFontFromFileTTF(fontInfo.first.c_str(), fontInfo.second.fontSize * contentZoomFactor, nullptr, imChars); 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); basefilePath = basefilePath.substr(0, pos + 1);
} }
else
{
basefilePath;
}
// lazy init // lazy init

View File

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

View File

@ -50,7 +50,7 @@ function build_mac_cmake()
cd $COCOS2DX_ROOT cd $COCOS2DX_ROOT
mkdir -p build mkdir -p build
cmake -S . -B build -GXcode -DBUILD_EXTENSION_IMGUI=ON 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 #xcodebuild -project Cocos2d-x.xcodeproj -alltargets -jobs $NUM_OF_CORES build | xcpretty
##the following commands must not be removed ##the following commands must not be removed
#xcodebuild -project Cocos2d-x.xcodeproj -alltargets -jobs $NUM_OF_CORES build #xcodebuild -project Cocos2d-x.xcodeproj -alltargets -jobs $NUM_OF_CORES build