From: David Steele Date: Thu, 22 Sep 2022 10:04:26 +0000 (+0100) Subject: Added memory pool logging X-Git-Tag: dali_2.2.7~11^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c8e0d2807617b0ba441ae67e735512bf6f3c1c68;p=platform%2Fcore%2Fuifw%2Fdali-core.git Added memory pool logging Added methods to fetch the current capacity of memory pools Added a method to Core to dump the capacities to the log output (This is triggered by setting DALI_MEMORY_POOL_INTERVAL to a non-zero value) Added logging to PixelData to log individual allocations (By setting DALI_LOG_PIXEL_DATA_SIZE to "1" or higher and enabling debug). Added method to PixelData to log total allocation (By setting DALI_OBJECT_PROFILER_INTERVAL to a non-zero value and enabling debug). Change-Id: I45220005a652ca978ea552dd93564bedad784ba7 --- diff --git a/automated-tests/src/dali/utc-Dali-Core.cpp b/automated-tests/src/dali/utc-Dali-Core.cpp index 67d14a5..ae881b2 100644 --- a/automated-tests/src/dali/utc-Dali-Core.cpp +++ b/automated-tests/src/dali/utc-Dali-Core.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * Copyright (c) 2022 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. @@ -50,3 +50,14 @@ int UtcDaliCoreGetObjectRegistry(void) DALI_TEST_CHECK(application.GetCore().GetObjectRegistry()); END_TEST; } + +int UtcDaliCoreCheckMemoryPool(void) +{ + TestApplication application; + + // Calling LogMemoryPools should check capacity across the board. + application.GetCore().LogMemoryPools(); + + tet_result(TET_PASS); + END_TEST; +} diff --git a/dali/integration-api/core.cpp b/dali/integration-api/core.cpp index 05f6d52..870861b 100644 --- a/dali/integration-api/core.cpp +++ b/dali/integration-api/core.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * Copyright (c) 2022 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,6 +145,11 @@ ObjectRegistry Core::GetObjectRegistry() const return ObjectRegistry(&mImpl->GetObjectRegistry()); } +void Core::LogMemoryPools() const +{ + mImpl->LogMemoryPools(); +} + Core::Core() : mImpl(nullptr) { diff --git a/dali/integration-api/core.h b/dali/integration-api/core.h index 0a4ce07..0b44348 100644 --- a/dali/integration-api/core.h +++ b/dali/integration-api/core.h @@ -2,7 +2,7 @@ #define DALI_INTEGRATION_CORE_H /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * Copyright (c) 2022 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. @@ -409,6 +409,11 @@ public: */ ObjectRegistry GetObjectRegistry() const; + /** + * Log core's memory pool's capacities + */ + void LogMemoryPools() const; + private: /** * Private constructor; see also Core::New() diff --git a/dali/internal/common/core-impl.cpp b/dali/internal/common/core-impl.cpp index 9a5c89e..28b8a6c 100644 --- a/dali/internal/common/core-impl.cpp +++ b/dali/internal/common/core-impl.cpp @@ -138,6 +138,10 @@ Core::Core(RenderController& renderController, mUpdateManager->SetShaderSaver(*mShaderFactory); GetImplementation(Dali::TypeRegistry::Get()).CallInitFunctions(); + + DALI_LOG_RELEASE_INFO("Node size: %lu\n", sizeof(Dali::Internal::SceneGraph::Node)); + DALI_LOG_RELEASE_INFO("Renderer size: %lu\n", sizeof(Dali::Internal::SceneGraph::Renderer)); + DALI_LOG_RELEASE_INFO("RenderItem size: %lu\n", sizeof(Dali::Internal::SceneGraph::RenderItem)); } Core::~Core() @@ -484,6 +488,47 @@ ObjectRegistry& Core::GetObjectRegistry() const return *(mObjectRegistry.Get()); } +void Core::LogMemoryPools() const +{ + uint32_t animationPoolCapacity = SceneGraph::Animation::GetMemoryPoolCapacity(); + uint32_t renderItemPoolCapacity = SceneGraph::RenderItem::GetMemoryPoolCapacity(); + uint32_t relayoutItemPoolCapacity = mRelayoutController->GetMemoryPoolCapacity(); + uint32_t rendererPoolCapacity = SceneGraph::Renderer::GetMemoryPoolCapacity(); + uint32_t textureSetPoolCapacity = SceneGraph::TextureSet::GetMemoryPoolCapacity(); + uint32_t renderTaskPoolCapacity = SceneGraph::RenderTaskList::GetMemoryPoolCapacity(); + uint32_t nodePoolCapacity = SceneGraph::Node::GetMemoryPoolCapacity(); + + DALI_LOG_RELEASE_INFO( + "\nMemory Pool capacities:\n" + " Animations: %lu\n" + " RenderItems: %lu\n" + " RelayoutItems: %lu\n" + " Renderers: %lu\n" + " TextureSets: %lu\n" + " RenderTasks: %lu\n" + " Nodes: %lu\n", + animationPoolCapacity, + renderItemPoolCapacity, + relayoutItemPoolCapacity, + rendererPoolCapacity, + textureSetPoolCapacity, + renderTaskPoolCapacity, + nodePoolCapacity); + + uint32_t updateQCapacity = mUpdateManager->GetUpdateMessageQueueCapacity(); + uint32_t renderQCapacity = mUpdateManager->GetRenderMessageQueueCapacity(); + + DALI_LOG_RELEASE_INFO( + "\nMessage Queue capacities:\n" + " UpdateQueue: %lu\n" + " RenderQueue: %lu\n", + updateQCapacity, + renderQCapacity); + + size_t renderInstructionCapacity = mUpdateManager->GetRenderInstructionCapacity(); + DALI_LOG_RELEASE_INFO("\nRenderInstruction capacity: %lu\n", renderInstructionCapacity); +} + EventThreadServices& Core::GetEventThreadServices() { return *this; diff --git a/dali/internal/common/core-impl.h b/dali/internal/common/core-impl.h index 8d218aa..5c21a44 100644 --- a/dali/internal/common/core-impl.h +++ b/dali/internal/common/core-impl.h @@ -198,6 +198,11 @@ public: */ ObjectRegistry& GetObjectRegistry() const; + /** + * Log the capacity of DALi memory pools + */ + void LogMemoryPools() const; + public: // Implementation of EventThreadServices /** * @copydoc EventThreadServices::RegisterObject diff --git a/dali/internal/common/fixed-size-memory-pool.cpp b/dali/internal/common/fixed-size-memory-pool.cpp index 452437c..f225a8d 100644 --- a/dali/internal/common/fixed-size-memory-pool.cpp +++ b/dali/internal/common/fixed-size-memory-pool.cpp @@ -231,6 +231,22 @@ void FixedSizeMemoryPool::FreeThreadSafe(void* memory) } } +uint32_t FixedSizeMemoryPool::GetCapacity() const +{ + // Ignores deleted objects list, just returns currently allocated size + uint32_t totalAllocation = 0; +#ifdef DEBUG_ENABLED + Mutex::ScopedLock lock(mImpl->mMutex); + Impl::Block* block = &mImpl->mMemoryBlocks; + while(block) + { + totalAllocation += block->mBlockSize; + block = block->nextBlock; + } +#endif + return totalAllocation; +} + } // namespace Internal } // namespace Dali diff --git a/dali/internal/common/fixed-size-memory-pool.h b/dali/internal/common/fixed-size-memory-pool.h index ff4138d..6e05ffe 100644 --- a/dali/internal/common/fixed-size-memory-pool.h +++ b/dali/internal/common/fixed-size-memory-pool.h @@ -2,7 +2,7 @@ #define DALI_INTERNAL_FIXED_SIZE_MEMORY_POOL_H /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * Copyright (c) 2022 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,13 @@ public: */ void FreeThreadSafe(void* memory); + /** + * Get the current capacity of the memory pool + * + * @note in release mode, this returns 0, as the block size isn't defined. + */ + uint32_t GetCapacity() const; + private: // Undefined FixedSizeMemoryPool(const FixedSizeMemoryPool& fixedSizeMemoryPool); diff --git a/dali/internal/common/memory-pool-object-allocator.h b/dali/internal/common/memory-pool-object-allocator.h index 7b6ab96..554ce9a 100644 --- a/dali/internal/common/memory-pool-object-allocator.h +++ b/dali/internal/common/memory-pool-object-allocator.h @@ -2,7 +2,7 @@ #define DALI_INTERNAL_MEMORY_POOL_OBJECT_ALLOCATOR_H /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * Copyright (c) 2022 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. @@ -154,6 +154,14 @@ public: mPool = new FixedSizeMemoryPool(TypeSizeWithAlignment::size); } + /** + * @brief Get the capacity of the memory pool + */ + uint32_t GetCapacity() const + { + return mPool->GetCapacity(); + } + private: // Undefined MemoryPoolObjectAllocator(const MemoryPoolObjectAllocator& memoryPoolObjectAllocator); diff --git a/dali/internal/event/images/pixel-data-impl.cpp b/dali/internal/event/images/pixel-data-impl.cpp index 622f867..745896a 100644 --- a/dali/internal/event/images/pixel-data-impl.cpp +++ b/dali/internal/event/images/pixel-data-impl.cpp @@ -18,10 +18,21 @@ // CLASS HEADER #include +#include + +#if defined(DEBUG_ENABLED) +Debug::Filter* gPixelDataLogFilter = Debug::Filter::New(Debug::NoLogging, false, "DALI_LOG_PIXEL_DATA_SIZE"); +#endif + namespace Dali { namespace Internal { +#if defined(DEBUG_ENABLED) +// Only track data allocation if debug is enabled +uint32_t PixelData::gPixelDataAllocationTotal{0}; +#endif + PixelData::PixelData(uint8_t* buffer, uint32_t bufferSize, uint32_t width, @@ -37,6 +48,10 @@ PixelData::PixelData(uint8_t* buffer, mPixelFormat(pixelFormat), mReleaseFunction(releaseFunction) { + DALI_LOG_INFO(gPixelDataLogFilter, Debug::Concise, "Allocated PixelData of size %u\n", bufferSize); +#if defined(DEBUG_ENABLED) + gPixelDataAllocationTotal += mBufferSize; +#endif } PixelData::~PixelData() @@ -51,6 +66,9 @@ PixelData::~PixelData() { delete[] mBuffer; } +#if defined(DEBUG_ENABLED) + gPixelDataAllocationTotal -= mBufferSize; +#endif } } diff --git a/dali/internal/event/images/pixel-data-impl.h b/dali/internal/event/images/pixel-data-impl.h index 5667496..746d347 100644 --- a/dali/internal/event/images/pixel-data-impl.h +++ b/dali/internal/event/images/pixel-data-impl.h @@ -20,6 +20,7 @@ // INTERNAL INCLUDES #include +#include #include #include @@ -121,6 +122,18 @@ public: */ uint32_t GetStride() const; + /** + * Class method to get the total currently allocated size of pixel buffers + */ + static uint32_t GetTotalAllocatedSize() + { +#if defined(DEBUG_ENABLED) + return gPixelDataAllocationTotal; +#else + return 0; +#endif + } + private: /* * Undefined copy constructor. @@ -140,6 +153,10 @@ private: uint32_t mStride; ///< Buffer stride in pixels, 0 means the buffer is tightly packed Pixel::Format mPixelFormat; ///< Pixel format Dali::PixelData::ReleaseFunction mReleaseFunction; ///< Function for releasing memory + +#if defined(DEBUG_ENABLED) + static uint32_t gPixelDataAllocationTotal; +#endif }; } // namespace Internal diff --git a/dali/internal/event/size-negotiation/relayout-controller-impl.cpp b/dali/internal/event/size-negotiation/relayout-controller-impl.cpp index 1589d94..dd0f98d 100644 --- a/dali/internal/event/size-negotiation/relayout-controller-impl.cpp +++ b/dali/internal/event/size-negotiation/relayout-controller-impl.cpp @@ -500,6 +500,11 @@ void RelayoutController::FindAndZero(const RawActorList& list, const Dali::RefOb } } +uint32_t RelayoutController::GetMemoryPoolCapacity() +{ + return mRelayoutInfoAllocator.GetCapacity(); +} + } // namespace Internal } // namespace Dali diff --git a/dali/internal/event/size-negotiation/relayout-controller-impl.h b/dali/internal/event/size-negotiation/relayout-controller-impl.h index 85cb31a..29809ea 100644 --- a/dali/internal/event/size-negotiation/relayout-controller-impl.h +++ b/dali/internal/event/size-negotiation/relayout-controller-impl.h @@ -2,7 +2,7 @@ #define DALI_INTERNAL_RELAYOUT_CONTROLLER_IMPL_H /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * Copyright (c) 2022 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. @@ -124,6 +124,12 @@ public: */ void SetProcessingCoreEvents(bool processingEvents); + /** + * Get the capacity of the memory pool containing relayout info + * (It Should be regularly purged!) + */ + uint32_t GetMemoryPoolCapacity(); + public: // CALLBACKS /** * @brief Callback raised after the application creates the scene diff --git a/dali/internal/render/common/render-instruction-container.cpp b/dali/internal/render/common/render-instruction-container.cpp index 6ae3c5b..37900ed 100644 --- a/dali/internal/render/common/render-instruction-container.cpp +++ b/dali/internal/render/common/render-instruction-container.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * Copyright (c) 2022 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. @@ -62,6 +62,17 @@ void RenderInstructionContainer::PushBack(BufferIndex bufferIndex, RenderInstruc mInstructions.push_back(renderInstruction); } +std::size_t RenderInstructionContainer::GetCapacity() const +{ + std::size_t capacity{0}; + for(auto& el : mInstructions) + { + capacity += el->GetCapacity(); + } + capacity += mInstructions.size() * sizeof(RenderInstruction*); + return capacity; +} + } // namespace SceneGraph } // namespace Internal diff --git a/dali/internal/render/common/render-instruction-container.h b/dali/internal/render/common/render-instruction-container.h index 9417afe..f2292c7 100644 --- a/dali/internal/render/common/render-instruction-container.h +++ b/dali/internal/render/common/render-instruction-container.h @@ -2,7 +2,7 @@ #define DALI_INTERNAL_SCENE_GRAPH_RENDER_INSTRUCTION_CONTAINER_H /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * Copyright (c) 2022 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. @@ -22,6 +22,7 @@ #include #include #include +#include namespace Dali { @@ -75,6 +76,11 @@ public: */ void PushBack(BufferIndex index, RenderInstruction* renderInstruction); + /** + * Get the total memory used by all the render instructions + */ + std::size_t GetCapacity() const; + private: std::vector mInstructions; }; diff --git a/dali/internal/render/common/render-instruction.cpp b/dali/internal/render/common/render-instruction.cpp index acde57b..f42041f 100644 --- a/dali/internal/render/common/render-instruction.cpp +++ b/dali/internal/render/common/render-instruction.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * Copyright (c) 2022 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. @@ -125,6 +125,20 @@ void RenderInstruction::Reset(Camera* camera, } } +std::size_t RenderInstruction::GetCapacity() +{ + std::size_t capacity{0u}; + RenderListContainer::Iterator iter = mRenderLists.Begin(); + RenderListContainer::ConstIterator end = mRenderLists.End(); + for(; iter != end; ++iter) + { + capacity += ((*iter)->GetCachedItemCount() * (sizeof(RenderItem) + sizeof(RenderItem*))); + capacity += sizeof(RenderList); + } + capacity += sizeof(RenderInstruction); + return capacity; +} + } // namespace SceneGraph } // namespace Internal diff --git a/dali/internal/render/common/render-instruction.h b/dali/internal/render/common/render-instruction.h index 52e7e68..f8d24aa 100644 --- a/dali/internal/render/common/render-instruction.h +++ b/dali/internal/render/common/render-instruction.h @@ -2,7 +2,7 @@ #define DALI_INTERNAL_SCENE_GRAPH_RENDER_INSTRUCTION_H /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * Copyright (c) 2022 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. @@ -129,6 +129,11 @@ public: return mCamera; } + /** + * Get the total memory usage of the render instruction + */ + std::size_t GetCapacity(); + public: // Data Render::RenderTracker* mRenderTracker; ///< Pointer to an optional tracker object (not owned) diff --git a/dali/internal/render/common/render-item.cpp b/dali/internal/render/common/render-item.cpp index 9b3ba8c..cc68d34 100644 --- a/dali/internal/render/common/render-item.cpp +++ b/dali/internal/render/common/render-item.cpp @@ -168,6 +168,11 @@ void RenderItem::operator delete(void* ptr) gRenderItemPool.Free(static_cast(ptr)); } +uint32_t RenderItem::GetMemoryPoolCapacity() +{ + return gRenderItemPool.GetCapacity(); +} + } // namespace SceneGraph } // namespace Internal diff --git a/dali/internal/render/common/render-item.h b/dali/internal/render/common/render-item.h index d1ca0f4..4a4bf2b 100644 --- a/dali/internal/render/common/render-item.h +++ b/dali/internal/render/common/render-item.h @@ -100,6 +100,11 @@ struct RenderItem bool mIsOpaque : 1; bool mIsUpdated : 1; + /** + * Get the capacity of the global pool. + */ + static uint32_t GetMemoryPoolCapacity(); + private: /** * Private constructor. See RenderItem::New diff --git a/dali/internal/render/queue/render-queue.cpp b/dali/internal/render/queue/render-queue.cpp index 49cd12f..ca582ba 100644 --- a/dali/internal/render/queue/render-queue.cpp +++ b/dali/internal/render/queue/render-queue.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * Copyright (c) 2022 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. @@ -80,6 +80,9 @@ uint32_t* RenderQueue::ReserveMessageSlot(BufferIndex updateBufferIndex, std::si void RenderQueue::ProcessMessages(BufferIndex bufferIndex) { + std::size_t capacity = container0->GetCapacity() + container1->GetCapacity(); + mCapacity = capacity; // write is atomic. + MessageBuffer* container = GetCurrentContainer(bufferIndex); for(MessageBuffer::Iterator iter = container->Begin(); iter.IsValid(); iter.Next()) diff --git a/dali/internal/render/queue/render-queue.h b/dali/internal/render/queue/render-queue.h index 4739889..0df8060 100644 --- a/dali/internal/render/queue/render-queue.h +++ b/dali/internal/render/queue/render-queue.h @@ -2,7 +2,7 @@ #define DALI_INTERNAL_SCENE_GRAPH_RENDER_QUEUE_H /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * Copyright (c) 2022 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. @@ -21,6 +21,8 @@ // INTERNAL INCLUDES #include #include +#include +#include namespace Dali { @@ -63,6 +65,14 @@ public: */ void ProcessMessages(BufferIndex bufferIndex); + /** + * Return the current capacity total of both buffers. + */ + std::size_t GetCapacity() const + { + return mCapacity; + } + private: /** * Helper to retrieve the current container. @@ -87,6 +97,8 @@ private: private: MessageBuffer* container0; ///< Messages are queued here when the update buffer index == 0 MessageBuffer* container1; ///< Messages are queued here when the update buffer index == 1 + + std::atomic mCapacity{0u}; // Current total capacity of both buffers. }; } // namespace SceneGraph diff --git a/dali/internal/update/animation/scene-graph-animation.cpp b/dali/internal/update/animation/scene-graph-animation.cpp index 49268b6..d75199a 100644 --- a/dali/internal/update/animation/scene-graph-animation.cpp +++ b/dali/internal/update/animation/scene-graph-animation.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * Copyright (c) 2022 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. @@ -484,6 +484,11 @@ void Animation::UpdateAnimators(BufferIndex bufferIndex, bool bake, bool animati } } +uint32_t Animation::GetMemoryPoolCapacity() +{ + return gAnimationMemoryPool.GetCapacity(); +} + } // namespace SceneGraph } // namespace Internal diff --git a/dali/internal/update/animation/scene-graph-animation.h b/dali/internal/update/animation/scene-graph-animation.h index cebcb2e..4119c15 100644 --- a/dali/internal/update/animation/scene-graph-animation.h +++ b/dali/internal/update/animation/scene-graph-animation.h @@ -2,7 +2,7 @@ #define DALI_INTERNAL_SCENE_GRAPH_ANIMATION_H /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * Copyright (c) 2022 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. @@ -292,6 +292,8 @@ public: */ void Update(BufferIndex bufferIndex, float elapsedSeconds, bool& looped, bool& finished, bool& progressReached); + static uint32_t GetMemoryPoolCapacity(); + protected: /** * Protected constructor. See New() diff --git a/dali/internal/update/manager/update-manager.cpp b/dali/internal/update/manager/update-manager.cpp index 1b5c1a3..2873011 100644 --- a/dali/internal/update/manager/update-manager.cpp +++ b/dali/internal/update/manager/update-manager.cpp @@ -112,7 +112,8 @@ inline void EraseUsingDiscardQueue(OwnerContainer& container, T* object, Dis void SortSiblingNodesRecursively(Node& node) { NodeContainer& container = node.GetChildren(); - std::sort(container.Begin(), container.End(), [](Node* a, Node* b) { return a->GetDepthIndex() < b->GetDepthIndex(); }); + std::sort(container.Begin(), container.End(), [](Node* a, Node* b) + { return a->GetDepthIndex() < b->GetDepthIndex(); }); // Descend tree and sort as well for(auto&& iter : container) @@ -136,11 +137,11 @@ struct UpdateManager::Impl { } - ~SceneInfo() = default; ///< Default non-virtual destructor - SceneInfo(SceneInfo&& rhs) = default; ///< Move constructor - SceneInfo& operator=(SceneInfo&& rhs) = default; ///< Move assignment operator - SceneInfo& operator=(const SceneInfo& rhs) = delete; ///< Assignment operator - SceneInfo(const SceneInfo& rhs) = delete; ///< Copy constructor + ~SceneInfo() = default; ///< Default non-virtual destructor + SceneInfo(SceneInfo&& rhs) = default; ///< Move constructor + SceneInfo& operator=(SceneInfo&& rhs) = default; ///< Move assignment operator + SceneInfo& operator=(const SceneInfo& rhs) = delete; ///< Assignment operator + SceneInfo(const SceneInfo& rhs) = delete; ///< Copy constructor Layer* root{nullptr}; ///< Root node (root is a layer). The layer is not stored in the node memory pool. OwnerPointer taskList; ///< Scene graph render task list @@ -288,11 +289,11 @@ struct UpdateManager::Impl OwnerPointer frameCallbackProcessor; ///< Owned FrameCallbackProcessor, only created if required. - float keepRenderingSeconds; ///< Set via Dali::Stage::KeepRendering - NodePropertyFlags nodeDirtyFlags; ///< cumulative node dirty flags from previous frame - uint32_t frameCounter; ///< Frame counter used in debugging to choose which frame to debug and which to ignore. - - DevelStage::Rendering renderingBehavior; ///< Set via DevelStage::SetRenderingBehavior + std::atomic renderInstructionCapacity{0u}; + float keepRenderingSeconds; ///< Set via Dali::Stage::KeepRendering + NodePropertyFlags nodeDirtyFlags; ///< cumulative node dirty flags from previous frame + uint32_t frameCounter; ///< Frame counter used in debugging to choose which frame to debug and which to ignore. + DevelStage::Rendering renderingBehavior; ///< Set via DevelStage::SetRenderingBehavior bool animationFinishedDuringUpdate; ///< Flag whether any animations finished during the Update() bool previousUpdateScene; ///< True if the scene was updated in the previous frame (otherwise it was optimized out) @@ -338,9 +339,8 @@ void UpdateManager::InstallRoot(OwnerPointer& layer) Layer* rootLayer = layer.Release(); - DALI_ASSERT_DEBUG(std::find_if(mImpl->scenes.begin(), mImpl->scenes.end(), [rootLayer](Impl::SceneInfoPtr& scene) { - return scene && scene->root == rootLayer; - }) == mImpl->scenes.end() && + DALI_ASSERT_DEBUG(std::find_if(mImpl->scenes.begin(), mImpl->scenes.end(), [rootLayer](Impl::SceneInfoPtr& scene) + { return scene && scene->root == rootLayer; }) == mImpl->scenes.end() && "Root Node already installed"); rootLayer->CreateTransform(&mImpl->transformManager); @@ -690,6 +690,21 @@ uint32_t* UpdateManager::ReserveMessageSlot(uint32_t size, bool updateScene) return mImpl->messageQueue.ReserveMessageSlot(size, updateScene); } +std::size_t UpdateManager::GetUpdateMessageQueueCapacity() const +{ + return mImpl->messageQueue.GetCapacity(); +} + +std::size_t UpdateManager::GetRenderMessageQueueCapacity() const +{ + return mImpl->renderQueue.GetCapacity(); +} + +std::size_t UpdateManager::GetRenderInstructionCapacity() const +{ + return mImpl->renderInstructionCapacity; +} + void UpdateManager::EventProcessingStarted() { mImpl->messageQueue.EventProcessingStarted(); @@ -817,7 +832,7 @@ bool UpdateManager::Animate(BufferIndex bufferIndex, float elapsedSeconds) void UpdateManager::ConstrainCustomObjects(BufferIndex bufferIndex) { - //Constrain custom objects (in construction order) + // Constrain custom objects (in construction order) for(auto&& object : mImpl->customObjects) { ConstrainPropertyOwner(*object, bufferIndex); @@ -890,7 +905,7 @@ void UpdateManager::UpdateRenderers(BufferIndex bufferIndex) { for(auto&& renderer : mImpl->renderers) { - //Apply constraints + // Apply constraints ConstrainPropertyOwner(*renderer, bufferIndex); mImpl->renderingRequired = renderer->PrepareRender(bufferIndex) || mImpl->renderingRequired; @@ -934,12 +949,12 @@ uint32_t UpdateManager::Update(float elapsedSeconds, { const BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex(); - //Clear nodes/resources which were previously discarded + // Clear nodes/resources which were previously discarded mImpl->discardQueue.Clear(bufferIndex); bool isAnimationRunning = IsAnimationRunning(); - //Process Touches & Gestures + // Process Touches & Gestures const bool gestureUpdated = ProcessGestures(bufferIndex, lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds); bool updateScene = // The scene-graph requires an update if.. @@ -956,7 +971,7 @@ uint32_t UpdateManager::Update(float elapsedSeconds, // values if the scene was updated in the previous frame. if(updateScene || mImpl->previousUpdateScene) { - //Reset properties from the previous update + // Reset properties from the previous update ResetProperties(bufferIndex); mImpl->transformManager.ResetToBaseValue(); } @@ -966,7 +981,7 @@ uint32_t UpdateManager::Update(float elapsedSeconds, // be set again updateScene |= mImpl->messageQueue.ProcessMessages(bufferIndex); - //Forward compiled shader programs to event thread for saving + // Forward compiled shader programs to event thread for saving ForwardCompiledShadersToEventThread(); // Although the scene-graph may not require an update, we still need to synchronize double-buffered @@ -974,13 +989,13 @@ uint32_t UpdateManager::Update(float elapsedSeconds, // We should not start skipping update steps or reusing lists until there has been two frames where nothing changes if(updateScene || mImpl->previousUpdateScene) { - //Animate + // Animate bool animationActive = Animate(bufferIndex, elapsedSeconds); - //Constraint custom objects + // Constraint custom objects ConstrainCustomObjects(bufferIndex); - //Clear the lists of renderers from the previous update + // Clear the lists of renderers from the previous update for(auto&& scene : mImpl->scenes) { if(scene) @@ -1001,36 +1016,36 @@ uint32_t UpdateManager::Update(float elapsedSeconds, mImpl->frameCallbackProcessor->Update(bufferIndex, elapsedSeconds); } - //Update node hierarchy, apply constraints, + // Update node hierarchy, apply constraints, UpdateNodes(bufferIndex); - //Apply constraints to RenderTasks, shaders + // Apply constraints to RenderTasks, shaders ConstrainRenderTasks(bufferIndex); ConstrainShaders(bufferIndex); - //Update renderers and apply constraints + // Update renderers and apply constraints UpdateRenderers(bufferIndex); - //Update the transformations of all the nodes + // Update the transformations of all the nodes if(mImpl->transformManager.Update()) { mImpl->nodeDirtyFlags |= NodePropertyFlags::TRANSFORM; } - //Initialise layer renderable reuse + // Initialise layer renderable reuse UpdateLayers(bufferIndex); - //Process Property Notifications + // Process Property Notifications ProcessPropertyNotifications(bufferIndex); - //Update cameras + // Update cameras for(auto&& cameraIterator : mImpl->cameras) { cameraIterator->Update(bufferIndex); } - //Process the RenderTasks if renderers exist. This creates the instructions for rendering the next frame. - //reset the update buffer index and make sure there is enough room in the instruction container + // Process the RenderTasks if renderers exist. This creates the instructions for rendering the next frame. + // reset the update buffer index and make sure there is enough room in the instruction container if(mImpl->renderersAdded) { // Calculate how many render tasks we have in total @@ -1044,6 +1059,7 @@ uint32_t UpdateManager::Update(float elapsedSeconds, } std::size_t numberOfRenderInstructions = 0; + mImpl->renderInstructionCapacity = 0u; for(auto&& scene : mImpl->scenes) { if(scene && scene->root && scene->taskList && scene->scene) @@ -1063,6 +1079,7 @@ uint32_t UpdateManager::Update(float elapsedSeconds, renderToFboEnabled, isRenderingToFbo); + mImpl->renderInstructionCapacity += scene->scene->GetRenderInstructions().GetCapacity(); scene->scene->SetSkipRendering(false); } else diff --git a/dali/internal/update/manager/update-manager.h b/dali/internal/update/manager/update-manager.h index 3065d34..a8a6683 100644 --- a/dali/internal/update/manager/update-manager.h +++ b/dali/internal/update/manager/update-manager.h @@ -47,6 +47,9 @@ #include // for OwnerPointer< Renderer > #include // for OwnerPointer< TextureSet > +// EXTERNAL INCLUDES +#include + namespace Dali { class FrameCallbackInterface; @@ -660,6 +663,21 @@ public: */ void RemoveFrameCallback(FrameCallbackInterface* frameCallback); + /** + * Get the update message queue capacity (mutex locked) + */ + std::size_t GetUpdateMessageQueueCapacity() const; + + /** + * Get the render message queue capacity + */ + std::size_t GetRenderMessageQueueCapacity() const; + + /** + * Get the render instruction capacity + */ + std::size_t GetRenderInstructionCapacity() const; + private: // Undefined UpdateManager(const UpdateManager&); diff --git a/dali/internal/update/nodes/node.cpp b/dali/internal/update/nodes/node.cpp index f0f4943..632a960 100644 --- a/dali/internal/update/nodes/node.cpp +++ b/dali/internal/update/nodes/node.cpp @@ -348,6 +348,11 @@ void Node::RecursiveDisconnectFromSceneGraph(BufferIndex updateBufferIndex) } } +uint32_t Node::GetMemoryPoolCapacity() +{ + return gNodeMemoryPool.GetCapacity(); +} + } // namespace SceneGraph } // namespace Internal diff --git a/dali/internal/update/nodes/node.h b/dali/internal/update/nodes/node.h index 3e28d7b..28baf5e 100644 --- a/dali/internal/update/nodes/node.h +++ b/dali/internal/update/nodes/node.h @@ -850,6 +850,14 @@ public: } /** + * @brief Get the total capacity of the memory pools + * @return The capacity of the memory pools + * + * @note This is different to the node count. + */ + static uint32_t GetMemoryPoolCapacity(); + + /** * @brief Returns partial rendering data associated with the node. * @return The partial rendering data */ @@ -921,10 +929,10 @@ private: // from NodeDataProvider private: // Delete copy and move - Node(const Node&) = delete; - Node(Node&&) = delete; + Node(const Node&) = delete; + Node(Node&&) = delete; Node& operator=(const Node& rhs) = delete; - Node& operator=(Node&& rhs) = delete; + Node& operator=(Node&& rhs) = delete; /** * Recursive helper to disconnect a Node and its children. diff --git a/dali/internal/update/queue/update-message-queue.cpp b/dali/internal/update/queue/update-message-queue.cpp index 83883a7..8b80412 100644 --- a/dali/internal/update/queue/update-message-queue.cpp +++ b/dali/internal/update/queue/update-message-queue.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * Copyright (c) 2022 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. @@ -287,6 +287,28 @@ bool MessageQueue::IsSceneUpdateRequired() const return mImpl->sceneUpdate; } +std::size_t MessageQueue::GetCapacity() const +{ + MessageQueueMutex::ScopedLock lock(mImpl->queueMutex); + + uint32_t capacity = 0u; + MessageBufferIter endIter = mImpl->freeQueue.end(); + for(MessageBufferIter iter = mImpl->freeQueue.begin(); iter != endIter; ++iter) + { + capacity += (*iter)->GetCapacity(); + } + endIter = mImpl->processQueue.end(); + for(MessageBufferIter iter = mImpl->processQueue.begin(); iter != endIter; ++iter) + { + capacity += (*iter)->GetCapacity(); + } + if(mImpl->currentMessageBuffer != nullptr) + { + capacity += mImpl->currentMessageBuffer->GetCapacity(); + } + return capacity; +} + } // namespace Update } // namespace Internal diff --git a/dali/internal/update/queue/update-message-queue.h b/dali/internal/update/queue/update-message-queue.h index 6fd1c47..cfc47ba 100644 --- a/dali/internal/update/queue/update-message-queue.h +++ b/dali/internal/update/queue/update-message-queue.h @@ -2,7 +2,7 @@ #define DALI_INTERNAL_UPDATE_MESSAGE_QUEUE_H /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * Copyright (c) 2022 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. @@ -22,6 +22,9 @@ #include #include +// EXTERNAL INCLUDES +#include + namespace Dali { namespace Integration @@ -99,6 +102,11 @@ public: */ bool IsSceneUpdateRequired() const; + /** + * Query for the capacity of the current message queue + */ + std::size_t GetCapacity() const; + private: /** * Helper to call Process and destructor on each queued message @@ -108,8 +116,8 @@ private: private: // Not copyable: - MessageQueue() = delete; - MessageQueue(const MessageQueue& rhs) = delete; + MessageQueue() = delete; + MessageQueue(const MessageQueue& rhs) = delete; MessageQueue& operator=(const MessageQueue& rhs) = delete; private: diff --git a/dali/internal/update/render-tasks/scene-graph-render-task-list.cpp b/dali/internal/update/render-tasks/scene-graph-render-task-list.cpp index 8139c2b..03c39fd 100644 --- a/dali/internal/update/render-tasks/scene-graph-render-task-list.cpp +++ b/dali/internal/update/render-tasks/scene-graph-render-task-list.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * Copyright (c) 2022 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. @@ -107,6 +107,11 @@ CompleteNotificationInterface* RenderTaskList::GetCompleteNotificationInterface( return mNotificationObject; } +uint32_t RenderTaskList::GetMemoryPoolCapacity() +{ + return gRenderTaskListMemoryPool.GetCapacity(); +} + } // namespace SceneGraph } // namespace Internal diff --git a/dali/internal/update/render-tasks/scene-graph-render-task-list.h b/dali/internal/update/render-tasks/scene-graph-render-task-list.h index c985491..84058fc 100644 --- a/dali/internal/update/render-tasks/scene-graph-render-task-list.h +++ b/dali/internal/update/render-tasks/scene-graph-render-task-list.h @@ -2,7 +2,7 @@ #define DALI_INTERNAL_SCENE_GRAPH_RENDER_TASK_LIST_H /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * Copyright (c) 2022 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. @@ -107,6 +107,11 @@ public: */ CompleteNotificationInterface* GetCompleteNotificationInterface(); + /** + * Get the capacity of the memory pools + */ + static uint32_t GetMemoryPoolCapacity(); + protected: /** * Protected constructor. See New() diff --git a/dali/internal/update/rendering/scene-graph-renderer.cpp b/dali/internal/update/rendering/scene-graph-renderer.cpp index 6f4b485..1e03ce8 100644 --- a/dali/internal/update/rendering/scene-graph-renderer.cpp +++ b/dali/internal/update/rendering/scene-graph-renderer.cpp @@ -734,6 +734,11 @@ void Renderer::ResetDirtyFlag() SetUpdated(false); } +uint32_t Renderer::GetMemoryPoolCapacity() +{ + return gRendererMemoryPool.GetCapacity(); +} + void Renderer::UniformMappingsChanged(const UniformMap& mappings) { // The mappings are either from PropertyOwner base class, or the Shader diff --git a/dali/internal/update/rendering/scene-graph-renderer.h b/dali/internal/update/rendering/scene-graph-renderer.h index f2a84d6..f49f2fb 100644 --- a/dali/internal/update/rendering/scene-graph-renderer.h +++ b/dali/internal/update/rendering/scene-graph-renderer.h @@ -435,6 +435,12 @@ public: */ void ResetDirtyFlag(); + /** + * Get the capacity of the memory pools + * @return the capacity of the memory pools + */ + static uint32_t GetMemoryPoolCapacity(); + public: // UniformMap::Observer /** * @copydoc UniformMap::Observer::UniformMappingsChanged diff --git a/dali/internal/update/rendering/scene-graph-texture-set.cpp b/dali/internal/update/rendering/scene-graph-texture-set.cpp index 0269286..1e95d3b 100644 --- a/dali/internal/update/rendering/scene-graph-texture-set.cpp +++ b/dali/internal/update/rendering/scene-graph-texture-set.cpp @@ -113,6 +113,11 @@ bool TextureSet::HasAlpha() const return mHasAlpha; } +uint32_t TextureSet::GetMemoryPoolCapacity() +{ + return gTextureSetMemoryPool.GetCapacity(); +} + } // namespace SceneGraph } // namespace Internal diff --git a/dali/internal/update/rendering/scene-graph-texture-set.h b/dali/internal/update/rendering/scene-graph-texture-set.h index 683296a..5e00716 100644 --- a/dali/internal/update/rendering/scene-graph-texture-set.h +++ b/dali/internal/update/rendering/scene-graph-texture-set.h @@ -2,7 +2,7 @@ #define DALI_INTERNAL_SCENE_GRAPH_TEXTURE_SET_H /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * Copyright (c) 2022 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. @@ -91,6 +91,12 @@ public: return mSamplers; } + /** + * Get the capacity of the memory pools + * @return the capacity of the memory pools + */ + static uint32_t GetMemoryPoolCapacity(); + private: /** * Protected constructor; See also TextureSet::New() diff --git a/dali/public-api/images/pixel-data.cpp b/dali/public-api/images/pixel-data.cpp index 2356c4b..c05363a 100644 --- a/dali/public-api/images/pixel-data.cpp +++ b/dali/public-api/images/pixel-data.cpp @@ -83,4 +83,9 @@ uint32_t PixelData::GetStride() const return GetImplementation(*this).GetStride(); } +uint32_t PixelData::GetTotalAllocatedSize() +{ + return Internal::PixelData::GetTotalAllocatedSize(); +} + } // namespace Dali diff --git a/dali/public-api/images/pixel-data.h b/dali/public-api/images/pixel-data.h index b7778d5..70e80da 100644 --- a/dali/public-api/images/pixel-data.h +++ b/dali/public-api/images/pixel-data.h @@ -177,6 +177,11 @@ public: */ uint32_t GetStride() const; + /** + * Class method to get the total currently allocated size of pixel buffers + */ + static uint32_t GetTotalAllocatedSize(); + public: /** * @brief The constructor. @@ -190,6 +195,6 @@ public: /** * @} */ -} //namespace Dali +} // namespace Dali #endif // DALI_PIXEL_DATA_H