You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
361 lines
10 KiB
C++
361 lines
10 KiB
C++
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
|
|
#define PROFILER_THREADED_LOAD 1
|
|
|
|
|
|
/** Helper struct containing all of the data and operations associated with a service connection */
|
|
struct FServiceConnection
|
|
{
|
|
FServiceConnection()
|
|
: DataLoadingProgress( 0.0f )
|
|
, ReadMessages(0)
|
|
{
|
|
MetaData.CriticalSection = &CriticalSection;
|
|
CurrentFrame = 0;
|
|
}
|
|
|
|
~FServiceConnection()
|
|
{
|
|
MetaData.CriticalSection = NULL;
|
|
}
|
|
|
|
FServiceConnection(const FServiceConnection& InConnnection)
|
|
{
|
|
MetaData.CriticalSection = &CriticalSection;
|
|
CurrentFrame = 0;
|
|
}
|
|
|
|
/** Instance Id */
|
|
FGuid InstanceId;
|
|
|
|
/** Service endpoint */
|
|
FMessageAddress ServiceAddress;
|
|
|
|
/** Descriptions for the stats */
|
|
FStatMetaData MetaData;
|
|
|
|
/** Current frame worth of data */
|
|
FProfilerDataFrame CurrentData;
|
|
|
|
/** Initialize the connection from the given authorization message and context */
|
|
void Initialize( const FProfilerServiceAuthorize2& Message, const IMessageContextRef& Context );
|
|
|
|
#if STATS
|
|
/** Current stats data */
|
|
FStatsThreadState CurrentThreadState;
|
|
#endif
|
|
|
|
/** Provides an FName to GroupId mapping */
|
|
TMap<FName, int32> GroupNameArray;
|
|
|
|
/** Provides the long stat name to StatId mapping. */
|
|
TMap<FName,int32> LongNameToStatID;
|
|
|
|
#if STATS
|
|
/** Stream reader */
|
|
FStatsReadStream Stream;
|
|
|
|
/** Pending stat messages */
|
|
TArray<FStatMessage> Messages;
|
|
#endif
|
|
|
|
/** Pending Data frames on a load */
|
|
TArray<FProfilerDataFrame> DataFrames;
|
|
|
|
/** Current data loading progress. */
|
|
float DataLoadingProgress;
|
|
|
|
/** Current frame of data to process */
|
|
int64 CurrentFrame;
|
|
|
|
/** Current number of read messages. */
|
|
uint64 ReadMessages;
|
|
|
|
/** Messages received and pending process, they are stored in a map as we can receive them out of order */
|
|
TMap<int64, TArray<uint8> > PendingMessages;
|
|
|
|
/** Critical Section needed to synchronize */
|
|
FCriticalSection CriticalSection;
|
|
|
|
#if STATS
|
|
// generates the old style cycle graph
|
|
void GenerateCycleGraphs(const FRawStatStackNode& Root, TMap<uint32, FProfilerCycleGraph>& Graphs);
|
|
|
|
// recursive call to generate the old cycle graph
|
|
void CreateGraphRecursively(const FRawStatStackNode* Root, FProfilerCycleGraph& Graph, uint32 InStartCycles);
|
|
|
|
// generates the old style accumulators
|
|
void GenerateAccumulators(TArray<FStatMessage>& Stats, TArray<FProfilerCountAccumulator>& CountAccumulators, TArray<FProfilerFloatAccumulator>& FloatAccumulators);
|
|
|
|
// adds a new style stat FName to the list of stats and generates an old style id and description
|
|
int32 FindOrAddStat( const FStatNameAndInfo& StatNameAndInfo, uint32 StatType );
|
|
|
|
// adds a new style stat FName to the list of threads and generates an old style id and description
|
|
int32 FindOrAddThread(const FStatNameAndInfo& Thread);
|
|
|
|
// updates the meta date for the given instance
|
|
void UpdateMetaData();
|
|
|
|
|
|
/**
|
|
* Reads stat message from the archive and converts them to be usable by the profiler..
|
|
*
|
|
* @return true if read a special marker that indicates end of file
|
|
*/
|
|
bool ReadAndConvertStatMessages( FArchive& Reader, bool bUseInAsync );
|
|
|
|
/** Adds all collected stat messages to the current stats thread state. */
|
|
void AddCollectedStatMessages( FStatMessage Message );
|
|
|
|
/** Generates profiler data frame based on the collected stat messages. */
|
|
void GenerateProfilerDataFrame();
|
|
#endif
|
|
};
|
|
|
|
/**
|
|
* Implements the ProfileClient manager.
|
|
*/
|
|
class FProfilerClientManager
|
|
: public IProfilerClient
|
|
{
|
|
class FAsyncReadWorker : public FNonAbandonableTask
|
|
{
|
|
public:
|
|
FServiceConnection* LoadConnection;
|
|
FArchive* FileReader;
|
|
|
|
/** Constructor */
|
|
FAsyncReadWorker(FServiceConnection* InConnection, FArchive* InReader)
|
|
: LoadConnection(InConnection)
|
|
, FileReader(InReader)
|
|
{}
|
|
|
|
void DoWork();
|
|
|
|
FORCEINLINE TStatId GetStatId() const
|
|
{
|
|
RETURN_QUICK_DECLARE_CYCLE_STAT(FAsyncReadWorker, STATGROUP_ThreadPoolAsyncTasks);
|
|
}
|
|
};
|
|
|
|
public:
|
|
|
|
/**
|
|
* Default constructor
|
|
*
|
|
* @param InMessageBus The message bus to use.
|
|
*/
|
|
FProfilerClientManager( const IMessageBusRef& InMessageBus );
|
|
|
|
/** Default destructor */
|
|
~FProfilerClientManager();
|
|
|
|
public:
|
|
|
|
// IProfilerClient Interface
|
|
|
|
virtual void Subscribe( const FGuid& Session ) override;
|
|
virtual void Track( const FGuid& Instance ) override;
|
|
virtual void Track( const TArray<TSharedPtr<ISessionInstanceInfo>>& Instances ) override;
|
|
virtual void Untrack( const FGuid& Instance ) override;
|
|
virtual void Unsubscribe() override;
|
|
virtual void SetCaptureState( const bool bRequestedCaptureState, const FGuid& InstanceId = FGuid() ) override;
|
|
virtual void SetPreviewState( const bool bRequestedPreviewState, const FGuid& InstanceId = FGuid() ) override;
|
|
virtual void LoadCapture( const FString& DataFilepath, const FGuid& ProfileId ) override;
|
|
virtual void RequestLastCapturedFile( const FGuid& InstanceId = FGuid() ) override;
|
|
|
|
virtual const FStatMetaData& GetStatMetaData( const FGuid& InstanceId ) const override
|
|
{
|
|
return Connections.Find(InstanceId)->MetaData;
|
|
}
|
|
|
|
virtual FProfilerClientDataDelegate& OnProfilerData() override
|
|
{
|
|
return ProfilerDataDelegate;
|
|
}
|
|
|
|
virtual FProfilerFileTransferDelegate& OnProfilerFileTransfer() override
|
|
{
|
|
return ProfilerFileTransferDelegate;
|
|
}
|
|
|
|
virtual FProfilerClientConnectedDelegate& OnProfilerClientConnected() override
|
|
{
|
|
return ProfilerClientConnectedDelegate;
|
|
}
|
|
|
|
virtual FProfilerClientDisconnectedDelegate& OnProfilerClientDisconnected() override
|
|
{
|
|
return ProfilerClientDisconnectedDelegate;
|
|
}
|
|
|
|
virtual FProfilerMetaDataUpdateDelegate& OnMetaDataUpdated() override
|
|
{
|
|
return ProfilerMetaDataUpdatedDelegate;
|
|
}
|
|
|
|
virtual FProfilerLoadStartedDelegate& OnLoadStarted() override
|
|
{
|
|
return ProfilerLoadStartedDelegate;
|
|
}
|
|
|
|
virtual FProfilerLoadCompletedDelegate& OnLoadCompleted() override
|
|
{
|
|
|
|
return ProfilerLoadCompletedDelegate;
|
|
}
|
|
|
|
virtual FProfilerLoadedMetaDataDelegate& OnLoadedMetaData() override
|
|
{
|
|
return ProfilerLoadedMetaDataDelegate;
|
|
}
|
|
|
|
static const int32 MaxFramesPerTick = 30;
|
|
|
|
private:
|
|
|
|
// Handles message bus shutdowns.
|
|
void HandleMessageBusShutdown();
|
|
|
|
// Handles FProfilerServiceAuthorize2 messages.
|
|
void HandleServiceAuthorize2Message( const FProfilerServiceAuthorize2& Message, const IMessageContextRef& Context );
|
|
|
|
// Handles FProfilerServiceFileChunk messages.
|
|
void HandleServiceFileChunk( const FProfilerServiceFileChunk& FileChunk, const IMessageContextRef& Context );
|
|
|
|
// Handles FProfilerServicePing messages.
|
|
void HandleServicePingMessage( const FProfilerServicePing& Message, const IMessageContextRef& Context );
|
|
|
|
// Handles ticker callbacks (used to retry connection with a profiler service).
|
|
bool HandleTicker( float DeltaTime );
|
|
|
|
// Handles FProfilerServiceData2 messages.
|
|
void HandleServiceData2Message( const FProfilerServiceData2& Message, const IMessageContextRef& Context );
|
|
|
|
// Handles FProfilerServicePreviewAck messages
|
|
void HandleServicePreviewAckMessage( const FProfilerServicePreviewAck& Messsage, const IMessageContextRef& Context );
|
|
|
|
// Handles ticker callbacks for sending out the received messages to subscribed clients
|
|
bool HandleMessagesTicker( float DeltaTime );
|
|
|
|
/** If hash is ok, writes the data to the archive and returns true, otherwise only returns false. */
|
|
bool CheckHashAndWrite( const FProfilerServiceFileChunk& FileChunk, const FProfilerFileChunkHeader& FileChunkHeader, FArchive* Writer );
|
|
|
|
/** Broadcast that meta data has been updated. */
|
|
void BroadcastMetadataUpdate();
|
|
|
|
/** Broadcast that loading has completed and cleans internal structures. */
|
|
void FinalizeLoading();
|
|
|
|
private:
|
|
|
|
/** Session this client is currently communicating with */
|
|
FGuid ActiveSessionId;
|
|
|
|
/** Session this client is trying to communicate with */
|
|
FGuid PendingSessionId;
|
|
TArray<FGuid> PendingInstances;
|
|
|
|
/** Service connections */
|
|
TMap<FGuid, FServiceConnection> Connections;
|
|
|
|
struct FReceivedFileInfo
|
|
{
|
|
FReceivedFileInfo( FArchive* InFileWriter, const int64 InProgress, const FString& InDestFilepath)
|
|
: FileWriter( InFileWriter )
|
|
, Progress( InProgress )
|
|
, DestFilepath( InDestFilepath )
|
|
, LastReceivedChunkTime( FPlatformTime::Seconds() )
|
|
{}
|
|
|
|
bool IsTimedOut() const
|
|
{
|
|
static const double TimeOut = 15.0f;
|
|
return LastReceivedChunkTime+TimeOut < FPlatformTime::Seconds();
|
|
}
|
|
|
|
void Update()
|
|
{
|
|
LastReceivedChunkTime = FPlatformTime::Seconds();
|
|
}
|
|
|
|
FArchive* FileWriter;
|
|
int64 Progress;
|
|
FString DestFilepath;
|
|
double LastReceivedChunkTime;
|
|
};
|
|
|
|
/** Active transfers, stored as a filename -> received file information. Assumes that filename is unique and never will be the same. */
|
|
TMap<FString,FReceivedFileInfo> ActiveTransfers;
|
|
|
|
/** List of failed transfers, so discard any new file chunks. */
|
|
TSet<FString> FailedTransfer;
|
|
|
|
/** Holds the messaging endpoint. */
|
|
FMessageEndpointPtr MessageEndpoint;
|
|
|
|
/** Holds a pointer to the message bus. */
|
|
IMessageBusPtr MessageBus;
|
|
|
|
/** Delegate for notifying clients of received data */
|
|
FProfilerClientDataDelegate ProfilerDataDelegate;
|
|
|
|
/** Delegate for notifying clients of received data through file transfer. */
|
|
FProfilerFileTransferDelegate ProfilerFileTransferDelegate;
|
|
|
|
/** Delegate for notifying clients of a session connection */
|
|
FProfilerClientConnectedDelegate ProfilerClientConnectedDelegate;
|
|
|
|
/** Delegate for notifying clients of a session disconnect */
|
|
FProfilerClientDisconnectedDelegate ProfilerClientDisconnectedDelegate;
|
|
|
|
/** Delegate for notifying clients of a meta data update */
|
|
FProfilerMetaDataUpdateDelegate ProfilerMetaDataUpdatedDelegate;
|
|
|
|
/** Delegate for notifying clients of a load start */
|
|
FProfilerLoadStartedDelegate ProfilerLoadStartedDelegate;
|
|
|
|
/** Delegate for notifying clients of a load completion */
|
|
FProfilerLoadCompletedDelegate ProfilerLoadCompletedDelegate;
|
|
|
|
/** Delegate for notifying clients of initial meta data load */
|
|
FProfilerLoadedMetaDataDelegate ProfilerLoadedMetaDataDelegate;
|
|
|
|
/** Holds a delegate to be invoked when the widget ticks. */
|
|
FTickerDelegate TickDelegate;
|
|
|
|
/** Handle to the registered TickDelegate. */
|
|
FDelegateHandle TickDelegateHandle;
|
|
|
|
/** Amount of time between connection retries */
|
|
float RetryTime;
|
|
|
|
/** Fake Connection used for loading a file */
|
|
FServiceConnection* LoadConnection;
|
|
|
|
/** Holds a delegate to be invoked when the widget ticks. */
|
|
FTickerDelegate MessageDelegate;
|
|
|
|
/** Handle to the registered MessageDelegate. */
|
|
FDelegateHandle MessageDelegateHandle;
|
|
|
|
#if PROFILER_THREADED_LOAD
|
|
/** Loads a file asynchronously */
|
|
bool AsyncLoad();
|
|
|
|
/** Load Task */
|
|
FAsyncTask<FAsyncReadWorker>* LoadTask;
|
|
#else
|
|
/** Loads a file synchronously */
|
|
bool SyncLoad();
|
|
/** File reader */
|
|
FArchive* FileReader;
|
|
#endif
|
|
|
|
/** Holds the last time a ping was made to instances */
|
|
FDateTime LastPingTime;
|
|
};
|