Release graphics contexts before terminate graphics 31/317631/4
authorEunki, Hong <eunkiki.hong@samsung.com>
Thu, 12 Sep 2024 10:57:31 +0000 (19:57 +0900)
committerEunki, Hong <eunkiki.hong@samsung.com>
Thu, 12 Sep 2024 12:05:31 +0000 (21:05 +0900)
Since some graphics items deleted after graphics controller shutdown called,
some memory leak trace tool check they are leaking points.

More over, for offscreen application cases,
DestroyResource API was not called at terminate cases.

To make insure those are removed well,
let we call ContextDestroyed for each manager.

Change-Id: I24293d1de7b95a56fb384374c667c69bea5e4180
Signed-off-by: Eunki, Hong <eunkiki.hong@samsung.com>
13 files changed:
automated-tests/src/dali/dali-test-suite-utils/test-application.cpp
dali/internal/common/core-impl.cpp
dali/internal/render/common/render-algorithms.cpp
dali/internal/render/common/render-algorithms.h
dali/internal/render/common/render-instruction.cpp
dali/internal/render/common/render-instruction.h
dali/internal/render/common/render-manager.cpp
dali/internal/update/common/scene-graph-scene.cpp
dali/internal/update/common/scene-graph-scene.h
dali/internal/update/manager/update-manager.cpp
dali/internal/update/manager/update-manager.h
dali/internal/update/render-tasks/scene-graph-render-task.cpp
dali/internal/update/render-tasks/scene-graph-render-task.h

index 6e6b3fc7fa11e79c5c246af687f5dd805dfcd516..1fa33c453d6564af570d39350fef3527efa13d16 100644 (file)
@@ -101,6 +101,10 @@ void TestApplication::InitializeCore()
 
 TestApplication::~TestApplication()
 {
+  if(DALI_LIKELY(mCore))
+  {
+    mCore->ContextDestroyed();
+  }
   Dali::Integration::Log::UninstallLogFunction();
   delete mCore;
 }
index fbf2598d62718148cad47036107c89a2984156cc..1aafb5861ef5d063fa9ac1301576ae2498381a03 100644 (file)
@@ -185,6 +185,7 @@ void Core::ContextCreated()
 
 void Core::ContextDestroyed()
 {
+  mUpdateManager->ContextDestroyed();
   mRenderManager->ContextDestroyed();
 }
 
index ced4aebe386e5e093ee862fbcfbc2adfab2acce6..3b53f48912a1560fdb6401bfea445ed32a00378d 100644 (file)
@@ -751,6 +751,11 @@ void RenderAlgorithms::SubmitCommandBuffer()
   mGraphicsController.SubmitCommandBuffers(submitInfo);
 }
 
+void RenderAlgorithms::DestroyCommandBuffer()
+{
+  mGraphicsCommandBuffer.reset();
+}
+
 void RenderAlgorithms::ProcessRenderInstruction(const RenderInstruction&            instruction,
                                                 BufferIndex                         bufferIndex,
                                                 Integration::DepthBufferAvailable   depthBufferAvailable,
index 38b4d6d670c5750305875b364b21ec1e77b4735f..8f91964040e2fe27c54821de7bb598206ebb7340 100644 (file)
@@ -83,6 +83,11 @@ public:
    */
   void SubmitCommandBuffer();
 
+  /**
+   * @brief Destroy main command buffer (called only one time, at terminate case)
+   */
+  void DestroyCommandBuffer();
+
   /**
    * Returns main command buffer
    *
index f42041f64f21d9a9e6ab0302670f337eb02272a7..bb45f2a5aae62a9b88490dd011d4b91bdca1e0a4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
@@ -45,6 +45,12 @@ RenderInstruction::RenderInstruction()
 
 RenderInstruction::~RenderInstruction() = default;
 
+void RenderInstruction::ContextDestroyed()
+{
+  // Destroy allocated render list now.
+  mRenderLists.Clear();
+}
+
 RenderList& RenderInstruction::GetNextFreeRenderList(size_t capacityRequired)
 {
   // check if we have enough lists, we can only be one behind at worst
index ba5105073e5a33f8201c171d9a869405cd02a113..b4225fd2f807d2cab357236f9e480e89d5b08c84 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_SCENE_GRAPH_RENDER_INSTRUCTION_H
 
 /*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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,9 +57,10 @@ public:
    */
   ~RenderInstruction();
 
-  RenderInstruction(const RenderInstruction&) = delete;
-
-  RenderInstruction& operator=(const RenderInstruction& rhs) = delete;
+  /**
+   * @brief The graphics context is being shutdown. Clean down any outstanding graphics resources.
+   */
+  void ContextDestroyed();
 
   /**
    * Get the next free Renderlist
@@ -134,14 +135,18 @@ public:
    */
   std::size_t GetCapacity();
 
+private:
+  RenderInstruction(const RenderInstruction&) = delete;
+  RenderInstruction& operator=(const RenderInstruction& rhs) = delete;
+
 public:                                  // Data
   Render::RenderTracker* mRenderTracker; ///< Pointer to an optional tracker object (not owned)
 
-  Viewport mViewport;                    ///< Optional viewport
-  Vector4  mClearColor;                  ///< Optional color to clear with
-  bool     mIsViewportSet : 1;           ///< Flag to determine whether the viewport is set
-  bool     mIsClearColorSet : 1;         ///< Flag to determine whether the clearColor is set
-  bool     mIgnoreRenderToFbo : 1;       ///< Whether to ignore the render to FBO option (used to measure the performance above 60 fps)
+  Viewport mViewport;              ///< Optional viewport
+  Vector4  mClearColor;            ///< Optional color to clear with
+  bool     mIsViewportSet : 1;     ///< Flag to determine whether the viewport is set
+  bool     mIsClearColorSet : 1;   ///< Flag to determine whether the clearColor is set
+  bool     mIgnoreRenderToFbo : 1; ///< Whether to ignore the render to FBO option (used to measure the performance above 60 fps)
 
   Render::FrameBuffer* mFrameBuffer;
   uint32_t             mRenderPassTag{0u};
index aca9fece738644c89e79a08b9690c8b76be65568..4f72d397ce79a5b87ed3aae3454f22b52bd4107b 100644 (file)
@@ -259,6 +259,37 @@ struct RenderManager::Impl
     }
   }
 
