Files
UnrealEngineUWP/Engine/Source/Runtime/RenderCore/Public/RenderGraphEvent.inl
luke thatcher 7ec6ef81f5 New GPU profiler improvements. The TStatId on FRHIBreadcrumb has been replaced with a FRHIBreadcrumbData struct that holds additional profiling related data, which includes:
- The TStatId for "stat gpu" stats.
 - The FName required by the CSV profiler for GPU stats.
 - The source file and line number to allow breadcrumbs shown in Insights to link back to their original source location.

Additional changes:
 - Added temporary support for the Insights GPU track. This is guarded by RHI_TEMP_USE_GPU_TRACE until we have a newer, more capable API.
 - Simplified FMeshDrawEvent into a standard RHI breadcrumb in FMeshDrawCommand::SubmitDraw().
 - Moved "r.GPUCsvStatsEnabled" cvar into GPUProfiler.cpp, so it is accessible to both old and new profilers.

#jira UE-177299
#rb mihnea.balta

[CL 35973862 by luke thatcher in ue5-main branch]
2024-09-03 14:10:13 -04:00

198 lines
4.5 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#if RHI_NEW_GPU_PROFILER
// @todo - new gpu profiler
#else
#if HAS_GPU_STATS
inline FRDGScope_GPU::FRDGScope_GPU(FRDGScopeState& State, FRHIGPUMask GPUMask, const FName& CsvStatName, const TStatId& Stat, const TCHAR* Description, FRHIDrawStatsCategory const& Category)
: CurrentCategory(Category.ShouldCountDraws() ? &Category : nullptr),
bEmitDuringExecute(AreGPUStatsEnabled() && !State.ScopeState.bParallelExecute)
{
if (AreGPUStatsEnabled())
{
if (bEmitDuringExecute)
{
StatName = CsvStatName;
StatId = Stat;
StatDescription = FString(Description);
}
else
{
StartQuery = FRealtimeGPUProfiler::Get()->PushEvent(GPUMask, CsvStatName, Stat, Description);
}
}
}
inline void FRDGScope_GPU::ImmediateEnd(FRDGScopeState&)
{
if (StartQuery)
{
StopQuery = FRealtimeGPUProfiler::Get()->PopEvent();
}
}
inline FRDGScope_GPU::~FRDGScope_GPU()
{
if (StartQuery)
{
StartQuery.Discard(true);
}
if (StopQuery)
{
StopQuery.Discard(false);
}
}
inline void FRDGScope_GPU::BeginCPU(FRHIComputeCommandList& RHICmdList, bool bPreScope)
{
if (CurrentCategory)
{
PreviousCategory = RHICmdList.SetDrawStatsCategory(CurrentCategory);
}
}
inline void FRDGScope_GPU::EndCPU(FRHIComputeCommandList& RHICmdList, bool bPreScope)
{
if (CurrentCategory)
{
RHICmdList.SetDrawStatsCategory(PreviousCategory);
}
}
inline void FRDGScope_GPU::BeginGPU(FRHIComputeCommandList& RHICmdList)
{
if (EnumHasAnyFlags(RHICmdList.GetPipeline(), ERHIPipeline::Graphics))
{
if (bEmitDuringExecute)
{
FRealtimeGPUProfiler::Get()->PushStat(RHICmdList.GetAsImmediate(), StatName, StatId, *StatDescription);
}
else if (StartQuery)
{
StartQuery.Submit(static_cast<FRHICommandList&>(RHICmdList), true);
}
}
}
inline void FRDGScope_GPU::EndGPU(FRHIComputeCommandList& RHICmdList)
{
if (EnumHasAnyFlags(RHICmdList.GetPipeline(), ERHIPipeline::Graphics))
{
if (bEmitDuringExecute)
{
FRealtimeGPUProfiler::Get()->PopStat(RHICmdList.GetAsImmediate());
}
else if (StopQuery)
{
StopQuery.Submit(static_cast<FRHICommandList&>(RHICmdList), false);
}
}
}
#endif
#endif // (RHI_NEW_GPU_PROFILER == 0)
#if RDG_EVENTS
inline FRDGScope_RHI::FRDGScope_RHI(FRDGScopeState& State, FRHIBreadcrumbData&& Data, FRDGEventName&& Name)
: Name(MoveTemp(Name))
#if WITH_RHI_BREADCRUMBS
, Node(Name.AllocBreadcrumb(MoveTemp(Data), State.GetBreadcrumbAllocator()))
#endif
{
#if WITH_RHI_BREADCRUMBS
if (Node)
{
Node->SetParent(State.CurrentBreadcrumbRef);
State.CurrentBreadcrumbRef = Node;
Node->BeginCPU();
if (!State.ScopeState.bImmediate)
{
// Link breadcrumbs together, so we can iterate over them during RDG compilation.
State.LocalBreadcrumbList.Append(Node);
}
}
#endif
}
inline void FRDGScope_RHI::ImmediateEnd(FRDGScopeState& State)
{
#if WITH_RHI_BREADCRUMBS
if (Node)
{
Node->EndCPU();
State.CurrentBreadcrumbRef = Node->GetParent();
}
#endif
}
#endif // RDG_EVENTS
template <typename TScopeType>
template <typename... TArgs>
inline TRDGEventScopeGuard<TScopeType>::TRDGEventScopeGuard(FRDGScopeState& State, ERDGScopeFlags Flags, TArgs&&... Args)
: State(State)
, Scope(Allocate(State, Flags))
{
if (Scope)
{
Scope->Impl.Emplace<TScopeType>(State, Forward<TArgs>(Args)...);
if (State.ScopeState.bImmediate)
{
Scope->BeginCPU(State.RHICmdList, false);
Scope->BeginGPU(State.RHICmdList);
}
}
}
template <typename TScopeType>
inline TRDGEventScopeGuard<TScopeType>::~TRDGEventScopeGuard()
{
if (Scope)
{
if (State.ScopeState.bImmediate)
{
Scope->EndGPU(State.RHICmdList);
Scope->EndCPU(State.RHICmdList, false);
}
Scope->ImmediateEnd(State);
State.ScopeState.Mask &= ~(TypeMask);
State.ScopeState.Current = State.ScopeState.Current->Parent;
}
}
template <typename TScopeType>
inline FRDGScope* TRDGEventScopeGuard<TScopeType>::Allocate(FRDGScopeState& State, ERDGScopeFlags Flags)
{
if (State.ScopeState.ScopeMode == ERDGScopeMode::Disabled && !EnumHasAnyFlags(Flags, ERDGScopeFlags::AlwaysEnable))
{
return nullptr;
}
if (State.ScopeState.ScopeMode == ERDGScopeMode::TopLevelOnly && (State.ScopeState.Mask & TypeMask))
{
return nullptr;
}
if (EnumHasAnyFlags(Flags, ERDGScopeFlags::Final))
{
// Mask off any nested scopes of the same type
State.ScopeState.Mask |= TypeMask;
}
FRDGScope* Scope = FRDGAllocator::GetTLS().Alloc<FRDGScope>(State.ScopeState.Current);
State.ScopeState.Current = Scope;
return Scope;
}