From: adam.b Date: Thu, 1 Apr 2021 12:44:13 +0000 (+0100) Subject: Added RenderPass and RenderTarget support X-Git-Tag: dali_2.0.28~25 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e55a2190173c771eca34729d740ef38f3876063a;p=platform%2Fcore%2Fuifw%2Fdali-core.git Added RenderPass and RenderTarget support Change-Id: I324b4f47c389fbef6c6b18f91acee2948cd5fa48 --- diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-graphics-command-buffer.h b/automated-tests/src/dali/dali-test-suite-utils/test-graphics-command-buffer.h index c10c3f1..4f8a184 100644 --- a/automated-tests/src/dali/dali-test-suite-utils/test-graphics-command-buffer.h +++ b/automated-tests/src/dali/dali-test-suite-utils/test-graphics-command-buffer.h @@ -509,8 +509,8 @@ public: } void BeginRenderPass( - Graphics::RenderPass& renderPass, - Graphics::RenderTarget& renderTarget, + Graphics::RenderPass* renderPass, + Graphics::RenderTarget* renderTarget, Graphics::Extent2D renderArea, std::vector clearValues) override { @@ -531,6 +531,11 @@ public: mCallStack.PushCall("EndRenderPass", ""); } + void ExecuteCommandBuffers(std::vector&& commandBuffers) override + { + mCallStack.PushCall("ExecuteCommandBuffers", ""); + } + void Draw( uint32_t vertexCount, uint32_t instanceCount, diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-graphics-pipeline.cpp b/automated-tests/src/dali/dali-test-suite-utils/test-graphics-pipeline.cpp index 83d535c..9e80f8f 100644 --- a/automated-tests/src/dali/dali-test-suite-utils/test-graphics-pipeline.cpp +++ b/automated-tests/src/dali/dali-test-suite-utils/test-graphics-pipeline.cpp @@ -32,9 +32,6 @@ TestGraphicsPipeline::TestGraphicsPipeline(TestGlAbstraction& gl, const Graphics if(createInfo.viewportState) viewportState = *createInfo.viewportState; - if(createInfo.framebufferState) - framebufferState = *createInfo.framebufferState; - if(createInfo.depthStencilState) depthStencilState = *createInfo.depthStencilState; diff --git a/dali/graphics-api/graphics-command-buffer.h b/dali/graphics-api/graphics-command-buffer.h index 0b81870..7056e47 100644 --- a/dali/graphics-api/graphics-command-buffer.h +++ b/dali/graphics-api/graphics-command-buffer.h @@ -21,9 +21,7 @@ // INTERNAL INCLUDES #include "graphics-types.h" -namespace Dali -{ -namespace Graphics +namespace Dali::Graphics { class Buffer; class Pipeline; @@ -179,13 +177,14 @@ public: * Calling EndRenderPass() is necessary to finalize the render pass. * * @param[in] renderPass valid render pass object - * @param[in] renderTarget valid render target + * @param[in] renderTarget valid render target, must not be used when framebuffer set + * @param[in] framebuffer valid framebuffer, must not be used with renderTarget * @param[in] renderArea area to draw * @param[in] clearValues clear values (compatible with renderpass spec) */ virtual void BeginRenderPass( - RenderPass& renderPass, - RenderTarget& renderTarget, + RenderPass* renderPass, + RenderTarget* renderTarget, Extent2D renderArea, std::vector clearValues) = 0; @@ -201,6 +200,13 @@ public: virtual void EndRenderPass() = 0; /** + * @brief Executes a list of secondary command buffers + * + * @param[in] commandBuffers List of buffers to execute + */ + virtual void ExecuteCommandBuffers( std::vector&& commandBuffers ) = 0; + + /** * @brief Draw primitives * * @param[in] vertexCount number of vertices @@ -296,7 +302,6 @@ protected: CommandBuffer(CommandBuffer&&) = default; CommandBuffer& operator=(CommandBuffer&&) = default; }; -} // Namespace Graphics } // Namespace Dali #endif diff --git a/dali/graphics-api/graphics-pipeline-create-info.h b/dali/graphics-api/graphics-pipeline-create-info.h index d4b4014..0ddcbd7 100644 --- a/dali/graphics-api/graphics-pipeline-create-info.h +++ b/dali/graphics-api/graphics-pipeline-create-info.h @@ -93,18 +93,6 @@ struct PipelineCreateInfo } /** - * @brief Sets the framebuffer state. - * - * @param[in] value pointer to valid framebuffer state structure - * @return reference to this structure - */ - auto& SetFramebufferState(FramebufferState* value) - { - framebufferState = value; - return *this; - } - - /** * @brief Sets the base pipeline. * * Setting base pipeline allows inheriting that pipeline state @@ -208,7 +196,6 @@ struct PipelineCreateInfo ProgramState* programState{nullptr}; ColorBlendState* colorBlendState{nullptr}; ViewportState* viewportState{nullptr}; - FramebufferState* framebufferState{nullptr}; Pipeline* basePipeline{nullptr}; DepthStencilState* depthStencilState{nullptr}; RasterizationState* rasterizationState{nullptr}; diff --git a/dali/graphics-api/graphics-render-pass-create-info.h b/dali/graphics-api/graphics-render-pass-create-info.h index 22152e3..04cd95f 100644 --- a/dali/graphics-api/graphics-render-pass-create-info.h +++ b/dali/graphics-api/graphics-render-pass-create-info.h @@ -18,16 +18,11 @@ * */ -// EXTERNAL INCLUDES -#include - // INTERNAL INCLUDES #include "graphics-render-pass.h" #include "graphics-types.h" -namespace Dali -{ -namespace Graphics +namespace Dali::Graphics { class RenderTarget; /** @@ -55,14 +50,14 @@ struct RenderPassCreateInfo } /** - * @brief Binds render target to render pass + * @brief Sets array of attachment descriptions * - * @param[in] value valid RenderTarget object + * @param[in] value pointer valid array of attachment descriptions * @return reference to this structure */ - auto& SetRenderTarget(RenderTarget* value) + auto& SetAttachments(const std::vector& value) { - renderTarget = value; + attachments = &value; return *this; } @@ -81,12 +76,10 @@ struct RenderPassCreateInfo GraphicsStructureType type{GraphicsStructureType::RENDERPASS_CREATE_INFO_STRUCT}; ExtensionCreateInfo* nextExtension{nullptr}; - RenderTarget* renderTarget{nullptr}; - + const std::vector* attachments{nullptr}; const AllocationCallbacks* allocationCallbacks{nullptr}; }; -} // namespace Graphics } // namespace Dali #endif // DALI_GRAPHICS_FRAMEBUFFER_FACTORY_H \ No newline at end of file diff --git a/dali/graphics-api/graphics-render-target-create-info.h b/dali/graphics-api/graphics-render-target-create-info.h index 8ec8664..9cb92c3 100644 --- a/dali/graphics-api/graphics-render-target-create-info.h +++ b/dali/graphics-api/graphics-render-target-create-info.h @@ -54,6 +54,58 @@ struct RenderTargetCreateInfo } /** + * @brief Sets surface associated with the RenderTarget + * + * The surface is a a pointer to any native surface object. + * + * @param[in] value Pointer to the native surface + * @return reference to this structure + */ + auto& SetSurface( Surface* value ) + { + surface = value; + return *this; + } + + /** + * @brief Sets framebuffer associated with the RenderTarget + * + * The framebuffer and surface must not be set together. + * + * @param[in] value Pointer to the Framebuffer object + * @return reference to this structure + */ + auto& SetFramebuffer( Framebuffer* value ) + { + framebuffer = value; + return *this; + } + + /** + * @brief Sets render target size + * + * @param[in] value Size of render target + * @return reference to this structure + */ + auto& SetExtent( Extent2D value ) + { + extent = value; + return *this; + } + + /** + * @brief Sets pre-transform of the render target + * + * @param[in] value transform flags + * @return reference to this structure + */ + auto& SetPreTransform( RenderTargetTransformFlags value ) + { + preTransform = value; + return *this; + } + + /** * @brief Sets allocation callbacks which will be used when object is created * and destroyed. * @@ -66,8 +118,12 @@ struct RenderTargetCreateInfo return *this; } - GraphicsStructureType type{GraphicsStructureType::RENDER_TARGET_CREATE_INFO_STRUCT}; - ExtensionCreateInfo* nextExtension{nullptr}; + GraphicsStructureType type{GraphicsStructureType::RENDER_TARGET_CREATE_INFO_STRUCT}; + Surface* surface{nullptr}; + Framebuffer* framebuffer{nullptr}; + Extent2D extent{}; + RenderTargetTransformFlags preTransform{0u}; + ExtensionCreateInfo* nextExtension{nullptr}; const AllocationCallbacks* allocationCallbacks{nullptr}; }; diff --git a/dali/graphics-api/graphics-render-target.h b/dali/graphics-api/graphics-render-target.h index fe291ad..a320119 100644 --- a/dali/graphics-api/graphics-render-target.h +++ b/dali/graphics-api/graphics-render-target.h @@ -20,10 +20,9 @@ #include "graphics-types.h" -namespace Dali -{ -namespace Graphics +namespace Dali::Graphics { +class Framebuffer; /** * @brief RenderTarget object binds to any presentable graphics output. */ @@ -42,7 +41,6 @@ protected: RenderTarget& operator=(RenderTarget&&) = default; }; -} // Namespace Graphics } // Namespace Dali #endif \ No newline at end of file diff --git a/dali/graphics-api/graphics-types.h b/dali/graphics-api/graphics-types.h index 1cffb5b..f32bffb 100644 --- a/dali/graphics-api/graphics-types.h +++ b/dali/graphics-api/graphics-types.h @@ -1302,6 +1302,96 @@ enum class GraphicsStructureType : uint32_t }; /** + * @brief Enum describes load operation associated + * with particular framebuffer attachment + */ +enum class AttachmentLoadOp +{ + LOAD, ///< Load previous content + CLEAR, ///< Clear the attachment + DONT_CARE ///< Let driver decide +}; + +/** + * @brief Enum describes store operation associated + * with particular framebuffer attachment + */ +enum class AttachmentStoreOp +{ + STORE, ///< Store content (color attachemnts) + DONT_CARE ///< Let driver decide (depth/stencil attachemnt with no intention of reading) +}; + +/** + * @brief The structure describes the read/write + * modes of a single framebuffer attachment + * + * The attachment description specifies what is going to + * happen to the attachment at the beginning and end of the + * render pass. + * + * The stencil operation is separated as it may be set + * independent from the depth component (use loadOp, storeOp + * to set up the depth component and stencilLoadOp, stencilStoreOp + * for stencil component). + */ +struct AttachmentDescription +{ + /** + * @brief Sets load operation for the attachment + * + * @param value Load operation + * @return this structure + */ + auto& SetLoadOp( AttachmentLoadOp value ) + { + loadOp = value; + return *this; + } + + /** + * @brief Sets store operation for the attachment + * + * @param value Store operation + * @return this structure + */ + auto& SetStoreOp( AttachmentStoreOp value ) + { + storeOp = value; + return *this; + } + + /** + * @brief Sets load operation for the stencil part of attachment + * + * @param value load operation + * @return this structure + */ + auto& SetStencilLoadOp( AttachmentLoadOp value ) + { + stencilLoadOp = value; + return *this; + } + + /** + * @brief Sets store operation for the stencil part of attachment + * + * @param value store operation + * @return this structure + */ + auto& SetStencilStoreOp( AttachmentStoreOp value ) + { + stencilStoreOp = value; + return *this; + } + + AttachmentLoadOp loadOp{}; + AttachmentStoreOp storeOp{}; + AttachmentLoadOp stencilLoadOp{}; + AttachmentStoreOp stencilStoreOp{}; +}; + +/** * @brief Helper function to be used by the extension developers * * The value of custom type must be unique and recognizable by the @@ -1396,6 +1486,34 @@ struct DefaultDeleter }; /** + * Surface type is just a void* to any native object. + */ +using Surface = void; + +/** + * @brief Enum describing preTransform of render target + */ +enum class RenderTargetTransformFlagBits +{ + TRANSFORM_IDENTITY_BIT = 0x00000001, + ROTATE_90_BIT = 0x00000002, + ROTATE_180_BIT = 0x00000004, + ROTATE_270_BIT = 0x00000008, + HORIZONTAL_MIRROR_BIT = 0x00000010, + HORIZONTAL_MIRROR_ROTATE_90_BIT = 0x00000020, + HORIZONTAL_MIRROR_ROTATE_180_BIT = 0x00000040, + HORIZONTAL_MIRROR_ROTATE_270_BIT = 0x00000080, +}; + +using RenderTargetTransformFlags = uint32_t; + +template +inline RenderTargetTransformFlags operator|(T flags, RenderTargetTransformFlagBits bit) +{ + return static_cast(flags) | static_cast(bit); +} + +/** * unique_ptr defined in the Graphics scope */ template> diff --git a/dali/internal/render/common/render-algorithms.cpp b/dali/internal/render/common/render-algorithms.cpp index 5aa3c14..7ab6f37 100644 --- a/dali/internal/render/common/render-algorithms.cpp +++ b/dali/internal/render/common/render-algorithms.cpp @@ -473,18 +473,6 @@ inline void RenderAlgorithms::ProcessRenderList(const RenderList& bool usedStencilBuffer(false); bool firstDepthBufferUse(true); - if(!mGraphicsCommandBuffer) - { - mGraphicsCommandBuffer = mGraphicsController.CreateCommandBuffer( - Graphics::CommandBufferCreateInfo() - .SetLevel(Graphics::CommandBufferLevel::SECONDARY), - nullptr); - } - else - { - mGraphicsCommandBuffer->Reset(); - } - mViewportRectangle = viewport; mGraphicsCommandBuffer->SetViewport(ViewportFromClippingBox(mViewportRectangle, orientation)); mHasLayerScissor = false; @@ -519,10 +507,11 @@ inline void RenderAlgorithms::ProcessRenderList(const RenderList& } // Submit scissor/viewport - Graphics::SubmitInfo submitInfo{{}, 0 | Graphics::SubmitFlagBits::FLUSH}; - submitInfo.cmdBuffer.push_back(mGraphicsCommandBuffer.get()); - mGraphicsController.SubmitCommandBuffers(submitInfo); + //Graphics::SubmitInfo submitInfo{{}, 0 | Graphics::SubmitFlagBits::FLUSH}; + //submitInfo.cmdBuffer.push_back(mGraphicsCommandBuffer.get()); + //mGraphicsController.SubmitCommandBuffers(submitInfo); + mGraphicsRenderItemCommandBuffers.clear(); // Loop through all RenderList in the RenderList, set up any prerequisites to render them, then perform the render. for(uint32_t index = 0u; index < count; ++index) { @@ -550,6 +539,8 @@ inline void RenderAlgorithms::ProcessRenderList(const RenderList& // The Renderer API will be used if specified. If AUTO, the Actors automatic clipping feature will be used. SetupClipping(item, context, usedStencilBuffer, lastClippingDepth, lastClippingId, stencilBufferAvailable, instruction); + + if(DALI_LIKELY(item.mRenderer)) { // Set up the depth buffer based on per-renderer flags if depth buffer is available @@ -572,12 +563,21 @@ inline void RenderAlgorithms::ProcessRenderList(const RenderList& auto const MAX_QUEUE = item.mRenderer->GetDrawCommands().empty() ? 1 : DevelRenderer::RENDER_QUEUE_MAX; for(auto queue = 0u; queue < MAX_QUEUE; ++queue) { - // Render the item. - item.mRenderer->Render(context, bufferIndex, *item.mNode, item.mModelMatrix, item.mModelViewMatrix, viewMatrix, projectionMatrix, item.mSize, !item.mIsOpaque, boundTextures, instruction, queue); + // Render the item. If rendered, add its command buffer into the list + if( item.mRenderer->Render(context, bufferIndex, *item.mNode, item.mModelMatrix, item.mModelViewMatrix, viewMatrix, projectionMatrix, item.mSize, !item.mIsOpaque, boundTextures, instruction, queue) ) + { + mGraphicsRenderItemCommandBuffers.emplace_back( item.mRenderer->GetGraphicsCommandBuffer() ); + } } } } } + + // Execute command buffers + if(!mGraphicsRenderItemCommandBuffers.empty()) + { + mGraphicsCommandBuffer->ExecuteCommandBuffers( std::move(mGraphicsRenderItemCommandBuffers) ); + } } RenderAlgorithms::RenderAlgorithms(Graphics::Controller& graphicsController) @@ -587,6 +587,34 @@ RenderAlgorithms::RenderAlgorithms(Graphics::Controller& graphicsController) { } +void RenderAlgorithms::ResetCommandBuffer() +{ + // Reset main command buffer + if(!mGraphicsCommandBuffer) + { + mGraphicsCommandBuffer = mGraphicsController.CreateCommandBuffer( + Graphics::CommandBufferCreateInfo() + .SetLevel(Graphics::CommandBufferLevel::SECONDARY), + nullptr); + } + else + { + mGraphicsCommandBuffer->Reset(); + } + + // Reset list of secondary buffers to submit + mGraphicsRenderItemCommandBuffers.clear(); +} + +void RenderAlgorithms::SubmitCommandBuffer() +{ + // Submit main command buffer + Graphics::SubmitInfo submitInfo; + submitInfo.cmdBuffer.push_back( mGraphicsCommandBuffer.get() ); + submitInfo.flags = 0 | Graphics::SubmitFlagBits::FLUSH; + mGraphicsController.SubmitCommandBuffers( submitInfo ); +} + void RenderAlgorithms::ProcessRenderInstruction(const RenderInstruction& instruction, Context& context, BufferIndex bufferIndex, diff --git a/dali/internal/render/common/render-algorithms.h b/dali/internal/render/common/render-algorithms.h index d887a74..c7f6994 100644 --- a/dali/internal/render/common/render-algorithms.h +++ b/dali/internal/render/common/render-algorithms.h @@ -72,6 +72,21 @@ public: const Rect& rootClippingRect, int orientation); + /** + * Resets main command buffer (per scene) + */ + void ResetCommandBuffer(); + + /** + * Submits main command buffer (per scene) + */ + void SubmitCommandBuffer(); + + [[nodiscard]] Graphics::CommandBuffer* GetMainCommandBuffer() const + { + return mGraphicsCommandBuffer.get(); + } + private: /** * @brief Calculate a 2D AABB (axis aligned bounding box) in screen space. @@ -151,6 +166,8 @@ private: Graphics::Controller& mGraphicsController; Graphics::UniquePtr mGraphicsCommandBuffer{}; + std::vector mGraphicsRenderItemCommandBuffers{}; + ScissorStackType mScissorStack; ///< Contains the currently applied scissor hierarchy (so we can undo clips) Dali::ClippingBox mViewportRectangle; ///< The viewport dimensions, used to translate AABBs to scissor coordinates bool mHasLayerScissor : 1; ///< Marks if the currently process render instruction has a layer-based clipping region diff --git a/dali/internal/render/common/render-manager.cpp b/dali/internal/render/common/render-manager.cpp index 3ff05d9..2bab722 100644 --- a/dali/internal/render/common/render-manager.cpp +++ b/dali/internal/render/common/render-manager.cpp @@ -87,6 +87,10 @@ struct RenderManager::Impl threadPool->Initialize(1u); uniformBufferManager.reset(new Render::UniformBufferManager(&graphicsController)); + + // initialize main command buffer + auto info = Graphics::CommandBufferCreateInfo().SetLevel( Graphics::CommandBufferLevel::PRIMARY ); + mainCommandBuffer = graphicsController.CreateCommandBuffer( info, nullptr ); } ~Impl() @@ -178,6 +182,12 @@ struct RenderManager::Impl std::unique_ptr threadPool; ///< The thread pool Vector boundTextures; ///< The textures bound for rendering Vector textureDependencyList; ///< The dependency list of binded textures + + Graphics::UniquePtr mainCommandBuffer; ///< Main command buffer + + Graphics::UniquePtr mainRenderPass; ///< Main renderpass + + }; RenderManager* RenderManager::New(Graphics::Controller& graphicsController, @@ -489,6 +499,9 @@ void RenderManager::PreRender(Integration::RenderStatus& status, bool forceClear const bool haveInstructions = count > 0u; + // Reset main command buffer + mImpl->mainCommandBuffer->Reset(); + DALI_LOG_INFO(gLogFilter, Debug::General, "Render: haveInstructions(%s) || mImpl->lastFrameWasRendered(%s) || forceClear(%s)\n", haveInstructions ? "true" : "false", mImpl->lastFrameWasRendered ? "true" : "false", forceClear ? "true" : "false"); // Only render if we have instructions to render, or the last frame was rendered (and therefore a clear is required). @@ -787,6 +800,11 @@ void RenderManager::RenderScene(Integration::RenderStatus& status, Integration:: void RenderManager::RenderScene(Integration::RenderStatus& status, Integration::Scene& scene, bool renderToFbo, Rect& clippingRect) { + // Reset main algorithms command buffer + mImpl->renderAlgorithms.ResetCommandBuffer(); + + auto mainCommandBuffer = mImpl->renderAlgorithms.GetMainCommandBuffer(); + Internal::Scene& sceneInternal = GetImplementation(scene); SceneGraph::Scene* sceneObject = sceneInternal.GetSceneObject(); @@ -824,7 +842,27 @@ void RenderManager::RenderScene(Integration::RenderStatus& status, Integration:: if(instruction.mFrameBuffer) { + auto& clearValues = instruction.mFrameBuffer->GetGraphicsRenderPassClearValues(); + // todo: use no-clear renderpass instead (not implemented yet) + + // Set the clear color for first color attachment + if( instruction.mIsClearColorSet ) + { + clearValues[0].color = { + instruction.mClearColor.r, + instruction.mClearColor.g, + instruction.mClearColor.b, + instruction.mClearColor.a + }; + } // offscreen buffer + mainCommandBuffer->BeginRenderPass( + instruction.mFrameBuffer->GetGraphicsRenderPass( Graphics::AttachmentLoadOp::CLEAR, Graphics::AttachmentStoreOp::STORE ), + instruction.mFrameBuffer->GetGraphicsRenderTarget(), + { instruction.mFrameBuffer->GetWidth(), instruction.mFrameBuffer->GetHeight() }, + clearValues + ); + if(mImpl->currentContext != &mImpl->context) { // Switch to shared context for off-screen buffer @@ -863,6 +901,7 @@ void RenderManager::RenderScene(Integration::RenderStatus& status, Integration:: if(instruction.mFrameBuffer) { + //instruction.mFrameBuffer->Bind(*mImpl->currentContext); // @todo Temporarily set per renderer per pipeline. Should use RenderPass instead @@ -878,12 +917,19 @@ void RenderManager::RenderScene(Integration::RenderStatus& status, Integration:: } // @todo Should this be a command in it's own right? + // @todo yes if(!instruction.mFrameBuffer) { mImpl->currentContext->Viewport(surfaceRect.x, surfaceRect.y, surfaceRect.width, surfaceRect.height); + /* + mainCommandBuffer->SetViewport( {surfaceRect.x, + surfaceRect.y, + surfaceRect.width, + surfaceRect.height} ); + */ } // Clear the entire color, depth and stencil buffers for the default framebuffer, if required. @@ -1080,6 +1126,10 @@ void RenderManager::RenderScene(Integration::RenderStatus& status, Integration:: { mImpl->currentContext->Flush(); } + + // End render pass + mainCommandBuffer->EndRenderPass(); + mImpl->renderAlgorithms.SubmitCommandBuffer(); } GLenum attachments[] = {GL_DEPTH, GL_STENCIL}; @@ -1088,6 +1138,9 @@ void RenderManager::RenderScene(Integration::RenderStatus& status, Integration:: void RenderManager::PostRender(bool uploadOnly) { + // Submit main command buffer + //mImpl->renderAlgorithms.SubmitCommandBuffer(); + if(!uploadOnly) { if(mImpl->currentContext->IsSurfacelessContextSupported()) diff --git a/dali/internal/render/renderers/render-frame-buffer.cpp b/dali/internal/render/renderers/render-frame-buffer.cpp index b88a805..44f4345 100644 --- a/dali/internal/render/renderers/render-frame-buffer.cpp +++ b/dali/internal/render/renderers/render-frame-buffer.cpp @@ -92,7 +92,58 @@ void FrameBuffer::Bind() { if(!mGraphicsObject) { - mGraphicsObject = mGraphicsController->CreateFramebuffer(mCreateInfo, nullptr); + mGraphicsObject = mGraphicsController->CreateFramebuffer(mCreateInfo, std::move(mGraphicsObject)); + + // Create render target + Graphics::RenderTargetCreateInfo rtInfo{}; + rtInfo + .SetFramebuffer( mGraphicsObject.get() ) + .SetExtent( {mWidth, mHeight} ) + .SetPreTransform( 0 | Graphics::RenderTargetTransformFlagBits::TRANSFORM_IDENTITY_BIT ); + mRenderTarget = mGraphicsController->CreateRenderTarget( rtInfo, std::move(mRenderTarget) ); + + std::vector attachmentDescriptions; + + // Default behaviour for color attachments is to CLEAR and STORE + //@todo Ideally, we should create new render pass whenever + // the loadop, storeop changes and the list of such renderpasses + // should be managed accordingly (as in Vulkan) + mClearValues.clear(); + for(auto& att: mCreateInfo.colorAttachments ) + { + if(att.texture) + { + Graphics::AttachmentDescription desc{}; + desc.SetLoadOp(Graphics::AttachmentLoadOp::CLEAR); + desc.SetStoreOp(Graphics::AttachmentStoreOp::STORE); + attachmentDescriptions.push_back(desc); + mClearValues.emplace_back(); + } + } + + if(mCreateInfo.depthStencilAttachment.depthTexture) + { + Graphics::AttachmentDescription depthStencilDesc{}; + depthStencilDesc.SetStencilLoadOp( Graphics::AttachmentLoadOp::CLEAR ) + .SetStoreOp( Graphics::AttachmentStoreOp::DONT_CARE ); + if(mCreateInfo.depthStencilAttachment.stencilTexture) + { + depthStencilDesc.SetStencilLoadOp( Graphics::AttachmentLoadOp::CLEAR) + .SetStoreOp( Graphics::AttachmentStoreOp::DONT_CARE); + } + mClearValues.emplace_back(); + attachmentDescriptions.push_back(depthStencilDesc); + } + + Graphics::RenderPassCreateInfo rpInfo{}; + rpInfo.SetAttachments( attachmentDescriptions ); + + // Add default render pass (loadOp = clear) + mRenderPass.emplace_back( mGraphicsController->CreateRenderPass( rpInfo, nullptr ) ); + + // Add default render pass (loadOp = dontcare) + attachmentDescriptions[0].SetLoadOp( Graphics::AttachmentLoadOp::DONT_CARE ); + mRenderPass.emplace_back( mGraphicsController->CreateRenderPass( rpInfo, nullptr ) ); } } @@ -106,6 +157,21 @@ uint32_t FrameBuffer::GetHeight() const return mHeight; } +[[nodiscard]] Graphics::RenderPass* FrameBuffer::GetGraphicsRenderPass( Graphics::AttachmentLoadOp colorLoadOp, + Graphics::AttachmentStoreOp colorStoreOp ) const +{ + // clear only when requested + if( colorLoadOp == Graphics::AttachmentLoadOp::CLEAR ) + { + return mRenderPass[0].get(); + } + else + { + return mRenderPass[1].get(); + } +} + + } // namespace Render } // namespace Internal diff --git a/dali/internal/render/renderers/render-frame-buffer.h b/dali/internal/render/renderers/render-frame-buffer.h index ce39488..01caa58 100644 --- a/dali/internal/render/renderers/render-frame-buffer.h +++ b/dali/internal/render/renderers/render-frame-buffer.h @@ -121,6 +121,24 @@ public: return mGraphicsObject.get(); } + [[nodiscard]] Graphics::RenderTarget* GetGraphicsRenderTarget() const + { + return mRenderTarget.get(); + } + + [[nodiscard]] Graphics::RenderPass* GetGraphicsRenderPass( Graphics::AttachmentLoadOp colorLoadOp, + Graphics::AttachmentStoreOp colorStoreOp ) const; + + /** + * The function returns initialized array of clear values + * which then can be modified and assed to BeginRenderPass() + * command. + */ + [[nodiscard]] auto& GetGraphicsRenderPassClearValues() + { + return mClearValues; + } + private: /** * @brief Undefined copy constructor. FrameBuffer cannot be copied @@ -138,6 +156,19 @@ private: Graphics::FramebufferCreateInfo mCreateInfo; + // Render pass and render target + + /** + * Render passes are created on fly depending on Load and Store operations + * The default render pass (most likely to be used) is the load = CLEAR + * amd store = STORE for color attachment. + */ + std::vector> mRenderPass{}; + Graphics::UniquePtr mRenderTarget{nullptr}; + + // clear colors + std::vector mClearValues{}; + uint32_t mWidth; uint32_t mHeight; diff --git a/dali/internal/render/renderers/render-renderer.cpp b/dali/internal/render/renderers/render-renderer.cpp index 3e2d510..622031b 100644 --- a/dali/internal/render/renderers/render-renderer.cpp +++ b/dali/internal/render/renderers/render-renderer.cpp @@ -570,7 +570,7 @@ void Renderer::Upload() mGeometry->Upload(*mGraphicsController); } -void Renderer::Render(Context& context, +bool Renderer::Render(Context& context, BufferIndex bufferIndex, const SceneGraph::NodeDataProvider& node, const Matrix& modelMatrix, @@ -586,7 +586,7 @@ void Renderer::Render(Context& conte // Before doing anything test if the call happens in the right queue if(mDrawCommands.empty() && queueIndex > 0) { - return; + return false; } // Prepare commands @@ -602,7 +602,7 @@ void Renderer::Render(Context& conte // Have commands but nothing to be drawn - abort if(!mDrawCommands.empty() && commands.empty()) { - return; + return false; } // Create command buffer if not present @@ -661,7 +661,7 @@ void Renderer::Render(Context& conte if(!program) { DALI_LOG_ERROR("Failed to get program for shader at address %p.\n", reinterpret_cast(&mRenderDataProvider->GetShader())); - return; + return false; } // Temporarily create a pipeline here - this will be used for transporting @@ -698,14 +698,16 @@ void Renderer::Render(Context& conte // @todo We should return the command buffer(s) and let the calling method submit // If not drawn, then don't add command buffer to submit info, and if empty, don't // submit. + /* if(drawn) { Graphics::SubmitInfo submitInfo{{}, 0 | Graphics::SubmitFlagBits::FLUSH}; submitInfo.cmdBuffer.push_back(commandBuffer.get()); mGraphicsController->SubmitCommandBuffers(submitInfo); } - + */ mUpdated = false; + return drawn; } void Renderer::BuildUniformIndexMap(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider& node, const Vector3& size, Program& program) @@ -1237,15 +1239,6 @@ Graphics::UniquePtr Renderer::PrepareGraphicsPipeline( mUpdated = true; - // @todo Should instead set framebuffer once through Renderpass, rather than modifying - // pipeline repeatedly. - Graphics::FramebufferState framebufferState{}; - if(instruction.mFrameBuffer) - { - instruction.mFrameBuffer->Bind(); // Ensure graphics object is created. - framebufferState.SetFramebuffer(*instruction.mFrameBuffer->GetGraphicsObject()); - } - // Create a new pipeline // @todo Passed as pointers - shallow copy will break. Implementation MUST deep copy. return mGraphicsController->CreatePipeline( @@ -1254,7 +1247,6 @@ Graphics::UniquePtr Renderer::PrepareGraphicsPipeline( .SetVertexInputState(&vertexInputState) .SetRasterizationState(&rasterizationState) .SetColorBlendState(&colorBlendState) - .SetFramebufferState(&framebufferState) .SetProgramState(&programState) .SetNextExtension(&mLegacyProgram), std::move(oldPipeline)); diff --git a/dali/internal/render/renderers/render-renderer.h b/dali/internal/render/renderers/render-renderer.h index 0d31f7a..2d4e19e 100644 --- a/dali/internal/render/renderers/render-renderer.h +++ b/dali/internal/render/renderers/render-renderer.h @@ -377,7 +377,7 @@ public: * @param[in] instruction. for use case like reflection where CullFace needs to be adjusted */ - void Render(Context& context, + bool Render(Context& context, BufferIndex bufferIndex, const SceneGraph::NodeDataProvider& node, const Matrix& modelMatrix, @@ -431,6 +431,11 @@ public: const void* data, uint32_t size); + [[nodiscard]] Graphics::CommandBuffer* GetGraphicsCommandBuffer() const + { + return mGraphicsCommandBuffer.get(); + } + private: struct UniformIndexMap;