Changed command buffer ownership 17/317917/7
authorDavid Steele <david.steele@samsung.com>
Thu, 9 Jan 2025 18:57:34 +0000 (18:57 +0000)
committerDavid Steele <david.steele@samsung.com>
Thu, 23 Jan 2025 16:43:29 +0000 (16:43 +0000)
Each render instruction now has a command buffer.

This enables the backend/gpu to synchronize each command buffer when
rendering to framebuffers.

Because RenderTask API is freeform, the same framebuffer can be written
to more than once in a frame using different actors, so each render pass
needs it's own command buffer.

(May still be potential issue with multiple render tasks against the
scene, e.g. magnifier isn't fixed in Vulkan by this change)

Change-Id: I367f94144ab9670c346b98a8e57ad2b54db96fd5
Signed-off-by: David Steele <david.steele@samsung.com>
automated-tests/src/dali/dali-test-suite-utils/test-application.cpp
automated-tests/src/dali/utc-Dali-Animation.cpp
dali/internal/render/common/render-algorithms.cpp
dali/internal/render/common/render-algorithms.h
dali/internal/render/common/render-instruction.h
dali/internal/render/common/render-manager.cpp
dali/internal/render/renderers/render-frame-buffer.cpp
dali/internal/render/renderers/render-frame-buffer.h
dali/internal/render/renderers/render-renderer.cpp
dali/internal/update/common/scene-graph-scene.cpp
dali/internal/update/common/scene-graph-scene.h

index 1fa33c453d6564af570d39350fef3527efa13d16..e5a943a51a052f1419b17f2124b86db19ac38150 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 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.
@@ -97,6 +97,7 @@ void TestApplication::InitializeCore()
 {
   mCore->SceneCreated();
   mCore->Initialize();
+  mCore->ProcessEvents(); // Ensure that scene messages are ready for next update/render.
 }
 
 TestApplication::~TestApplication()
index 9cbf7860b1efea84e4058be4551b7f10db414fca..d80998159eaf78c2b4c1f5c0f4e8af366371bef3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 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.
@@ -476,6 +476,8 @@ int UtcDaliAnimationSetLoopCountP(void)
 
   Actor actor = Actor::New();
   application.GetScene().Add(actor);
+  application.SendNotification();
+  application.Render(0);
 
   // Build the animation
   float     durationSeconds(1.0f);
@@ -687,6 +689,7 @@ int UtcDaliAnimationSetLoopCountP3(void)
   animation.SetLooping(true);
   DALI_TEST_CHECK(animation.IsLooping());
 
+  application.SendNotification();
   application.Render(static_cast<unsigned int>(durationSeconds * intervalSeconds * 1000.0f));
   application.SendNotification();
   finishCheck.CheckSignalNotReceived();
@@ -797,6 +800,7 @@ int UtcDaliAnimationGetLoopCountP(void)
 
   animation.Play();
 
+  application.SendNotification();
   application.Render(0);
   application.SendNotification();
 
@@ -12698,8 +12702,8 @@ int UtcDaliAnimationAnimateBetweenIntegerP(void)
   const Property::Index index = actor.RegisterProperty("customProperty", startValue);
   application.GetScene().Add(actor);
 
-  application.Render();
   application.SendNotification();
+  application.Render();
 
   DALI_TEST_EQUALS(actor.GetProperty<int>(index), startValue, TEST_LOCATION);
 
index 59a2c64d6e99a1f03961d3c31fa6a6c8d33eb60b..529598a59b324b1ceb4aadc98b1f43e34b0cb0f8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 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.
@@ -741,42 +741,6 @@ RenderAlgorithms::RenderAlgorithms(Graphics::Controller& graphicsController)
 {
 }
 
-void RenderAlgorithms::ResetCommandBuffer()
-{
-  // Reset main command buffer
-  if(!mGraphicsCommandBuffer)
-  {
-    mGraphicsCommandBuffer = mGraphicsController.CreateCommandBuffer(
-      Graphics::CommandBufferCreateInfo()
-        .SetLevel(Graphics::CommandBufferLevel::PRIMARY),
-      nullptr);
-  }
-  else
-  {
-    mGraphicsCommandBuffer->Reset();
-  }
-
-  Graphics::CommandBufferBeginInfo info;
-  info.usage = 0 | Graphics::CommandBufferUsageFlagBits::ONE_TIME_SUBMIT;
-  mGraphicsCommandBuffer->Begin(info);
-}
-
-void RenderAlgorithms::SubmitCommandBuffer()
-{
-  // Submit main command buffer
-  mGraphicsCommandBuffer->End();
-
-  Graphics::SubmitInfo submitInfo;
-  submitInfo.cmdBuffer.push_back(mGraphicsCommandBuffer.get());
-  submitInfo.flags = 0 | Graphics::SubmitFlagBits::FLUSH;
-  mGraphicsController.SubmitCommandBuffers(submitInfo);
-}
-
-void RenderAlgorithms::DestroyCommandBuffer()
-{
-  mGraphicsCommandBuffer.reset();
-}
-
 void RenderAlgorithms::ProcessRenderInstruction(const RenderInstruction&            instruction,
                                                 BufferIndex                         bufferIndex,
                                                 Integration::DepthBufferAvailable   depthBufferAvailable,
@@ -786,9 +750,11 @@ void RenderAlgorithms::ProcessRenderInstruction(const RenderInstruction&
                                                 int                                 orientation,
                                                 const Uint16Pair&                   sceneSize,
                                                 Graphics::RenderPass*               renderPass,
-                                                Graphics::RenderTarget*             renderTarget)
+                                                Graphics::RenderTarget*             renderTarget,
+                                                Graphics::CommandBuffer*            commandBuffer)
 {
-  DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_RENDER_INSTRUCTION_PROCESS", [&](std::ostringstream& oss) { oss << "[" << instruction.RenderListCount() << "]"; });
+  DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_RENDER_INSTRUCTION_PROCESS", [&](std::ostringstream& oss)
+                                          { oss << "[" << instruction.RenderListCount() << "]"; });
 
   DALI_PRINT_RENDER_INSTRUCTION(instruction, bufferIndex);
 
@@ -826,16 +792,16 @@ void RenderAlgorithms::ProcessRenderInstruction(const RenderInstruction&
                           renderTarget);
 
         // Execute command buffer
-        auto* commandBuffer = renderList->GetCommandBuffer();
-        if(commandBuffer)
+        auto* secondaryCommandBuffer = renderList->GetCommandBuffer();
+        if(secondaryCommandBuffer)
         {
-          buffers.push_back(commandBuffer);
+          buffers.push_back(secondaryCommandBuffer);
         }
       }
     }
     if(!buffers.empty())
     {
-      mGraphicsCommandBuffer->ExecuteCommandBuffers(std::move(buffers));
+      commandBuffer->ExecuteCommandBuffers(std::move(buffers));
     }
   }
   DALI_TRACE_END(gTraceFilter, "DALI_RENDER_INSTRUCTION_PROCESS");
