Untoon Engine

Trace-Macro-Reference

本页目录

追踪宏速查

这里整理 Unreal 渲染代码里常用的追踪、统计和内存标记宏,方便给 Untoon pass 起统一的观测名字。这些宏只影响可观测性,不该改变渲染结果。

适用场景:

  • 在 Unreal Insights 中查看 CPU / RDG / GPU timeline
  • 在 stat 系统中查看 CPU cycle 或计数
  • 在 CSV profiler 中导出性能数据
  • 在 Low Level Memory Tracker 中归类内存分配
  • 给 RHI breadcrumb / GPU crash marker 提供可读名字

基本原则

优先选择静态名字,避免在高频路径中构造动态字符串。能用 TRACE_CPUPROFILER_EVENT_SCOPE(RenderToonLightPass) 时,不要为了显示同样名字改用动态 FString。

在 Engine/Source/Runtime/Renderer/Private/Untoon 下新增 pass 时,至少放这几个宏:

LLM_SCOPE_BYNAME(TEXT("Untoon.LightPass"));
RDG_CSV_STAT_EXCLUSIVE_SCOPE(GraphBuilder, Toon);
SCOPED_NAMED_EVENT(FDeferredShadingSceneRenderer_RenderToonLightPass, FColor::Turquoise);
SCOPE_CYCLE_COUNTER(STAT_CLP_ToonLightPass);
RDG_EVENT_SCOPE_STAT(GraphBuilder, ToonLightPass, "ToonLightPass");

这些宏分别覆盖 LLM、CSV、CPU named event / CPU trace、stat cycle counter、RDG / GPU stat。

RDG 与 RHI 宏

常用头文件:

  • Engine/Source/Runtime/RenderCore/Public/RenderGraphEvent.h
  • Engine/Source/Runtime/RHI/Public/RHIBreadcrumbs.h
  • Engine/Source/Runtime/RenderCore/Public/ProfilingDebugging/RealtimeGPUProfiler.h
宏 用途 常见位置 备注
RDG_EVENT_NAME("Name") 给 GraphBuilder.AddPass / AddDispatchPass 提供 pass 名称 RDG pass 创建处 只是名字对象,通常传给 RDG_EVENT_NAME(...) 参数
RDG_EVENT_NAME("Name%d", Index) 创建带参数的 RDG pass 名称 per-view / per-stage pass 动态格式化比静态名字更贵,必要时再用
RDG_EVENT_SCOPE(GraphBuilder, "Name") 在 RDG timeline 中创建作用域 pass 调度函数顶层或子阶段 不绑定 GPU stat
RDG_EVENT_SCOPE_STAT(GraphBuilder, StatName, "Name") 创建 RDG 作用域并绑定 GPU stat 主要渲染 pass 顶层 StatName 需要先声明 DECLARE_GPU_STAT 或 DECLARE_GPU_DRAWCALL_STAT
RDG_EVENT_SCOPE_CONDITIONAL(GraphBuilder, Condition, "Name") 条件创建 RDG 作用域 多 view、debug-only 或可选阶段 常用于 Views.Num() > 1 的 per-view 标记
RDG_EVENT_SCOPE_CONDITIONAL_STAT(GraphBuilder, Condition, StatName, "Name") 条件 RDG 作用域并绑定 GPU stat 可选 GPU 阶段 条件为 false 时不创建
RDG_EVENT_SCOPE_FINAL(GraphBuilder, "Name") 创建 final RDG 作用域 需要压住子事件的聚合区域 会禁用同类嵌套 scope,谨慎使用
RDG_RHI_EVENT_SCOPE(GraphBuilder, Name) 同时加 RDG scope 和 RHI breadcrumb RHI 命令明显分段处 Name 参数会被字符串化
RDG_RHI_EVENT_SCOPE_STAT(GraphBuilder, Stat, Name) 同时加 RDG scope、RHI breadcrumb 和 GPU stat 重要 GPU 阶段 适合 render target 分配、visibility、主要 pass
RHI_BREADCRUMB_EVENT(RHICmdList, "Name") 给 RHI command list 加 breadcrumb 非 RDG 或底层 RHI 代码 用于 GPU crash marker / RHI timeline
RHI_BREADCRUMB_EVENT_STAT(RHICmdList, Stat, "Name") RHI breadcrumb 并绑定 GPU stat 非 RDG GPU 区间 RDG 代码优先用 RDG_RHI_EVENT_SCOPE_STAT
RDG_GPU_MASK_SCOPE(GraphBuilder, View.GPUMask) 限定 RDG pass 的 GPU mask 多 GPU / per-view pass 常和 per-view scope 一起使用
RDG_CSV_STAT_EXCLUSIVE_SCOPE(GraphBuilder, StatName) 在 RDG scope 生命周期内记录 CSV exclusive stat RDG pass 顶层 依赖 CSV_PROFILER_STATS

