From: Adam Bialogonski Date: Tue, 30 Mar 2021 17:19:01 +0000 (+0100) Subject: Create render pass for surface rendering X-Git-Tag: dali_2.0.28~24 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F21%2F256021%2F12;p=platform%2Fcore%2Fuifw%2Fdali-core.git Create render pass for surface rendering Change-Id: I09069aab42d4e7af67aee7700e2a4e4c2ec27db4 --- diff --git a/dali/integration-api/scene.cpp b/dali/integration-api/scene.cpp index bbe1139..4963c8f 100644 --- a/dali/integration-api/scene.cpp +++ b/dali/integration-api/scene.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * Copyright (c) 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,11 +18,14 @@ // CLASS HEADER #include -// INTERNAL INCLUDES -#include +// EXTERNAL INCLUDES +#include #include #include +// INTERNAL INCLUDES +#include + namespace Dali { namespace Integration @@ -121,6 +124,11 @@ void Scene::Discard() GetImplementation(*this).Discard(); } +void Scene::SetSurfaceRenderTarget(Graphics::RenderTarget* renderTarget) +{ + GetImplementation(*this).SetSurfaceRenderTarget(renderTarget); +} + Integration::Scene Scene::Get(Actor actor) { return Dali::Integration::Scene(&GetImplementation(actor).GetScene()); diff --git a/dali/integration-api/scene.h b/dali/integration-api/scene.h index eeb191f..a553ff3 100644 --- a/dali/integration-api/scene.h +++ b/dali/integration-api/scene.h @@ -2,7 +2,7 @@ #define DALI_SCENE_H /* - * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * Copyright (c) 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -41,6 +41,11 @@ namespace Internal DALI_INTERNAL class Scene; } +namespace Graphics +{ +class RenderTarget; +} + namespace Integration { struct Event; @@ -218,6 +223,13 @@ public: void Discard(); /** + * @brief Sets the render target for the surface. + * + * @param[in] renderTarget The render target for the surface + */ + void SetSurfaceRenderTarget(Graphics::RenderTarget* renderTarget); + + /** * @brief Retrieve the Scene that the given actor belongs to. * @return The Scene. */ diff --git a/dali/internal/event/common/scene-impl.cpp b/dali/internal/event/common/scene-impl.cpp index 95104fb..6f72912 100644 --- a/dali/internal/event/common/scene-impl.cpp +++ b/dali/internal/event/common/scene-impl.cpp @@ -316,6 +316,13 @@ bool Scene::IsSurfaceRectChanged() const return mSceneObject->IsSurfaceRectChanged(); } +void Scene::SetSurfaceRenderTarget(Graphics::RenderTarget* renderTarget) +{ + // Send the surface render target to SceneGraph::Scene + ThreadLocalStorage* tls = ThreadLocalStorage::GetInternal(); + SetSurfaceRenderTargetMessage(tls->GetEventThreadServices(), *mSceneObject, renderTarget); +} + bool Scene::EmitKeyEventGeneratedSignal(const Dali::KeyEvent& event) { // Emit the KeyEventGenerated signal when KeyEvent is generated diff --git a/dali/internal/event/common/scene-impl.h b/dali/internal/event/common/scene-impl.h index 1346448..96c3bc3 100644 --- a/dali/internal/event/common/scene-impl.h +++ b/dali/internal/event/common/scene-impl.h @@ -257,6 +257,11 @@ public: bool IsSurfaceRectChanged() const; /** + * @copydoc Dali::Integration::Scene::SetSurfaceRenderTarget + */ + void SetSurfaceRenderTarget(Graphics::RenderTarget* renderTarget); + + /** * Used by the EventProcessor to emit key event signals. * @param[in] event The key event. */ diff --git a/dali/internal/render/common/render-manager.cpp b/dali/internal/render/common/render-manager.cpp index 2bab722..c4898da 100644 --- a/dali/internal/render/common/render-manager.cpp +++ b/dali/internal/render/common/render-manager.cpp @@ -89,8 +89,8 @@ struct RenderManager::Impl uniformBufferManager.reset(new Render::UniformBufferManager(&graphicsController)); // initialize main command buffer - auto info = Graphics::CommandBufferCreateInfo().SetLevel( Graphics::CommandBufferLevel::PRIMARY ); - mainCommandBuffer = graphicsController.CreateCommandBuffer( info, nullptr ); + auto info = Graphics::CommandBufferCreateInfo().SetLevel(Graphics::CommandBufferLevel::PRIMARY); + mainCommandBuffer = graphicsController.CreateCommandBuffer(info, nullptr); } ~Impl() @@ -186,8 +186,6 @@ struct RenderManager::Impl Graphics::UniquePtr mainCommandBuffer; ///< Main command buffer Graphics::UniquePtr mainRenderPass; ///< Main renderpass - - }; RenderManager* RenderManager::New(Graphics::Controller& graphicsController, @@ -357,7 +355,7 @@ void RenderManager::RemoveFrameBuffer(Render::FrameBuffer* frameBuffer) void RenderManager::InitializeScene(SceneGraph::Scene* scene) { - scene->Initialize(*mImpl->CreateSceneContext()); + scene->Initialize(*mImpl->CreateSceneContext(), mImpl->graphicsController); mImpl->sceneContainer.push_back(scene); } @@ -375,7 +373,7 @@ void RenderManager::UninitializeScene(SceneGraph::Scene* scene) void RenderManager::SurfaceReplaced(SceneGraph::Scene* scene) { Context* newContext = mImpl->ReplaceSceneContext(scene->GetContext()); - scene->Initialize(*newContext); + scene->Initialize(*newContext, mImpl->graphicsController); } void RenderManager::AttachColorTextureToFrameBuffer(Render::FrameBuffer* frameBuffer, Render::Texture* texture, uint32_t mipmapLevel, uint32_t layer) @@ -514,10 +512,11 @@ void RenderManager::PreRender(Integration::RenderStatus& status, bool forceClear { mImpl->currentContext = &mImpl->context; - if(mImpl->currentContext->IsSurfacelessContextSupported()) - { - mImpl->graphicsController.GetGlContextHelperAbstraction().MakeSurfacelessContextCurrent(); - } + // Context switch now happens when the uploading happens in graphics side + // if(mImpl->currentContext->IsSurfacelessContextSupported()) + // { + // mImpl->graphicsController.GetGlContextHelperAbstraction().MakeSurfacelessContextCurrent(); + // } // Clear the current cached program when the context is switched mImpl->programController.ClearCurrentProgram(); @@ -846,32 +845,31 @@ void RenderManager::RenderScene(Integration::RenderStatus& status, Integration:: // todo: use no-clear renderpass instead (not implemented yet) // Set the clear color for first color attachment - if( instruction.mIsClearColorSet ) + if(instruction.mIsClearColorSet) { clearValues[0].color = { instruction.mClearColor.r, instruction.mClearColor.g, instruction.mClearColor.b, - instruction.mClearColor.a - }; + instruction.mClearColor.a}; } // offscreen buffer mainCommandBuffer->BeginRenderPass( - instruction.mFrameBuffer->GetGraphicsRenderPass( Graphics::AttachmentLoadOp::CLEAR, Graphics::AttachmentStoreOp::STORE ), + instruction.mFrameBuffer->GetGraphicsRenderPass(Graphics::AttachmentLoadOp::CLEAR, Graphics::AttachmentStoreOp::STORE), instruction.mFrameBuffer->GetGraphicsRenderTarget(), - { instruction.mFrameBuffer->GetWidth(), instruction.mFrameBuffer->GetHeight() }, - clearValues - ); + {instruction.mFrameBuffer->GetWidth(), instruction.mFrameBuffer->GetHeight()}, + clearValues); if(mImpl->currentContext != &mImpl->context) { // Switch to shared context for off-screen buffer mImpl->currentContext = &mImpl->context; - if(mImpl->currentContext->IsSurfacelessContextSupported()) - { - mImpl->graphicsController.GetGlContextHelperAbstraction().MakeSurfacelessContextCurrent(); - } + // Context switch now happens when render pass starts + // if(mImpl->currentContext->IsSurfacelessContextSupported()) + // { + // mImpl->graphicsController.GetGlContextHelperAbstraction().MakeSurfacelessContextCurrent(); + // } // Clear the current cached program when the context is switched mImpl->programController.ClearCurrentProgram(); @@ -890,6 +888,24 @@ void RenderManager::RenderScene(Integration::RenderStatus& status, Integration:: mImpl->programController.ClearCurrentProgram(); } } + + // surface + auto& clearValues = sceneObject->GetGraphicsRenderPassClearValues(); + + if(instruction.mIsClearColorSet) + { + clearValues[0].color = { + instruction.mClearColor.r, + instruction.mClearColor.g, + instruction.mClearColor.b, + instruction.mClearColor.a}; + } + + mainCommandBuffer->BeginRenderPass( + sceneObject->GetGraphicsRenderPass(), + sceneObject->GetSurfaceRenderTarget(), + {static_cast(surfaceRect.width), static_cast(surfaceRect.height)}, + clearValues); } // Make sure that GL context must be created @@ -901,7 +917,6 @@ 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 @@ -913,17 +928,20 @@ void RenderManager::RenderScene(Integration::RenderStatus& status, Integration:: } else { - mImpl->currentContext->BindFramebuffer(GL_FRAMEBUFFER, 0u); + //mImpl->currentContext->BindFramebuffer(GL_FRAMEBUFFER, 0u); } // @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, @@ -936,6 +954,8 @@ void RenderManager::RenderScene(Integration::RenderStatus& status, Integration:: // It is important to clear all 3 buffers when they are being used, for performance on deferred renderers // e.g. previously when the depth & stencil buffers were NOT cleared, it caused the DDK to exceed a "vertex count limit", // and then stall. That problem is only noticeable when rendering a large number of vertices per frame. + + /* GLbitfield clearMask = GL_COLOR_BUFFER_BIT; mImpl->currentContext->ColorMask(true); @@ -952,7 +972,7 @@ void RenderManager::RenderScene(Integration::RenderStatus& status, Integration:: mImpl->currentContext->StencilMask(0xFF); // 8 bit stencil mask, all 1's clearMask |= GL_STENCIL_BUFFER_BIT; } - + */ if(!instruction.mIgnoreRenderToFbo && (instruction.mFrameBuffer != nullptr)) { // Offscreen buffer rendering @@ -1012,34 +1032,36 @@ void RenderManager::RenderScene(Integration::RenderStatus& status, Integration:: // @todo The following block should be a command in it's own right. // Currently takes account of surface orientation in Context. // Or move entirely to RenderPass implementation - mImpl->currentContext->Viewport(viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height); + mainCommandBuffer->SetViewport( { + float(viewportRect.x), + float(viewportRect.y), + float(viewportRect.width), + float(viewportRect.height)} ); + + //mImpl->currentContext->Viewport(viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height); if(instruction.mIsClearColorSet) { - mImpl->currentContext->ClearColor(clearColor.r, - clearColor.g, - clearColor.b, - clearColor.a); if(!clearFullFrameRect) { if(!clippingRect.IsEmpty()) { - mImpl->currentContext->SetScissorTest(true); - mImpl->currentContext->Scissor(clippingRect.x, clippingRect.y, clippingRect.width, clippingRect.height); - mImpl->currentContext->Clear(clearMask, Context::FORCE_CLEAR); - mImpl->currentContext->SetScissorTest(false); + //mImpl->currentContext->SetScissorTest(true); + //mImpl->currentContext->Scissor(clippingRect.x, clippingRect.y, clippingRect.width, clippingRect.height); + //mImpl->currentContext->Clear(clearMask, Context::FORCE_CLEAR); + //mImpl->currentContext->SetScissorTest(false); } else { - mImpl->currentContext->SetScissorTest(true); - mImpl->currentContext->Scissor(viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height); - mImpl->currentContext->Clear(clearMask, Context::FORCE_CLEAR); - mImpl->currentContext->SetScissorTest(false); + //mImpl->currentContext->SetScissorTest(true); + //mImpl->currentContext->Scissor(viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height); + //mImpl->currentContext->Clear(clearMask, Context::FORCE_CLEAR); + //mImpl->currentContext->SetScissorTest(false); } } else { - mImpl->currentContext->SetScissorTest(false); - mImpl->currentContext->Clear(clearMask, Context::FORCE_CLEAR); + //mImpl->currentContext->SetScissorTest(false); + //mImpl->currentContext->Clear(clearMask, Context::FORCE_CLEAR); } } @@ -1122,10 +1144,11 @@ void RenderManager::RenderScene(Integration::RenderStatus& status, Integration:: instruction.mRenderTracker = nullptr; // Only create once. } - if(renderToFbo) - { - mImpl->currentContext->Flush(); - } + // This now happens when the render pass for frame buffer finishes + // if(renderToFbo) + // { + // mImpl->currentContext->Flush(); + // } // End render pass mainCommandBuffer->EndRenderPass(); @@ -1143,10 +1166,11 @@ void RenderManager::PostRender(bool uploadOnly) if(!uploadOnly) { - if(mImpl->currentContext->IsSurfacelessContextSupported()) - { - mImpl->graphicsController.GetGlContextHelperAbstraction().MakeSurfacelessContextCurrent(); - } + // Context switch now happens outside the render manager + // if(mImpl->currentContext->IsSurfacelessContextSupported()) + // { + // mImpl->graphicsController.GetGlContextHelperAbstraction().MakeSurfacelessContextCurrent(); + // } GLenum attachments[] = {GL_DEPTH, GL_STENCIL}; mImpl->context.InvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments); diff --git a/dali/internal/update/common/scene-graph-scene.cpp b/dali/internal/update/common/scene-graph-scene.cpp index 8779ba9..a4fb196 100644 --- a/dali/internal/update/common/scene-graph-scene.cpp +++ b/dali/internal/update/common/scene-graph-scene.cpp @@ -44,9 +44,26 @@ Scene::~Scene() mFramePresentedCallbacks.clear(); } -void Scene::Initialize(Context& context) +void Scene::Initialize(Context& context, Graphics::Controller& graphicsController) { mContext = &context; + + // Create the render pass for the surface + std::vector attachmentDescriptions; + + // Default behaviour for color attachments is to CLEAR and STORE + mClearValues.clear(); + Graphics::AttachmentDescription desc{}; + desc.SetLoadOp(Graphics::AttachmentLoadOp::CLEAR); + desc.SetStoreOp(Graphics::AttachmentStoreOp::STORE); + attachmentDescriptions.push_back(desc); + mClearValues.emplace_back(); + + Graphics::RenderPassCreateInfo rpInfo{}; + rpInfo.SetAttachments(attachmentDescriptions); + + // Add default render pass (loadOp = clear) + mRenderPass = graphicsController.CreateRenderPass(rpInfo, nullptr); } Context* Scene::GetContext() diff --git a/dali/internal/update/common/scene-graph-scene.h b/dali/internal/update/common/scene-graph-scene.h index ab6cde4..b41dd22 100644 --- a/dali/internal/update/common/scene-graph-scene.h +++ b/dali/internal/update/common/scene-graph-scene.h @@ -18,6 +18,7 @@ */ // INTERNAL INCLUDES +#include #include #include #include @@ -51,8 +52,9 @@ public: /** * Creates a scene object in the GPU. * @param[in] context The GL context + * @param[in] graphicsController The graphics controller */ - void Initialize(Context& context); + void Initialize(Context& context, Graphics::Controller& graphicsController); /** * Gets the context holding the GL state of rendering for the scene @@ -160,6 +162,46 @@ public: */ bool IsSurfaceRectChanged(); + /** + * Set the render target of the surface + * + * @param[in] renderTarget The render target. + */ + void SetSurfaceRenderTarget(Graphics::RenderTarget* renderTarget) + { + mRenderTarget = renderTarget; + } + + /** + * Get the render target created for the scene + * + * @return the render target + */ + [[nodiscard]] Graphics::RenderTarget* GetSurfaceRenderTarget() const + { + return mRenderTarget; + } + + /** + * Get the graphics render pass created for the scene + * + * @return the graphics render pass + */ + [[nodiscard]] Graphics::RenderPass* GetGraphicsRenderPass() const + { + return mRenderPass.get(); + } + + /** + * Get an initialized array of clear values which then can be modified and accessed to BeginRenderPass() command. + * + * @return the array of clear values + */ + [[nodiscard]] auto& GetGraphicsRenderPassClearValues() + { + return mClearValues; + } + private: Context* mContext; ///< The context holding the GL state of rendering for the scene, not owned @@ -176,6 +218,19 @@ private: Rect mSurfaceRect; ///< The rectangle of surface which is related ot this scene. int32_t mSurfaceOrientation; ///< The orientation of surface which is related of this scene bool mSurfaceRectChanged; ///< The flag of surface's rectangle is changed when is resized, moved or rotated. + + // Render pass and render target + + /** + * Render pass is created on fly depending on Load and Store operations + * The default render pass (most likely to be used) is the load = CLEAR + * and store = STORE for color attachment. + */ + Graphics::UniquePtr mRenderPass{nullptr}; ///< The render pass created to render the surface + Graphics::RenderTarget* mRenderTarget{nullptr}; ///< This is created in the event thread when surface is created/resized/replaced + + // clear colors + std::vector mClearValues{}; }; /// Messages @@ -223,6 +278,17 @@ inline void SetSurfaceOrientationMessage(EventThreadServices& eventThreadService new(slot) LocalType(&scene, &Scene::SetSurfaceOrientation, orientation); } +inline void SetSurfaceRenderTargetMessage(EventThreadServices& eventThreadServices, const Scene& scene, Graphics::RenderTarget* renderTarget) +{ + using LocalType = MessageValue1; + + // Reserve some memory inside the message queue + uint32_t* slot = eventThreadServices.ReserveMessageSlot(sizeof(LocalType)); + + // Construct message in the message queue memory; note that delete should not be called on the return value + new(slot) LocalType(&scene, &Scene::SetSurfaceRenderTarget, renderTarget); +} + } // namespace SceneGraph } // namespace Internal