This runbook is the operator-facing guide for the Phase 72 renderer and platform
profiling stack. The Tracy-specific workflow remains in
V2/docs/engineering/tracy-profiling-workflow.md; this document ties Tracy,
RenderDoc, PIX, Xcode GPU capture, Vulkan labels, Nsight Graphics, Superluminal,
GPU timing, memory, shader statistics, histograms, and GPU regression gates into
one workflow.
Source Of Truth#
The implementation is validated by these contracts:
V2/ue/Build/Performance/v2-tracy-profiling-workflow.jsonV2/ue/Build/Performance/v2-renderdoc-capture-api.jsonV2/ue/Build/Performance/v2-renderdoc-overlay-suppression.jsonV2/ue/Build/Performance/v2-gpu-timing-query-system.jsonV2/ue/Build/Performance/v2-gpu-timing-overlay.jsonV2/ue/Build/Performance/v2-pix-event-markers.jsonV2/ue/Build/Performance/v2-metal-gpu-capture.jsonV2/ue/Build/Performance/v2-vulkan-debug-labels.jsonV2/ue/Build/Performance/v2-nsight-graphics-markers.jsonV2/ue/Build/Performance/v2-gpu-memory-dashboard.jsonV2/ue/Build/Performance/v2-shader-statistics-collection.jsonV2/ue/Build/Performance/v2-frame-time-histogram.jsonV2/ue/Build/Performance/v2-gpu-performance-regression.jsonV2/ue/Build/Performance/v2-superluminal-markers.jsonV2/ue/Build/Performance/v2-cross-platform-profiling-abstraction.jsonV2/ue/Build/Performance/v2-profiling-documentation.json
Renderer code lives under libs/maya/engine-core/crates/maya-renderer/src. CPU
instrumentation uses maya_renderer_profile_scope!, which keeps the Tracy zone
alive while emitting platform markers for Superluminal, PIX, and Nsight when the
backend and platform support them.
Tool Setup Matrix#
Use this matrix when choosing the first tool for a profiling request.
| Tool | Platform | Setup | Primary output |
|---|---|---|---|
| Tracy | All dev builds with --features tracy |
Build the affected Rust crate with tracy; never enable shipping+tracy |
.tracy capture and CI p95 report |
| RenderDoc | Vulkan, DX12, and supported desktop GPU paths | Enable the RenderDoc capture API and keep overlay suppression active during capture | Frame capture with clean overlays |
| GPU timing overlay | Dev renderer builds | Enable timestamp query backend and the dev overlay toggle | Per-pass timing bars and frame snapshots |
| PIX | Windows DX12 | Use PIX event markers from pix_markers; markers are DX12-only |
Named GPU regions in PIX |
| Xcode GPU capture | macOS Metal | Use MetalCaptureConfig and the Xcode capture destination |
Saved/Profiling/Metal/maya-metal-capture-{frame}-{label}.gputrace |
| Vulkan debug labels | Vulkan | Keep vkCmdBeginDebugUtilsLabel labels around render passes and compute dispatches |
Named passes in Vulkan debuggers |
| NVIDIA Nsight Graphics | Vulkan or DX12 on NVIDIA GPUs | Use NVTX ranges through nsight_markers |
Render pass, compute dispatch, and debug marker ranges |
| Superluminal Performance | Windows CPU profiling | Load PerformanceAPI.dll and use Superluminal thread names and event scopes |
CPU event timeline with render command mapping |
| GPU memory dashboard | All renderer backends | Feed resource lifetimes, memory budgets, and resource descriptors | Memory pressure, breakdowns, and top resource rows |
| Shader statistics | Shader compiler outputs | Parse compiler reports and shader source metadata | VGPR, SGPR, occupancy, and warning rows |
Local command shape for Tracy-enabled Rust validation:
cd libs/maya/engine-core
CARGO_BUILD_JOBS=1 cargo check -p maya-renderer --features tracy
TRACY_NO_INVARIANT_CHECK=1 CARGO_BUILD_JOBS=1 cargo test -p maya-renderer --lib profiling_abstraction --features tracy
Local command shape for GPU regression validation:
python3 V2/ue/Tools/run-v2-gpu-performance-regression.py --self-test
python3 V2/ue/Tools/check-v2-gpu-performance-regression.py
Capture Workflows#
Start with the workflow that matches the symptom.
| Symptom | First capture | Required follow-up |
|---|---|---|
| CPU spike, scheduler gap, lock contention, or packet burst | Tracy | Preserve .tracy, Git SHA, command line, and p95 frame summary |
| Single-frame rendering defect | RenderDoc | Capture with overlay suppression enabled and note the triggering pass |
| DX12 GPU pass ordering or marker issue | PIX | Confirm PIXBeginEvent and PIXEndEvent ranges are balanced |
| Metal-only rendering defect | Xcode GPU capture | Save the .gputrace path and frame label |
| Vulkan or NVIDIA GPU bottleneck | Nsight Graphics | Confirm nvtxRangePushEx and nvtxRangePop ranges surround render passes |
| CPU timeline correlation on Windows | Superluminal Performance | Confirm PerformanceAPI_BeginEvent, PerformanceAPI_EndEvent, and thread names |
| Memory pressure or residency issue | GPU memory dashboard | Export memory breakdown and top 32 resource rows |
| Shader occupancy or register pressure issue | Shader statistics | Preserve compiler report input and warning rows |
| Repeatable GPU performance regression | GPU regression runner | Compare current report with baseline and store the report artifact |
Manual Tracy capture still uses:
tracy-capture -o Saved/Profiling/Tracy/maya-capture.tracy -a 127.0.0.1 -p 8086 -f -s 10 -m 4096
GPU regression capture uses the standardized scene contract:
/Game/V2/Performance/Maps/GPUBaseline_City
V2_GPURegression_CityFlythrough
pc-ultra-4k
3840x2160
30 warmup frames
120 sample frames
required passes: shadow_map, gbuffer, lighting, post_process
Triage Workflow#
Use this order for performance incidents:
- Confirm the frame-time histogram: p50, p95, p99, jitter, hitch count, and
whether samples exceed
DEFAULT_FRAME_TIME_HISTOGRAM_HITCH_US. - Check GPU timing overlay bars and pass snapshots to decide whether the frame is CPU-bound, GPU-bound, or memory-bound.
- If CPU-bound, open Tracy first; on Windows, open Superluminal when thread naming or render command mapping needs a second CPU view.
- If GPU-bound, choose RenderDoc for correctness, PIX for DX12, Xcode GPU capture for Metal, or Nsight Graphics for NVIDIA Vulkan/DX12 captures.
- If memory-bound, inspect the GPU memory dashboard pressure level, resource breakdown, transient resources, alias groups, and large resources.
- If shader-bound, inspect shader statistics for VGPR, SGPR, temporary registers, local memory, shared memory, thread group size, wave size, and occupancy percent.
- If the issue is repeatable, run the GPU regression self-test or full standardized scene and compare against baseline.
Every incident note must include the capture tool, artifact path, Git SHA, backend, resolution, render preset, scene, sample count, and threshold result.
Performance Budgets#
Budgets are enforced by source contracts and Horde gates. Do not relax these in docs; change the source contract and checker if the budget changes.
| Budget | Value |
|---|---|
| 60 Hz frame target | 16.67 ms |
| 120 Hz frame target | 8.33 ms |
| 30 Hz recovery target | 33.33 ms |
| Frame histogram hitch threshold | 33.333 ms |
| GPU regression average delta | <= 5.0 percent |
| GPU regression p95 delta | <= 10.0 percent |
| GPU regression p99 delta | <= 12.5 percent |
| GPU regression per-pass p95 delta | <= 15.0 percent |
| GPU regression hitch rate | <= 1.0 percent |
| GPU regression minimum sample count | 60 |
| GPU regression required pass coverage | 100.0 percent |
| GPU memory default budget | 8589934592 bytes |
| GPU memory warning pressure | 80 percent |
| GPU memory critical pressure | 90 percent |
| GPU memory row cap | 32 resources |
| GPU large resource warning | 20 percent of budget |
| Shader VGPR warning / critical | 96 / 128 |
| Shader SGPR warning / critical | 80 / 104 |
| Shader temporary register warning / critical | 96 / 160 |
| Shader low occupancy / critical occupancy | 50 percent / 25 percent |
CI gates that fail the build:
performance.gpu_regression.p95_regression_pct <= 10performance.gpu_regression.pass_p95_regression_pct <= 15performance.gpu_memory_dashboard.budget_pressure == 1performance.frame_time_histogram.budget_hitches == 1performance.shader_statistics.register_pressure == 1performance.cross_platform_profile.balanced_scopes == 1
CI And Release Gates#
The V2 build workflow must run these documentation checks:
python3 V2/ue/Tools/check-v2-profiling-documentation.py
python3 -m json.tool V2/ue/Build/Performance/v2-profiling-documentation.json
python3 V2/tools/validate-v2-docs.py
The profiling documentation gate is complete only when these Horde gates are present:
profiling-doc-tool-setupprofiling-doc-capture-workflowsprofiling-doc-performance-budgetsprofiling-doc-evidence-checklistprofiling-doc-ci-wired
The broader profiling gate chain must also keep the Tracy, RenderDoc, GPU timing, PIX, Metal, Vulkan, Nsight, GPU memory, shader statistics, frame histogram, GPU regression, Superluminal, and cross-platform profiling checks in the workflow.
Evidence Checklist#
Attach this evidence for any profiler-driven performance fix:
- Capture artifact:
.tracy, RenderDoc capture,.wpix,.gputrace, Nsight report, Superluminal session export, GPU memory snapshot, shader statistics report, or GPU regression report. - Git SHA and branch.
- Backend: Vulkan, DirectX12, Metal, or WebGPU.
- Platform and GPU driver version when available.
- Scene, map, view sequence, resolution, render preset, and sample count.
- Frame histogram p50, p95, p99, jitter, and hitch count.
- GPU regression result with average, p95, p99, per-pass p95, hitch rate, and pass coverage.
- Budget result: pass, warning, or failed.
Verification#
Run these checks after changing profiling docs, contracts, or workflow wiring:
python3 V2/ue/Tools/check-v2-profiling-documentation.py
python3 V2/ue/Tools/check-v2-ci-workflow.py
python3 -m json.tool V2/ue/Build/Performance/v2-profiling-documentation.json
python3 -m json.tool V2/ue/Build/Horde/v2-buildgraph-job.json
python3 V2/tools/validate-v2-docs.py
npx prettier --check V2/docs/engineering/profiling-tool-setup-workflows-budgets.md
For changes that touch Rust profiling macros, marker encoders, or GPU regression
data models, also run the affected cargo check and focused unit tests from
libs/maya/engine-core.