index 7411f5f637ac9a598202c187c9b4a451e63e6352..a2831a7a2d1962e78276e7f4e135cf7cdc15c5af 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_RENDER_ALGORITHMS_H
 
 /*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 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.
@@ -61,7 +61,9 @@ public:
    * @param[in] rootClippingRect       The clipping rectangle
    * @param[in] orientation            The Scene's surface orientation.
    * @param[in] sceneSize              The Scene's surface size.
+   * @param[in] renderPass             The RenderPass associated with the renderTarget
    * @param[in] renderTarget           The RenderTarget associated with instruction
+   * @param[in] commandBuffer          The CommandBuffer associated with the renderTarget
    */
   void ProcessRenderInstruction(const SceneGraph::RenderInstruction& instruction,
                                 BufferIndex                          bufferIndex,
@@ -72,35 +74,8 @@ public:
                                 int                                  orientation,
                                 const Uint16Pair&                    sceneSize,
                                 Graphics::RenderPass*                renderPass,
-                                Graphics::RenderTarget*              renderTarget);
-
-  /**
-   * Resets main command buffer
-   */
-  void ResetCommandBuffer();
-
-  /**
-   * Submits main command buffer
-   */
-  void SubmitCommandBuffer();
-
-  /**
-   * @brief Destroy main command buffer (called only one time, at terminate case)
-   */
-  void DestroyCommandBuffer();
-
-  /**
-   * Returns main command buffer
-   *
-   * 'Main' command buffer exists per each scene and it is used
-   * to bake all render instructions for the scene.
-   *
-   * @return main command buffer
-   */
-  [[nodiscard]] Graphics::CommandBuffer* GetMainCommandBuffer() const
-  {
-    return mGraphicsCommandBuffer.get();
-  }
+                                Graphics::RenderTarget*              renderTarget,
+                                Graphics::CommandBuffer*             commandBuffer);
 
 private:
   /**
@@ -174,8 +149,7 @@ private:
 
   using ScissorStackType = std::vector<Dali::ClippingBox>; ///< The container type used to maintain the applied scissor hierarchy
 
-  Graphics::Controller&                        mGraphicsController;
-  Graphics::UniquePtr<Graphics::CommandBuffer> mGraphicsCommandBuffer{};
+  Graphics::Controller& mGraphicsController;
 
   std::vector<Graphics::CommandBuffer*> mGraphicsRenderItemCommandBuffers{}; ///< Collection of command buffers issuing single draw call
 
index b4225fd2f807d2cab357236f9e480e89d5b08c84..b0a0be5510a45ab605ec8ca72109b28c7c6735fb 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_SCENE_GRAPH_RENDER_INSTRUCTION_H
 
 /*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 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.
@@ -57,6 +57,12 @@ public:
    */
   ~RenderInstruction();
 