GPU Stat 声明宏

宏 用途 常见位置 备注
DECLARE_GPU_STAT(StatName) 声明一个 GPU stat .cpp 文件顶层 用于 RDG_EVENT_SCOPE_STAT
DECLARE_GPU_STAT_NAMED(StatName, TEXT("Display Name")) 声明带显示名的 GPU stat .cpp 文件顶层 显示名需要更友好时使用
DECLARE_GPU_STAT_EXTERN(StatName) 在头文件声明外部 GPU stat .h 文件 与 DEFINE_GPU_STAT 配对
DEFINE_GPU_STAT(StatName) 定义外部 GPU stat 一个 .cpp 文件 避免多重定义
DECLARE_GPU_DRAWCALL_STAT(StatName) 声明带 drawcall 分类的 GPU stat mesh pass / raster pass .cpp 适合 BasePass、ShadowDepth、Untoon mesh pass
DECLARE_GPU_DRAWCALL_STAT_NAMED(StatName, TEXT("Display Name")) 声明带显示名的 drawcall GPU stat .cpp 文件顶层 名字需要空格或更清晰时使用
DECLARE_GPU_DRAWCALL_STAT_EXTERN(StatName) 头文件外部声明 drawcall GPU stat .h 文件 与 DEFINE_GPU_DRAWCALL_STAT 配对
DEFINE_GPU_DRAWCALL_STAT(StatName) 定义外部 drawcall GPU stat 一个 .cpp 文件 用于跨文件共享 stat

Unreal 5.8 中旧式 SCOPED_GPU_STAT / RDG_GPU_STAT_SCOPE 已废弃。新代码应优先使用 RDG_EVENT_SCOPE_STAT 或 RHI_BREADCRUMB_EVENT_STAT。

CPU Named Event 宏

常用头文件:

  • Engine/Source/Runtime/Core/Public/HAL/PlatformMisc.h
  • Engine/Source/Runtime/Core/Public/ProfilingDebugging/CpuProfilerTrace.h
宏 用途 常见位置 备注
SCOPED_NAMED_EVENT(Name, Color) 创建外部 profiler named event,并同步创建 CPU trace scope 渲染函数顶层 Name 是 token,会字符串化
SCOPED_NAMED_EVENT_TEXT("Name", Color) 使用静态文本创建 named event 需要字符串字面量时 静态名字开销低
SCOPED_NAMED_EVENT_TCHAR(Text, Color) 使用 TCHAR* 创建 named event 已有 TCHAR* 名称时 比静态 token 更动态
SCOPED_NAMED_EVENT_FSTRING(Text, Color) 使用 FString 创建 named event debug 或低频路径 会解引用 *Text,高频路径谨慎使用
SCOPED_NAMED_EVENT_F(Format, Color, ...) 格式化 named event per-view debug 名称 格式化有额外成本
SCOPED_NAMED_EVENT_TCHAR_CONDITIONAL(Text, Color, Condition) 条件 named event 可选阶段 条件 false 时不开始 named event
SCOPED_ENTER_BACKGROUND_EVENT(Name) 标记进入后台相关任务 平台生命周期代码 渲染 pass 中少见

SCOPED_NAMED_EVENT 在 named event 关闭时仍会退化为 TRACE_CPUPROFILER_EVENT_SCOPE,因此它也是 CPU trace 的常见入口。

CPU Trace 宏