+  /**
+   * @brief Remove all owned render context.
+   *
+   * @note Should be called at ContextDestroyed case.
+   */
+  void ContextDestroyed()
+  {
+    sceneContainer.clear();
+    renderAlgorithms.DestroyCommandBuffer();
+
+    samplerContainer.Clear();
+    frameBufferContainer.Clear();
+    vertexBufferContainer.Clear();
+    geometryContainer.Clear();
+    rendererContainer.Clear();
+    textureContainer.Clear();
+
+    mRenderTrackers.Clear();
+
+    updatedTextures.Clear();
+    textureDiscardQueue.Clear();
+
+    pipelineCache.reset(); // clear now before the program contoller is deleted
+
+    if(DALI_LIKELY(uniformBufferManager))
+    {
+      uniformBufferManager->ContextDestroyed();
+    }
+    uniformBufferManager.reset();
+  }
+
   // the order is important for destruction,
   Graphics::Controller&           graphicsController;
   RenderQueue                     renderQueue;      ///< A message queue for receiving messages from the update-thread.
@@ -333,7 +364,24 @@ RenderManager::~RenderManager()
 
 void RenderManager::ContextDestroyed()
 {
-  mImpl->uniformBufferManager->ContextDestroyed();
+  // Call Destroy for some items.
+  for(auto&& item : mImpl->frameBufferContainer)
+  {
+    if(DALI_LIKELY(item))
+    {
+      item->Destroy();
+    }
+  }
+  for(auto&& item : mImpl->textureContainer)
+  {
+    if(DALI_LIKELY(item))
+    {
+      item->Destroy();
+    }
+  }
+
+  // Remove owned render context
+  mImpl->ContextDestroyed();
 }
 
 RenderQueue& RenderManager::GetRenderQueue()
index c03e831fd2d47c038eca55e13c9928b84f1f5a82..530f39b98d73837027340602178783fc0191c4e8 100644 (file)
@@ -106,6 +106,14 @@ void Scene::Initialize(Graphics::Controller& graphicsController, Integration::De
   mRenderPassNoClear = graphicsController.CreateRenderPass(rpInfo, nullptr);
 }
 
