Path: blob/main_old/src/tests/restricted_traces/retrace_restricted_traces.py
1693 views
#! /usr/bin/env python31#2# Copyright 2020 The ANGLE Project Authors. All rights reserved.3# Use of this source code is governed by a BSD-style license that can be4# found in the LICENSE file.5#6'''7Script that re-captures the traces in the restricted trace folder. We can8use this to update traces without needing to re-run the app on a device.9'''1011import argparse12import fnmatch13import json14import logging15import os16import re17import subprocess18import sys1920from gen_restricted_traces import get_context as get_context2122DEFAULT_TEST_SUITE = 'angle_perftests'23DEFAULT_TEST_JSON = 'restricted_traces.json'24DEFAULT_LOG_LEVEL = 'info'2526# We preserve select metadata in the trace header that can't be re-captured properly.27# Currently this is just the set of default framebuffer surface config bits.28METADATA_KEYWORDS = ['kDefaultFramebuffer']293031def src_trace_path(trace):32script_dir = os.path.dirname(sys.argv[0])33return os.path.join(script_dir, trace)343536def context_header(trace, trace_path):37context_id = get_context(trace_path)38header = '%s_capture_context%s.h' % (trace, context_id)39return os.path.join(trace_path, header)404142def get_num_frames(trace):43trace_path = src_trace_path(trace)4445lo = 9999999946hi = 04748for file in os.listdir(trace_path):49match = re.match(r'.+_capture_context\d_frame(\d+)\.cpp', file)50if match:51frame = int(match.group(1))52if frame < lo:53lo = frame54if frame > hi:55hi = frame5657return hi - lo + 1585960def get_trace_metadata(trace):61trace_path = src_trace_path(trace)62header_file = context_header(trace, trace_path)63metadata = []64with open(header_file, 'rt') as f:65for line in f.readlines():66for keyword in METADATA_KEYWORDS:67if keyword in line:68metadata += [line]69return metadata707172def replace_metadata(header_file, metadata):73lines = []74replaced = False75with open(header_file, 'rt') as f:76for line in f.readlines():77found_keyword = False78for keyword in METADATA_KEYWORDS:79if keyword in line:80found_keyword = True81break8283if found_keyword:84if not replaced:85replaced = True86lines += metadata87else:88lines += [line]8990with open(header_file, 'wt') as f:91f.writelines(lines)929394def path_contains_header(path):95for file in os.listdir(path):96if fnmatch.fnmatch(file, '*.h'):97return True98return False99100101def main():102parser = argparse.ArgumentParser()103parser.add_argument('gn_path', help='GN build path')104parser.add_argument('out_path', help='Output directory')105parser.add_argument('-f', '--filter', help='Trace filter. Defaults to all.', default='*')106parser.add_argument('-l', '--log', help='Logging level.', default=DEFAULT_LOG_LEVEL)107parser.add_argument(108'--no-swiftshader',109help='Trace against native Vulkan.',110action='store_true',111default=False)112parser.add_argument(113'-n',114'--no-overwrite',115help='Skip traces which already exist in the out directory.',116action='store_true')117parser.add_argument(118'--validation', help='Enable state serialization validation calls.', action='store_true')119parser.add_argument(120'--limit',121'--frame-limit',122type=int,123help='Limits the number of captured frames to produce a shorter trace than the original.')124args, extra_flags = parser.parse_known_args()125126logging.basicConfig(level=args.log.upper())127128script_dir = os.path.dirname(sys.argv[0])129130# Load trace names131with open(os.path.join(script_dir, DEFAULT_TEST_JSON)) as f:132traces = json.loads(f.read())133134traces = [trace.split(' ')[0] for trace in traces['traces']]135136binary = os.path.join(args.gn_path, DEFAULT_TEST_SUITE)137if os.name == 'nt':138binary += '.exe'139140failures = []141142for trace in fnmatch.filter(traces, args.filter):143logging.debug('Tracing %s' % trace)144145trace_path = os.path.abspath(os.path.join(args.out_path, trace))146if not os.path.isdir(trace_path):147os.makedirs(trace_path)148elif args.no_overwrite and path_contains_header(trace_path):149logging.info('Skipping "%s" because the out folder already exists' % trace)150continue151152num_frames = get_num_frames(trace)153metadata = get_trace_metadata(trace)154155logging.debug('Read metadata: %s' % str(metadata))156157max_steps = min(args.limit, num_frames) if args.limit else num_frames158159# We start tracing from frame 2. --retrace-mode issues a Swap() after Setup() so we can160# accurately re-trace the MEC.161additional_env = {162'ANGLE_CAPTURE_LABEL': trace,163'ANGLE_CAPTURE_OUT_DIR': trace_path,164'ANGLE_CAPTURE_FRAME_START': '2',165'ANGLE_CAPTURE_FRAME_END': str(num_frames + 1),166}167if args.validation:168additional_env['ANGLE_CAPTURE_VALIDATION'] = '1'169# Also turn on shader output init to ensure we have no undefined values.170# This feature is also enabled in replay when using --validation.171additional_env['ANGLE_FEATURE_OVERRIDES_ENABLED'] = 'forceInitShaderOutputVariables'172173env = {**os.environ.copy(), **additional_env}174175renderer = 'vulkan' if args.no_swiftshader else 'vulkan_swiftshader'176177trace_filter = '--gtest_filter=TracePerfTest.Run/%s_%s' % (renderer, trace)178run_args = [179binary,180trace_filter,181'--retrace-mode',182'--max-steps-performed',183str(max_steps),184'--enable-all-trace-tests',185]186187print('Capturing "%s" (%d frames)...' % (trace, num_frames))188logging.debug('Running "%s" with environment: %s' %189(' '.join(run_args), str(additional_env)))190try:191subprocess.check_call(run_args, env=env)192193header_file = context_header(trace, trace_path)194195if not os.path.exists(header_file):196logging.error('There was a problem tracing "%s", could not find header file: %s' %197(trace, header_file))198failures += [trace]199else:200replace_metadata(header_file, metadata)201except:202logging.exception('There was an exception running "%s":' % trace)203failures += [trace]204205if failures:206print('The following traces failed to re-trace:\n')207print('\n'.join([' ' + trace for trace in failures]))208return 1209210return 0211212213if __name__ == '__main__':214sys.exit(main())215216217