宏 用途 常见位置 备注
TRACE_CPUPROFILER_EVENT_SCOPE(Name) 创建静态 CPU trace 作用域 普通 C++ 函数或 lambda 内 推荐用于大多数 CPU 区间
TRACE_CPUPROFILER_EVENT_SCOPE_CONDITIONAL(Name, Condition) 条件 CPU trace 作用域 可选或 debug 路径 条件 false 时不开启
TRACE_CPUPROFILER_EVENT_SCOPE_STR("Name") 使用静态字符串创建 CPU trace 名字不是合法 token 时 字符串指针应稳定
TRACE_CPUPROFILER_EVENT_SCOPE_STR_CONDITIONAL("Name", Condition) 条件静态字符串 trace 可选阶段 比动态字符串更轻
TRACE_CPUPROFILER_EVENT_SCOPE_TEXT(Text) 使用动态字符串创建 CPU trace 动态 pass 名称 开销更高,必要时使用
TRACE_CPUPROFILER_EVENT_SCOPE_TEXT_CONDITIONAL(Text, Condition) 条件动态字符串 trace 低频动态命名 避免高频滥用
TRACE_CPUPROFILER_EVENT_SCOPE_ON_CHANNEL(Name, Channel) 只在指定 trace channel 开启时记录 专用 trace channel 需要同时开启 CpuChannel 和指定 channel
TRACE_CPUPROFILER_EVENT_SCOPE_TEXT_ON_CHANNEL(Text, Channel) 动态字符串 + 指定 channel 专用 trace channel 高频路径谨慎使用
TRACE_CPUPROFILER_EVENT_MANUAL_START(Name) 手动开始 CPU trace 事件 不能用 RAII scope 的代码 必须配对 manual end
TRACE_CPUPROFILER_EVENT_MANUAL_END() 手动结束 CPU trace 事件 与 manual start 配对 同线程配对
TRACE_CPUPROFILER_EVENT_MANUAL_IS_ENABLED() 判断 manual trace 是否开启 避免只为 trace 计算数据 常和 manual start 一起用
TRACE_CPUPROFILER_EVENT_FLUSH() flush 当前线程 trace buffer 进入长时间等待前 低频使用

Stats 宏

常用头文件:

  • Engine/Source/Runtime/Core/Public/Stats/Stats.h
宏 用途 常见位置 备注
DECLARE_STATS_GROUP(TEXT("Desc"), STATGROUP_Name, STATCAT_Advanced) 声明 stat group 模块 .cpp 或公共头 新建大类时使用
DECLARE_STATS_GROUP_VERBOSE(...) 声明默认关闭的 stat group 详细/低频统计 避免默认污染 stat 输出
DECLARE_CYCLE_STAT(TEXT("Desc"), STAT_Name, STATGROUP_Group) 声明 CPU cycle stat .cpp 文件顶层 与 SCOPE_CYCLE_COUNTER 配对
DECLARE_CYCLE_STAT_EXTERN(..., API) 头文件外部声明 cycle stat .h 文件 与 DEFINE_STAT 相关机制配合
DECLARE_DWORD_COUNTER_STAT(TEXT("Desc"), STAT_Name, STATGROUP_Group) 声明每帧清零整数计数 顶层 常用于数量统计
DECLARE_FLOAT_COUNTER_STAT(TEXT("Desc"), STAT_Name, STATGROUP_Group) 声明每帧清零浮点计数 顶层 常用于比例或耗时辅助
DECLARE_DWORD_ACCUMULATOR_STAT(TEXT("Desc"), STAT_Name, STATGROUP_Group) 声明累积整数 顶层 不会每帧自动清零
DECLARE_FLOAT_ACCUMULATOR_STAT(TEXT("Desc"), STAT_Name, STATGROUP_Group) 声明累积浮点数 顶层 适合长期累计
DECLARE_MEMORY_STAT(TEXT("Desc"), STAT_Name, STATGROUP_Group) 声明内存 stat 顶层 粗粒度内存统计
DECLARE_MEMORY_STAT_POOL(TEXT("Desc"), STAT_Name, STATGROUP_Group, Pool) 声明指定内存池 stat 顶层 需要指定 FPlatformMemory region
SCOPE_CYCLE_COUNTER(STAT_Name) 记录当前作用域 CPU cycle 函数或代码块内 需要先 DECLARE_CYCLE_STAT
QUICK_SCOPE_CYCLE_COUNTER(STAT_Name) 快速声明并记录临时 cycle stat 局部临时分析 不适合长期公共命名规范
SCOPE_CYCLE_COUNTER_STATID(StatId) 使用动态 TStatId 记录 cycle 框架/动态 stat 普通 pass 少用
CONDITIONAL_SCOPE_CYCLE_COUNTER(STAT_Name, Condition) 条件 CPU cycle scope 可选路径 条件 false 时空 stat id
SCOPE_SECONDS_ACCUMULATOR(STAT_Name) 累积秒数 长期累计耗时 与 accumulator stat 配合
SCOPE_MS_ACCUMULATOR(STAT_Name) 累积毫秒 长期累计耗时 输出单位是 ms
INC_DWORD_STAT(STAT_Name) 计数 +1 事件计数 每帧或累计取决于 stat 声明
INC_DWORD_STAT_BY(STAT_Name, Amount) 整数计数增加 数量统计 Amount 为 0 时不发送
DEC_DWORD_STAT(STAT_Name) 计数 -1 数量统计 与 inc 对称
DEC_DWORD_STAT_BY(STAT_Name, Amount) 整数计数减少 数量统计 Amount 为 0 时不发送
INC_FLOAT_STAT_BY(STAT_Name, Amount) 浮点计数增加 比例/权重统计 Amount 为 0 时不发送
DEC_FLOAT_STAT_BY(STAT_Name, Amount) 浮点计数减少 比例/权重统计 Amount 为 0 时不发送
SET_DWORD_STAT(STAT_Name, Value) 设置整数 stat 当前值 Nanite bins / light count 等 适合最终值
SET_FLOAT_STAT(STAT_Name, Value) 设置浮点 stat 当前值 比例、时间等 适合最终值
INC_MEMORY_STAT_BY(STAT_Name, Amount) 增加内存 stat 手动内存统计 与 LLM 不是同一系统
DEC_MEMORY_STAT_BY(STAT_Name, Amount) 减少内存 stat 手动内存统计 与 inc 配对

