开发工具调试器图形学GPU【免费下载链接】renderdocRenderDoc is a stand-alone graphics debugging tool.项目地址https://gitcode.com/gh_mirrors/re/renderdoc点击查看免费下载本篇技术指南围绕 RenderDoc 的捕获文件.rdc访问机制展开系统讲解renderdocPython 模块中CaptureAccess与CaptureFile两套接口的定位与用法、打开文件与启动回放的完整流程、文件格式与转换能力以及通过 Section 读写和 ASCII Section 手工拼接两种方式为捕获附加自定义数据的具体方法。读完本文你将掌握在不依赖 RenderDoc UI 的情况下用脚本独立完成捕获文件的打开、元数据查询、格式转换、自定义数据注入与回放启动的完整实战方案。.rdc 捕获文件是什么RenderDoc 在应用运行期间触发捕获后会将一帧或多帧的完整 GPU 执行数据保存为.rdc文件。这个文件包含了回放该捕获帧所需的全部数据同时也包含元数据与附加信息捕获使用的图形 API即源码文档中称为 driver 的部分及其版本信息捕获产生平台的机器标识machine ident帧捕获正文frame capture数据可选的无损缩略图extended thumbnail可选的调用栈callstack及其模块信息用户或工具附加的自定义 Section。从源码层面看.rdc文件是一个结构简单但组织清晰的容器RDCFile实现位于 rdcfile.cpp文件以R,D,O,C四字符魔数MAGIC_HEADER见 rdcfile.cpp#L142开头随后是文件头magic、版本号、版本字符串、可选的二进制缩略图、捕获元数据CaptureMetaData包含machineIdent与driverID、时间基准CaptureTimeBase包含timeBase与timeFreq最后是一系列紧挨排列的 Section详见 rdcfile.cpp#L80-L138 中完整格式注释。正是由于容器结构简单.rdc文件可以由脚本管理既能通过官方 Python API 附加自定义信息也能用最朴素的方式——把文本格式的 Section 直接拼接到文件末尾即下文ASCII Sections一节。这套文件访问能力也正是 RenderDoc 在脱离 UI 情况下启动回放与分析的基础当你不使用 RenderDoc 图形界面而是通过 python_module 中描述的 Replay API 完全独立地驱动回放时首先接触的就是这里讲的捕获文件接口。访问捕获文件的两大接口CaptureAccess 与 CaptureFile捕获文件由两个主要接口管理见 renderdoc_replay.h#L1243-L1247 的接口声明接口定位适用场景renderdoc.CaptureAccess功能受限的子集可通过网络连接使用不要求本地磁盘上有该文件renderdoc.CaptureFile功能更完整必须在本地可访问的文件上初始化继承自CaptureAccess并追加本地文件能力具体来说CaptureAccess支持 Section 的枚举、查找与读写、可用 GPU 列表查询等基础能力GetSectionCount、FindSectionByName、FindSectionByType、GetSectionProperties、GetSectionContents、WriteSection、GetAvailableGPUs而CaptureFile对应 C 侧ICaptureFile见 renderdoc_replay.h#L1583-L1795在此基础上增加了OpenFile/OpenBuffer从磁盘文件或内存缓冲区初始化Convert格式转换与导出GetCaptureFileFormats查询支持的格式LocalReplaySupport本地回放支持程度RecordedMachineIdent/TimestampBase/TimestampFrequency机器与时间信息GetThumbnail读取缩略图GetStructuredData/SetStructuredData结构化数据读取与注入OpenCapture本地启动回放。注本文以本地CaptureFile为主线展开并在需要时标注哪些功能可以通过远程CaptureAccess使用。RenderDoc 的网络回放功能详见 remote_replay。从零创建一个 CaptureFile创建CaptureFile的入口是renderdoc.OpenCaptureFile()对应 C 接口RENDERDOC_OpenCaptureFile见 renderdoc_replay.h#L1959。这个句柄归 Python 所有使用完毕后必须调用CaptureFile.Shutdown()显式销毁import renderdoc as rd # 创建句柄由 python 持有所有权 cap rd.OpenCaptureFile() # ... 打开文件、读取数据、回放 ... # 使用完毕后显式关闭句柄 cap.Shutdown()Shutdown()会关闭文件句柄并释放其持有的资源。如果跳过这一步句柄会一直持有对文件或内存缓冲的引用甚至可能因未释放文件锁而导致后续操作失败。在 UI 脚本中获取当前捕获如果你运行在 RenderDoc UI 内的 Python 脚本中可以直接访问 UI 当前加载的捕获qrenderdoc.ReplayManager.GetCaptureAccess()获取当前捕获的CaptureAccess无论本地还是远程打开都可用qrenderdoc.ReplayManager.GetCaptureFile()获取当前捕获的CaptureFile。注意如果捕获是在远程打开的此方法会返回None因为本地并没有该文件。import qrenderdoc as qrd replay qrd.ReplayManager.Get() # 任何情况下都可用 access replay.GetCaptureAccess() # 仅当捕获文件在本地打开时返回 CaptureFile远程打开时为 None cap replay.GetCaptureFile()此外这两个接口必须仅在 replay thread 上访问参见 threading 中关于pythreading的说明。Replay API 的线程模型要求所有回放相关调用在专门的回放线程中执行UI 脚本应通过qrenderdoc.ReplayManager.BlockInvoke等机制将访问调度到该线程。打开捕获文件OpenFile 与进度回调创建CaptureFile后调用OpenFile(filename, filetype, progress)打开文件import renderdoc as rd cap rd.OpenCaptureFile() def progress_cb(p): print(Opening... %d%% % int(p * 100)) result cap.OpenFile(frame123.rdc, , progress_cb) if result ! rd.ResultCode.Succeeded: print(Failed to open: %s % result) else: print(Opened successfully)OpenFile的关键语义对应 renderdoc_replay.h#L1591-L1610filename要打开的.rdc文件路径filetype输入格式。绝大多数情况下传即可——rdc是始终保证受支持的格式当filetype为空或无法识别时都会按rdc处理progress可选进度回调打开过程中尤其发生格式导入时会被间歇调用。回调签名须匹配rd.ProgressCallback接收一个 0~1 的float。另外还有OpenBuffer(buffer, filetype, progress)变体允许从内存缓冲区初始化句柄适用于不想解析整个文件或数据已在内存中的场景见 renderdoc_replay.h#L1612-L1628。打开文件后的磁盘锁OpenFile成功后RenderDoc 会对磁盘上的文件持有独占锁这使得用户无法在文件打开期间复制它。如果需要复制应使用CopyFileTo(newpath)它会把磁盘文件复制到新位置新文件加锁、旧文件解锁以便必要时删除而原捕获句柄不受影响见 renderdoc_replay.h#L1630-L1642。打开捕获进行回放OpenCapture 与生命周期约束拿到CaptureFile后可以用OpenCapture(opts, progress)启动回放成功时返回ReplayController对应 renderdoc_replay.h#L1737-L1755import renderdoc as rd cap rd.OpenCaptureFile() if cap.OpenFile(frame123.rdc, , None) ! rd.ResultCode.Succeeded: raise RuntimeError(open failed) # 使用默认回放选项启动回放返回 (ResultDetails, ReplayController) status, controller cap.OpenCapture(rd.ReplayOptions(), None) if status rd.ResultCode.Succeeded: print(Replay ready, driver: %s % controller.GetDriverName()) # ---- 在这里进行帧回放、状态查询、着色器调试等分析 ---- # 先关闭控制器再关闭捕获文件 controller.Shutdown() else: print(Replay failed: %s % status) cap.Shutdown()生命周期上有一个必须遵守的顺序CaptureFile在ReplayController使用期间必须保持打开状态因此你应该先完成分析并关闭控制器再关闭捕获文件。ReplayOptions用于控制回放方式例如强制在特定 GPU 上回放结合CaptureAccess.GetAvailableGPUs()获取的 GPU 列表等。注意OpenCapture仅支持以原生rdc格式打开的句柄其他格式打开的文件会直接失败见 renderdoc_replay.h#L1737-L1738。远程场景下则由IRemoteServer.OpenCapture(proxyid, filename, opts, progress)完成远程打开、本地代理渲染且必须用CloseCapture而不是Shutdown来正确清理本地代理见 renderdoc_replay.h#L1542-L1574。捕获文件格式rdc 与其他格式的转换绝大多数情况下OpenFile打开的都是标准.rdc文件此时filetype应传rdc或空字符串。RenderDoc 也支持其他格式但导入支持非常有限——导入要求格式包含回放所需的全部信息相对而言导出Convert更有实用价值因为导出可以只包含数据的受限子集。import renderdoc as rd cap rd.OpenCaptureFile() cap.OpenFile(frame123.rdc, , None) # 查询所有支持的格式及其能力 for fmt in cap.GetCaptureFileFormats(): print(ext%s name%s desc%s requiresBuffers%s open%s convert%s % ( fmt.extension, fmt.name, fmt.description, fmt.requiresBuffers, fmt.openSupported, fmt.convertSupported)) # 将当前文件导出为指定格式 res cap.Convert(frame123_out.xxx, xxx, None, None) cap.Shutdown()GetCaptureFileFormats()返回的CaptureFileFormat定义见 control_types.h#L1227字段含义如下字段含义extension格式扩展名如rdcname格式名称description格式描述requiresBuffers转换该格式是否需要缓冲区数据与结构化数据导出相关openSupported是否支持从该格式导入打开convertSupported是否支持导出到该格式Convert(filename, filetype, file, progress)还接受一个可选的SDFile参数当目标格式不需要缓冲区requiresBuffers False且你已经有一个携带结构化数据的ReplayController时可以传入已有的SDFile避免重新加载文件传None则内部自行获取结构化数据。捕获数据轻量打开与元数据查询打开文件是一个非常轻量的操作它只解码容器、加载捕获元数据不会发起任何图形 API 调用、不会开始回放也不会把大量数据载入内存。因此适合在脚本中快速对一批捕获做体检。打开后可以查询的元数据包括import renderdoc as rd cap rd.OpenCaptureFile() cap.OpenFile(frame123.rdc, , None) # 使用的图形 APIdriver如 D3D11、OpenGL、Vulkan print(Driver:, cap.DriverName()) # 本地是否支持回放返回 rd.ReplaySupport print(Local replay support:, cap.LocalReplaySupport()) # 记录该捕获的机器标识平台x86 / Android 等与位数32/64 位 print(Machine ident:, cap.RecordedMachineIdent()) # 缩略图支持 JPG/PNG/TGA/BMPmaxsize 限制最大宽高 thumb cap.GetThumbnail(rd.FileType.PNG, 512) print(Thumbnail %dx%d, %d bytes % (thumb.width, thumb.height, len(thumb.data))) # 时间基准所有时间戳相对的基础值与频率 print(Timestamp base:, cap.TimestampBase()) print(Timestamp freq:, cap.TimestampFrequency()) cap.Shutdown()DriverName()返回创建该捕获的驱动名称字符串见 renderdoc_replay.h#L1347-L1352LocalReplaySupport()查询本地对该捕获的回放支持程度见 renderdoc_replay.h#L1674-L1682。如果文件是以非rdc格式打开的该查询恒返回不支持回放RecordedMachineIdent()机器标识字符串包含平台与位数信息如 x86 或 Android、32 位或 64 位。在显示该捕获不兼容之类的用户提示时非常有用见 renderdoc_replay.h#L1684-L1689GetThumbnail(type, maxsize)返回嵌入缩略图type仅支持FileType.JPG / PNG / TGA / BMPmaxsize为最大宽高超出则缩放见 renderdoc_replay.h#L1779-L1790TimestampBase()/TimestampFrequency()时间戳基准值与换算频率时间戳除以频率即可换算为微秒见 renderdoc_replay.h#L1691-L1705。请求结构化数据SDFile除了元数据还可以请求捕获的结构化数据SDFile。这与回放是完全不同的两个操作请求结构化数据时RenderDoc 会解码捕获内的序列化数据但不会发起任何图形 API 调用。详细机制见 structured_data。import renderdoc as rd cap rd.OpenCaptureFile() cap.OpenFile(frame123.rdc, , None) sd cap.GetStructuredData() # 返回 rd.SDFile print(Structured data chunk count:, len(sd.chunks)) cap.Shutdown()关键特性可跨平台只要该构建的 RenderDoc 支持目标 API就能加载结构化数据。例如 Linux 上因完全没有 D3D 支持而无法加载 D3D 捕获的结构化数据但 Windows 机器可以加载 Android Vulkan 捕获的结构化数据即使它无法回放该捕获重量级操作请求结构化数据需要读取并解码整个捕获比单纯打开文件重得多返回的SDFile包含缓冲区buffers因此与任何requiresBuffers为真CaptureFileFormat.requiresBuffers的导出格式兼容可直接用于ConvertSDFile的生命周期与捕获句柄绑定句柄销毁后不可再使用见 renderdoc_replay.h#L1757-L1765。反向地SetStructuredData(sd)允许用生成的SDFile填充捕获数据会被内部复制配合SetMetadata(...)可以纯内存地构造一个捕获文件再通过Convert保存到磁盘见 renderdoc_replay.h#L1707-L1777。捕获 Sections容器中的信息单元rdc容器文件由一个小文件头加任意数量的 Section组成。默认情况下至少包含帧捕获本身对应的 Section通常还包含一个扩展无损缩略图如果捕获了调用栈还会有一个平台相关的 Section 记录已加载模块信息供后续调用栈解析使用。SectionType官方预定义 Section已知的官方 Section 由SectionType枚举定义见 replay_enums.h#L120-L137每个枚举值同时对应一个字符串路径如帧捕获为renderdoc/internal/framecapture枚举值说明Unknown未知/自定义类型通常为 0FrameCapture帧捕获正文路径renderdoc/internal/framecaptureResolveDatabase调用栈解析数据库Bookmarks书签NotesUI 笔记路径renderdoc/ui/notesResourceRenames资源重命名记录AMDRGPProfileAMD RGP 性能分析数据ExtendedThumbnail扩展无损缩略图EmbeddedLogfile内嵌日志文件EditedShaders编辑过的着色器D3D12Core/D3D12SDKLayersD3D12 相关模块信息EmbeddedExternalFiles内嵌的外部依赖文件如着色器调试文件Section 的枚举与访问既可以通过CaptureAccess也可以通过CaptureFile完成两个接口还都支持新增或覆写Section。读取与写入自定义 Section自定义数据通过以下 API 读写import renderdoc as rd cap rd.OpenCaptureFile() cap.OpenFile(frame123.rdc, , None) # 枚举所有 section for i in range(cap.GetSectionCount()): props cap.GetSectionProperties(i) print(Section %d: name%s type%s version%d flags%s % ( i, props.name, props.type, props.version, props.flags)) data cap.GetSectionContents(i) print( contents: %d bytes % len(data)) # 按名字查找返回索引找不到为 -1 idx cap.FindSectionByName(mytool/customdata) # 按类型查找返回索引找不到为 -1 idx2 cap.FindSectionByType(rd.SectionType.Notes) # 写入/覆写一个自定义 section props rd.SectionProperties() props.name mytool/customdata props.type rd.SectionType.Unknown props.version 1 res cap.WriteSection(props, bmy custom payload) if res ! rd.ResultCode.Succeeded: print(WriteSection failed: %s % res) cap.Shutdown()接口细节见 renderdoc_replay.h#L1257-L1309GetSectionCount()Section 总数FindSectionByName(name)/FindSectionByType(type)按名字或类型定位索引找不到返回-1。索引不应被缓存因为写入 Section 可能重排索引顺序GetSectionProperties(index)返回SectionProperties描述该 SectionGetSectionContents(index)返回该 Section 的原始字节内容bytesWriteSection(props, contents)写入新 Section。若已存在相同类型或名字的 Section会被覆写同一捕获中不允许两个 Section 共享相同类型或名字见 rdcfile.cpp#L110-L111 的格式约束。SectionProperties结构见 data_types.h#L199-L238包含字段含义nameSection 名字字符串typeSectionType未知/自定义为UnknownflagsSectionFlags描述存储方式如是否压缩versionSection 版本号含义由类型自行定义uncompressedSize解压后的数据字节数compressedSize磁盘上压缩后的字节数命名规范重要自定义 Section 的名字应避免使用renderdoc/前缀。Section 名可以是任意字符串请使用自己的命名空间如mytool/...、company/project/...以免与官方内部 Section 冲突。ASCII Sections用纯文本手工追加数据为了给原始脚本提供更便捷的访问途径RenderDoc 支持把文本文件直接拼接到.rdc文件末尾来添加 Section——这样即便不调用 Python API也能以非常有限的方式向捕获注入数据。⚠️高级特性警告这是一个advanced功能操作时必须非常小心。任何格式错误都可能使捕获文件完全无法打开除非确实需要这么做否则请优先考虑更安全的方案即使用WriteSectionAPI。ASCII Section 的格式一个 ASCII Section 的头部格式如下示例中带注释但真实格式必须不含多余空白与注释A # 字面字符 A表示这是一个 ASCII Section 119 # 内容长度字节数十进制数字 4 # SectionType 的数值自定义 section 通常为 0 1 # 本 section 的版本号用于向后兼容 renderdoc/ui/notes # section 的名字 # 名字之后必须有一个换行符对照 rdcfile.cpp#L92-L113 的容器格式定义每个 ASCII Section 的头部逐行含义为一个字面字符AASCII 0x41标识该 Section 为 ASCII 格式便于脚本/手工直接拼接一个十进制数字字符串表示紧跟其后的 section 数据长度字节数一个十进制数字字符串表示该 Section 的SectionType数值——自定义 Section 通常是0Unknown一个十进制数字字符串表示 section 版本号Section 名字UTF-8 字符串后面必须紧跟一个换行符。头部可以用文本编辑器或任何脚本手工构造。如上文所说第二行的长度字节数应该由脚本自动计算生成而不是手工维护。头部之后就是 Section 内容内容可以是任意数据。官方 UI 的 notes Section 是 JSON 格式的其中comments键对应要显示的字符串{ comments: These are some notes! there isnt really much to put here, except to demonstrate an ASCII section. }拼接步骤与验证把上面的头部去掉注释和空白再拼上 JSON 内容整体追加到一个已有.rdc文件的末尾# 1. 构造 ASCII section 文本文件头部 内容无注释无多余空白 # 2. 追加到 .rdc 末尾 cat ascii_section.txt frame123.rdc之后用 RenderDoc UI 打开该捕获即可在 UI 的笔记视图中看到 JSON 中comments字段提供的文字内容。这种做法的典型用途就是为捕获批量添加可被 UI 展示的备注信息。从实现上看解析器对 ASCII Section 的校验相当严格见 rdcfile.cpp#L454-L509换行序列必须是\n允许\r\n单独\r视为非法返回FileCorrupted长度、类型、版本逐行按十进制解析非法字符会污染解析结果解析失败会报ResultCode::FileCorrupted文件将被判定为损坏而无法打开——这正是文档反复警告格式错误后果严重的原因。二进制 Section 与 ASCII Section 的结构差异为便于理解容器设计这里对比两类 Section 的磁盘布局完整定义见 rdcfile.cpp#L88-L133ASCII SectionA标志 换行分隔的四行十进制字段长度/类型/版本/名字 换行 原始数据二进制 Section\0标志 3 字节保留位 uint32类型 uint64压缩长度 uint64解压长度 uint64版本 uint32flags uint32名字长度 UTF-8 名字 数据。二进制 Section 支持压缩SectionFlags中记录数据长度在磁盘上和解压后可能不同ASCII Section 则不支持压缩、布局固定为纯文本这也是它能被手工拼接的原因。完整示例脚本化打开 → 查询 → 加注 → 回放流水线结合以上内容一个典型的脚本化捕获处理流水线如下import renderdoc as rd def handle_capture(path): cap rd.OpenCaptureFile() try: # 1) 轻量打开仅解析容器与元数据 if cap.OpenFile(path, , None) ! rd.ResultCode.Succeeded: return None # 2) 元数据查询 print(Driver:, cap.DriverName()) print(Replay support locally:, cap.LocalReplaySupport()) print(Recorded on:, cap.RecordedMachineIdent()) # 3) 写入自定义追踪信息覆写同名 section props rd.SectionProperties() props.name mytool/processed props.type rd.SectionType.Unknown props.version 1 cap.WriteSection(props, bprocessed by my pipeline) # 4) 启动回放进行分析成功后 controller 独立于 cap 存在 status, controller cap.OpenCapture(rd.ReplayOptions(), None) if status ! rd.ResultCode.Succeeded: print(Replay failed:, status) return None # 在这里使用 controller 分析帧...略 controller.Shutdown() # 先关控制器 return controller finally: cap.Shutdown() # 后关捕获文件句柄 handle_capture(frame123.rdc)小结.rdc文件是 RenderDoc 捕获的容器格式包含帧捕获正文、缩略图、调用栈信息及任意自定义 Section其底层布局定义于 rdcfile.cppCaptureAccess提供跨网络的受限能力子集CaptureFile则在本地文件上提供完整能力打开、转换、结构化数据、回放两者都必须只在 replay thread 上访问OpenFile是轻量操作只读元数据不发图形 API 调用OpenCapture才真正启动回放且需先关ReplayController再关CaptureFile自定义数据可以通过WriteSection/GetSectionContents以编程方式读写也可通过将纯文本 ASCII Section 追加到文件末尾实现零 API注入但后者必须严格遵循格式否则会损坏捕获文件更深入的主题可继续阅读 python_module独立驱动 Replay API、remote_replay网络回放、structured_data结构化数据与 threading线程模型。赞分享开发工具调试器图形学GPU【免费下载链接】renderdocRenderDoc is a stand-alone graphics debugging tool.项目地址https://gitcode.com/gh_mirrors/re/renderdoc点击查看免费下载相关推荐RenderDoc 捕获注释Capture Comments完全指南为 .rdc 捕获文件添加持久化文本备注RenderDoc 捕获注释Capture Comments完全指南为 .rdc 捕获文件添加持久化文本备注 本指南聚焦 RenderDoc 图形调试工具开发工具调试器图形学GPU如何将普通小爱音箱升级为AI智能助手MiGPT完整指南如何将普通小爱音箱升级为AI智能助手MiGPT完整指南 还在为小爱音箱的人工智障表现而烦恼吗你是否渴望让家里的智能音箱真正理解你的需求成为能够深度对话人工智能AI 应用语音智能家居交互助手ContextMenu未来路线图iOS 17适配与新功能展望ContextMenu未来路线图iOS 17适配与新功能展望 ContextMenu是一款受Things 3启发的iOS上下文菜单UI组件当前版本为0.5创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考