rdc-cli 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- rdc_cli-0.2.0/LICENSE +21 -0
- rdc_cli-0.2.0/PKG-INFO +130 -0
- rdc_cli-0.2.0/README.md +106 -0
- rdc_cli-0.2.0/pyproject.toml +45 -0
- rdc_cli-0.2.0/setup.cfg +4 -0
- rdc_cli-0.2.0/src/rdc/__init__.py +4 -0
- rdc_cli-0.2.0/src/rdc/adapter.py +61 -0
- rdc_cli-0.2.0/src/rdc/cli.py +65 -0
- rdc_cli-0.2.0/src/rdc/commands/capture.py +62 -0
- rdc_cli-0.2.0/src/rdc/commands/completion.py +49 -0
- rdc_cli-0.2.0/src/rdc/commands/counters.py +50 -0
- rdc_cli-0.2.0/src/rdc/commands/doctor.py +98 -0
- rdc_cli-0.2.0/src/rdc/commands/events.py +140 -0
- rdc_cli-0.2.0/src/rdc/commands/export.py +57 -0
- rdc_cli-0.2.0/src/rdc/commands/info.py +125 -0
- rdc_cli-0.2.0/src/rdc/commands/pipeline.py +330 -0
- rdc_cli-0.2.0/src/rdc/commands/resources.py +126 -0
- rdc_cli-0.2.0/src/rdc/commands/search.py +67 -0
- rdc_cli-0.2.0/src/rdc/commands/session.py +57 -0
- rdc_cli-0.2.0/src/rdc/commands/unix_helpers.py +79 -0
- rdc_cli-0.2.0/src/rdc/commands/usage.py +57 -0
- rdc_cli-0.2.0/src/rdc/commands/vfs.py +206 -0
- rdc_cli-0.2.0/src/rdc/daemon_client.py +32 -0
- rdc_cli-0.2.0/src/rdc/daemon_server.py +2079 -0
- rdc_cli-0.2.0/src/rdc/discover.py +84 -0
- rdc_cli-0.2.0/src/rdc/formatters/json_fmt.py +20 -0
- rdc_cli-0.2.0/src/rdc/formatters/tsv.py +60 -0
- rdc_cli-0.2.0/src/rdc/protocol.py +61 -0
- rdc_cli-0.2.0/src/rdc/services/__init__.py +1 -0
- rdc_cli-0.2.0/src/rdc/services/query_service.py +512 -0
- rdc_cli-0.2.0/src/rdc/services/session_service.py +174 -0
- rdc_cli-0.2.0/src/rdc/session_state.py +86 -0
- rdc_cli-0.2.0/src/rdc/vfs/__init__.py +0 -0
- rdc_cli-0.2.0/src/rdc/vfs/formatter.py +62 -0
- rdc_cli-0.2.0/src/rdc/vfs/router.py +191 -0
- rdc_cli-0.2.0/src/rdc/vfs/tree_cache.py +308 -0
- rdc_cli-0.2.0/src/rdc_cli.egg-info/PKG-INFO +130 -0
- rdc_cli-0.2.0/src/rdc_cli.egg-info/SOURCES.txt +40 -0
- rdc_cli-0.2.0/src/rdc_cli.egg-info/dependency_links.txt +1 -0
- rdc_cli-0.2.0/src/rdc_cli.egg-info/entry_points.txt +2 -0
- rdc_cli-0.2.0/src/rdc_cli.egg-info/requires.txt +17 -0
- rdc_cli-0.2.0/src/rdc_cli.egg-info/top_level.txt +1 -0
rdc_cli-0.2.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jim
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
rdc_cli-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: rdc-cli
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Unix-friendly CLI for RenderDoc captures
|
|
5
|
+
Author: Jim
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Requires-Python: >=3.10
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Requires-Dist: click>=8.1
|
|
11
|
+
Provides-Extra: rich
|
|
12
|
+
Requires-Dist: rich>=13.0; extra == "rich"
|
|
13
|
+
Provides-Extra: imaging
|
|
14
|
+
Requires-Dist: Pillow>=10.0; extra == "imaging"
|
|
15
|
+
Provides-Extra: diff
|
|
16
|
+
Requires-Dist: Pillow>=10.0; extra == "diff"
|
|
17
|
+
Requires-Dist: numpy>=1.24; extra == "diff"
|
|
18
|
+
Provides-Extra: dev
|
|
19
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
20
|
+
Requires-Dist: pytest-cov>=5.0; extra == "dev"
|
|
21
|
+
Requires-Dist: mypy>=1.10; extra == "dev"
|
|
22
|
+
Requires-Dist: ruff>=0.6; extra == "dev"
|
|
23
|
+
Dynamic: license-file
|
|
24
|
+
|
|
25
|
+
# rdc-cli
|
|
26
|
+
|
|
27
|
+
Unix-friendly CLI for [RenderDoc](https://renderdoc.org/) `.rdc` captures. Pipe-friendly TSV output, JSON mode, 33 commands, daemon-backed session for interactive exploration.
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
rdc open capture.rdc # Start session
|
|
31
|
+
rdc draws # List draw calls (TSV)
|
|
32
|
+
rdc pipeline 142 # Pipeline state at EID 142
|
|
33
|
+
rdc shader 142 ps # Pixel shader disassembly
|
|
34
|
+
rdc texture 5 -o out.png # Export texture
|
|
35
|
+
rdc draws --json | jq '...' # Machine-readable output
|
|
36
|
+
rdc close # End session
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Install
|
|
40
|
+
|
|
41
|
+
### PyPI (recommended)
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
pipx install rdc-cli
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### AUR (Arch Linux)
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
yay -S rdc-cli-git
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
This builds the renderdoc Python module automatically — no extra setup needed.
|
|
54
|
+
|
|
55
|
+
### From source
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
git clone https://github.com/BANANASJIM/rdc-cli.git
|
|
59
|
+
cd rdc-cli
|
|
60
|
+
pixi install && pixi run sync
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Setup renderdoc
|
|
64
|
+
|
|
65
|
+
`rdc` requires the renderdoc Python module (`renderdoc.cpython-*.so`), which is **not** included in most system packages. Your Python version must match the one used to compile renderdoc.
|
|
66
|
+
|
|
67
|
+
### Build from source
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
git clone --depth 1 https://github.com/baldurk/renderdoc.git
|
|
71
|
+
cd renderdoc
|
|
72
|
+
cmake -B build -DENABLE_PYRENDERDOC=ON -DENABLE_QRENDERDOC=OFF
|
|
73
|
+
cmake --build build -j$(nproc)
|
|
74
|
+
export RENDERDOC_PYTHON_PATH=$PWD/build/lib
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Module discovery order
|
|
78
|
+
|
|
79
|
+
1. `RENDERDOC_PYTHON_PATH` environment variable
|
|
80
|
+
2. `/usr/lib/renderdoc`, `/usr/local/lib/renderdoc`
|
|
81
|
+
3. Sibling directory of `renderdoccmd` on PATH
|
|
82
|
+
|
|
83
|
+
### Verify
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
rdc doctor
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Commands
|
|
90
|
+
|
|
91
|
+
Run `rdc --help` for the full command list, or `rdc <command> --help` for details.
|
|
92
|
+
|
|
93
|
+
| Category | Commands |
|
|
94
|
+
|----------|----------|
|
|
95
|
+
| Session | `open`, `close`, `status`, `goto` |
|
|
96
|
+
| Inspection | `info`, `stats`, `events`, `draws`, `event`, `draw`, `log` |
|
|
97
|
+
| GPU state | `pipeline`, `bindings`, `shader`, `shaders`, `shader-map` |
|
|
98
|
+
| Resources | `resources`, `resource`, `passes`, `pass`, `usage` |
|
|
99
|
+
| Export | `texture`, `rt`, `buffer` |
|
|
100
|
+
| Search | `search`, `counters` |
|
|
101
|
+
| VFS | `ls`, `cat`, `tree` |
|
|
102
|
+
| Utility | `doctor`, `completion`, `capture`, `count` |
|
|
103
|
+
|
|
104
|
+
All commands support `--json` for machine-readable output.
|
|
105
|
+
|
|
106
|
+
### Shell completions
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
rdc completion bash > ~/.local/share/bash-completion/completions/rdc
|
|
110
|
+
rdc completion zsh > ~/.zfunc/_rdc
|
|
111
|
+
eval "$(rdc completion bash)"
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Development
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
pixi run sync # Install Python deps
|
|
118
|
+
pixi run check # lint + typecheck + test (653 tests, 92% coverage)
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
GPU integration tests require a real renderdoc module:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
export RENDERDOC_PYTHON_PATH=/path/to/renderdoc/build/lib
|
|
125
|
+
pixi run test-gpu
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## License
|
|
129
|
+
|
|
130
|
+
MIT
|
rdc_cli-0.2.0/README.md
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# rdc-cli
|
|
2
|
+
|
|
3
|
+
Unix-friendly CLI for [RenderDoc](https://renderdoc.org/) `.rdc` captures. Pipe-friendly TSV output, JSON mode, 33 commands, daemon-backed session for interactive exploration.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
rdc open capture.rdc # Start session
|
|
7
|
+
rdc draws # List draw calls (TSV)
|
|
8
|
+
rdc pipeline 142 # Pipeline state at EID 142
|
|
9
|
+
rdc shader 142 ps # Pixel shader disassembly
|
|
10
|
+
rdc texture 5 -o out.png # Export texture
|
|
11
|
+
rdc draws --json | jq '...' # Machine-readable output
|
|
12
|
+
rdc close # End session
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Install
|
|
16
|
+
|
|
17
|
+
### PyPI (recommended)
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pipx install rdc-cli
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### AUR (Arch Linux)
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
yay -S rdc-cli-git
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
This builds the renderdoc Python module automatically — no extra setup needed.
|
|
30
|
+
|
|
31
|
+
### From source
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
git clone https://github.com/BANANASJIM/rdc-cli.git
|
|
35
|
+
cd rdc-cli
|
|
36
|
+
pixi install && pixi run sync
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Setup renderdoc
|
|
40
|
+
|
|
41
|
+
`rdc` requires the renderdoc Python module (`renderdoc.cpython-*.so`), which is **not** included in most system packages. Your Python version must match the one used to compile renderdoc.
|
|
42
|
+
|
|
43
|
+
### Build from source
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
git clone --depth 1 https://github.com/baldurk/renderdoc.git
|
|
47
|
+
cd renderdoc
|
|
48
|
+
cmake -B build -DENABLE_PYRENDERDOC=ON -DENABLE_QRENDERDOC=OFF
|
|
49
|
+
cmake --build build -j$(nproc)
|
|
50
|
+
export RENDERDOC_PYTHON_PATH=$PWD/build/lib
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Module discovery order
|
|
54
|
+
|
|
55
|
+
1. `RENDERDOC_PYTHON_PATH` environment variable
|
|
56
|
+
2. `/usr/lib/renderdoc`, `/usr/local/lib/renderdoc`
|
|
57
|
+
3. Sibling directory of `renderdoccmd` on PATH
|
|
58
|
+
|
|
59
|
+
### Verify
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
rdc doctor
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Commands
|
|
66
|
+
|
|
67
|
+
Run `rdc --help` for the full command list, or `rdc <command> --help` for details.
|
|
68
|
+
|
|
69
|
+
| Category | Commands |
|
|
70
|
+
|----------|----------|
|
|
71
|
+
| Session | `open`, `close`, `status`, `goto` |
|
|
72
|
+
| Inspection | `info`, `stats`, `events`, `draws`, `event`, `draw`, `log` |
|
|
73
|
+
| GPU state | `pipeline`, `bindings`, `shader`, `shaders`, `shader-map` |
|
|
74
|
+
| Resources | `resources`, `resource`, `passes`, `pass`, `usage` |
|
|
75
|
+
| Export | `texture`, `rt`, `buffer` |
|
|
76
|
+
| Search | `search`, `counters` |
|
|
77
|
+
| VFS | `ls`, `cat`, `tree` |
|
|
78
|
+
| Utility | `doctor`, `completion`, `capture`, `count` |
|
|
79
|
+
|
|
80
|
+
All commands support `--json` for machine-readable output.
|
|
81
|
+
|
|
82
|
+
### Shell completions
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
rdc completion bash > ~/.local/share/bash-completion/completions/rdc
|
|
86
|
+
rdc completion zsh > ~/.zfunc/_rdc
|
|
87
|
+
eval "$(rdc completion bash)"
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Development
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
pixi run sync # Install Python deps
|
|
94
|
+
pixi run check # lint + typecheck + test (653 tests, 92% coverage)
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
GPU integration tests require a real renderdoc module:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
export RENDERDOC_PYTHON_PATH=/path/to/renderdoc/build/lib
|
|
101
|
+
pixi run test-gpu
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## License
|
|
105
|
+
|
|
106
|
+
MIT
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "rdc-cli"
|
|
7
|
+
version = "0.2.0"
|
|
8
|
+
description = "Unix-friendly CLI for RenderDoc captures"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
authors = [{name = "Jim"}]
|
|
13
|
+
dependencies = [
|
|
14
|
+
"click>=8.1",
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
[project.optional-dependencies]
|
|
18
|
+
rich = ["rich>=13.0"]
|
|
19
|
+
imaging = ["Pillow>=10.0"]
|
|
20
|
+
diff = ["Pillow>=10.0", "numpy>=1.24"]
|
|
21
|
+
dev = [
|
|
22
|
+
"pytest>=8.0",
|
|
23
|
+
"pytest-cov>=5.0",
|
|
24
|
+
"mypy>=1.10",
|
|
25
|
+
"ruff>=0.6",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
[project.scripts]
|
|
29
|
+
rdc = "rdc.cli:main"
|
|
30
|
+
|
|
31
|
+
[tool.setuptools]
|
|
32
|
+
package-dir = {"" = "src"}
|
|
33
|
+
|
|
34
|
+
[tool.setuptools.packages.find]
|
|
35
|
+
where = ["src"]
|
|
36
|
+
|
|
37
|
+
[tool.pytest.ini_options]
|
|
38
|
+
addopts = "-q"
|
|
39
|
+
testpaths = ["tests"]
|
|
40
|
+
markers = ["gpu: requires real renderdoc module and GPU"]
|
|
41
|
+
|
|
42
|
+
[tool.mypy]
|
|
43
|
+
python_version = "3.10"
|
|
44
|
+
strict = true
|
|
45
|
+
warn_unused_configs = true
|
rdc_cli-0.2.0/setup.cfg
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def parse_version_tuple(value: str) -> tuple[int, int]:
|
|
9
|
+
"""Parse RenderDoc version string into (major, minor)."""
|
|
10
|
+
match = re.search(r"(\d+)\.(\d+)", value)
|
|
11
|
+
if not match:
|
|
12
|
+
return (0, 0)
|
|
13
|
+
return int(match.group(1)), int(match.group(2))
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass(frozen=True)
|
|
17
|
+
class RenderDocAdapter:
|
|
18
|
+
"""Compatibility adapter for RenderDoc API changes across versions."""
|
|
19
|
+
|
|
20
|
+
controller: Any
|
|
21
|
+
version: tuple[int, int]
|
|
22
|
+
|
|
23
|
+
def get_root_actions(self) -> Any:
|
|
24
|
+
"""Return root actions with compatibility handling."""
|
|
25
|
+
if self.version >= (1, 32) and hasattr(self.controller, "GetRootActions"):
|
|
26
|
+
return self.controller.GetRootActions()
|
|
27
|
+
if hasattr(self.controller, "GetDrawcalls"):
|
|
28
|
+
return self.controller.GetDrawcalls()
|
|
29
|
+
raise AttributeError("controller has neither GetRootActions nor GetDrawcalls")
|
|
30
|
+
|
|
31
|
+
def get_api_properties(self) -> Any:
|
|
32
|
+
"""Return API properties from the controller."""
|
|
33
|
+
return self.controller.GetAPIProperties()
|
|
34
|
+
|
|
35
|
+
def get_resources(self) -> Any:
|
|
36
|
+
"""Return all resources from the controller."""
|
|
37
|
+
return self.controller.GetResources()
|
|
38
|
+
|
|
39
|
+
def get_pipeline_state(self) -> Any:
|
|
40
|
+
"""Return current pipeline state."""
|
|
41
|
+
return self.controller.GetPipelineState()
|
|
42
|
+
|
|
43
|
+
def get_structured_file(self) -> Any:
|
|
44
|
+
"""Return structured file from the controller."""
|
|
45
|
+
return self.controller.GetStructuredFile()
|
|
46
|
+
|
|
47
|
+
def set_frame_event(self, eid: int, force: bool = True) -> None:
|
|
48
|
+
"""Move the replay to the given event ID."""
|
|
49
|
+
self.controller.SetFrameEvent(eid, force)
|
|
50
|
+
|
|
51
|
+
def get_textures(self) -> Any:
|
|
52
|
+
"""Return all texture descriptions from the controller."""
|
|
53
|
+
return self.controller.GetTextures()
|
|
54
|
+
|
|
55
|
+
def get_buffers(self) -> Any:
|
|
56
|
+
"""Return all buffer descriptions from the controller."""
|
|
57
|
+
return self.controller.GetBuffers()
|
|
58
|
+
|
|
59
|
+
def shutdown(self) -> None:
|
|
60
|
+
"""Shutdown the replay controller."""
|
|
61
|
+
self.controller.Shutdown()
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import click
|
|
4
|
+
|
|
5
|
+
from rdc import __version__
|
|
6
|
+
from rdc.commands.capture import capture_cmd
|
|
7
|
+
from rdc.commands.completion import completion_cmd
|
|
8
|
+
from rdc.commands.counters import counters_cmd
|
|
9
|
+
from rdc.commands.doctor import doctor_cmd
|
|
10
|
+
from rdc.commands.events import draw_cmd, draws_cmd, event_cmd, events_cmd
|
|
11
|
+
from rdc.commands.export import buffer_cmd, rt_cmd, texture_cmd
|
|
12
|
+
from rdc.commands.info import info_cmd, log_cmd, stats_cmd
|
|
13
|
+
from rdc.commands.pipeline import bindings_cmd, pipeline_cmd, shader_cmd, shaders_cmd
|
|
14
|
+
from rdc.commands.resources import pass_cmd, passes_cmd, resource_cmd, resources_cmd
|
|
15
|
+
from rdc.commands.search import search_cmd
|
|
16
|
+
from rdc.commands.session import close_cmd, goto_cmd, open_cmd, status_cmd
|
|
17
|
+
from rdc.commands.unix_helpers import count_cmd, shader_map_cmd
|
|
18
|
+
from rdc.commands.usage import usage_cmd
|
|
19
|
+
from rdc.commands.vfs import cat_cmd, complete_cmd, ls_cmd, tree_cmd
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@click.group(context_settings={"help_option_names": ["-h", "--help"]})
|
|
23
|
+
@click.version_option(version=__version__, prog_name="rdc")
|
|
24
|
+
def main() -> None:
|
|
25
|
+
"""rdc: Unix-friendly CLI for RenderDoc captures."""
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
main.add_command(doctor_cmd, name="doctor")
|
|
29
|
+
main.add_command(capture_cmd, name="capture")
|
|
30
|
+
main.add_command(open_cmd, name="open")
|
|
31
|
+
main.add_command(close_cmd, name="close")
|
|
32
|
+
main.add_command(status_cmd, name="status")
|
|
33
|
+
main.add_command(goto_cmd, name="goto")
|
|
34
|
+
main.add_command(info_cmd, name="info")
|
|
35
|
+
main.add_command(stats_cmd, name="stats")
|
|
36
|
+
main.add_command(events_cmd, name="events")
|
|
37
|
+
main.add_command(draws_cmd, name="draws")
|
|
38
|
+
main.add_command(event_cmd, name="event")
|
|
39
|
+
main.add_command(draw_cmd, name="draw")
|
|
40
|
+
main.add_command(count_cmd, name="count")
|
|
41
|
+
main.add_command(shader_map_cmd, name="shader-map")
|
|
42
|
+
main.add_command(pipeline_cmd, name="pipeline")
|
|
43
|
+
main.add_command(bindings_cmd, name="bindings")
|
|
44
|
+
main.add_command(shader_cmd, name="shader")
|
|
45
|
+
main.add_command(shaders_cmd, name="shaders")
|
|
46
|
+
main.add_command(resources_cmd, name="resources")
|
|
47
|
+
main.add_command(resource_cmd, name="resource")
|
|
48
|
+
main.add_command(passes_cmd, name="passes")
|
|
49
|
+
main.add_command(pass_cmd, name="pass")
|
|
50
|
+
main.add_command(log_cmd, name="log")
|
|
51
|
+
main.add_command(ls_cmd, name="ls")
|
|
52
|
+
main.add_command(cat_cmd, name="cat")
|
|
53
|
+
main.add_command(tree_cmd, name="tree")
|
|
54
|
+
main.add_command(complete_cmd, name="_complete")
|
|
55
|
+
main.add_command(texture_cmd, name="texture")
|
|
56
|
+
main.add_command(rt_cmd, name="rt")
|
|
57
|
+
main.add_command(buffer_cmd, name="buffer")
|
|
58
|
+
main.add_command(search_cmd, name="search")
|
|
59
|
+
main.add_command(usage_cmd, name="usage")
|
|
60
|
+
main.add_command(completion_cmd, name="completion")
|
|
61
|
+
main.add_command(counters_cmd, name="counters")
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
if __name__ == "__main__":
|
|
65
|
+
main()
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import shutil
|
|
4
|
+
import subprocess
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
import click
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def _find_renderdoccmd() -> str | None:
|
|
11
|
+
in_path = shutil.which("renderdoccmd")
|
|
12
|
+
if in_path:
|
|
13
|
+
return in_path
|
|
14
|
+
|
|
15
|
+
common_paths = [
|
|
16
|
+
Path("/opt/renderdoc/bin/renderdoccmd"),
|
|
17
|
+
Path("/usr/local/bin/renderdoccmd"),
|
|
18
|
+
]
|
|
19
|
+
for path in common_paths:
|
|
20
|
+
if path.exists() and path.is_file():
|
|
21
|
+
return str(path)
|
|
22
|
+
return None
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@click.command(
|
|
26
|
+
"capture",
|
|
27
|
+
context_settings={"ignore_unknown_options": True, "allow_extra_args": True},
|
|
28
|
+
)
|
|
29
|
+
@click.option("--api", "api_name", type=str, help="Capture API (maps to --opt-api).")
|
|
30
|
+
@click.option("-o", "--output", type=click.Path(path_type=Path), help="Output capture file path.")
|
|
31
|
+
@click.option("--list-apis", is_flag=True, help="List capture APIs via renderdoccmd and exit.")
|
|
32
|
+
@click.pass_context
|
|
33
|
+
def capture_cmd(
|
|
34
|
+
ctx: click.Context,
|
|
35
|
+
api_name: str | None,
|
|
36
|
+
output: Path | None,
|
|
37
|
+
list_apis: bool,
|
|
38
|
+
) -> None:
|
|
39
|
+
"""Thin wrapper around renderdoccmd capture."""
|
|
40
|
+
bin_path = _find_renderdoccmd()
|
|
41
|
+
if not bin_path:
|
|
42
|
+
click.echo("error: renderdoccmd not found in PATH", err=True)
|
|
43
|
+
raise SystemExit(1)
|
|
44
|
+
|
|
45
|
+
argv: list[str] = [bin_path, "capture"]
|
|
46
|
+
|
|
47
|
+
if list_apis:
|
|
48
|
+
argv.append("--list-apis")
|
|
49
|
+
else:
|
|
50
|
+
if api_name:
|
|
51
|
+
argv.extend(["--opt-api", api_name])
|
|
52
|
+
if output:
|
|
53
|
+
argv.extend(["--capture-file", str(output)])
|
|
54
|
+
argv.extend(ctx.args)
|
|
55
|
+
|
|
56
|
+
result = subprocess.run(argv, check=False)
|
|
57
|
+
if result.returncode != 0:
|
|
58
|
+
raise SystemExit(result.returncode)
|
|
59
|
+
|
|
60
|
+
if output and not list_apis:
|
|
61
|
+
click.echo(f"capture saved: {output}", err=True)
|
|
62
|
+
click.echo(f"next: rdc open {output}", err=True)
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"""Shell completion script generation."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
import click
|
|
9
|
+
|
|
10
|
+
_SUPPORTED_SHELLS = ("bash", "zsh", "fish")
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _detect_shell() -> str:
|
|
14
|
+
"""Detect current shell from $SHELL."""
|
|
15
|
+
name = Path(os.environ.get("SHELL", "bash")).name
|
|
16
|
+
return name if name in _SUPPORTED_SHELLS else "bash"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _generate(shell: str) -> str:
|
|
20
|
+
"""Generate completion script via Click's built-in mechanism."""
|
|
21
|
+
from click.shell_completion import get_completion_class
|
|
22
|
+
|
|
23
|
+
from rdc.cli import main # deferred: rdc.cli imports this module
|
|
24
|
+
|
|
25
|
+
cls = get_completion_class(shell)
|
|
26
|
+
if cls is None:
|
|
27
|
+
raise click.ClickException(f"Unsupported shell: {shell}")
|
|
28
|
+
comp = cls(cli=main, ctx_args={}, prog_name="rdc", complete_var="_RDC_COMPLETE")
|
|
29
|
+
return comp.source()
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@click.command("completion")
|
|
33
|
+
@click.argument("shell", required=False, type=click.Choice(_SUPPORTED_SHELLS))
|
|
34
|
+
def completion_cmd(shell: str | None) -> None:
|
|
35
|
+
"""Generate shell completion script.
|
|
36
|
+
|
|
37
|
+
Prints the completion script to stdout. Redirect or eval as needed.
|
|
38
|
+
|
|
39
|
+
\b
|
|
40
|
+
Examples:
|
|
41
|
+
rdc completion bash > ~/.local/share/bash-completion/completions/rdc
|
|
42
|
+
rdc completion zsh > ~/.zfunc/_rdc
|
|
43
|
+
eval "$(rdc completion bash)"
|
|
44
|
+
"""
|
|
45
|
+
if shell is None:
|
|
46
|
+
shell = _detect_shell()
|
|
47
|
+
click.echo(f"# Detected shell: {shell}", err=True)
|
|
48
|
+
|
|
49
|
+
click.echo(_generate(shell))
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"""rdc counters command — GPU performance counters."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
import click
|
|
8
|
+
|
|
9
|
+
from rdc.commands.info import _daemon_call
|
|
10
|
+
from rdc.formatters.json_fmt import write_json
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@click.command("counters")
|
|
14
|
+
@click.option("--list", "show_list", is_flag=True, help="List available counters.")
|
|
15
|
+
@click.option("--eid", type=int, default=None, help="Filter to specific event ID.")
|
|
16
|
+
@click.option("--name", "name_filter", default=None, help="Filter counters by name substring.")
|
|
17
|
+
@click.option("--json", "use_json", is_flag=True, help="JSON output.")
|
|
18
|
+
def counters_cmd(
|
|
19
|
+
show_list: bool,
|
|
20
|
+
eid: int | None,
|
|
21
|
+
name_filter: str | None,
|
|
22
|
+
use_json: bool,
|
|
23
|
+
) -> None:
|
|
24
|
+
"""Query GPU performance counters.
|
|
25
|
+
|
|
26
|
+
Use --list to enumerate available counters, or run without --list
|
|
27
|
+
to fetch counter values for all draw events.
|
|
28
|
+
"""
|
|
29
|
+
if show_list:
|
|
30
|
+
result = _daemon_call("counter_list")
|
|
31
|
+
if use_json:
|
|
32
|
+
write_json(result)
|
|
33
|
+
return
|
|
34
|
+
click.echo("ID\tNAME\tUNIT\tTYPE\tCATEGORY")
|
|
35
|
+
for c in result.get("counters", []):
|
|
36
|
+
click.echo(f"{c['id']}\t{c['name']}\t{c['unit']}\t{c['type']}\t{c['category']}")
|
|
37
|
+
return
|
|
38
|
+
|
|
39
|
+
params: dict[str, Any] = {}
|
|
40
|
+
if eid is not None:
|
|
41
|
+
params["eid"] = eid
|
|
42
|
+
if name_filter is not None:
|
|
43
|
+
params["name"] = name_filter
|
|
44
|
+
result = _daemon_call("counter_fetch", params)
|
|
45
|
+
if use_json:
|
|
46
|
+
write_json(result)
|
|
47
|
+
return
|
|
48
|
+
click.echo("EID\tCOUNTER\tVALUE\tUNIT")
|
|
49
|
+
for r in result.get("rows", []):
|
|
50
|
+
click.echo(f"{r['eid']}\t{r['counter']}\t{r['value']}\t{r['unit']}")
|