多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

RenderDoc Python API 完整指南:脚本自动化、UI 扩展与 IDE 调试实战

RenderDoc Python API 完整指南:脚本自动化、UI 扩展与 IDE 调试实战 RenderDoc Python API 完整指南脚本自动化、UI 扩展与 IDE 调试实战【免费下载链接】renderdocRenderDoc is a stand-alone graphics debugging tool.项目地址: https://gitcode.com/gh_mirrors/re/renderdoc导读RenderDoc 将内部 C API 直接封装暴露给 Python使其成为一款可深度脚本化、可个性化定制的图形调试工具——UI 中看到的任何功能都能以某种方式通过 Python 触达UI 本身的大量组件也可编程访问。本篇指南以 docs/python_api/index.rst 为主线系统讲解三大核心场景在 UI 内编写并运行脚本First Steps、把脚本固化为可持久加载的 UI 扩展UI Extensions、以及通过外部 IDE如 VS Code获得完整补全与断点调试能力。读完后你将能独立完成打开捕获 → 遍历事件与管线状态 → 自动化分析 → 注册菜单与自建面板 → 外部调试的完整技术闭环。一、Python API 全景两套模块一条主线RenderDoc 的 Python 能力分为两个层次理解二者的边界是使用一切 API 的前提renderdoc模块底层核心接口即 UI 本身构建其上的那套 API 的 Python 封装。涵盖捕获capturing、重放replay、输出outputs、分析analysis、资源resources、着色器shaders、管线pipelines、结构化数据structured_data、计数器counters与帧统计frame_stats等参考 renderdoc 模块索引。qrenderdoc模块UI 专属接口面向界面集成与扩展开发提供窗口windows、扩展注册extensions、配置config与主流程控制main参考 qrenderdoc 模块索引。两条主线贯穿所有文档脚本Scripting在 UI 内置的 Python 脚本面板中运行的一次性脚本适合临时分析与自动化扩展Extensions以extension.json__init__.py形式持久化注册的 Python 模块随 UI 启动自动加载适合日常长期使用。从源码结构看UI 脚本环境由 qrenderdoc/Code/pyrenderdoc 下的 SWIG 绑定实现示例脚本与完整教程代码可在 docs/python_api/examples 中找到而renderdoc底层核心对应的 C 入口集中在 renderdoc/replay 与 renderdoc/api/replay。二、第一个脚本在 UI 内读取当前事件与输出目标2.1 打开 Python 脚本面板从菜单Window → Python Scripting打开脚本面板。主区域是脚本编辑器支持编写、加载、保存与运行 Python 代码左侧是项目浏览器展示最近打开的文件、UI 扩展以及预置示例底部是交互式 REPL可逐行执行 Python、输出/错误标签页与帮助信息。2.2 环境全局变量pyrenderdoc在 RenderDoc UI 中运行脚本时会预置一个全局变量pyrenderdoc它是qrenderdoc.CaptureContext的实例是访问 API 的入口提供当前事件、管线状态以及事件浏览器等面板句柄。2.3 完整示例脚本先打开任意一个捕获文件然后运行以下脚本同样可在项目浏览器的Examples中找到Tutorial: First Steps with Python源码见 first_steps.pyif not pyrenderdoc.IsCaptureLoaded(): filename pyrenderdoc.Extensions().OpenFileName(Choose a capture, , *.rdc) pyrenderdoc.LoadCapture(filename, renderdoc.ReplayOptions(), filename, False, True) eid pyrenderdoc.CurEvent() name pyrenderdoc.GetEventBrowser().GetEventName(eid) print(fCurrently we are at EID {eid} named: {name}) if eid 1: prevname pyrenderdoc.GetEventBrowser().GetEventName(eid - 1) print(f the previous event {eid-1} is named: {prevname}) pipe pyrenderdoc.CurPipelineState() outputs pipe.GetOutputTargets() for idx, out in enumerate(outputs): if out.resource ! renderdoc.ResourceId.Null(): name pyrenderdoc.GetResourceName(out.resource) print(fOutput {idx} is: {name}) depth pipe.GetDepthTarget() name pyrenderdoc.GetResourceName(depth.resource) print(fDepth is: {name})点击Run后输出窗口可能出现类似结果Currently we are at EID 9408 named: vkCmdDrawIndexed(123, 2) the previous event 9407 is named: vkCmdBindDescriptorSets(1, { Descriptor Set 692529 }) Output 0 is: 2D Color Attachment 690491 Output 1 is: 2D Color Attachment 690493 Output 2 is: 2D Color Attachment 690496 Output 3 is: 2D Color Attachment 690498 Output 4 is: 2D Color Attachment 6905002.4 逐段拆解① 加载捕获若未打开IsCaptureLoaded()判断当前是否已有捕获否则通过Extensions().OpenFileName弹出文件选择框过滤*.rdc再用LoadCapture(filename, renderdoc.ReplayOptions(), filename, False, True)加载。ReplayOptions是重放配置的默认值可后续按需定制。② 查询当前事件CurEvent()返回当前事件 IDEID整数用GetEventBrowser().GetEventName(eid)获取该事件的格式化名称如vkCmdDrawIndexed(123, 2)。事件 ID 的详细语义参见 事件 ID 深入讲解当前事件的概念参见 curevent。③ 读取管线输出CurPipelineState()返回renderdoc.PipeState这是对当前管线状态子集的跨 API 抽象与捕获所用图形 API 无关不覆盖所有状态尤其 API 间存在差异的部分但适合常规用法。GetOutputTargets()获取颜色输出目标列表GetDepthTarget()获取深度目标。④ 资源名解析与判空由于部分 API 输出槽位固定且可能稀疏需用out.resource ! renderdoc.ResourceId.Null()跳过未绑定的槽位GetResourceName(resource)将 Resource ID 解析为人可读名称如2D Color Attachment 690491。Resource ID 的完整机制见 resourceids。⑤ 输出与异常print()的输出发送到输出面板面板隐藏时会自动弹出Python 异常同样打印到此面板。sys.exit()可以安全地中止脚本不会关闭 RenderDoc 本身。三、UI 扩展把脚本固化为常驻功能一次性脚本适合快速验证而UI 扩展更适合日常使用它以磁盘上的 Python 模块形式存在随 UI 启动自动加载并可注册菜单项、创建自定义面板。3.1 扩展的存储位置与目录结构扩展位于用户配置目录下平台相关Windows%APPDATA%\qrenderdoc\extensionsLinux~/.local/share/qrenderdoc/extensions扩展本质是位于该根目录下的 Python 模块子文件夹且支持嵌套extensions/foo/bar/first对应模块foo.bar.first与extensions/foo/bar/second相互独立。每个模块需要两个文件__init__.pyPython 模块主体必须包含全局函数registerextension.json清单文件元数据 兼容性约束。3.2extension.json清单清单模板完整字段说明参见 如何注册 Python 扩展{ extension_api: 1, name: Extension name for users, version: 1.0, minimum_renderdoc: 1.2, description: A longer description of your extension.\n\nIt can contain multiple lines, author: Your name youremail.com, url: url/to/repository }extension_api当前固定为1是唯一必填字段其余字段省略时使用默认值但建议填全。minimum_renderdoc控制扩展可在哪个 RenderDoc 版本上启用用于屏蔽不兼容版本。name、description、version、author、url均为展示性信息会呈现给用户。缺少extension.json的模块不会被 RenderDoc 枚举和展示。3.3 创建与启用扩展快速创建在 Python 脚本窗口的项目侧栏中双击UI Extensions下的Create New...或右键该节标题选择对应菜单在弹出的对话框中输入包名如tutorialextRenderDoc 会自动生成extension.json与__init__.py。启用通过Tools → Manage Extensions打开扩展管理器勾选目标扩展的Enable列即可加载。默认扩展不启用由于 Python 模块无法卸载取消勾选后需重启 RenderDoc 才会真正禁用。扩展文件在磁盘上被修改后可在 Python 脚本窗口或状态栏中重新加载reload若涉及回调、打开的 UI 或已注册处理器等持久化代码重载可能不稳定此时建议重启 RenderDoc 保证干净加载。3.4register入口与生命周期扩展加载或重载时模块中必须存在全局函数register签名如下def register(version, pyrenderdoc): # version 是 RenderDoc Major.Minor 版本字符串如 1.2 # pyrenderdoc 是 CaptureContext 句柄与 UI 内全局变量相同可选定义unregister()无参数在扩展被重载时先执行清理再调用register。3.5 实战示例注册菜单并创建寻宝面板以下完整代码可在Examples的Tutorial: UI extension中找到需复制进你的__init__.py才能运行源码见 ui_extensions.pyimport renderdoc as rd import qrenderdoc as qrd from typing import List def check_draw(best_size: int, action: rd.ActionDescription): if action.flags rd.ActionFlags.Drawcall: size action.numIndices * action.numInstances if size best_size: return action.eventId, size return 0, 0 def find_largest_draw(best_size: int, actions: List[rd.ActionDescription]): ret 0 for action in actions: result check_draw(best_size, action) if result[0] 0: result find_largest_draw(best_size, action.children) if result[0] 0: ret, best_size result return ret, best_size def open_window(pyrenderdoc: qrd.CaptureContext, data): mqt pyrenderdoc.Extensions().GetMiniQtHelper() top mqt.CreateToplevelWidget(Scavenger Hunt) group mqt.CreateGroupBox(False) mqt.SetWidgetText(group, Exciting scavenger hunt!) label mqt.CreateLabel() mqt.SetWidgetText(label, Guess the biggest draw!) eid, size find_largest_draw(0, pyrenderdoc.CurRootActions()) def do_guess(pyrenderdoc, widget, text): print(fSpoiler: largest draw is {eid}, it drew {size} indices) if pyrenderdoc.CurEvent() eid: msg You found it! elif pyrenderdoc.CurEvent() eid: msg The largest draw is later in the capture... else: msg The largest draw is earlier in the capture... mqt.SetWidgetText(label, fGuess the biggest draw!\n\n{msg}) button mqt.CreateButton(do_guess) mqt.SetWidgetText(button, Guess) if eid 0: mqt.SetWidgetText( label, You dont have a capture with drawcalls loaded :(.\n Re-open this window after opening a capture!, ) mqt.SetWidgetEnabled(button, False) mqt.AddWidget(top, group) mqt.AddWidget(group, label) mqt.AddWidget(group, button) pyrenderdoc.AddDockWindow( top, qrd.DockReference.TopOf, pyrenderdoc.GetEventBrowser().Widget(), 0.2 ) def register(version, pyrenderdoc: qrd.CaptureContext): print(fTutorial extension registered in RenderDoc {version}) pyrenderdoc.Extensions().RegisterPanelMenu( qrd.PanelMenu.EventBrowser, [Tutorial, Scavenger Hunt], open_window )3.6 逐段拆解从菜单到面板的完整链路注册菜单项RegisterPanelMenu(qrd.PanelMenu.EventBrowser, [Tutorial, Scavenger Hunt], open_window)在事件浏览器工具栏注册带子菜单结构的菜单项点击时回调open_window。PanelMenu枚举还提供其他可注册菜单位置可自行探索。获取 MiniQtHelperExtensions().GetMiniQtHelper()返回qrenderdoc.MiniQtHelper——RenderDoc 提供的简化 UI 构建 API。虽然 RenderDoc 通常内置 PySide 提供的完整 Qt 绑定qrenderdoc模块可访问但完整 Qt API 复杂简单 UI 用 MiniQtHelper 更高效。创建窗口与控件CreateToplevelWidget(Scavenger Hunt)创建顶层窗口其标题为Scavenger HuntCreateGroupBox(False)、CreateLabel()、CreateButton(callback)分别创建分组框、标签与按钮SetWidgetText设置文本SetWidgetEnabled控制可用性。回调参数约定交互控件的回调统一为WidgetCallback(context: qrenderdoc.CaptureContext, widget, text)形式——第一个参数是CaptureContextwidget是触发事件的控件text随事件类型不同提供当前或选中文本等上下文信息回调可选且创建后不能增删。布局控件按容器递归方式排布——垂直容器CreateVerticalContainer、水平容器CreateHorizontalContainer与网格容器CreateGridContainerAddWidget用于垂直/水平容器AddGridWidget用于网格。顶层窗口与分组框默认自带隐式垂直容器因此可直接AddWidget。详见 Mini-Qt Helper 深入讲解。生命周期控件句柄由 Python 持有但具有显式生命周期——顶层面板被用户关闭或调用CloseToplevelWidget时会递归销毁所有子控件未挂载的控件须用DestroyWidget显式销毁。关闭后遗留的句柄不可再访问。详见 生命周期管理。接入停靠系统AddDockWindow(top, qrd.DockReference.TopOf, pyrenderdoc.GetEventBrowser().Widget(), 0.2)将顶层控件加入 RenderDoc 的停靠docking系统停靠在事件浏览器上方、占 20% 空间。任何控件都可作为新顶层停靠面板但官方建议使用显式顶层控件以便捕获其关闭回调。编辑__init__.py后状态栏会提示文件已变更点击状态栏按钮即可重载扩展四、IDE 集成VS Code 补全、Stubs 与断点调试RenderDoc 内置的脚本环境不如专业 IDE 强大因此官方支持外部 IDE 集成——既能获得完整自动补全还能设置断点、单步调试UI 内运行的 Python 代码。4.1 VS Code 快速配置VS Code 开箱即可用于简单代码编辑要获得完整调试与补全按以下步骤配置以 VS Code 为例PyCharm 等工具亦可参考安装pylance与debugpy扩展Python 官方元扩展会自动安装二者。打开设置Ctrl-,将 RenderDoc stubs 目录加入Extensions → PyLance → Extra Pathsid:python.analysis.extraPaths禁用Extensions → Python Debugger → Just my codeid:debugpy.debugJustMyCode可选启用Features → Tasks → Allow Automatic Tasksid:task.allowAutomaticTasks调试时启用Run and Debug侧栏底部的Breakpoints → User Uncaught Exceptions。若刚安装调试扩展需重启 RenderDoc UI 使其被发现。之后可在 Python 脚本面板点击Attach External Debugger按钮调试 Python 代码。stubs 目录位置平台相关Windows 为%APPDATA%\qrenderdoc\pystubs\latestLinux 为~/.local/share/qrenderdoc/pystubs/latest。settings.json 形如{ python.analysis.extraPaths: [ C:\\users\\baldurk\\appdata\\roaming\\qrenderdoc\\pystubs\\latest ], debugpy.debugJustMyCode: false, task.allowAutomaticTasks: on }4.2 Python Stubs补全的基石RenderDoc 的模块由 C 编写无法携带 IDE 所需类型注解。标准替代方案是提供stub 文件——纯 Python 编写、只有签名与类型注解、无实现体。RenderDoc 会在应用数据目录Windows%APPDATA%\qrenderdoc\pystubsLinux~/.local/share/qrenderdoc/pystubs下为每个版本生成一套 stubs另有滚动更新的latest版本。日常开发直接用latest即可若针对特定版本可改用带版本号的目录。配置完成后任何import renderdoc/import qrenderdoc的脚本都会获得完整补全。4.3 Python 调试debugpy 与端口 5678RenderDoc 通过集成debugpy常见的远程调试库让外部调试器连接并调试 UI 内的 Python 代码若 VS Code 安装在标准位置且安装了ms-python.debugpyRenderDoc 首次启动会自动加载并初始化debugpy找不到 VS Code 时尝试从 PyCharm 安装目录加载也可自定义debugpy路径。刚装扩展后需重启 RenderDoc。debugpy就绪后调试器默认监听本地端口5678。在 VS Code/IDE 中配置 remote attach 连接localhost:5678即可。RenderDoc 检测到 VS Code 后脚本中按Attach External Debugger会自动以必要环境启动 VS Code若启用Allow Automatic Tasks会在启动时自动连接调试器。重要RenderDoc 的调试连接是单例的——同一时刻只能有一个 IDE/调试器连接且多个 UI 实例时仅第一个启动的实例可被连接。附加动作须从 IDE 侧发起UI 内的按钮只是启动 IDE 并可能触发其立即连接并非必须。注意若从源码构建默认基于 Python 3.6不支持调试需按 自定义 Python 版本 一节改用更新版本或直接使用官方发布版基于 Python 3.8。4.4 常见陷阱路径映射与Just My Code路径映射path mappingsRenderDoc 默认会创建.vscode/launch.json配置附加调试但不会覆盖已存在的文件。VS Code 默认的远程附加配置含 path mappings而同机同路径调试时会导致 RenderDoc 调试失效表现为文件重复打开新标签、断点不生效。强烈建议删除所有路径映射并在重新附加前重启 RenderDoc 与 VS Code。Just My Code由于 RenderDoc 的 Python 集成方式特殊VS Code 可能认为脚本不属于项目因此务必禁用debugpy的Just my code。未捕获异常RenderDoc 自身会捕获未处理异常以提升 UI 稳定性因此需在Breakpoints中启用User Uncaught ExceptionsVS Code 才能正确拦截异常。五、命令行脚本执行与进阶场景5.1--py与--ui-py部分工作流需要从命令行运行脚本RenderDoc UI 提供两种方式--py path/to/script.py在初始化早期、UI 创建显示之前运行脚本适合无头执行与批量处理。与 UI 内运行不同此类脚本中调用sys.exit()会使整个 RenderDoc 进程退出。--ui-py path/to/script.py等待 UI 显示后打开 Python 脚本窗口并以新标签页加载运行指定脚本。5.2 示例集合与深入专题项目浏览器Examples中预置了大量可直接加载运行的示例对应源码位于 docs/python_api/examples覆盖常见工作流show_buffer.py / show_texture.py展示缓冲区与纹理iter_actions.py遍历动作action树pipe_state.py查询管线状态shader_refl.py着色器反射信息resource_usage.py资源使用分析mem_binds.py内存绑定history_debug.py像素历史调试mesh_output.py网格输出advanced_buffers.py高级缓冲区处理exe_launching.py启动外部程序event_filter.py事件过滤。所有示例共用一个 preamble用于外部 IDE 的类型提示见 FAQ 中对应条目# these imports are not strictly necessary, but are convenient import renderdoc import qrenderdoc # this is here to give autocomplete when editing the example # in VS Code where it doesnt know about this global from typing import TYPE_CHECKING if TYPE_CHECKING: pyrenderdoc qrenderdoc.CaptureContext()原理TYPE_CHECKING仅在类型检查器如 IDE中为True、实际执行时为False从而在不影响运行的前提下为pyrenderdoc标注正确的CaptureContext类型该类型无法从 Python 创建直接执行会失败。示例还普遍带有检查捕获是否打开、未打开则提示选择的前置逻辑与first_steps.py开头一致。深入专题参见 in_depth/index资源 ID、事件 ID、当前事件、帧观察者回调frame_viewers可在捕获加载/关闭或事件选择时获得回调、ReplayController底层 API 的主入口、线程模型、生命周期、着色器反射、描述符与绑定、结构化数据、MiniQt、输出、捕获访问、程序启动与远程重放。六、常见问题FAQ要点脚本崩溃Python 绑定是 C API 的薄封装向 API 传递语义非法数据如把纹理 ID 传给期望着色器 ID 的函数可能直接崩溃Python API不做健壮错误检查持有指向已删除 C 对象的 Python 引用如捕获关闭后的缓存信息也可能崩溃。此类问题通常需自查脚本除非能用纯 UI 复现否则不应归为 RenderDoc 缺陷。REPL 中对象预览不友好临时对象可能显示Swig Object of type FooBar * at 0x...这是绑定生成方式所致对含属性的结构体可用renderdoc.DumpObject获得更可读的预览。新建面板看不到为避免 UI 抖动新创建的BufferViewer、ShaderViewer等非单例面板不会自动显示必须调用AddDockWindow将其挂入 UI 层级。API 兼容性Python API 目前未锁定各版本间可能有破坏性变更重命名、删除成员或改变成员含义结构体新增成员或类新增方法不影响现有脚本。每个版本 release notes 会列出 Python 破坏性变更建议面向最新版本编写脚本。UI 定制权限底层renderdoc模块自动暴露全部能力UI 与 Python 使用同一 APIqrenderdoc模块则编写得更保守避免暴露大量未用功能。若需要 UI 中尚不可编程访问的功能可提交 feature request按需开放。C 直接使用这些 API可以但不推荐且不受支持。Python 因不依赖 ABI 而能容忍结构体重排/新增成员C 则需承受全部 ABI 变更。数据修改边界多数情况下返回的列表与对象是拷贝归 Python 所有可自由修改但有例外——ShaderReflection对象、ActionDescription的相邻/子节点引用、SDFile的SDObject与缓冲区均为引用修改它们可能损坏内部数据甚至崩溃不应修改。Android理论上脚本重放与平台无关但因 Android 平台本身的不稳定性Python 脚本与 Android 捕获组合不被官方支持如需使用需谨慎。七、脱离 UI 使用 Python 模块高级用法除 UI 内嵌运行时外还可在独立 Python 解释器中以普通模块方式加载renderdoc模块qrenderdoc因依赖 UI 不可独立加载。此用法属于高级场景写普通脚本或扩展并不需要完整说明见 python_module。7.1 构建与版本匹配RenderDoc 默认不随发布包附带可导入解释器的 Python 模块因为绑定与特定 Python 主次版本强绑定。需自行从源码构建构建成功后模块位置依平台而异Windows 为避免文件名冲突位于pymodules子目录Linux 输出到lib目录下的renderdoc.so。模块默认针对构建时的 Python 版本编译Linux 取决于系统版本Windows 为源码捆绑的 Python 3.6只能在该版本中安全加载。7.2 指定 Python 版本Windows在 Visual Studio 工程中qrenderdoc、pyrenderdoc_module、qrenderdoc_module各自的Python Configuration属性页指定解释器路径。RenderDoc 还需标准库 zip 包python3.xx.zip类似官方 embeddable package。可用源码树中的 util/make_python_lib_zip.py 从解释器自身将Lib/编译为 zip 放到python.exe旁。构建成功提示形如Built against python from C:\Python314失败则回退到捆绑 Python 3.6 并给出缺失项提示如Python.h、pythonMAJMIN.zip、pythonMAJMIN.lib。LinuxCMake 3.12 可用-DFORCE_PY_VERSION3.xx强制指定版本配置阶段会打印实际使用的 Python 版本。7.3 加载模块与核心库依赖模块只是薄封装依赖 RenderDoc 核心库Windows核心库需在PATH中Python 3.8 还需调用os.add_dll_directory指向renderdoc.dll所在目录。缺失时报ImportError: DLL load failed while importing renderdoc: The specified module could not be found.Linux模块带RUNPATH指向自身位置核心库librenderdoc.so通常同目录即可加载移动后可设置LD_LIBRARY_PATH否则报ImportError: librenderdoc.so: cannot open shared object file: No such file or directory。7.4 直接使用 API 的必备初始化UI 通常代为处理初始化独立使用时必须显式管理import renderdoc renderdoc.InitialiseReplay() # 任何其他 API 调用前必须调用一次 # ... 执行捕获/重放/分析 ... renderdoc.ShutdownReplay() # 进程结束前调用初始化前或关闭后的任何 API 调用均非法关闭后不可再次初始化。仓库 util/test 下的自动化测试脚本全部由 Python 编写演示了捕获、重放与分析全流程的直接模块用法。八、推荐学习路径先按 first_steps.py 在 UI 中跑通第一个脚本理解pyrenderdoc入口阅读 examples 中的示例覆盖各常见工作流按 ui_extensions.py 创建你的第一个 UI 扩展将脚本固化为常驻功能按 ide_integration.rst 配置 VS Code获得补全与断点调试能力编写复杂脚本前通读 in_depth 专题尤其是生命周期、线程、事件 ID 与资源 ID需要脱离 UI 的自动化时参考 python_module 手动构建与加载模块遇到疑难先查 FAQ它涵盖了崩溃、对象预览、命令行执行、兼容性等高频问题。【免费下载链接】renderdocRenderDoc is a stand-alone graphics debugging tool.项目地址: https://gitcode.com/gh_mirrors/re/renderdoc创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表