学习使用 RenderDoc 的 Python API
目标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 s
目标
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
步骤如下:
- 在菜单栏中选择Window中的Python Shell
- 选择 Interactive Python Shell 分栏中的Run Scripts分栏
- 在写完脚本之后,点击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
实例。
而renderdoc
和qrenderdoc
是自动加载的模块。
1. 获得 ReplayManager
使用CaptureContext
的Replay()
函数可以获得一个ReplayManager
对象:
例如:
ReplayManager
用于访问UI中还没有抽象出来的底层信息。
2. ReplayManager的BlockInvoke
个人理解,ReplayManager
的BlockInvoke
函数是将一个回调函数插入到遍历的过程中(此处不确定,待日后研究)
而回调函数可以接收一个ReplayController
对象
测试脚本:
# Replay时的回调函数:
def Callback(controller):
print(controller)
pyrenderdoc.Replay().BlockInvoke(Callback)
ReplayController
是访问一个capture和当前状态的信息的基础接口,也可以控制Replay和可用的分析功能。
3. ReplayController的GetDrawcalls
ReplayController
的函数GetDrawcalls
函数将遍历并收集当前capture中的所有“根级别”的drawcall:
返回值是DrawCallDescription
的列表。(这个类型的成员较多,我放到了附录中)
在这里只打印其eventId
和name
:
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定义
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)