-
-
Save benjamintanweihao/458928a93254418d83f74a87e1be5f52 to your computer and use it in GitHub Desktop.
# RenderDoc Python scripts, powered by IronPython 2.7.4.1000 | |
# The 'renderdoc' object is the Core class instance. | |
config = {} | |
config['py_lib_dir'] = 'C:\\Python27\\Lib\\' | |
config['save_dir'] = 'C:\\workspace\\playing-for-data\\data\\processed\\' # where we store extraction results | |
# creates a prefixes for files and directories from logfilename | |
config['dir_prefix'] = lambda logFilename: '' | |
config['file_prefix'] = lambda logFilename: basename(logFilename)[:-4] + '_' | |
# The following values depend on the game and need to be specified. | |
# Hence, we do not set default values. | |
# For extracting mesh, shader, and texture ids we need to reliably identify the G-buffer pass. | |
# By 'G-buffer' pass we mean the pass that renders all objects of interest. Hence, this pass will reference | |
# all meshes, shaders, and textures. | |
# We identify the G-buffer pass by its render targets (number of color targets, whether there is depth) | |
# If multiple passes fulfil the specified conditions, we only process the first one. | |
# You need to change this behaviour for some games. | |
config[ | |
'gbufferpass_colortargets'] = 4 # number of color targets that identify the G-buffer pass, most probably 4 as games want to use all available render targets | |
config['gbufferpass_hasdepth'] = True # whether G-buffer pass has a depth target | |
# Our names for the color buffers | |
config['gbuffer_names'] = ['gbuffer1', 'gbuffer2', 'gbuffer3', | |
'gbuffer4'] # the number should match the config['gbufferpass_colortargets'] | |
# We want to extract clean images without any UI elements. Hence, we need to identify the pass | |
# where the HUD is rendered. | |
config['hudpass_colortargets'] = 4 # number of color targets that identify the HUD pass | |
config['hudpass_hasdepth'] = True # whether HUD pass has a depth target | |
config['hudpass_drawcallname'] = '' # name of drawcall event | |
# Add python libraries | |
import sys | |
sys.path.append(config['py_lib_dir']) | |
# Load frame info | |
frameInfo = renderdoc.FrameInfo | |
assert (len(frameInfo) == 1, 'expected only one frame.') | |
frameId = renderdoc.CurFrame | |
print('Extracting from frame %d' % frameId) | |
# Get prefix and set up directory | |
from os import mkdir | |
from os.path import dirname, basename, exists | |
dirPrefix = config['dir_prefix'](renderdoc.LogFileName) | |
filePrefix = config['file_prefix'](renderdoc.LogFileName) | |
saveDir = '%s/%s/' % (config['save_dir'], dirPrefix) | |
if not exists(saveDir): | |
mkdir(saveDir) | |
pass | |
print('Output directory is %s' % saveDir) | |
print('File prefix is %s' % filePrefix) | |
# Get drawcalls | |
drawcalls = renderdoc.GetDrawcalls(frameId) | |
print('Found %d drawcalls.' % len(drawcalls)) | |
def containsTargets(drawcallName, numColorTargets, hasDepthTarget): | |
""" Determines if drawcall has multiple render targets by checking its name. | |
The name is defined by renderdoc and contains information about render targets.""" | |
if hasDepthTarget: | |
result = drawcallName.find('(%d Targets + Depth)' % numColorTargets) >= 0 | |
return result | |
else: | |
result = drawcallName.find('(%d Targets)' % numColorTargets) >= 0 | |
return result | |
pass | |
def findGbufferPass(numColorTargets, hasDepthTarget): | |
""" Identifies the G-buffer pass. """ | |
gbufferEnd = 0 | |
gbufferIds = [i for i, call in enumerate(drawcalls) if containsTargets(call.name, numColorTargets, hasDepthTarget)] | |
if len(gbufferIds) == 1: | |
gbufferId = gbufferIds[0] | |
gbufferCalls = drawcalls[gbufferId].children | |
print('G-buffer pass has %d drawcalls.' % len(gbufferCalls)) | |
gbufferEnd = drawcalls[gbufferId].children[-1].eventID # last drawcall of the G-buffer pass | |
pass | |
assert (gbufferEnd > 0, 'Did not find any drawcall with the specified G-buffer settings.') | |
return gbufferId, gbufferEnd | |
def findFinalPass(numColorTargets, hasDepthTarget, drawCallName): | |
""" Returns the EventID of the pass that draws the final image (before HUD). """ | |
# Find last drawcall before HUD | |
potentialHudIds = [i for i, call in enumerate(drawcalls) if | |
containsTargets(call.name, numColorTargets, hasDepthTarget)] | |
print('Found %d potential HUD passes.' % len(potentialHudIds)) | |
colorpassIds = [i for i, call in enumerate(drawcalls) if containsTargets(call.name, 1, False)] | |
a = colorpassIds[:] | |
a.extend(potentialHudIds[:-3]) | |
assert (len(a) > 0, 'Found not enough potential final passes.') | |
firstPotentialFinalId = max(a) | |
finalPassId = 0 | |
return [call.eventID for call in drawcalls[-1:0:-1] if call.name.find(drawCallName) >= 0][1] | |
def getColorBuffers(frameId, eventId): | |
""" Sets the pipeline to eventId and returns the ids of bound render targets. """ | |
renderdoc.SetEventID(None, frameId, eventId) | |
commonState = renderdoc.CurPipelineState | |
outputTargets = commonState.GetOutputTargets() | |
return [t for t in outputTargets if str(t) <> '0'] | |
def initIDRendering(frameId, gbufferId, gbufferEnd): | |
""" Initializes ID rendering. """ | |
gbufferStart = drawcalls[gbufferId].children[0].eventID | |
renderdoc.SetEventID(None, frameId, gbufferStart) | |
renderdoc.SetIDRenderingEvents(frameId, gbufferStart, gbufferEnd) | |
renderdoc.SetIDRendering(True) | |
pass | |
gbufferId, gbufferEnd = findGbufferPass(config['gbufferpass_colortargets'], config['gbufferpass_hasdepth']) | |
print('G-buffer pass is done at EID %d.' % gbufferEnd) | |
bufferIds = getColorBuffers(frameId, gbufferEnd) | |
# Save color targets | |
for i, bid in enumerate(bufferIds): | |
renderdoc.SaveTexture(bid, '{0}/{1}_{2}.png'.format(saveDir, filePrefix, config['gbuffer_names'][i])) | |
# Save depth target | |
depthTarget = renderdoc.CurPipelineState.GetDepthTarget() | |
renderdoc.SaveTexture(depthTarget, '{0}/{1}_depth.exr'.format(saveDir, filePrefix)) | |
finalPassId = findFinalPass(config['hudpass_colortargets'], config['hudpass_hasdepth'], config['hudpass_drawcallname']) | |
assert (finalPassId == 0, 'Found not enough potential final passes.') | |
bufferIds = getColorBuffers(frameId, finalPassId) | |
assert (len(bufferIds) == 1, 'Found %d potential final render targets.' % len(bufferIds)) | |
renderdoc.SaveTexture(bufferIds[0], '{0}/{1}_final.png'.format(saveDir, filePrefix)) | |
# now do the id rendering | |
print('Rendering ids...') | |
initIDRendering(frameId, gbufferId, gbufferEnd) | |
bufferIds = getColorBuffers(frameId, gbufferEnd) | |
bufferNames = ['texture', 'mesh', 'shader', 'overflow'] | |
for i, bid in enumerate(bufferIds): | |
renderdoc.SaveTexture(bid, '{0}/{1}_{2}.png'.format(saveDir, filePrefix, bufferNames[i])) | |
renderdoc.HashTextures('{0}/{1}_tex.txt'.format(saveDir, filePrefix)) | |
renderdoc.HashBuffers('{0}/{1}_mesh.txt'.format(saveDir, filePrefix)) | |
renderdoc.HashShaders('{0}/{1}_shader.txt'.format(saveDir, filePrefix)) | |
print('done.') | |
# close renderdoc | |
# renderdoc.AppWindow.Close() |
Ohai! Yup. Direct X 12 doesn't work. So far, it only works with Direct X 10 and 10.1. Even 11 doesn't work. Otherwise, the draw calls do not contain the string "N Targets + Depth". Ping me if you need more help. I've spent a lot of time trying to get everything working :)
Hello,actually sometimes I run it successfully and produced right png files and txt files,but only for one logfile,and when I open another logfile and run the same program,it doesn't work with the following error:
EnvironmentError: System.Runtime.InteropServices.SEHException (0x80004005): 外部组件发生异常。
And this error always happens if I go on running the program with a certain logfile,unless I restart my computer then it can work only with the first logfile,and if I go on running the same error happens. Do you know why?
That means DirectX 12 doesn't work?
In fact,I'm facing some problems in running this script from the 2016-playing-for-data project