+void Scene::ContextDestroyed()
+{
+  mRenderPass.reset();
+  mRenderPassNoClear.reset();
+
+  mRenderTarget.reset();
+}
+
 RenderInstructionContainer& Scene::GetRenderInstructions()
 {
   return mInstructions;
index 1d2b6d92c2129bcb27465650e0c451c3a9eb3f9a..3df3b00f398a919c2ae89370ad327a92031bc723 100644 (file)
@@ -137,6 +137,11 @@ public:
    */
   void Initialize(Graphics::Controller& graphicsController, Integration::DepthBufferAvailable depthBufferAvailable, Integration::StencilBufferAvailable stencilBufferAvailable);
 
+  /**
+   * @brief The graphics context is being shutdown. Clean down any outstanding graphics resources.
+   */
+  void ContextDestroyed();
+
   /**
    * Gets the render instructions for the scene
    * @return the render instructions
index 296e897e7988f6dcd2d1ae301b0b9012bc299fb0..2e329faa79c0e2b1a4a7bce67a1333447da77869 100644 (file)
@@ -295,6 +295,34 @@ struct UpdateManager::Impl
     return *frameCallbackProcessor;
   }
 
+  /**
+   * @brief Remove all owned render context at scene.
+   *
+   * @note Should be called at ContextDestroyed case.
+   */
+  void ContextDestroyed()
+  {
+    // Disconnect render tasks from nodes, before destroying the nodes
+    for(auto&& scene : scenes)
+    {
+      if(scene)
+      {
+        if(scene->scene)
+        {
+          scene->scene->ContextDestroyed();
+        }
+        if(scene->taskList)
+        {
+          RenderTaskList::RenderTaskContainer& tasks = scene->taskList->GetTasks();
+          for(auto&& task : tasks)
+          {
+            task->ContextDestroyed();
+          }
+        }
+      }
+    }
+  }
+
   SceneGraphBuffers              sceneGraphBuffers;       ///< Used to keep track of which buffers are being written or read
   RenderMessageDispatcher        renderMessageDispatcher; ///< Used for passing messages to the render-thread
   NotificationManager&           notificationManager;     ///< Queues notification messages for the event-thread.
@@ -416,6 +444,12 @@ UpdateManager::~UpdateManager()
   TextureSet::ResetMemoryPool();
 }
 
+void UpdateManager::ContextDestroyed()
+{
+  // Remove owned update context
+  mImpl->ContextDestroyed();
+}
+
 void UpdateManager::InstallRoot(OwnerPointer<Layer>& layer)
 {
   DALI_ASSERT_DEBUG(layer->IsLayer());
index 64e096cb20b7eac9b073f3da688b1966d293ca50..241a75ae2b259a31d484872bc2aa6ca3e99038f0 100644 (file)
@@ -127,6 +127,11 @@ public:
    */
   ~UpdateManager() override;
 
+  /**
+   * @brief The graphics context is being shutdown. Clean down any outstanding graphics resources.
+   */
+  void ContextDestroyed();
+
   // Node connection methods
 
   /**
index 7fbba3d7412402b4034f5e84bbb5e2f04448369a..8044497fffccfb2be1508cda7d5cda290efc8a74 100644 (file)
@@ -57,7 +57,10 @@ RenderTask::~RenderTask()
   }
   if(mRenderSyncTracker)
   {
-    mRenderMessageDispatcher->RemoveRenderTracker(*mRenderSyncTracker);
+    if(DALI_LIKELY(mRenderMessageDispatcher))
+    {
+      mRenderMessageDispatcher->RemoveRenderTracker(*mRenderSyncTracker);
+    }
   }
 }
 
@@ -389,6 +392,8 @@ RenderInstruction& RenderTask::PrepareRenderInstruction(BufferIndex updateBuffer
     // create tracker if one doesn't yet exist.
     if(!mRenderSyncTracker)
     {
+      DALI_ASSERT_ALWAYS(mRenderMessageDispatcher && "We don't allow to call PrepareRenderInstruction after Graphics context destroyed!");
+
       mRenderSyncTracker = new Render::RenderTracker();
       mRenderMessageDispatcher->AddRenderTracker(*mRenderSyncTracker);
     }
@@ -468,6 +473,18 @@ void RenderTask::SetRenderPassTag(uint32_t renderPassTag)
   mRenderPassTag = renderPassTag;
 }
 
+void RenderTask::ContextDestroyed()
+{
+  // Note : We don't need to call RemoveRenderTracker in this case.
+  // (Since RenderManager::ContextDestroyed will delete it.)
+  mRenderSyncTracker = nullptr;
+
+  mRenderMessageDispatcher = nullptr;
+
+  mRenderInstruction[0].ContextDestroyed();
+  mRenderInstruction[1].ContextDestroyed();
+}
+
 void RenderTask::PropertyOwnerConnected(PropertyOwner& owner)
 {
   // check if we've gone from inactive to active
index 6099aeaab27645cc8c4fcfe308d619ec6b5e6f56..909109d5d113a3ec6c9644954907406a50e87abc 100644 (file)
@@ -374,6 +374,11 @@ public:
    */
   void SetRenderPassTag(uint32_t renderPassTag);
 
+  /**
+   * @brief The graphics context is being shutdown. Clean down any outstanding graphics resources.
+   */
+  void ContextDestroyed();
+
 private: // from PropertyOwner::Observer
   /**
    * @copydoc PropertyOwner::Observer::PropertyOwnerConnected( PropertyOwner& owner )