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#ifndef ${guard} 40#define ${guard} 41 42#ifdef __cplusplus 43extern "C" { 44#endif 45 46% for p in instance_prefixes: 47extern const struct vk_instance_entrypoint_table ${p}_instance_entrypoints; 48% endfor 49 50% for p in physical_device_prefixes: 51extern const struct vk_physical_device_entrypoint_table ${p}_physical_device_entrypoints; 52% endfor 53 54% for p in device_prefixes: 55extern const struct vk_device_entrypoint_table ${p}_device_entrypoints; 56% endfor 57 58% if gen_proto: 59% for e in instance_entrypoints: 60 % if e.guard is not None: 61#ifdef ${e.guard} 62 % endif 63 % for p in physical_device_prefixes: 64 VKAPI_ATTR ${e.return_type} VKAPI_CALL ${p}_${e.name}(${e.decl_params()}); 65 % endfor 66 % if e.guard is not None: 67#endif // ${e.guard} 68 % endif 69% endfor 70 71% for e in physical_device_entrypoints: 72 % if e.guard is not None: 73#ifdef ${e.guard} 74 % endif 75 % for p in physical_device_prefixes: 76 VKAPI_ATTR ${e.return_type} VKAPI_CALL ${p}_${e.name}(${e.decl_params()}); 77 % endfor 78 % if e.guard is not None: 79#endif // ${e.guard} 80 % endif 81% endfor 82 83% for e in device_entrypoints: 84 % if e.guard is not None: 85#ifdef ${e.guard} 86 % endif 87 % for p in device_prefixes: 88 VKAPI_ATTR ${e.return_type} VKAPI_CALL ${p}_${e.name}(${e.decl_params()}); 89 % endfor 90 % if e.guard is not None: 91#endif // ${e.guard} 92 % endif 93% endfor 94% endif 95 96#ifdef __cplusplus 97} 98#endif 99 100#endif /* ${guard} */ 101""") 102 103TEMPLATE_C = Template(COPYRIGHT + """ 104/* This file generated from ${filename}, don't edit directly. */ 105 106#include "${header}" 107 108/* Weak aliases for all potential implementations. These will resolve to 109 * NULL if they're not defined, which lets the resolve_entrypoint() function 110 * either pick the correct entry point. 111 * 112 * MSVC uses different decorated names for 32-bit versus 64-bit. Declare 113 * all argument sizes for 32-bit because computing the actual size would be 114 * difficult. 115 */ 116 117<%def name="entrypoint_table(type, entrypoints, prefixes)"> 118% if gen_weak: 119 % for e in entrypoints: 120 % if e.guard is not None: 121#ifdef ${e.guard} 122 % endif 123 % for p in prefixes: 124#ifdef _MSC_VER 125#ifdef _M_IX86 126 % for args_size in [4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 60, 104]: 127 #pragma comment(linker, "/alternatename:_${p}_${e.name}@${args_size}=_vk_entrypoint_stub@0") 128 % endfor 129#else 130 #pragma comment(linker, "/alternatename:${p}_${e.name}=vk_entrypoint_stub") 131#if defined(_M_ARM64EC) 132 #pragma comment(linker, "/alternatename:#${p}_${e.name}=#vk_entrypoint_stub") 133#endif 134#endif 135#else 136 VKAPI_ATTR ${e.return_type} VKAPI_CALL ${p}_${e.name}(${e.decl_params()}) __attribute__ ((weak)); 137#endif 138 % endfor 139 % if e.guard is not None: 140#endif // ${e.guard} 141 % endif 142 % endfor 143% endif 144 145% for p in prefixes: 146const struct vk_${type}_entrypoint_table ${p}_${type}_entrypoints = { 147 % for e in entrypoints: 148 % if e.guard is not None: 149#ifdef ${e.guard} 150 % endif 151 .${e.name} = ${p}_${e.name}, 152 % if e.guard is not None: 153#elif defined(_MSC_VER) 154 .${e.name} = (PFN_vkVoidFunction)vk_entrypoint_stub, 155#endif // ${e.guard} 156 % endif 157 % endfor 158}; 159% endfor 160</%def> 161 162${entrypoint_table('instance', instance_entrypoints, instance_prefixes)} 163${entrypoint_table('physical_device', physical_device_entrypoints, physical_device_prefixes)} 164${entrypoint_table('device', device_entrypoints, device_prefixes)} 165""") 166 167def get_entrypoints_defines(doc): 168 """Maps entry points to extension defines.""" 169 entrypoints_to_defines = {} 170 171 platform_define = {} 172 for platform in doc.findall('./platforms/platform'): 173 name = platform.attrib['name'] 174 define = platform.attrib['protect'] 175 platform_define[name] = define 176 177 for extension in doc.findall('./extensions/extension[@platform]'): 178 platform = extension.attrib['platform'] 179 define = platform_define[platform] 180 181 for entrypoint in extension.findall('./require/command'): 182 fullname = entrypoint.attrib['name'] 183 entrypoints_to_defines[fullname] = define 184 185 return entrypoints_to_defines 186 187 188def main(): 189 parser = argparse.ArgumentParser() 190 parser.add_argument('--out-c', required=True, help='Output C file.') 191 parser.add_argument('--out-h', required=True, help='Output H file.') 192 parser.add_argument('--xml', 193 help='Vulkan API XML file.', 194 required=True, action='append', dest='xml_files') 195 parser.add_argument('--proto', help='Generate entrypoint prototypes', 196 action='store_true', dest='gen_proto') 197 parser.add_argument('--weak', help='Generate weak entrypoint declarations', 198 action='store_true', dest='gen_weak') 199 parser.add_argument('--prefix', 200 help='Prefix to use for all dispatch tables.', 201 action='append', default=[], dest='prefixes') 202 parser.add_argument('--device-prefix', 203 help='Prefix to use for device dispatch tables.', 204 action='append', default=[], dest='device_prefixes') 205 args = parser.parse_args() 206 207 instance_prefixes = args.prefixes 208 physical_device_prefixes = args.prefixes 209 device_prefixes = args.prefixes + args.device_prefixes 210 211 entrypoints = get_entrypoints_from_xml(args.xml_files) 212 213 device_entrypoints = [] 214 physical_device_entrypoints = [] 215 instance_entrypoints = [] 216 for e in entrypoints: 217 if e.is_device_entrypoint(): 218 device_entrypoints.append(e) 219 elif e.is_physical_device_entrypoint(): 220 physical_device_entrypoints.append(e) 221 else: 222 instance_entrypoints.append(e) 223 224 assert os.path.dirname(args.out_c) == os.path.dirname(args.out_h) 225 226 environment = { 227 'gen_proto': args.gen_proto, 228 'gen_weak': args.gen_weak, 229 'header': os.path.basename(args.out_h), 230 'instance_entrypoints': instance_entrypoints, 231 'instance_prefixes': instance_prefixes, 232 'physical_device_entrypoints': physical_device_entrypoints, 233 'physical_device_prefixes': physical_device_prefixes, 234 'device_entrypoints': device_entrypoints, 235 'device_prefixes': device_prefixes, 236 'filename': os.path.basename(__file__), 237 } 238 239 # For outputting entrypoints.h we generate a anv_EntryPoint() prototype 240 # per entry point. 241 try: 242 with open(args.out_h, 'w', encoding='utf-8') as f: 243 guard = os.path.basename(args.out_h).replace('.', '_').upper() 244 f.write(TEMPLATE_H.render(guard=guard, **environment)) 245 with open(args.out_c, 'w', encoding='utf-8') as f: 246 f.write(TEMPLATE_C.render(**environment)) 247 248 except Exception: 249 # In the event there's an error, this imports some helpers from mako 250 # to print a useful stack trace and prints it, then exits with 251 # status 1, if python is run with debug; otherwise it just raises 252 # the exception 253 import sys 254 from mako import exceptions 255 print(exceptions.text_error_template().render(), file=sys.stderr) 256 sys.exit(1) 257 258if __name__ == '__main__': 259 main() 260