Make multiple renderer share the list of uboView + Recycle uboView 35/322935/6
authorEunki, Hong <eunkiki.hong@samsung.com>
Fri, 18 Apr 2025 06:16:30 +0000 (15:16 +0900)
committerEunki, Hong <eunkiki.hong@samsung.com>
Thu, 24 Apr 2025 08:45:45 +0000 (17:45 +0900)
Let we reduce the allocation of ubo view list

Also, make we recycle same pointer of temperal uboView,
so we can reduce reallocate memory from pool.

Change-Id: Idb28c6227350a36ebc7c4e537fd90e385bb903f9
Signed-off-by: Eunki, Hong <eunkiki.hong@samsung.com>
dali/internal/render/common/render-algorithms.cpp
dali/internal/render/common/shared-uniform-buffer-view-container.cpp
dali/internal/render/renderers/render-renderer.cpp
dali/internal/render/renderers/render-renderer.h
dali/internal/render/renderers/uniform-buffer-manager.cpp
dali/internal/render/renderers/uniform-buffer-manager.h
dali/internal/render/renderers/uniform-buffer-view.cpp
dali/internal/render/renderers/uniform-buffer-view.h

index 985cdde2ad2b5deb4b49e179c2f6e10172b95ac4..01bda032f2a0776167424959896d12164b5b86a6 100644 (file)
@@ -749,6 +749,9 @@ inline void RenderAlgorithms::ProcessRenderList(const RenderList&
       }
     }
   }
+
+  // Finalize Render::Renderer Render for this secondary command buffer.
+  Renderer::FinishedCommandBuffer();
   secondaryCommandBuffer.End();
 }
 
index 49515698435a1838be48c2569425b47f1dda3b6a..080198eb4802e00291eb598d8742f122b06c0cab 100644 (file)
@@ -109,13 +109,15 @@ void SharedUniformBufferViewContainer::Initialize(BufferIndex renderBufferIndex,
   uint32_t totalUniformBufferViewCount = 0u;
 #endif
 
+  static Render::UniformBufferView* sDummyView = nullptr;
+
   for(auto& item : mImpl->mSharedUniformBlockBufferViews)
   {
     const auto& program            = *item.first.program;
     auto&       sharedUniformBlock = *item.first.sharedUniformBlock;
     uint32_t    blockSize          = item.first.blockSize;
 
-    item.second = uniformBufferManager.CreateUniformBufferView(blockSize, false);
+    item.second = uniformBufferManager.CreateUniformBufferView(sDummyView, blockSize, false);
 
     if(DALI_UNLIKELY(!item.second))
     {
index 07bd508fcbe7b419ab552ef7b2548dea97325fd0..2cbd5da70a69e49e5e8a592f06329057bbf0ba07 100644 (file)
@@ -85,6 +85,12 @@ Dali::Internal::MemoryPoolObjectAllocator<Renderer>& GetRenderRendererMemoryPool
   static Dali::Internal::MemoryPoolObjectAllocator<Renderer> gRenderRendererMemoryPool;
   return gRenderRendererMemoryPool;
 }
+
+Render::UboViewContainer& GetUboViewList()
+{
+  static Render::UboViewContainer gUboViews;
+  return gUboViews;
+}
 } // namespace
 
 void Renderer::PrepareCommandBuffer()
@@ -95,6 +101,12 @@ void Renderer::PrepareCommandBuffer()
   // todo : Fill here as many caches as we can store for reduce the number of command buffers
 }
 
+void Renderer::FinishedCommandBuffer()
+{
+  // Ensure to remove current frame's UBOView list now.
+  GetUboViewList().Clear();
+}
+
 RendererKey Renderer::NewKey(SceneGraph::RenderDataProvider* dataProvider,
                              Render::Geometry*               geometry,
                              uint32_t                        blendingBitmask,
@@ -795,15 +807,15 @@ void Renderer::WriteUniformBuffer(
   const Vector3&                       size,
   std::size_t                          nodeIndex)
 {
-  auto& reflection = mGraphicsController->GetProgramReflection(program->GetGraphicsProgram());
+  const auto& reflection = mGraphicsController->GetProgramReflection(program->GetGraphicsProgram());
 
   const auto& programRequirements = program->GetUniformBlocksMemoryRequirements();
 
   // Allocate UBO view per each block (include standalone block)
   auto blockCount = programRequirements.blockCount;
 
-  std::vector<std::unique_ptr<UniformBufferView>> uboViews;
-  uboViews.resize(blockCount);
+  auto& uboViews = GetUboViewList();
+  uboViews.Resize(blockCount);
 
   // Prepare bindings
   auto uboCount = reflection.GetUniformBlockCount();
@@ -832,17 +844,18 @@ void Renderer::WriteUniformBuffer(
         mUniformBufferBindings[i].buffer = sharedUniformBufferViewPtr->GetBuffer();
         mUniformBufferBindings[i].offset = sharedUniformBufferViewPtr->GetOffset();
 
-        uboViews[i].reset(nullptr);
+        delete uboViews[i];
+        uboViews[i] = nullptr;
       }
       else
       {
         // If this block is NOT shared, create new uboView.
-        auto uniformBufferView = mUniformBufferManager->CreateUniformBufferView(programRequirements.blockSize[i], standaloneUniforms);
+        auto uniformBufferView = mUniformBufferManager->CreateUniformBufferView(uboViews[i], programRequirements.blockSize[i], standaloneUniforms);
 
         mUniformBufferBindings[i].buffer = uniformBufferView->GetBuffer();
         mUniformBufferBindings[i].offset = uniformBufferView->GetOffset();
 
-        uboViews[i].reset(uniformBufferView.release());
+        uboViews[i] = uniformBufferView.release();
       }
     }
   }
