summaryrefslogtreecommitdiff
path: root/.gitlab-ci/tracie/dump_trace_images.py
diff options
context:
space:
mode:
Diffstat (limited to '.gitlab-ci/tracie/dump_trace_images.py')
-rw-r--r--.gitlab-ci/tracie/dump_trace_images.py134
1 files changed, 134 insertions, 0 deletions
diff --git a/.gitlab-ci/tracie/dump_trace_images.py b/.gitlab-ci/tracie/dump_trace_images.py
new file mode 100644
index 00000000000..66a99f7efe2
--- /dev/null
+++ b/.gitlab-ci/tracie/dump_trace_images.py
@@ -0,0 +1,134 @@
+#!/usr/bin/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 argparse
+import os
+import sys
+import subprocess
+from pathlib import Path
+from traceutil import trace_type_from_filename, TraceType
+
+def log(severity, msg, end='\n'):
+ print("[dump_trace_images] %s: %s" % (severity, msg), flush=True, end=end)
+
+def log_result(msg):
+ print(msg, flush=True)
+
+def run_logged_command(cmd, log_path):
+ ret = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ logoutput = ("[dump_trace_images] Running: %s\n" % " ".join(cmd)).encode() + \
+ ret.stdout
+ log_path.parent.mkdir(parents=True, exist_ok=True)
+ with log_path.open(mode='wb') as log:
+ log.write(logoutput)
+ if ret.returncode:
+ raise RuntimeError(
+ logoutput.decode(errors='replace') +
+ "[dump_traces_images] Process failed with error code: %d" % ret.returncode)
+
+def get_last_apitrace_frame_call(trace_path):
+ cmd = ["apitrace", "dump", "--calls=frame", str(trace_path)]
+ ret = subprocess.run(cmd, stdout=subprocess.PIPE)
+ for l in reversed(ret.stdout.decode(errors='replace').splitlines()):
+ s = l.split(None, 1)
+ if len(s) >= 1 and s[0].isnumeric():
+ return int(s[0])
+ return -1
+
+def dump_with_apitrace(trace_path, calls, device_name):
+ outputdir = str(trace_path.parent / "test" / device_name)
+ os.makedirs(outputdir, exist_ok=True)
+ outputprefix = str(Path(outputdir) / trace_path.name) + "-"
+ if len(calls) == 0:
+ calls = [str(get_last_apitrace_frame_call(trace_path))]
+ cmd = ["apitrace", "dump-images", "--calls=" + ','.join(calls),
+ "-o", outputprefix, str(trace_path)]
+ log_path = Path(outputdir) / (trace_path.name + ".log")
+ run_logged_command(cmd, log_path)
+
+def dump_with_renderdoc(trace_path, calls, device_name):
+ outputdir = str(trace_path.parent / "test" / device_name)
+ script_path = Path(os.path.dirname(os.path.abspath(__file__)))
+ cmd = [str(script_path / "renderdoc_dump_images.py"), str(trace_path), outputdir]
+ cmd.extend(calls)
+ log_path = Path(outputdir) / (trace_path.name + ".log")
+ run_logged_command(cmd, log_path)
+
+def dump_with_testtrace(trace_path, calls, device_name):
+ from PIL import Image
+ outputdir_path = trace_path.parent / "test" / device_name
+ outputdir_path.mkdir(parents=True, exist_ok=True)
+ with trace_path.open() as f:
+ rgba = f.read()
+ color = [int(rgba[0:2], 16), int(rgba[2:4], 16),
+ int(rgba[4:6], 16), int(rgba[6:8], 16)]
+ if len(calls) == 0: calls = ["0"]
+ for c in calls:
+ outputfile = str(outputdir_path / trace_path.name) + "-" + c + ".png"
+ log_path = outputdir_path / (trace_path.name + ".log")
+ with log_path.open(mode='w') as log:
+ log.write("Writing RGBA: %s to %s" % (rgba, outputfile))
+ Image.frombytes('RGBA', (32, 32), bytes(color * 32 * 32)).save(outputfile)
+
+def dump_from_trace(trace_path, calls, device_name):
+ log("Info", "Dumping trace %s" % trace_path, end='... ')
+ trace_type = trace_type_from_filename(trace_path.name)
+ try:
+ if trace_type == TraceType.APITRACE:
+ dump_with_apitrace(trace_path, calls, device_name)
+ elif trace_type == TraceType.RENDERDOC:
+ dump_with_renderdoc(trace_path, calls, device_name)
+ elif trace_type == TraceType.TESTTRACE:
+ dump_with_testtrace(trace_path, calls, device_name)
+ else:
+ raise RuntimeError("Unknown tracefile extension")
+ log_result("OK")
+ return True
+ except Exception as e:
+ log_result("ERROR")
+ log("Debug", "=== Failure log start ===")
+ print(e)
+ log("Debug", "=== Failure log end ===")
+ return False
+
+def main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument('tracepath', help="trace to dump")
+ parser.add_argument('--device-name', required=True,
+ help="the name of the graphics device used to produce images")
+ parser.add_argument('--calls', required=False,
+ help="the call numbers from the trace to dump (default: last frame)")
+
+ args = parser.parse_args()
+ if args.calls is not None:
+ args.calls = args.calls.split(",")
+ else:
+ args.calls = []
+
+ success = dump_from_trace(Path(args.tracepath), args.calls, args.device_name)
+
+ sys.exit(0 if success else 1)
+
+if __name__ == "__main__":
+ main()