CSV Profiler 宏

常用头文件:

  • Engine/Source/Runtime/Core/Public/ProfilingDebugging/CsvProfiler.h
宏 用途 常见位置 备注
CSV_DEFINE_CATEGORY(Category, true) 定义 CSV 分类 .cpp 顶层 true 表示默认开启
CSV_DEFINE_CATEGORY_MODULE(API, Category, true) 模块导出 CSV 分类 模块公共统计 跨模块时使用
CSV_SCOPED_TIMING_STAT_EXCLUSIVE(StatName) 记录 exclusive CPU 时间 非 RDG 代码块 直接写入 CSV profiler
CSV_SCOPED_TIMING_STAT_EXCLUSIVE_CONDITIONAL(StatName, Condition) 条件 exclusive CPU 时间 可选路径 条件 false 时不记录
RDG_CSV_STAT_EXCLUSIVE_SCOPE(GraphBuilder, StatName) RDG 生命周期内 exclusive CSV stat RDG pass RDG pass 优先使用这个
CSV_CUSTOM_STAT(Category, StatName, Value, Op) 写入自定义 CSV 数值 light count、pass count Op 常用 Set / Accumulate
CSV_CUSTOM_STAT_GLOBAL(StatName, Value, Op) 写入全局自定义 CSV 数值 全局指标 不挂特定 category
CSV_CUSTOM_STAT_MINIMAL(Category, StatName, Value, Op) 更轻量的自定义 stat 高频基础指标 功能较少

LLM 内存宏

常用头文件:

  • Engine/Source/Runtime/Core/Public/HAL/LowLevelMemTracker.h
宏 用途 常见位置 备注
LLM_SCOPE(ELLMTag::Tag) 将作用域内分配归类到内置 LLM tag 系统级代码 tag 来自 ELLMTag
LLM_SCOPE_BYNAME(TEXT("Name")) 使用自定义名字归类内存 Untoon 自有系统 适合 Untoon.LightPass 等
LLM_SCOPE_BYTAG(TagDeclName) 使用声明过的 LLM tag 有全局 tag 声明的系统 依赖 LLM_DECLARE_TAG 系列
LLM_SCOPE_DYNAMIC(UniqueName, Tracker, TagSet, Constructor) 动态 LLM scope 资产、对象、动态名字 成本更高
LLM_SCOPE_RENDER_RESOURCE(Tag) 归类 render resource 内存 Render resource 创建 带 RenderResources. 前缀
LLM_PLATFORM_SCOPE(ELLMTag::Tag) 平台 tracker scope 底层平台分配 和 default tracker 不同
LLM_SCOPE_CLEAR() 清空当前 LLM scope 需要避免继承外层 tag 时 低频使用
LLM_SCOPED_PAUSE_TRACKING(AllocType) 暂停指定分配类型追踪 LLM 内部或特殊 allocator 谨慎使用
LLM_IF_ENABLED(Code) LLM 开启时执行代码 避免无谓计算 宏参数是代码片段
LLM_IS_ENABLED() 查询 LLM 是否开启 条件分支 可避免构建昂贵名字
LLM_DEFINE_TAG(TagDeclName, DisplayName, ParentTagName) 定义可跨文件使用的 LLM tag 一个 .cpp 文件 后两个参数可按宏定义省略或继续传 stat 信息
LLM_DEFINE_STATIC_TAG(TagDeclName, DisplayName, ParentTagName) 定义文件内静态 LLM tag .cpp 文件顶层 不需要跨文件引用时使用
LLM_DECLARE_TAG(TagDeclName) 声明由 LLM_DEFINE_TAG 定义的外部 LLM tag .h 或使用方 .cpp 与 LLM_SCOPE_BYTAG 配合
LLM_DECLARE_TAG_API(TagDeclName, ModuleAPI) 声明带模块导出符号的外部 LLM tag 公共头文件 跨模块使用时需要
LLM_TAG_NAME(TagDeclName) 获取声明 tag 的唯一 FName 需要把 tag name 传给底层接口时 普通 scope 代码通常不需要