+  // Deleted copy constructor
+  RenderInstruction(const RenderInstruction&) = delete;
+
+  // Deleted assignment operator
+  RenderInstruction& operator=(const RenderInstruction& rhs) = delete;
+
   /**
    * @brief The graphics context is being shutdown. Clean down any outstanding graphics resources.
    */
@@ -130,16 +136,21 @@ public:
     return mCamera;
   }
 
+  [[nodiscard]] Graphics::CommandBuffer* GetCommandBuffer(Graphics::Controller& graphicsController)
+  {
+    if(!mCommandBuffer)
+    {
+      mCommandBuffer = graphicsController.CreateCommandBuffer(Graphics::CommandBufferCreateInfo().SetLevel(Graphics::CommandBufferLevel::PRIMARY), nullptr);
+    }
+    return mCommandBuffer.get();
+  }
+
   /**
    * Get the total memory usage of the render instruction
    */
   std::size_t GetCapacity();
 
-private:
-  RenderInstruction(const RenderInstruction&) = delete;
-  RenderInstruction& operator=(const RenderInstruction& rhs) = delete;
-
-public:                                  // Data
+public:
   Render::RenderTracker* mRenderTracker; ///< Pointer to an optional tracker object (not owned)
 
   Viewport mViewport;              ///< Optional viewport
@@ -151,7 +162,9 @@ public:                                  // Data
   Render::FrameBuffer* mFrameBuffer;
   uint32_t             mRenderPassTag{0u};
 
-private:                                             // Data
+private:
+  Graphics::UniquePtr<Graphics::CommandBuffer> mCommandBuffer{nullptr}; ///< Output of render lists
+
   Camera*                       mCamera;             ///< camera that is used
   RenderListContainer           mRenderLists;        ///< container of all render lists
   RenderListContainer::SizeType mNextFreeRenderList; ///< index for the next free render list
