学习使用 RenderDoc 的 Python API

本文介绍了如何在RenderDoc界面中利用Python API进行更深入的捕获控制。首先,通过PythonShell运行脚本来加载捕获文件,然后详细解释了ReplayManager、BlockInvoke和ReplayController的用法,特别是ReplayController的GetDrawcalls方法,用于遍历和打印所有根级别的绘制调用信息。此外,还提供了官方范例脚本【Iteratedrawcalltree】的解析和简化版代码,帮助读者理解如何遍历和分析绘制调用树。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目标

RenderDoc有一套PythonAPI。不过正如官方文档所说:

This API is not necessary to use RenderDoc by default, but if you would like more control or custom triggering of captures this API can provide the mechanism to do so.

默认情况下,使用RenderDoc不需要此API,但如果你想对captures进行更多的控制,或者自定义的trigger,则API可以提供这样的机制。

本篇的目标是尝试在RenderDoc界面上使用PythonAPI,并尝试跑一个简单的范例脚本。

尝试使用 Python API

步骤如下:

  1. 在菜单栏中选择Window中的Python Shell
  2. 选择 Interactive Python Shell 分栏中的Run Scripts分栏
  3. 在写完脚本之后,点击Run即可运行脚本

在这里插入图片描述


例如,下面脚本将加载一个capture:

#capture的路径:
filepath = 'D:/Test/test1.rdc'

#加载这个capture
pyrenderdoc.LoadCapture(filepath, renderdoc.ReplayOptions(), filepath, False, True)

在这里插入图片描述

尝试运行官方范例脚本

下面尝试运行官方文档中的范例脚本【Iterate drawcall tree】(代码见附录)
在这里插入图片描述
运行后可在“Output面板”中看到输出的信息:
在这里插入图片描述

以上例为基础讨论

下面,以上例为基础,讨论下PythonAPI的基础用法。不过清除些暂时无用的代码,并做些简化。

0. 环境

正如注释中所说:

# The 'pyrenderdoc' object is the current CaptureContext instance.
# The 'renderdoc' and 'qrenderdoc' modules are available.

pyrenderdoc是自动添加到当前环境中的CaptureContext实例。
renderdocqrenderdoc是自动加载的模块。
在这里插入图片描述

1. 获得 ReplayManager

使用CaptureContextReplay()函数可以获得一个ReplayManager对象:
在这里插入图片描述
例如:
在这里插入图片描述


在这里插入图片描述
ReplayManager用于访问UI中还没有抽象出来的底层信息。

2. ReplayManager的BlockInvoke

个人理解,ReplayManagerBlockInvoke函数是将一个回调函数插入到遍历的过程中(此处不确定,待日后研究)
在这里插入图片描述
而回调函数可以接收一个ReplayController对象
测试脚本:

# Replay时的回调函数:
def Callback(controller):
	print(controller)

pyrenderdoc.Replay().BlockInvoke(Callback)

在这里插入图片描述


在这里插入图片描述
ReplayController是访问一个capture和当前状态的信息的基础接口,也可以控制Replay和可用的分析功能。

3. ReplayController的GetDrawcalls

ReplayController的函数GetDrawcalls函数将遍历并收集当前capture中的所有“根级别”的drawcall:
在这里插入图片描述
返回值是DrawCallDescription的列表。(这个类型的成员较多,我放到了附录中)
在这里只打印其eventIdname

for d in controller.GetDrawcalls():
	#打印其ID与名字:
	print('%d: %s' % (d.eventId, d.name))
完整代码

下面就是简化后的脚本代码:

# Replay时的回调函数:
def Callback(controller):
    #遍历所有的“根级别”的DrawCall
	for d in controller.GetDrawcalls():
        #打印其ID与名字:
		print('%d: %s' % (d.eventId, d.name))

pyrenderdoc.Replay().BlockInvoke(Callback)

在这里插入图片描述

附录:官方文档中的范例脚本【Iterate drawcall tree

import sys

# Import renderdoc if not already imported (e.g. in the UI)
if 'renderdoc' not in sys.modules and '_renderdoc' not in sys.modules:
	import renderdoc

# Alias renderdoc for legibility
rd = renderdoc

# Define a recursive function for iterating over draws
def iterDraw(d, indent = ''):
	# Print this drawcall
	print('%s%d: %s' % (indent, d.eventId, d.name))

	# Iterate over the draw's children
	for d in d.children:
		iterDraw(d, indent + '    ')

def sampleCode(controller):
	# Iterate over all of the root drawcalls
	for d in controller.GetDrawcalls():
		iterDraw(d)

	# Start iterating from the first real draw as a child of markers
	draw = controller.GetDrawcalls()[0]

	while len(draw.children) > 0:
		draw = draw.children[0]

	# Counter for which pass we're in
	passnum = 0
	# Counter for how many draws are in the pass
	passcontents = 0
	# Whether we've started seeing draws in the pass - i.e. we're past any
	# starting clear calls that may be batched together
	inpass = False

	print("Pass #0 starts with %d: %s" % (draw.eventId, draw.name))

	while draw != None:
		# When we encounter a clear
		if draw.flags & rd.DrawFlags.Clear:
			if inpass:
				print("Pass #%d contained %d draws" % (passnum, passcontents))
				passnum += 1
				print("Pass #%d starts with %d: %s" % (passnum, draw.eventId, draw.name))
				passcontents = 0
				inpass = False
		else:
			passcontents += 1
			inpass = True

		# Advance to the next drawcall
		draw = draw.next
		if draw is None:
			break

	if inpass:
		print("Pass #%d contained %d draws" % (passnum, passcontents))

def loadCapture(filename):
	# Open a capture file handle
	cap = rd.OpenCaptureFile()

	# Open a particular file - see also OpenBuffer to load from memory
	status = cap.OpenFile(filename, '', None)

	# Make sure the file opened successfully
	if status != rd.ReplayStatus.Succeeded:
		raise RuntimeError("Couldn't open file: " + str(status))

	# Make sure we can replay
	if not cap.LocalReplaySupport():
		raise RuntimeError("Capture cannot be replayed")

	# Initialise the replay
	status,controller = cap.OpenCapture(rd.ReplayOptions(), None)

	if status != rd.ReplayStatus.Succeeded:
		raise RuntimeError("Couldn't initialise replay: " + str(status))

	return cap,controller

if 'pyrenderdoc' in globals():
	pyrenderdoc.Replay().BlockInvoke(sampleCode)
else:
	rd.InitialiseReplay(rd.GlobalEnvironment(), [])

	if len(sys.argv) <= 1:
		print('Usage: python3 {} filename.rdc'.format(sys.argv[0]))
		sys.exit(0)

	cap,controller = loadCapture(sys.argv[1])

	sampleCode(controller)

	controller.Shutdown()
	cap.Shutdown()

	rd.ShutdownReplay()

附录:DrawCallDescription定义

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值