Untoon pass 里一般优先使用 LLM_SCOPE_BYNAME(TEXT("Untoon.X")),除非这个内存分类需要跨文件长期复用,再考虑声明正式 LLM tag。

选择建议

目标 推荐宏
想在 RDG / GPU timeline 中看到一个 pass RDG_EVENT_SCOPE_STAT
想给 GraphBuilder.AddPass 命名 RDG_EVENT_NAME
想在多 view 下区分每个 view RDG_EVENT_SCOPE_CONDITIONAL(GraphBuilder, Views.Num() > 1, "View%d", ViewIndex)
想在 CPU timeline 中看到函数耗时 TRACE_CPUPROFILER_EVENT_SCOPE 或 SCOPED_NAMED_EVENT
想在外部 profiler / GPU marker 中看到名字 SCOPED_NAMED_EVENT 或 RHI_BREADCRUMB_EVENT
想在 stat SceneRendering 中看到 CPU cycle DECLARE_CYCLE_STAT + SCOPE_CYCLE_COUNTER
想统计数量、bin 数、light 数 DECLARE_DWORD_COUNTER_STAT + SET_DWORD_STAT
想导出 CSV 性能数据 RDG_CSV_STAT_EXCLUSIVE_SCOPE 或 CSV_CUSTOM_STAT
想知道内存分配属于哪个 Untoon 系统 LLM_SCOPE_BYNAME(TEXT("Untoon.X"))

Untoon 命名建议

Untoon 自有 pass 建议使用稳定、可搜索的名字:

子系统 建议 RDG / GPU stat 名 建议 LLM 名
Shadow Mask ToonShadowMaskPass Untoon.ShadowMask
Shadow Blur / Bloom UntoonShadowBloom Untoon.ShadowBloom
Light Pass ToonLightPass Untoon.LightPass
Outline ToonOutlinePass Untoon.Outline
Nanite Shadow Mask export ToonShadowMaskNanite 继承 Shadow Mask 外层 scope
Nanite Light export ToonLightPassNanite 继承 Light Pass 外层 scope

注意事项

  • 不要把 Untoon pass 的 cycle counter 归到上游无关 stat,例如 Water、Translucency 或 BasePass。
  • 不要在高频 per-pixel、per-primitive 循环中构造动态 profiler 名字。
  • 不要继续新增已废弃的 SCOPED_GPU_STAT、RDG_GPU_STAT_SCOPE。
  • 不要为了追踪宏改动 shader 或渲染结果。
  • 上游文件中新增 Untoon 追踪宏仍然属于 Untoon 改动,必须遵守 marker 规则。
  • Untoon 自有目录 Engine/Source/Runtime/Renderer/Private/Untoon 内不需要 Untoon Engine Start/End marker。

参考源码

  • Engine/Source/Runtime/RenderCore/Public/RenderGraphEvent.h
  • Engine/Source/Runtime/RenderCore/Public/ProfilingDebugging/RealtimeGPUProfiler.h
  • Engine/Source/Runtime/RHI/Public/RHIBreadcrumbs.h
  • Engine/Source/Runtime/Core/Public/HAL/PlatformMisc.h
  • Engine/Source/Runtime/Core/Public/ProfilingDebugging/CpuProfilerTrace.h
  • Engine/Source/Runtime/Core/Public/Stats/Stats.h
  • Engine/Source/Runtime/Core/Public/ProfilingDebugging/CsvProfiler.h
  • Engine/Source/Runtime/Core/Public/HAL/LowLevelMemTracker.h