index 971bbb7a44e71c982a793b35233a715f782912aa..3a92d6f6ebc96475ace79cb5bd2f40657deb9bb0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 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.
@@ -268,7 +268,6 @@ struct RenderManager::Impl
   void ContextDestroyed()
   {
     sceneContainer.clear();
-    renderAlgorithms.DestroyCommandBuffer();
 
     renderedFrameBufferContainer.clear();
     samplerContainer.Clear();
@@ -977,8 +976,6 @@ void RenderManager::RenderScene(Integration::RenderStatus& status, Integration::
 
   uint32_t instructionCount = sceneObject->GetRenderInstructions().Count(mImpl->renderBufferIndex);
 
-  std::vector<Graphics::RenderTarget*> targetsToPresent;
-
   Rect<int32_t> surfaceRect = sceneObject->GetSurfaceRect();
   if(clippingRect == surfaceRect)
   {
@@ -1051,9 +1048,11 @@ void RenderManager::RenderScene(Integration::RenderStatus& status, Integration::
       }
     }
   }
+
+  auto sceneRenderTarget = sceneObject->GetSurfaceRenderTarget();
   if(!renderToFbo)
   {
-    mImpl->graphicsController.EnableDepthStencilBuffer(*sceneObject->GetSurfaceRenderTarget(), sceneNeedsDepthBuffer, sceneNeedsStencilBuffer);
+    mImpl->graphicsController.EnableDepthStencilBuffer(*sceneRenderTarget, sceneNeedsDepthBuffer, sceneNeedsStencilBuffer);
   }
   // Fill resource binding for the scene
   std::vector<Graphics::SceneResourceBinding> sceneResourceBindings;
@@ -1070,11 +1069,6 @@ void RenderManager::RenderScene(Integration::RenderStatus& status, Integration::
   }
   mImpl->graphicsController.SetResourceBindingHints(sceneResourceBindings);
 
-  // Reset main algorithms command buffer
-  mImpl->renderAlgorithms.ResetCommandBuffer();
-
-  auto mainCommandBuffer = mImpl->renderAlgorithms.GetMainCommandBuffer();
-
   DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Render scene (%s), CPU:%d GPU:%d\n", renderToFbo ? "Offscreen" : "Onscreen", totalSizeCPU, totalSizeGPU);
 
   auto& uboManager = mImpl->uniformBufferManager;
@@ -1110,6 +1104,30 @@ void RenderManager::RenderScene(Integration::RenderStatus& status, Integration::
   }
 #endif
 
+  if(renderToFbo)
+  {
+    for(uint32_t i = 0; i < instructionCount; ++i)
+    {
+      RenderInstruction& instruction = sceneObject->GetRenderInstructions().At(mImpl->renderBufferIndex, i);
+      if(instruction.mFrameBuffer)
+      {
+        // Ensure graphics framebuffer is created, bind attachments and create render passes/commandbuffers
+        // Only happens once per framebuffer. If the creation fails, e.g. no attachments yet,
+        // then don't render to this framebuffer.
+        if(!instruction.mFrameBuffer->GetGraphicsObject())
+        {
+          const bool created = instruction.mFrameBuffer->CreateGraphicsObjects();
+          if(!created)
+          {
+            continue;
+          }
+        }
+      }
+    }
+  }
+
+  std::vector<Graphics::CommandBuffer*> commandBuffers;
+
   for(uint32_t i = 0; i < instructionCount; ++i)
   {
     RenderInstruction& instruction = sceneObject->GetRenderInstructions().At(mImpl->renderBufferIndex, i);
@@ -1130,22 +1148,16 @@ void RenderManager::RenderScene(Integration::RenderStatus& status, Integration::
       surfaceOrientation -= 360;
     }
 
-    Graphics::RenderTarget*           currentRenderTarget = nullptr;
-    Graphics::RenderPass*             currentRenderPass   = nullptr;
+    Graphics::RenderTarget*           currentRenderTarget  = nullptr;
+    Graphics::RenderPass*             currentRenderPass    = nullptr;
+    Graphics::CommandBuffer*          currentCommandBuffer = nullptr;
     std::vector<Graphics::ClearValue> currentClearValues{};
 
     if(instruction.mFrameBuffer)
     {
-      // Ensure graphics framebuffer is created, bind attachments and create render passes
-      // Only happens once per framebuffer. If the create fails, e.g. no attachments yet,
-      // then don't render to this framebuffer.
       if(!instruction.mFrameBuffer->GetGraphicsObject())
       {
-        const bool created = instruction.mFrameBuffer->CreateGraphicsObjects();
-        if(!created)
-        {
-          continue;
-        }
+        continue;
       }
 
       auto& clearValues = instruction.mFrameBuffer->GetGraphicsRenderPassClearValues();
@@ -1201,7 +1213,15 @@ void RenderManager::RenderScene(Integration::RenderStatus& status, Integration::
       currentRenderPass   = sceneObject->GetGraphicsRenderPass(loadOp, Graphics::AttachmentStoreOp::STORE);
     }
 
-    targetsToPresent.emplace_back(currentRenderTarget);
+    // Setup command buffer for this instruction.
+    currentCommandBuffer = instruction.GetCommandBuffer(mImpl->graphicsController);
+    commandBuffers.emplace_back(currentCommandBuffer);
+
+    currentCommandBuffer->Reset();
+    Graphics::CommandBufferBeginInfo info;
+    info.usage = 0 | Graphics::CommandBufferUsageFlagBits::ONE_TIME_SUBMIT;
+    info.SetRenderTarget(*currentRenderTarget);
+    currentCommandBuffer->Begin(info);
 
     if(!instruction.mIgnoreRenderToFbo && (instruction.mFrameBuffer != nullptr))
     {
@@ -1271,70 +1291,72 @@ void RenderManager::RenderScene(Integration::RenderStatus& status, Integration::
     // When the surface is rotated, the input values already were set with the rotated angle.
     // So, re-calculation is needed.
     scissorArea = RecalculateScissorArea(scissorArea, surfaceOrientation, surfaceRect);
-
-    // Begin render pass
-    mainCommandBuffer->BeginRenderPass(
-      currentRenderPass,
-      currentRenderTarget,
-      scissorArea,
-      currentClearValues);
-
-    // Note, don't set the viewport/scissor on the primary command buffer.
-
-    mImpl->renderAlgorithms.ProcessRenderInstruction(
-      instruction,
-      mImpl->renderBufferIndex,
-      depthBufferAvailable,
-      stencilBufferAvailable,
-      viewportRect,
-      clippingRect,
-      surfaceOrientation,
-      Uint16Pair(surfaceRect.width, surfaceRect.height),
-      currentRenderPass,
-      currentRenderTarget);
-
-    Graphics::SyncObject* syncObject{nullptr};
-    // If the render instruction has an associated render tracker (owned separately)
-    // and framebuffer, create a one shot sync object, and use it to determine when
-    // the render pass has finished executing on GPU.
-    if(instruction.mRenderTracker && instruction.mFrameBuffer)
+    if(scissorArea.width > 0 && scissorArea.height > 0)
     {
-      syncObject                 = instruction.mRenderTracker->CreateSyncObject(mImpl->graphicsController);
-      instruction.mRenderTracker = nullptr;
-    }
-    mainCommandBuffer->EndRenderPass(syncObject);
+      // Begin render pass
+      currentCommandBuffer->BeginRenderPass(currentRenderPass,
+                                            currentRenderTarget,
+                                            scissorArea,
+                                            currentClearValues);
+
+      // Note, don't set the viewport/scissor on primary command buffer.
+      mImpl->renderAlgorithms.ProcessRenderInstruction(instruction,
+                                                       mImpl->renderBufferIndex,
+                                                       depthBufferAvailable,
+                                                       stencilBufferAvailable,
+                                                       viewportRect,
+                                                       clippingRect,
+                                                       surfaceOrientation,
+                                                       Uint16Pair(surfaceRect.width, surfaceRect.height),
+                                                       currentRenderPass,
+                                                       currentRenderTarget,
+                                                       currentCommandBuffer);
+
+      Graphics::SyncObject* syncObject{nullptr};
+
+      // If the render instruction has an associated render tracker (owned separately)
+      // and framebuffer, create a one shot sync object, and use it to determine when
+      // the render pass has finished executing on GPU.
+      if(instruction.mRenderTracker && instruction.mFrameBuffer)
+      {
+        syncObject                 = instruction.mRenderTracker->CreateSyncObject(mImpl->graphicsController);
+        instruction.mRenderTracker = nullptr;
+      }
+      currentCommandBuffer->EndRenderPass(syncObject);
 
-    if(instruction.mFrameBuffer && instruction.mFrameBuffer->IsKeepingRenderResultRequested())
-    {
-      mainCommandBuffer->ReadPixels(instruction.mFrameBuffer->GetRenderResultBuffer());
-      mImpl->renderedFrameBufferContainer.push_back(instruction.mFrameBuffer);
+      if(instruction.mFrameBuffer && instruction.mFrameBuffer->IsKeepingRenderResultRequested())
+      {
+        currentCommandBuffer->ReadPixels(instruction.mFrameBuffer->GetRenderResultBuffer());
+        mImpl->renderedFrameBufferContainer.push_back(instruction.mFrameBuffer);
+      }
     }
   }
 
-  if(targetsToPresent.size() > 0u)
-  {
-    DALI_TRACE_BEGIN_WITH_MESSAGE_GENERATOR(gTraceFilter, "DALI_RENDER_FINISHED", [&](std::ostringstream& oss) { oss << "[" << targetsToPresent.size() << "]"; });
-  }
-
   // Flush UBOs
   mImpl->uniformBufferManager->Flush(sceneObject, renderToFbo);
-  mImpl->renderAlgorithms.SubmitCommandBuffer();
-  mImpl->commandBufferSubmitted = true;
 
-  if(targetsToPresent.size() > 0u)
+  // Submit command buffers
+  Graphics::SubmitInfo submitInfo;
+  submitInfo.flags = 0 | Graphics::SubmitFlagBits::FLUSH;
+
+  for(auto commandBuffer : commandBuffers)
   {
-    std::sort(targetsToPresent.begin(), targetsToPresent.end());
+    commandBuffer->End();
+    submitInfo.cmdBuffer.push_back(commandBuffer);
+  }
 
-    Graphics::RenderTarget* rt = nullptr;
-    for(auto& target : targetsToPresent)
-    {
-      if(target != rt)
-      {
-        mImpl->graphicsController.PresentRenderTarget(target);
-        rt = target;
-      }
-    }
+  if(!submitInfo.cmdBuffer.empty())
+  {
+    mImpl->graphicsController.SubmitCommandBuffers(submitInfo);
+    mImpl->commandBufferSubmitted = true;
+  }
 
+  // present render target (if main scene)
+  if(!renderToFbo)
+  {
+    DALI_TRACE_BEGIN(gTraceFilter, "DALI_RENDER_FINISHED");
+    auto renderTarget = sceneObject->GetSurfaceRenderTarget();
+    mImpl->graphicsController.PresentRenderTarget(renderTarget);
     DALI_TRACE_END(gTraceFilter, "DALI_RENDER_FINISHED");
   }
 }
index 462a160cdb4ce1ae81ca26b8873b4fd64f409fa8..0f4fbb6aa13b6db8b30cdf0c48c4585a54de9b4c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 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.
@@ -145,7 +145,7 @@ uint8_t* FrameBuffer::GetRenderResultBuffer()
       delete[] mRenderResult;
     }
     mRenderResult = new uint8_t[mWidth * mHeight * Dali::Pixel::GetBytesPerPixel(Pixel::Format::RGBA8888)];
-    buffer = mRenderResult;
+    buffer        = mRenderResult;
   }
   return buffer;
 }
