Files
UnrealEngine/Engine/Source/Developer/Profiler/Private/ProfilerManager.cpp
2025-05-18 13:04:45 +08:00

698 lines
22 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "ProfilerManager.h"
#if STATS
#include "Modules/ModuleManager.h"
#include "IProfilerClientModule.h"
#include "Stats/StatsFile.h"
#include "ProfilerDataProvider.h"
#include "ProfilerRawStatsForThreadView.h"
#include "Widgets/SProfilerMiniView.h"
#include "Widgets/SProfilerWindow.h"
#include "Templates/UniquePtr.h"
#define LOCTEXT_NAMESPACE "FProfilerCommands"
DEFINE_LOG_CATEGORY(Profiler);
FProfilerSettings FProfilerSettings::Defaults( true );
DEFINE_STAT(STAT_DG_OnPaint);
DEFINE_STAT(STAT_PM_HandleProfilerData);
DEFINE_STAT(STAT_PM_Tick);
DEFINE_STAT(STAT_PM_MemoryUsage);
TSharedPtr<FProfilerManager> FProfilerManager::Instance = nullptr;
struct FEventGraphSampleLess
{
FORCEINLINE bool operator()(const FEventGraphSample& A, const FEventGraphSample& B) const
{
return A._InclusiveTimeMS < B._InclusiveTimeMS;
}
};
FProfilerManager::FProfilerManager( const TSharedRef<ISessionManager>& InSessionManager )
: SessionManager( InSessionManager )
, CommandList( new FUICommandList() )
, ProfilerActionManager( this )
, Settings()
, ProfilerType( EProfilerSessionTypes::InvalidOrMax )
, bLivePreview( false )
, bHasCaptureFileFullyProcessed( false )
{
FEventGraphSample::InitializePropertyManagement();
#if 0
// Performance tests.
static FTotalTimeAndCount CurrentNative(0.0f, 0);
static FTotalTimeAndCount CurrentPointer(0.0f, 0);
static FTotalTimeAndCount CurrentShared(0.0f, 0);
for( int32 Lx = 0; Lx < 16; ++Lx )
{
FRandomStream RandomStream( 666 );
TArray<FEventGraphSample> EventsNative;
TArray<FEventGraphSample*> EventsPointer;
TArray<FEventGraphSamplePtr> EventsShared;
const int32 NumEvents = 16384;
for( int32 Nx = 0; Nx < NumEvents; ++Nx )
{
const double Rnd = RandomStream.FRandRange( 0.0f, 16384.0f );
const FString EventName = TTypeToString<double>::ToString( Rnd );
FEventGraphSample NativeEvent( *EventName );
NativeEvent._InclusiveTimeMS = Rnd;
FEventGraphSamplePtr SharedEvent = FEventGraphSample::CreateNamedEvent( *EventName );
SharedEvent->_InclusiveTimeMS = Rnd;
EventsNative.Add(NativeEvent);
EventsPointer.Add(SharedEvent.Get());
EventsShared.Add(SharedEvent);
}
{
FProfilerScopedLogTime ScopedLog( TEXT("1.NativeSorting"), &CurrentNative );
EventsNative.Sort( FEventGraphSampleLess() );
}
{
FProfilerScopedLogTime ScopedLog( TEXT("2PointerSorting"), &CurrentPointer );
EventsPointer.Sort( FEventGraphSampleLess() );
}
{
FProfilerScopedLogTime ScopedLog( TEXT("3.SharedSorting"), &CurrentShared );
FEventArraySorter::Sort( EventsShared, FEventGraphSample::GetEventPropertyByIndex(EEventPropertyIndex::InclusiveTimeMS).Name, EEventCompareOps::Less );
}
}
#endif // 0
}
void FProfilerManager::PostConstructor()
{
// Register tick functions.
OnTick = FTickerDelegate::CreateSP( this, &FProfilerManager::Tick );
OnTickHandle = FTSTicker::GetCoreTicker().AddTicker( OnTick, 1.0f );
// Create profiler client.
ProfilerClient = FModuleManager::GetModuleChecked<IProfilerClientModule>("ProfilerClient").CreateProfilerClient();
// Register profiler client delegates.
ProfilerClient->OnProfilerData().AddSP(this, &FProfilerManager::ProfilerClient_OnProfilerData);
ProfilerClient->OnProfilerClientConnected().AddSP(this, &FProfilerManager::ProfilerClient_OnClientConnected);
ProfilerClient->OnProfilerClientDisconnected().AddSP(this, &FProfilerManager::ProfilerClient_OnClientDisconnected);
ProfilerClient->OnLoadStarted().AddSP(this, &FProfilerManager::ProfilerClient_OnLoadStarted);
ProfilerClient->OnLoadCompleted().AddSP(this, &FProfilerManager::ProfilerClient_OnLoadCompleted);
ProfilerClient->OnLoadCancelled().AddSP(this, &FProfilerManager::ProfilerClient_OnLoadCancelled);
ProfilerClient->OnMetaDataUpdated().AddSP(this, &FProfilerManager::ProfilerClient_OnMetaDataUpdated);
ProfilerClient->OnProfilerFileTransfer().AddSP(this, &FProfilerManager::ProfilerClient_OnProfilerFileTransfer);
SessionManager->OnInstanceSelectionChanged().AddSP( this, &FProfilerManager::SessionManager_OnInstanceSelectionChanged );
SetDataPreview( false );
SetDataCapture( false );
FProfilerCommands::Register();
BindCommands();
}
void FProfilerManager::BindCommands()
{
ProfilerActionManager.Map_ProfilerManager_Load();
ProfilerActionManager.Map_ProfilerManager_LoadMultiple();
ProfilerActionManager.Map_ToggleDataPreview_Global();
ProfilerActionManager.Map_ProfilerManager_ToggleLivePreview_Global();
ProfilerActionManager.Map_ToggleDataCapture_Global();
ProfilerActionManager.Map_OpenSettings_Global();
}
FProfilerManager::~FProfilerManager()
{
FProfilerCommands::Unregister();
// Unregister tick function.
FTSTicker::GetCoreTicker().RemoveTicker( OnTickHandle );
// Remove ourselves from the session manager.
if (SessionManager.IsValid())
{
SessionManager->OnCanSelectSession().RemoveAll( this );
SessionManager->OnSelectedSessionChanged().RemoveAll( this );
SessionManager->OnInstanceSelectionChanged().RemoveAll( this );
}
// Remove ourselves from the profiler client.
if( ProfilerClient.IsValid() )
{
ProfilerClient->Unsubscribe();
ProfilerClient->OnProfilerData().RemoveAll(this);
ProfilerClient->OnProfilerClientConnected().RemoveAll(this);
ProfilerClient->OnProfilerClientDisconnected().RemoveAll(this);
ProfilerClient->OnMetaDataUpdated().RemoveAll(this);
ProfilerClient->OnLoadCompleted().RemoveAll(this);
ProfilerClient->OnLoadStarted().RemoveAll(this);
ProfilerClient->OnProfilerFileTransfer().RemoveAll(this);
}
ClearStatsAndInstances();
}
TSharedPtr<FProfilerManager> FProfilerManager::Get()
{
return FProfilerManager::Instance;
}
FProfilerActionManager& FProfilerManager::GetActionManager()
{
return FProfilerManager::Instance->ProfilerActionManager;
}
FProfilerSettings& FProfilerManager::GetSettings()
{
return FProfilerManager::Instance->Settings;
}
const TSharedRef< FUICommandList > FProfilerManager::GetCommandList() const
{
return CommandList;
}
const FProfilerCommands& FProfilerManager::GetCommands()
{
return FProfilerCommands::Get();
}
TSharedPtr<FProfilerSession> FProfilerManager::GetProfilerSession()
{
return ProfilerSession;
}
class FStatsHeaderReader : public FStatsReadFile
{
friend struct FStatsReader<FStatsHeaderReader>;
typedef FStatsReadFile Super;
protected:
/** Initialization constructor. */
FStatsHeaderReader( const TCHAR* InFilename )
: FStatsReadFile( InFilename, false )
{}
};
static int32 GetNumFrameFromCaptureSlow( const FString& ProfilerCaptureFilepath )
{
TUniquePtr<FStatsHeaderReader> Instance( FStatsReader<FStatsHeaderReader>::Create( *ProfilerCaptureFilepath ) );
return Instance->GetNumFrames();
}
void FProfilerManager::LoadProfilerCapture( const FString& ProfilerCaptureFilepath )
{
// Deselect the active session.
if (ActiveSession.IsValid())
{
SessionManager->SelectSession( nullptr );
}
ClearStatsAndInstances();
ProfilerSession = MakeShareable( new FProfilerSession( ProfilerCaptureFilepath ) );
ActiveInstanceID = ProfilerSession->GetInstanceID();
ProfilerSession->
SetOnCaptureFileProcessed( FProfilerSession::FCaptureFileProcessedDelegate::CreateSP( this, &FProfilerManager::ProfilerSession_OnCaptureFileProcessed ) )
.SetOnAddThreadTime( FProfilerSession::FAddThreadTimeDelegate::CreateSP( this, &FProfilerManager::ProfilerSession_OnAddThreadTime ) );
ProfilerClient->LoadCapture( ProfilerCaptureFilepath, ActiveInstanceID );
const int32 NumFrames = GetNumFrameFromCaptureSlow( ProfilerCaptureFilepath );
ProfilerSession->SetNumberOfFrames( NumFrames );
SessionInstancesUpdatedEvent.Broadcast();
ProfilerType = EProfilerSessionTypes::StatsFile;
GetProfilerWindow()->ManageEventGraphTab( ActiveInstanceID, true, ProfilerSession->GetName() );
SetViewMode( EProfilerViewMode::LineIndexBased );
}
void FProfilerManager::LoadRawStatsFile( const FString& RawStatsFileFileath )
{
// #Profiler: Rework
#if 0
if (ActiveSession.IsValid())
{
SessionManager->SelectSession( NULL );
}
ClearStatsAndInstances();
TSharedRef<FRawProfilerSession> ProfilerSession = MakeShareable( new FRawProfilerSession( RawStatsFileFileath ) );
const FGuid ProfilerInstanceID = ProfilerSession->GetInstanceID();
//ProfilerSessionInstances.Add( ProfilerInstanceID, ProfilerSession );
ProfilerSession->
//SetOnCaptureFileProcessed( FProfilerSession::FCaptureFileProcessedDelegate::CreateSP( this, /&FProfilerManager::ProfilerSession_OnCaptureFileProcessed ) )
SetOnAddThreadTime( FProfilerSession::FAddThreadTimeDelegate::CreateSP( this, &FProfilerManager::ProfilerSession_OnAddThreadTime ) );
//ProfilerSessionInstances.Add( ProfilerInstanceID, ProfilerSession );
ProfilerSession->PrepareLoading();
RequestFilterAndPresetsUpdateEvent.Broadcast();
//ProfilerSession_OnCaptureFileProcessed( ProfilerInstanceID );
bHasCaptureFileFullyProcessed = true;
//TrackDefaultStats();
SessionInstancesUpdatedEvent.Broadcast();
ProfilerType = EProfilerSessionTypes::StatsFileRaw;
GetProfilerWindow()->ManageEventGraphTab( ProfilerInstanceID, true, ProfilerSession->GetName() );
SetViewMode( EProfilerViewMode::ThreadViewTimeBased );
GetProfilerWindow()->GraphPanel->ThreadView->AttachProfilerStream( ProfilerSession->GetStream() );
#endif // 0
}
bool FProfilerManager::Tick( float DeltaTime )
{
SCOPE_CYCLE_COUNTER(STAT_PM_Tick);
if (ProfilerSession.IsValid() && !bHasCaptureFileFullyProcessed)
{
static SIZE_T StartUsedPhysical = FPlatformMemory::GetStats().UsedPhysical;
const double MBInv = 1.0 / 1024.0 / 1024.0;
const SIZE_T DiffPhys = FPlatformMemory::GetStats().UsedPhysical - StartUsedPhysical;
const double SessionMemory = MBInv * (double)ProfilerSession->GetMemoryUsage();
const double PhysMemory = MBInv * (double)DiffPhys;
UE_LOG( LogStats, VeryVerbose, TEXT( "ProfilerSession: %6.2f MB (%6.2f MB) # (%6.2f MB) / %7u -> %4u" ),
SessionMemory,
PhysMemory,
PhysMemory - SessionMemory,
ProfilerSession->GetDataProvider()->GetNumSamples(),
ProfilerSession->GetDataProvider()->GetNumFrames() );
}
return true;
}
double LoadStartTime = 0.0;
void FProfilerManager::ProfilerSession_OnCaptureFileProcessed( const FGuid ProfilerInstanceID )
{
if (ProfilerSession.IsValid() && ProfilerWindow.IsValid())
{
TrackDefaultStats();
RequestFilterAndPresetsUpdateEvent.Broadcast();
GetProfilerWindow()->UpdateEventGraph( ProfilerInstanceID, ProfilerSession->GetEventGraphDataAverage(), ProfilerSession->GetEventGraphDataMaximum(), true );
bHasCaptureFileFullyProcessed = true;
const double TotalLoadTime = FPlatformTime::Seconds() - LoadStartTime;
const FString Description = ProfilerSession->GetName();
UE_LOG( LogStats, Warning, TEXT( "OnCaptureFileProcessed: %s" ), *Description );
UE_LOG( LogStats, Warning, TEXT( "TotalLoadTime: %.2f" ), TotalLoadTime );
// Update the notification that a file has been fully processed.
GetProfilerWindow()->ManageLoadingProgressNotificationState( Description, EProfilerNotificationTypes::LoadingOfflineCapture, ELoadingProgressStates::Loaded, 1.0f );
}
}
const bool FProfilerManager::IsDataPreviewing() const
{
return IsConnected() && ProfilerSession.IsValid() && ProfilerSession->bDataPreviewing;
}
void FProfilerManager::SetDataPreview( const bool bRequestedDataPreviewState )
{
ProfilerClient->SetPreviewState( bRequestedDataPreviewState );
if (ProfilerSession.IsValid())
{
ProfilerSession->bDataPreviewing = bRequestedDataPreviewState;
}
}
const bool FProfilerManager::IsDataCapturing() const
{
return IsConnected() && ProfilerSession.IsValid() && ProfilerSession->bDataCapturing;
}
void FProfilerManager::SetDataCapture( const bool bRequestedDataCaptureState )
{
ProfilerClient->SetCaptureState( bRequestedDataCaptureState );
if (ProfilerSession.IsValid())
{
ProfilerSession->bDataCapturing = bRequestedDataCaptureState;
}
}
/*-----------------------------------------------------------------------------
ProfilerClient
-----------------------------------------------------------------------------*/
void FProfilerManager::ProfilerClient_OnProfilerData( const FGuid& InstanceID, const FProfilerDataFrame& Content )
{
SCOPE_CYCLE_COUNTER(STAT_PM_HandleProfilerData);
if (ProfilerSession.IsValid())
{
ProfilerSession->UpdateProfilerData( Content );
// Game thread should always be enabled.
TrackDefaultStats();
}
}
void FProfilerManager::ProfilerClient_OnMetaDataUpdated( const FGuid& InstanceID, const FStatMetaData& MetaData )
{
if (ProfilerSession.IsValid())
{
ProfilerSession->UpdateMetadata( MetaData );
if (ProfilerSession->GetSessionType() == EProfilerSessionTypes::Live)
{
RequestFilterAndPresetsUpdateEvent.Broadcast();
}
}
}
void FProfilerManager::ProfilerClient_OnLoadStarted( const FGuid& InstanceID )
{
if (ProfilerSession.IsValid() && GetProfilerWindow().IsValid())
{
const FString Description = ProfilerSession->GetName();
UE_LOG( LogStats, Warning, TEXT( "OnLoadStarted: %s" ), *Description );
LoadStartTime = FPlatformTime::Seconds();
// Display the notification that a file is being loaded.
GetProfilerWindow()->ManageLoadingProgressNotificationState( Description, EProfilerNotificationTypes::LoadingOfflineCapture, ELoadingProgressStates::Started, 0.0f );
}
}
void FProfilerManager::ProfilerClient_OnLoadCompleted( const FGuid& InstanceID )
{
// Inform that the file has been loaded and we can hide the notification.
if (ProfilerSession.IsValid())
{
ProfilerSession->LoadComplete();
const FString Description = ProfilerSession->GetName();
UE_LOG( LogStats, Warning, TEXT( "OnLoadCompleted: %s" ), *Description );
}
}
void FProfilerManager::ProfilerClient_OnLoadCancelled(const FGuid& InstanceID)
{
// Inform that the load was cancelled and close the progress notification.
if (ProfilerSession.IsValid())
{
const FString Description = ProfilerSession->GetName();
UE_LOG(LogStats, Warning, TEXT("OnLoadCancelled: %s"), *Description);
GetProfilerWindow()->ManageLoadingProgressNotificationState(Description, EProfilerNotificationTypes::LoadingOfflineCapture, ELoadingProgressStates::Cancelled, 0.0f);
}
}
void FProfilerManager::ProfilerClient_OnProfilerFileTransfer( const FString& Filename, int64 FileProgress, int64 FileSize )
{
// Display and update the notification a file that is being sent.
const float Progress = static_cast<float>((double)FileProgress/(double)FileSize);
ELoadingProgressStates ProgressState = ELoadingProgressStates::InvalidOrMax;
if( FileProgress == 0 )
{
ProgressState = ELoadingProgressStates::Started;
}
else if( FileProgress == -1 && FileSize == -1 )
{
ProgressState = ELoadingProgressStates::Failed;
}
else if( FileProgress > 0 && FileProgress < FileSize )
{
ProgressState = ELoadingProgressStates::InProgress;
}
else if( FileProgress == FileSize )
{
ProgressState = ELoadingProgressStates::Loaded;
}
if( ProfilerWindow.IsValid() )
{
ProfilerWindow.Pin()->ManageLoadingProgressNotificationState( Filename, EProfilerNotificationTypes::SendingServiceSideCapture, ProgressState, Progress );
}
}
void FProfilerManager::ProfilerClient_OnClientConnected( const FGuid& SessionID, const FGuid& InstanceID )
{
}
void FProfilerManager::ProfilerClient_OnClientDisconnected( const FGuid& SessionID, const FGuid& InstanceID )
{
}
/*-----------------------------------------------------------------------------
SessionManager
-----------------------------------------------------------------------------*/
void FProfilerManager::SessionManager_OnInstanceSelectionChanged(const TSharedPtr<ISessionInstanceInfo>& InInstance, bool Selected)
{
const TSharedPtr<ISessionInfo>& SelectedSession = SessionManager->GetSelectedSession();
const bool SessionIsValid = SelectedSession.IsValid()
&& (SelectedSession->GetSessionOwner() == FPlatformProcess::UserName(false))
&& (SessionManager->GetSelectedInstances().Num() > 0);
if (InInstance->GetInstanceId() != ActiveInstanceID && SessionIsValid && InInstance.IsValid() && Selected)
{
ClearStatsAndInstances();
if (SessionIsValid)
{
ActiveSession = SelectedSession;
ActiveInstanceID = InInstance->GetInstanceId();
ProfilerClient->Subscribe( ActiveSession->GetSessionId() );
ProfilerType = EProfilerSessionTypes::Live;
SetViewMode( EProfilerViewMode::LineIndexBased );
}
else
{
ActiveSession = nullptr;
ProfilerClient->Unsubscribe();
ProfilerType = EProfilerSessionTypes::InvalidOrMax;
}
if (ActiveSession.IsValid())
{
ProfilerSession = MakeShareable( new FProfilerSession( InInstance ) );
ProfilerSession->SetOnAddThreadTime( FProfilerSession::FAddThreadTimeDelegate::CreateSP( this, &FProfilerManager::ProfilerSession_OnAddThreadTime ) );
ProfilerClient->Track( ActiveInstanceID );
TSharedPtr<SProfilerWindow> ProfilerWindowPtr = GetProfilerWindow();
if (ProfilerWindowPtr.IsValid())
{
ProfilerWindowPtr->ManageEventGraphTab( ActiveInstanceID, true, ProfilerSession->GetName() );
}
}
RequestFilterAndPresetsUpdateEvent.Broadcast();
}
SessionInstancesUpdatedEvent.Broadcast();
}
/*-----------------------------------------------------------------------------
Stat tracking
-----------------------------------------------------------------------------*/
bool FProfilerManager::TrackStat( const uint32 StatID )
{
bool bAdded = false;
// Check if all profiler instances have this stat ready.
const bool bStatIsReady = ProfilerSession->GetAggregatedStat( StatID ) != nullptr;
if( StatID != 0 && bStatIsReady )
{
TSharedPtr<FTrackedStat> TrackedStat = TrackedStats.FindRef( StatID );
if (!TrackedStat.IsValid())
{
// R = H, G = S, B = V
const FLinearColor GraphColor = GetColorForStatID( StatID );
// const FLinearColor ColorAverageHSV = ColorAverage.LinearRGBToHSV();
//
// FLinearColor ColorBackgroundHSV = ColorAverageHSV;
// ColorBackgroundHSV.G = FMath::Max( 0.0f, ColorBackgroundHSV.G-0.25f );
//
// FLinearColor ColorExtremesHSV = ColorAverageHSV;
// ColorExtremesHSV.G = FMath::Min( 1.0f, ColorExtremesHSV.G+0.25f );
// ColorExtremesHSV.B = FMath::Min( 1.0f, ColorExtremesHSV.B+0.25f );
//
// const FLinearColor ColorBackground = ColorBackgroundHSV.HSVToLinearRGB();
// const FLinearColor ColorExtremes = ColorExtremesHSV.HSVToLinearRGB();
TrackedStat = TrackedStats.Add( StatID, MakeShareable( new FTrackedStat( ProfilerSession->CreateGraphDataSource( StatID ), GraphColor, StatID ) ) );
bAdded = true;
TrackedStatChangedEvent.Broadcast( TrackedStat, true );
}
}
return bAdded;
}
bool FProfilerManager::UntrackStat( const uint32 StatID )
{
bool bRemoved = false;
// Game thread time is always tracked.
const uint32 GameThreadStatID = ProfilerSession->GetMetaData()->GetGameThreadStatID();
if (StatID != GameThreadStatID)
{
TSharedPtr<FTrackedStat> TrackedStat = TrackedStats.FindRef( StatID );
if (TrackedStat.IsValid())
{
TrackedStatChangedEvent.Broadcast( TrackedStat, false );
TrackedStats.Remove( StatID );
bRemoved = true;
}
}
return bRemoved;
}
void FProfilerManager::ClearStatsAndInstances()
{
CloseAllEventGraphTabs();
ProfilerType = EProfilerSessionTypes::InvalidOrMax;
ViewMode = EProfilerViewMode::InvalidOrMax;
SetDataPreview( false );
bLivePreview = false;
SetDataCapture( false );
bHasCaptureFileFullyProcessed = false;
for( auto It = TrackedStats.CreateConstIterator(); It; ++It )
{
const TSharedPtr<FTrackedStat>& TrackedStat = It.Value();
TrackedStatChangedEvent.Broadcast( TrackedStat, false );
}
TrackedStats.Empty();
ProfilerClient->Untrack( ActiveInstanceID );
ProfilerClient->CancelLoading( ActiveInstanceID );
ActiveInstanceID.Invalidate();
}
const bool FProfilerManager::IsStatTracked( const uint32 StatID ) const
{
return TrackedStats.Contains( StatID );
}
// @TODO: Move to profiler settings
const FLinearColor& FProfilerManager::GetColorForStatID( const uint32 StatID ) const
{
static TMap<uint32,FLinearColor> StatID2ColorMapping;
FLinearColor* Color = StatID2ColorMapping.Find( StatID );
if( !Color )
{
const FColor RandomColor = FColor::MakeRandomColor();
Color = &StatID2ColorMapping.Add( StatID, FLinearColor(RandomColor) );
}
return *Color;
}
void FProfilerManager::TrackDefaultStats()
{
// Find StatId for the game thread.
if (ProfilerSession.IsValid())
{
if( ProfilerSession->GetMetaData()->IsReady() )
{
TrackStat( ProfilerSession->GetMetaData()->GetGameThreadStatID() );
}
}
}
/*-----------------------------------------------------------------------------
Event graphs management
-----------------------------------------------------------------------------*/
void FProfilerManager::CloseAllEventGraphTabs()
{
TSharedPtr<SProfilerWindow> ProfilerWindowPtr = GetProfilerWindow();
if( ProfilerWindowPtr.IsValid() )
{
// Iterate through all profiler sessions.
if (ProfilerSession.IsValid())
{
ProfilerWindowPtr->ManageEventGraphTab( ProfilerSession->GetInstanceID(), false, TEXT("") );
}
ProfilerWindowPtr->ProfilerMiniView->Reset();
}
}
void FProfilerManager::DataGraph_OnSelectionChangedForIndex( uint32 FrameStartIndex, uint32 FrameEndIndex )
{
// SCOPE_LOG_TIME_FUNC();
if (ProfilerSession.IsValid())
{
FEventGraphContainer EventGraphContainer = ProfilerSession->CreateEventGraphData( FrameStartIndex, FrameEndIndex );
GetProfilerWindow()->UpdateEventGraph( ProfilerSession->GetInstanceID(), EventGraphContainer.Average, EventGraphContainer.Maximum, false );
}
}
void FProfilerManager::ProfilerSession_OnAddThreadTime( int32 FrameIndex, const TMap<uint32, float>& ThreadMS, const TSharedRef<FProfilerStatMetaData>& StatMetaData )
{
TSharedPtr<SProfilerWindow> ProfilerWindowPtr = GetProfilerWindow();
if( ProfilerWindowPtr.IsValid() )
{
ProfilerWindowPtr->ProfilerMiniView->AddThreadTime( FrameIndex, ThreadMS, StatMetaData );
// Update the notification that a file is being loaded.
const float DataLoadingProgress = ProfilerSession->GetProgress();
ProfilerWindowPtr->ManageLoadingProgressNotificationState( ProfilerSession->GetName(), EProfilerNotificationTypes::LoadingOfflineCapture, ELoadingProgressStates::InProgress, DataLoadingProgress );
}
}
void FProfilerManager::SetViewMode( EProfilerViewMode NewViewMode )
{
if( NewViewMode != ViewMode )
{
// Broadcast.
OnViewModeChangedEvent.Broadcast( NewViewMode );
ViewMode = NewViewMode;
}
}
#undef LOCTEXT_NAMESPACE
#endif // STATS