• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2
3# Copyright (c) 2019 Collabora Ltd
4#
5# Permission is hereby granted, free of charge, to any person obtaining a
6# copy of this software and associated documentation files (the "Software"),
7# to deal in the Software without restriction, including without limitation
8# the rights to use, copy, modify, merge, publish, distribute, sublicense,
9# and/or sell copies of the Software, and to permit persons to whom the
10# Software is furnished to do so, subject to the following conditions:
11#
12# The above copyright notice and this permission notice shall be included
13# in all copies or substantial portions of the Software.
14#
15# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
19# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21# OTHER DEALINGS IN THE SOFTWARE.
22#
23# SPDX-License-Identifier: MIT
24
25import atexit
26import os
27import shutil
28import sys
29import tempfile
30from pathlib import Path
31
32def cleanup(dirpath):
33        shutil.rmtree(dirpath)
34
35dirpath = tempfile.mkdtemp()
36atexit.register(cleanup, dirpath)
37RENDERDOC_DEBUG_FILE = dirpath + "/renderdoc.log"
38
39# Needs to be in the environment before importing the module
40os.environ['RENDERDOC_DEBUG_LOG_FILE'] = RENDERDOC_DEBUG_FILE
41import renderdoc as rd
42
43def findDrawWithEventId(controller, eventId):
44   for d in controller.GetDrawcalls():
45      if d.eventId == eventId:
46         return d
47
48   return None
49
50def dumpImage(controller, eventId, outputDir, tracefile):
51    draw = findDrawWithEventId(controller, eventId)
52    if draw is None:
53        raise RuntimeError("Couldn't find draw call with eventId " + str(eventId))
54
55    controller.SetFrameEvent(draw.eventId, True)
56
57    texsave = rd.TextureSave()
58
59    # Select the first color output
60    texsave.resourceId = draw.outputs[0]
61
62    if texsave.resourceId == rd.ResourceId.Null():
63        return
64
65    filepath = Path(outputDir)
66    filepath.mkdir(parents = True, exist_ok = True)
67    filepath = filepath / (tracefile + "-" + str(int(draw.eventId)) + ".png")
68
69    print("Saving image at eventId %d: %s to %s" % (draw.eventId, draw.name, filepath))
70
71    # Most formats can only display a single image per file, so we select the
72    # first mip and first slice
73    texsave.mip = 0
74    texsave.slice.sliceIndex = 0
75
76    # For formats with an alpha channel, preserve it
77    texsave.alpha = rd.AlphaMapping.Preserve
78    texsave.destType = rd.FileType.PNG
79    controller.SaveTexture(texsave, str(filepath))
80
81def loadCapture(filename):
82    cap = rd.OpenCaptureFile()
83
84    status = cap.OpenFile(filename, '', None)
85
86    if status != rd.ReplayStatus.Succeeded:
87        raise RuntimeError("Couldn't open file: " + str(status))
88    if not cap.LocalReplaySupport():
89        raise RuntimeError("Capture cannot be replayed")
90
91    status, controller = cap.OpenCapture(rd.ReplayOptions(), None)
92
93    if status != rd.ReplayStatus.Succeeded:
94        if os.path.exists(RENDERDOC_DEBUG_FILE):
95            print(open(RENDERDOC_DEBUG_FILE, "r").read())
96        raise RuntimeError("Couldn't initialise replay: " + str(status))
97
98    if os.path.exists(RENDERDOC_DEBUG_FILE):
99        open(RENDERDOC_DEBUG_FILE, "w").write("")
100
101    return (cap, controller)
102
103def renderdoc_dump_images(filename, eventIds, outputDir):
104   rd.InitialiseReplay(rd.GlobalEnvironment(), [])
105   cap, controller = loadCapture(filename);
106
107   tracefile = Path(filename).name
108
109   if len(eventIds) == 0:
110      eventIds.append(controller.GetDrawcalls()[-1].eventId)
111
112   for eventId in eventIds:
113      dumpImage(controller, eventId, outputDir, tracefile)
114
115   cap.Shutdown()
116
117   rd.ShutdownReplay()
118
119if __name__ == "__main__":
120   if len(sys.argv) < 3:
121      raise RuntimeError("Usage: renderdoc_dump_images.py <trace> <outputdir> [<draw-id>...]")
122
123   eventIds = [int(e) for e in sys.argv[3:]]
124
125   renderdoc_dump_images(sys.argv[1], eventIds, sys.argv[2])
126