@@ -162,7 +162,7 @@ void FrameBuffer::SetRenderResultDrawn()
 Dali::PixelData FrameBuffer::GetRenderResult()
 {
   Dali::Mutex::ScopedLock lock(mPixelDataMutex);
-  Dali::PixelData pixelData;
+  Dali::PixelData         pixelData;
   if(!mIsKeepingRenderResultRequested && mRenderedPixelData)
   {
     pixelData = mRenderedPixelData;
@@ -243,7 +243,8 @@ bool FrameBuffer::CreateGraphicsObjects()
         .SetPreTransform(0 | Graphics::RenderTargetTransformFlagBits::TRANSFORM_IDENTITY_BIT);
 
       mRenderTarget = mGraphicsController->CreateRenderTarget(rtInfo, std::move(mRenderTarget));
-      created       = true;
+
+      created = true;
     }
   }
   return created;
index 2020d2dd88dd0e743b376d21c3b0976399a04db6..6d25f281728cc9be2f7ac57208e621667158b851 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_RENDER_FRAME_BUFFER_H
 
 /*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 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.
 
 // INTERNAL INCLUDES
 #include <dali/devel-api/rendering/frame-buffer-devel.h>
-#include <dali/internal/render/renderers/render-sampler.h>
-#include <dali/public-api/rendering/frame-buffer.h>
 #include <dali/devel-api/threading/mutex.h>
+#include <dali/internal/render/renderers/render-sampler.h>
 
-#include <dali/integration-api/debug.h>
+#include <unordered_map>
 
 namespace Dali
 {
@@ -31,6 +30,11 @@ using Mask = Dali::FrameBuffer::Attachment::Mask;
 
 namespace Internal
 {
+namespace SceneGraph
+{
+class RenderInstruction;
+}
+
 namespace Render
 {
 class Texture;
@@ -172,7 +176,7 @@ public:
 
   /**
    * The function returns initialized array of clear values
-   * which then can be modified and assed to BeginRenderPass()
+   * which then can be modified and passed to BeginRenderPass()
    * command.
    */
   [[nodiscard]] auto& GetGraphicsRenderPassClearValues()
