1#!/usr/bin/python3 2# 3# Copyright 2022 The ANGLE Project Authors. All rights reserved. 4# Use of this source code is governed by a BSD-style license that can be 5# found in the LICENSE file. 6# 7# gen_interpreter_utils.py: 8# Code generator for the GLC interpreter. 9# NOTE: don't run this script directly. Run scripts/run_code_generation.py. 10 11import os 12import re 13import sys 14 15import registry_xml 16 17EXIT_SUCCESS = 0 18EXIT_FAILURE = 1 19 20BASE_PATH = '../util/capture/trace_interpreter_autogen' 21 22CPP_TEMPLATE = """\ 23// GENERATED FILE - DO NOT EDIT. 24// Generated by {script_name} using data from {data_source_name}. 25// 26// Copyright 2022 The ANGLE Project Authors. All rights reserved. 27// Use of this source code is governed by a BSD-style license that can be 28// found in the LICENSE file. 29// 30// {file_name}.cpp: 31// Helper code for trace interpreter. 32 33#include "angle_trace_gl.h" 34#include "trace_fixture.h" 35#include "trace_interpreter.h" 36 37namespace angle 38{{ 39CallCapture ParseCallCapture(const Token &nameToken, size_t numParamTokens, const Token *paramTokens, const TraceStringMap &strings) 40{{ 41{parse_cases} 42 if (numParamTokens > 0) 43 {{ 44 printf("Expected zero parameter tokens for %s\\n", nameToken); 45 UNREACHABLE(); 46 }} 47 return CallCapture(nameToken, ParamBuffer()); 48}} 49 50{dispatch_cases} 51 52void ReplayCustomFunctionCall(const CallCapture &call, const TraceFunctionMap &customFunctions) 53{{ 54 ASSERT(call.entryPoint == EntryPoint::Invalid); 55 const Captures &captures = call.params.getParamCaptures(); 56 57{custom_dispatch_cases} 58 59 auto iter = customFunctions.find(call.customFunctionName); 60 if (iter == customFunctions.end()) 61 {{ 62 printf("Unknown custom function: %s\\n", call.customFunctionName.c_str()); 63 UNREACHABLE(); 64 }} 65 else 66 {{ 67 ASSERT(call.params.empty()); 68 const TraceFunction &customFunc = iter->second; 69 for (const CallCapture &customCall : customFunc) 70 {{ 71 ReplayTraceFunctionCall(customCall, customFunctions); 72 }} 73 }} 74}} 75}} // namespace angle 76""" 77 78PARSE_CASE = """\ 79 if (strcmp(nameToken, "{ep}") == 0) 80 {{ 81 ParamBuffer params = ParseParameters<{pfn}>(paramTokens, strings); 82 return CallCapture({call}, std::move(params)); 83 }} 84""" 85 86CUSTOM_DISPATCH_CASE = """\ 87 if (call.customFunctionName == "{fn}") 88 {{ 89 DispatchCallCapture({fn}, captures); 90 return; 91 }} 92""" 93 94DISPATCH_CASE = """\ 95template <typename Fn, EnableIfNArgs<Fn, {nargs}> = 0> 96void DispatchCallCapture(Fn *fn, const Captures &cap) 97{{ 98 (*fn)({args}); 99}} 100""" 101 102FIXTURE_H = '../util/capture/trace_fixture.h' 103 104 105def GetFunctionsFromFixture(): 106 funcs = [] 107 arg_counts = set() 108 pattern = 'void ' 109 with open(FIXTURE_H) as f: 110 lines = f.read().split(';') 111 for line in lines: 112 line = re.sub('// .*\n', '', line.strip()) 113 if line.startswith(pattern): 114 func_name = line[len(pattern):line.find('(')] 115 func_args = line.count(',') + 1 116 funcs.append(func_name) 117 arg_counts.add(func_args) 118 f.close() 119 return sorted(funcs), arg_counts 120 121 122def get_dispatch(n): 123 return ', '.join(['Arg<Fn, %d>(cap)' % i for i in range(n)]) 124 125 126def main(cpp_output_path): 127 gles = registry_xml.GetGLES() 128 egl = registry_xml.GetEGL() 129 130 def fn(ep): 131 return 'std::remove_pointer<PFN%sPROC>::type' % ep.upper() 132 133 fixture_functions, arg_counts = GetFunctionsFromFixture() 134 135 eps_and_enums = sorted(list(set(gles.GetEnums() + egl.GetEnums()))) 136 parse_cases = [ 137 PARSE_CASE.format(ep=ep, pfn=fn(ep), call='EntryPoint::%s' % enum) 138 for (enum, ep) in eps_and_enums 139 ] 140 parse_cases += [ 141 PARSE_CASE.format(ep=fn, pfn='decltype(%s)' % fn, call='"%s"' % fn) 142 for fn in fixture_functions 143 ] 144 145 dispatch_cases = [DISPATCH_CASE.format(nargs=n, args=get_dispatch(n)) for n in arg_counts] 146 147 custom_dispatch_cases = [CUSTOM_DISPATCH_CASE.format(fn=fn) for fn in fixture_functions] 148 149 format_args = { 150 'script_name': os.path.basename(sys.argv[0]), 151 'data_source_name': 'gl.xml and gl_angle_ext.xml', 152 'file_name': os.path.basename(BASE_PATH), 153 'parse_cases': ''.join(parse_cases), 154 'dispatch_cases': '\n'.join(dispatch_cases), 155 'custom_dispatch_cases': ''.join(custom_dispatch_cases), 156 } 157 158 cpp_content = CPP_TEMPLATE.format(**format_args) 159 cpp_output_path = registry_xml.script_relative(cpp_output_path) 160 with open(cpp_output_path, 'w') as f: 161 f.write(cpp_content) 162 163 return EXIT_SUCCESS 164 165 166if __name__ == '__main__': 167 inputs = registry_xml.xml_inputs + [FIXTURE_H] 168 outputs = [ 169 '%s.cpp' % BASE_PATH, 170 ] 171 172 if len(sys.argv) > 1: 173 if sys.argv[1] == 'inputs': 174 print(','.join(inputs)) 175 elif sys.argv[1] == 'outputs': 176 print(','.join(outputs)) 177 else: 178 sys.exit(main(registry_xml.script_relative(outputs[0]))) 179