blob: a89b5fda7947d76baacb10801502520d84e37b96 [file] [log] [blame]
#!/usr/bin/env python3
# Copyright (c) 2019 Collabora Ltd
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.
#
# SPDX-License-Identifier: MIT
import atexit
import os
import shutil
import sys
import tempfile
from pathlib import Path
def cleanup(dirpath):
shutil.rmtree(dirpath)
dirpath = tempfile.mkdtemp()
atexit.register(cleanup, dirpath)
RENDERDOC_DEBUG_FILE = dirpath + "/renderdoc.log"
# Needs to be in the environment before importing the module
os.environ['RENDERDOC_DEBUG_LOG_FILE'] = RENDERDOC_DEBUG_FILE
import renderdoc as rd
def findDrawWithEventId(controller, eventId):
for d in controller.GetDrawcalls():
if d.eventId == eventId:
return d
return None
def dumpImage(controller, eventId, outputDir, tracefile):
draw = findDrawWithEventId(controller, eventId)
if draw is None:
raise RuntimeError("Couldn't find draw call with eventId " + str(eventId))
controller.SetFrameEvent(draw.eventId, True)
texsave = rd.TextureSave()
# Select the first color output
texsave.resourceId = draw.outputs[0]
if texsave.resourceId == rd.ResourceId.Null():
return
filepath = Path(outputDir)
filepath.mkdir(parents = True, exist_ok = True)
filepath = filepath / (tracefile + "-" + str(int(draw.eventId)) + ".png")
print("Saving image at eventId %d: %s to %s" % (draw.eventId, draw.name, filepath))
# Most formats can only display a single image per file, so we select the
# first mip and first slice
texsave.mip = 0
texsave.slice.sliceIndex = 0
# For formats with an alpha channel, preserve it
texsave.alpha = rd.AlphaMapping.Preserve
texsave.destType = rd.FileType.PNG
controller.SaveTexture(texsave, str(filepath))
def loadCapture(filename):
cap = rd.OpenCaptureFile()
status = cap.OpenFile(filename, '', None)
if status != rd.ReplayStatus.Succeeded:
raise RuntimeError("Couldn't open file: " + str(status))
if not cap.LocalReplaySupport():
raise RuntimeError("Capture cannot be replayed")
status, controller = cap.OpenCapture(rd.ReplayOptions(), None)
if status != rd.ReplayStatus.Succeeded:
if os.path.exists(RENDERDOC_DEBUG_FILE):
print(open(RENDERDOC_DEBUG_FILE, "r").read())
raise RuntimeError("Couldn't initialise replay: " + str(status))
if os.path.exists(RENDERDOC_DEBUG_FILE):
open(RENDERDOC_DEBUG_FILE, "w").write("")
return (cap, controller)
def renderdoc_dump_images(filename, eventIds, outputDir):
rd.InitialiseReplay(rd.GlobalEnvironment(), [])
cap, controller = loadCapture(filename);
tracefile = Path(filename).name
if len(eventIds) == 0:
eventIds.append(controller.GetDrawcalls()[-1].eventId)
for eventId in eventIds:
dumpImage(controller, eventId, outputDir, tracefile)
cap.Shutdown()
rd.ShutdownReplay()
if __name__ == "__main__":
if len(sys.argv) < 3:
raise RuntimeError("Usage: renderdoc_dump_images.py <trace> <outputdir> [<draw-id>...]")
eventIds = [int(e) for e in sys.argv[3:]]
renderdoc_dump_images(sys.argv[1], eventIds, sys.argv[2])