- 开发工具
- 调试器
- 图形学
- GPU
【免费下载链接】renderdoc
RenderDoc is a stand-alone graphics debugging tool.
本指南面向 RenderDoc 的贡献者与二次开发者,系统说明在为 RenderDoc 提交功能或修改时应当如何测试与验证。文章以官方贡献文档 docs/CONTRIBUTING/Testing.md 为骨架,结合仓库中真实的自动化测试基础设施(util/test 目录下的测试框架、demo 程序与 190+ 条测试用例),讲解测试现状、测试思路、自动化测试的运行方式,以及如何新增一条测试。
一、官方文档对测试的定位:当前仍是"ad-hoc"验证为主
官方 Testing.md 明确说明了当前测试策略的现状:
目前,任何特性和变更的测试基本是即兴(ad-hoc)的。我一直在开发一套正式的测试套件,用于同时测试 API 捕获/重放支持以及分析功能。
翻译成实操要点就是两条:
- 改动后务必回归验证:在提交修改之前,围绕你改动所涉及的区域做针对性测试("test any changes you make around the area that you've tested")。例如你改了 Vulkan 驱动的捕获逻辑,就应该跑一遍 Vulkan 相关的 demo 和捕获流程。
- PR 阶段听从维护者建议:如果维护者对测试有特别建议,通常会在 Pull Request 中直接提出,按建议补测即可。
这条文档撰写于测试套件尚未成型的阶段,属于"过渡期指引"。但从当前仓库的目录结构看,文档中提到的"proper test suite"已经落地为 util/test 目录下的一套完整、可运行的自动化测试体系。因此,今天的贡献者实际上拥有两条测试路径:轻量的针对性手测(ad-hoc)与完整的自动化测试套件(util/test/run_tests.py)。
二、理解测试套件的整体架构
自动化测试体系位于仓库根目录下的 util/test,主要由四部分组成:
| 组成部分 | 路径 | 职责 |
|---|---|---|
| 测试入口 | util/test/run_tests.py | 命令行入口,解析参数、调度测试、汇总结果 |
| 测试框架 | util/test/rdtest | Python 测试框架:用例基类、日志、图像比较、远端服务等 |
| demo 程序 | util/test/demos | 一组自包含的小型 API 使用示例,按图形 API 分目录(D3D11、D3D12、GL、Vulkan) |
| 测试用例 | util/test/tests | 190+ 条 Python 测试用例,与 demo 一一对应 |
从源码结构看,整套系统的工作流是:
- demo 负责制造可复现的图形场景(如绘制一个简单三角形、创建各类纹理、触发特定的资源生命周期场景),并在运行时被 RenderDoc 注入捕获;
- 测试用例负责回放分析:打开捕获文件,通过
renderdocPython 模块(rd)驱动重放,校验管线状态、着色器输出、像素拾取值、网格数据等是否符合预期; - 测试框架负责调度与报告:每个用例在独立子进程中执行(防止崩溃拖垮整轮测试),失败时把 RenderDoc 日志、截图差异等产物写入 artifacts 目录。
2.1 用例基类:rdtest.TestCase
所有测试用例继承自 util/test/rdtest/testcase.py 中的TestCase基类。核心设计是两种互补的写法:
- 实现
get_capture()+check_capture():前者负责运行 demo 并产生捕获文件,后者负责对捕获内容做断言。默认的run()方法会依次调用两者(见 testcase.py#L745-L762); - 直接实现
run():完全自定义流程,适合需要自己打开多个捕获文件的复杂用例。
基类内置了大量断言工具,例如:
check_triangle():在输出缓冲区多个位置拾取像素,验证前景/背景颜色是否符合预期(testcase.py#L633-L666);check_pixel_value():像素拾取值比较,支持按纹理格式自动放宽 epsilon(8-bit 纹理用1/255、16-bit 用1/16384);check_mesh_data()/check_task_data():把重放得到的 VS 输出网格数据与参考数据逐顶点、逐属性比对;debug_vertex()/debug_pixel()/debug_thread():分别对顶点、像素、计算线程执行着色器调试,并把单步跟踪状态与预期逐指令比对。
以最简单的用例 Vulkan/VK_Simple_Triangle.py 为例,可以看到一个典型用例的完整形态:声明demos_test_name指向同名 demo,在check_capture()中取最后一个 action、把事件定位到该 action、用check_triangle()验证三角形渲染结果,再通过get_postvs()拿到顶点着色器输出,与预期的gl_Position、vertOut等参考值做精确比对。
2.2 demo 程序:测试的"素材工厂"
demo 程序是测试能否成立的前提——绝大多数测试依赖它生成捕获文件。它位于 util/test/demos,按 API 组织:d3d11/、d3d12/、gl/、vk/各有一个*_test.cpp入口和大量按场景拆分的 demo(如vk_draw_zoo.cpp、d3d12_rtas_zoo.cpp、gl_texture_zoo.cpp等)。
按 util/test/README.md 的说明,demos 的构建方式如下:
- Windows:直接打开 util/test/demos.sln 编译,无外部依赖;
- Linux / Apple:
cmake -Bbuild -Hdemos make -C buildLinux 需要libX11、libxcb、libX11-xcb(构建支持 GL 的 RenderDoc 本来就需要这些)。
需要特别注意一个"软依赖":如果 demos 没有链接 shaderc,运行时会调用外部的glslc把着色器编译为 SPIR-V,找不到glslc时部分测试会被自动禁用;目前只有 Windows 支持链接 shaderc(在$VULKAN_SDK环境变量指向的目录下自动查找)。
三、针对性手测:贡献者日常的回归验证方式
在提交修改前,官方文档要求你围绕改动区域做验证。结合仓库结构,可以给出具体的操作建议:
- 改了捕获/注入逻辑:用 renderdoccmd 或 qrenderdoc 对本地自有的测试程序做捕获,重点验证目标 API 下的帧捕获、资源枚举是否正常;
- 改了重放或分析逻辑:运行相关 API 的测试用例(见下节自动化测试),或直接打开已有捕获文件在 qrenderdoc 中人工检查管线状态、纹理查看器、网格查看器、着色器调试等面板;
- 改了 shader 分析:重点跑 shader debug 类用例(
Shader_Debug_Zoo、Shader_ISA、Shader_Editing),以及Pixel_History、Mesh_Zoo等分析类用例; - 测试用例自身的维护:如果你修改的功能已有对应测试,务必保证该测试仍然通过;如果测试用例本身不适用,在 PR 中说明理由。
同时建议遵守 README 中的告诫:不要制造"uber-demo",尽量让每个 demo 只做一件简单的事,这样测试失败时可以快速定位到具体特性。
四、运行自动化测试套件
4.1 前置条件
按 util/test/README.md 的说明:
- 使用与构建 RenderDoc 时相同的 Python 版本(Windows 仓库自带 python 3.6 左右);
- Windows 上 Python 的位数必须与 RenderDoc 构建一致(64 位构建对应 64 位 Python);
- Linux/Apple 需要把
demos_x64所在目录加入PATH,或用--demos-binary显式指定路径; - 先按上文构建好 demos 程序。
4.2 常用参数
运行run_tests.py的常用参数如下(详见 run_tests.py 参数解析部分):
| 参数 | 作用 |
|---|---|
--renderdoc <path> | 指定 renderdoc 库路径,会修改 OS 库搜索路径(Windows 下同时加入 DLL 搜索目录) |
--pyrenderdoc <path> | 指定renderdocPython 模块路径(如 Windows 下的x64/Development/pymodules) |
-l/--list | 仅列出可用测试并退出 |
-t/--test_include <regexp> | 只运行名称匹配该正则的测试,默认.*(全部运行) |
-x/--test_exclude <regexp> | 排除名称匹配该正则的测试 |
-j/--parallel <N> | 用 N 个进程并行运行测试(0或1表示串行) |
--test-timeout <秒> | 单个测试无输出时的超时时间,默认 90 秒 |
--data <path> | 参考数据目录,默认脚本旁的data/ |
--artifacts <path> | 输出产物目录,默认artifacts/(运行前会被清空) |
--temp <path> | 临时工作目录,默认tmp/(运行前会被清空) |
--data-extra <path> | 额外参考数据目录(大型捕获,不入库),默认data_extra/ |
--demos-binary <path> | 指定已构建的 demos 二进制路径 |
--demos-timeout <秒> | 期望 demos 运行完成的超时时间 |
--adb-device <设备> | 在指定的 ADB 设备上运行测试(此时--demos-binary应为 demo 的 APK) |
--debugger | 调试模式:测试在当前进程内运行,异常不被框架捕获,便于断点调试 |
注意:README 与源码都明确提示,tmp/与artifacts/目录在运行开始时会被整体清空(runner.py 中的清理逻辑),不要在其中存放任何重要数据。
一个典型的 Linux 运行示例:
python3 util/test/run_tests.py \ --renderdoc /path/to/librenderdoc.so \ --pyrenderdoc /path/to/pymodules \ --demos-binary /path/to/demos_x64 \ -t "VK_Simple_Triangle|GL_Simple_Triangle" \ -j 4Windows 示例(对应 README 中的用法):
python run_tests.py --renderdoc path\to\renderdoc\x64\Development ^ --pyrenderdoc path\to\renderdoc\x64\Development\pymodules4.3 结果解读
运行结束后,artifacts/目录中会生成自包含的结果日志output.log.html:它本质是纯文本日志,但内嵌了 JavaScript 与样式(testresults.css、testresults.js),用浏览器打开即可获得可读性良好的报告;所有依赖及图像对比产物都放在同一目录下,因此整个 artifacts 目录可以独立带走查看。
从 runner.py 的实现可以看到几处值得了解的行为:
- 进程隔离:每个测试默认在独立子进程中运行(
--internal_run_test内部参数),这样测试崩溃不会拖垮整轮运行(runner.py#L65-L79); - 自动处理 Vulkan layer 注册:如果检测到 Vulkan layer 未注册,会尝试自动注册,Windows 下必要时通过 UAC 提权(runner.py#L289-L329);
- 跳过机制:测试会先调用
check_support(),demo 未编译进二进制、平台不支持等情况会被标记为 skip 并记录原因,而不是失败(runner.py#L359-L380); - 汇总输出:结束时打印通过/失败/跳过统计,若存在失败用例则以退出码 1 结束(runner.py#L461-L479)。
五、如何新增一条测试
5.1 编写 demo(如果功能需要新的捕获场景)
在 util/test/demos 对应 API 目录下新建或复制一个现有 demo(例如复制vk_template.cpp),只实现一个简单的场景。若需要主程序注册该 demo,请参考main.cpp与同目录其他*_test.cpp的注册方式。
5.2 编写测试用例
在 util/test/tests 对应 API 目录下新建同名 Python 用例,复制现有用例并修改校验逻辑。README 的建议是:
demos 项目中包含辅助库,最好的起步方式就是复制一个现有测试再按需修改;避免 uber-demo,尽量只做一件简单的事。测试用例通常与 demo 一一对应,同样可以复制现有用例并加入自己的检查。
用例骨架(以VK_Simple_Triangle为模板):
import renderdoc as rd import rdtest class VK_My_Feature(rdtest.TestCase): demos_test_name = 'VK_My_Feature' # 对应 demos 中的测试名 demos_frame_cap = 5 # 捕获帧数上限 demos_frame_count = 1 # 要捕获的帧数 def check_capture(self): # 打开捕获后,用 self.controller 驱动重放并断言 # 例如 self.check_triangle(...)、self.check_pixel_value(...) pass5.3 新增参考图像(仅当需要图像比对时)
README 给出了新增参考图像的明确流程:
- 首次不带参考图像运行,框架会输出将要用于比对的图像;
- 用
pngcrush处理该图像(确保保留 RGBA 输出),以减小仓库体积; - 放入参考数据目录供后续比对。
需要图像比对的典型场景如check_final_backbuffer():它把最后一个 action 的 backbuffer 保存为 PNG,与参考图逐像素比对(testcase.py#L830-L847)。
5.4 运行与验证
用-t正则只跑你的新用例(如-t "VK_My_Feature"),确认通过后,再跑一次该 API 目录下的相关用例(如-t "VK_"),确认没有破坏既有功能。
六、测试套件覆盖的能力范围
当前仓库的测试体系已具备相当完整的覆盖面,可作为贡献者判断"改动应跑到哪些测试"的参考:
- 四套图形 API:D3D11、D3D12、OpenGL、Vulkan,各自拥有独立测试目录(util/test/tests/D3D11、D3D12、GL、Vulkan);
- 捕获/重放基础能力:空捕获(
Empty_Capture)、泄漏检查(Leak_Check)、资源生命周期(Resource_Lifetimes)、帧 0 校验(Frame0)等; - 分析功能:像素历史(
Pixel_History)、网格数据(Mesh_Zoo)、纹理/缓冲区(Texture_Zoo、Buffer_Truncation)、丢弃操作(Discard_Zoo)、覆盖层(Overlay_Test)等; - 着色器调试:
Shader_Debug_Zoo、Shader_ISA、Shader_Editing、Shader_Linkage_Zoo等,配合debug_vertex/debug_pixel做指令级单步比对; - 较新的图形特性:D3D12 的 Mesh Shader、VRS、光线追踪资源(
RTAS),Vulkan 的 Dynamic Rendering、Descriptor Buffer、Ray Query 等。
七、小结:贡献者的测试清单
综合官方文档与仓库现状,提交修改前建议按以下清单自检:
- 手测改动区域:围绕你修改的代码路径做一次真实捕获与重放验证;
- 跑相关自动化用例:用
-t正则选中与你改动相关的测试目录(如D3D12_、GL_、VK_、GL_Shader_Debug等),确保没有回归; - 新功能配套测试:涉及新功能时按第五章流程补充 demo 与用例,参考图像用 pngcrush 压缩后入库;
- 关注 PR 反馈:维护者对测试若有额外要求会在 PR 中提出,按建议补充即可。
通过"针对性手测 + 自动化测试套件"的组合,即使是变更范围横跨多个图形 API 的功能,也能在提交前获得足够可信的验证结果。
- 开发工具
- 调试器
- 图形学
- GPU
【免费下载链接】renderdoc
RenderDoc is a stand-alone graphics debugging tool.
相关推荐
Gitpod 手动测试套件(Ruruku 测试计划)完全指南:从发布验证到全功能回归
Gitpod 手动测试套件(Ruruku 测试计划)完全指南:从发布验证到全功能回归 Gitpod 在 dev/manual tests/ 目录下维护了一套基于
开发工具后端云原生自动化测试:Qwen3-1.7B-FP8功能与性能测试套件
自动化测试:Qwen3 1.7B FP8功能与性能测试套件 引言 在大语言模型(Large Language Model,LLM)部署和应用的实践中,自动化测试
大模型深度学习10分钟上手Whisper自动化测试:从单元测试到性能验证全指南
10分钟上手Whisper自动化测试:从单元测试到性能验证全指南 你是否还在为语音识别模型的测试效率低下而烦恼?是否遇到过模型升级后兼容性问题难以排查的情况?本
人工智能语音音频本地部署桌面应用
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考