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