# Nsight Graphics Analyzer

> >

- **Type:** Skill
- **Install:** `agentstack add skill-frostyleaves-nsight-graphics-analyzer-nsight-graphics-analyzer`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [FrostyLeaves](https://agentstack.voostack.com/s/frostyleaves)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [FrostyLeaves](https://github.com/FrostyLeaves)
- **Source:** https://github.com/FrostyLeaves/nsight-graphics-analyzer/tree/main/plugins/nsight-graphics-analyzer/skills/nsight-graphics-analyzer

## Install

```sh
agentstack add skill-frostyleaves-nsight-graphics-analyzer-nsight-graphics-analyzer
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Nsight Graphics 2026 Skill

Wrapper around NVIDIA Nsight Graphics 2026.1+. The agent captures GPU
frames, gets 3 small JSON artifacts, and uses drill-down subcommands
to answer follow-up questions without ever loading the raw 300+ MB
TSV bundle.

## When to use

User intents that should trigger this skill:

- "Why is this frame slow on the GPU?" / "Profile GPU performance" / "Grab a frame to inspect"
- "Capture a frame from this game" / "frame trace" / "GPU Trace"
- "What draw calls does this frame make?" / "API stream"
- "How fast does this `.ngfx-capture` replay?" / "replay perf"
- "Inspect markers / stages / metrics in this `.ngfx-gputrace`"
- "Generate a C++ capture so I can edit and replay it"

Trigger keywords: `nsight`, `ngfx`, `nsight graphics`, `GPU trace`, `frame
capture`, `frame trace`, `gpu profiling`, `frame profiling`.

## Quick start (90% case)

```
# 1. capture a 200 ms GPU Trace 30 s after launch (game must already be loaded)
python "/scripts/nsight.py" gputrace-capture \
  --exe "C:\Game\game.exe" --wd "C:\Game" \
  --start-after-ms 30000 --max-duration-ms 200 \
  --architecture Ada --metric-set-name "Throughput Metrics" \
  --time-every-action \
  --out "D:\captures\game.ngfx-gputrace"

# 2. the wrapper writes 3 small JSON next to the .ngfx-gputrace:
#    /game.gputrace.summary.json  (~50 KB)
#    /game.gputrace.stages.json   (~3  KB)
#    /game.gputrace.actions.json  (~15 KB)

# 3. drill into the dominant stage from summary.json's analysis.hotspots
python "/scripts/nsight.py" gputrace-stages \
  "/game.ngfx-gputrace" --parent "Render Camera" --top 10
```

Replace `` with the directory containing this `SKILL.md`. For
any subcommand's full flag list run `python scripts/nsight.py  --help`.

**Three rules to never break:**

- `GPUTRACE_REGIMES.xls` is **300+ MB** — never Read it directly. Drill
  through `gputrace-stages` / `gputrace-actions` / `gputrace-metric`.
- Anti-cheat games (EAC/BattlEye/Vanguard) refuse capture and exit with
  code 4. Try `cpp-capture` or disable the anti-cheat per game policy.
- If a capture fails with a permission error, re-run from an elevated
  PowerShell. `doctor` reports `is_admin`.

## Tool layout

A single Python entry point dispatches to 25 subcommands. Full flag list
for any subcommand: `python "/scripts/nsight.py"  --help`.

| Group | Subcommands | Purpose |
|---|---|---|
| Env | `locate` / `doctor` / `capabilities` / `kill` | Detect install, self-check, dump per-binary flags, kill residuals |
| Run no-capture | `launch` / `attach` | Run game under ngfx with no capture taken |
| Capture | `capture` / `cpp-capture` / `gputrace-capture` | Graphics Capture / C++ Capture / GPU Trace + 3 JSON |
| Trigger | `trigger-hotkey` | Synthesize F11 (or another F-key) into a target window so the agent — not a human — fires a `--start-after-hotkey` capture |
| Post-process | `gputrace` | Rebuild 3 JSON from existing trace |
| Drill | `gputrace-stages` / `gputrace-actions` / `gputrace-metric` | Stage tree / leaf-marker top-N / metric aggregate |
| Diagnose (7) | `gputrace-{stalls,bandwidth,shader-bound,texture-cache,overdraw,geometry,draws}` | Focused verdict[]-producing diagnostic commands |
| Replay | `export-{metadata,functions,screenshot}` / `replay-perf` / `replay-analyze` | Metadata / API stream / PNG extraction; replay timing; combined |

Exit codes: `0` success, `2` user error, `3` Nsight not found, `4`
underlying tool failed, `5` wrapper-side timeout. `stdout` is JSON for
query commands; pass `--out FILE` to redirect.

## Parameter Decision Guide

For decisions beyond the Quick Start path — picking a start trigger,
tuning trace quality vs cost, navigating drill-down after capture,
or reaching for an advanced ngfx flag — **Read
`references/parameters.md`**. That file contains five decision tables:

- **A.** User goal → command → required flags → what to read
- **B.** GPU Trace start trigger choice (`--start-after-ms` vs
  `--start-after-frames` vs `--start-after-hotkey` vs SDK)
- **C.** Trace quality vs cost trade-off (`--time-every-action`,
  `--set-gpu-clocks`, `--real-time-shader-profiler`, etc.)
- **D.** Drill-down workflow once the three JSON artifacts are written
- **E.** Advanced 1:1 ngfx flags (rare; skip unless asked)

⚠️ One red-line warning that belongs in the body, not the reference:
**`--multi-pass-metrics` is unusable through this wrapper** (Nsight
2025.3 + 2026.1, verified May 2026). Combined with the mandatory
`--auto-export` it deterministically writes an unloadable
`.ngfx-gputrace`. The wrapper still accepts the flag for
forensic / bug-report purposes but emits a runtime WARNING and returns
`bundle_complete=False`. Full investigation in DESIGN.md → Investigations.

## Capabilities-driven feature gating

The wrapper checks every conditional flag against the live ngfx install
and exits with code 4 + a clear message if your build lacks that flag —
preventing cryptic ngfx parse errors. Run `python scripts/nsight.py
capabilities` to see what's available locally; `wrapper_features.`
maps each wrapper flag to its underlying ngfx flag.

## Subcommand reference

Full flag list for any subcommand: `python scripts/nsight.py  --help`.
This section is the agent-facing purpose only; flag detail lives in `--help`.

### `gputrace-capture`

Wraps `ngfx.exe --activity "GPU Trace Profiler" --auto-export ...`.
Always writes `/.ngfx-gputrace` + `BASE/` + 3 JSON
artifacts. Use `--dry-run` to preview the ngfx command line.

### `trigger-hotkey`

Synthesize a function-key press (default F11) into a target window via
Win32 `SendInput`. Pair with `gputrace-capture --start-after-hotkey`
run in the background to let the agent — not a human — fire the
trigger once an external workflow has reached the desired scene.
See the **Agent-triggered capture** workflow pattern below.

### `gputrace`

Re-runs the parser pipeline against an existing trace + BASE/. Use
after a skill upgrade to regenerate JSON without re-launching the game.

### `gputrace-stages`

Stage-tree drill. `--parent REGEX` returns children of all matching
parents grouped by name. `--depth N` restricts to a specific depth.

### `gputrace-actions`

Top-N leaf markers (deepest D3DPERF_EVENTS nodes). `--filter` matches
the leaf's own name; `--in-marker` matches any ancestor in the path.
`--with-metrics` adds the headline block via one streaming REGIMES pass
(~1-2 s). Important: read the `definition` field — actions are leaf
markers, not raw draw calls.

### `gputrace-metric`

Aggregate one metric. `--name PATTERN` is a regex over the metric
catalog; `--all-matches` allows multi-match output. `--in-marker REGEX`
returns per-marker windows in addition to the global aggregate.

### Diagnostic command family (7 commands)

`gputrace-stalls`, `gputrace-bandwidth`, `gputrace-shader-bound`,
`gputrace-overdraw`, `gputrace-geometry`, `gputrace-texture-cache`,
`gputrace-draws` — focused diagnostic commands. Each returns a
`verdict[]` array of `{tag, severity, message}`, `severity ∈ {info,
medium, high}`. **Thresholds are heuristics; treat verdicts as
investigation starters, not absolute judgments.** Most accept
`--in-marker REGEX` to scope to a subtree (`gputrace-stalls` and
`gputrace-draws` are whole-frame only).

**Recommended investigation order on an unknown frame:**

1. `gputrace-stalls` — rule out CPU-bound / pipeline-bubble first; if
   the GPU isn't busy, the rest of the analysis doesn't matter.
2. `gputrace-bandwidth` — memory-bound vs compute-bound axis.
3. Branch:
   - memory-bound → `gputrace-texture-cache` to localize
   - compute-bound → `gputrace-shader-bound` for SM utilization detail
4. `gputrace-overdraw` — opaque-pass quality.
5. `gputrace-geometry` — vertex/primitive frontend.
6. `gputrace-draws` — CPU-side state-churn / small-batch signals.

### `replay-perf`

Replays a `.ngfx-capture` N times via `ngfx-replay -n N --perf-report-dir`
and parses `iteration_times.csv`. Useful for replay-cost regression;
**not** for original-app GPU performance (that's `gputrace-capture`).

## How to read the artifacts

**Read `summary.json` first.** Four fields that matter:

- `analysis.frame_budget.verdict` → 60fps / 30fps / below_30fps
- `analysis.throughput.dominant` → most loaded subsystem
- `analysis.hotspots.slowest_stage` → where to drill
- `analysis.warnings` → natural-language flags

Then pick a drill direction: stage > 50% GPU → drill it; throughput
dominated by `dram`/`pcie` → memory-heavy; `sm` dominant → shaders.
**Always drill via subcommands**, never by reading `BASE/*.xls` directly
(REGIMES is 300+ MB).

**Top-level JSON shapes:**

```
summary.json:  source, session, summary{frame/marker/metric counts},
               analysis{frame_budget, throughput, hotspots, warnings},
               headline_metrics, metrics[], hardware_context
stages.json:   source, headline_metrics, roots[], top_stages[]
               each: name, depth, total_duration_ns, fraction_of_gpu, headline
actions.json:  source, definition, top_20_slowest_actions[]
               each: name, path, instance_count, duration fields, headline
```

**Diagnostic verdict thresholds** — use these to interpret `verdict[]`
beyond just `severity`:

| Command | Key signal | Healthy | Red |
|---|---|---|---|
| `overdraw` | `overdraw_ratio` | ~1.0 (1.5-3 typical) | > 3 |
| `overdraw` | `zcull_rejection_rate` | > 0.3 |  80%).

### Deep bottleneck dive (single stage > 80% of frame time)

```
gputrace-stages --parent "" --top 20
gputrace-actions --in-marker "" --top 20 --with-metrics
gputrace-metric --name "dramc__throughput" --in-marker ""
gputrace-metric --name "sm__throughput" --in-marker ""
```

### Capture-once-then-iterate

```
gputrace-capture --exe ... --out trace.ngfx-gputrace
# now drill repeatedly; no re-launch needed
gputrace-stages "/trace.ngfx-gputrace" ...
gputrace-actions "/trace.ngfx-gputrace" ...
```

### Reanalyze an old trace

```
gputrace "/old-trace.ngfx-gputrace"   # rebuilds 3 JSON
```

### cpp-capture for repro (deterministic C++ replay code)

```
cpp-capture --exe ... --wait-seconds 10 --out D:\repro
```

### Attach to a running game (can't relaunch, e.g. multiplayer)

```
attach --activity "GPU Trace Profiler" --pid 12345
# user presses F11 in the running app
```

### Agent-triggered capture in a larger workflow

**Use this when:** the agent is orchestrating a wider workflow — launching
the game, running automated tests / bot actions / other skills, then
deciding when to capture — and only the agent (not a human at the
keyboard) knows when the target scene is on screen. Timer-based triggers
(`--start-after-ms` / `--start-after-frames`) don't fit because the
runtime of the surrounding workflow is unpredictable.

**Why F11 simulation is the only option:** ngfx's GPU Trace activity
exposes exactly five start triggers (`--start-after-ms` /
`--start-after-frames` / `--start-after-submits` / `--start-after-hotkey`
/ `--start-with-ngfx-sdk` / `--start-on-replay-begin`). `ngfx-rpc.exe`
is the UI↔replayer IPC, not a trace-trigger RPC, and `--start-with-ngfx-sdk`
requires the game to link the NGFX SDK and call `NGFX_GPUTrace_StartTrace`.
For an unmodified target, **hotkey is the only externally addressable
trigger**, and `trigger-hotkey` synthesizes it without a human.

**Pattern:**

```
# 1. Launch ngfx + game in the background, armed for F11 trigger.
#    DO NOT wait on this command — it blocks until the trace is written.
python scripts/nsight.py gputrace-capture \
  --exe "C:\Game\game.exe" --wd "C:\Game" \
  --start-after-hotkey \
  --max-duration-ms 200 \
  --architecture  --metric-set-name "Throughput Metrics" \
  --time-every-action \
  --out "D:\captures\game.ngfx-gputrace"
# (Run via your harness's background-task primitive; capture the task ID.)

# 2. Attach a streaming watcher to the background task's output so the
#    agent is notified when the bundle is written. The wrapper prints
#    "GPU Trace report saved to ..." then "bundle_complete=True". Watch
#    for those lines (and also for "error", "fatal", "denied" to fail fast).

# 3. The agent now runs the rest of the workflow (other skills, automated
#    tests, scripted gameplay) — no polling. The capture is dormant in
#    the game process; F11 has not been pressed yet.

# 4. When the workflow signals "ready to capture":
python scripts/nsight.py trigger-hotkey --process game
# Returns JSON with foreground_ok / sent fields. exit 0 = key delivered.

# 5. ngfx hook receives F11, runs the 200 ms trace, writes the bundle,
#    wrapper post-processes into 3 JSON. The streaming watcher from step 2
#    fires; the agent reads summary.json and drills as usual.
```

**Notes:**

- **Background launch is mandatory.** `gputrace-capture` blocks until the
  bundle is written, which is "forever" from the agent's point of view
  (it depends on when step 4 fires). The agent must run step 1
  asynchronously.
- **Watch for completion, do not poll.** The wrapper writes `bundle_complete=True`
  + the saved path to its stdout/stderr; pipe that into your harness's
  streaming notification primitive so the agent reacts to the event
  rather than guessing.
- **Windowed/borderless mode preferred.** `SendInput` is reliable against
  windowed and borderless-window games. Exclusive-fullscreen + DRM
  combinations can swallow synthetic keystrokes; if `trigger-hotkey`
  reports `sent=true` but no trace appears, switch the game to
  borderless-window and retry.
- **Foreground stealing is restricted on Windows.** `trigger-hotkey`
  calls `AllowSetForegroundWindow(ASFW_ANY) + SetForegroundWindow`,
  which works from an elevated shell (`doctor` reports `is_admin=true`)
  and usually from a non-elevated shell that recently saw user input.
  If it can't bring the window forward it still sends the key (ngfx's
  hook is global) and emits a stderr WARNING. Pass `--no-foreground` to
  skip the foreground step entirely if you'd rather not steal focus.
- **Use `--use-scancode` if the default fails.** Some engines / DRM
  shims only honour hardware scancodes (KEYEVENTF_SCANCODE). The flag
  toggles the wParam encoding without other changes.
- **ngfx 2026.1.x cleanup-phase crash is benign.** After the trace is
  written, ngfx exits with rc `0xC0000409` *after* `trace_written=True`
  and `bundle_complete=True`. The wrapper detects this and still
  produces the 3 JSON. Don't treat the non-zero rc as failure; check
  `bundle_complete` instead.
- **Disambiguating multiple instances.** If `tasklist` finds more than
  one process matching `--process`, `trigger-hotkey` refuses and lists
  the PIDs; re-run with `--pid `. Always use `--pid` when ngfx itself
  launched the game (you have the PID from the capture-task output).

## Out of scope

- **Per-API-call timing** (no `vkCmdDraw` durations — Nsight 2026.1
  removed `GPUTrace.pyd`; actions in this skill are leaf markers, not
  raw draw calls). Use RenderDoc/PIX for per-API timing.
- **HTML/PDF report generation** — agent writes Markdown directly.
- **Capture diff** (compare two runs) — future work.
- **Cross-platform** — Windows only.
- **Auto-installing Nsight** — `doctor` only detects.
- **Remote capture (ngfx-rpc)** — use `ngfx-rpc.exe` manually if needed.
- **NVTX marker injection** — game-side, not skill-side.
- **GUI launching** — open `ngfx-ui.exe` manually for visual inspection.

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [FrostyLeaves](https://github.com/FrostyLeaves)
- **Source:** [FrostyLeaves/nsight-graphics-analyzer](https://github.com/FrostyLeaves/nsight-graphics-analyzer)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-frostyleaves-nsight-graphics-analyzer-nsight-graphics-analyzer
- Seller: https://agentstack.voostack.com/s/frostyleaves
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