@@ -850,7 +863,7 @@ void Renderer::WriteUniformBuffer(
   // update the uniform buffer
   // pass shared UBO and offset, return new offset for next item to be used
   // don't process bindings if there are no uniform buffers allocated
-  if(!uboViews.empty())
+  if(!uboViews.IsEmpty())
   {
     // Write default uniforms
     WriteDefaultUniformV2(program->GetDefaultUniform(Program::DefaultUniformIndex::MODEL_MATRIX), uboViews, modelMatrix);
@@ -912,12 +925,12 @@ bool Renderer::WriteDefaultUniform(const Graphics::UniformInfo* uniformInfo, Ren
 }
 
 template<class T>
-bool Renderer::WriteDefaultUniformV2(const Graphics::UniformInfo* uniformInfo, const std::vector<std::unique_ptr<Render::UniformBufferView>>& uboViews, const T& data)
+bool Renderer::WriteDefaultUniformV2(const Graphics::UniformInfo* uniformInfo, const Render::UboViewContainer& uboViews, const T& data)
 {
   if(uniformInfo && !uniformInfo->name.empty())
   {
     // Test for non-null view first
-    auto ubo = uboViews[uniformInfo->bufferIndex].get();
+    auto* ubo = uboViews[uniformInfo->bufferIndex];
 
     if(ubo == nullptr) // Uniform belongs to shared UniformBlock, can't overwrite
     {
@@ -958,11 +971,11 @@ void Renderer::WriteUniform(Render::UniformBufferView& ubo, const Graphics::Unif
   ubo.Write(data, size, uniformInfo.offset);
 }
 
-void Renderer::FillUniformBuffer(Program&                                                       program,
-                                 const SceneGraph::RenderInstruction&                           instruction,
-                                 const std::vector<std::unique_ptr<Render::UniformBufferView>>& uboViews,
-                                 BufferIndex                                                    updateBufferIndex,
-                                 std::size_t                                                    nodeIndex)
+void Renderer::FillUniformBuffer(Program&                             program,
+                                 const SceneGraph::RenderInstruction& instruction,
+                                 const Render::UboViewContainer&      uboViews,
+                                 BufferIndex                          updateBufferIndex,
+                                 std::size_t                          nodeIndex)
 {
   for(auto& iter : mUniformIndexMaps[nodeIndex])
   {
@@ -997,7 +1010,7 @@ void Renderer::FillUniformBuffer(Program&
       }
       case UniformIndexMap::State::INITIALIZED:
       {
-        Render::UniformBufferView* ubo = uboViews[uniform.uniformBlockIndex].get();
+        auto* ubo = uboViews[uniform.uniformBlockIndex];
         if(ubo == nullptr) // Uniform belongs to shared UniformBlock, can't overwrite
         {
           uniform.state = UniformIndexMap::State::NOT_USED;
index 8336b816d905291e3743512f90e8e8ff7a4cc472..2ce51494da7ce1dec390b654793ac37e2bb82198 100644 (file)
@@ -26,6 +26,7 @@
 #include <dali/public-api/rendering/texture-set.h>
 #include <dali/public-api/signals/render-callback.h>
 
+#include <dali/devel-api/common/owner-container.h>
 #include <dali/graphics-api/graphics-controller.h>
 #include <dali/integration-api/debug.h>
 #include <dali/internal/common/blending-options.h>
@@ -67,6 +68,8 @@ using PipelineCacheL2Container = std::list<PipelineCacheL2>;
 using PipelineCachePtr         = PipelineCacheL2Container::iterator;
 
 using RendererKey = MemoryPoolKey<Render::Renderer>;
+
+using UboViewContainer = Dali::OwnerContainer<Render::UniformBufferView*>;
 } //namespace Render
 } //namespace Internal
 
@@ -124,6 +127,11 @@ public:
    */
   static void PrepareCommandBuffer();
 
+  /**
+   * @brief Global static finalize for Render::Renderer after new CommandBuffer's Render fill finished.
+   */
+  static void FinishedCommandBuffer();
+
   /**
    * Create a new renderer instance
    * @param[in] dataProviders The data providers for the renderer
@@ -500,9 +508,9 @@ public:
                            const T&                     data);
 
   template<class T>
-  bool WriteDefaultUniformV2(const Graphics::UniformInfo*                                   uniformInfo,
-                             const std::vector<std::unique_ptr<Render::UniformBufferView>>& uboViews,
-                             const T&                                                       data);
+  bool WriteDefaultUniformV2(const Graphics::UniformInfo*    uniformInfo,
+                             const Render::UboViewContainer& uboViews,
+                             const T&                        data);
 
   template<class T>
   void WriteUniform(Render::UniformBufferView&   ubo,
@@ -638,11 +646,11 @@ private:
    * @param[in] updateBufferIndex update buffer index
    * @param[in] nodeIndex Index of node/renderer pair in mUniformIndexMaps
    */
-  void FillUniformBuffer(Program&                                                       program,
-                         const SceneGraph::RenderInstruction&                           instruction,
-                         const std::vector<std::unique_ptr<Render::UniformBufferView>>& uboViews,
-                         BufferIndex                                                    updateBufferIndex,
-                         std::size_t                                                    nodeIndex);
+  void FillUniformBuffer(Program&                             program,
+                         const SceneGraph::RenderInstruction& instruction,
+                         const Render::UboViewContainer&      uboViews,
+                         BufferIndex                          updateBufferIndex,
+                         std::size_t                          nodeIndex);
 
   /**
    * @brief Write dynamic (i.e. not default) uniform into the buffer
index e9b5b485b58fbed413d4adf319c8d8177dbbb985..1935ca622c62287508333debee2c1543cd24c6b1 100644 (file)
@@ -60,7 +60,7 @@ void UniformBufferManager::SetCurrentSceneRenderInfo(SceneGraph::Scene* scene, b
   mCurrentUBOSet = FindSetForScene(scene);
 }
 
-Graphics::UniquePtr<UniformBufferView> UniformBufferManager::CreateUniformBufferView(uint32_t size, bool emulated)
+Graphics::UniquePtr<UniformBufferView> UniformBufferManager::CreateUniformBufferView(UniformBufferView*& oldView, uint32_t size, bool emulated)
 {
   // Allocate offset of given UBO (allocation strategy may reuse memory)
 
@@ -75,7 +75,7 @@ Graphics::UniquePtr<UniformBufferView> UniformBufferManager::CreateUniformBuffer
 
   // Use current offset and increment it after
   auto offset = ubo->GetCurrentOffset();
-  auto retval = Graphics::UniquePtr<UniformBufferView>(UniformBufferView::New(*ubo.get(), offset));
+  auto retval = Graphics::UniquePtr<UniformBufferView>(UniformBufferView::TryRecycle(oldView, *ubo.get(), offset));
 
   // make sure new offset will meet alignment requirements
   uint32_t alignedSize = ubo->AlignSize(size);
index c9f69033995be08bffe3ff948fdcba6c292214a2..ff235c4f6ccd54f25afddd97370d7025e57fe871 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_UNIFORM_BUFFER_MANAGER_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.
@@ -47,7 +47,7 @@ public:
 
   void ContextDestroyed();
 
-  Graphics::UniquePtr<UniformBufferView> CreateUniformBufferView(uint32_t size, bool emulated = true);
+  Graphics::UniquePtr<UniformBufferView> CreateUniformBufferView(UniformBufferView*& oldView, uint32_t size, bool emulated = true);
 
   /**
    * @brief Registers scene with the manager
index 87fe74ea461734e2aedf827eb8d85636b1daaf0d..4f6b33ed84309ff1e45e4a87227b80ef66788a03 100644 (file)
@@ -39,6 +39,19 @@ UniformBufferView* UniformBufferView::New(UniformBufferV2& ubo, uint32_t offset)
   return new(GetUboViewMemoryPool().AllocateRaw()) UniformBufferView(ubo, offset);
 }
 
+UniformBufferView* UniformBufferView::TryRecycle(UniformBufferView*& oldView, UniformBufferV2& ubo, uint32_t offset)
+{
+  auto* ptr = oldView;
+  if(ptr)
+  {
+    oldView             = nullptr;
+    ptr->mUniformBuffer = &ubo;
+    ptr->mOffset        = offset;
+    return ptr;
+  }
+  return UniformBufferView::New(ubo, offset);
+}
+
 void UniformBufferView::ResetMemoryPool()
 {
   GetUboViewMemoryPool().ResetMemoryPool();
index 1f3f90d2f39d4cc4af7e12f22cddcc9e36e6aa88..a1de275c0191c6d1f2ad43bcb5445114807725e0 100644 (file)
@@ -56,6 +56,15 @@ public:
    */
   static UniformBufferView* New(UniformBufferV2& ubo, uint32_t offset);
 
+  /**
+   * Try to recycle input view. If recycle failed, inputed view memory freed, and new UniformView created.
+   * @param[in, out] oldView The old buffer view that want to recycle. Set as nullptr after recycle done.
+   * @param[in] ubo The buffer for this view
+   * @param[in] offset The offset of this view from ubo
+   * @return A UniformBufferView that recycled, or newly created.
+   */
+  static UniformBufferView* TryRecycle(UniformBufferView*& oldView, UniformBufferV2& ubo, uint32_t offset);
+
   /**
    * Clear memory pool of UniformBufferView.
    * This should be called at the begin of Core.