From 51a52998aa89944a01ae78203806a01075ad884a Mon Sep 17 00:00:00 2001 From: Willy Scheibel Date: Wed, 5 Jul 2017 19:47:33 +0200 Subject: [PATCH] Emulate target framebuffer attachments if a render stage requests unsatisfiable attachment types --- .../demo-stages-plugins/ShapeDemo.cpp | 3 +- .../gloperate/include/gloperate/base/Canvas.h | 77 +++-- .../rendering/AbstractRenderTarget.h | 12 + .../base/RenderbufferRenderTargetStage.h | 19 +- source/gloperate/source/base/Canvas.cpp | 296 ++++++++++++++---- .../source/rendering/AbstractRenderTarget.cpp | 114 +++++++ .../base/RenderbufferRenderTargetStage.cpp | 37 ++- .../stages/interfaces/RenderInterface.cpp | 2 +- 8 files changed, 454 insertions(+), 106 deletions(-) diff --git a/source/examples/demo-stages-plugins/ShapeDemo.cpp b/source/examples/demo-stages-plugins/ShapeDemo.cpp index 2baa64be..f764f742 100644 --- a/source/examples/demo-stages-plugins/ShapeDemo.cpp +++ b/source/examples/demo-stages-plugins/ShapeDemo.cpp @@ -165,7 +165,8 @@ ShapeDemo::ShapeDemo(Environment * environment, const std::string & name) // Colorize rasterization stage addStage(m_colorizeRasterization.get()); - m_colorizeRasterization->createInput("ColorAttachment") << *createInput("Color"); + m_colorizeRasterization->createInput("Color") << *createInput("Color"); + //m_colorizeRasterization->createInput("Depth") << *createInput("Depth"); // This example doesn't need a depth buffer for postprocessing m_colorizeRasterization->renderInterface.viewport << canvasInterface.viewport; m_colorizeRasterization->drawable << m_colorizeRenderPass->renderPass; diff --git a/source/gloperate/include/gloperate/base/Canvas.h b/source/gloperate/include/gloperate/base/Canvas.h index 74ce700e..8186129e 100644 --- a/source/gloperate/include/gloperate/base/Canvas.h +++ b/source/gloperate/include/gloperate/base/Canvas.h @@ -37,6 +37,7 @@ class DepthRenderTarget; class DepthStencilRenderTarget; class StencilRenderTarget; class BlitStage; +class RenderbufferRenderTargetStage; /** @@ -313,30 +314,62 @@ class GLOPERATE_API Canvas : public cppexpose::Object cppexpose::Variant getSlotStatus(const std::string & path, const std::string & slot); //@} + /** + * @brief + * Detect framebuffer and render stage compatability and determine render targets + * for render stage inputs + * + * @param[in] targetFBO + * The target framebuffer whose attachments are used when compatible + * @param[out] colorRenderTarget + * The resulting color render target for render stage input + * @param[out] depthRenderTarget + * The resulting depth render target for render stage input + * @param[out] stencilRenderTarget + * The resulting stencil render target for render stage input + * @param[out] depthStencilRenderTarget + * The resulting combined depth-stencil render target for render stage input + * + * @remarks + * The output paarameters are filled with usable render targets as render stage input. + * These may be the attachments from the target framebuffer or emulated ones + */ + void determineRenderTargets( + globjects::Framebuffer * targetFBO, + ColorRenderTarget * & colorRenderTarget, + DepthRenderTarget * & depthRenderTarget, + StencilRenderTarget * & stencilRenderTarget, + DepthStencilRenderTarget * & depthStencilRenderTarget + ); protected: - Environment * m_environment; ///< Gloperate environment to which the canvas belongs - AbstractGLContext * m_openGLContext; ///< OpenGL context used for rendering onto the canvas - bool m_initialized; ///< 'true' if the context has been initialized and the viewport has been set, else 'false' - gloperate::ChronoTimer m_clock; ///< Time measurement - glm::vec4 m_viewport; ///< Viewport (in real device coordinates) - float m_timeDelta; ///< Time delta since the last update (in seconds) - std::unique_ptr m_renderStage; ///< Render stage that renders into the canvas - std::unique_ptr m_oldStage; ///< Old render stage, will be destroyed on the next render call - std::unique_ptr m_blitStage; ///< Blit stage that is used to blit to target color attachment if render stage uses own targets - std::unique_ptr m_mouseDevice; ///< Device for Mouse Events - std::unique_ptr m_keyboardDevice; ///< Device for Keyboard Events - bool m_replaceStage; ///< 'true' if the stage has just been replaced, else 'false' - std::mutex m_mutex; ///< Mutex for separating main and render thread - cppexpose::ScopedConnection m_inputChangedConnection; ///< Connection for the inputChanged-signal of the current stage - cppexpose::Function m_inputChangedCallback; ///< Script function that is called on inputChanged (slot, status) - std::vector m_changedInputs; ///< List of changed input slots - std::mutex m_changedInputMutex; ///< Mutex to access m_changedInputs - - std::unique_ptr m_colorTarget; ///< Input render target for color attachment - std::unique_ptr m_depthTarget; ///< Input render target for depth attachment - std::unique_ptr m_depthStencilTarget; ///< Input render target for combined depth stencil attachment - std::unique_ptr m_stencilTarget; ///< Input render target for stencil attachment + Environment * m_environment; ///< Gloperate environment to which the canvas belongs + AbstractGLContext * m_openGLContext; ///< OpenGL context used for rendering onto the canvas + bool m_initialized; ///< 'true' if the context has been initialized and the viewport has been set, else 'false' + gloperate::ChronoTimer m_clock; ///< Time measurement + glm::vec4 m_viewport; ///< Viewport (in real device coordinates) + float m_timeDelta; ///< Time delta since the last update (in seconds) + std::unique_ptr m_renderStage; ///< Render stage that renders into the canvas + std::unique_ptr m_oldStage; ///< Old render stage, will be destroyed on the next render call + std::unique_ptr m_colorRenderTargetStage; ///< Color render target stage for rendertarget emulation + std::unique_ptr m_depthRenderTargetStage; ///< Depth render target stage for rendertarget emulation + std::unique_ptr m_stencilRenderTargetStage; ///< Stencil render target stage for rendertarget emulation + std::unique_ptr m_depthStencilRenderTargetStage; ///< Combined depth stencil render target stage for rendertarget emulation + std::unique_ptr m_blitStage; ///< Blit stage that is used to blit to target color attachment if render stage uses own targets + std::unique_ptr m_mouseDevice; ///< Device for Mouse Events + std::unique_ptr m_keyboardDevice; ///< Device for Keyboard Events + bool m_replaceStage; ///< 'true' if the stage has just been replaced, else 'false' + std::mutex m_mutex; ///< Mutex for separating main and render thread + cppexpose::ScopedConnection m_inputChangedConnection; ///< Connection for the inputChanged-signal of the current stage + cppexpose::Function m_inputChangedCallback; ///< Script function that is called on inputChanged (slot, status) + std::vector m_changedInputs; ///< List of changed input slots + std::mutex m_changedInputMutex; ///< Mutex to access m_changedInputs + + std::unique_ptr m_targetFBOColorTarget; ///< Input target FBO render target for color attachment + std::unique_ptr m_colorTarget; ///< Input render target for color attachment + std::unique_ptr m_depthTarget; ///< Input render target for depth attachment + std::unique_ptr m_depthStencilTarget; ///< Input render target for combined depth stencil attachment + std::unique_ptr m_stencilTarget; ///< Input render target for stencil attachment }; diff --git a/source/gloperate/include/gloperate/rendering/AbstractRenderTarget.h b/source/gloperate/include/gloperate/rendering/AbstractRenderTarget.h index 7257a7ee..21ef1251 100644 --- a/source/gloperate/include/gloperate/rendering/AbstractRenderTarget.h +++ b/source/gloperate/include/gloperate/rendering/AbstractRenderTarget.h @@ -50,6 +50,18 @@ class GLOPERATE_API AbstractRenderTarget */ virtual ~AbstractRenderTarget(); + /** + * @brief + * Checks if this and another AbstractRenderTarget points to the same render underlying framebuffer memory segment + * + * @param[in] other + * The other render target + * + * @return + * 'true' if both render targets points to the same framebuffer attachment, else 'false' + */ + bool matchesAttachment(const AbstractRenderTarget * other) const; + /** * @brief * Release the current target diff --git a/source/gloperate/include/gloperate/stages/base/RenderbufferRenderTargetStage.h b/source/gloperate/include/gloperate/stages/base/RenderbufferRenderTargetStage.h index 577d484b..1a16edd0 100644 --- a/source/gloperate/include/gloperate/stages/base/RenderbufferRenderTargetStage.h +++ b/source/gloperate/include/gloperate/stages/base/RenderbufferRenderTargetStage.h @@ -27,6 +27,7 @@ namespace gloperate class ColorRenderTarget; class DepthRenderTarget; class StencilRenderTarget; +class DepthStencilRenderTarget; /** @@ -53,10 +54,11 @@ class GLOPERATE_API RenderbufferRenderTargetStage : public gloperate::Stage Input size; ///< Viewport size (only z and w component is used as width and height) // Outputs - Output renderbuffer; ///< Renderbuffer - Output colorRenderTarget; ///< Color RenderTarget - Output depthRenderTarget; ///< Depth RenderTarget - Output stencilRenderTarget; ///< Stencil RenderTarget + Output renderbuffer; ///< Renderbuffer + Output colorRenderTarget; ///< Color RenderTarget + Output depthRenderTarget; ///< Depth RenderTarget + Output stencilRenderTarget; ///< Stencil RenderTarget + Output depthStencilRenderTarget; ///< Depth-stencil RenderTarget public: @@ -86,10 +88,11 @@ class GLOPERATE_API RenderbufferRenderTargetStage : public gloperate::Stage protected: - std::unique_ptr m_renderbuffer; ///< The created renderbuffer - std::unique_ptr m_colorRenderTarget; ///< The color render target - std::unique_ptr m_depthRenderTarget; ///< The depth render target - std::unique_ptr m_stencilRenderTarget; ///< The stencil render target + std::unique_ptr m_renderbuffer; ///< The created renderbuffer + std::unique_ptr m_colorRenderTarget; ///< The color render target + std::unique_ptr m_depthRenderTarget; ///< The depth render target + std::unique_ptr m_stencilRenderTarget; ///< The stencil render target + std::unique_ptr m_depthStencilRenderTarget; ///< The depth-stencil render target }; diff --git a/source/gloperate/source/base/Canvas.cpp b/source/gloperate/source/base/Canvas.cpp index d63273b4..00c5a346 100644 --- a/source/gloperate/source/base/Canvas.cpp +++ b/source/gloperate/source/base/Canvas.cpp @@ -28,6 +28,7 @@ #include #include #include +#include using namespace cppassist; @@ -54,10 +55,15 @@ Canvas::Canvas(Environment * environment) , m_openGLContext(nullptr) , m_initialized(false) , m_timeDelta(0.0f) +, m_colorRenderTargetStage(cppassist::make_unique(environment)) +, m_depthRenderTargetStage(cppassist::make_unique(environment)) +, m_stencilRenderTargetStage(cppassist::make_unique(environment)) +, m_depthStencilRenderTargetStage(cppassist::make_unique(environment)) , m_blitStage(cppassist::make_unique(environment, "FinalBlit")) , m_mouseDevice(cppassist::make_unique(m_environment->inputManager(), m_name)) , m_keyboardDevice(cppassist::make_unique(m_environment->inputManager(), m_name)) , m_replaceStage(false) +, m_targetFBOColorTarget(cppassist::make_unique()) , m_colorTarget(cppassist::make_unique()) , m_depthTarget(cppassist::make_unique()) , m_depthStencilTarget(cppassist::make_unique()) @@ -79,6 +85,11 @@ Canvas::Canvas(Environment * environment) // Register canvas m_environment->registerCanvas(this); + + m_colorRenderTargetStage->internalFormat = gl::GL_RGBA8; + m_depthRenderTargetStage->internalFormat = gl::GL_DEPTH_COMPONENT; + m_stencilRenderTargetStage->internalFormat = gl::GL_STENCIL; + m_depthStencilRenderTargetStage->internalFormat = gl::GL_DEPTH24_STENCIL8; } Canvas::~Canvas() @@ -159,6 +170,10 @@ void Canvas::setOpenGLContext(AbstractGLContext * context) } m_blitStage->deinitContext(m_openGLContext); + m_colorRenderTargetStage->deinitContext(m_openGLContext); + m_depthRenderTargetStage->deinitContext(m_openGLContext); + m_stencilRenderTargetStage->deinitContext(m_openGLContext); + m_depthStencilRenderTargetStage->deinitContext(m_openGLContext); m_openGLContext = nullptr; } @@ -176,6 +191,10 @@ void Canvas::setOpenGLContext(AbstractGLContext * context) } m_blitStage->initContext(m_openGLContext); + m_colorRenderTargetStage->initContext(m_openGLContext); + m_depthRenderTargetStage->initContext(m_openGLContext); + m_stencilRenderTargetStage->initContext(m_openGLContext); + m_depthStencilRenderTargetStage->initContext(m_openGLContext); } // Reset status @@ -288,72 +307,34 @@ void Canvas::render(globjects::Framebuffer * targetFBO) m_replaceStage = false; } - // Extract default color and depth buffer from FBO if (targetFBO->isDefault()) { - m_colorTarget->setTarget(gl::GL_BACK_LEFT); - m_depthTarget->setTarget(gl::GL_DEPTH_ATTACHMENT); - m_stencilTarget->setTarget(gl::GL_STENCIL_ATTACHMENT); + m_targetFBOColorTarget->setTarget(gl::GL_BACK_LEFT); } else { - unsigned int i = 0; - globjects::FramebufferAttachment * colorAttachment = nullptr; - while (i < 16 && colorAttachment == nullptr) - { - colorAttachment = targetFBO->getAttachment(gl::GL_COLOR_ATTACHMENT0+i); - } - const auto depthAttachment = targetFBO->getAttachment(gl::GL_DEPTH_ATTACHMENT); - const auto stencilAttachment = targetFBO->getAttachment(gl::GL_STENCIL_ATTACHMENT); - const auto depthStencilAttachment = targetFBO->getAttachment(gl::GL_DEPTH_STENCIL_ATTACHMENT); + m_targetFBOColorTarget->setTarget(targetFBO->getAttachment(gl::GL_COLOR_ATTACHMENT0)); + } - if (colorAttachment) - { - m_colorTarget->setTarget(colorAttachment); - } - else - { - m_colorTarget->releaseTarget(); - } - if (depthAttachment) - { - m_depthTarget->setTarget(depthAttachment); - } - else - { - m_depthTarget->releaseTarget(); - } + ColorRenderTarget * colorRenderTarget = nullptr; + DepthRenderTarget * depthRenderTarget = nullptr; + StencilRenderTarget * stencilRenderTarget = nullptr; + DepthStencilRenderTarget * depthStencilRenderTarget = nullptr; - if (stencilAttachment) - { - m_stencilTarget->setTarget(stencilAttachment); - } - else - { - m_stencilTarget->releaseTarget(); - } - if (depthStencilAttachment) - { - m_depthStencilTarget->setTarget(depthStencilAttachment); - } - else - { - m_depthStencilTarget->releaseTarget(); - } - } + determineRenderTargets(targetFBO, colorRenderTarget, depthRenderTarget, stencilRenderTarget, depthStencilRenderTarget); // Update render stage input render targets - m_renderStage->forAllInputs([this](Input * input) { - input->setValue(m_colorTarget.get()); + m_renderStage->forAllInputs([colorRenderTarget](Input * input) { + input->setValue(colorRenderTarget); }); - m_renderStage->forAllInputs([this](Input * input) { - input->setValue(m_depthTarget.get()); + m_renderStage->forAllInputs([depthRenderTarget](Input * input) { + input->setValue(depthRenderTarget); }); - m_renderStage->forAllInputs([this](Input * input) { - input->setValue(m_depthStencilTarget.get()); + m_renderStage->forAllInputs([depthStencilRenderTarget](Input * input) { + input->setValue(depthStencilRenderTarget); }); - m_renderStage->forAllInputs([this](Input * input) { - input->setValue(m_stencilTarget.get()); + m_renderStage->forAllInputs([stencilRenderTarget](Input * input) { + input->setValue(stencilRenderTarget); }); // Render @@ -365,9 +346,9 @@ void Canvas::render(globjects::Framebuffer * targetFBO) if (colorOutput) { - if (**colorOutput == m_colorTarget.get()) + if ((**colorOutput)->matchesAttachment(m_targetFBOColorTarget.get())) { - + // nothing to blit } else { @@ -377,7 +358,7 @@ void Canvas::render(globjects::Framebuffer * targetFBO) m_blitStage->source = **colorOutput; m_blitStage->sourceViewport = viewport ? **viewport : m_viewport; - m_blitStage->target = m_colorTarget.get(); + m_blitStage->target = m_targetFBOColorTarget.get(); m_blitStage->targetViewport = m_viewport; m_blitStage->process(); } @@ -874,5 +855,206 @@ cppexpose::Variant Canvas::getSlotStatus(const std::string & path, const std::st return status; } +void Canvas::determineRenderTargets( + globjects::Framebuffer * targetFBO, + ColorRenderTarget * & colorRenderTarget, + DepthRenderTarget * & depthRenderTarget, + StencilRenderTarget * & stencilRenderTarget, + DepthStencilRenderTarget * & depthStencilRenderTarget +) +{ + // Check render stage render target requirements + + auto requiresColorRenderTarget = false; + auto requiresDepthRenderTarget = false; + auto requiresStencilRenderTarget = false; + auto requiresDepthStencilRenderTarget = false; + + m_renderStage->forAllInputs([& requiresColorRenderTarget, & requiresDepthRenderTarget, & requiresStencilRenderTarget, & requiresDepthStencilRenderTarget](AbstractSlot * slot) { + requiresColorRenderTarget |= dynamic_cast *>(slot) != nullptr; + requiresDepthRenderTarget |= dynamic_cast *>(slot) != nullptr; + requiresStencilRenderTarget |= dynamic_cast *>(slot) != nullptr; + requiresDepthStencilRenderTarget |= dynamic_cast *>(slot) != nullptr; + }); + + if (requiresDepthStencilRenderTarget && (requiresDepthRenderTarget || requiresStencilRenderTarget)) + { + cppassist::warning("gloperate") << "Render stage requests both combined and separate render targets; only combined is assigned"; + requiresDepthRenderTarget = false; + requiresStencilRenderTarget = false; + } + + // Extract default color and depth buffer from FBO + if (targetFBO->isDefault()) + { + if (requiresDepthRenderTarget || requiresStencilRenderTarget || requiresDepthStencilRenderTarget) + { + // Emulate default FBO with additional attachments + m_colorTarget->releaseTarget(); + m_depthTarget->releaseTarget(); + m_stencilTarget->releaseTarget(); + m_depthStencilTarget->releaseTarget(); + + m_colorRenderTargetStage->size = m_viewport; + m_colorRenderTargetStage->process(); + colorRenderTarget = *m_colorRenderTargetStage->colorRenderTarget; + + if (requiresDepthRenderTarget) + { + m_depthRenderTargetStage->size = m_viewport; + m_depthRenderTargetStage->process(); + depthRenderTarget = *m_depthRenderTargetStage->depthRenderTarget; + } + else + { + depthRenderTarget = nullptr; + } + + if (requiresStencilRenderTarget) + { + m_stencilRenderTargetStage->size = m_viewport; + m_stencilRenderTargetStage->process(); + stencilRenderTarget = *m_stencilRenderTargetStage->stencilRenderTarget; + } + else + { + stencilRenderTarget = nullptr; + } + + if (requiresDepthStencilRenderTarget) + { + m_depthStencilRenderTargetStage->size = m_viewport; + m_depthStencilRenderTargetStage->process(); + depthStencilRenderTarget = *m_depthStencilRenderTargetStage->depthStencilRenderTarget; + } + else + { + depthStencilRenderTarget = nullptr; + } + } + else + { + // Default FBO can be used + m_colorTarget->setTarget(gl::GL_BACK_LEFT); + m_depthTarget->releaseTarget(); + m_stencilTarget->releaseTarget(); + m_depthStencilTarget->releaseTarget(); + + colorRenderTarget = m_colorTarget.get(); + depthRenderTarget = nullptr; + stencilRenderTarget = nullptr; + depthStencilRenderTarget = nullptr; + } + } + else + { + unsigned int i = 0; + globjects::FramebufferAttachment * colorAttachment = nullptr; + + while (i < 16 && colorAttachment == nullptr) + { + colorAttachment = targetFBO->getAttachment(gl::GL_COLOR_ATTACHMENT0+i); + } + + const auto depthAttachment = targetFBO->getAttachment(gl::GL_DEPTH_ATTACHMENT); + const auto stencilAttachment = targetFBO->getAttachment(gl::GL_STENCIL_ATTACHMENT); + const auto depthStencilAttachment = targetFBO->getAttachment(gl::GL_DEPTH_STENCIL_ATTACHMENT); + + if (requiresColorRenderTarget) + { + if (colorAttachment) + { + m_colorTarget->setTarget(colorAttachment); + colorRenderTarget = m_colorTarget.get(); + } + else + { + cppassist::warning("gloperate") << "Target FBO doesn't have a color attachment"; + + // Emulate color attachment + m_colorTarget->releaseTarget(); + + m_colorRenderTargetStage->size = m_viewport; + m_colorRenderTargetStage->process(); + colorRenderTarget = *m_colorRenderTargetStage->colorRenderTarget; + } + } + else + { + m_colorTarget->releaseTarget(); + colorRenderTarget = nullptr; + } + + if (requiresDepthRenderTarget) + { + if (depthAttachment) + { + m_depthTarget->setTarget(depthAttachment); + depthRenderTarget = m_depthTarget.get(); + } + else + { + // Emulate depth attachment + m_depthTarget->releaseTarget(); + + m_depthRenderTargetStage->size = m_viewport; + m_depthRenderTargetStage->process(); + depthRenderTarget = *m_depthRenderTargetStage->depthRenderTarget; + } + } + else + { + m_depthTarget->releaseTarget(); + depthRenderTarget = nullptr; + } + + if (requiresStencilRenderTarget) + { + if (stencilAttachment) + { + m_stencilTarget->setTarget(stencilAttachment); + stencilRenderTarget = m_stencilTarget.get(); + } + else + { + // Emulate stencil attachment + m_stencilTarget->releaseTarget(); + + m_stencilRenderTargetStage->size = m_viewport; + m_stencilRenderTargetStage->process(); + stencilRenderTarget = *m_stencilRenderTargetStage->stencilRenderTarget; + } + } + else + { + m_stencilTarget->releaseTarget(); + stencilRenderTarget = nullptr; + } + + if (requiresDepthStencilRenderTarget) + { + if (depthStencilAttachment) + { + m_depthStencilTarget->setTarget(depthStencilAttachment); + depthStencilRenderTarget = m_depthStencilTarget.get(); + } + else + { + // Emulate depth-stencil attachment + m_depthStencilTarget->releaseTarget(); + + m_depthStencilRenderTargetStage->size = m_viewport; + m_depthStencilRenderTargetStage->process(); + depthStencilRenderTarget = *m_depthStencilRenderTargetStage->depthStencilRenderTarget; + } + } + else + { + m_depthStencilTarget->releaseTarget(); + depthStencilRenderTarget = nullptr; + } + } +} + } // namespace gloperate diff --git a/source/gloperate/source/rendering/AbstractRenderTarget.cpp b/source/gloperate/source/rendering/AbstractRenderTarget.cpp index 25b3d30b..20981abc 100644 --- a/source/gloperate/source/rendering/AbstractRenderTarget.cpp +++ b/source/gloperate/source/rendering/AbstractRenderTarget.cpp @@ -6,6 +6,8 @@ #include #include +#include +#include #include #include @@ -27,6 +29,118 @@ AbstractRenderTarget::~AbstractRenderTarget() { } +bool AbstractRenderTarget::matchesAttachment(const AbstractRenderTarget * other) const +{ + if (this == other) + { + return true; + } + + if (currentTargetType() == other->currentTargetType()) + { + switch (currentTargetType()) + { + case RenderTargetType::Texture: + if (textureAttachment() == nullptr || other->textureAttachment() == nullptr) + { + return false; + } + + return textureAttachment()->id() == other->textureAttachment()->id(); + case RenderTargetType::Renderbuffer: + if (renderbufferAttachment() == nullptr || other->renderbufferAttachment() == nullptr) + { + return false; + } + + return renderbufferAttachment()->id() == other->renderbufferAttachment()->id(); + case RenderTargetType::DefaultFBOAttachment: + return defaultFramebufferAttachment() == other->defaultFramebufferAttachment(); + case RenderTargetType::UserDefinedFBOAttachment: + if (framebufferAttachment() == nullptr || other->framebufferAttachment() == nullptr) + { + return false; + } + + if (framebufferAttachment() == other->framebufferAttachment()) + { + return true; + } + + if (framebufferAttachment()->isTextureAttachment() && other->framebufferAttachment()->isTextureAttachment()) + { + return framebufferAttachment()->asTextureAttachment()->texture()->id() == + other->framebufferAttachment()->asTextureAttachment()->texture()->id(); + } + else if (framebufferAttachment()->isRenderBufferAttachment() && other->framebufferAttachment()->isRenderBufferAttachment()) + { + return framebufferAttachment()->asRenderBufferAttachment()->renderBuffer()->id() == + other->framebufferAttachment()->asRenderBufferAttachment()->renderBuffer()->id(); + } + else + { + return false; + } + case RenderTargetType::Invalid: + default: + return false; + } + } + else if (currentTargetType() == RenderTargetType::DefaultFBOAttachment || other->currentTargetType() == RenderTargetType::DefaultFBOAttachment) + { + return false; + } + else if ((currentTargetType() == RenderTargetType::Texture || currentTargetType() == RenderTargetType::Renderbuffer) && + (other->currentTargetType() == RenderTargetType::Texture || other->currentTargetType() == RenderTargetType::Renderbuffer)) + { + return false; + } + else if (currentTargetType() == RenderTargetType::UserDefinedFBOAttachment) + { + if (other->currentTargetType() == RenderTargetType::Texture) + { + return framebufferAttachment()->isTextureAttachment() + && framebufferAttachment()->asTextureAttachment()->texture()->id() == other->textureAttachment()->id(); + } + else if (other->currentTargetType() == RenderTargetType::Renderbuffer) + { + return framebufferAttachment()->isRenderBufferAttachment() + && framebufferAttachment()->asRenderBufferAttachment()->renderBuffer()->id() == other->renderbufferAttachment()->id(); + } + else + { + assert(false); + + return false; + } + } + else if (other->currentTargetType() == RenderTargetType::UserDefinedFBOAttachment) + { + if (currentTargetType() == RenderTargetType::Texture) + { + return other->framebufferAttachment()->isTextureAttachment() + && other->framebufferAttachment()->asTextureAttachment()->texture()->id() == textureAttachment()->id(); + } + else if (currentTargetType() == RenderTargetType::Renderbuffer) + { + return other->framebufferAttachment()->isRenderBufferAttachment() + && other->framebufferAttachment()->asRenderBufferAttachment()->renderBuffer()->id() == renderbufferAttachment()->id(); + } + else + { + assert(false); + + return false; + } + } + else + { + assert(false); + + return false; + } +} + void AbstractRenderTarget::releaseTarget() { switch (m_currentTargetType) diff --git a/source/gloperate/source/stages/base/RenderbufferRenderTargetStage.cpp b/source/gloperate/source/stages/base/RenderbufferRenderTargetStage.cpp index 2780312a..917e2ca3 100644 --- a/source/gloperate/source/stages/base/RenderbufferRenderTargetStage.cpp +++ b/source/gloperate/source/stages/base/RenderbufferRenderTargetStage.cpp @@ -11,6 +11,7 @@ #include #include #include +#include using namespace gl; @@ -32,6 +33,7 @@ RenderbufferRenderTargetStage::RenderbufferRenderTargetStage(gloperate::Environm , colorRenderTarget("colorRenderTarget", this) , depthRenderTarget("depthRenderTarget", this) , stencilRenderTarget("stencilRenderTarget", this) +, depthStencilRenderTarget("depthStencilRenderTarget", this) { } @@ -45,18 +47,20 @@ void RenderbufferRenderTargetStage::onContextInit(gloperate::AbstractGLContext * m_renderbuffer = cppassist::make_unique(); // Create wrapping render target - m_colorRenderTarget = cppassist::make_unique(); - m_depthRenderTarget = cppassist::make_unique(); - m_stencilRenderTarget = cppassist::make_unique(); + m_colorRenderTarget = cppassist::make_unique(); + m_depthRenderTarget = cppassist::make_unique(); + m_stencilRenderTarget = cppassist::make_unique(); + m_depthStencilRenderTarget = cppassist::make_unique(); } void RenderbufferRenderTargetStage::onContextDeinit(AbstractGLContext *) { // Clean up OpenGL objects - m_renderbuffer = nullptr; - m_colorRenderTarget = nullptr; - m_depthRenderTarget = nullptr; - m_stencilRenderTarget = nullptr; + m_renderbuffer = nullptr; + m_colorRenderTarget = nullptr; + m_depthRenderTarget = nullptr; + m_stencilRenderTarget = nullptr; + m_depthStencilRenderTarget = nullptr; } void RenderbufferRenderTargetStage::onProcess() @@ -72,29 +76,28 @@ void RenderbufferRenderTargetStage::onProcess() const auto height = (*size)[3]; m_renderbuffer->storage(*internalFormat, width, height); + + m_colorRenderTarget->releaseTarget(); + m_depthRenderTarget->releaseTarget(); + m_stencilRenderTarget->releaseTarget(); + m_depthStencilRenderTarget->releaseTarget(); + switch(*internalFormat) { case GL_DEPTH_COMPONENT: case GL_DEPTH_COMPONENT16: case GL_DEPTH_COMPONENT24: case GL_DEPTH_COMPONENT32F: - m_colorRenderTarget->releaseTarget(); - m_stencilRenderTarget->releaseTarget(); - m_depthRenderTarget->setTarget(m_renderbuffer.get()); break; case GL_DEPTH_STENCIL: case GL_DEPTH24_STENCIL8: case GL_DEPTH32F_STENCIL8: - m_colorRenderTarget->releaseTarget(); - - m_depthRenderTarget->setTarget(m_renderbuffer.get()); - m_stencilRenderTarget->setTarget(m_renderbuffer.get()); + m_depthStencilRenderTarget->setTarget(m_renderbuffer.get()); break; + case GL_STENCIL: + m_stencilRenderTarget->setTarget(m_renderbuffer.get()); default: // Color attachment - m_depthRenderTarget->releaseTarget(); - m_stencilRenderTarget->releaseTarget(); - m_colorRenderTarget->setTarget(m_renderbuffer.get()); break; } diff --git a/source/gloperate/source/stages/interfaces/RenderInterface.cpp b/source/gloperate/source/stages/interfaces/RenderInterface.cpp index 2a2f5295..843dfff1 100644 --- a/source/gloperate/source/stages/interfaces/RenderInterface.cpp +++ b/source/gloperate/source/stages/interfaces/RenderInterface.cpp @@ -598,7 +598,7 @@ globjects::Framebuffer * RenderInterface::obtainFBO(size_t index, AbstractRender const auto attachment = fbo->getAttachment(attachmentIndex); const auto attachedRenderbuffer = static_cast(attachment); - if (!attachment->isRenderBufferAttachment() || attachedRenderbuffer->renderBuffer() != renderTarget->renderbufferAttachment()) + if (!attachment || !attachment->isRenderBufferAttachment() || attachedRenderbuffer->renderBuffer() != renderTarget->renderbufferAttachment()) { fbo->attachRenderBuffer(attachmentIndex, renderTarget->renderbufferAttachment()); }