目标

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定义

在这里插入图片描述

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