1e5c31af7Sopenharmony_ci#!/usr/bin/env python 2e5c31af7Sopenharmony_ci 3e5c31af7Sopenharmony_ci# Copyright 2019 The Amber Authors. All rights reserved. 4e5c31af7Sopenharmony_ci# 5e5c31af7Sopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License"); 6e5c31af7Sopenharmony_ci# you may not use this file except in compliance with the License. 7e5c31af7Sopenharmony_ci# You may obtain a copy of the License at 8e5c31af7Sopenharmony_ci# 9e5c31af7Sopenharmony_ci# http://www.apache.org/licenses/LICENSE-2.0 10e5c31af7Sopenharmony_ci# 11e5c31af7Sopenharmony_ci# Unless required by applicable law or agreed to in writing, software 12e5c31af7Sopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS, 13e5c31af7Sopenharmony_ci# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14e5c31af7Sopenharmony_ci# See the License for the specific language governing permissions and 15e5c31af7Sopenharmony_ci# limitations under the License. 16e5c31af7Sopenharmony_ci 17e5c31af7Sopenharmony_ci# Generates vk-wrappers.inc in the src/ directory. 18e5c31af7Sopenharmony_ci 19e5c31af7Sopenharmony_cifrom __future__ import print_function 20e5c31af7Sopenharmony_ci 21e5c31af7Sopenharmony_ciimport os.path 22e5c31af7Sopenharmony_ciimport re 23e5c31af7Sopenharmony_ciimport sys 24e5c31af7Sopenharmony_ciimport xml.etree.ElementTree as ET 25e5c31af7Sopenharmony_cifrom string import Template 26e5c31af7Sopenharmony_ci 27e5c31af7Sopenharmony_cidef read_inc(file): 28e5c31af7Sopenharmony_ci methods = [] 29e5c31af7Sopenharmony_ci pattern = re.compile(r"AMBER_VK_FUNC\((\w+)\)") 30e5c31af7Sopenharmony_ci with open(file, 'r') as f: 31e5c31af7Sopenharmony_ci for line in f: 32e5c31af7Sopenharmony_ci match = pattern.search(line) 33e5c31af7Sopenharmony_ci if match == None: 34e5c31af7Sopenharmony_ci raise Exception("FAILED TO MATCH PATTERN"); 35e5c31af7Sopenharmony_ci 36e5c31af7Sopenharmony_ci methods.append(match.group(1)) 37e5c31af7Sopenharmony_ci return methods 38e5c31af7Sopenharmony_ci 39e5c31af7Sopenharmony_ci 40e5c31af7Sopenharmony_cidef read_vk(file): 41e5c31af7Sopenharmony_ci methods = {} 42e5c31af7Sopenharmony_ci tree = ET.parse(file) 43e5c31af7Sopenharmony_ci root = tree.getroot(); 44e5c31af7Sopenharmony_ci for command in root.iter("command"): 45e5c31af7Sopenharmony_ci proto = command.find('proto') 46e5c31af7Sopenharmony_ci if proto == None: 47e5c31af7Sopenharmony_ci continue 48e5c31af7Sopenharmony_ci 49e5c31af7Sopenharmony_ci return_type = proto.find('type').text 50e5c31af7Sopenharmony_ci name = proto.find('name').text 51e5c31af7Sopenharmony_ci 52e5c31af7Sopenharmony_ci param_list = [] 53e5c31af7Sopenharmony_ci for param in command.findall('param'): 54e5c31af7Sopenharmony_ci param_val = "".join(param.itertext()) 55e5c31af7Sopenharmony_ci param_name = param.find('name').text 56e5c31af7Sopenharmony_ci param_list.append({ 57e5c31af7Sopenharmony_ci 'def': param_val, 58e5c31af7Sopenharmony_ci 'name': param_name 59e5c31af7Sopenharmony_ci }) 60e5c31af7Sopenharmony_ci 61e5c31af7Sopenharmony_ci methods[name] = { 62e5c31af7Sopenharmony_ci 'return_type': return_type, 63e5c31af7Sopenharmony_ci 'name': name, 64e5c31af7Sopenharmony_ci 'params': param_list 65e5c31af7Sopenharmony_ci } 66e5c31af7Sopenharmony_ci 67e5c31af7Sopenharmony_ci return methods 68e5c31af7Sopenharmony_ci 69e5c31af7Sopenharmony_ci 70e5c31af7Sopenharmony_cidef gen_wrappers(methods, xml): 71e5c31af7Sopenharmony_ci content = "" 72e5c31af7Sopenharmony_ci for method in methods: 73e5c31af7Sopenharmony_ci data = xml[method] 74e5c31af7Sopenharmony_ci if data == None: 75e5c31af7Sopenharmony_ci raise Exception("Failed to find {}".format(method)) 76e5c31af7Sopenharmony_ci 77e5c31af7Sopenharmony_ci param_vals = [] 78e5c31af7Sopenharmony_ci param_names = [] 79e5c31af7Sopenharmony_ci for param in data['params']: 80e5c31af7Sopenharmony_ci param_vals.append(param['def']) 81e5c31af7Sopenharmony_ci param_names.append(param['name']) 82e5c31af7Sopenharmony_ci 83e5c31af7Sopenharmony_ci signature = ', '.join(str(x) for x in param_vals) 84e5c31af7Sopenharmony_ci arguments = ', '.join(str(x) for x in param_names) 85e5c31af7Sopenharmony_ci return_type = data['return_type'] 86e5c31af7Sopenharmony_ci return_variable = '' 87e5c31af7Sopenharmony_ci call_prefix = '' 88e5c31af7Sopenharmony_ci if return_type != 'void': 89e5c31af7Sopenharmony_ci return_variable = 'ret' 90e5c31af7Sopenharmony_ci call_prefix = return_type + ' ' + return_variable + ' = ' 91e5c31af7Sopenharmony_ci 92e5c31af7Sopenharmony_ci template = Template(R'''{ 93e5c31af7Sopenharmony_ci PFN_${method} ptr = reinterpret_cast<PFN_${method}>(getInstanceProcAddr(instance_, "${method}")); 94e5c31af7Sopenharmony_ci if (!ptr) { 95e5c31af7Sopenharmony_ci return Result("Vulkan: Unable to load ${method} pointer"); 96e5c31af7Sopenharmony_ci } 97e5c31af7Sopenharmony_ci if (delegate && delegate->LogGraphicsCalls()) { 98e5c31af7Sopenharmony_ci ptrs_.${method} = [ptr, delegate](${signature}) -> ${return_type} { 99e5c31af7Sopenharmony_ci delegate->Log("${method}"); 100e5c31af7Sopenharmony_ci uint64_t timestamp_start = 0; 101e5c31af7Sopenharmony_ci if (delegate->LogGraphicsCallsTime()) { 102e5c31af7Sopenharmony_ci timestamp_start = delegate->GetTimestampNs(); 103e5c31af7Sopenharmony_ci } 104e5c31af7Sopenharmony_ci ${call_prefix}ptr(${arguments}); 105e5c31af7Sopenharmony_ci if (delegate->LogGraphicsCallsTime()) { 106e5c31af7Sopenharmony_ci uint64_t timestamp_end = delegate->GetTimestampNs(); 107e5c31af7Sopenharmony_ci uint64_t duration = timestamp_end - timestamp_start; 108e5c31af7Sopenharmony_ci std::ostringstream out; 109e5c31af7Sopenharmony_ci out << "time "; 110e5c31af7Sopenharmony_ci // name of method on 40 characters 111e5c31af7Sopenharmony_ci out << std::left << std::setw(40) << "${method}"; 112e5c31af7Sopenharmony_ci // duration in nanoseconds on 12 characters, right-aligned 113e5c31af7Sopenharmony_ci out << std::right << std::setw(12) << duration; 114e5c31af7Sopenharmony_ci out << " ns"; 115e5c31af7Sopenharmony_ci delegate->Log(out.str()); 116e5c31af7Sopenharmony_ci } 117e5c31af7Sopenharmony_ci return ${return_variable}; 118e5c31af7Sopenharmony_ci }; 119e5c31af7Sopenharmony_ci } else { 120e5c31af7Sopenharmony_ci ptrs_.${method} = [ptr](${signature}) -> ${return_type} { 121e5c31af7Sopenharmony_ci ${call_prefix}ptr(${arguments}); 122e5c31af7Sopenharmony_ci return ${return_variable}; 123e5c31af7Sopenharmony_ci }; 124e5c31af7Sopenharmony_ci } 125e5c31af7Sopenharmony_ci} 126e5c31af7Sopenharmony_ci''') 127e5c31af7Sopenharmony_ci 128e5c31af7Sopenharmony_ci content += template.substitute(method=method, 129e5c31af7Sopenharmony_ci signature=signature, 130e5c31af7Sopenharmony_ci arguments=arguments, 131e5c31af7Sopenharmony_ci return_type=return_type, 132e5c31af7Sopenharmony_ci return_variable=return_variable, 133e5c31af7Sopenharmony_ci call_prefix=call_prefix) 134e5c31af7Sopenharmony_ci 135e5c31af7Sopenharmony_ci return content 136e5c31af7Sopenharmony_ci 137e5c31af7Sopenharmony_ci 138e5c31af7Sopenharmony_cidef gen_headers(methods, xml): 139e5c31af7Sopenharmony_ci content = "" 140e5c31af7Sopenharmony_ci for method in methods: 141e5c31af7Sopenharmony_ci data = xml[method] 142e5c31af7Sopenharmony_ci if data == None: 143e5c31af7Sopenharmony_ci raise Exception("Failed to find {}".format(method)) 144e5c31af7Sopenharmony_ci 145e5c31af7Sopenharmony_ci param_vals = [] 146e5c31af7Sopenharmony_ci param_names = [] 147e5c31af7Sopenharmony_ci for param in data['params']: 148e5c31af7Sopenharmony_ci param_vals.append(param['def']) 149e5c31af7Sopenharmony_ci param_names.append(param['name']) 150e5c31af7Sopenharmony_ci 151e5c31af7Sopenharmony_ci content += "std::function<{}({})> {};\n".format(data['return_type'], 152e5c31af7Sopenharmony_ci ', '.join(str(x) for x in param_vals), method) 153e5c31af7Sopenharmony_ci 154e5c31af7Sopenharmony_ci return content 155e5c31af7Sopenharmony_ci 156e5c31af7Sopenharmony_ci 157e5c31af7Sopenharmony_cidef gen_direct(methods): 158e5c31af7Sopenharmony_ci content = ""; 159e5c31af7Sopenharmony_ci 160e5c31af7Sopenharmony_ci template = Template(R''' 161e5c31af7Sopenharmony_ciif (!(ptrs_.${method} = reinterpret_cast<PFN_${method}>(getInstanceProcAddr(instance_, "${method}")))) { 162e5c31af7Sopenharmony_ci return Result("Vulkan: Unable to load ${method} pointer"); 163e5c31af7Sopenharmony_ci} 164e5c31af7Sopenharmony_ci''') 165e5c31af7Sopenharmony_ci 166e5c31af7Sopenharmony_ci for method in methods: 167e5c31af7Sopenharmony_ci content += template.substitute(method=method) 168e5c31af7Sopenharmony_ci 169e5c31af7Sopenharmony_ci return content 170e5c31af7Sopenharmony_ci 171e5c31af7Sopenharmony_ci 172e5c31af7Sopenharmony_cidef gen_direct_headers(methods): 173e5c31af7Sopenharmony_ci content = "" 174e5c31af7Sopenharmony_ci for method in methods: 175e5c31af7Sopenharmony_ci content += "PFN_{} {};\n".format(method, method); 176e5c31af7Sopenharmony_ci 177e5c31af7Sopenharmony_ci return content 178e5c31af7Sopenharmony_ci 179e5c31af7Sopenharmony_ci 180e5c31af7Sopenharmony_cidef main(): 181e5c31af7Sopenharmony_ci if len(sys.argv) != 3: 182e5c31af7Sopenharmony_ci print('usage: {} <outdir> <src_dir>'.format( 183e5c31af7Sopenharmony_ci sys.argv[0])) 184e5c31af7Sopenharmony_ci sys.exit(1) 185e5c31af7Sopenharmony_ci 186e5c31af7Sopenharmony_ci outdir = sys.argv[1] 187e5c31af7Sopenharmony_ci srcdir = sys.argv[2] 188e5c31af7Sopenharmony_ci 189e5c31af7Sopenharmony_ci vulkan_versions = ("1-0", "1-1") 190e5c31af7Sopenharmony_ci 191e5c31af7Sopenharmony_ci for vulkan_version in vulkan_versions: 192e5c31af7Sopenharmony_ci 193e5c31af7Sopenharmony_ci vkfile = os.path.join(srcdir, 'third_party', 'vulkan-headers', 'registry', 'vk.xml') 194e5c31af7Sopenharmony_ci incfile = os.path.join(srcdir, 'src', 'vulkan', 'vk-funcs-%s.inc' % vulkan_version) 195e5c31af7Sopenharmony_ci 196e5c31af7Sopenharmony_ci data = read_inc(incfile) 197e5c31af7Sopenharmony_ci 198e5c31af7Sopenharmony_ci wrapper_content = '' 199e5c31af7Sopenharmony_ci header_content = '' 200e5c31af7Sopenharmony_ci if os.path.isfile(vkfile): 201e5c31af7Sopenharmony_ci vk_data = read_vk(vkfile) 202e5c31af7Sopenharmony_ci wrapper_content = gen_wrappers(data, vk_data) 203e5c31af7Sopenharmony_ci header_content = gen_headers(data, vk_data) 204e5c31af7Sopenharmony_ci else: 205e5c31af7Sopenharmony_ci wrapper_content = gen_direct(data) 206e5c31af7Sopenharmony_ci header_content = gen_direct_headers(data) 207e5c31af7Sopenharmony_ci 208e5c31af7Sopenharmony_ci outfile = os.path.join(outdir, 'vk-wrappers-%s.inc' % vulkan_version) 209e5c31af7Sopenharmony_ci if os.path.isfile(outfile): 210e5c31af7Sopenharmony_ci with open(outfile, 'r') as f: 211e5c31af7Sopenharmony_ci if wrapper_content == f.read(): 212e5c31af7Sopenharmony_ci return 213e5c31af7Sopenharmony_ci with open(outfile, 'w') as f: 214e5c31af7Sopenharmony_ci f.write(wrapper_content) 215e5c31af7Sopenharmony_ci 216e5c31af7Sopenharmony_ci hdrfile = os.path.join(outdir, 'vk-wrappers-%s.h' % vulkan_version) 217e5c31af7Sopenharmony_ci if os.path.isfile(hdrfile): 218e5c31af7Sopenharmony_ci with open(hdrfile, 'r') as f: 219e5c31af7Sopenharmony_ci if header_content == f.read(): 220e5c31af7Sopenharmony_ci return 221e5c31af7Sopenharmony_ci with open(hdrfile, 'w') as f: 222e5c31af7Sopenharmony_ci f.write(header_content) 223e5c31af7Sopenharmony_ci 224e5c31af7Sopenharmony_ci 225e5c31af7Sopenharmony_ciif __name__ == '__main__': 226e5c31af7Sopenharmony_ci main() 227