cl: Fix missing OpenCL 3.0 definition
[piglit.git] / framework / replay / backends / renderdoc / renderdoc_dump_images.py
bloba1c16f8e22fa9d76895b2bb8b2a1eab8e0b643bf
1 #!/usr/bin/env python3
2 # coding=utf-8
4 # Copyright (c) 2019 Collabora Ltd
5 # Copyright © 2020 Valve Corporation.
7 # Permission is hereby granted, free of charge, to any person obtaining a
8 # copy of this software and associated documentation files (the "Software"),
9 # to deal in the Software without restriction, including without limitation
10 # the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 # and/or sell copies of the Software, and to permit persons to whom the
12 # Software is furnished to do so, subject to the following conditions:
14 # The above copyright notice and this permission notice shall be included
15 # in all copies or substantial portions of the Software.
17 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 # OTHER DEALINGS IN THE SOFTWARE.
25 # SPDX-License-Identifier: MIT
27 import argparse
28 import atexit
29 import os
30 import shutil
31 import tempfile
32 from pathlib import Path
35 def cleanup(dirpath):
36 shutil.rmtree(dirpath)
39 TMP_DIR = tempfile.mkdtemp()
40 atexit.register(cleanup, TMP_DIR)
41 RENDERDOC_DEBUG_FILE = TMP_DIR + "/renderdoc.log"
43 # Needs to be in the environment before importing the module
44 os.environ['RENDERDOC_DEBUG_LOG_FILE'] = RENDERDOC_DEBUG_FILE
45 import renderdoc as rd # noqa: E402
47 try:
48 from renderdoc import ResultCode
49 except ImportError:
50 from renderdoc import ReplayStatus as ResultCode
53 def find_draw_with_event_id(controller, event_id):
54 try:
55 for root_action in controller.GetRootActions():
56 if root_action.eventId == event_id:
57 return root_action
58 except AttributeError:
59 for root_drawcall in controller.GetDrawcalls():
60 if root_drawcall.eventId == event_id:
61 return root_drawcall
63 return None
66 def dump_image(controller, event_id, output_dir, tracefile):
67 draw = find_draw_with_event_id(controller, event_id)
68 if draw is None:
69 raise RuntimeError("Couldn't find draw call with event ID " +
70 str(event_id))
72 controller.SetFrameEvent(draw.eventId, True)
74 texsave = rd.TextureSave()
76 # Select the first color output
77 texsave.resourceId = draw.outputs[0]
79 if texsave.resourceId == rd.ResourceId.Null():
80 return
82 filepath = Path(output_dir)
83 filepath.mkdir(parents=True, exist_ok=True)
84 filepath = filepath / (tracefile + "-" + str(int(draw.eventId)) + ".png")
86 try:
87 filename: str = draw.GetName(controller.GetStructuredFile())
88 except AttributeError:
89 filename: str = draw.name
91 print(f"Saving image at event ID {draw.eventId}: {filename} to {filepath}")
93 # Most formats can only display a single image per file, so we select the
94 # first mip and first slice
95 texsave.mip = 0
96 texsave.slice.sliceIndex = 0
98 # For formats with an alpha channel, preserve it
99 texsave.alpha = rd.AlphaMapping.Preserve
100 texsave.destType = rd.FileType.PNG
101 controller.SaveTexture(texsave, str(filepath))
104 def load_capture(filename):
105 cap = rd.OpenCaptureFile()
107 status = cap.OpenFile(filename, '', None)
109 if status != ResultCode.Succeeded:
110 raise RuntimeError("Couldn't open file: " + str(status))
111 if not cap.LocalReplaySupport():
112 raise RuntimeError("Capture cannot be replayed")
114 status, controller = cap.OpenCapture(rd.ReplayOptions(), None)
116 if status != ResultCode.Succeeded:
117 if os.path.exists(RENDERDOC_DEBUG_FILE):
118 print(open(RENDERDOC_DEBUG_FILE, "r").read())
119 raise RuntimeError("Couldn't initialise replay: " + str(status))
121 if os.path.exists(RENDERDOC_DEBUG_FILE):
122 open(RENDERDOC_DEBUG_FILE, "w").write("")
124 return (cap, controller)
127 def renderdoc_dump_images(filename, event_ids, output_dir):
128 rd.InitialiseReplay(rd.GlobalEnvironment(), [])
129 cap, controller = load_capture(filename)
131 tracefile = Path(filename).name
133 if not event_ids:
134 try:
135 event_ids.append(controller.GetRootActions()[-1].eventId)
136 except AttributeError:
137 event_ids.append(controller.GetDrawcalls()[-1].eventId)
139 for event_id in event_ids:
140 dump_image(controller, event_id, output_dir, tracefile)
142 cap.Shutdown()
144 rd.ShutdownReplay()
147 def main():
148 parser = argparse.ArgumentParser()
150 parser.add_argument('file_path',
151 help='the path to a trace file.')
152 parser.add_argument('output_dir',
153 help='the path in which to place the results')
154 parser.add_argument('draw_id',
155 type=int,
156 nargs=argparse.REMAINDER,
157 help=('a draw-id number from the trace to dump. '
158 'If none are provided, by default, '
159 'the last frame will be used.'))
161 args = parser.parse_args()
163 renderdoc_dump_images(args.file_path, args.draw_id, args.output_dir)
166 if __name__ == '__main__':
167 main()