return 320;
}
+ void FrameStart() override
+ {
+ }
+
+ void LogMemoryPools() override
+ {
+ }
+
/**
* Store cached configurations
*/
mObjectProfiler = new ObjectProfiler(mCore->GetObjectRegistry(), timeInterval);
}
+ const uint32_t poolTimeInterval = mEnvironmentOptions->GetMemoryPoolInterval();
+ if(0u < poolTimeInterval)
+ {
+ mMemoryPoolTimer = Dali::Timer::New(poolTimeInterval * 1000);
+ mMemoryPoolTimer.TickSignal().Connect(mMemoryPoolTimerSlotDelegate, &Adaptor::MemoryPoolTimeout);
+ mMemoryPoolTimer.Start();
+ }
+
mNotificationTrigger = TriggerEventFactory::CreateTriggerEvent(MakeCallback(this, &Adaptor::ProcessCoreEvents), TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER);
mDisplayConnection = Dali::DisplayConnection::New(*mGraphics, defaultWindow->GetSurface()->GetSurfaceType());
mKernelTracer(),
mSystemTracer(),
mObjectProfiler(nullptr),
+ mMemoryPoolTimerSlotDelegate(this),
mSocketFactory(),
mMutex(),
mThreadMode(threadMode),
mCallbackManager->RemoveIdleEntererCallback(callback);
}
+bool Adaptor::MemoryPoolTimeout()
+{
+ mCore->LogMemoryPools();
+ return true; // Keep logging forever
+}
+
} // namespace Adaptor
} // namespace Internal
#define DALI_INTERNAL_ADAPTOR_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.
// EXTERNAL INCLUDES
#include <dali/devel-api/threading/mutex.h>
#include <dali/integration-api/render-controller.h>
+#include <dali/public-api/adaptor-framework/timer.h>
#include <dali/public-api/common/vector-wrapper.h>
#include <dali/public-api/math/rect.h>
#include <dali/public-api/math/uint-16-pair.h>
*/
void RemoveIdleEnterer(CallbackBase* callback);
+ /**
+ * Trigger to log the memory pools from Core and Adaptor
+ */
+ bool MemoryPoolTimeout();
+
private:
/**
* Constructor
KernelTrace mKernelTracer; ///< Kernel tracer
SystemTrace mSystemTracer; ///< System tracer
ObjectProfiler* mObjectProfiler; ///< Tracks object lifetime for profiling
- SocketFactory mSocketFactory; ///< Socket factory
- Mutex mMutex; ///< Mutex
- ThreadMode mThreadMode; ///< The thread mode
- const bool mEnvironmentOptionsOwned : 1; ///< Whether we own the EnvironmentOptions (and thus, need to delete it)
- bool mUseRemoteSurface : 1; ///< whether the remoteSurface is used or not
- Dali::LayoutDirection::Type mRootLayoutDirection; ///< LayoutDirection of window
+ Dali::Timer mMemoryPoolTimer; ///< Logs memory pool capacity
+ SlotDelegate<Adaptor> mMemoryPoolTimerSlotDelegate;
+ SocketFactory mSocketFactory; ///< Socket factory
+ Mutex mMutex; ///< Mutex
+ ThreadMode mThreadMode; ///< The thread mode
+ const bool mEnvironmentOptionsOwned : 1; ///< Whether we own the EnvironmentOptions (and thus, need to delete it)
+ bool mUseRemoteSurface : 1; ///< whether the remoteSurface is used or not
+ Dali::LayoutDirection::Type mRootLayoutDirection; ///< LayoutDirection of window
std::unique_ptr<Integration::AddOnManager> mAddOnManager; ///< Pointer to the addon manager
#include <dali/internal/adaptor/common/combined-update-render-controller-debug.h>
#include <dali/internal/graphics/common/graphics-interface.h>
#include <dali/internal/graphics/gles/egl-graphics.h>
-#include <dali/internal/graphics/gles/egl-implementation.h>
#include <dali/internal/system/common/environment-options.h>
#include <dali/internal/system/common/time-service.h>
#include <dali/internal/window-system/common/window-impl.h>
// Update time
uint64_t lastFrameTime;
TimeService::GetNanoseconds(lastFrameTime);
+ uint64_t lastMemPoolLogTime = lastFrameTime;
LOG_UPDATE_RENDER("THREAD INITIALISED");
uint64_t timeToSleepUntil = 0;
int extraFramesDropped = 0;
+ const uint64_t memPoolInterval = mEnvironmentOptions.GetMemoryPoolInterval() * NANOSECONDS_PER_SECOND;
+
const unsigned int renderToFboInterval = mEnvironmentOptions.GetRenderToFboInterval();
const bool renderToFboEnabled = 0u != renderToFboInterval;
unsigned int frameCount = 0u;
// RENDER
//////////////////////////////
+ graphics.FrameStart();
mAdaptorInterfaces.GetDisplayConnectionInterface().ConsumeEvents();
if(mPreRenderCallback != NULL)
TRACE_UPDATE_RENDER_END("DALI_RENDER");
AddPerformanceMarker(PerformanceInterface::RENDER_END);
+ // if the memory pool interval is set and has elapsed, log the graphics memory pools
+ if(0 < memPoolInterval && memPoolInterval < lastFrameTime - lastMemPoolLogTime)
+ {
+ lastMemPoolLogTime = lastFrameTime;
+ graphics.LogMemoryPools();
+ }
+
mForceClear = false;
// Trigger event thread to request Update/Render thread to sleep if update not required
*/
virtual void CacheConfigurations(ConfigurationManager& configurationManager) = 0;
+ /**
+ * Initialize data for logging frame info
+ */
+ virtual void FrameStart() = 0;
+
+ /**
+ * Log total capacity of memory pools during this frame
+ */
+ virtual void LogMemoryPools() = 0;
+
protected:
Integration::DepthBufferAvailable mDepthBufferRequired; ///< Whether the depth buffer is required
Integration::StencilBufferAvailable mStencilBufferRequired; ///< Whether the stencil buffer is required
void EglGraphicsController::InitializeGLES(Integration::GlAbstraction& glAbstraction)
{
- DALI_LOG_RELEASE_INFO("Initializing New Graphics Controller #1\n");
+ DALI_LOG_RELEASE_INFO("Initializing Graphics Controller Phase 1\n");
mGlAbstraction = &glAbstraction;
mContext = std::make_unique<GLES::Context>(*this);
mCurrentContext = mContext.get();
Integration::GlContextHelperAbstraction& glContextHelperAbstraction,
Internal::Adaptor::GraphicsInterface& graphicsInterface)
{
- DALI_LOG_RELEASE_INFO("Initializing New Graphics Controller #2\n");
+ DALI_LOG_RELEASE_INFO("Initializing Graphics Controller Phase 2\n");
auto* syncImplPtr = static_cast<Internal::Adaptor::EglSyncImplementation*>(&syncImplementation);
mEglSyncImplementation = syncImplPtr;
mGraphics = &graphicsInterface;
}
+void EglGraphicsController::FrameStart()
+{
+ mCapacity = 0; // Reset the command buffer capacity at the start of the frame.
+}
+
void EglGraphicsController::SubmitCommandBuffers(const SubmitInfo& submitInfo)
{
for(auto& cmdbuf : submitInfo.cmdBuffer)
{
// Push command buffers
- mCommandQueue.push(static_cast<GLES::CommandBuffer*>(cmdbuf));
+ auto* commandBuffer = static_cast<GLES::CommandBuffer*>(cmdbuf);
+ mCapacity += commandBuffer->GetCapacity();
+ mCommandQueue.push(commandBuffer);
}
// If flush bit set, flush all pending tasks
properties.compressed = glesTexture->IsCompressed();
properties.extent2D = createInfo.size;
properties.nativeHandle = glesTexture->GetGLTexture();
- //TODO: Skip format1, emulated, packed, directWriteAccessEnabled of TextureProperties for now
+ // TODO: Skip format1, emulated, packed, directWriteAccessEnabled of TextureProperties for now
return properties;
}
void EglGraphicsController::DeleteSurfaceContext(Dali::RenderSurfaceInterface* surface)
{
mSurfaceContexts.erase(std::remove_if(
- mSurfaceContexts.begin(), mSurfaceContexts.end(), [surface](SurfaceContextPair& iter) { return surface == iter.first; }),
+ mSurfaceContexts.begin(), mSurfaceContexts.end(), [surface](SurfaceContextPair& iter)
+ { return surface == iter.first; }),
mSurfaceContexts.end());
}
{
mCurrentContext = mContext.get();
mCurrentContext->GlContextCreated();
-
if(!mSharedContext)
{
auto eglGraphics = dynamic_cast<Dali::Internal::Adaptor::EglGraphics*>(mGraphics);
{
if(surface && mGraphics->IsResourceContextSupported())
{
- auto iter = std::find_if(mSurfaceContexts.begin(), mSurfaceContexts.end(), [surface](SurfaceContextPair& iter) {
- return (iter.first == surface);
- });
+ auto iter = std::find_if(mSurfaceContexts.begin(), mSurfaceContexts.end(), [surface](SurfaceContextPair& iter)
+ { return (iter.first == surface); });
if(iter != mSurfaceContexts.end())
{
Internal::Adaptor::EglSyncImplementation& GetEglSyncImplementation();
/**
+ * Mark the start of the frame.
+ *
+ * Note, this is used for logging & debugging, so is not part of the main Graphics API.
+ */
+ void FrameStart();
+
+ /**
* @copydoc Dali::Graphics::SubmitCommandBuffers()
*/
void SubmitCommandBuffers(const SubmitInfo& submitInfo) override;
return mSyncPool;
}
+ std::size_t GetCapacity() const
+ {
+ return mCapacity;
+ }
+
private:
Integration::GlAbstraction* mGlAbstraction{nullptr};
Integration::GlContextHelperAbstraction* mGlContextHelperAbstraction{nullptr};
GLES::TextureDependencyChecker mTextureDependencyChecker; // Checks if FBO textures need syncing
GLES::SyncPool mSyncPool;
+ std::size_t mCapacity; ///< Memory Usage (of command buffers)
};
} // namespace Graphics
} // namespace Dali
-#endif //DALI_EGL_GRAPHICS_CONTROLLER_H
+#endif // DALI_EGL_GRAPHICS_CONTROLLER_H
inline void resize(int newSize)
{
ptr = reinterpret_cast<T*>(realloc(ptr, newSize * sizeof(T)));
- capacity = newSize;
+ capacity = newSize * sizeof(T);
dataSize = newSize;
}
size = commandPool.size;
return commandPool.data.ptr;
}
+
+ std::size_t GetTotalCapacity() const
+ {
+ return commandPool.data.capacity + memoryPool.data.capacity;
+ }
};
CommandBuffer::CommandBuffer(const Graphics::CommandBufferCreateInfo& createInfo, EglGraphicsController& controller)
GetController().DiscardResource(this);
}
+std::size_t CommandBuffer::GetCapacity()
+{
+ std::size_t total{0u};
+ if(mCommandPool)
+ {
+ total = mCommandPool->GetTotalCapacity();
+ }
+ return total;
+}
+
} // namespace Dali::Graphics::GLES
*/
void DiscardResource() override;
+ // Get the total memory usage of this command buffer
+ std::size_t GetCapacity();
+
private:
std::unique_ptr<CommandPool> mCommandPool; ///< Pool of commands and transient memory
};
// INTERNAL INCLUDES
#include <dali/integration-api/adaptor-framework/render-surface-interface.h>
+#include <dali/integration-api/debug.h>
#include <dali/internal/system/common/configuration-manager.h>
#include <dali/internal/system/common/environment-options.h>
#include <dali/internal/window-system/common/display-utils.h> // For Utils::MakeUnique
mGLES->SetShadingLanguageVersion(configurationManager.GetShadingLanguageVersion());
}
+void EglGraphics::FrameStart()
+{
+ mGraphicsController.FrameStart();
+}
+
+void EglGraphics::LogMemoryPools()
+{
+ std::size_t graphicsCapacity = mGraphicsController.GetCapacity();
+ DALI_LOG_RELEASE_INFO(
+ "EglGraphics:\n"
+ " GraphicsController Capacity: %lu\n",
+ graphicsCapacity);
+}
+
} // namespace Adaptor
} // namespace Internal
} // namespace Dali
void CacheConfigurations(ConfigurationManager& configurationManager) override;
+ /**
+ * @copydoc Dali::Internal::Adaptor::GraphicsInterface::FrameStart()
+ */
+ void FrameStart() override;
+
+ /**
+ * @copydoc Dali::Internal::Adaptor::GraphicsInterface::LogMemoryPools()
+ */
+ void LogMemoryPools() override;
+
private:
// Eliminate copy and assigned operations
- EglGraphics(const EglGraphics& rhs) = delete;
+ EglGraphics(const EglGraphics& rhs) = delete;
EglGraphics& operator=(const EglGraphics& rhs) = delete;
/**
#include <cstring>
// INTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
#include <dali/internal/imaging/common/alpha-mask.h>
#include <dali/internal/imaging/common/gaussian-blur.h>
#include <dali/internal/imaging/common/image-operations.h>
{
namespace
{
+
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gPixelBufferFilter = Debug::Filter::New(Debug::NoLogging, false, "DALI_LOG_PIXEL_BUFFER_SIZE");
+#endif
+
const float TWO_PI = 2.f * Math::PI; ///< 360 degrees in radians
// based on W3C Recommendations (https://www.w3.org/TR/AERT/#color-contrast)
constexpr uint32_t BRIGHTNESS_CONSTANT_R = 299;
constexpr uint32_t BRIGHTNESS_CONSTANT_B = 114;
} // namespace
+#if defined(DEBUG_ENABLED)
+uint32_t PixelBuffer::gPixelBufferAllocationTotal{0};
+#endif
+
PixelBuffer::PixelBuffer(uint8_t* buffer,
uint32_t bufferSize,
uint32_t width,
if(bufferSize > 0)
{
buffer = static_cast<uint8_t*>(malloc(bufferSize));
+#if defined(DEBUG_ENABLED)
+ gPixelBufferAllocationTotal += bufferSize;
+#endif
}
+ DALI_LOG_INFO(gPixelBufferFilter, Debug::Concise, "Allocated PixelBuffer of size %u\n", bufferSize);
+
return new PixelBuffer(buffer, bufferSize, width, height, width, pixelFormat);
}
Dali::PixelData PixelBuffer::Convert(PixelBuffer& pixelBuffer)
{
+#if defined(DEBUG_ENABLED)
+ gPixelBufferAllocationTotal -= pixelBuffer.mBufferSize;
+#endif
Dali::PixelData pixelData = Dali::PixelData::New(pixelBuffer.mBuffer,
pixelBuffer.mBufferSize,
pixelBuffer.mWidth,
{
if(mBuffer)
{
+#if defined(DEBUG_ENABLED)
+ gPixelBufferAllocationTotal -= mBufferSize;
+#endif
free(mBuffer);
}
}
ReleaseBuffer();
mBuffer = reinterpret_cast<unsigned char*>(malloc(size));
mBufferSize = size;
+#if defined(DEBUG_ENABLED)
+ gPixelBufferAllocationTotal += size;
+#endif
}
bool PixelBuffer::Rotate(Degree angle)
// INTERNAL INCLUDES
#include <dali/devel-api/adaptor-framework/pixel-buffer.h>
+#include <dali/integration-api/debug.h>
#include <dali/public-api/images/image-operations.h> // For ImageDimensions
#include <dali/public-api/images/pixel-data.h>
#include <dali/public-api/object/base-object.h>
public:
/**
+ * Get the total allocated size of current pixel buffers
+ */
+ static uint32_t GetTotalAllocatedSize()
+ {
+#if defined(DEBUG_ENABLED)
+ return gPixelBufferAllocationTotal;
+#else
+ return 0;
+#endif
+ }
+
+ /**
* Get the width of the buffer in pixels.
* @return The width of the buffer in pixels
*/
uint32_t mStride; ///< Buffer stride in bytes, 0 means the buffer is tightly packed
Pixel::Format mPixelFormat; ///< Pixel format
bool mPreMultiplied; ///< PreMultiplied
+
+#if defined(DEBUG_ENABLED)
+ static uint32_t gPixelBufferAllocationTotal;
+#endif
};
} // namespace Adaptor
/*
- * 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.
mFpsFrequency(0),
mUpdateStatusFrequency(0),
mObjectProfilerInterval(0),
+ mMemoryPoolInterval(0),
mPerformanceStatsLevel(0),
mPerformanceStatsFrequency(DEFAULT_STATISTICS_LOG_FREQUENCY),
mPerformanceTimeStampOutput(0),
{
return mObjectProfilerInterval;
}
-
+unsigned int EnvironmentOptions::GetMemoryPoolInterval() const
+{
+ return mMemoryPoolInterval;
+}
unsigned int EnvironmentOptions::GetPerformanceStatsLoggingOptions() const
{
return mPerformanceStatsLevel;
mFpsFrequency = GetEnvironmentVariable(DALI_ENV_FPS_TRACKING, 0);
mUpdateStatusFrequency = GetEnvironmentVariable(DALI_ENV_UPDATE_STATUS_INTERVAL, 0);
mObjectProfilerInterval = GetEnvironmentVariable(DALI_ENV_OBJECT_PROFILER_INTERVAL, 0);
+ mMemoryPoolInterval = GetEnvironmentVariable(DALI_ENV_MEMORY_POOL_INTERVAL, 0);
mPerformanceStatsLevel = GetEnvironmentVariable(DALI_ENV_LOG_PERFORMANCE_STATS, 0);
mPerformanceStatsFrequency = GetEnvironmentVariable(DALI_ENV_LOG_PERFORMANCE_STATS_FREQUENCY, 0);
mPerformanceTimeStampOutput = GetEnvironmentVariable(DALI_ENV_PERFORMANCE_TIMESTAMP_OUTPUT, 0);
#define DALI_INTERNAL_ADAPTOR_ENVIRONMENT_OPTIONS_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.
unsigned int GetObjectProfilerInterval() const;
/**
+ * @return memory pool status interval (0==off)
+ */
+ unsigned int GetMemoryPoolInterval() const;
+
+ /**
* @return performance statistics log level ( 0 == off )
*/
unsigned int GetPerformanceStatsLoggingOptions() const;
unsigned int mFpsFrequency; ///< how often fps is logged out in seconds
unsigned int mUpdateStatusFrequency; ///< how often update status is logged out in frames
unsigned int mObjectProfilerInterval; ///< how often object counts are logged out in seconds
+ uint32_t mMemoryPoolInterval; ///< how often memory pool capacities are logged out in seconds
unsigned int mPerformanceStatsLevel; ///< performance statistics logging bitmask
unsigned int mPerformanceStatsFrequency; ///< performance statistics logging frequency (seconds)
unsigned int mPerformanceTimeStampOutput; ///< performance time stamp output ( bitmask)
#define DALI_INTERNAL_ADAPTOR_ENVIRONMENT_VARIABLES_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.
#define DALI_ENV_UPDATE_STATUS_INTERVAL "DALI_UPDATE_STATUS_INTERVAL"
#define DALI_ENV_OBJECT_PROFILER_INTERVAL "DALI_OBJECT_PROFILER_INTERVAL"
+#define DALI_ENV_MEMORY_POOL_INTERVAL "DALI_MEMORY_POOL_INTERVAL"
// Pan-Gesture configuration:
// Prediction Modes 1 & 2:
/*
- * Copyright (c) 20217 Samsung Electronics Co., Ltd.
+ * Copyright (c) 20227 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.
// EXTERNAL INCLUDES
#include <dali/integration-api/debug.h>
#include <dali/integration-api/profiling.h>
+#include <dali/internal/imaging/common/pixel-buffer-impl.h>
+#include <dali/public-api/images/pixel-data.h>
#include <dali/public-api/object/base-object.h>
#include <dali/public-api/object/ref-object.h>
#include <dali/public-api/object/type-registry.h>
+
#include <stdlib.h>
using std::string;
bool ObjectProfiler::OnTimeout()
{
+ uint32_t pixelDataSize = Dali::PixelData::GetTotalAllocatedSize();
+ uint32_t pixelBufferSize = Dali::Internal::Adaptor::PixelBuffer::GetTotalAllocatedSize();
+ LogMessage(Debug::DebugInfo, "Total PixelData: %9.1fkb\n", ((float)pixelDataSize) / 1024.0f);
+ LogMessage(Debug::DebugInfo, "Total PixelBuffer: %9.1fkb\n", ((float)pixelBufferSize) / 1024.0f);
+
DisplayInstanceCounts();
return true;
}
{
auto&& countIter = std::find_if(mInstanceCountContainer.begin(),
mInstanceCountContainer.end(),
- [theType](const InstanceCountPair& instance) { return instance.first == theType; });
+ [theType](const InstanceCountPair& instance)
+ { return instance.first == theType; });
if(countIter != mInstanceCountContainer.end())
{
(*countIter).second--;