# Technical Documentation: wolfpld/tracy

> ℹ️ **Provenance:** Multi-Tier Ingestion · [CodeWiki Reference](https://codewiki.google/github.com/wolfpld/tracy)

### Overview (`README.md`)

<div align="center">

# Tracy Profiler

</div>

### A real time, nanosecond resolution, remote telemetry, hybrid frame and sampling profiler for games and other applications.

Tracy supports profiling CPU (Direct support is provided for C, C++, Lua, Python and Fortran integration. At the same time, third-party bindings to many other languages exist on the internet, such as [Rust](https://github.com/nagisa/rust_tracy_client), [Zig](https://github.com/tealsnow/zig-tracy), [C#](https://github.com/clibequilibrium/Tracy-CSharp), [OCaml](https://github.com/imandra-ai/ocaml-tracy), [Odin](https://github.com/oskarnp/odin-tracy), etc.), GPU (All major graphics/compute APIs: OpenGL, Vulkan, Direct3D 11/12, Metal, OpenCL, CUDA, WebGPU.), memory allocations, locks, context switches, automatically attribute screenshots to captured frames, and much more.

- [Documentation](https://github.com/wolfpld/tracy/releases/latest/download/tracy.pdf) for usage and build process instructions
- [Releases](https://github.com/wolfpld/tracy/releases) containing the documentation (`tracy.pdf`) and compiled Windows x64 binaries (`Tracy-<version>.7z`) as assets
- [Changelog](NEWS)
- [Interactive demo](https://tracy.nereid.pl/)







[An Introduction to Tracy Profiler in C++ - Marcos Slomp - CppCon 2023](https://youtu.be/ghXk3Bk5F2U?t=37)

[Introduction to Tracy Profiler v0.2](https://www.youtube.com/watch?v=fB5B46lbapc)  
[New features in Tracy Profiler v0.3](https://www.youtube.com/watch?v=3SXpDpDh2Uo)  
[New features in Tracy Profiler v0.4](https://www.youtube.com/watch?v=eAkgkaO8B9o)  
[New features in Tracy Profiler v0.5](https://www.youtube.com/watch?v=P6E7qLMmzTQ)  
[New features in Tracy Profiler v0.6](https://www.youtube.com/watch?v=uJkrFgriuOo)  
[New features in Tracy Profiler v0.7](https://www.youtube.com/watch?v=_hU7vw00MZ4)  
[New features in Tracy Profiler v0.8](https://www.youtube.com/watch?v=30wpRpHTTag)

---

### Overview (`tests/cuda/repro/graph/README.md`)

# Tracy CUDA Graph GPU Zone Repro

Demonstrates that unpatched Tracy fails to show GPU zones for kernels
launched via CUDA Graphs (`cudaGraphLaunch`).

## Root cause

When kernels are launched through CUDA Graphs, CUPTI delivers
`CONCURRENT_KERNEL` and `MEMCPY` activity records but no corresponding
API callback fires for the individual kernel launches. Tracy's
`matchActivityToAPICall()` always fails, and `matchError()` silently
drops every GPU zone.

## Build and run

```bash
cmake -S . -B ./build
cmake --build ./build --parallel --config Release
ctest --test-dir ./build -C Release -R repro
```

## What to expect

| Tracy version | GPU zones shown |
|---|---|
| Unpatched | 0 |
| Patched (cuda-graph-gpu-zones.patch) | ~30 (10 launches x 3 ops) |

## The graph structure

Each graph launch contains:
1. `vector_add` kernel (c = a + b)
2. Device-to-device memcpy
3. `vector_add` kernel (c = a + c)

The graph is launched 10 times, so 30 GPU operations total.

---

### Overview (`tests/cuda/repro/on_demand/README.md`)

# Tracy CUDA On-Demand Profiling Repro

Demonstrates that unpatched Tracy crashes when a profiler connects to a
CUDA application built with `TRACY_ON_DEMAND`.

## Root cause

`CUDACtx`'s constructor (`TracyCUDA.hpp`) writes a `GpuNewContext` queue
item but does not call `DeferItem()`, unlike every other GPU backend
(Vulkan, OpenGL, D3D11/12, Metal, WebGPU, Rocprof), which all defer it
under `#ifdef TRACY_ON_DEMAND`.

Under on-demand mode, a new connection clears the client's pending
serial queue (`ClearQueues()`) before replaying deferred items. Since
`GpuNewContext` is never deferred, it never survives that clear — no
matter how early the connection happens, even immediately after the
context is created. The `GpuContextName` message that `Name()` sends
right after (already correctly deferred) is then replayed to a server
that has no record of the context, triggering:

    Assertion `ctx' failed in Worker::ProcessGpuContextName

In release builds (assert compiled out) this is undefined behavior —
a null-pointer dereference, typically a segfault.

This is the same bug already fixed for the Rocprof backend in #1336;
see also the closed issue #1171, which describes this exact crash.

## Build and run

```bash
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build
./build/repro &
tracy-capture -o repro.tracy -s 5
```

The reproducer is also registered as a ctest target:

```bash
ctest --test-dir build -R repro
```

## Verifying the GPU zones

`check_gpu_zones` loads a `.tracy` file and prints, for each GPU
context, whether it is named and how many GPU zones it recorded. It
links the Tracy server library, so it is built only on request:

```bash
cmake -B build -DBUILD_CHECK_TOOL=ON
cmake --build build --target check_gpu_zones
./build/check_gpu_zones repro.tracy
# Expected (patched): "GPU context 0: line_scan_processing_cuda, 200 zones"
```

Exit codes: 0 = at least one named context with recorded zones, 2 =
otherwise.

## What to expect

| Tracy version | Result |
|---|---|
| Unpatched | `tracy-capture` crashes: `Assertion 'ctx' failed` |
| Patched | Capture succeeds, GPU context named and populated with zones |

---

### Overview (`tests/rocprof/repro/on_demand/README.md`)

# Rocprofiler On-Demand Profiling Repro

Demonstrates that unpatched Tracy crashes when a profiler connects to a
HIP application built with `TRACY_ON_DEMAND` and `TRACY_ROCPROF`.

## Root cause

Three bugs in `TracyRocprof.cpp` break on-demand profiling:

1. **GpuNewContext not deferred.** `gpu_context_allocate()` writes a
   `GpuNewContext` queue item but does not call `DeferItem()`. When a
   Tracy client connects late, the context creation message is never
   replayed. The server then receives `GpuZoneBegin` events for a
   context it has never seen, triggering:

       Assertion `ctx' failed in ProcessGpuZoneBeginImplCommon

2. **GpuContextName not deferred.** Same function writes the context
   name ("rocprofv3") without calling `DeferItem()`. Even after fixing
   bug 1, a late-connecting client sees the GPU context but it appears
   unnamed in the profiler. Use `check_gpu_ctx_name` to verify.

3. **Kernel symbols dropped before init.** The `data->init` guard at the
   top of `tool_callback_tracing_callback()` blocks all callbacks before
   the GPU context is allocated. Kernel symbol registrations
   (`CODE_OBJECT_DEVICE_KERNEL_SYMBOL_REGISTER`) happen at HIP init
   time — before `data->init` is true — so they are silently dropped.
   Even if the crash is worked around, kernel names would be missing.

## Prerequisites

- AMD GPU with working ROCm driver
- `librocprofiler-sdk.so` available (typically at `/opt/rocm/lib/`)
- `/opt/rocm/bin/hipcc`

## Build and run

```bash
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build
./build/repro &
tracy-capture -o repro.tracy -s 5
```

If ROCm is not under `/opt/rocm`, pass `-DROCM_PATH=/path/to/rocm`.

The reproducer is also registered as a ctest target:

```bash
ctest --test-dir build -R repro
```

## Verifying the context name

`check_gpu_ctx_name` loads a `.tracy` file and prints the GPU context
names. It links the Tracy server library, so it is built only on request:

```bash
cmake -B build -DBUILD_CHECK_TOOL=ON
cmake --build build --target check_gpu_ctx_name
./build/check_gpu_ctx_name repro.tracy
# Expected (patched):   "GPU context 0: rocprofv3"
# Expected (unpatched): "GPU context 0: (unnamed)"
```

Exit codes: 0 = all contexts named, 2 = unnamed context found.

## What to expect

| Tracy version | Result |
|---|---|
| Unpatched | `tracy-capture` crashes: `Assertion 'ctx' failed` |
| Patched (GpuNewContext only) | Capture succeeds but GPU context is unnamed |
| Fully patched | Capture succeeds with ~50 GPU zones and context named "rocprofv3" |

---

--- METRICS ---
- Files Extracted: 4
- Estimated Token Budget: ~1952 tokens
- Canonical Reference: https://codewiki.google/github.com/wolfpld/tracy
