diff --git a/CLAUDE.md b/CLAUDE.md index 27493f9..8258993 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,134 +1,134 @@ # RenderDoc MCP Server -RenderDoc UI拡張機能として動作するMCPサーバー。AIアシスタントがRenderDocのキャプチャデータにアクセスし、DirectX 11/12のグラフィックスデバッグを支援する。 +An MCP server that runs as a RenderDoc UI extension, enabling AI assistants to access RenderDoc capture data and assist with DirectX 11/12 graphics debugging. -## アーキテクチャ +## Architecture -**ハイブリッドプロセス分離方式**: +**Hybrid Process Separation Approach**: ``` Claude/AI Client (stdio) │ ▼ -MCP Server Process (標準Python + FastMCP 2.0) +MCP Server Process (Standard Python + FastMCP 2.0) │ File-based IPC (%TEMP%/renderdoc_mcp/) ▼ RenderDoc Process (Extension + File Polling) ``` -## プロジェクト構成 +## Project Structure ``` RenderDocMCP/ -├── mcp_server/ # MCPサーバー -│ ├── server.py # FastMCPエントリーポイント -│ ├── config.py # 設定 +├── mcp_server/ # MCP Server +│ ├── server.py # FastMCP entry point +│ ├── config.py # Configuration │ └── bridge/ -│ └── client.py # ファイルベースIPCクライアント +│ └── client.py # File-based IPC client │ -├── renderdoc_extension/ # RenderDoc拡張機能 +├── renderdoc_extension/ # RenderDoc Extension │ ├── __init__.py # register()/unregister() -│ ├── extension.json # マニフェスト -│ ├── socket_server.py # ファイルベースIPCサーバー -│ ├── request_handler.py # リクエスト処理 -│ └── renderdoc_facade.py # RenderDoc APIラッパー +│ ├── extension.json # Manifest +│ ├── socket_server.py # File-based IPC server +│ ├── request_handler.py # Request handler +│ └── renderdoc_facade.py # RenderDoc API wrapper │ └── scripts/ - └── install_extension.py # 拡張機能インストール + └── install_extension.py # Extension installer ``` -## MCPツール - -| ツール名 | 説明 | -|---------|------| -| `list_captures` | 指定ディレクトリ内の.rdcファイル一覧を取得 | -| `open_capture` | キャプチャファイルを開く(既存キャプチャは自動で閉じる) | -| `get_capture_status` | キャプチャ読込状態確認 | -| `get_draw_calls` | ドローコール一覧(階層構造、フィルタリング対応) | -| `get_frame_summary` | フレーム全体の統計情報(ドローコール数、マーカー一覧等) | -| `find_draws_by_shader` | シェーダー名でドローコールを逆引き検索 | -| `find_draws_by_texture` | テクスチャ名でドローコールを逆引き検索 | -| `find_draws_by_resource` | リソースIDでドローコールを逆引き検索 | -| `get_draw_call_details` | 特定ドローコールの詳細 | -| `get_action_timings` | アクションのGPU実行時間を取得 | -| `get_shader_info` | シェーダーソース/定数バッファ | -| `get_buffer_contents` | バッファデータ取得(オフセット/長さ指定可) | -| `get_texture_info` | テクスチャメタデータ | -| `get_texture_data` | テクスチャピクセルデータ取得(mip/slice/3Dスライス対応) | -| `get_pipeline_state` | パイプライン状態全体 | - -### get_draw_calls フィルタリングオプション +## MCP Tools + +| Tool Name | Description | +|-----------|-------------| +| `list_captures` | List .rdc files in specified directory | +| `open_capture` | Open capture file (closes existing capture automatically) | +| `get_capture_status` | Check capture load status | +| `get_draw_calls` | Get draw call list (hierarchical structure, filtering supported) | +| `get_frame_summary` | Get frame-wide statistics (draw call count, marker list, etc.) | +| `find_draws_by_shader` | Reverse search draw calls by shader name | +| `find_draws_by_texture` | Reverse search draw calls by texture name | +| `find_draws_by_resource` | Reverse search draw calls by resource ID | +| `get_draw_call_details` | Get specific draw call details | +| `get_action_timings` | Get GPU execution time for actions | +| `get_shader_info` | Get shader source/constant buffers | +| `get_buffer_contents` | Get buffer data (offset/length can be specified) | +| `get_texture_info` | Get texture metadata | +| `get_texture_data` | Get texture pixel data (mip/slice/3D slice supported) | +| `get_pipeline_state` | Get full pipeline state | + +### get_draw_calls Filtering Options ```python get_draw_calls( - include_children=True, # 子アクションを含める - marker_filter="Camera.Render", # このマーカー配下のみ取得 - exclude_markers=["GUI.Repaint", "UIR.DrawChain"], # 除外するマーカー - event_id_min=7372, # event_id範囲の開始 - event_id_max=7600, # event_id範囲の終了 - only_actions=True, # マーカーを除外(ドローコールのみ) - flags_filter=["Drawcall", "Dispatch"], # 特定フラグのみ + include_children=True, # Include child actions + marker_filter="Camera.Render", # Only get actions under this marker + exclude_markers=["GUI.Repaint", "UIR.DrawChain"], # Exclude markers + event_id_min=7372, # event_id range start + event_id_max=7600, # event_id range end + only_actions=True, # Exclude markers (draw calls only) + flags_filter=["Drawcall", "Dispatch"], # Specific flags only ) ``` -### キャプチャ管理ツール +### Capture Management Tools ```python -# ディレクトリ内のキャプチャファイルを列挙 +# List capture files in directory list_captures(directory="D:\\captures") # → {"count": 3, "captures": [{"filename": "game.rdc", "path": "...", "size_bytes": 12345, "modified_time": "..."}, ...]} -# キャプチャファイルを開く(既存キャプチャは自動で閉じられる) +# Open capture file (existing capture is automatically closed) open_capture(capture_path="D:\\captures\\game.rdc") # → {"success": true, "filename": "game.rdc", "api": "D3D11"} ``` -### 逆引き検索ツール +### Reverse Search Tools ```python -# シェーダー名で検索(部分一致) +# Search by shader name (partial match) find_draws_by_shader(shader_name="Toon", stage="pixel") -# テクスチャ名で検索(部分一致) +# Search by texture name (partial match) find_draws_by_texture(texture_name="CharacterSkin") -# リソースIDで検索(完全一致) +# Search by resource ID (exact match) find_draws_by_resource(resource_id="ResourceId::12345") ``` -### GPU タイミング取得 +### GPU Timing Acquisition ```python -# 全アクションのタイミングを取得 +# Get timing for all actions get_action_timings() # → {"available": true, "unit": "CounterUnit.Seconds", "timings": [...], "total_duration_ms": 12.5, "count": 150} -# 特定のイベントIDのみ取得 +# Get timing for specific event IDs get_action_timings(event_ids=[100, 200, 300]) -# マーカーでフィルタリング +# Filter by marker get_action_timings(marker_filter="Camera.Render", exclude_markers=["GUI.Repaint"]) ``` -**注意**: GPUタイミングカウンターはハードウェア/ドライバーによっては利用できない場合があります。 -`available: false` が返された場合、そのキャプチャではタイミング情報を取得できません。 +**Note**: GPU timing counters may not be available depending on hardware/driver. +If `available: false` is returned, timing information cannot be retrieved for that capture. -## 通信プロトコル +## Communication Protocol -ファイルベースIPC: -- IPCディレクトリ: `%TEMP%/renderdoc_mcp/` -- `request.json`: リクエスト(MCPサーバー → RenderDoc) -- `response.json`: レスポンス(RenderDoc → MCPサーバー) -- `lock`: 書き込み中ロックファイル -- ポーリング間隔: 100ms(RenderDoc側) +File-based IPC: +- IPC directory: `%TEMP%/renderdoc_mcp/` +- `request.json`: Request (MCP Server → RenderDoc) +- `response.json`: Response (RenderDoc → MCP Server) +- `lock`: Lock file during write +- Polling interval: 100ms (RenderDoc side) -## 開発ノート +## Development Notes -- RenderDoc内蔵Pythonにはsocket/QtNetworkモジュールがないため、ファイルベースIPCを採用 -- RenderDoc拡張機能はPython 3.6標準ライブラリのみ使用 -- ReplayControllerへのアクセスは`BlockInvoke`経由で行う +- File-based IPC is used because RenderDoc's embedded Python doesn't have socket/QtNetwork modules +- RenderDoc extension uses only Python 3.6 standard library +- ReplayController is accessed via `BlockInvoke` -## 参考リンク +## References - [FastMCP](https://github.com/jlowin/fastmcp) - [RenderDoc Python API](https://renderdoc.org/docs/python_api/index.html) diff --git a/README.en.md b/README.en.md new file mode 100644 index 0000000..4aee981 --- /dev/null +++ b/README.en.md @@ -0,0 +1,160 @@ +# RenderDoc MCP Server + +[日本語](README.md) | **[English]** + +An MCP server that runs as a RenderDoc UI extension, enabling AI assistants to access RenderDoc capture data and assist with graphics debugging. + +## Architecture + +``` +Claude/AI Client (stdio) + │ + ▼ +MCP Server Process (Python + FastMCP 2.0) + │ File-based IPC (%TEMP%/renderdoc_mcp/) + ▼ +RenderDoc Process (Extension) +``` + +Communication is done via file-based IPC since RenderDoc's embedded Python doesn't have the socket module. + +## Setup + +### 1. Install RenderDoc Extension + +```bash +python scripts/install_extension.py +``` + +The extension will be installed to `%APPDATA%\qrenderdoc\extensions\renderdoc_mcp_bridge`. + +### 2. Enable Extension in RenderDoc + +1. Launch RenderDoc +2. Tools > Manage Extensions +3. Enable "RenderDoc MCP Bridge" + +### 3. Install MCP Server + +```bash +uv tool install . +uv tool update-shell # Add to PATH +``` + +After restarting your shell, the `renderdoc-mcp` command will be available. + +> **Note**: Use `--editable` flag for development to apply source code changes immediately. +> For stable installation, use `uv tool install .`. + +### 4. Configure MCP Client + +#### Claude Desktop + +Add to `claude_desktop_config.json`: + +```json +{ + "mcpServers": { + "renderdoc": { + "command": "renderdoc-mcp" + } + } +} +``` + +#### Claude Code (Cursor) + +Add to `.mcp.json`: + +```json +{ + "mcpServers": { + "renderdoc": { + "command": "renderdoc-mcp" + } + } +} +``` + +## Usage + +1. Launch RenderDoc and open a capture file (.rdc) +2. Access RenderDoc data from MCP clients (Claude, etc.) + +## MCP Tools + +| Tool | Description | +|------|-------------| +| `get_capture_status` | Check capture load status | +| `get_draw_calls` | Get draw call list in hierarchical structure | +| `get_frame_summary` | Get frame statistics and top-level markers | +| `find_draws_by_shader` | Find draw calls using specific shader (partial match) | +| `find_draws_by_texture` | Find draw calls using specific texture (partial match) | +| `find_draws_by_resource` | Find draw calls using specific resource ID (exact match) | +| `get_draw_call_details` | Get detailed information about a specific draw call | +| `get_shader_info` | Get shader source code and constant buffer values | +| `get_buffer_contents` | Get buffer contents (Base64) | +| `get_texture_info` | Get texture metadata | +| `get_texture_data` | Get texture pixel data (Base64) | +| `get_pipeline_state` | Get pipeline state | +| `list_captures` | List all .rdc files in directory | +| `open_capture` | Open a capture file | + +## Examples + +### Get Draw Call List + +``` +get_draw_calls(include_children=true) +``` + +### Get Shader Information + +``` +get_shader_info(event_id=123, stage="pixel") +``` + +### Get Pipeline State + +``` +get_pipeline_state(event_id=123) +``` + +### Get Texture Data + +``` +# Get mip 0 of 2D texture +get_texture_data(resource_id="ResourceId::123") + +# Get specific mip level +get_texture_data(resource_id="ResourceId::123", mip=2) + +# Get specific cube map face (0=X+, 1=X-, 2=Y+, 3=Y-, 4=Z+, 5=Z-) +get_texture_data(resource_id="ResourceId::456", slice=3) + +# Get specific depth slice of 3D texture +get_texture_data(resource_id="ResourceId::789", depth_slice=5) +``` + +### Get Partial Buffer Data + +``` +# Get entire buffer +get_buffer_contents(resource_id="ResourceId::123") + +# Get 512 bytes from offset 256 +get_buffer_contents(resource_id="ResourceId::123", offset=256, length=512) +``` + +## Requirements + +- Python 3.10+ +- [uv](https://docs.astral.sh/uv/) +- RenderDoc 1.20+ + +> **Note**: Tested only on Windows + DirectX 11. +> May work on Linux/macOS + Vulkan/OpenGL but untested. + +## License + +MIT diff --git a/README.md b/README.md index d563823..ba1d6c6 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # RenderDoc MCP Server +**[日本語]** | [English](README.en.md) + RenderDoc UI拡張機能として動作するMCPサーバー。AIアシスタントがRenderDocのキャプチャデータにアクセスし、グラフィックスデバッグを支援する。 ## アーキテクチャ diff --git a/renderdoc-mcp-improvement-proposal.md b/renderdoc-mcp-improvement-proposal.md deleted file mode 100644 index 7054fe5..0000000 --- a/renderdoc-mcp-improvement-proposal.md +++ /dev/null @@ -1,260 +0,0 @@ -# RenderDoc MCP 改善提案 - -## 背景 - -UnityプロジェクトでRenderDocキャプチャを分析する際、以下の課題がある: - -1. **UIノイズ問題**: Unity Editorからキャプチャすると、`GUI.Repaint`や`UIR.DrawChain`などのEditor UI描画が大量に含まれ、実際のゲーム描画(`Camera.Render`配下)を探すのが困難 -2. **レスポンスサイズ問題**: `get_draw_calls(include_children=true)`の結果が70KB超になり、LLMのコンテキストを圧迫 -3. **探索の非効率性**: 特定のシェーダーやテクスチャを使用しているドローコールを見つけるのに、全ドローコールを1つずつ確認する必要がある - -## 改善提案 - -### 1. マーカーフィルタリング(優先度: 高) - -特定のマーカー配下のみ、または特定のマーカーを除外して取得する機能。 - -```python -get_draw_calls( - include_children=True, - marker_filter="Camera.Render", # このマーカー配下のみ取得 - exclude_markers=["GUI.Repaint", "UIR.DrawChain", "UGUI.Rendering"] -) -``` - -**ユースケース**: -- Unity Editorキャプチャからゲーム描画のみを抽出 -- 特定のレンダリングパス(Shadows, PostProcess等)のみを調査 - -**期待される効果**: -- レスポンスサイズを10-20%に削減 -- LLMが直接解析可能なサイズに収まる - ---- - -### 2. event_id範囲指定(優先度: 高) - -特定のevent_id範囲のみを取得する機能。 - -```python -get_draw_calls( - event_id_min=7372, - event_id_max=7600, - include_children=True -) -``` - -**ユースケース**: -- `Camera.Render`のevent_idが判明している場合、その周辺のみを取得 -- 問題のあるドローコール周辺を詳細に調査 - -**期待される効果**: -- 必要な部分だけを高速に取得 -- 段階的な探索が可能に - ---- - -### 3. シェーダー/テクスチャ/リソースによる逆引き検索(優先度: 中) - -特定のリソースを使用しているドローコールを検索する機能。 - -```python -# シェーダー名で検索(部分一致) -find_draws_by_shader(shader_name="Toon") - -# テクスチャ名で検索(部分一致) -find_draws_by_texture(texture_name="CharacterSkin") - -# リソースIDで検索(完全一致) -find_draws_by_resource(resource_id="ResourceId::12345") -``` - -**返り値例**: -```json -{ - "matches": [ - {"event_id": 7538, "name": "DrawIndexed", "match_reason": "pixel_shader contains 'Toon'"}, - {"event_id": 7620, "name": "DrawIndexed", "match_reason": "pixel_shader contains 'Toon'"} - ], - "total_matches": 2 -} -``` - -**ユースケース**: -- 「このシェーダーを使っているドローはどれ?」という最も一般的な質問に直接回答 -- 特定のテクスチャがどこで使われているか追跡 -- シェーダーバグの影響範囲を特定 - ---- - -### 4. フレームサマリー取得(優先度: 中) - -フレーム全体の概要を取得する機能。 - -```python -get_frame_summary() -``` - -**返り値例**: -```json -{ - "api": "D3D11", - "total_events": 7763, - "statistics": { - "draw_calls": 64, - "dispatches": 193, - "clears": 5, - "copies": 8 - }, - "top_level_markers": [ - {"name": "WaitForRenderJobs", "event_id": 118}, - {"name": "CustomRenderTextures.Update", "event_id": 6451}, - {"name": "Camera.Render", "event_id": 7372}, - {"name": "UIR.DrawChain", "event_id": 6484} - ], - "render_targets": [ - {"resource_id": "ResourceId::22573", "name": "MainRT", "resolution": "1920x1080"}, - {"resource_id": "ResourceId::22585", "name": "ShadowMap", "resolution": "2048x2048"} - ], - "unique_shaders": { - "vertex": 12, - "pixel": 15, - "compute": 8 - } -} -``` - -**ユースケース**: -- 探索の起点として全体像を把握 -- どのマーカー配下を詳しく見るか判断 -- パフォーマンス概要の把握 - ---- - -### 5. ドローコールのみ取得モード(優先度: 中) - -マーカー(PushMarker/PopMarker)を除外し、実際の描画コールのみを取得する機能。 - -```python -get_draw_calls( - only_actions=True, # マーカーを除外 - flags_filter=["Drawcall", "Dispatch"] # 特定のフラグを持つもののみ -) -``` - -**ユースケース**: -- ドローコールの総数と一覧だけ欲しい場合 -- Compute Shader(Dispatch)のみを調査したい場合 - ---- - -### 6. バッチパイプラインステート取得(優先度: 低) - -複数のevent_idのパイプラインステートを一度に取得する機能。 - -```python -get_multiple_pipeline_states(event_ids=[7538, 7558, 7450, 7458]) -``` - -**返り値例**: -```json -{ - "states": { - "7538": { /* pipeline state */ }, - "7558": { /* pipeline state */ }, - "7450": { /* pipeline state */ }, - "7458": { /* pipeline state */ } - } -} -``` - -**ユースケース**: -- 複数のドローコールを比較分析 -- 差分調査(正常なドローと異常なドローの比較) - ---- - -## 優先度まとめ - -| 優先度 | 機能 | 実装難易度 | 効果 | -|--------|------|-----------|------| -| **高** | マーカーフィルタリング | 中 | UIノイズ除去で劇的に改善 | -| **高** | event_id範囲指定 | 低 | 部分取得で高速化 | -| **中** | シェーダー/テクスチャ逆引き | 高 | 最も多いユースケースを直接サポート | -| **中** | フレームサマリー | 中 | 探索の起点として有用 | -| **中** | ドローコールのみ取得 | 低 | シンプルなフィルタリング | -| **低** | バッチ取得 | 低 | 効率化だが必須ではない | - -## Unity固有のフィルタリングプリセット(オプション) - -Unity専用のプリセットがあると便利: - -```python -get_draw_calls( - preset="unity_game_rendering" -) -``` - -**プリセット内容**: -- `marker_filter`: "Camera.Render" -- `exclude_markers`: ["GUI.Repaint", "UIR.DrawChain", "GUITexture.Draw", "UGUI.Rendering.RenderOverlays", "PlayerEndOfFrame", "EditorLoop"] - ---- - -## 実装の参考:現在のワークフローの問題点 - -### 現状のフロー - -``` -1. get_draw_calls(include_children=true) - → 76KB のJSONが返る(ファイルに保存される) - -2. ファイルを外部ツール(Python等)で解析 - → Camera.Render の event_id を特定(例: 7372) - -3. 手動でevent_id範囲を指定して詳細調査 - → get_pipeline_state(7538), get_shader_info(7538, "pixel"), ... -``` - -### 改善後の理想フロー - -``` -1. get_frame_summary() - → Camera.Render が event_id: 7372 にあることが分かる - -2. get_draw_calls(marker_filter="Camera.Render", exclude_markers=[...]) - → 必要なドローコールのみ取得(数KB) - -3. find_draws_by_shader(shader_name="MyShader") - → 該当するevent_idが直接返る - -4. get_pipeline_state(event_id) で詳細確認 -``` - ---- - -## 補足:スキップすべきUnityマーカー一覧 - -Unity Editorからのキャプチャで除外すべきマーカー: - -| マーカー名 | 説明 | -|-----------|------| -| `GUI.Repaint` | IMGUI描画 | -| `UIR.DrawChain` | UI Toolkit描画 | -| `GUITexture.Draw` | GUIテクスチャ描画 | -| `UGUI.Rendering.RenderOverlays` | uGUIオーバーレイ | -| `PlayerEndOfFrame` | フレーム終了処理 | -| `EditorLoop` | エディタループ処理 | - -逆に、重要なマーカー: - -| マーカー名 | 説明 | -|-----------|------| -| `Camera.Render` | メインカメラ描画の起点 | -| `Drawing` | 描画フェーズ | -| `Render.OpaqueGeometry` | 不透明オブジェクト描画 | -| `Render.TransparentGeometry` | 半透明オブジェクト描画 | -| `RenderForward.RenderLoopJob` | フォワードレンダリングのドローコール群 | -| `Camera.RenderSkybox` | スカイボックス描画 | -| `Camera.ImageEffects` | ポストプロセス | -| `Shadows.RenderShadowMap` | シャドウマップ生成 |