diff --git a/Source/Engine/Content/Storage/FlaxStorage.cpp b/Source/Engine/Content/Storage/FlaxStorage.cpp index 17daba278..ed8b623ae 100644 --- a/Source/Engine/Content/Storage/FlaxStorage.cpp +++ b/Source/Engine/Content/Storage/FlaxStorage.cpp @@ -1425,6 +1425,7 @@ bool FlaxStorage::CloseFileHandles() return false; } PROFILE_CPU(); + PROFILE_MEM(ContentFiles); // Note: this is usually called by the content manager when this file is not used or on exit // In those situations all the async tasks using this storage should be cancelled externally diff --git a/Source/Engine/Core/Delegate.h b/Source/Engine/Core/Delegate.h index b11d9b845..8efc2beec 100644 --- a/Source/Engine/Core/Delegate.h +++ b/Source/Engine/Core/Delegate.h @@ -12,6 +12,9 @@ #include "Engine/Threading/Threading.h" #include "Engine/Core/Collections/HashSet.h" #endif +#if COMPILE_WITH_PROFILER +#include "Engine/Profiler/ProfilerMemory.h" +#endif /// /// The function object that supports binding static, member and lambda functions. @@ -457,6 +460,7 @@ public: /// The function to bind. void Bind(const FunctionType& f) { + PROFILE_MEM(EngineDelegate); #if DELEGATE_USE_ATOMIC const intptr size = Platform::AtomicRead(&_size); FunctionType* bindings = (FunctionType*)Platform::AtomicRead(&_ptr); diff --git a/Source/Engine/Graphics/Textures/GPUTexture.cpp b/Source/Engine/Graphics/Textures/GPUTexture.cpp index 245fb1e01..07b85bc42 100644 --- a/Source/Engine/Graphics/Textures/GPUTexture.cpp +++ b/Source/Engine/Graphics/Textures/GPUTexture.cpp @@ -628,6 +628,7 @@ GPUTask* GPUTexture::UploadMipMapAsync(const BytesContainer& data, int32 mipInde GPUTask* GPUTexture::UploadMipMapAsync(const BytesContainer& data, int32 mipIndex, int32 rowPitch, int32 slicePitch, bool copyData) { PROFILE_CPU(); + PROFILE_MEM(GraphicsTextures); ASSERT(IsAllocated()); ASSERT(mipIndex < MipLevels() && data.IsValid()); ASSERT(data.Length() >= slicePitch); @@ -720,6 +721,7 @@ bool GPUTexture::DownloadData(TextureData& result) MISSING_CODE("support volume texture data downloading."); } PROFILE_CPU(); + PROFILE_MEM(GraphicsTextures); // Use faster path for staging resources if (IsStaging()) // TODO: what about chips with unified memory? if rendering is not active then we can access GPU memory from CPU directly (eg. mobile, integrated GPUs and some consoles) @@ -806,6 +808,7 @@ Task* GPUTexture::DownloadDataAsync(TextureData& result) MISSING_CODE("support volume texture data downloading."); } PROFILE_CPU(); + PROFILE_MEM(GraphicsTextures); // Use faster path for staging resources if (IsStaging()) diff --git a/Source/Engine/Input/Input.cpp b/Source/Engine/Input/Input.cpp index e0fc0297f..8438977b1 100644 --- a/Source/Engine/Input/Input.cpp +++ b/Source/Engine/Input/Input.cpp @@ -169,6 +169,7 @@ void Mouse::OnMouseMoved(const Float2& newPosition) void Mouse::OnMouseDown(const Float2& position, const MouseButton button, Window* target) { + PROFILE_MEM(Input); Event& e = _queue.AddOne(); e.Type = EventType::MouseDown; e.Target = target; @@ -187,6 +188,7 @@ bool Mouse::IsAnyButtonDown() const void Mouse::OnMouseUp(const Float2& position, const MouseButton button, Window* target) { + PROFILE_MEM(Input); Event& e = _queue.AddOne(); e.Type = EventType::MouseUp; e.Target = target; @@ -196,6 +198,7 @@ void Mouse::OnMouseUp(const Float2& position, const MouseButton button, Window* void Mouse::OnMouseDoubleClick(const Float2& position, const MouseButton button, Window* target) { + PROFILE_MEM(Input); Event& e = _queue.AddOne(); e.Type = EventType::MouseDoubleClick; e.Target = target; @@ -205,6 +208,7 @@ void Mouse::OnMouseDoubleClick(const Float2& position, const MouseButton button, void Mouse::OnMouseMove(const Float2& position, Window* target) { + PROFILE_MEM(Input); Event& e = _queue.AddOne(); e.Type = EventType::MouseMove; e.Target = target; @@ -213,6 +217,7 @@ void Mouse::OnMouseMove(const Float2& position, Window* target) void Mouse::OnMouseLeave(Window* target) { + PROFILE_MEM(Input); Event& e = _queue.AddOne(); e.Type = EventType::MouseLeave; e.Target = target; @@ -220,6 +225,7 @@ void Mouse::OnMouseLeave(Window* target) void Mouse::OnMouseWheel(const Float2& position, float delta, Window* target) { + PROFILE_MEM(Input); Event& e = _queue.AddOne(); e.Type = EventType::MouseWheel; e.Target = target; @@ -316,6 +322,7 @@ void Keyboard::OnCharInput(Char c, Window* target) if (c < 32) return; + PROFILE_MEM(Input); Event& e = _queue.AddOne(); e.Type = EventType::Char; e.Target = target; @@ -326,6 +333,7 @@ void Keyboard::OnKeyUp(KeyboardKeys key, Window* target) { if (key >= KeyboardKeys::MAX) return; + PROFILE_MEM(Input); Event& e = _queue.AddOne(); e.Type = EventType::KeyUp; e.Target = target; @@ -336,6 +344,7 @@ void Keyboard::OnKeyDown(KeyboardKeys key, Window* target) { if (key >= KeyboardKeys::MAX) return; + PROFILE_MEM(Input); Event& e = _queue.AddOne(); e.Type = EventType::KeyDown; e.Target = target; diff --git a/Source/Engine/Profiler/ProfilerCPU.cpp b/Source/Engine/Profiler/ProfilerCPU.cpp index 9ebc39bd5..5f5141e9e 100644 --- a/Source/Engine/Profiler/ProfilerCPU.cpp +++ b/Source/Engine/Profiler/ProfilerCPU.cpp @@ -3,6 +3,7 @@ #if COMPILE_WITH_PROFILER #include "ProfilerCPU.h" +#include "ProfilerMemory.h" #include "Engine/Engine/Globals.h" #include "Engine/Threading/ThreadRegistry.h" @@ -157,6 +158,7 @@ int32 ProfilerCPU::BeginEvent() auto thread = Thread::Current; if (thread == nullptr) { + PROFILE_MEM(Profiler); const auto id = Platform::GetCurrentThreadID(); const auto t = ThreadRegistry::GetThread(id); if (t) diff --git a/Source/Engine/Profiler/ProfilerGPU.cpp b/Source/Engine/Profiler/ProfilerGPU.cpp index 168677c1b..9330663f4 100644 --- a/Source/Engine/Profiler/ProfilerGPU.cpp +++ b/Source/Engine/Profiler/ProfilerGPU.cpp @@ -3,6 +3,7 @@ #if COMPILE_WITH_PROFILER #include "ProfilerGPU.h" +#include "ProfilerMemory.h" #include "Engine/Core/Log.h" #include "Engine/Engine/Engine.h" #include "Engine/Graphics/GPUDevice.h" @@ -45,6 +46,7 @@ void ProfilerGPU::EventBuffer::TryResolve() } // Collect queries results and free them + PROFILE_MEM(Profiler); for (int32 i = 0; i < _data.Count(); i++) { auto& e = _data[i]; @@ -58,6 +60,7 @@ void ProfilerGPU::EventBuffer::TryResolve() int32 ProfilerGPU::EventBuffer::Add(const Event& e) { + PROFILE_MEM(Profiler); const int32 index = _data.Count(); _data.Add(e); return index; @@ -88,6 +91,7 @@ GPUTimerQuery* ProfilerGPU::GetTimerQuery() } else { + PROFILE_MEM(Profiler); result = GPUDevice::Instance->CreateTimerQuery(); _timerQueriesPool.Add(result); } diff --git a/Source/Engine/Profiler/ProfilerMemory.cpp b/Source/Engine/Profiler/ProfilerMemory.cpp index 972dd6646..807f397cc 100644 --- a/Source/Engine/Profiler/ProfilerMemory.cpp +++ b/Source/Engine/Profiler/ProfilerMemory.cpp @@ -234,6 +234,8 @@ void InitProfilerMemory(const Char* cmdLine, int32 stage) // Init hierarchy #define INIT_PARENT(parent, child) GroupParents[(int32)ProfilerMemory::Groups::child] = (uint8)ProfilerMemory::Groups::parent + INIT_PARENT(Engine, EngineThreading); + INIT_PARENT(Engine, EngineDelegate); INIT_PARENT(Malloc, MallocArena); INIT_PARENT(Graphics, GraphicsTextures); INIT_PARENT(Graphics, GraphicsRenderTargets); diff --git a/Source/Engine/Profiler/ProfilerMemory.h b/Source/Engine/Profiler/ProfilerMemory.h index 1b1ad5ac3..2112a407d 100644 --- a/Source/Engine/Profiler/ProfilerMemory.h +++ b/Source/Engine/Profiler/ProfilerMemory.h @@ -30,8 +30,6 @@ public: TotalUntracked, // Initial memory used by program upon startup (eg. executable size, static variables). ProgramSize, - // General purpose engine memory. - Engine, // Profiling tool memory overhead. Profiler, @@ -40,6 +38,13 @@ public: // Total memory allocated via arena allocators (all pages). MallocArena, + // General purpose engine memory. + Engine, + // Memory used by the threads (and relevant systems such as Job System). + EngineThreading, + // Memory used by Delegate (engine events system to store all references). + EngineDelegate, + // Total graphics memory usage. Graphics, // Total textures memory usage. diff --git a/Source/Engine/Threading/ConcurrentQueue.h b/Source/Engine/Threading/ConcurrentQueue.h index ba60dcec6..79c819cc8 100644 --- a/Source/Engine/Threading/ConcurrentQueue.h +++ b/Source/Engine/Threading/ConcurrentQueue.h @@ -3,6 +3,7 @@ #pragma once #include "Engine/Core/Memory/Memory.h" +#include "Engine/Profiler/ProfilerMemory.h" #define MOODYCAMEL_EXCEPTIONS_ENABLED 0 #include @@ -17,6 +18,7 @@ struct ConcurrentQueueSettings : public moodycamel::ConcurrentQueueDefaultTraits // Use default engine memory allocator static inline void* malloc(size_t size) { + PROFILE_MEM(EngineThreading); return Allocator::Allocate((uint64)size); } diff --git a/Source/Engine/Threading/JobSystem.cpp b/Source/Engine/Threading/JobSystem.cpp index 634f1a884..612584c40 100644 --- a/Source/Engine/Threading/JobSystem.cpp +++ b/Source/Engine/Threading/JobSystem.cpp @@ -12,6 +12,7 @@ #include "Engine/Core/Collections/RingBuffer.h" #include "Engine/Engine/EngineService.h" #include "Engine/Profiler/ProfilerCPU.h" +#include "Engine/Profiler/ProfilerMemory.h" #if USE_CSHARP #include "Engine/Scripting/ManagedCLR/MCore.h" #endif @@ -118,17 +119,22 @@ void* JobSystemAllocation::Allocate(uintptr size) } } if (!result) + { + PROFILE_MEM(EngineThreading); result = Platform::Allocate(size, 16); + } return result; } void JobSystemAllocation::Free(void* ptr, uintptr size) { + PROFILE_MEM(EngineThreading); MemPool.Add({ ptr, size }); } bool JobSystemService::Init() { + PROFILE_MEM(EngineThreading); ThreadsCount = Math::Min(Platform::GetCPUInfo().LogicalProcessorCount, ARRAY_COUNT(Threads)); for (int32 i = 0; i < ThreadsCount; i++) { diff --git a/Source/Engine/Threading/ThreadPool.cpp b/Source/Engine/Threading/ThreadPool.cpp index aeb4dea98..e84aa2cdd 100644 --- a/Source/Engine/Threading/ThreadPool.cpp +++ b/Source/Engine/Threading/ThreadPool.cpp @@ -14,6 +14,7 @@ #include "Engine/Platform/ConditionVariable.h" #include "Engine/Platform/CPUInfo.h" #include "Engine/Platform/Thread.h" +#include "Engine/Profiler/ProfilerMemory.h" FLAXENGINE_API bool IsInMainThread() { @@ -36,6 +37,7 @@ String ThreadPoolTask::ToString() const void ThreadPoolTask::Enqueue() { + PROFILE_MEM(EngineThreading); ThreadPoolImpl::Jobs.Add(this); ThreadPoolImpl::JobsSignal.NotifyOne(); } @@ -58,6 +60,8 @@ ThreadPoolService ThreadPoolServiceInstance; bool ThreadPoolService::Init() { + PROFILE_MEM(EngineThreading); + // Spawn threads const int32 numThreads = Math::Clamp(Platform::GetCPUInfo().ProcessorCoreCount - 1, 2, PLATFORM_THREADS_LIMIT / 2); LOG(Info, "Spawning {0} Thread Pool workers", numThreads); diff --git a/Source/Engine/Threading/ThreadRegistry.cpp b/Source/Engine/Threading/ThreadRegistry.cpp index d793f7e56..522a5479b 100644 --- a/Source/Engine/Threading/ThreadRegistry.cpp +++ b/Source/Engine/Threading/ThreadRegistry.cpp @@ -3,10 +3,11 @@ #include "ThreadRegistry.h" #include "Engine/Core/Collections/Dictionary.h" #include "Engine/Platform/CriticalSection.h" +#include "Engine/Profiler/ProfilerMemory.h" namespace ThreadRegistryImpl { - Dictionary Registry(64); + Dictionary Registry; CriticalSection Locker; } @@ -46,6 +47,7 @@ void ThreadRegistry::KillEmAll() void ThreadRegistry::Add(Thread* thread) { + PROFILE_MEM(EngineThreading); ASSERT(thread && thread->GetID() != 0); Locker.Lock(); ASSERT(!Registry.ContainsKey(thread->GetID()) && !Registry.ContainsValue(thread)); diff --git a/Source/Engine/Tools/TextureTool/TextureTool.cpp b/Source/Engine/Tools/TextureTool/TextureTool.cpp index 75f4da774..b892385da 100644 --- a/Source/Engine/Tools/TextureTool/TextureTool.cpp +++ b/Source/Engine/Tools/TextureTool/TextureTool.cpp @@ -14,6 +14,7 @@ #include "Engine/Graphics/PixelFormatSampler.h" #include "Engine/Graphics/Textures/TextureData.h" #include "Engine/Profiler/ProfilerCPU.h" +#include "Engine/Profiler/ProfilerMemory.h" #if USE_EDITOR #include "Engine/Core/Collections/Dictionary.h" @@ -210,6 +211,7 @@ bool TextureTool::HasAlpha(const StringView& path) bool TextureTool::ImportTexture(const StringView& path, TextureData& textureData) { PROFILE_CPU(); + PROFILE_MEM(GraphicsTextures); LOG(Info, "Importing texture from \'{0}\'", path); const auto startTime = DateTime::NowUTC(); @@ -247,6 +249,7 @@ bool TextureTool::ImportTexture(const StringView& path, TextureData& textureData bool TextureTool::ImportTexture(const StringView& path, TextureData& textureData, Options options, String& errorMsg) { PROFILE_CPU(); + PROFILE_MEM(GraphicsTextures); LOG(Info, "Importing texture from \'{0}\'. Options: {1}", path, options.ToString()); const auto startTime = DateTime::NowUTC(); @@ -296,6 +299,7 @@ bool TextureTool::ImportTexture(const StringView& path, TextureData& textureData bool TextureTool::ExportTexture(const StringView& path, const TextureData& textureData) { PROFILE_CPU(); + PROFILE_MEM(GraphicsTextures); LOG(Info, "Exporting texture to \'{0}\'.", path); const auto startTime = DateTime::NowUTC(); ImageType type; @@ -346,6 +350,7 @@ bool TextureTool::Convert(TextureData& dst, const TextureData& src, const PixelF return true; } PROFILE_CPU(); + PROFILE_MEM(GraphicsTextures); #if COMPILE_WITH_DIRECTXTEX return ConvertDirectXTex(dst, src, dstFormat); @@ -375,6 +380,7 @@ bool TextureTool::Resize(TextureData& dst, const TextureData& src, int32 dstWidt return true; } PROFILE_CPU(); + PROFILE_MEM(GraphicsTextures); #if COMPILE_WITH_DIRECTXTEX return ResizeDirectXTex(dst, src, dstWidth, dstHeight); #elif COMPILE_WITH_STB @@ -488,6 +494,7 @@ bool TextureTool::GetImageType(const StringView& path, ImageType& type) bool TextureTool::Transform(TextureData& texture, const Function& transformation) { PROFILE_CPU(); + PROFILE_MEM(GraphicsTextures); auto sampler = PixelFormatSampler::Get(texture.Format); if (!sampler) return true; diff --git a/Source/Engine/Utilities/Screenshot.cpp b/Source/Engine/Utilities/Screenshot.cpp index 85abf19d8..9a453701d 100644 --- a/Source/Engine/Utilities/Screenshot.cpp +++ b/Source/Engine/Utilities/Screenshot.cpp @@ -82,6 +82,7 @@ bool CaptureScreenshot::Run() LOG(Warning, "Missing target render task."); return true; } + PROFILE_MEM(Graphics); // TODO: how about a case two or more screenshots at the same second? update counter and check files @@ -147,6 +148,7 @@ void Screenshot::Capture(GPUTexture* target, const StringView& path) LOG(Warning, "Cannot take screenshot. Graphics device is not ready."); return; } + PROFILE_MEM(Graphics); // Faster path for staging textures that contents are ready to access on a CPU if (target->IsStaging()) @@ -211,6 +213,7 @@ void Screenshot::Capture(SceneRenderTask* target, const StringView& path) LOG(Warning, "Cannot take screenshot. Graphics device is not ready."); return; } + PROFILE_MEM(Graphics); // Create tasks auto saveTask = New(target, path);