Compilation failures when adding SCOPED_GPU_EVENT to core rendering files

The problem ends up being that `SCOPED_GPU_STAT` depends on the define `CSV_PROFILER` being true but it doesn’t check for that. `SCOPED_GPU_STAT` expands out to:

#define SCOPED_GPU_STAT(RHICmdList, StatName) \
FScopedGPUStatEvent PREPROCESSOR_JOIN(GPUStatEvent_##StatName,__LINE__); \
PREPROCESSOR_JOIN(GPUStatEvent_##StatName,__LINE__).Begin(RHICmdList, \
														  CSV_STAT_FNAME(StatName), \
														  GET_STATID( Stat_GPU_##StatName ).GetName(), \
														  nullptr    , \
														  DrawcallCountCategory_##StatName);

And the `CSV_STAT_FNAME` and (maybe also the) `GET_STATID` calls require `CSV_PROFILER` to be true. If it isn’t true, they noop, and we get output like:

FScopedGPUStatEvent GPUStatEvent_SomeStat1795; GPUStatEvent_SomeStat1795.Begin(RHICommandList,, FName(), nullptr , DrawcallCountCategory_SomeStat);

Which is clearly going to cause compilation errors.

My question is: how would you recommend modifying engine code such that `SCOPED_GPU_STAT` will actually no-op instead of cause compilation errors when its being evaluated in contexts which cannot support it. I believe the specific crash is occurring when building `UnrealPak` / `ShaderCompilationWorker`, since in that context there is `WITH_ENGINE` is false, and `CSV_PROFILER` is also false.

Would something like this be preferred in `Engine/Source/Runtime/RenderCore/Public/ProfilingDebugging/RealtimeGPUProfiler.h`:

#if HAS_GPU_STATS
...
// #if STATS <-- original code
#if STATS && WITH_ENGINE
#define SCOPED_GPU_STAT(RHICmdList, StatName) ...
#else
// no-op
#endif
...
#endif

Thanks for your support.

Steps to Reproduce
Hi,

I’m trying to add GPU Profiling scopes to some core renderer code. The general pattern for adding these scopes is:

// SomeFile.cpp

DECLARE_GPU_STAT(MyStat)

void SomeClass::SomeFunction(FRHICommandList& RHICommandList)
{
  SCOPED_GPU_STAT(RHICommandList, MyStat);
}


This works just great in other files, but when i try to add `SCOPED_GPU_STAT`s in `RenderCore/Private/RenderGraphUtils.cpp` compilation fails with:

[1/8] Compile [x64] RenderGraphUtils.cpp
C:\project\Engine\Source\Runtime\RenderCore\Private\RenderGraphUtils.cpp(798,4): error C2760: syntax error: ',' was unexpected here; expected ')'
                 SCOPED_GPU_STAT(RHICommandList, AlertStat1)
                 ^
C:\project\Engine\Source\Runtime\RenderCore\Private\RenderGraphUtils.cpp(798,4): error C2760: syntax error: ',' was unexpected here; expected ';'
C:\project\Engine\Source\Runtime\RenderCore\Private\RenderGraphUtils.cpp(798,4): error C2760: syntax error: ',' was unexpected here; expected '}'
C:\project\Engine\Source\Runtime\RenderCore\Private\RenderGraphUtils.cpp(798,4): error C2059: syntax error: ','
C:\project\Engine\Source\Runtime\RenderCore\Private\RenderGraphUtils.cpp(799,3): error C2059: syntax error: ')'
        });
         ^
C:\project\Engine\Source\Runtime\RenderCore\Private\RenderGraphUtils.cpp(800,1): error C2059: syntax error: '}'
}
^
C:\project\Engine\Source\Runtime\RenderCore\Private\RenderGraphUtils.cpp(800,1): error C2143: syntax error: missing ';' before '}'
C:\project\Engine\Source\Runtime\RenderCore\Private\RenderGraphUtils.cpp(822,1): error C2143: syntax error: missing ';' before '{'
{
^
C:\project\Engine\Source\Runtime\RenderCore\Private\RenderGraphUtils.cpp(822,1): error C2447: '{': missing function header (old-style formal list?)

Hi there,

Yes, that would work. Here is a narrower change that would only no-op if the CSV Profile isnt available.

#if STATS
 
	#define SCOPED_GPU_STAT(RHICmdList, StatName)           FScopedGPUStatEvent PREPROCESSOR_JOIN(GPUStatEvent_##StatName,__LINE__); PREPROCESSOR_JOIN(GPUStatEvent_##StatName,__LINE__).Begin(RHICmdList, CSV_STAT_FNAME(StatName), GET_STATID( Stat_GPU_##StatName ).GetName(), nullptr  , DrawcallCountCategory_##StatName);
 
	#define SCOPED_GPU_STAT_VERBOSE(RHICmdList, StatName, Description) FScopedGPUStatEvent PREPROCESSOR_JOIN(GPUStatEvent_##StatName,__LINE__); PREPROCESSOR_JOIN(GPUStatEvent_##StatName,__LINE__).Begin(RHICmdList, CSV_STAT_FNAME(StatName), GET_STATID( Stat_GPU_##StatName ).GetName(), Description, DrawcallCountCategory_##StatName);
 
#elif CSV_PROFILER
 
	#define SCOPED_GPU_STAT(RHICmdList, StatName)           FScopedGPUStatEvent PREPROCESSOR_JOIN(GPUStatEvent_##StatName,__LINE__); PREPROCESSOR_JOIN(GPUStatEvent_##StatName,__LINE__).Begin(RHICmdList, CSV_STAT_FNAME(StatName), FName(), nullptr  , DrawcallCountCategory_##StatName);
 
	#define SCOPED_GPU_STAT_VERBOSE(RHICmdList, StatName, Description) FScopedGPUStatEvent PREPROCESSOR_JOIN(GPUStatEvent_##StatName,__LINE__); PREPROCESSOR_JOIN(GPUStatEvent_##StatName,__LINE__).Begin(RHICmdList, CSV_STAT_FNAME(StatName), FName(), Description, DrawcallCountCategory_##StatName);
 
#else
 
	#define SCOPED_GPU_STAT(RHICmdList, StatName)            
 
	#define SCOPED_GPU_STAT_VERBOSE(RHICmdList, StatName, Description)
 
#endif

Modifying the engine here should be pretty safe, and if you were to do an engine upgrade, it should be noted that SCOPED_GPU_STAT in 5.6 onwards has been deprecated in favour of RHI_BREADCRUMB_EVENT_STAT with the new GPU profiler

Here’s a video from Luke Thatcher from Unreal Fest Stockholm 2025 about the new GPU profiler, if interested: https://dev.epicgames.com/community/learning/tutorials/7Ox6/unreal-engine-new-gpu-profiler-and-rhi-submission-pipeline

Kind Regards

Keegan Gibson