// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "CoreMinimal.h" #if STATS #include "Containers/LockFreeList.h" #include "Misc/Guid.h" #include "Async/TaskGraphInterfaces.h" #include "ProfilerCommon.h" #include "ProfilerSample.h" #include "ProfilerDataSource.h" #include "ISessionInstanceInfo.h" #include "Containers/Ticker.h" #include "IProfilerServiceManager.h" #include "Stats/StatsData.h" #include "ProfilerStream.h" class FFPSAnalyzer; class FProfilerGroup; class IDataProvider; /** * Enumerates profiler session type. */ enum class EProfilerSessionTypes { /** Based on the live connection. */ Live, LiveRaw, /** Based on the regular stats file. */ StatsFile, /** Based on the raw stats file. */ StatsFileRaw, Combined, Summary, /** Invalid enum type, may be used as a number of enumerations. */ InvalidOrMax, }; namespace ProfilerSessionTypes { /** * Returns the string representation of the specified EProfilerSessionType value. * * @param ProfilerSessionType The value to get the string for. * @return A string value. */ inline FString ToString(EProfilerSessionTypes ProfilerSessionType) { // @TODO: Localize switch(ProfilerSessionType) { case EProfilerSessionTypes::Live: return FString("Live"); case EProfilerSessionTypes::StatsFile: return FString("Offline"); default: return FString("InvalidOrMax"); } } } /** * Enumerates loading a capture file progress states. */ enum class ELoadingProgressStates { Started, InProgress, Loaded, Failed, Cancelled, /** Invalid enum type, may be used as a number of enumerations. */ InvalidOrMax, }; enum class EProfilerNotificationTypes { LoadingOfflineCapture, SendingServiceSideCapture, }; class FProfilerGroup; /** * Contains information about stat like name, ID and type, and information about the owning stat group. */ class FProfilerStat : public FNoncopyable { friend class FProfilerStatMetaData; public: /** * Default constructor. * * @param InID The unique ID for this stat */ FProfilerStat(const uint32 InStatID = 0); protected: /** * Sets the new description for this stat. * * @param InName The name of this stat * @param InGroupID The pointer to the group that this stat belongs to * @param InType The type of this stat */ void Initialize(const FString& InName, FProfilerGroup* InOwningGroupPtr, const EStatType InType) { // Skip leading spaces in the name of the stat. int32 Index = 0; while(FChar::IsWhitespace(InName[Index])) { Index++; } const FString CleanedName = *InName+Index; _Name = *CleanedName; _OwningGroupPtr = InOwningGroupPtr; _Type = ConvertStatTypeToProfilerSampleType(InType); } /** * @return a profiler sample type from the specified generic stat type */ static const EProfilerSampleTypes::Type ConvertStatTypeToProfilerSampleType(const EStatType StatType) { EProfilerSampleTypes::Type ProfilerUnit = EProfilerSampleTypes::InvalidOrMax; switch(StatType) { case STATTYPE_MemoryCounter: { ProfilerUnit = EProfilerSampleTypes::Memory; break; } case STATTYPE_AccumulatorFLOAT: case STATTYPE_CounterFLOAT: { ProfilerUnit = EProfilerSampleTypes::NumberFloat; break; } case STATTYPE_AccumulatorDWORD: case STATTYPE_CounterDWORD: { ProfilerUnit = EProfilerSampleTypes::NumberInt; break; } case STATTYPE_CycleCounter: { ProfilerUnit = EProfilerSampleTypes::HierarchicalTime; break; } case STATTYPE_Error: break; } return ProfilerUnit; } public: /** * @return the display name for this stat. */ const FName& Name() const { return _Name; } /** * @return a reference to the group that this stat belongs to. */ const FProfilerGroup& OwningGroup() const { check(_OwningGroupPtr != NULL); return *_OwningGroupPtr; } /** * @return the unique ID for this stat. */ const uint32 ID() const { return _ID; } /** * @return the type of this stat. */ const EProfilerSampleTypes::Type Type() const { return _Type; } /** * @return number of bytes allocated by this stat. */ const SIZE_T GetMemoryUsage() const { return sizeof(_Name) + sizeof(*this); } /** * @return a pointer to the default profiler stat. */ static FProfilerStat* GetDefaultPtr() { return &Default; } protected: /** The display name for this stat. */ FName _Name; /** The pointer to the group that this stat belongs to. */ FProfilerGroup* _OwningGroupPtr; /** The unique ID for this stat. */ const uint32 _ID; /** Holds the type of this stat. */ EProfilerSampleTypes::Type _Type; /** Default profiler stat, used for uninitialized stats. */ static FProfilerStat Default; }; template <> struct TIsPODType { enum { Value = true }; }; /** * Contains information about stat group and stats associated with the specified stat group. */ class FProfilerGroup : public FNoncopyable { friend class FProfilerStatMetaData; public: /** Default constructor. */ FProfilerGroup() : _Name(TEXT("(Group-Default)")) , _ID(0) {} protected: /** * Initialization constructor. * * @param InID The unique ID for this stat group * */ FProfilerGroup(const uint32 InID) : _Name(*FString::Printf(TEXT("(Group-%04u)"), InID)) , _ID(InID) {} /** * Sets the new name for this stat group. * * @param InName The name of this stat group * */ void Initialize(const FString& InName) { _Name = *InName; } /** * Adds a stat to this group. * * @param ProfilerStat Pointer to the existing stat object * */ void AddStat(FProfilerStat* ProfilerStat) { OwnedStats.Add(ProfilerStat); } public: /** * @return a reference to the list of stats that are in this stat group. */ const TArray& GetStats() const { return OwnedStats; } /** * @return the display name for this stat group. */ const FName& Name() const { return _Name; } /** * @return the unique ID for this stat group. */ const uint32 ID() const { return _ID; } /** * @return number of bytes allocated by this group. */ const SIZE_T GetMemoryUsage() const { return OwnedStats.GetAllocatedSize() + sizeof(_Name) + sizeof(*this); } /** * @return a pointer to the default profiler group. */ static FProfilerGroup* GetDefaultPtr() { return &Default; } protected: /** Contains a list of stats that are in this stat group. */ TArray OwnedStats; /** The display name for this stat group. */ FName _Name; /** The unique ID for this stat group. */ const uint32 _ID; /** Default profiler group, used for uninitialized stats. */ static FProfilerGroup Default; }; /** * Structure holding the metadata describing the various stats and data associated with them. * Critical data like stat and group description are stored in arrays of predefined size to allow constant time access. */ class FProfilerStatMetaData : public FNoncopyable, public TSharedFromThis { friend class FProfilerSession; friend class FRawProfilerSession; protected: /** Constructor. */ FProfilerStatMetaData() : SecondsPerCycle(FPlatformTime::GetSecondsPerCycle()) , GameThreadID(0) {} public: /** Destructor. */ ~FProfilerStatMetaData() { // Delete all allocated descriptions. for(auto It = StatDescriptions.CreateConstIterator(); It; ++It) { delete It.Value(); } StatDescriptions.Empty(); for(auto It = GroupDescriptions.CreateConstIterator(); It; ++It) { delete It.Value(); } GroupDescriptions.Empty(); } /** * @return number of bytes allocated by this instance of stat metadata. */ const SIZE_T GetMemoryUsage() const { SIZE_T MemorySize = 0; MemorySize += sizeof(*this); MemorySize += StatDescriptions.GetAllocatedSize(); for(auto It = StatDescriptions.CreateConstIterator(); It; ++It) { MemorySize += It.Value()->GetMemoryUsage(); } MemorySize += GroupDescriptions.GetAllocatedSize(); for(auto It = GroupDescriptions.CreateConstIterator(); It; ++It) { MemorySize += It.Value()->GetMemoryUsage(); } MemorySize += GetThreadDescriptions().GetAllocatedSize(); return MemorySize; } protected: /** * Updates this instance of stat metadata. * * @param StatMetaData The stat metadata received from the connected profiler client */ void Update(const FStatMetaData& ClientStatMetaData); public: /** * Updates this stats metadata based on the stats thread state. * This is a temporary solution to make it working with current implementation of FProfilerSample. */ void UpdateFromStatsState(const FStatsThreadState& StatsThreadStats); private: /** * Initialized the specified stat group. * If specified stat group doesn't exist, adds it to the list of stat group descriptions. * * @param GroupID The ID of the stat group that needs to be initialized * @param GroupName The name of the stat group that needs to be initialized */ void InitializeGroup(const uint32 GroupID, const FString& GroupName) { FProfilerGroup* GroupPtr = GroupDescriptions.FindRef(GroupID); if(!GroupPtr) { GroupPtr = GroupDescriptions.Add(GroupID, new FProfilerGroup(GroupID)); } GroupPtr->Initialize(GroupName); } /** * Initialized the specified stat. * * @param StatID The id of the stat that needs to be initialized * @param GroupID The id of the stat group that will be assigned to the specified stat * @param StatName The name of the stat that needs to be initialized * @param InType The type of the stat that needs to be initialized * @param StatName The unique stat name */ void InitializeStat(const uint32 StatID, const uint32 GroupID, const FString& StatName, const EStatType InType, FName StatFName = NAME_None) { FProfilerStat* StatPtr = StatDescriptions.FindRef(StatID); if(!StatPtr) { StatPtr = StatDescriptions.Add(StatID, new FProfilerStat(StatID)); if(StatFName != NAME_None) { StatFNameDescriptions.Add(StatFName, StatPtr); } FProfilerGroup* GroupPtr = GroupDescriptions.FindRef(GroupID); StatPtr->Initialize(StatName, GroupPtr, InType); static const FName NAME_Threads(TEXT("Threads")); if(StatFName == NAME_None && GroupPtr->Name() == NAME_Threads) { // Check if this stat is a thread stat. const uint32 ThreadID = FStatsUtils::ParseThreadID(StatPtr->Name().ToString()); if(ThreadID != 0) { const FString* ThreadDesc = GetThreadDescriptions().Find(ThreadID); if(ThreadDesc) { // Replace the stat name with a thread name. const FString UniqueThreadName = FString::Printf(TEXT("%s [0x%x]"), **ThreadDesc, ThreadID); StatPtr->_Name = *UniqueThreadName; ThreadIDtoStatID.Add(ThreadID, StatID); // Game thread is always NAME_GameThread if(**ThreadDesc == FName(NAME_GameThread)) { GameThreadID = ThreadID; } // Rendering thread may be "Rendering thread" or NAME_RenderThread with an index else if(ThreadDesc->Contains(FName(NAME_RenderThread).GetPlainNameString())) { RenderThreadIDs.AddUnique(ThreadID); } else if(ThreadDesc->Contains(TEXT("RenderingThread"))) { RenderThreadIDs.AddUnique(ThreadID); } } } } if(GroupPtr != FProfilerGroup::GetDefaultPtr()) { GroupPtr->AddStat(StatPtr); } } } public: /** * @return a reference to the stat description specified by the stat ID */ const FProfilerStat& GetStatByID(const uint32 StatID) const { return *StatDescriptions.FindChecked(StatID); } /** * @return a reference to the stat description specified by the unique stat name. */ const FProfilerStat& GetStatByFName(FName StatName) const { return *StatFNameDescriptions.FindChecked(StatName); } /** * @return an instance of a const iterator for the stat descriptions. */ const TMap::TConstIterator GetStatIterator() const { return StatDescriptions.CreateConstIterator(); } /** * @return a reference to the group description specified by the group ID */ const FProfilerGroup& GetGroup(const uint32 GroupID) const { return *GroupDescriptions.FindChecked(GroupID); } /** * @return an instance of a const iterator for the stat group descriptions. */ const TMap::TConstIterator GetGroupIterator() const { return GroupDescriptions.CreateConstIterator(); } /** * @return a reference to the thread descriptions. */ const TMap& GetThreadDescriptions() const { return ThreadDescriptions; } /** * @return seconds per CPU cycle */ const double GetSecondsPerCycle() const { return SecondsPerCycle; } /** * @return the specified number of cycles converted to milliseconds. */ const double ConvertCyclesToMS(const uint32 Cycles) const { return SecondsPerCycle * 1000 * Cycles; } /** * @return the profiler sample type for the specified stat ID. */ const EProfilerSampleTypes::Type GetSampleTypeForStatID(const uint32 StatID) const { return GetStatByID(StatID).Type(); } /** * @return true, if the stat for the specified stat ID has been initialized. */ const bool IsStatInitialized(const uint32 StatID) { return StatDescriptions.Contains(StatID); } const uint32 GetGameThreadID() const { return GameThreadID; } const TArray& GetRenderThreadID() const { return RenderThreadIDs; } bool IsReady() const { return GameThreadID != 0; } const uint32 GetGameThreadStatID() const { return ThreadIDtoStatID.FindChecked(GameThreadID); } protected: /** All initialized stat descriptions, stored as StatID -> FProfilerStat. */ TMap StatDescriptions; /** All initialized stat descriptions, stored as unique stat name -> FProfilerStat. */ TMap StatFNameDescriptions; /** All initialized stat group descriptions, stored as StatID -> FProfilerGroup. */ TMap GroupDescriptions; /** Thread descriptions, stored as ThreadID -> ThreadDesc/Name. */ TMap ThreadDescriptions; /** * Helper map, as a part of migration into stats2, stored as ThreadID -> StatID. * Used during creating a thread sample, so we can use the real stat id and get data graph for this thread */ TMap ThreadIDtoStatID; /** Seconds per CPU cycle. */ double SecondsPerCycle; /** Game thread id. */ uint32 GameThreadID; /** Array of all render thread ids. */ TArray RenderThreadIDs; }; /** Holds the aggregated information for the specific stat across all frames that have been captured. */ class FProfilerAggregatedStat { friend class FProfilerSession; public: enum Type { EAvgValue, EMinValue, EMaxValue, EAvgNumCalls, EMinNumCalls, EMaxNumCalls, EFramesWithCallPct, EInvalidOrMax }; /** Default constructor. */ FProfilerAggregatedStat(const FName& InStatName, const FName& InGroupName, EProfilerSampleTypes::Type InStatType); public: /** @return The average value of all combined instances. */ const double AvgValue() const { return _ValueAllFrames / (double)_NumFrames; } /** @return The min value of all combined instances. */ const double MinValue() const { return _MinValueAllFrames; } /** @return The max value of all combined instances. */ const double MaxValue() const { return _MaxValueAllFrames; } /** @return The average number of calls of all combined instances. */ const float AvgNumCalls() const { return static_cast((double)_NumCallsAllFrames / (double)_NumFrames); } /** @return The min number of calls of all combined instances. */ const float MinNumCalls() const { return (float)_MinNumCallsAllFrames; } /** @return The max number of calls of all combined instances. */ const float MaxNumCalls() const { return (float)_MaxNumCallsAllFrames; } /** * @return the percentage of how often the stat is called, only matters for the hierarchical stat */ const float FramesWithCallPct() const { return static_cast((double)_NumFramesWithCall / (double)_NumFrames * 100.0); } /** * @return true, if this aggregated has a valid calls stats, only matters for the hierarchical stat. */ const bool HasCalls() const { return StatType == EProfilerSampleTypes::HierarchicalTime; } /** * @return a string representation of this aggregated stat. */ FString ToString() const; /** * @return a string representation of the specified value type. */ FString GetFormattedValue(const Type ValueType) const; protected: /** Called once a frame to update aggregates. */ void Advance(); /** * Adds a profiler sample to our aggregated data * * @param Sample - a reference to the profiler sample that will be aggregated * */ void Aggregate(const FProfilerSample& Sample, const TSharedRef& Metadata); protected: FName _StatName; FName _GroupName; /** The accumulated value of all instances for this stat for one frame. */ double _ValueOneFrame; /** The accumulated value of all instances for this stat across all frames. */ double _ValueAllFrames; /** The minimum value of all instances for this stat across all frames. */ double _MinValueAllFrames; /** The maximum value of all instances for this stat across all frames. */ double _MaxValueAllFrames; /** The number of times this stat has been called on all frames. */ uint64 _NumCallsAllFrames; /** The number of times this stat has been called on one frame. */ uint32 _NumCallsOneFrame; /** The minimum number of times this stat has been called on all frames. */ uint32 _MinNumCallsAllFrames; /** The maximum number of times this stat has been called on all frames. */ uint32 _MaxNumCallsAllFrames; /** Number of frames. */ uint32 _NumFrames; /** Number of frames with a least one call to this stat. */ uint32 _NumFramesWithCall; /** Stat type. */ const EProfilerSampleTypes::Type StatType; }; //template <> struct TIsPODType { enum { Value = true }; }; // @TODO: Standardize naming used in the profiler session/ session / session instance. /** * Class that holds the profiler session information. */ class FProfilerSession : public TSharedFromThis { friend class FProfilerManager; friend class FProfilerActionManager; protected: /** Default constructor. */ FProfilerSession( EProfilerSessionTypes InSessionType, const TSharedPtr& InSessionInstanceInfo, FGuid InSessionInstanceID, FString InDataFilepath); public: /** * Initialization constructor, creates a profiler session from a capture file. */ FProfilerSession(const FString& InDataFilepath); /** * Initialization constructor, creates a live profiler session. */ FProfilerSession(const TSharedPtr& InSessionInstanceInfo); /** Destructor. */ ~FProfilerSession(); public: /** Updates this profiler session. */ bool HandleTicker(float DeltaTime); public: typedef TMap FThreadTimesMap; typedef TSharedRef FProfilerStatMetaDataRef; DECLARE_DELEGATE_ThreeParams(FAddThreadTimeDelegate, int32 /*FrameIndex*/, const FThreadTimesMap& /*ThreadMS*/, const FProfilerStatMetaDataRef& /*StatMetaData*/); FProfilerSession& SetOnAddThreadTime(const FAddThreadTimeDelegate& InOnAddThreadTime) { OnAddThreadTime = InOnAddThreadTime; return *this; } protected: FAddThreadTimeDelegate OnAddThreadTime; public: /** * The delegate to execute when this profiler session has fully processed a capture file and profiler manager can update all widgets. * * @param SessionInstanceID - the session instance ID of this session, used to determine of which session this method should be called * */ DECLARE_DELEGATE_OneParam(FCaptureFileProcessedDelegate, const FGuid /*SessionInstanceID*/); /** * Sets the handler that will be invoked when this profiler session has fully processed a capture file * * @return This instance (for method chaining). */ FProfilerSession& SetOnCaptureFileProcessed(const FCaptureFileProcessedDelegate& InOnCaptureFileProcessed) { OnCaptureFileProcessed = InOnCaptureFileProcessed; return *this; } protected: /** The delegate to execute when this profiler session has fully processed a capture file and profiler manager can update all widgets. */ FCaptureFileProcessedDelegate OnCaptureFileProcessed; public: /** * @return the name of this profiler session */ const FString GetName() const { FString SessionName; if(SessionType == EProfilerSessionTypes::Live) { SessionName = FString::Printf(TEXT("%s"), *SessionInstanceInfo->GetInstanceName()); } else if(SessionType == EProfilerSessionTypes::StatsFile) { SessionName = FString::Printf(TEXT("%s"), *DataFilepath); } else if(SessionType == EProfilerSessionTypes::StatsFileRaw) { SessionName = FString::Printf(TEXT("%s"), *DataFilepath); } return SessionName; } /** * @return the short name of this profiler session */ const FString GetShortName() const { return FProfilerHelper::ShortenName(GetName(), 12); } /** * @return session type for this profiler session */ const EProfilerSessionTypes GetSessionType() const { return SessionType; } /** * @return an unique session instance ID. */ const FGuid GetInstanceID() const { return SessionInstanceID; } /** * @return the time when this profiler session was created (time of the connection to the client, time when a profiler capture was created). */ const FDateTime& GetCreationTime() const { return CreationTime; } /** * @return a shared reference to the the data provider which holds all the collected profiler samples. */ const TSharedRef& GetDataProvider() const { return DataProvider; } /** * @return a shared reference to the stat metadata which holds all collected stats descriptions. */ const TSharedRef& GetMetaData() const { return StatMetaData; } /** * @return a const pointer to the aggregated stat for the specified stat ID or null if not found. */ FORCEINLINE_DEBUGGABLE const FProfilerAggregatedStat* GetAggregatedStat(const uint32 StatID) const { return AggregatedStats.Find(StatID); } FORCEINLINE_DEBUGGABLE const TMap& GetInclusiveAggregateStackStats(const uint32 FrameIndex) const { return InclusiveAggregateStackStats[FrameIndex]; } const TSharedRef GetEventGraphDataTotal() const; const TSharedRef GetEventGraphDataMaximum() const; const TSharedRef GetEventGraphDataAverage() const; /** * @return number of bytes allocated by this profiler session. */ const SIZE_T GetMemoryUsage() const; /** * @return a new instance of the graph data source for the specified stat ID. */ TSharedRef CreateGraphDataSource(const uint32 InStatID); /** * @return a new instance of the event graph container for the specified frame range. */ FEventGraphContainer CreateEventGraphData(const uint32 FrameStartIndex, const uint32 FrameEndIndex); /** Combines event graphs for the specified frames range. */ FEventGraphData* CombineEventGraphs(const uint32 FrameStartIndex, const uint32 FrameEndIndex); /** Combines event graphs for the specified frames range, as the task graph task. */ void CombineEventGraphsTask(const uint32 FrameStartIndex, const uint32 FrameEndIndex); protected: /** * Recursively populates hierarchy based on the specified profiler cycle graph. * * @param ParentGraph * @param ParentStartTimeMS * @param ParentDurationMS * @param ParentSampleIndex * @return */ void PopulateHierarchy_Recurrent ( const uint32 StatThreadID, const FProfilerCycleGraph& ParentGraph, const uint32 ParentDurationCycles, const uint32 ParentSampleIndex, TMap& StatIDToInclusiveTime ); /** Called when this profiler session receives a new profiler data. */ void UpdateProfilerData(const FProfilerDataFrame& Content); /** Called when this profiler session receives information that the meta data has been updated. @see FProfilerMetaDataUpdateDelegate and IProfilerClient */ void UpdateMetadata(const FStatMetaData& InClientStatMetaData); /** * Updates aggregated stats. * * @param FrameIndex - the index of the profiler samples that will be used to update the aggregated stats. * */ void UpdateAggregatedStats(const uint32 FrameIndex); /** * Updates aggregated event graphs. * * @param FrameIndex - the index of the profiler samples that will be used to update the aggregated stats. * */ void UpdateAggregatedEventGraphData(const uint32 FrameIndex); /** Completion sync. */ void CompletionSyncAggregatedEventGraphData(); void EventGraphCombine(const FEventGraphData* Current, const uint32 InNumFrames); void UpdateAllEventGraphs(const uint32 InNumFrames); /** Called when the capture file has been fully loaded. */ void LoadComplete(); /** Sets number of frames. */ void SetNumberOfFrames(int32 InNumFrames); /** * @return progress as floating point between 0 and 1. */ float GetProgress() const; protected: /** All aggregated stats, stored as StatID -> FProfilerAggregatedStat. */ TMap AggregatedStats; /** Inclusive aggregated stack stack for all frames. FrameIndex < StatID, StatValue > */ TArray< TMap > InclusiveAggregateStackStats; // TODO: This part will go away once we fully switch over to the stats2. //{ /** Profiler data collected for the previous frames. */ TMap FrameToProfilerDataMapping; /** Frame indices that should be processed by the profiler manager. */ TArray FrameToProcess; /** Copy of the client stats metadata. */ FStatMetaData ClientStatMetadata; /** If true, we need to update the metadata before we update the data provider. */ bool bRequestStatMetadataUpdate; bool bLastPacket; uint32 StatMetaDataSize; //} /** The delegate to be invoked when this profiler session instance ticks. */ FTickerDelegate OnTick; /** Handle to the registered OnTick. */ FTSTicker::FDelegateHandle OnTickHandle; /** The data provider which holds all the collected profiler samples. */ TSharedRef DataProvider; /** The stat metadata which holds all collected stats descriptions. */ TSharedRef StatMetaData; /** Aggregated event graph data for all collected frames, used for generating average values. Also contains min and max. */ FEventGraphDataPtr EventGraphDataTotal; /** Highest "per-frame" event graph. */ FEventGraphDataPtr EventGraphDataMaximum; /** Per-frame average event graph. */ FEventGraphDataPtr EventGraphDataAverage; /** Temporary event graph data for the specified frame. Recreated each frame, used by the task graph tasks only. */ const FEventGraphData* EventGraphDataCurrent; /** Event graph completion sync (combine for max, combine for add) that can be done in parallel, but need to wait before combining the next frame. */ FGraphEventRef CompletionSync; /** Combined event graphs calculated on the task graph threads. */ TLockFreePointerListFIFO CombinedSubEventGraphsLFL; // TODO: Temporary, need to be stored in metadata or send via UMB. /** The time when this profiler session was created (time of the connection to the client, time when a capture file was created). */ FDateTime CreationTime; /** Session type for this profiler session. */ EProfilerSessionTypes SessionType; /** Shared pointer to the session instance info. */ const TSharedPtr SessionInstanceInfo; /** An unique session instance ID. */ FGuid SessionInstanceID; /** Data filepath. */ FString DataFilepath; /** Number of frames in the file. */ int32 NumFrames; /** Number of frames already processed. */ int32 NumFramesProcessed; /** True, if this profiler session instance is currently previewing data, only valid if profiler is connected to network based session. */ bool bDataPreviewing; /** True, if this profiler session instance is currently capturing data to a file, only valid if profiler is connected to network based session. */ bool bDataCapturing; /** True, if this profiler session instance has the whole profiler data, but it still needs to be processed by the tick method. */ bool bHasAllProfilerData; public: /** Provides analysis of the frame rate */ TSharedRef FPSAnalyzer; }; #endif // STATS