@@ -180,7 +184,6 @@ public:
     return mClearValues;
   }
 
-private:
   /**
    * @brief Undefined copy constructor. FrameBuffer cannot be copied
    */
@@ -197,15 +200,14 @@ private:
 
   Graphics::FramebufferCreateInfo mCreateInfo;
 
-  // Render pass and render target
+  Graphics::UniquePtr<Graphics::RenderTarget> mRenderTarget{nullptr};
 
   /**
    * 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.
+   * and store = STORE for color attachment.
    */
   std::vector<Graphics::UniquePtr<Graphics::RenderPass>> mRenderPass{};
-  Graphics::UniquePtr<Graphics::RenderTarget>            mRenderTarget{nullptr};
 
   // clear colors
   std::vector<Graphics::ClearValue> mClearValues{};
index a69db41421ffb1116e5e17e62a53593e6bbe5b37..eb4b44b60ecd1067ff7e23f6c6ba72166ac871a3 100644 (file)
@@ -221,9 +221,7 @@ bool Renderer::BindTextures(Graphics::CommandBuffer& commandBuffer)
         //   if it's default, delete the graphics object
         //   otherwise re-initialize it if dirty
 
-        const Graphics::Sampler* graphicsSampler = samplers ? ((i < (*samplers).Size() && (*samplers)[i]) ? (*samplers)[i]->GetGraphicsObject()
-                                                                                                          : nullptr)
-                                                            : nullptr;
+        const Graphics::Sampler* graphicsSampler = samplers ? ((i < (*samplers).Size() && (*samplers)[i]) ? (*samplers)[i]->GetGraphicsObject() : nullptr) : nullptr;
 
         const Graphics::TextureBinding textureBinding{graphicsTexture, graphicsSampler, textureUnit};
         textureBindings.push_back(textureBinding);
