diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 000000000..c7f1bac99 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,53 @@ +# RenderDoc + GitHub Copilot GPU Debugging + +> Based on [rudybear/renderdoc-skill](https://github.com/rudybear/renderdoc-skill) — adapted for GitHub Copilot. + +## Project Overview + +This project provides Copilot with instructions for GPU frame capture, inspection, and debugging using `rdc-cli` (a 66-command CLI wrapping RenderDoc's Python API). Works with Vulkan, D3D11, D3D12, and OpenGL applications. + +## Tools + +- **rdc-cli** (`rdc`): CLI wrapping RenderDoc's Python API. Install via `pip install rdc-cli`. +- **renderdoc.pyd**: Python module from RenderDoc (built from source or from an official install). + +## Environment + +- `RENDERDOC_PYTHON_PATH=` — rdc-cli uses this to find renderdoc.pyd +- Captures go in `./captures/` (or any directory you choose) +- Analysis exports (PNGs, meshes, buffers) go in `./captures/analysis/` + +## Your Application (customize this section) + + +- **Executable**: `/path/to/your/app` +- **CWD requirement**: Set CWD to your project root if the app resolves assets relative to CWD +- **Debug markers**: List any debug markers your app emits (e.g., "Shadow Pass", "GBuffer Pass") +- **Scenes / modes**: List any flags or scenes relevant to your app + +## Capture Requirements + +- **Vulkan layer**: Must be registered (see `.github/instructions/renderdoc-gpu-debug.instructions.md` for setup details) +- **Environment**: `ENABLE_VULKAN_RENDERDOC_CAPTURE=1` must be set for Vulkan apps +- **Swapchain**: The app must present frames (headless apps without `vkQueuePresentKHR` cannot be captured) +- **Capture script**: Use `rdc capture` or the RenderDoc Python API for programmatic capture + +## Quick Start + +```bash +# Check setup +rdc doctor + +# Capture a frame +rdc capture -o ./captures/my_capture.rdc -- /path/to/app [args...] + +# Inspect +rdc open ./captures/my_capture.rdc +rdc info --json +rdc draws --limit 20 +rdc close +``` + +## GPU Debugging Instructions + +See `.github/instructions/renderdoc-gpu-debug.instructions.md` for the full GPU debugging instructions with workflows, recipes, and command reference. diff --git a/.github/instructions/debugging-recipes.instructions.md b/.github/instructions/debugging-recipes.instructions.md new file mode 100644 index 000000000..177ed3a83 --- /dev/null +++ b/.github/instructions/debugging-recipes.instructions.md @@ -0,0 +1,361 @@ +--- +applyTo: "**/*.{rdc,frag,vert,comp,glsl,hlsl,spv}" +--- + +# GPU Debugging Recipes + +> Adapted from [rudybear/renderdoc-skill](https://github.com/rudybear/renderdoc-skill) for GitHub Copilot. + +Extended debugging workflows with expected output shapes. + +## Recipe 1: Object is Invisible + +**Symptoms**: An object that should be visible in the scene is not rendered. + +### Step-by-step + +```bash +# 1. Open the capture +rdc open ./captures/frame.rdc + +# 2. List all draws to find the expected object +rdc draws --json --limit 50 + +# 3. If you know the pass name, filter: +rdc draws --pass "Raster Pass" --json + +# 4. Check rasterizer state — is back-face culling removing it? +rdc pipeline EID rs --json +``` + +**Expected rasterizer output shape:** +```json +{ + "CullMode": "Back", + "FrontFace": "CounterClockwise", + "DepthClipEnable": true, + "FillMode": "Solid", + "Viewports": [{"X": 0, "Y": 0, "Width": 512, "Height": 512, "MinDepth": 0.0, "MaxDepth": 1.0}] +} +``` + +**Common causes:** +- `CullMode` is `Front` when geometry has clockwise winding (or vice versa) +- Viewport is zero-sized or doesn't cover the object +- Scissor rect clips the object +- Depth test rejects it (object behind another or outside depth range) +- Blend state has `ColorWriteMask: 0` (writing disabled) +- Vertex transform puts vertices off-screen + +```bash +# 5. Check depth state +rdc pipeline EID ds --json + +# 6. Verify the draw is issuing geometry +rdc draw EID --json +# Expected: VertexCount > 0, InstanceCount > 0 + +# 7. Debug a vertex to check transform +rdc debug vertex EID 0 --json +# Look at gl_Position / SV_Position — is it in NDC [-1,1]? + +# 8. Close +rdc close +``` + +--- + +## Recipe 2: Colors Are Wrong + +**Symptoms**: Object renders but with incorrect colors, wrong texture, or unexpected tint. + +### Step-by-step + +```bash +rdc open ./captures/frame.rdc + +# 1. Export what we see +rdc rt EID -o ./captures/analysis/wrong_color.png +# Then view the image to inspect + +# 2. Pick the pixel +rdc pick-pixel 256 256 EID --json +``` + +**Expected pick-pixel output:** +```json +{ + "x": 256, "y": 256, + "r": 0.502, "g": 0.0, "b": 0.0, "a": 1.0 +} +``` + +```bash +# 3. Check bound textures +rdc bindings EID --json +# Look for sampler2D / texture2D bindings, verify resource IDs + +# 4. Export the bound texture to verify it's correct +rdc texture RESID -o ./captures/analysis/bound_tex.png + +# 5. Check constant buffers for material colors +rdc shader EID ps --constants --json + +# 6. Check blend state +rdc pipeline EID om --json +``` + +**Expected output merger shape:** +```json +{ + "BlendState": { + "Blends": [{ + "Enabled": false, + "Source": "One", + "Destination": "Zero", + "Operation": "Add", + "ColorWriteMask": 15 + }] + }, + "DepthStencilState": { + "DepthEnable": true, + "DepthFunc": "LessEqual" + } +} +``` + +```bash +# 7. If still unclear, trace the pixel shader +rdc debug pixel EID 256 256 --trace + +rdc close +``` + +**Common causes:** +- Wrong texture bound (check resource ID matches expected) +- Constant buffer has wrong material color +- Blend state is additive (`Source: One, Dest: One`) when it should be alpha +- Texture format mismatch (sRGB vs linear, swizzled channels) +- Fragment shader has hardcoded color or wrong calculation + +--- + +## Recipe 3: Shadows Are Broken + +**Symptoms**: Shadows are too dark, too blocky, have peter-panning, acne, or are missing entirely. + +### Step-by-step + +```bash +rdc open ./captures/frame.rdc + +# 1. List passes to confirm structure +rdc passes --json + +# 2. Find shadow pass draws +rdc draws --pass "Shadow Pass" --json + +# 3. Get the last shadow pass draw (final shadow map state) +SHADOW_EID=$(rdc draws --pass "Shadow Pass" -q | tail -1) + +# 4. Export the shadow map +rdc rt $SHADOW_EID -o ./captures/analysis/shadow_map.png +# View the image — look for: +# - Resolution (too small = blocky shadows) +# - Coverage (objects should appear as silhouettes) +# - Depth range (should use full [0,1] range) + +# 5. Check shadow map resolution via bindings +rdc bindings $SHADOW_EID --json +# Look at render target dimensions (e.g., 1024x1024 or 2048x2048) + +# 6. Check depth bias (prevents shadow acne) +rdc pipeline $SHADOW_EID rs --json +``` + +**Expected rasterizer with depth bias:** +```json +{ + "DepthBias": 1.25, + "SlopeScaledDepthBias": 1.75, + "DepthBiasClamp": 0.0 +} +``` + +**Shadow acne**: DepthBias too low (or zero). Increase bias. +**Peter-panning**: DepthBias too high. Reduce bias. +**No shadows**: Bias doesn't help — check light matrices in constants. + +```bash +# 7. Find the raster pass that samples the shadow +LIGHT_EID=$(rdc draws --pass "Raster Pass" -q | head -1) + +# 8. Check the fragment shader for shadow sampling +rdc shader $LIGHT_EID ps --source +# Look for: shadow map sampling, bias, PCF kernel, comparison sampler + +# 9. Check light matrices and shadow parameters in constants +rdc shader $LIGHT_EID ps --constants --json +# Look for: lightViewProj, shadowBias, shadowMapSize, pcfRadius + +# 10. Debug a pixel that should be in shadow +rdc debug pixel $LIGHT_EID 300 400 --trace +# Follow the shadow calculation through the trace + +# 11. Export the final frame for comparison +rdc rt $LIGHT_EID -o ./captures/analysis/final_frame.png + +rdc close +``` + +**Common shadow issues:** +| Symptom | Likely Cause | Check | +|---------|-------------|-------| +| Blocky/pixelated | Low shadow map resolution | bindings → RT dimensions | +| Acne (self-shadowing) | Depth bias too low | pipeline rs → DepthBias | +| Peter-panning (detached) | Depth bias too high | pipeline rs → DepthBias | +| Missing entirely | Shadow map not sampled | bindings on raster pass | +| Wrong direction | Light matrix incorrect | shader constants → lightViewProj | +| Hard edges | No PCF / PCF radius = 0 | shader source → PCF code | + +--- + +## Recipe 4: Performance Is Bad + +**Symptoms**: Low FPS, high GPU utilization, large frame time. + +### Step-by-step + +```bash +rdc open ./captures/frame.rdc + +# 1. Get frame statistics +rdc stats --json +# Look for: total draws, total events, per-pass breakdown + +# 2. Check draw count per pass +rdc passes --json +# Excessive draws in any single pass? + +# 3. Look for the most expensive draws (if counters available) +rdc counters --list +# If GPU counters are available: +rdc counters --name "duration" --json + +# 4. Check for massive textures +rdc resources --type Texture --sort size --json +# Textures > 16MB at high resolution may indicate uncompressed or oversized + +# 5. Look for redundant state changes +rdc events --limit 200 --json + +# 6. Check for overdraw with wireframe overlay +rdc rt EID --overlay wireframe -o ./captures/analysis/wireframe.png +# Dense wireframe = high geometric complexity + +rdc close +``` + +**Performance red flags:** +- Draw count > 1000 per pass (consider batching/instancing) +- Textures > 32MB (consider compression, mipmaps) +- Multiple passes with identical draw calls (redundant work) +- Many small draws with state changes between each + +--- + +## Recipe 5: What Changed Between Two Frames + +**Symptoms**: Regression between two builds, or before/after a code change. + +### Step-by-step + +```bash +# Capture both frames +rdc capture -o ./captures/before.rdc -- ./app --args +# ... make code change ... +rdc capture -o ./captures/after.rdc -- ./app --args + +# Quick summary +rdc diff ./captures/before.rdc ./captures/after.rdc --shortstat + +# Detailed comparisons +rdc diff ./captures/before.rdc ./captures/after.rdc --draws --json +rdc diff ./captures/before.rdc ./captures/after.rdc --passes --json +rdc diff ./captures/before.rdc ./captures/after.rdc --resources --json + +# Visual diff of final framebuffer +rdc diff ./captures/before.rdc ./captures/after.rdc \ + --framebuffer \ + --diff-output ./captures/analysis/diff.png +# View diff.png — changed pixels will be highlighted + +# Compare pipeline state at a specific draw +rdc diff ./captures/before.rdc ./captures/after.rdc --pipeline EID --json +``` + +--- + +## Recipe 6: Debug This Pixel + +**Symptoms**: User points at a specific pixel and asks "why does this look like that?" + +### Step-by-step + +```bash +rdc open ./captures/frame.rdc + +# 1. Get pixel history — who wrote to this pixel? +rdc pixel X Y --json +``` + +**Expected pixel history output shape:** +```json +[ + { + "eid": 42, + "name": "DrawIndexed(360)", + "passed": true, + "pre": {"r": 0.0, "g": 0.0, "b": 0.0, "a": 0.0}, + "post": {"r": 0.8, "g": 0.2, "b": 0.1, "a": 1.0}, + "depth_passed": true, + "stencil_passed": true + }, + { + "eid": 67, + "name": "DrawIndexed(180)", + "passed": false, + "failure_reason": "depth_test" + } +] +``` + +```bash +# 2. Go to the draw that produced the final color (last passing entry) +# 3. Read the final pixel value +rdc pick-pixel X Y 42 --json + +# 4. Get the shader execution summary +rdc debug pixel 42 X Y --json + +# 5. If you need the full trace +rdc debug pixel 42 X Y --trace + +# 6. Check specific variable values at a line +rdc debug pixel 42 X Y --dump-at 15 +# Shows all variable values when execution reaches line 15 + +# 7. Cross-reference with pipeline state +rdc pipeline 42 --json + +# 8. Export the render target at that draw to see context +rdc rt 42 -o ./captures/analysis/at_draw_42.png + +rdc close +``` + +**Interpretation guide:** +- If pixel history shows `passed: false` with `failure_reason: depth_test` — the object is behind something +- If pixel history shows `passed: false` with `failure_reason: stencil_test` — stencil mask is blocking +- If the final color differs from shader output — blend state is modifying it +- If no entries in pixel history — nothing is drawing to that pixel (check viewport/scissor) diff --git a/.github/instructions/rdc-commands-reference.instructions.md b/.github/instructions/rdc-commands-reference.instructions.md new file mode 100644 index 000000000..f3fb8a477 --- /dev/null +++ b/.github/instructions/rdc-commands-reference.instructions.md @@ -0,0 +1,710 @@ +--- +applyTo: "**/*.{rdc,frag,vert,comp,glsl,hlsl,spv}" +--- + +# rdc-cli Command Quick Reference + +> Adapted from [rudybear/renderdoc-skill](https://github.com/rudybear/renderdoc-skill) for GitHub Copilot. + +Complete reference for all 66 `rdc-cli` commands. + +## `rdc assert-clean` + +Assert capture log has no messages at or above given severity. + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--min-severity` | Minimum severity threshold. | choice | HIGH | +| `--json` | JSON output. | flag | | + +## `rdc assert-count` + +Assert a capture metric satisfies a numeric comparison. + +**Arguments:** `what` (choice, required) + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--expect` | Expected count value. | integer | | +| `--op` | Comparison operator. | choice | eq | +| `--pass` | Filter by render pass name. | text | | +| `--json` | JSON output. | flag | | + +## `rdc assert-image` + +Compare two images pixel-by-pixel. + +**Arguments:** `expected` (file, required), `actual` (file, required) + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--threshold` | Diff ratio threshold (%). | float | 0.0 | +| `--diff-output` | Write diff visualization PNG. | file | | +| `--json` | JSON output. | flag | | + +## `rdc assert-pixel` + +Assert pixel RGBA at (x, y) matches expected value within tolerance. + +**Arguments:** `eid` (integer, required), `x` (integer, required), `y` (integer, required) + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--expect` | Expected RGBA as 4 space-separated floats. | text | | +| `--tolerance` | Per-channel tolerance. | float | 0.01 | +| `--target` | Render target index. | integer | 0 | +| `--json` | JSON output. | flag | | + +## `rdc assert-state` + +Assert pipeline state value at EID matches expected. + +**Arguments:** `eid` (integer, required), `key_path` (text, required) + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--expect` | Expected value. | text | | +| `--json` | JSON output. | flag | | + +## `rdc attach` + +Attach to a running RenderDoc target by ident. + +**Arguments:** `ident` (integer, required) + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--host` | Target host. | text | localhost | + +## `rdc bindings` + +Show bound resources per shader stage. + +**Arguments:** `eid` (integer, optional) + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--binding` | Filter by binding index. | integer | | +| `--set` | Filter by descriptor set index. | integer | | +| `--json` | Output JSON. | flag | | +| `--no-header` | Omit TSV header | flag | | +| `--jsonl` | JSONL output | flag | | +| `-q, --quiet` | Print primary key column only | flag | | + +## `rdc buffer` + +Export buffer raw data. + +**Arguments:** `id` (integer, required) + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `-o, --output` | Write to file | path | | +| `--raw` | Force raw output even on TTY | flag | | + +## `rdc capture` + +Execute application and capture a frame. + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `-o, --output` | Output .rdc file path. | path | | +| `--api` | Capture API name. | text | | +| `--list-apis` | List capture APIs and exit. | flag | | +| `--frame` | Queue capture at frame N. | integer | | +| `--trigger` | Inject only; do not auto-capture. | flag | | +| `--timeout` | Capture timeout in seconds. | float | 60.0 | +| `--wait-for-exit` | Wait for process to exit. | flag | | +| `--keep-alive` | Keep target process running after capture. | flag | | +| `--auto-open` | Open capture after success. | flag | | +| `--api-validation` | Enable API validation. | flag | | +| `--callstacks` | Capture callstacks. | flag | | +| `--hook-children` | Hook child processes. | flag | | +| `--ref-all-resources` | Reference all resources. | flag | | +| `--soft-memory-limit` | Soft memory limit (MB). | integer | | +| `--delay-for-debugger` | Debugger attach delay (s). | integer | | +| `--json` | Output as JSON. | flag | | + +## `rdc capture-copy` + +Copy a capture from the target to a local path. + +**Arguments:** `capture_id` (integer, required), `dest` (text, required) + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--ident` | Target ident (default: most recent). | integer | | +| `--host` | Target host. | text | localhost | +| `--timeout` | Timeout in seconds. | float | 30.0 | + +## `rdc capture-list` + +List captures from the attached target. + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--ident` | Target ident (default: most recent). | integer | | +| `--host` | Target host. | text | localhost | +| `--timeout` | Timeout in seconds. | float | 5.0 | +| `--json` | Output as JSON. | flag | | + +## `rdc capture-trigger` + +Trigger a capture on the attached target. + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--ident` | Target ident (default: most recent). | integer | | +| `--host` | Target host. | text | localhost | +| `--num-frames` | Number of frames to capture. | integer | 1 | + +## `rdc cat` + +Output VFS leaf node content. + +**Arguments:** `path` (text, required) + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--json` | JSON output | flag | | +| `--raw` | Force raw output even on TTY | flag | | +| `-o, --output` | Write binary output to file | path | | + +## `rdc close` + +Close daemon-backed session. + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--shutdown` | Send shutdown RPC to daemon. | flag | | + +## `rdc count` + +Output a single integer count to stdout. + +**Arguments:** `what` (choice, required) + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--pass` | Filter by render pass name. | text | | + +## `rdc counters` + +Query GPU performance counters. + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--list` | List available counters. | flag | | +| `--eid` | Filter to specific event ID. | integer | | +| `--name` | Filter counters by name substring. | text | | +| `--json` | JSON output. | flag | | +| `--no-header` | Omit TSV header | flag | | +| `--jsonl` | JSONL output | flag | | +| `-q, --quiet` | Print primary key column only | flag | | + +## `rdc debug pixel` + +Debug pixel shader at (X, Y) for event EID. + +**Arguments:** `eid` (integer, required), `x` (integer, required), `y` (integer, required) + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--trace` | Full execution trace (TSV) | flag | | +| `--dump-at` | Var snapshot at LINE | integer | | +| `--sample` | MSAA sample index | integer | | +| `--primitive` | Primitive ID override | integer | | +| `--json` | JSON output | flag | | +| `--no-header` | Suppress TSV header row | flag | | + +## `rdc debug thread` + +Debug compute shader thread at workgroup (GX,GY,GZ) thread (TX,TY,TZ). + +**Arguments:** `eid` (int, required), `gx` `gy` `gz` (int, required), `tx` `ty` `tz` (int, required) + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--trace` | Full execution trace (TSV) | flag | | +| `--dump-at` | Var snapshot at LINE | integer | | +| `--json` | JSON output | flag | | +| `--no-header` | Suppress TSV header row | flag | | + +## `rdc debug vertex` + +Debug vertex shader for vertex VTX_ID at event EID. + +**Arguments:** `eid` (integer, required), `vtx_id` (integer, required) + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--trace` | Full execution trace (TSV) | flag | | +| `--dump-at` | Var snapshot at LINE | integer | | +| `--instance` | Instance index (default 0) | integer | 0 | +| `--json` | JSON output | flag | | +| `--no-header` | Suppress TSV header row | flag | | + +## `rdc diff` + +Compare two RenderDoc captures side-by-side. + +**Arguments:** `capture_a` (file, required), `capture_b` (file, required) + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--draws` | Compare draw calls | flag | | +| `--resources` | Compare resources | flag | | +| `--passes` | Compare passes | flag | | +| `--stats` | Compare stats | flag | | +| `--framebuffer` | Compare framebuffer | flag | | +| `--pipeline` | Compare pipeline at EID | text | | +| `--json` | JSON output | flag | | +| `--format` | Output format | choice | tsv | +| `--shortstat` | One-line summary | flag | | +| `--no-header` | Omit TSV header | flag | | +| `--verbose` | Verbose output | flag | | +| `--timeout` | Timeout in seconds | float | 60.0 | +| `--target` | Color target index (default 0) | integer | 0 | +| `--threshold` | Max diff ratio % to count as identical | float | 0.0 | +| `--eid` | Compare at specific EID (default: last draw) | integer | | +| `--diff-output` | Write diff PNG here | path | | + +## `rdc doctor` + +Run environment checks for rdc-cli. No arguments or options. + +## `rdc draw` + +Show draw call detail. + +**Arguments:** `eid` (integer, optional) + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--json` | JSON output | flag | | + +## `rdc draws` + +List draw calls. + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--pass` | Filter by pass name | text | | +| `--sort` | Sort field | text | | +| `--limit` | Max rows | integer | | +| `--no-header` | Omit TSV header | flag | | +| `--json` | JSON output | flag | | +| `--jsonl` | JSONL output | flag | | +| `-q, --quiet` | Only EID column | flag | | + +## `rdc event` + +Show single API call detail. + +**Arguments:** `eid` (integer, required) + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--json` | JSON output | flag | | + +## `rdc events` + +List all events. + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--type` | Filter by type | text | | +| `--filter` | Filter by name glob | text | | +| `--limit` | Max rows | integer | | +| `--range` | EID range N:M | text | | +| `--no-header` | Omit TSV header | flag | | +| `--json` | JSON output | flag | | +| `--jsonl` | JSONL output | flag | | +| `-q, --quiet` | Only EID column | flag | | + +## `rdc goto` + +Update current event ID via daemon. + +**Arguments:** `eid` (integer, required) + +## `rdc gpus` + +List GPUs available at capture time. + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--json` | Output as JSON. | flag | | + +## `rdc info` + +Show capture metadata. + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--json` | JSON output | flag | | + +## `rdc log` + +Show debug/validation messages from the capture. + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--level` | Filter by severity. | choice | | +| `--eid` | Filter by event ID. | integer | | +| `--json` | JSON output | flag | | +| `--no-header` | Omit TSV header | flag | | +| `--jsonl` | JSONL output | flag | | +| `-q, --quiet` | Print primary key column only | flag | | + +## `rdc ls` + +List VFS directory contents. + +**Arguments:** `path` (text, optional) + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `-F, --classify` | Append type indicator (/ * @) | flag | | +| `-l, --long` | Long format (TSV with metadata) | flag | | +| `--json` | JSON output | flag | | +| `--no-header` | Omit TSV header (with -l) | flag | | +| `--jsonl` | JSONL output (with -l) | flag | | +| `-q, --quiet` | Print name only (with -l) | flag | | + +## `rdc mesh` + +Export post-transform mesh as OBJ. + +**Arguments:** `eid` (integer, optional) + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--stage` | Mesh data stage (default: vs-out) | choice | vs-out | +| `-o, --output` | Write to file | path | | +| `--json` | JSON output | flag | | +| `--no-header` | Suppress OBJ header comment | flag | | + +## `rdc open` + +Create local default session and start daemon skeleton. + +**Arguments:** `capture` (text, optional) + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--preload` | Preload shader cache after open. | flag | | +| `--proxy` | Proxy host[:port] for remote replay. | text | | +| `--remote` | Remote host. | text | | +| `--listen` | Listen on [ADDR]:PORT. | text | | +| `--connect` | Connect to an already-running external daemon. | text | | +| `--token` | Authentication token (required with --connect). | text | | + +## `rdc pass` + +Show detail for a single render pass by 0-based index or name. + +**Arguments:** `identifier` (text, required) + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--json` | Output JSON. | flag | | + +## `rdc passes` + +List render passes. + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--json` | Output JSON. | flag | | +| `--no-header` | Omit TSV header | flag | | +| `--jsonl` | JSONL output | flag | | +| `-q, --quiet` | Print primary key column only | flag | | + +## `rdc pick-pixel` + +Read pixel color at (X, Y) from the current render target. + +**Arguments:** `x` (integer, required), `y` (integer, required), `eid` (integer, optional) + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--target` | Color target index (default 0) | integer | 0 | +| `--json` | JSON output | flag | | + +## `rdc pipeline` + +Show pipeline summary for current or specified EID. + +**Arguments:** `eid` (integer, optional), `section` (text, optional) + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--json` | Output JSON. | flag | | + +## `rdc pixel` + +Query pixel history at (X, Y) for the current or specified event. + +**Arguments:** `x` (integer, required), `y` (integer, required), `eid` (integer, optional) + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--target` | Color target index (default 0) | integer | 0 | +| `--sample` | MSAA sample index (default 0) | integer | 0 | +| `--json` | JSON output | flag | | +| `--no-header` | Omit TSV header | flag | | +| `--jsonl` | JSONL output | flag | | +| `-q, --quiet` | Print primary key column only | flag | | + +## `rdc resource` + +Show details of a specific resource. + +**Arguments:** `resid` (integer, required) + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--json` | Output JSON. | flag | | + +## `rdc resources` + +List all resources. + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--json` | Output JSON. | flag | | +| `--type` | Filter by resource type (exact, case-insensitive). | text | | +| `--name` | Filter by name substring (case-insensitive). | text | | +| `--sort` | Sort order. | choice | id | +| `--no-header` | Omit TSV header | flag | | +| `--jsonl` | JSONL output | flag | | +| `-q, --quiet` | Print primary key column only | flag | | + +## `rdc rt` + +Export render target as PNG. + +**Arguments:** `eid` (integer, optional) + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `-o, --output` | Write to file | path | | +| `--target` | Color target index (default 0) | integer | 0 | +| `--raw` | Force raw output even on TTY | flag | | +| `--overlay` | Render with debug overlay | choice | | +| `--width` | Overlay render width | integer | 256 | +| `--height` | Overlay render height | integer | 256 | + +## `rdc script` + +Execute a Python script inside the daemon process. + +**Arguments:** `script_file` (file, required) + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--arg` | Script argument. | text | | +| `--json` | Raw JSON output. | flag | | + +## `rdc search` + +Search shader disassembly text for PATTERN (regex). + +**Arguments:** `pattern` (text, required) + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--stage` | Filter by stage (vs/ps/cs/...). | text | | +| `--limit` | Max results. | integer | 200 | +| `-C, --context` | Context lines. | integer | 0 | +| `--case-sensitive` | Case-sensitive search. | flag | | +| `--json` | JSON output. | flag | | + +## `rdc sections` + +List all embedded sections. + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--json` | Output as JSON. | flag | | + +## `rdc shader` + +Show shader metadata for a stage at EID. + +**Arguments:** `first` (text, optional), `second` (text, optional) + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--reflect` | Include reflection data (inputs/outputs/cbuffers). | flag | | +| `--constants` | Include constant buffer values. | flag | | +| `--source` | Include debug source code. | flag | | +| `--target` | Disassembly target format (e.g., 'dxil', 'spirv', 'glsl'). | text | | +| `--targets` | List available disassembly targets. | flag | | +| `-o, --output` | Output file path. | path | | +| `--all` | Get all shader data for all stages. | flag | | +| `--json` | Output JSON. | flag | | + +## `rdc shader-build` + +Build a shader from source file. + +**Arguments:** `source_file` (file, required) + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--stage` | Shader stage | choice | | +| `--entry` | Entry point name | text | main | +| `--encoding` | Encoding name (default: GLSL) | text | GLSL | +| `--json` | JSON output | flag | | +| `-q, --quiet` | Print only shader_id | flag | | + +## `rdc shader-encodings` + +List available shader encodings for this capture. + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--json` | JSON output | flag | | + +## `rdc shader-map` + +Output EID-to-shader mapping as TSV. + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--no-header` | Omit TSV header row. | flag | | +| `--json` | JSON output. | flag | | +| `--jsonl` | JSONL output. | flag | | +| `-q, --quiet` | Print EID column only. | flag | | + +## `rdc shader-replace` + +Replace shader at EID/STAGE with a built shader. + +**Arguments:** `eid` (integer, required), `stage` (choice, required) + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--with` | Built shader ID from shader-build | integer | | +| `--json` | JSON output | flag | | + +## `rdc shader-restore` + +Restore original shader at EID/STAGE. + +**Arguments:** `eid` (integer, required), `stage` (choice, required) + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--json` | JSON output | flag | | + +## `rdc shader-restore-all` + +Restore all replaced shaders and free built resources. + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--json` | JSON output | flag | | + +## `rdc shaders` + +List unique shaders in capture. + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--stage` | Filter by shader stage. | choice | | +| `--sort` | Sort order. | choice | name | +| `--json` | Output JSON. | flag | | +| `--no-header` | Omit TSV header | flag | | +| `--jsonl` | JSONL output | flag | | +| `-q, --quiet` | Print primary key column only | flag | | + +## `rdc snapshot` + +Export a complete rendering state snapshot for a draw event. + +**Arguments:** `eid` (integer, required) + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `-o, --output` | Output directory | path | | +| `--json` | JSON output | flag | | + +## `rdc stats` + +Show per-pass breakdown, top draws, largest resources. + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--json` | JSON output | flag | | +| `--no-header` | Omit TSV header | flag | | +| `--jsonl` | JSONL output | flag | | +| `-q, --quiet` | Print primary key column only | flag | | + +## `rdc status` + +Show current daemon-backed session status. No options. + +## `rdc tex-stats` + +Show texture min/max statistics and optional histogram. + +**Arguments:** `resource_id` (integer, required), `eid` (integer, optional) + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--mip` | Mip level (default 0) | integer | 0 | +| `--slice` | Array slice (default 0) | integer | 0 | +| `--histogram` | Show 256-bucket histogram | flag | | +| `--json` | JSON output | flag | | + +## `rdc texture` + +Export texture as PNG. + +**Arguments:** `id` (integer, required) + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `-o, --output` | Write to file | path | | +| `--mip` | Mip level (default 0) | integer | 0 | +| `--raw` | Force raw output even on TTY | flag | | + +## `rdc thumbnail` + +Export capture thumbnail. + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--maxsize` | Max thumbnail dimension. | integer | 0 | +| `-o, --output` | Write image to file. | path | | +| `--json` | Output as JSON. | flag | | + +## `rdc tree` + +Display VFS subtree structure. + +**Arguments:** `path` (text, optional) + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--depth` | Tree depth | integer | 2 | +| `--json` | JSON output | flag | | + +## `rdc usage` + +Show resource usage (which events read/write a resource). + +**Arguments:** `resource_id` (integer, optional) + +| Flag | Help | Type | Default | +|------|------|------|---------| +| `--all` | Show all resources usage matrix. | flag | | +| `--type` | Filter by resource type. | text | | +| `--usage` | Filter by usage type. | text | | +| `--json` | JSON output. | flag | | +| `--no-header` | Omit TSV header | flag | | +| `--jsonl` | JSONL output | flag | | +| `-q, --quiet` | Print primary key column only | flag | | diff --git a/.github/instructions/renderdoc-gpu-debug.instructions.md b/.github/instructions/renderdoc-gpu-debug.instructions.md new file mode 100644 index 000000000..38afdaf51 --- /dev/null +++ b/.github/instructions/renderdoc-gpu-debug.instructions.md @@ -0,0 +1,498 @@ +--- +applyTo: "**/*.{rdc,frag,vert,comp,glsl,hlsl,spv}" +--- + +# RenderDoc GPU Debugging Instructions + +> Adapted from [rudybear/renderdoc-skill](https://github.com/rudybear/renderdoc-skill) for GitHub Copilot. + +## When to Use + +Use these instructions when the user mentions: +GPU debugging, .rdc files, RenderDoc, shader issues, pipeline state, rendering artifacts, +frame capture, shadow problems, visual glitches, draw calls, render targets, pixel history, +texture inspection, depth buffer, blend state, rasterizer state, vertex shader, fragment shader, +pixel shader, compute shader, mesh output, GPU performance, overdraw, bandwidth, shadow map, +PCF filtering, screen-space artifacts, z-fighting, alpha blending, stencil, MSAA, +"why does this look wrong", "debug this pixel", "what's drawing here", "capture a frame", +"inspect the pipeline", "export render target", Vulkan debugging, D3D debugging, GL debugging. + +DO NOT use for: CSS rendering, React rendering, server-side rendering, HTML layout, +browser DevTools, web performance, canvas 2D, SVG rendering. + +## Overview + +This provides GPU frame capture, inspection, and debugging using `rdc-cli`, a 66-command CLI wrapping RenderDoc's Python API. It works with Vulkan, D3D11, D3D12, and OpenGL applications. + +### Prerequisites + +Before any GPU debugging, verify the environment: + +```bash +rdc doctor +``` + +All checks should pass. If `rdc doctor` fails, check: +- `RENDERDOC_PYTHON_PATH` is set to the directory containing `renderdoc.pyd` +- `renderdoc.dll` is in the same directory as `renderdoc.pyd` +- `renderdoccmd.exe` is on PATH or in the module directory + +## 1. Session Lifecycle + +Every inspection session follows open-work-close: + +```bash +rdc open path/to/capture.rdc # Start daemon, load capture +# ... inspection commands ... +rdc close # Release resources, stop daemon +``` + +Check session state with `rdc status`. Only one capture can be open at a time. + +**IMPORTANT**: Always close sessions when done. Leaked daemon processes consume GPU memory. + +## 2. Capture Workflow + +### Capture from an executable + +```bash +rdc capture -o output.rdc -- /path/to/app [app-args...] +``` + +Key options: +- `-o, --output`: Output .rdc file path +- `--frame N`: Capture frame N (default: first presented frame) +- `--timeout S`: Capture timeout in seconds (default: 60) +- `--api-validation`: Enable API validation layer +- `--ref-all-resources`: Reference all resources (larger capture, more complete) +- `--wait-for-exit`: Wait for the app to exit after capture + +### CWD matters + +Many applications resolve assets relative to CWD. Always set CWD appropriately: + +```bash +cd /path/to/app/root && rdc capture -o /output/path/capture.rdc -- ./app +``` + +### Vulkan layer requirement + +For Vulkan apps, the RenderDoc Vulkan layer must be registered: +- **Windows**: Registry `HKCU\SOFTWARE\Khronos\Vulkan\ImplicitLayers` must contain `renderdoc.json` (DWORD 0) +- **Linux**: Copy `renderdoc.json` to `~/.local/share/vulkan/implicit_layer.d/` +- Environment: `ENABLE_VULKAN_RENDERDOC_CAPTURE=1` must be set + +### If headless capture fails + +Headless Vulkan apps (no swapchain / no `vkQueuePresentKHR`) cannot be captured by RenderDoc since frame boundaries are defined by present calls. Options: +1. If possible, run the app in a non-headless mode that opens a window with a swapchain +2. Use the RenderDoc Python API for reliable programmatic capture (see [RenderDoc documentation](https://renderdoc.org/docs/in_application_api.html)) +3. Use `--trigger` mode (inject without auto-capture, then `rdc capture-trigger`) +4. Fall back to `renderdoccmd capture` directly + +## 3. Frame Exploration + +After opening a capture, start with high-level overview: + +```bash +rdc info --json # API, GPU, driver, resolution, frame number +rdc stats --json # Per-pass breakdown, top draws, largest resources +rdc passes # List render passes (debug markers / implicit passes) +rdc draws --limit 20 # First 20 draw calls +rdc count draws # Total draw call count +``` + +### Navigate by pass + +```bash +rdc draws --pass "Shadow Pass" --json # Draws in a specific pass +rdc draws --pass "GBuffer" --limit 10 # First 10 GBuffer draws +``` + +### Navigate by event + +```bash +rdc events --limit 50 # All API events (not just draws) +rdc events --type DrawIndexed --json # Filter by event type +rdc event 42 --json # Detail for one event +``` + +### VFS browsing + +The virtual filesystem provides a structured view of the capture: + +```bash +rdc ls / # Root directories +rdc ls /textures -l # List textures with metadata +rdc tree /pipelines --depth 2 # Pipeline tree +rdc cat /events/42 # Event detail +``` + +## 4. Pipeline State Inspection + +Get full pipeline state at any draw call: + +```bash +rdc pipeline EID --json # Full pipeline state +rdc pipeline EID vs --json # Vertex shader section only +rdc pipeline EID ps --json # Pixel/fragment shader section only +rdc pipeline EID om --json # Output merger (blend, depth, stencil) +rdc pipeline EID rs --json # Rasterizer state (culling, viewport) +rdc pipeline EID ia --json # Input assembler (vertex buffers, topology) +rdc pipeline EID ds --json # Depth-stencil state +``` + +### Bound resources + +```bash +rdc bindings EID --json # All bindings for all stages +rdc bindings EID --set 0 --json # Descriptor set 0 only +``` + +## 5. Shader Inspection + +### View shader metadata and source + +```bash +rdc shader EID vs --json # Vertex shader metadata +rdc shader EID ps --json # Fragment/pixel shader metadata +rdc shader EID ps --source # Debug source code (if available) +rdc shader EID ps --reflect --json # Reflection: inputs, outputs, cbuffers +rdc shader EID ps --constants --json # Constant buffer values at this draw +``` + +### Disassembly targets + +```bash +rdc shader EID ps --targets # List available disassembly formats +rdc shader EID ps --target spirv # SPIR-V disassembly +rdc shader EID ps --target glsl # GLSL (cross-compiled, if available) +``` + +### Search shaders + +```bash +rdc search "shadow" --json # Search all shader disassembly for "shadow" +rdc search "main" --stage ps # Search only pixel shaders +rdc shaders --stage ps --json # List all unique pixel shaders +rdc shader-map --json # EID-to-shader mapping +``` + +## 6. Visual Inspection: Export-View-Analyze + +This is the core pattern for visual debugging. Export to PNG, then view the image to diagnose issues. + +### Export render targets + +```bash +rdc rt EID -o ./captures/analysis/render_target.png +rdc rt EID --target 1 -o ./captures/analysis/rt_target1.png # MRT target 1 +``` + +### Export textures + +```bash +rdc texture RESID -o ./captures/analysis/texture.png +rdc texture RESID --mip 2 -o ./captures/analysis/mip2.png +``` + +### Export thumbnail + +```bash +rdc thumbnail -o ./captures/analysis/thumb.png +``` + +### View exported images + +After exporting a PNG, open it in the editor or image viewer to inspect visually. + +### Analyze + +Correlate what you see in the image with pipeline state data: +1. Export the render target at the suspicious draw +2. View the exported image +3. Check pipeline state (`rdc pipeline EID --json`) +4. Check shader constants (`rdc shader EID ps --constants --json`) +5. Form hypothesis and verify + +## 7. Pixel Debugging + +### Pixel history + +Find all draws that wrote to a pixel: + +```bash +rdc pixel X Y --json # Full pixel history at current event +rdc pixel X Y EID --json # Pixel history up to EID +``` + +### Pick pixel color + +Read the current color at a pixel: + +```bash +rdc pick-pixel X Y --json # Color at (X,Y) from current render target +rdc pick-pixel X Y EID --json # Color at specific event +``` + +### Debug pixel shader + +Step through shader execution for a specific pixel: + +```bash +rdc debug pixel EID X Y --json # Shader inputs/outputs summary +rdc debug pixel EID X Y --trace # Full execution trace (every line) +rdc debug pixel EID X Y --dump-at 42 # Variable snapshot at line 42 +``` + +### Debug vertex shader + +```bash +rdc debug vertex EID VTXID --json # Vertex shader debug for vertex ID +rdc debug vertex EID VTXID --trace # Full trace +``` + +### Debug compute shader + +```bash +rdc debug thread EID GX GY GZ TX TY TZ --json # Compute thread debug +``` + +## 8. Shader Edit-Replay + +Modify shaders without recompiling the application: + +```bash +# 1. Check available encodings +rdc shader-encodings --json + +# 2. Extract shader source +rdc shader EID ps --source -o ./captures/analysis/shader.frag + +# 3. Edit the shader file + +# 4. Build the modified shader +rdc shader-build ./captures/analysis/shader.frag --encoding GLSL --stage ps --json + +# 5. Replace (use the shader_id from build output) +rdc shader-replace EID ps --with SHADER_ID --json + +# 6. Export to verify the change +rdc rt EID -o ./captures/analysis/after_edit.png + +# 7. Restore when done +rdc shader-restore EID ps +# or: rdc shader-restore-all +``` + +## 9. Frame Comparison + +Compare two captures: + +```bash +# Quick summary of differences +rdc diff capture_a.rdc capture_b.rdc --shortstat + +# Detailed comparisons +rdc diff capture_a.rdc capture_b.rdc --draws --json # Draw call differences +rdc diff capture_a.rdc capture_b.rdc --resources --json # Resource differences +rdc diff capture_a.rdc capture_b.rdc --passes --json # Pass structure differences +rdc diff capture_a.rdc capture_b.rdc --framebuffer --json # Final framebuffer diff + +# Visual diff +rdc diff capture_a.rdc capture_b.rdc --framebuffer --diff-output ./captures/analysis/diff.png +``` + +## 10. Debugging Recipes + +### Recipe: Object is invisible + +```bash +# 1. Find the draw call that should render the object +rdc draws --json | jq '.[] | select(.name | contains("ObjectName"))' +# or search by pass: +rdc draws --pass "Main Pass" --json + +# 2. Check if it's being culled +rdc pipeline EID rs --json # Look at CullMode, FrontFace + +# 3. Check depth state +rdc pipeline EID ds --json # DepthEnable, DepthFunc, DepthWriteMask + +# 4. Check blend state (maybe alpha is 0) +rdc pipeline EID om --json # BlendEnable, SrcBlend, DestBlend + +# 5. Check vertex transform +rdc debug vertex EID 0 --json # Is the position off-screen or behind camera? + +# 6. Check if the draw is even issuing primitives +rdc draw EID --json # VertexCount, InstanceCount, IndexCount +``` + +### Recipe: Colors are wrong + +```bash +# 1. Export the render target to see what's there +rdc rt EID -o ./captures/analysis/wrong_color.png + +# 2. Pick the problematic pixel +rdc pick-pixel X Y EID --json + +# 3. Check texture bindings — is the right texture bound? +rdc bindings EID --json + +# 4. Export the bound texture +rdc texture RESID -o ./captures/analysis/bound_texture.png + +# 5. Check shader constants — wrong material colors? +rdc shader EID ps --constants --json + +# 6. Check blend state — additive when it should be alpha? +rdc pipeline EID om --json + +# 7. Debug the pixel shader to trace the calculation +rdc debug pixel EID X Y --trace +``` + +### Recipe: Shadows are broken + +```bash +# 1. Find the shadow pass +rdc passes --json +rdc draws --pass "Shadow*" --json + +# 2. Export the shadow map +SHADOW_EID=$(rdc draws --pass "Shadow*" -q | tail -1) +rdc rt $SHADOW_EID -o ./captures/analysis/shadow_map.png + +# 3. Check shadow map resolution (is it too small?) +rdc bindings $SHADOW_EID --json # Look at render target dimensions + +# 4. Check depth bias +rdc pipeline $SHADOW_EID rs --json # DepthBias, SlopeScaledDepthBias + +# 5. Find the lighting pass that reads the shadow map +rdc draws --pass "Raster*" --json +LIGHT_EID=$(rdc draws --pass "Raster*" -q | head -1) + +# 6. Check how the shadow map is sampled +rdc shader $LIGHT_EID ps --source # Look for shadow sampling code +rdc shader $LIGHT_EID ps --constants --json # Light matrices, bias values + +# 7. Debug a shadowed pixel +rdc debug pixel $LIGHT_EID X Y --trace +``` + +### Recipe: Performance is bad + +```bash +# 1. Get frame overview +rdc stats --json + +# 2. Count draws per pass +rdc passes --json # Look for passes with excessive draw counts + +# 3. Look for redundant state changes +rdc events --limit 500 --json | jq 'group_by(.type) | map({type: .[0].type, count: length}) | sort_by(-.count)' + +# 4. Check for large resources +rdc resources --sort size --json | jq '.[-10:]' # Top 10 largest resources + +# 5. Look for overdraw (if GPU counters available) +rdc counters --list +rdc counters --name "overdraw" --json + +# 6. Export with wireframe overlay to visualize overdraw +rdc rt EID --overlay wireframe -o ./captures/analysis/wireframe.png +``` + +### Recipe: What changed between two frames + +```bash +# Quick diff +rdc diff before.rdc after.rdc --shortstat + +# Detailed diffs +rdc diff before.rdc after.rdc --draws --json +rdc diff before.rdc after.rdc --framebuffer --diff-output ./captures/analysis/frame_diff.png + +# Compare pipeline state at specific draw +rdc diff before.rdc after.rdc --pipeline EID --json +``` + +### Recipe: Debug this pixel + +```bash +# 1. Get pixel history — which draws touched this pixel? +rdc pixel X Y --json + +# 2. Pick the draw that produced the final color +# (usually the last non-failing entry in pixel history) + +# 3. Get the pixel's current value +rdc pick-pixel X Y EID --json + +# 4. Debug the shader at that pixel +rdc debug pixel EID X Y --json + +# 5. Get full execution trace if needed +rdc debug pixel EID X Y --trace + +# 6. Check variable values at a specific shader line +rdc debug pixel EID X Y --dump-at LINE_NUMBER +``` + +## 11. Output Size Management + +GPU captures can produce enormous output. Follow these rules: + +1. **Always use `--limit` for exploration**: `rdc draws --limit 20`, `rdc events --limit 50` +2. **Filter by pass**: `rdc draws --pass "Shadow Pass"` instead of all draws +3. **Use `-q` for ID lists**: `rdc draws -q` returns only EIDs, not full details +4. **Use `--json` selectively**: JSON is verbose; use TSV default for scanning +5. **Pipeline sections**: `rdc pipeline EID vs` instead of full `rdc pipeline EID` +6. **Limit search results**: `rdc search "pattern" --limit 10` + +### Size estimates +- `rdc info`: ~20 lines +- `rdc draws --limit 20`: ~25 lines +- `rdc pipeline EID --json`: ~200-500 lines (full), ~50 lines (per section) +- `rdc shader EID ps --source`: ~50-500 lines depending on shader +- `rdc debug pixel EID X Y --trace`: ~100-1000 lines depending on shader complexity + +## 12. Error Handling + +### rdc not found +```bash +pip install rdc-cli +``` + +### rdc doctor fails +Check `RENDERDOC_PYTHON_PATH` points to directory containing `renderdoc.pyd` and `renderdoc.dll`. + +### Capture fails with "no swapchain" +The app may not present frames in the expected way. Try: +```bash +rdc capture --trigger -- /path/to/app # Inject-only mode +# Then manually trigger: rdc capture-trigger +``` + +### Daemon not responding +```bash +rdc status # Check if daemon is alive +rdc close # Force close +rdc open capture.rdc # Re-open +``` + +### GPU feature not supported +Some features (GPU counters, pixel history) depend on the GPU and driver. Check: +```bash +rdc gpus --json # GPU capabilities +rdc counters --list # Available counters (empty if not supported) +``` + +## Command Reference + +For the complete list of all 66 commands with arguments, options, types, and defaults, see `rdc-commands-reference.instructions.md`. + +For extended debugging recipes with expected output shapes, see `debugging-recipes.instructions.md`.