TestApplication::~TestApplication()
{
+ if(DALI_LIKELY(mCore))
+ {
+ mCore->ContextDestroyed();
+ }
Dali::Integration::Log::UninstallLogFunction();
delete mCore;
}
void Core::ContextDestroyed()
{
+ mUpdateManager->ContextDestroyed();
mRenderManager->ContextDestroyed();
}
mGraphicsController.SubmitCommandBuffers(submitInfo);
}
+void RenderAlgorithms::DestroyCommandBuffer()
+{
+ mGraphicsCommandBuffer.reset();
+}
+
void RenderAlgorithms::ProcessRenderInstruction(const RenderInstruction& instruction,
BufferIndex bufferIndex,
Integration::DepthBufferAvailable depthBufferAvailable,
*/
void SubmitCommandBuffer();
+ /**
+ * @brief Destroy main command buffer (called only one time, at terminate case)
+ */
+ void DestroyCommandBuffer();
+
/**
* Returns main command buffer
*
/*
- * 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.
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
#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.
*/
~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
*/
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};
}
}
+ /**
+ * @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.
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()
mRenderPassNoClear = graphicsController.CreateRenderPass(rpInfo, nullptr);
}
+void Scene::ContextDestroyed()
+{
+ mRenderPass.reset();
+ mRenderPassNoClear.reset();
+
+ mRenderTarget.reset();
+}
+
RenderInstructionContainer& Scene::GetRenderInstructions()
{
return mInstructions;
*/
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
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.
TextureSet::ResetMemoryPool();
}
+void UpdateManager::ContextDestroyed()
+{
+ // Remove owned update context
+ mImpl->ContextDestroyed();
+}
+
void UpdateManager::InstallRoot(OwnerPointer<Layer>& layer)
{
DALI_ASSERT_DEBUG(layer->IsLayer());
*/
~UpdateManager() override;
+ /**
+ * @brief The graphics context is being shutdown. Clean down any outstanding graphics resources.
+ */
+ void ContextDestroyed();
+
// Node connection methods
/**
}
if(mRenderSyncTracker)
{
- mRenderMessageDispatcher->RemoveRenderTracker(*mRenderSyncTracker);
+ if(DALI_LIKELY(mRenderMessageDispatcher))
+ {
+ mRenderMessageDispatcher->RemoveRenderTracker(*mRenderSyncTracker);
+ }
}
}
// 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);
}
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
*/
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 )