@@ -651,7 +649,8 @@ std::size_t Renderer::BuildUniformIndexMap(BufferIndex bufferIndex, const SceneG
   const auto nodeChangeCounter          = nodePtr ? uniformMapNode.GetChangeCounter() : 0;
   const auto renderItemMapChangeCounter = uniformMap.GetChangeCounter();
 
-  auto iter = std::find_if(mNodeIndexMap.begin(), mNodeIndexMap.end(), [nodePtr, programPtr](RenderItemLookup& element) { return (element.node == nodePtr && element.program == programPtr); });
+  auto iter = std::find_if(mNodeIndexMap.begin(), mNodeIndexMap.end(), [nodePtr, programPtr](RenderItemLookup& element)
+                           { return (element.node == nodePtr && element.program == programPtr); });
 
   std::size_t renderItemMapIndex;
   if(iter == mNodeIndexMap.end())
@@ -1000,7 +999,8 @@ void Renderer::DetachFromNodeDataProvider(const SceneGraph::NodeDataProvider& no
   }
 
   // Remove mNodeIndexMap and mUniformIndexMaps.
-  auto iter = std::find_if(mNodeIndexMap.begin(), mNodeIndexMap.end(), [&node](RenderItemLookup& element) { return element.node == &node; });
+  auto iter = std::find_if(mNodeIndexMap.begin(), mNodeIndexMap.end(), [&node](RenderItemLookup& element)
+                           { return element.node == &node; });
   while(iter != mNodeIndexMap.end())
   {
     // Swap between end of mUniformIndexMaps and removed.
@@ -1027,7 +1027,8 @@ void Renderer::DetachFromNodeDataProvider(const SceneGraph::NodeDataProvider& no
     // Remove uniform index maps.
     mUniformIndexMaps.pop_back();
 
-    iter = std::find_if(mNodeIndexMap.begin(), mNodeIndexMap.end(), [&node](RenderItemLookup& element) { return element.node == &node; });
+    iter = std::find_if(mNodeIndexMap.begin(), mNodeIndexMap.end(), [&node](RenderItemLookup& element)
+                        { return element.node == &node; });
   }
 }
 
index ebf5241d5c035b5c74c87814a63968b6688dae58..73ddffe6c70a3ee480d1e58328071517b83ff374 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 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.
index 3df3b00f398a919c2ae89370ad327a92031bc723..1f5dae9d63b9588891fa6229e54f8135c59b5772 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_SCENE_GRAPH_SCENE_H
 
 /*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 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.
@@ -404,18 +404,19 @@ private:
   bool mNeedFullUpdate;                   ///< A flag to update full area
   bool mPartialUpdateEnabled;             ///< True if the partial update is enabled
 
-  // Render pass and render target
+  // Render target, command buffer and render passes
 
   Graphics::RenderTargetCreateInfo mRenderTargetCreateInfo; // Passed in by message before 2nd stage Initialization happens.
 
+  Graphics::UniquePtr<Graphics::RenderTarget> mRenderTarget{nullptr}; ///< This is created in Update/Render thread when surface is created/resized/replaced
+
   /**
    * 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<Graphics::RenderPass>   mRenderPass{nullptr};        ///< The render pass created to render the surface
-  Graphics::UniquePtr<Graphics::RenderPass>   mRenderPassNoClear{nullptr}; ///< The render pass created to render the surface without clearing color
-  Graphics::UniquePtr<Graphics::RenderTarget> mRenderTarget{nullptr};      ///< This is created in Update/Render thread when surface is created/resized/replaced
+  Graphics::UniquePtr<Graphics::RenderPass> mRenderPass{nullptr};        ///< The render pass created to render the surface
+  Graphics::UniquePtr<Graphics::RenderPass> mRenderPassNoClear{nullptr}; ///< The render pass created to render the surface without clearing color
 
   SceneGraph::Layer* mRoot{nullptr}; ///< Root node