1# coding=utf-8 2COPYRIGHT=u""" 3/* Copyright © 2015-2021 Intel Corporation 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice (including the next 13 * paragraph) shall be included in all copies or substantial portions of the 14 * Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 * IN THE SOFTWARE. 23 */ 24""" 25 26import argparse 27import os 28 29from mako.template import Template 30 31# Mesa-local imports must be declared in meson variable 32# '{file_without_suffix}_depend_files'. 33from vk_dispatch_table_gen import get_entrypoints_from_xml 34 35TEMPLATE_H = Template(COPYRIGHT + """\ 36/* This file generated from ${filename}, don't edit directly. */ 37 38#include "vk_dispatch_table.h" 39 40#ifndef ${guard} 41#define ${guard} 42 43#ifdef __cplusplus 44extern "C" { 45#endif 46 47% for p in instance_prefixes: 48extern const struct vk_instance_entrypoint_table ${p}_instance_entrypoints; 49% endfor 50 51% for p in physical_device_prefixes: 52extern const struct vk_physical_device_entrypoint_table ${p}_physical_device_entrypoints; 53% endfor 54 55% for p in device_prefixes: 56extern const struct vk_device_entrypoint_table ${p}_device_entrypoints; 57% endfor 58 59% if gen_proto: 60% for e in instance_entrypoints: 61 % if e.guard is not None: 62#ifdef ${e.guard} 63 % endif 64 % for p in physical_device_prefixes: 65 VKAPI_ATTR ${e.return_type} VKAPI_CALL ${p}_${e.name}(${e.decl_params()}); 66 % endfor 67 % if e.guard is not None: 68#endif // ${e.guard} 69 % endif 70% endfor 71 72% for e in physical_device_entrypoints: 73 % if e.guard is not None: 74#ifdef ${e.guard} 75 % endif 76 % for p in physical_device_prefixes: 77 VKAPI_ATTR ${e.return_type} VKAPI_CALL ${p}_${e.name}(${e.decl_params()}); 78 % endfor 79 % if e.guard is not None: 80#endif // ${e.guard} 81 % endif 82% endfor 83 84% for e in device_entrypoints: 85 % if e.guard is not None: 86#ifdef ${e.guard} 87 % endif 88 % for p in device_prefixes: 89 VKAPI_ATTR ${e.return_type} VKAPI_CALL ${p}_${e.name}(${e.decl_params()}); 90 % endfor 91 % if e.guard is not None: 92#endif // ${e.guard} 93 % endif 94% endfor 95% endif 96 97#ifdef __cplusplus 98} 99#endif 100 101#endif /* ${guard} */ 102""") 103 104TEMPLATE_C = Template(COPYRIGHT + """ 105/* This file generated from ${filename}, don't edit directly. */ 106 107#include "${header}" 108 109/* Weak aliases for all potential implementations. These will resolve to 110 * NULL if they're not defined, which lets the resolve_entrypoint() function 111 * either pick the correct entry point. 112 * 113 * MSVC uses different decorated names for 32-bit versus 64-bit. Declare 114 * all argument sizes for 32-bit because computing the actual size would be 115 * difficult. 116 */ 117 118<%def name="entrypoint_table(type, entrypoints, prefixes)"> 119% if gen_weak: 120 % for e in entrypoints: 121 % if e.guard is not None: 122#ifdef ${e.guard} 123 % endif 124 % for p in prefixes: 125#ifdef _MSC_VER 126#ifdef _M_IX86 127 % for args_size in [4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 60, 104]: 128 #pragma comment(linker, "/alternatename:_${p}_${e.name}@${args_size}=_vk_entrypoint_stub@0") 129 % endfor 130#else 131 #pragma comment(linker, "/alternatename:${p}_${e.name}=vk_entrypoint_stub") 132#endif 133#else 134 VKAPI_ATTR ${e.return_type} VKAPI_CALL ${p}_${e.name}(${e.decl_params()}) __attribute__ ((weak)); 135#endif 136 % endfor 137 % if e.guard is not None: 138#endif // ${e.guard} 139 % endif 140 % endfor 141% endif 142 143% for p in prefixes: 144const struct vk_${type}_entrypoint_table ${p}_${type}_entrypoints = { 145 % for e in entrypoints: 146 % if e.guard is not None: 147#ifdef ${e.guard} 148 % endif 149 .${e.name} = ${p}_${e.name}, 150 % if e.guard is not None: 151#elif defined(_MSC_VER) 152 .${e.name} = (PFN_vkVoidFunction)vk_entrypoint_stub, 153#endif // ${e.guard} 154 % endif 155 % endfor 156}; 157% endfor 158</%def> 159 160${entrypoint_table('instance', instance_entrypoints, instance_prefixes)} 161${entrypoint_table('physical_device', physical_device_entrypoints, physical_device_prefixes)} 162${entrypoint_table('device', device_entrypoints, device_prefixes)} 163""") 164 165def get_entrypoints_defines(doc): 166 """Maps entry points to extension defines.""" 167 entrypoints_to_defines = {} 168 169 platform_define = {} 170 for platform in doc.findall('./platforms/platform'): 171 name = platform.attrib['name'] 172 define = platform.attrib['protect'] 173 platform_define[name] = define 174 175 for extension in doc.findall('./extensions/extension[@platform]'): 176 platform = extension.attrib['platform'] 177 define = platform_define[platform] 178 179 for entrypoint in extension.findall('./require/command'): 180 fullname = entrypoint.attrib['name'] 181 entrypoints_to_defines[fullname] = define 182 183 return entrypoints_to_defines 184 185 186def main(): 187 parser = argparse.ArgumentParser() 188 parser.add_argument('--out-c', required=True, help='Output C file.') 189 parser.add_argument('--out-h', required=True, help='Output H file.') 190 parser.add_argument('--xml', 191 help='Vulkan API XML file.', 192 required=True, action='append', dest='xml_files') 193 parser.add_argument('--proto', help='Generate entrypoint prototypes', 194 action='store_true', dest='gen_proto') 195 parser.add_argument('--weak', help='Generate weak entrypoint declarations', 196 action='store_true', dest='gen_weak') 197 parser.add_argument('--prefix', 198 help='Prefix to use for all dispatch tables.', 199 action='append', default=[], dest='prefixes') 200 parser.add_argument('--device-prefix', 201 help='Prefix to use for device dispatch tables.', 202 action='append', default=[], dest='device_prefixes') 203 args = parser.parse_args() 204 205 instance_prefixes = args.prefixes 206 physical_device_prefixes = args.prefixes 207 device_prefixes = args.prefixes + args.device_prefixes 208 209 entrypoints = get_entrypoints_from_xml(args.xml_files) 210 211 device_entrypoints = [] 212 physical_device_entrypoints = [] 213 instance_entrypoints = [] 214 for e in entrypoints: 215 if e.is_device_entrypoint(): 216 device_entrypoints.append(e) 217 elif e.is_physical_device_entrypoint(): 218 physical_device_entrypoints.append(e) 219 else: 220 instance_entrypoints.append(e) 221 222 assert os.path.dirname(args.out_c) == os.path.dirname(args.out_h) 223 224 environment = { 225 'gen_proto': args.gen_proto, 226 'gen_weak': args.gen_weak, 227 'header': os.path.basename(args.out_h), 228 'instance_entrypoints': instance_entrypoints, 229 'instance_prefixes': instance_prefixes, 230 'physical_device_entrypoints': physical_device_entrypoints, 231 'physical_device_prefixes': physical_device_prefixes, 232 'device_entrypoints': device_entrypoints, 233 'device_prefixes': device_prefixes, 234 'filename': os.path.basename(__file__), 235 } 236 237 # For outputting entrypoints.h we generate a anv_EntryPoint() prototype 238 # per entry point. 239 try: 240 with open(args.out_h, 'w') as f: 241 guard = os.path.basename(args.out_h).replace('.', '_').upper() 242 f.write(TEMPLATE_H.render(guard=guard, **environment)) 243 with open(args.out_c, 'w') as f: 244 f.write(TEMPLATE_C.render(**environment)) 245 246 except Exception: 247 # In the event there's an error, this imports some helpers from mako 248 # to print a useful stack trace and prints it, then exits with 249 # status 1, if python is run with debug; otherwise it just raises 250 # the exception 251 if __debug__: 252 import sys 253 from mako import exceptions 254 sys.stderr.write(exceptions.text_error_template().render() + '\n') 255 sys.exit(1) 256 raise 257 258if __name__ == '__main__': 259 main() 260