全自动化截帧到逆向还原分析,配合unityMCP效果更佳
개요
从安装到精通 —— 让 AI 帮你分析 GPU 截帧、逆向着色器、导出 Unity 资源 RenderDoc MCP Server 是一个 ,它充当 AI 智能体与 RenderDoc 之间的桥梁。装上它之后,你可以用自然语言让 AI: - 🔍 分析 GPU 截帧中的每一个绘制调用 - 🎨 自动识别贴图用途(漫反射、法线、PBR 等) - 💎 逆向还原着色器(HLSL/GLSL/SPIR-V) - 📊 读取 Shader 运行时参数的真实值 - 🐛 逐行调试像素/顶点着色器 - 📤 一键导出模型+贴图+材质到 Unity - ⚡ 分析 GPU 性能瓶颈 因为 RenderDoc 内置的 Python 是 3.6 版本,而 MCP SDK 需要 Python 3.10+。两个 Python 版本无法直接互通,所以使用 来桥接: - :运行在系统 Python 3.10+ 上,负责与 AI 通信 - :运行在 RenderDoc 内置的 Python 3.6 上,负责实际操作 GPU 数据 - :通过 %TEMP%/renderdoc_mcp_ipc/ 目录下的 JSON 文件交换数据 1. 访问 https://renderdoc.org/builds 2. 下载最新稳定版安装包 3. 安装到默认路径(如 C:\Program Files\RenderDoc) 4. 验证:运行 qrenderdoc.exe 能正常打开 1. 打开 RenderDoc 2. 菜单 File > Launch Application 3. 选择你要截帧的程序(游戏/图形应用) 4. 点击 Launch 5. 在应用运行时按 F12 或 Print Screen 截帧 6. 截帧文件保存为 .rdc 格式 如果 pip install -e . 报错 Unable to determine which files to ship inside the wheel,确保 pyproject.toml 包含:
README
RenderDoc MCP Server 完整使用手册
从安装到精通 —— 让 AI 帮你分析 GPU 截帧、逆向着色器、导出 Unity 资源
版本: 1.5.0 | 工具数量: 37 个 | 更新日期: 2026-04-14
📖 目录
第一章:概述与架构
1.1 这是什么?
RenderDoc MCP Server 是一个 MCP(Model Context Protocol)服务器,它充当 AI 智能体与 RenderDoc 之间的桥梁。装上它之后,你可以用自然语言让 AI:
- 🔍 分析 GPU 截帧中的每一个绘制调用
- 🎨 自动识别贴图用途(漫反射、法线、PBR 等)
- 💎 逆向还原着色器(HLSL/GLSL/SPIR-V)
- 📊 读取 Shader 运行时参数的真实值
- 🐛 逐行调试像素/顶点着色器
- 📤 一键导出模型+贴图+材质到 Unity
- ⚡ 分析 GPU 性能瓶颈
1.2 三层架构
┌─────────────┐ stdio ┌──────────────────┐ 文件IPC ┌──────────────────┐
│ AI / IDE │ ◄────────────► │ MCP Server │ ◄────────────► │ RenderDoc 扩展 │
│ (WorkBuddy) │ │ (Python 3.10+) │ │ (Python 3.6) │
│ │ │ server.py │ │ __init__.py │
└─────────────┘ └──────────────────┘ └──────────────────┘
│ │
37 个 MCP 工具 pyrenderdoc API
(renderdoc.dll)
为什么需要三层?
因为 RenderDoc 内置的 Python 是 3.6 版本,而 MCP SDK 需要 Python 3.10+。两个 Python 版本无法直接互通,所以使用 文件 IPC(进程间通信) 来桥接:
- MCP Server:运行在系统 Python 3.10+ 上,负责与 AI 通信
- RenderDoc 扩展:运行在 RenderDoc 内置的 Python 3.6 上,负责实际操作 GPU 数据
- IPC 通信:通过
%TEMP%/renderdoc_mcp_ipc/目录下的 JSON 文件交换数据
1.3 系统要求
| 组件 | 最低要求 |
|---|---|
| 操作系统 | Windows 10/11, Linux, macOS |
| RenderDoc | v1.20+ (推荐 v1.30+) |
| 系统 Python | 3.10+ (用于运行 MCP Server) |
| MCP 客户端 | WorkBuddy / Claude Desktop / 任何 MCP 兼容客户端 |
| 磁盘空间 | ~50MB (不含截帧文件) |
第二章:环境准备
2.1 安装 RenderDoc
Windows:
- 访问 https://renderdoc.org/builds
- 下载最新稳定版安装包
- 安装到默认路径(如
C:\Program Files\RenderDoc) - 验证:运行
qrenderdoc.exe能正常打开
Linux (Ubuntu/Debian):
sudo apt-get install renderdoc
# 或从 PPA 安装最新版
sudo add-apt-repository ppa:baldurk/renderdoc
sudo apt-get update
sudo apt-get install renderdoc
2.2 安装 Python 3.10+
如果系统已有 Python 3.10+,可跳过。
Windows:
# 使用 winget
winget install Python.Python.3.12
# 或访问 https://www.python.org/downloads/ 手动下载
Linux:
sudo apt-get install python3.12 python3.12-venv python3-pip
验证:
python --version
# 应显示 Python 3.10+ 的版本号
2.3 获取一个 GPU 截帧
如果你还没有 .rdc 截帧文件,可以这样获取:
- 打开 RenderDoc
- 菜单
File > Launch Application - 选择你要截帧的程序(游戏/图形应用)
- 点击
Launch - 在应用运行时按
F12或Print Screen截帧 - 截帧文件保存为
.rdc格式
第三章:安装与配置
3.1 安装 MCP Server
# 1. 进入项目目录
cd renderdoc-mcp
# 2. 安装(开发模式,方便更新)
pip install -e .
# 验证安装成功
renderdoc-mcp --help
# 或
python -m src.server --help
如果 pip install -e . 报错 Unable to determine which files to ship inside the wheel,确保 pyproject.toml 包含:
[tool.hatch.build.targets.wheel]
packages = ["src"]
3.2 安装 RenderDoc 扩展
扩展是一个 Python 文件,需要放到 RenderDoc 的扩展目录中。
Windows 路径:
C:\Users\\AppData\Roaming\qrenderdoc\extensions\renderdoc_mcp\__init__.py
Linux 路径:
~/.local/share/qrenderdoc/extensions/renderdoc_mcp/__init__.py
操作步骤:
-
创建扩展目录:
# Windows mkdir "$env:APPDATA\qrenderdoc\extensions\renderdoc_mcp"
Linux
mkdir -p ~/.local/share/qrenderdoc/extensions/renderdoc_mcp
2. 将扩展文件复制到该目录(如果项目中已有,直接复制)
3. 重启 RenderDoc
4. 验证:在 RenderDoc 中,菜单 `Tools > RenderDoc MCP > Status`,应显示 "MCP bridge is RUNNING"
### 3.3 配置 MCP 客户端
根据你使用的 MCP 客户端进行配置。
#### WorkBuddy 配置
编辑 `~/.workbuddy/mcp.json`:
```json
{
"mcpServers": {
"renderdoc": {
"command": "renderdoc-mcp",
"env": {}
}
}
}
或者使用 Python 模块方式:
{
"mcpServers": {
"renderdoc": {
"command": "python",
"args": ["-m", "src.server"],
"cwd": "C:\\Users\\admin\\WorkBuddy\\Claw\\renderdoc-mcp",
"env": {}
}
}
}
Claude Desktop 配置
编辑 claude_desktop_config.json:
{
"mcpServers": {
"renderdoc": {
"command": "renderdoc-mcp"
}
}
}
3.4 完整启动流程
每次使用前需要按照以下顺序启动:
方式一(手动启动):
步骤 1:打开 RenderDoc (qrenderdoc.exe)
↓
步骤 2:加载截帧文件 (File > Open Capture)
↓
步骤 3:确认扩展运行 (Tools > RenderDoc MCP > Status → "RUNNING")
↓
步骤 4:启动/重启 MCP 客户端 (WorkBuddy / Claude Desktop)
↓
步骤 5:在 AI 对话中使用 RenderDoc 工具
方式二(自动启动 🆕):
步骤 1:启动 MCP 客户端 (WorkBuddy / Claude Desktop)
↓
步骤 2:在 AI 对话中输入 "打开截帧 C:\path\to\capture.rdc"
↓
步骤 3:AI 调用 launch_renderdoc() → 自动启动 RenderDoc + 加载截帧 + 等待桥接就绪
↓
步骤 4:直接开始分析!
💡 提示:
launch_renderdoc工具会自动查找 qrenderdoc 可执行文件,启动后等待 MCP 桥接就绪(最多30秒)。如果 RenderDoc 已经在运行,会自动切换为open_capture以提高速度。
⚠️ 注意:使用方式一时,RenderDoc 必须先打开并加载截帧,然后才能启动 MCP Server。否则工具调用会超时。
第四章:验证安装
4.1 快速健康检查
在 AI 对话中输入:
帮我检查 RenderDoc MCP 是否连接正常
AI 会调用 ping() 工具,正常响应应返回:
{"status": "ok", "server": "renderdoc_mcp", "ipc_dir": "C:\\Users\\...\\renderdoc_mcp_ipc"}
4.2 查看截帧状态
查看当前截帧的基本信息
AI 会调用 get_capture_status(),返回:
{
"loaded": true,
"api": "Vulkan",
"renderer": "AMD Radeon RX 6800",
"frameNumber": 8228,
"draws": 125,
"dispatches": 0,
"calls": 1547
}
4.3 如果不工作
| 症状 | 可能原因 | 解决方法 |
|---|---|---|
ping 超时 |
RenderDoc 未打开 | 先打开 RenderDoc |
ping 超时 |
扩展未加载 | 检查扩展目录路径是否正确 |
ping 超时 |
截帧未加载 | 先在 RenderDoc 中打开 .rdc 文件 |
| “Unknown method” | 扩展版本旧 | 更新扩展 __init__.py |
| 工具数量不对 | Server 或扩展不匹配 | 同时更新 server.py 和 init.py |
第五章:37个工具详解
📡 类别一:连接管理 (2个)
ping
检查 RenderDoc 桥接是否在线。
用法:ping
参数:无
返回:{status: "ok", server: "renderdoc_mcp", ipc_dir: "..."}
使用场景:每次开始工作前先 ping 一下,确认连接正常。
get_capture_status
检查截帧加载状态和图形 API 信息。
用法:get_capture_status
参数:无
返回:{loaded, api, renderer, frameNumber, draws, dispatches, calls}
返回字段说明:
| 字段 | 说明 |
|---|---|
loaded |
是否已加载截帧 |
api |
图形 API (D3D11/D3D12/Vulkan/OpenGL) |
renderer |
GPU 名称 |
frameNumber |
帧号 |
draws |
Draw Call 数量 |
dispatches |
Compute Dispatch 数量 |
calls |
总 API 调用数 |
📂 类别二:截帧管理 (3个)
list_captures
列出指定目录下的所有 .rdc 截帧文件。
用法:list_captures(directory)
参数:directory - 要搜索的目录路径
返回:[{name, path, size}, ...]
示例:
列出 C:\Captures 目录下的所有截帧文件
→ list_captures("C:\\Captures")
open_capture
在 RenderDoc 中打开一个截帧文件。
用法:open_capture(capture_path)
参数:capture_path - .rdc 文件的绝对路径
返回:{opened: "path"}
示例:
打开截帧文件 C:\Captures\game_frame.rdc
→ open_capture("C:\\Captures\\game_frame.rdc")
launch_renderdoc 🆕
启动 RenderDoc 应用程序并打开一个 .rdc 截帧文件。无需提前打开 RenderDoc。
用法:launch_renderdoc(capture_path, renderdoc_path)
参数:
capture_path: str .rdc 文件的绝对路径(必填)
renderdoc_path: str qrenderdoc 可执行文件路径(可选,自动检测)
返回:{launched, exe, capture, pid, bridgeReady, waitTime, fileSizeMB}
自动查找 qrenderdoc 的搜索顺序:
- 用户指定路径 (
renderdoc_path参数) RENDERDOC_PATH/RENDERDOC_MODULE_PATH环境变量- 系统
PATH - 常见安装路径(Windows:
C:\Program Files\RenderDoc\,Linux:/usr/bin/,macOS:/Applications/)
智能行为:
- 如果 RenderDoc 已在运行且 MCP 桥接可用 → 自动切换为
open_capture(更快) - 🆕 根据文件大小动态等待:200MB → 90s
- 超时后不报错——返回
bridgeReady=false+ 友好提示,用ping()检查后续状态 - 返回 PID 和等待时间信息
- 兼容新旧版本 RenderDoc 的
LoadCaptureAPI(自动适配 4/5 参数签名)
⚠️ 注意:加载大截帧(>200MB)可能需要较长时间。如果 MCP 请求超时,RenderDoc 仍会在后台继续加载,等待完成后再用
ping检查桥接状态即可。
示例:
启动 RenderDoc 并加载截帧
→ launch_renderdoc("C:\\Captures\\game_frame.rdc")
→ 返回:{launched: true, exe: "C:\\Program Files\\RenderDoc\\qrenderdoc.exe",
capture: "C:\\Captures\\game_frame.rdc", pid: 12345, bridgeReady: true, waitTime: "5.0s"}
与 open_capture 的区别:
open_capture |
launch_renderdoc |
|
|---|---|---|
| 前提条件 | RenderDoc 必须已打开 | 无前提,自动启动 |
| 速度 | 即时 | 需等待启动(~5-30s) |
| 适用场景 | 切换截帧 | 从零开始打开截帧 |
🎨 类别三:DrawCall 分析 (3个)
get_draw_calls
获取帧内所有绘制调用,支持多种过滤条件。
用法:get_draw_calls(include_children, marker_filter, only_actions, event_id_min, event_id_max)
参数:
include_children: bool = True 是否包含子操作
marker_filter: str = "" 按 Marker 名称过滤
only_actions: bool = False 仅返回实际 Draw/Dispatch
event_id_min: int = 0 最小事件 ID (0=不限)
event_id_max: int = 0 最大事件 ID (0=不限)
返回:{count, actions: [{eventId, name, flags, numIndices, numInstances, depth}, ...]}
返回字段说明:
| 字段 | 说明 |
|---|---|
eventId |
事件 ID(全局唯一,用于其他工具的参数) |
name |
名称(Marker 名或 “Action N”) |
flags |
操作标志位(Draw=64, Dispatch=128 等) |
numIndices |
索引/顶点数(三角形数 = numIndices / 3) |
numInstances |
实例数(GPU Instancing) |
depth |
层级深度(嵌套在 Marker 内的深度) |
示例:
获取所有绘制调用
→ get_draw_calls()
只看事件 60-100 之间的操作
→ get_draw_calls(event_id_min=60, event_id_max=100)
搜索名称包含 "Eye" 的操作
→ get_draw_calls(marker_filter="Eye")
get_frame_summary
获取帧的统计摘要。
用法:get_frame_summary
参数:无
返回:同 get_capture_status
get_draw_call_details
获取单个 DrawCall 的详细信息。
用法:get_draw_call_details(event_id)
参数:event_id - 事件 ID
返回:{eventId, vertexShader, fragmentShader, renderTargets, depthTarget, viewport}
🔧 类别四:管线状态 (1个)
get_pipeline_state
获取指定事件的完整渲染管线状态。
用法:get_pipeline_state(event_id)
参数:event_id - 事件 ID
返回:{shaders: {vertex, fragment, ...}, renderTargets, depthTarget}
每个 shader 条目包含:
| 字段 | 说明 |
|---|---|
shaderId |
着色器资源 ID |
entryPoint |
入口函数名 |
textureCount |
绑定纹理数 |
cbufferCount |
常量缓冲区数 |
samplerCount |
采样器数 |
常用场景:确定一个 DrawCall 使用了哪些着色器,绑定了多少纹理。
💎 类别五:着色器分析 (4个)
get_shader_info
获取着色器的详细信息 + 反汇编 + 绑定纹理。这是最常用的着色器分析工具。
用法:get_shader_info(event_id, stage)
参数:
event_id: int 事件 ID
stage: str "vertex" | "fragment"/"pixel" | "geometry" | "compute" | "hull"/"tess_ctrl" | "domain"/"tess_eval"
返回:{shaderId, pipelineId, stage, entryPoint, disassemblyTargets, disassembly,
inputs, outputs, boundTextures, constantBuffers, samplers}
返回字段详解:
| 字段 | 说明 |
|---|---|
disassemblyTargets |
可用的反汇编目标列表(如 [“SPIR-V (RenderDoc)”, “AMDIL”, “RDNA2 gfx1030”, …]) |
disassembly |
各目标的反汇编代码(字典) |
sourceFiles |
嵌入的源码文件(如有) |
inputs |
着色器输入签名 |
outputs |
着色器输出签名 |
boundTextures |
绑定纹理列表(含 slot、resourceId、尺寸、格式、推断角色) |
constantBuffers |
常量缓冲区(含变量名和运行时值) |
samplers |
采样器状态 |
reverse_shader
一站式着色器逆向 —— 与 get_shader_info 功能相同,但语义更明确。
用法:reverse_shader(event_id, stage)
参数:同 get_shader_info
返回:同 get_shader_info
何时使用:当你想完整理解一个着色器在做什么的时候。
get_bound_textures
获取着色器某个阶段绑定的所有纹理,含 自动角色推断。
用法:get_bound_textures(event_id, stage)
参数:
event_id: int 事件 ID
stage: str 着色器阶段
返回:[{slot, name, bind, resourceId, texName, width, height, format, role}, ...]
角色推断规则:
| 关键词匹配 | 推断角色 | 说明 |
|---|---|---|
albedo, diffuse, basecolor, _col, maintex |
albedo |
基础颜色贴图 |
normal, nrm, bump, _n_ |
normal |
法线贴图 |
metallic, metalness, _met |
metallic |
金属度贴图 |
rough, roughness, _rgh, smoothness |
roughness |
粗糙度贴图 |
ao, occlusion, _occ |
ao |
环境光遮蔽 |
emissive, emission, glow |
emissive |
自发光贴图 |
env, cubemap, reflection, ibl |
environment |
环境反射 |
shadow, shadowmap |
shadow |
阴影贴图 |
| BC5/RG 格式 | normal |
格式启发推断 |
| BC6H/HDR 格式 | environment |
格式启发推断 |
find_draws_by_texture
搜索使用了指定纹理名称的所有 DrawCall。
用法:find_draws_by_texture(texture_name)
参数:texture_name - 部分匹配的纹理名称(如 "eye", "skin")
返回:{textureIds, draws: [{eventId, name}], note}
find_draws_by_shader
按着色器名称搜索 DrawCall。
用法:find_draws_by_shader(shader_name, stage)
参数:
shader_name: str 部分匹配的着色器名称
stage: str = "" 可选阶段过滤
返回:搜索结果
⚠️ 此功能在扩展端尚未完全实现。
find_draws_by_resource
按资源 ID 搜索 DrawCall。
用法:find_draws_by_resource(resource_id)
参数:resource_id - 资源 ID
返回:搜索结果
⚠️ 此功能在扩展端尚未完全实现。
📦 类别六:资源检查 (4个)
get_textures
列出截帧中所有存活的纹理。
用法:get_textures
参数:无
返回:[{id, name, w, h, fmt, mips, array, size}, ...]
示例输出:
[
{"id": 102757, "name": "RT_Color", "w": 1598, "h": 898, "fmt": "R8G8B8A8_UNORM", "mips": 1, "size": 5738408},
{"id": 110432, "name": "eye_iris_d", "w": 512, "h": 512, "fmt": "BC3_UNORM", "mips": 10, "size": 349524}
]
get_buffers
列出所有缓冲区。
用法:get_buffers
参数:无
返回:[{id, name, length}, ...]
get_resources
列出所有资源(纹理、缓冲区、着色器、管线对象等)。
用法:get_resources
参数:无
返回:[{id, name, type}, ...]
get_texture_info
获取单个纹理的详细元数据。
用法:get_texture_info(resource_id)
参数:resource_id - 纹理资源 ID
返回:{id, name, w, h, d, fmt, mips, array, size}
🖼️ 类别七:纹理操作 (5个)
get_texture_data
获取纹理的像素数据(Base64 编码)。
用法:get_texture_data(resource_id, mip, slice)
参数:
resource_id: int 纹理 ID
mip: int = 0 Mip 级别
slice: int = 0 数组切片
返回:{resourceId, length, base64: "...(前10000字符)"}
pick_pixel
读取纹理上指定坐标的像素值。
用法:pick_pixel(resource_id, x, y)
参数:
resource_id: int 纹理 ID
x: int X 坐标
y: int Y 坐标
返回:{x, y, r, g, b, a}
使用场景:检查渲染目标上某个像素的颜色值,验证渲染结果。
get_texture_minmax
获取纹理中的最小/最大像素值。
用法:get_texture_minmax(resource_id)
参数:resource_id - 纹理 ID
返回:{min: {r, g, b, a}, max: {r, g, b, a}}
使用场景:检查 HDR 纹理的值域范围,判断是否有异常值。
save_texture
将纹理导出到磁盘。自动检测 CubeMap(arraysize=6)并适配导出。
用法:save_texture(resource_id, output_path, mip, slice)
参数:
resource_id: int 纹理 ID
output_path: str 输出文件路径
mip: int = 0 Mip 级别
slice: int = -1 CubeMap 面索引:-1=全部面(默认), 0-5=指定面
返回:
2D 纹理:{saved: "path", type: "2D"}
CubeMap PNG/JPG:{type: "cubemap", faces: 6, savedFaces: [...]}
CubeMap DDS:{saved: "path", type: "cubemap", format: "DDS (all 6 faces)"}
支持格式:PNG, JPG, BMP, TGA, HDR, EXR, DDS(根据文件扩展名自动选择)
CubeMap 导出策略(v1.3.0 🆕):
| 格式 | 行为 | 文件 |
|---|---|---|
| DDS | 6 面合并为单文件 | cubemap.dds |
| PNG/JPG/等 | 自动拆为 6 个面文件 | cubemap_face0_posX.png ~ cubemap_face5_negZ.png |
| 指定 slice=N | 只导出第 N 面 | cubemap.png(单文件) |
面序:0=+X(右), 1=-X(左), 2=+Y(上), 3=-Y(下), 4=+Z(前), 5=-Z(后)
示例:
save_texture(102757, "C:/output/render_target.png") # 2D 纹理
save_texture(98134, "C:/output/env_cubemap.dds") # CubeMap → 1个DDS
save_texture(98134, "C:/output/env_cubemap.png") # CubeMap → 6张PNG
save_texture(98134, "C:/output/env_front.png", slice=4) # CubeMap → 仅+Z面
get_buffer_contents
读取缓冲区原始数据。
用法:get_buffer_contents(resource_id, offset, length)
参数:
resource_id: int 缓冲区 ID
offset: int = 0 起始偏移(字节)
length: int = 256 读取长度(字节)
返回:{resourceId, offset, length, hex: "...", base64: "..."}
🔍 类别八:像素历史 (1个)
pixel_history
追踪一个像素在整帧内的完整修改历史。
用法:pixel_history(resource_id, x, y)
参数:
resource_id: int 渲染目标纹理 ID
x: int 像素 X 坐标
y: int 像素 Y 坐标
返回:[{eventId, pre: {r,g,b,a}, post: {r,g,b,a}}, ...]
使用场景:调查某个像素为什么显示了错误的颜色。通过查看每次写入前后的值,可以定位到是哪个 DrawCall 导致了问题。
示例:
查看渲染目标 102757 上坐标 (400, 300) 的像素历史
→ pixel_history(102757, 400, 300)
→ 返回:[
{eventId: 23, post: {r: 0.0, g: 0.0, b: 0.0, a: 0.0}}, // Clear
{eventId: 73, post: {r: 0.8, g: 0.2, b: 0.1, a: 1.0}}, // 眼球渲染
{eventId: 94, post: {r: 0.9, g: 0.7, b: 0.3, a: 1.0}}, // 特效叠加
]
🐛 类别九:着色器调试 (2个)
debug_pixel
逐步跟踪像素着色器的执行过程。
用法:debug_pixel(x, y)
参数:
x: int 像素 X 坐标
y: int 像素 Y 坐标
返回:{x, y, steps, trace: [{step, vars: [{name, val}]}, ...]}
⚠️ 需要先通过
get_pipeline_state或get_shader_info设置当前事件。
使用场景:当着色器输出不正确时,逐步查看每个变量在执行过程中的值。
debug_vertex
逐步跟踪顶点着色器的执行过程。
用法:debug_vertex(vertex_id, instance_id)
参数:
vertex_id: int 顶点 ID
instance_id: int = 0 实例 ID
返回:{vertexId, steps, trace: [{step, vars}]}
⚡ 类别十:性能分析 (3个)
enumerate_counters
列出 GPU 支持的所有性能计数器。
用法:enumerate_counters
参数:无
返回:[{id, name, desc, unit}, ...]
fetch_counters
获取指定性能计数器的值。
用法:fetch_counters(counter_ids)
参数:counter_ids - 逗号分隔的计数器 ID 列表 (如 "1,2,3")
返回:[{eventId, counter, value}, ...]
get_action_timings
获取 DrawCall 的 GPU 耗时。
用法:get_action_timings(event_ids, marker_filter)
参数:
event_ids: str = "" 逗号分隔的事件 ID (空=全部)
marker_filter: str = "" Marker 名称过滤
返回:计时数据
📐 类别十一:网格和调试 (3个)
get_post_vs_data
获取顶点着色器后的网格输出信息。
用法:get_post_vs_data
参数:无
返回:{numIndices, topology, indexStride, vertexStride}
get_debug_messages
获取图形驱动的验证/调试消息。
用法:get_debug_messages
参数:无
返回:[{eventId, severity, msg}, ...]
debug_vulkan_bindings 🆕
诊断工具:dump Vulkan descriptor set 绑定的原始数据结构,用于排查纹理绑定解析问题。
用法:debug_vulkan_bindings(event_id, stage)
参数:
event_id: int 事件 ID
stage: str 着色器阶段(默认 "fragment")
返回:{eventId, api, readOnlyResources, descriptorAccess, shaderReflection, ...}
超时:60 秒
用途:当 get_bound_textures 返回 resourceId=0 时,使用此工具诊断 Vulkan descriptor 的实际数据路径。
返回字段说明:
readOnlyResources—UsedDescriptor对象列表(含.descriptor.resource实际纹理 ID)descriptorAccess—DescriptorAccess对象列表(含 descriptor store 和索引信息)shaderReflection— Shader 反射中的只读资源绑定信息
📤 类别十二:导出 (2个)
export_drawcall
一键导出 DrawCall 的全部数据。
用法:export_drawcall(event_id, output_dir)
参数:
event_id: int 事件 ID
output_dir: str 输出目录
返回:{eventId, outputDir, files: [...]}
超时:60 秒
导出内容:
- 所有格式的着色器反汇编 (
.txt) - 嵌入源码 (如有)
- 所有绑定纹理 (
.png) - 常量缓冲区值
- 管线状态摘要 (
summary.json)
export_to_unity 🆕
一键将 DrawCall 导出为 Unity 可用资源(模型 + 材质映射)。
v1.5.0 改进:修复了多个模型导出质量问题——DX11 左手坐标系自动转换为右手坐标系、索引重映射精确提取、压缩编码法线自动检测。
纹理不在此工具导出——使用
save_texture或export_drawcall单独导出纹理文件。 本工具返回的textures列表包含每张纹理的resourceId,方便后续按需导出。
用法:export_to_unity(event_id, output_dir, mesh_name)
参数:
event_id: int 事件 ID
output_dir: str 输出目录
mesh_name: str = "exported_mesh" 模型和材质名称
返回:{eventId, outputDir, meshFile, fbxFile, textures, materialFile, meshStats, files}
超时:60 秒
模型提取方式(v1.3.0 改进):
优先使用 VBuffer + IBuffer + VertexInputs 直接读取 GPU 缓冲区(参考 Model Extractor 插件), Vulkan/ANGLE 截帧兼容性远优于旧的 PostVS 方式。PostVS 作为回退方案保留。
支持的顶点格式:Float32、Float16、UNorm、SNorm、UInt、SInt。
导出内容:
| 文件 | 说明 |
|---|---|
{name}.obj |
3D 模型 — OBJ 格式(顶点/法线/UV/索引) |
{name}.fbx |
🆕 3D 模型 — FBX 7.4 ASCII 格式(Unity/Unreal/Blender 通用) |
{name}_material.json |
Unity 材质定义(Standard/URP/HDRP 属性映射) |
{name}_UnityImport.cs |
C# 编辑器脚本(一键导入) |
{name}_unity_export.json |
完整导出摘要(含纹理绑定信息) |
返回的纹理绑定信息(不导出文件):
"textures": [
{
"role": "albedo",
"slot": 0,
"resourceId": 268775,
"width": 512, "height": 512,
"hint": "Use save_texture(resource_id=268775, output_path=...) to export"
}
]
Unity 导入流程:
- 复制导出文件夹(含
.fbx)到 UnityAssets/目录 - 用
save_texture按 resourceId 导出所需纹理到同一目录 - 将
_UnityImport.cs放入Assets/Editor/ - 菜单 →
RenderDoc > Import {name} - 自动完成:导入模型 → 创建材质 → 赋贴图
🔍 类别十三:智能识别与分析 (2个)
identify_drawcalls 🆕
智能识别每个 DrawCall 的渲染内容(眼球、头发、铠甲、饰品等)。
核心原理:对每个 DrawCall 执行 SetFrameEvent → SaveTexture(RT),生成 RT 累积截图,直接"看到"每个 DrawCall 画了什么——比按面数猜测准确率高出一个数量级。
用法:identify_drawcalls(event_id_min, event_id_max, output_dir, render_target)
参数:
event_id_min: int = 0 起始事件 ID
event_id_max: int = 999999 结束事件 ID
output_dir: str = "" 缩略图输出目录(每个 DrawCall 一张 RT 截图)
render_target: int = 0 渲染目标 ID(0=自动检测)
返回:{renderTarget, rtSize, actionCount, shaderGroups, actions: [...]}
超时:120 秒
每个 DrawCall 返回的信息:
| 字段 | 说明 |
|---|---|
eventId |
事件 ID |
triangles |
三角面数 |
vertexShader / fragmentShader |
Shader ID(同 shader = 同材质类型) |
textureCount |
绑定纹理数 |
textures |
前 5 个纹理的 resourceId + 尺寸 |
screenBBox |
屏幕空间包围盒(minX/Y, maxX/Y, depth) |
screenCoverage |
屏幕覆盖率百分比 |
thumbnail |
RT 累积截图路径(需指定 output_dir) |
Shader 分组:自动按 VS/FS shader ID 分组,返回 shaderGroups:
{
"110742/110743": [66], // 皮肤 shader → EID 66
"110755/110756": [73], // 眼球 shader → EID 73
"110759/110760": [87, 126], // 头发 shader → EID 87, 126
"106208/106209": [94,97,...], // 饰品 shader → 8个实例
}
识别流程:
- 运行
identify_drawcalls并指定output_dir保存缩略图 - 对比相邻截图(eid_NNNN.png),差异部分就是该 DrawCall 画的内容
- 结合
shaderGroups分组——同 shader 的 DrawCall 是同类型部件
analyze_lighting 🆕
分析 DrawCall 的灯光设置——从 shader 代码和 constant buffer 中提取所有灯光相关信息。
用法:analyze_lighting(event_id)
参数:
event_id: int 事件 ID
返回:{eventId, cbuffers, lightingModel, shadowMaps, environmentMaps}
超时:60 秒
分析内容:
| 维度 | 说明 |
|---|---|
| 光照模型检测 | 从 shader 反汇编中推断 PBR/Blinn-Phong/Lambert 等模型 |
| Shader 特性 | 阴影映射、环境反射、次表面散射、多光源循环等 |
| CBuffer 结构 | 所有 uniform 变量的名称、类型、数组大小 |
| 变量语义分类 | 自动将变量分为 light / shadow / ambient 类别 |
| 阴影贴图 | 识别绑定的 Depth 格式纹理(shadow map) |
| 环境贴图 | 识别绑定的 CubeMap(IBL / 反射探针) |
光照模型检测结果示例:
{
"model": "PBR (inferred)",
"features": [
"shadow_mapping",
"environment_reflection",
"multi_light_loop"
]
}
CBuffer 变量自动分类(对 ANGLE 匿名变量的启发式规则):
| 数组模式 | 推断类别 | 说明 |
|---|---|---|
float4[4] |
ambient_or_matrix |
SH 系数或变换矩阵 |
float4[6] |
light_array |
多光源数据(位置/颜色/方向/衰减) |
float4[8] |
shadow_matrix |
阴影级联矩阵 |
float4[2] |
shadow_param |
阴影图集 UV 参数 |
| 单值(单位向量) | light_direction |
主光方向 |
| 单值(0~2 范围 RGB) | color_or_light |
灯光颜色 |
注意:Vulkan/ANGLE 截帧中 cbuffer 变量名为匿名(
_childN),值需要通过 RenderDoc GUI 查看。 D3D11 截帧通常有完整的变量名和值。
第六章:实战工作流
6.1 工作流一:分析一个 DrawCall
目标:理解游戏中某个物体是怎么渲染的
Step 1: "列出所有 draw call"
→ get_draw_calls(only_actions=True)
→ 找到你感兴趣的 eventId (比如 73)
Step 2: "查看事件 73 的管线状态"
→ get_pipeline_state(73)
→ 确认使用了哪些 shader
Step 3: "逆向事件 73 的 fragment shader"
→ get_shader_info(73, "fragment")
→ 获取:反汇编代码 + 绑定纹理 + 常量缓冲区值
Step 4: "保存事件 73 的所有绑定纹理"
→ 对每个 boundTexture 调用 save_texture()
6.2 工作流二:定位渲染问题
目标:排查为什么某个像素显示了错误颜色
Step 1: "获取渲染目标信息"
→ get_textures() → 找到 RT 的 resourceId
Step 2: "查看像素 (400,300) 的修改历史"
→ pixel_history(rt_id, 400, 300)
→ 找到哪个 eventId 写入了错误值
Step 3: "分析那个 DrawCall 的 shader"
→ get_shader_info(event_id, "fragment")
Step 4: "调试那个像素"
→ debug_pixel(400, 300)
→ 逐步查看变量值
6.3 工作流三:导出到 Unity
目标:将截帧中的角色眼球导出到 Unity
Step 1: "列出 60-100 之间的 draw call"
→ get_draw_calls(event_id_min=60, event_id_max=100)
→ 找到眼球的 eventId (比如 73)
Step 2: "导出事件 73 到 Unity,命名为 eye_ball"
→ export_to_unity(73, "C:/output/eye", "eye_ball")
→ 生成 .obj + .png × N + material.json + UnityImport.cs
Step 3: 复制到 Unity 项目,运行导入脚本
6.4 工作流四:着色器逆向还原
目标:把截帧中的 shader 完整还原为可用的 .shader 文件
Step 1: "逆向事件 73 的 fragment shader"
→ reverse_shader(73, "fragment")
→ 获取 SPIR-V / HLSL 反汇编
Step 2: "逆向事件 73 的 vertex shader"
→ reverse_shader(73, "vertex")
→ 获取顶点着色器反汇编
Step 3: "获取事件 73 的所有绑定纹理和 cbuffer 值"
→ get_bound_textures(73, "fragment")
→ 获取纹理槽位映射
Step 4: "一键导出事件 73 的全部数据"
→ export_drawcall(73, "C:/output/shader_data")
→ 获取所有反汇编文件 + 纹理 + 参数
Step 5: 基于导出数据,让 AI 还原为完整的 Unity .shader 文件
6.5 工作流五:性能分析
目标:找到帧内最耗时的 DrawCall
Step 1: "列出所有可用的性能计数器"
→ enumerate_counters()
→ 找到 GPU Time 计数器的 ID
Step 2: "获取所有 DrawCall 的 GPU 耗时"
→ fetch_counters("1") (假设 1 是 GPU Time)
→ 按耗时排序,找到瓶颈
Step 3: "分析耗时最高的 DrawCall"
→ get_shader_info(event_id, "fragment")
→ 查看 shader 复杂度
第七章:故障排除
7.1 连接问题
问题:ping 超时
✅ 检查清单:
1. RenderDoc (qrenderdoc.exe) 是否正在运行?
2. 截帧文件是否已加载?(标题栏显示文件名)
3. 扩展是否加载?
→ Tools > RenderDoc MCP > Status
→ 应显示 "MCP bridge is RUNNING"
4. IPC 目录是否可访问?
→ 检查 %TEMP%\renderdoc_mcp_ipc\ 是否存在
问题:扩展菜单不存在
✅ 检查清单:
1. 扩展文件路径是否正确?
Windows: %APPDATA%\qrenderdoc\extensions\renderdoc_mcp\__init__.py
Linux: ~/.local/share/qrenderdoc/extensions/renderdoc_mcp/__init__.py
2. 文件名必须是 __init__.py,目录名必须是 renderdoc_mcp
3. 重启 RenderDoc
4. 查看 RenderDoc 的输出面板是否有错误信息
7.2 API 兼容性问题
问题:某些工具返回错误
不同版本的 RenderDoc 的 Python API 有差异。已知的兼容性处理:
| 问题 | 说明 | 解决方案 |
|---|---|---|
TextureDescription 无 name |
旧版本不直接存名字 | 通过 GetResources() 查找 |
ResourceFormat str() 返回 Swig 对象 |
SWIG 包装问题 | 使用 .name 属性 |
SigParameter 无 compType |
Vulkan/ANGLE 截帧 | getattr 安全访问 |
无 GetShaderPipelineObject |
旧版 API | Vulkan fallback |
无 GetConstantBuffers/GetSamplers |
版本差异 | try/except 保护 |
UsedDescriptor 无 .resources |
绑定结构变化 | 多种结构兼容 |
LoadCapture 需要 5 参数 |
新版 API 签名变化 | try/except 自动适配 4/5 参数 |
Vulkan UsedDescriptor.resource 返回指针 |
SWIG 绑定差异 | 🆕 改用 .descriptor.resource 路径(v1.2.0 修复) |
7.3 性能问题
问题:工具调用很慢
✅ 优化建议:
1. 避免频繁调用 get_textures() / get_resources() —— 结果不会变,缓存即可
2. export_drawcall 可能需要 30-60 秒 —— 它要遍历所有反汇编目标
3. pixel_history 在大尺寸 RT 上可能很慢 —— 这是 RenderDoc 本身的限制
4. 如果 IPC 超时,增加 timeout 参数
第八章:高级技巧
8.1 使用多个截帧
通过 list_captures + open_capture 可以切换不同截帧进行对比分析。
8.2 批量导出纹理
# 让 AI 执行:
"获取所有纹理列表,然后把所有大于 256x256 的纹理都导出为 PNG"
→ get_textures()
→ 对每个符合条件的纹理调用 save_texture()
8.3 Shader 对比分析
"比较事件 73 和事件 80 的 fragment shader 有什么区别"
→ get_shader_info(73, "fragment")
→ get_shader_info(80, "fragment")
→ AI 对比两个 shader 的差异
8.4 自定义 Unity 导入
export_to_unity 生成的 _material.json 包含三套属性映射:
property:Unity Standard ShaderurpProperty:URP (Universal Render Pipeline)hdrpProperty:HDRP (High Definition Render Pipeline)
你可以手动编辑 JSON 来适配自定义 Shader。
8.5 IPC 调试
如果需要调试 IPC 通信,可以查看中间文件:
# 查看 IPC 目录
dir $env:TEMP\renderdoc_mcp_ipc\
# 查看最近的请求(如果有残留)
cat $env:TEMP\renderdoc_mcp_ipc\request.json
# 查看 RenderDoc 输出面板中的 [RD-MCP] 日志
附录A:API兼容性说明
本项目对以下 RenderDoc 版本进行了兼容性处理:
| RenderDoc 版本 | 图形 API | 测试状态 |
|---|---|---|
| v1.26+ | Vulkan (ANGLE/SPIR-V) | ✅ 已测试通过 |
| v1.26+ | D3D11 (DXBC/ps_5_0) | ✅ 已测试通过 |
| v1.20+ | D3D12 | ⚠️ 兼容代码已就位(未实际测试) |
| v1.20+ | OpenGL | ⚠️ 兼容代码已就位(未实际测试) |
D3D11 测试结果:
- Pipeline state获取:✅ null pipeline ID fallback 生效
- DXBC反汇编:✅ ps_5_0 正确反汇编
- 输入/输出语义:✅ SV_Position/TEXCOORD/SV_Target/SV_IsFrontFace 正确解析
- CBuffer变量:✅ 支持多CBuffer(含65KB动态索引cbuffer)
- 纹理绑定:✅ SRV检测
- Hull/Domain着色器:✅ 支持Tessellation阶段
Vulkan/ANGLE 和 D3D11 截帧已经过完整的兼容性测试和修复。
Vulkan 纹理导出修复(v1.2.0):
- 问题:Vulkan 截帧中
get_bound_textures/export_drawcall无法导出纹理(resourceId 全部返回 0) - 根因:
UsedDescriptor的 SWIG 绑定中,int(binding.resource)返回内存指针而非 ResourceId - 修复:改用
binding.descriptor.resource路径解析(UsedDescriptor → Descriptor → resource) - 验证:王者荣耀 Vulkan/ANGLE 截帧 → 9 张纹理全部成功导出为 PNG(含 Albedo/Normal/AO/Depth)
模型导出重写 + FBX 支持(v1.3.0):
- 改进:参考 Model Extractor 插件,改用
GetVBuffers() + GetIBuffer() + GetVertexInputs()直接读取 GPU 缓冲区 - 优势:支持 Float16/Float32/UNorm/SNorm/UInt/SInt 顶点格式,Vulkan 兼容性远优于旧 PostVS 方式
- 新增:FBX 7.4 ASCII 导出(
_write_fbx_ascii),兼容 Unity/Unreal/Blender/Maya - 精简:
export_to_unity不再导出纹理 PNG(改用save_texture/export_drawcall单独导出),响应从超时 → 秒级完成 - 验证:关羽头部 EID=172(2590 顶点/4772 面)→ OBJ 157.9KB + FBX 198.9KB — 两种格式同时生成 ✅
模型导出质量修复(v1.5.0):
- 索引修复:正确应用
baseVertex(DrawIndexed 的 BaseVertexLocation)和indexOffset(索引缓冲区偏移);引入索引重映射机制,只导出 DrawCall 实际引用的唯一顶点,杜绝多余顶点 - 坐标系转换:DX11 左手坐标系 → 右手坐标系自动转换(位置 X 轴取负 + 三角面缠绕方向反转),解决模型镜像问题
- 法线处理:自动检测压缩编码的 tangent frame(如 NORMAL 语义存 packed uint32),超出 [-1.5, 1.5] 范围的法线自动丢弃,让 Unity/Blender 根据面重算
- UV 修复:
flip_uv_v默认关闭(DX11 → Unity 不需要翻转 V 坐标),避免 UV 上下颠倒 - 顶点属性读取:始终按原始 compCount 读取再截取到 wanted_comp,避免 4 分量属性读 3 分量时的跨步对齐错误;分量不足时自动补零
- 格式支持:新增 R10G10B10A2_UNorm/SNorm 打包格式解码
- 验证:D3D11 抓帧 EID=320(3346 唯一顶点)→ OBJ + FBX 导出,UV/模型/法线在 Unity 中完全正确 ✅
附录B:已知限制
- find_by_shader 和 find_by_resource 在扩展端尚未完全实现
- get_action_timings 在扩展端没有对应处理函数
- 着色器调试(debug_pixel/debug_vertex)返回的步骤数限制为 50 步
- 纹理数据(get_texture_data)的 Base64 输出截断为前 10000 字符
- 缓冲区数据(get_buffer_data)最大读取 4096 字节
- 模型导出优先使用 VBuffer+IBuffer 方式(v1.3.0),PostVS 作为回退;FBX 导出为 ASCII 7.4 格式
- CubeMap 纹理导出已适配(v1.3.0):PNG/JPG 自动导出 6 面文件,DDS 导出完整 CubeMap
- 模型导出已包含 DX→右手坐标系自动转换(v1.5.0);压缩编码法线(packed tangent frame)会自动丢弃,由导入工具重算
附录C:文件结构参考
renderdoc-mcp/
├── pyproject.toml # Python 项目配置
├── README.md # 英文文档
├── README_CN.md # 中文概览
├── MANUAL_CN.md # 本文件 - 完整手册
├── SETUP_GUIDE.md # 安装配置报告
└── src/
├── __init__.py
├── server.py # MCP Server (37 个工具)
├── rd_wrapper.py # RenderDoc API 封装 (本地直连模式)
└── ipc_client.py # 文件 IPC 客户端
RenderDoc 扩展:
%APPDATA%/qrenderdoc/extensions/renderdoc_mcp/
└── __init__.py # 扩展端处理函数 (31 个方法)
IPC 通信目录:
%TEMP%/renderdoc_mcp_ipc/
├── request.json # 请求文件 (临时)
├── ready # 就绪信号 (临时)
└── response.json # 响应文件 (临时)
手册版本: 1.5.0 | 最后更新: 2026-04-14
설치
This server does not publish a one-line install command.
Open the repository installation guide