// Copyright (c) Wojciech Figat. All rights reserved. #pragma once #include "Engine/Platform/Platform.h" #if COMPILE_WITH_PROFILER #include "Engine/Core/Types/StringView.h" /// /// Provides memory allocations collecting utilities. /// API_CLASS(Static) class FLAXENGINE_API ProfilerMemory { DECLARE_SCRIPTING_TYPE_MINIMAL(ProfilerMemory); public: /// /// List of different memory categories used to track and analyze memory allocations specific to a certain engine system. /// API_ENUM() enum class Groups : uint8 { // Not categorized. Unknown, // Total used system memory (reported by platform). Total, // Total amount of tracked memory (by ProfilerMemory tool). TotalTracked, // Total amount of untracked memory (gap between total system memory usage and tracked memory size). TotalUntracked, // Initial memory used by program upon startup (eg. executable size, static variables). ProgramSize, // Total memory allocated via malloc. Malloc, // General purpose engine memory. Engine, // Profiling tool memory overhead. Profiler, // Total graphics memory usage. Graphics, // Total textures memory usage. GraphicsTextures, // Total buffers memory usage. GraphicsBuffers, // Total meshes memory usage (vertex and idnex buffers allocated by models). GraphicsMeshes, // Totoal shaders memory usage (shaders bytecode, PSOs data). GraphicsShaders, // Totoal materials memory usage (constant buffers, parameters data). GraphicsMaterials, // Totoal command buffers memory usage (draw lists, constants uploads, ring buffer allocators). GraphicsCommands, // Total Artificial Intelligence systems memory usage (eg. Behavior Trees). AI, // Total animations system memory usage. Animations, // Total animation data memory usage (curves, events, keyframes, graphs, etc.). AnimationsData, // Total autio system memory. Audio, // Total content system memory usage. Content, // Total general purpose memory allocated by assets. ContentAssets, // Total memory used by content files buffers (file reading and streaming buffers). ContentFiles, // Total memory used by content streaming system (internals). ContentStreaming, // Total memory allocated by input system. Input, // Total memory allocated by scene objects. Level, // Total localization system memory. Localization, // Total navigation system memory. Navigation, // Total networking system memory. Networking, // Total particles memory (loaded assets, particles buffers and instance parameters). Particles, // Total physics memory. Physics, // Total scripting memory allocated by game. Scripting, // Total User Interface components memory. UI, // Total video system memory (video file data, frame buffers, GPU images and any audio buffers used by video playback). Video, // Custom game-specific memory tracking. CustomGame0, // Custom game-specific memory tracking. CustomGame1, // Custom game-specific memory tracking. CustomGame2, // Custom game-specific memory tracking. CustomGame3, // Custom game-specific memory tracking. CustomGame4, // Custom game-specific memory tracking. CustomGame5, // Custom game-specific memory tracking. CustomGame6, // Custom game-specific memory tracking. CustomGame7, // Custom game-specific memory tracking. CustomGame8, // Custom game-specific memory tracking. CustomGame9, // Custom plugin-specific memory tracking. CustomPlugin0, // Custom plugin-specific memory tracking. CustomPlugin1, // Custom plugin-specific memory tracking. CustomPlugin2, // Custom plugin-specific memory tracking. CustomPlugin3, // Custom plugin-specific memory tracking. CustomPlugin4, // Custom plugin-specific memory tracking. CustomPlugin5, // Custom plugin-specific memory tracking. CustomPlugin6, // Custom plugin-specific memory tracking. CustomPlugin7, // Custom plugin-specific memory tracking. CustomPlugin8, // Custom plugin-specific memory tracking. CustomPlugin9, // Total editor-specific memory. Editor, MAX }; /// /// The memory groups array wraper to avoid dynamic memory allocation. /// API_STRUCT(NoDefault) struct GroupsArray { DECLARE_SCRIPTING_TYPE_MINIMAL(GroupsArray); // Values for each group API_FIELD(NoArray) int64 Values[100]; }; public: /// /// Increments memory usage by a specific group. /// /// The group to update. /// The amount of memory allocated (in bytes). API_FUNCTION() static void IncrementGroup(Groups group, uint64 size); /// /// Decrements memory usage by a specific group. /// /// The group to update. /// The amount of memory freed (in bytes). API_FUNCTION() static void DecrementGroup(Groups group, uint64 size); /// /// Enters a new group context scope (by the current thread). Informs the profiler about context of any memory allocations within. /// /// The group to enter. API_FUNCTION() static void BeginGroup(Groups group); /// /// Leaves the last group context scope (by the current thread). /// API_FUNCTION() static void EndGroup(); /// /// Renames the group. Can be used for custom game/plugin groups naming. /// /// The group to update. /// The new name to set. API_FUNCTION() static void RenameGroup(Groups group, const StringView& name); /// /// Gets the names of all groups (array matches Groups enums). /// API_FUNCTION() static Array GetGroupNames(); /// /// Gets the memory stats for all groups (array matches Groups enums). /// /// 0 to get current memory, 1 to get peek memory, 2 to get current count. API_FUNCTION() static GroupsArray GetGroups(int32 mode = 0); /// /// Dumps the memory allocations stats (groupped). /// /// 'all' to dump all groups, 'file' to dump info to a file (in Logs folder) API_FUNCTION(Attributes="DebugCommand") static void Dump(const StringView& options = StringView::Empty); public: /// /// The profiling tools usage flag. Can be used to disable profiler. Run engine with '-mem' command line to activate it from start. /// static bool Enabled; static void OnMemoryAlloc(void* ptr, uint64 size); static void OnMemoryFree(void* ptr); public: /// /// Helper structure used to call begin/end on group within single code block. /// struct GroupScope { FORCE_INLINE GroupScope(Groups group) { if (ProfilerMemory::Enabled) ProfilerMemory::BeginGroup(group); } FORCE_INLINE ~GroupScope() { if (ProfilerMemory::Enabled) ProfilerMemory::EndGroup(); } }; }; #define PROFILE_MEM_INC(group, size) ProfilerMemory::IncrementGroup(ProfilerMemory::Groups::group, size) #define PROFILE_MEM_DEC(group, size) ProfilerMemory::DecrementGroup(ProfilerMemory::Groups::group, size) #define PROFILE_MEM(group) ProfilerMemory::GroupScope ProfileMem(ProfilerMemory::Groups::group) #define PROFILE_MEM_BEGIN(group) if (ProfilerMemory::Enabled) ProfilerMemory::BeginGroup(ProfilerMemory::Groups::group) #define PROFILE_MEM_END() if (ProfilerMemory::Enabled) ProfilerMemory::EndGroup() #else // Empty macros for disabled profiler #define PROFILE_MEM_INC(group, size) #define PROFILE_MEM_DEC(group, size) #define PROFILE_MEM(group) #define PROFILE_MEM_BEGIN(group) #define PROFILE_MEM_END() #endif