From c2ec2928c236d045a79d51f24f09a4c7015e1d73 Mon Sep 17 00:00:00 2001 From: Vadim Slyusarev Date: Sun, 30 Jan 2022 17:59:33 +0000 Subject: [PATCH] Adding support for GPU counters in UE4 plugin --- gui/Optick/Properties/AssemblyInfo.cs | 4 +- .../Source/OptickPlugin.Build.cs | 4 - .../Source/Private/OptickPlugin.cpp | 262 +++++++++--------- .../Source/Private/OptickUE4Classes.h | 235 +++++++--------- tools/Publish.bat | 3 +- tools/Publish_UE4.bat | 5 + 6 files changed, 241 insertions(+), 272 deletions(-) diff --git a/gui/Optick/Properties/AssemblyInfo.cs b/gui/Optick/Properties/AssemblyInfo.cs index 9bc949c4..74eeb719 100644 --- a/gui/Optick/Properties/AssemblyInfo.cs +++ b/gui/Optick/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.3.2.0")] -[assembly: AssemblyFileVersion("1.3.2.0")] +[assembly: AssemblyVersion("1.3.3.0")] +[assembly: AssemblyFileVersion("1.3.3.0")] diff --git a/samples/UnrealEnginePlugin/Source/OptickPlugin.Build.cs b/samples/UnrealEnginePlugin/Source/OptickPlugin.Build.cs index a7e5f50b..dd30400f 100644 --- a/samples/UnrealEnginePlugin/Source/OptickPlugin.Build.cs +++ b/samples/UnrealEnginePlugin/Source/OptickPlugin.Build.cs @@ -57,16 +57,12 @@ public OptickPlugin(ReadOnlyTargetRules Target) : base(Target) } ); -/* -#if UE_4_24_OR_LATER PublicDefinitions.AddRange( new string[] { "OPTICK_UE4_GPU=1", } ); -#endif -*/ if (Target.bBuildEditor == true) { diff --git a/samples/UnrealEnginePlugin/Source/Private/OptickPlugin.cpp b/samples/UnrealEnginePlugin/Source/Private/OptickPlugin.cpp index fa04c022..fdb69348 100644 --- a/samples/UnrealEnginePlugin/Source/Private/OptickPlugin.cpp +++ b/samples/UnrealEnginePlugin/Source/Private/OptickPlugin.cpp @@ -4,7 +4,7 @@ #include "CoreMinimal.h" #include "Containers/Ticker.h" #include "GenericPlatform/GenericPlatformFile.h" -#include "HAL/X.h" +#include "HAL/PlatformFilemanager.h" #include "HAL/PlatformProcess.h" #include "Misc/EngineVersion.h" #include "Misc/CoreDelegates.h" @@ -112,10 +112,12 @@ class FOptickPlugin : public IOptickPlugin uint64 Convert32bitCPUTimestamp(int64 timestamp) const; #ifdef OPTICK_UE4_GPU + void OnEndFrameRT(); - uint64 ConvertGPUTimestamp(uint64 timestamp); + uint64 ConvertGPUTimestamp(uint64 timestamp, int GPUIndex); - FGPUTimingCalibrationTimestamp CalibrationTimestamp; + bool UpdateCalibrationTimestamp(FRealtimeGPUProfilerFrameImpl* Frame, int GPUIndex); + FGPUTimingCalibrationTimestamp CalibrationTimestamps[MAX_NUM_GPUS]; #endif public: @@ -294,8 +296,6 @@ void FOptickPlugin::StartCapture() if (!IsCapturing) { #ifdef OPTICK_UE4_GPU - CalibrationTimestamp = FGPUTiming::GetCalibrationTimestamp(); - GPUThreadStorage.Reset(); for (auto& pair : StorageMap) pair.Value->Reset(); @@ -393,7 +393,57 @@ uint64 FOptickPlugin::Convert32bitCPUTimestamp(int64 timestamp) const } #ifdef OPTICK_UE4_GPU -#if UE_4_24_OR_LATER + +bool FOptickPlugin::UpdateCalibrationTimestamp(FRealtimeGPUProfilerFrameImpl* Frame, int GPUIndex) +{ + FGPUTimingCalibrationTimestamp& CalibrationTimestamp = CalibrationTimestamps[GPUIndex]; + CalibrationTimestamp = FGPUTimingCalibrationTimestamp{ 0, 0 }; + + if (Frame->TimestampCalibrationQuery.IsValid()) + { +#if UE_4_27_OR_LATER + CalibrationTimestamp.GPUMicroseconds = Frame->TimestampCalibrationQuery->GPUMicroseconds[GPUIndex]; + CalibrationTimestamp.CPUMicroseconds = Frame->TimestampCalibrationQuery->CPUMicroseconds[GPUIndex]; +#else + CalibrationTimestamp.GPUMicroseconds = Frame->TimestampCalibrationQuery->GPUMicroseconds; + CalibrationTimestamp.CPUMicroseconds = Frame->TimestampCalibrationQuery->CPUMicroseconds; +#endif + } + + if (CalibrationTimestamp.GPUMicroseconds == 0 || CalibrationTimestamp.CPUMicroseconds == 0) // Unimplemented platforms, or invalid on the first frame + { + if (Frame->GpuProfilerEvents.Num() > 1) + { + // Align CPU and GPU frames + CalibrationTimestamp.GPUMicroseconds = Frame->GpuProfilerEvents[1].GetStartResultMicroseconds(0); + CalibrationTimestamp.CPUMicroseconds = FPlatformTime::ToSeconds64(Frame->CPUFrameStartTimestamp) * 1000 * 1000; + } + else + { + // Fallback to legacy + CalibrationTimestamp = FGPUTiming::GetCalibrationTimestamp(); + } + } + + return CalibrationTimestamp.GPUMicroseconds != 0 && CalibrationTimestamp.CPUMicroseconds != 0; +} + +struct TimeRange +{ + uint64 Start; + uint64 Finish; + bool IsOverlap(TimeRange other) const + { + return !((Finish < other.Start) || (other.Finish < Start)); + } + bool IsValid() const + { + return Start != 0 && Finish != 0 && Finish > Start; + } + TimeRange() : Start(0), Finish(0) {} + TimeRange(uint64 start, uint64 finish) : Start(start), Finish(finish) {} +}; + void FOptickPlugin::OnEndFrameRT() { FScopeLock ScopeLock(&UpdateCriticalSection); @@ -418,6 +468,7 @@ void FOptickPlugin::OnEndFrameRT() if (!Event.GatherQueryResults(RHICmdList)) { + #if !(UE_BUILD_SHIPPING || UE_BUILD_TEST) UE_LOG(OptickLog, Warning, TEXT("Query is not ready.")); #endif @@ -426,162 +477,106 @@ void FOptickPlugin::OnEndFrameRT() } } - for (int32 i = 1; i < NumEventsThisFramePlusOne; ++i) - { - FRealtimeGPUProfilerEventImpl& Event = Frame->GpuProfilerEvents[i]; - - const FName Name = Event.Name; - - Optick::EventDescription* Description = nullptr; - - if (Optick::EventDescription** ppDescription = GPUDescriptionMap.Find(Name)) - { - Description = *ppDescription; - } - else - { - Description = Optick::EventDescription::CreateShared(TCHAR_TO_ANSI(*Name.ToString())); - GPUDescriptionMap.Add(Name, Description); - } - - uint64 startTimestamp = ConvertGPUTimestamp(Event.StartResultMicroseconds); - uint64 endTimestamp = ConvertGPUTimestamp(Event.EndResultMicroseconds); + TArray EventStack; - if (Name == NAME_GPU_Unaccounted) - { - OPTICK_FRAME_FLIP(Optick::FrameType::GPU, startTimestamp); + if (NumEventsThisFramePlusOne <= 1) + return; - if (GPUThreadStorage.LastTimestamp != 0) - { - OPTICK_STORAGE_POP(GPUThreadStorage.EventStorage, GPUThreadStorage.LastTimestamp); - } - - OPTICK_STORAGE_PUSH(GPUThreadStorage.EventStorage, Optick::GetFrameDescription(Optick::FrameType::GPU), startTimestamp) - } - else - { - OPTICK_STORAGE_EVENT(GPUThreadStorage.EventStorage, Description, startTimestamp, endTimestamp); - } - GPUThreadStorage.LastTimestamp = FMath::Max(GPUThreadStorage.LastTimestamp, endTimestamp); - } - } - } -} -#else -void FOptickPlugin::OnEndFrameRT() -{ - FScopeLock ScopeLock(&UpdateCriticalSection); + // VS TODO: Add MGPU support + uint32 GPUIndex = 0; - if (!IsCapturing || !Optick::IsActive(Optick::Mode::GPU)) - return; + // Can't collect GPU data without valid calibration between CPU and GPU timestamps + if (!UpdateCalibrationTimestamp(Frame, GPUIndex)) + return; - QUICK_SCOPE_CYCLE_COUNTER(STAT_FOptickPlugin_UpdRT); + uint64 lastTimeStamp = FMath::Max(CalibrationTimestamps[GPUIndex].CPUMicroseconds, GPUThreadStorage.LastTimestamp); - if (FRealtimeGPUProfilerImpl* gpuProfiler = reinterpret_cast(FRealtimeGPUProfiler::Get())) - { - if (FRealtimeGPUProfilerFrameImpl* Frame = gpuProfiler->Frames[gpuProfiler->ReadBufferIndex]) - { - FRHICommandListImmediate& RHICmdList = FRHICommandListExecutor::GetImmediateCommandList(); + const FRealtimeGPUProfilerEventImpl& FirstEvent = Frame->GpuProfilerEvents[1]; + uint64 frameStartTimestamp = FMath::Max(ConvertGPUTimestamp(FirstEvent.GetStartResultMicroseconds(GPUIndex), GPUIndex), lastTimeStamp); - bool bAnyEventFailed = false; - bool bAllQueriesAllocated = true; + OPTICK_FRAME_FLIP(Optick::FrameType::GPU, frameStartTimestamp); + OPTICK_STORAGE_PUSH(GPUThreadStorage.EventStorage, Optick::GetFrameDescription(Optick::FrameType::GPU), frameStartTimestamp) - for (int i = 0; i < Frame->GpuProfilerEvents.Num(); ++i) + for (int32 Idx = 1; Idx < NumEventsThisFramePlusOne; ++Idx) { - FRealtimeGPUProfilerEventImpl* Event = Frame->GpuProfilerEvents[i]; - check(Event != nullptr); + const FRealtimeGPUProfilerEventImpl& Event = Frame->GpuProfilerEvents[Idx]; - if (!Event->HasValidResult()) + if (Event.GetGPUMask().Contains(GPUIndex)) { - Event->GatherQueryResults(RHICmdList); - } + const FName Name = Event.Name; - if (!Event->HasValidResult()) - { -#if UE_BUILD_DEBUG - UE_LOG(OptickLog, Warning, TEXT("Query '%s' not ready."), *Event->GetName().ToString()); -#endif - // The frame isn't ready yet. Don't update stats - we'll try again next frame. - bAnyEventFailed = true; - continue; - } + if (Name == NAME_GPU_Unaccounted) + continue; - if (!Event->HasQueriesAllocated()) - { - bAllQueriesAllocated = false; - } - } - - if (bAnyEventFailed) - { - return; - } + Optick::EventDescription* Description = nullptr; - if (!bAllQueriesAllocated) - { - static bool bWarned = false; + if (Optick::EventDescription** ppDescription = GPUDescriptionMap.Find(Name)) + { + Description = *ppDescription; + } + else + { + Description = Optick::EventDescription::CreateShared(TCHAR_TO_ANSI(*Name.ToString())); + GPUDescriptionMap.Add(Name, Description); + } - if (!bWarned) - { - bWarned = true; - UE_LOG(OptickLog, Warning, TEXT("Ran out of GPU queries! Results for this frame will be incomplete")); - } - } + uint64 startTimestamp = ConvertGPUTimestamp(Event.GetStartResultMicroseconds(GPUIndex), GPUIndex); + uint64 endTimestamp = ConvertGPUTimestamp(Event.GetEndResultMicroseconds(GPUIndex), GPUIndex); + // Fixing potential errors + startTimestamp = FMath::Max(startTimestamp, lastTimeStamp); + endTimestamp = FMath::Max(endTimestamp, startTimestamp); - for (int i = 0; i < Frame->GpuProfilerEvents.Num(); ++i) - { - FRealtimeGPUProfilerEventImpl* Event = Frame->GpuProfilerEvents[i]; - check(Event != nullptr); + // Ensuring correct hierarchy + while (EventStack.Num() && (EventStack.Last().Finish <= startTimestamp)) + EventStack.Pop(); - const FName Name = Event->Name; + // Discovered broken hierarchy, skipping event + if (EventStack.Num() && (endTimestamp < EventStack.Last().Start)) + continue; - Optick::EventDescription* Description = nullptr; + // Clamp range against the parent counter + if (EventStack.Num()) + { + TimeRange parent = EventStack.Last(); + startTimestamp = FMath::Clamp(startTimestamp, parent.Start, parent.Finish); + endTimestamp = FMath::Clamp(endTimestamp, parent.Start, parent.Finish); + } - if (Optick::EventDescription** ppDescription = GPUDescriptionMap.Find(Name)) - { - Description = *ppDescription; - } - else - { - Description = Optick::EventDescription::CreateShared(TCHAR_TO_ANSI(*Name.ToString())); - GPUDescriptionMap.Add(Name, Description); - } + // Ignore invalid events + if (startTimestamp == endTimestamp) + continue; - uint64 startTimestamp = ConvertGPUTimestamp(Event->StartResultMicroseconds); - uint64 endTimestamp = ConvertGPUTimestamp(Event->EndResultMicroseconds); + //if (Name == NAME_GPU_Unaccounted) + //{ + // OPTICK_FRAME_FLIP(Optick::FrameType::GPU, startTimestamp); - if (Name == NAME_GPU_Unaccounted) - { - OPTICK_FRAME_FLIP(Optick::FrameType::GPU, startTimestamp); - if (GPUThreadStorage.LastTimestamp != 0) + // OPTICK_STORAGE_PUSH(GPUThreadStorage.EventStorage, Optick::GetFrameDescription(Optick::FrameType::GPU), startTimestamp) + //} + //else { - OPTICK_STORAGE_POP(GPUThreadStorage.EventStorage, GPUThreadStorage.LastTimestamp); + EventStack.Add(TimeRange(startTimestamp, endTimestamp)); + OPTICK_STORAGE_EVENT(GPUThreadStorage.EventStorage, Description, startTimestamp, endTimestamp); } - - OPTICK_STORAGE_PUSH(GPUThreadStorage.EventStorage, Optick::GetFrameDescription(Optick::FrameType::GPU), startTimestamp) - } - else - { - OPTICK_STORAGE_EVENT(GPUThreadStorage.EventStorage, Description, startTimestamp, endTimestamp); + lastTimeStamp = FMath::Max(lastTimeStamp, endTimestamp); } - GPUThreadStorage.LastTimestamp = FMath::Max(GPUThreadStorage.LastTimestamp, endTimestamp); } + + OPTICK_STORAGE_POP(GPUThreadStorage.EventStorage, lastTimeStamp); + GPUThreadStorage.LastTimestamp = lastTimeStamp; } } } -#endif -uint64 FOptickPlugin::ConvertGPUTimestamp(uint64 timestamp) +uint64 FOptickPlugin::ConvertGPUTimestamp(uint64 timestamp, int GPUIndex) { - if (CalibrationTimestamp.CPUMicroseconds == 0 || CalibrationTimestamp.GPUMicroseconds == 0) + if (CalibrationTimestamps[GPUIndex].CPUMicroseconds == 0 || CalibrationTimestamps[GPUIndex].GPUMicroseconds == 0) { - CalibrationTimestamp.CPUMicroseconds = uint64(FPlatformTime::ToSeconds64(FPlatformTime::Cycles64()) * 1e6); - CalibrationTimestamp.GPUMicroseconds = timestamp; + return (uint64)-1; } - const uint64 cpuTimestampUs = timestamp - CalibrationTimestamp.GPUMicroseconds + CalibrationTimestamp.CPUMicroseconds; + const uint64 cpuTimestampUs = timestamp - CalibrationTimestamps[GPUIndex].GPUMicroseconds + CalibrationTimestamps[GPUIndex].CPUMicroseconds; const uint64 cpuTimestamp = cpuTimestampUs * 1e-6 / FPlatformTime::GetSecondsPerCycle64(); return cpuTimestamp; } @@ -639,13 +634,22 @@ void FOptickPlugin::GetDataFromStatsThread(int64 CurrentFrame) const FName groupName = Item.NameAndInfo.GetGroupName(); uint32 color = 0; + uint32 filter = 0; if (NAME_STATGROUP_CPUStalls == groupName) - color = Optick::Color::White; + { + color = Optick::Color::Tomato; + filter = Optick::Filter::Wait; + } for (int i = 0; i < sizeof(NAME_Wait) / sizeof(NAME_Wait[0]); ++i) + { if (NAME_Wait[i] == shortName) + { color = Optick::Color::White; + filter = Optick::Filter::Wait; + } + } Description = Optick::EventDescription::CreateShared(TCHAR_TO_ANSI(*shortName.ToString()), nullptr, 0, color); diff --git a/samples/UnrealEnginePlugin/Source/Private/OptickUE4Classes.h b/samples/UnrealEnginePlugin/Source/Private/OptickUE4Classes.h index 0bcecff8..0f0925a7 100644 --- a/samples/UnrealEnginePlugin/Source/Private/OptickUE4Classes.h +++ b/samples/UnrealEnginePlugin/Source/Private/OptickUE4Classes.h @@ -4,16 +4,16 @@ #ifdef OPTICK_UE4_GPU -#define UE_4_24_OR_LATER (ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION >= 24) - // RenderCore #include "GPUProfiler.h" #include "ProfilingDebugging/RealtimeGPUProfiler.h" #include "ProfilingDebugging/TracingProfiler.h" +#include "Runtime/Launch/Resources/Version.h" -#define REALTIME_GPU_PROFILER_EVENT_TRACK_FRAME_NUMBER (TRACING_PROFILER || DO_CHECK) +#define UE_4_27_OR_LATER (ENGINE_MAJOR_VERSION >= 4 && ENGINE_MINOR_VERSION >= 27) -#ifdef UE_4_24_OR_LATER + +#define REALTIME_GPU_PROFILER_EVENT_TRACK_FRAME_NUMBER (TRACING_PROFILER || DO_CHECK) /*----------------------------------------------------------------------------- FRealTimeGPUProfilerEvent class @@ -24,36 +24,99 @@ class FRealtimeGPUProfilerEventImpl static const uint64 InvalidQueryResult = 0xFFFFFFFFFFFFFFFFull; public: - bool GatherQueryResults(FRHICommandListImmediate& RHICmdList) - { - QUICK_SCOPE_CYCLE_COUNTER(STAT_SceneUtils_GatherQueryResults); - - // Get the query results which are still outstanding - check(StartQuery.IsValid() && EndQuery.IsValid()); - - if (StartResultMicroseconds == InvalidQueryResult) - { - if (!RHICmdList.GetRenderQueryResult(StartQuery.GetQuery(), StartResultMicroseconds, false)) - { - StartResultMicroseconds = InvalidQueryResult; - } - } - - if (EndResultMicroseconds == InvalidQueryResult) - { - if (!RHICmdList.GetRenderQueryResult(EndQuery.GetQuery(), EndResultMicroseconds, false)) - { - EndResultMicroseconds = InvalidQueryResult; - } - } - - return HasValidResult(); + bool GatherQueryResults(FRHICommandListImmediate& RHICmdList) + { + //QUICK_SCOPE_CYCLE_COUNTER(STAT_SceneUtils_GatherQueryResults); + + // Get the query results which are still outstanding + check(GFrameNumberRenderThread != FrameNumber); + check(StartQuery.IsValid() && EndQuery.IsValid()); + + for (uint32 GPUIndex : GPUMask) + { + if (StartResultMicroseconds[GPUIndex] == InvalidQueryResult) + { + if (!RHICmdList.GetRenderQueryResult(StartQuery.GetQuery(), StartResultMicroseconds[GPUIndex], false, GPUIndex)) + { + StartResultMicroseconds[GPUIndex] = InvalidQueryResult; + } + } + + if (EndResultMicroseconds[GPUIndex] == InvalidQueryResult) + { + if (!RHICmdList.GetRenderQueryResult(EndQuery.GetQuery(), EndResultMicroseconds[GPUIndex], false, GPUIndex)) + { + EndResultMicroseconds[GPUIndex] = InvalidQueryResult; + } + } + } + + return HasValidResult(); + } + + uint64 GetResultUs(uint32 GPUIndex) const + { + check(HasValidResult(GPUIndex)); + + if (StartResultMicroseconds[GPUIndex] > EndResultMicroseconds[GPUIndex]) + { + return 0llu; + } + + return EndResultMicroseconds[GPUIndex] - StartResultMicroseconds[GPUIndex]; + } + + bool HasValidResult(uint32 GPUIndex) const + { + return StartResultMicroseconds[GPUIndex] != InvalidQueryResult && EndResultMicroseconds[GPUIndex] != InvalidQueryResult; + } + + bool HasValidResult() const + { + for (uint32 GPUIndex : GPUMask) + { + if (!HasValidResult(GPUIndex)) + { + return false; + } + } + return true; + } + +#if STATS + const FName& GetStatName() const + { + return StatName; + } +#endif + + const FName& GetName() const + { + return Name; + } + + FRHIGPUMask GetGPUMask() const + { + return GPUMask; + } + + uint64 GetStartResultMicroseconds(uint32 GPUIndex) const + { + return StartResultMicroseconds[GPUIndex]; + } + + uint64 GetEndResultMicroseconds(uint32 GPUIndex) const + { + return EndResultMicroseconds[GPUIndex]; + } + + uint32 GetFrameNumber() const + { + return FrameNumber; } - bool HasValidResult() const - { - return StartResultMicroseconds != InvalidQueryResult && EndResultMicroseconds != InvalidQueryResult; - } + TStaticArray StartResultMicroseconds; + TStaticArray EndResultMicroseconds; FRHIPooledRenderQuery StartQuery; FRHIPooledRenderQuery EndQuery; @@ -61,19 +124,15 @@ class FRealtimeGPUProfilerEventImpl FName Name; STAT(FName StatName;) - uint64 StartResultMicroseconds; - uint64 EndResultMicroseconds; + FRHIGPUMask GPUMask; -#if REALTIME_GPU_PROFILER_EVENT_TRACK_FRAME_NUMBER uint32 FrameNumber; -#endif #if DO_CHECK bool bInsideQuery; #endif }; - class FRealtimeGPUProfilerFrameImpl { public: @@ -83,6 +142,9 @@ class FRealtimeGPUProfilerFrameImpl uint32 InclusiveTimeUs; }; + uint64 CPUFrameStartTimestamp; + FTimestampCalibrationQueryRHIRef TimestampCalibrationQuery; + static constexpr uint32 GPredictedMaxNumEvents = 100u; static constexpr uint32 GPredictedMaxNumEventsUpPow2 = 128u; static constexpr uint32 GPredictedMaxStackDepth = 32u; @@ -100,105 +162,6 @@ class FRealtimeGPUProfilerFrameImpl TArray> EventAggregates; }; - -#else - -/*----------------------------------------------------------------------------- -FRealTimeGPUProfilerEvent class ------------------------------------------------------------------------------*/ -class FRealtimeGPUProfilerEventImpl -{ -public: - static const uint64 InvalidQueryResult = 0xFFFFFFFFFFFFFFFFull; - -public: - bool HasQueriesAllocated() const - { - return StartQuery.GetQuery() != nullptr; - } - - bool GatherQueryResults(FRHICommandListImmediate& RHICmdList) - { - QUICK_SCOPE_CYCLE_COUNTER(STAT_Optick_GatherQueryResults); - // Get the query results which are still outstanding - check(GFrameNumberRenderThread != FrameNumber); - if (HasQueriesAllocated()) - { - if (StartResultMicroseconds == InvalidQueryResult) - { - if (!RHICmdList.GetRenderQueryResult(StartQuery.GetQuery(), StartResultMicroseconds, false)) - { - StartResultMicroseconds = InvalidQueryResult; - } - bBeginQueryInFlight = false; - } - if (EndResultMicroseconds == InvalidQueryResult) - { - if (!RHICmdList.GetRenderQueryResult(EndQuery.GetQuery(), EndResultMicroseconds, false)) - { - EndResultMicroseconds = InvalidQueryResult; - } - bEndQueryInFlight = false; - } - } - else - { - // If we don't have a query allocated, just set the results to zero - EndResultMicroseconds = StartResultMicroseconds = 0; - } - return HasValidResult(); - } - - bool HasValidResult() const - { - return StartResultMicroseconds != FRealtimeGPUProfilerEventImpl::InvalidQueryResult && EndResultMicroseconds != FRealtimeGPUProfilerEventImpl::InvalidQueryResult; - } - - FRHIPooledRenderQuery StartQuery; - FRHIPooledRenderQuery EndQuery; -#if STATS - FName StatName; -#endif - FName Name; - uint64 StartResultMicroseconds; - uint64 EndResultMicroseconds; - uint32 FrameNumber; - - bool bInsideQuery; - bool bBeginQueryInFlight; - bool bEndQueryInFlight; -}; - -class FRealtimeGPUProfilerFrameImpl -{ -public: - uint32& QueryCount; - - TArray GpuProfilerEvents; - TArray EventStack; - - struct FRealtimeGPUProfilerTimelineEvent - { - enum class EType { PushEvent, PopEvent }; - EType Type; - int32 EventIndex; - }; - - TArray GpuProfilerTimelineEvents; - - struct FGPUEventTimeAggregate - { - float ExclusiveTime; - float InclusiveTime; - }; - TArray EventAggregates; - - uint32 FrameNumber; - FRenderQueryPoolRHIRef RenderQueryPool; -}; - -#endif - class FRealtimeGPUProfilerImpl { public: diff --git a/tools/Publish.bat b/tools/Publish.bat index 91088a1d..aa02af4f 100644 --- a/tools/Publish.bat +++ b/tools/Publish.bat @@ -1,4 +1,5 @@ @echo off call Publish_Main.bat -call Publish_UE4.bat \ No newline at end of file +call Publish_UE4.bat 4.26 +call Publish_UE4.bat 4.27 \ No newline at end of file diff --git a/tools/Publish_UE4.bat b/tools/Publish_UE4.bat index 0c8e133e..e9434887 100644 --- a/tools/Publish_UE4.bat +++ b/tools/Publish_UE4.bat @@ -12,6 +12,11 @@ rem MsBuild gui/OptickApp_vs2017.sln /t:Rebuild /p:Configuration=Release /p:Plat for /f %%i in ('powershell "(Get-Item -path gui\Bin\Release\x64\Optick.exe).VersionInfo.ProductVersion"') do set VERSION=%%i set UNREAL_VERSION=4.27 + +IF "%~1" == "" GOTO skipversion +set UNREAL_VERSION="%~1" +:skipversion + set VERSION_NAME=%VERSION:~0,-2%_UE4Plugin%UNREAL_VERSION% xcopy /Y gui\Bin\Release\x64\Optick.exe samples\UnrealEnginePlugin\GUI\*