Iterate Action tree

In this example we will show how to iterate over actions.

The actions returned from GetRootActions() are actions or marker regions at the root level - with no parent marker region. There are multiple ways to iterate through the list of actions.

The first way illustrated in this sample is to walk the tree using children, which contains the list of child actions at any point in the tree. There is also parent which points to the parent action.

The second is to use previous and next, which point to the previous and next action respectively in a linear fashion, regardless of nesting depth.

In the example we use this iteration to determine the number of passes, using the action flags to denote the start of each pass by a starting clear call.

Example Source

Download the example script.

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 actions
def iterAction(d, indent = ''):
	# Print this action
	print('%s%d: %s' % (indent, d.eventId, d.GetName(controller.GetStructuredFile())))

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

def sampleCode(controller):
	# Iterate over all of the root actions
	for d in controller.GetRootActions():
		iterAction(d)

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

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

	# Counter for which pass we're in
	passnum = 0
	# Counter for how many actions are in the pass
	passcontents = 0
	# Whether we've started seeing actions 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" % (action.eventId, action.GetName(controller.GetStructuredFile())))

	while action != None:
		# When we encounter a clear
		if action.flags & rd.ActionFlags.Clear:
			if inpass:
				print("Pass #%d contained %d actions" % (passnum, passcontents))
				passnum += 1
				print("Pass #%d starts with %d: %s" % (passnum, action.eventId, action.GetName(controller.GetStructuredFile())))
				passcontents = 0
				inpass = False
		else:
			passcontents += 1
			inpass = True

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

	if inpass:
		print("Pass #%d contained %d actions" % (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()

Sample output:

1: Scene
2: ID3D11DeviceContext::ClearRenderTargetView()
3: ID3D11DeviceContext::ClearDepthStencilView()
9: ID3D11DeviceContext::ClearRenderTargetView()
10: ID3D11DeviceContext::ClearRenderTargetView()
11: ID3D11DeviceContext::ClearDepthStencilView()
13: GBuffer
        25: Floor
        28: ID3D11DeviceContext::DrawIndexed()
        29: empty label
                30: ID3DUserDefinedAnnotation::EndEvent()
        40: Base
        43: ID3D11DeviceContext::DrawIndexed()
        53: Center sphere
        56: ID3D11DeviceContext::DrawIndexed()
        66: Cone
        69: ID3D11DeviceContext::DrawIndexed()
        79: Cone
        82: ID3D11DeviceContext::DrawIndexed()
        92: Cone
        95: ID3D11DeviceContext::DrawIndexed()
        105: Cone
        108: ID3D11DeviceContext::DrawIndexed()
        118: Cone
        121: ID3D11DeviceContext::DrawIndexed()
        131: Cone
        134: ID3D11DeviceContext::DrawIndexed()
        144: Cone
        147: ID3D11DeviceContext::DrawIndexed()
        157: Cone
        160: ID3D11DeviceContext::DrawIndexed()
        170: Cone
        173: ID3D11DeviceContext::DrawIndexed()
        183: Cone
        186: ID3D11DeviceContext::DrawIndexed()
        196: Sphere
        199: ID3D11DeviceContext::DrawIndexed()
        209: Sphere
        212: ID3D11DeviceContext::DrawIndexed()
        222: Sphere
        225: ID3D11DeviceContext::DrawIndexed()
        235: Sphere
        238: ID3D11DeviceContext::DrawIndexed()
        248: Sphere
        251: ID3D11DeviceContext::DrawIndexed()
        261: Sphere
        264: ID3D11DeviceContext::DrawIndexed()
        274: Sphere
        277: ID3D11DeviceContext::DrawIndexed()
        287: Sphere
        290: ID3D11DeviceContext::DrawIndexed()
        300: Sphere
        303: ID3D11DeviceContext::DrawIndexed()
        313: Sphere
        316: ID3D11DeviceContext::DrawIndexed()
        317: ID3DUserDefinedAnnotation::EndEvent()
319: ID3D11DeviceContext::ClearDepthStencilView()
321: Shadowmap
        330: Floor
        333: ID3D11DeviceContext::DrawIndexed()
        334: empty label
                335: ID3DUserDefinedAnnotation::EndEvent()
        342: Base
        345: ID3D11DeviceContext::DrawIndexed()
        352: Center sphere
        355: ID3D11DeviceContext::DrawIndexed()
        362: Cone
        365: ID3D11DeviceContext::DrawIndexed()
        372: Cone
        375: ID3D11DeviceContext::DrawIndexed()
        382: Cone
        385: ID3D11DeviceContext::DrawIndexed()
        392: Cone
        395: ID3D11DeviceContext::DrawIndexed()
        402: Cone
        405: ID3D11DeviceContext::DrawIndexed()
        412: Cone
        415: ID3D11DeviceContext::DrawIndexed()
        422: Cone
        425: ID3D11DeviceContext::DrawIndexed()
        432: Cone
        435: ID3D11DeviceContext::DrawIndexed()
        442: Cone
        445: ID3D11DeviceContext::DrawIndexed()
        452: Cone
        455: ID3D11DeviceContext::DrawIndexed()
        462: Sphere
        465: ID3D11DeviceContext::DrawIndexed()
        472: Sphere
        475: ID3D11DeviceContext::DrawIndexed()
        482: Sphere
        485: ID3D11DeviceContext::DrawIndexed()
        492: Sphere
        495: ID3D11DeviceContext::DrawIndexed()
        502: Sphere
        505: ID3D11DeviceContext::DrawIndexed()
        512: Sphere
        515: ID3D11DeviceContext::DrawIndexed()
        522: Sphere
        525: ID3D11DeviceContext::DrawIndexed()
        532: Sphere
        535: ID3D11DeviceContext::DrawIndexed()
        542: Sphere
        545: ID3D11DeviceContext::DrawIndexed()
        552: Sphere
        555: ID3D11DeviceContext::DrawIndexed()
        556: ID3DUserDefinedAnnotation::EndEvent()
558: ID3D11DeviceContext::ClearRenderTargetView()
559: ID3D11DeviceContext::ClearDepthStencilView()
561: Lighting
        563: ID3D11DeviceContext::ClearRenderTargetView()
        564: ID3D11DeviceContext::ClearRenderTargetView()
        566: Point light
        580: ID3D11DeviceContext::DrawIndexed()
        581: Sun light
        597: ID3D11DeviceContext::DrawIndexed()
        600: Cube light
        614: ID3D11DeviceContext::DrawIndexed()
        615: ID3DUserDefinedAnnotation::EndEvent()
617: ID3D11DeviceContext::ClearRenderTargetView()
618: ID3D11DeviceContext::ClearDepthStencilView()
620: Shading
        630: ID3D11DeviceContext::Draw()
        645: ID3D11DeviceContext::DrawIndexed()
        652: ID3DUserDefinedAnnotation::EndEvent()
653: ID3DUserDefinedAnnotation::EndEvent()
654: Present(ResourceId::47)
Pass #0 starts with 2: ID3D11DeviceContext::ClearRenderTargetView()
Pass #0 contained 23 actions
Pass #1 starts with 319: ID3D11DeviceContext::ClearDepthStencilView()
Pass #1 contained 23 actions
Pass #2 starts with 558: ID3D11DeviceContext::ClearRenderTargetView()
Pass #2 contained 3 actions
Pass #3 starts with 617: ID3D11DeviceContext::ClearRenderTargetView()
Pass #3 contained 3 actions