1#!/usr/bin/python3 2# 3# Copyright (c) 2013-2017 The Khronos Group Inc. 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17import argparse, cProfile, pdb, string, sys, time 18from reg import * 19from generator import write 20from cgenerator import CGeneratorOptions, COutputGenerator 21# LoaderAndValidationLayer Generator Modifications 22from threading_generator import ThreadGeneratorOptions, ThreadOutputGenerator 23from parameter_validation_generator import ParameterValidationGeneratorOptions, ParameterValidationOutputGenerator 24from unique_objects_generator import UniqueObjectsGeneratorOptions, UniqueObjectsOutputGenerator 25from object_tracker_generator import ObjectTrackerGeneratorOptions, ObjectTrackerOutputGenerator 26from dispatch_table_helper_generator import DispatchTableHelperOutputGenerator, DispatchTableHelperOutputGeneratorOptions 27from helper_file_generator import HelperFileOutputGenerator, HelperFileOutputGeneratorOptions 28from loader_extension_generator import LoaderExtensionOutputGenerator, LoaderExtensionGeneratorOptions 29from mock_icd_generator import MockICDGeneratorOptions, MockICDOutputGenerator 30 31# Simple timer functions 32startTime = None 33 34def startTimer(timeit): 35 global startTime 36 startTime = time.clock() 37 38def endTimer(timeit, msg): 39 global startTime 40 endTime = time.clock() 41 if (timeit): 42 write(msg, endTime - startTime, file=sys.stderr) 43 startTime = None 44 45# Turn a list of strings into a regexp string matching exactly those strings 46def makeREstring(list): 47 return '^(' + '|'.join(list) + ')$' 48 49# Returns a directory of [ generator function, generator options ] indexed 50# by specified short names. The generator options incorporate the following 51# parameters: 52# 53# extensions - list of extension names to include. 54# protect - True if re-inclusion protection should be added to headers 55# directory - path to directory in which to generate the target(s) 56def makeGenOpts(extensions = [], removeExtensions = [], protect = True, directory = '.'): 57 global genOpts 58 genOpts = {} 59 60 # Descriptive names for various regexp patterns used to select 61 # versions and extensions 62 allVersions = allExtensions = '.*' 63 noVersions = noExtensions = None 64 65 addExtensions = makeREstring(extensions) 66 removeExtensions = makeREstring(removeExtensions) 67 68 # Copyright text prefixing all headers (list of strings). 69 prefixStrings = [ 70 '/*', 71 '** Copyright (c) 2015-2017 The Khronos Group Inc.', 72 '**', 73 '** Licensed under the Apache License, Version 2.0 (the "License");', 74 '** you may not use this file except in compliance with the License.', 75 '** You may obtain a copy of the License at', 76 '**', 77 '** http://www.apache.org/licenses/LICENSE-2.0', 78 '**', 79 '** Unless required by applicable law or agreed to in writing, software', 80 '** distributed under the License is distributed on an "AS IS" BASIS,', 81 '** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.', 82 '** See the License for the specific language governing permissions and', 83 '** limitations under the License.', 84 '*/', 85 '' 86 ] 87 88 # Text specific to Vulkan headers 89 vkPrefixStrings = [ 90 '/*', 91 '** This header is generated from the Khronos Vulkan XML API Registry.', 92 '**', 93 '*/', 94 '' 95 ] 96 97 # Defaults for generating re-inclusion protection wrappers (or not) 98 protectFile = protect 99 protectFeature = protect 100 protectProto = protect 101 102 103 # 104 # LoaderAndValidationLayer Generators 105 # Options for threading layer 106 genOpts['thread_check.h'] = [ 107 ThreadOutputGenerator, 108 ThreadGeneratorOptions( 109 filename = 'thread_check.h', 110 directory = directory, 111 apiname = 'vulkan', 112 profile = None, 113 versions = allVersions, 114 emitversions = allVersions, 115 defaultExtensions = 'vulkan', 116 addExtensions = addExtensions, 117 removeExtensions = removeExtensions, 118 prefixText = prefixStrings + vkPrefixStrings, 119 protectFeature = False, 120 apicall = 'VKAPI_ATTR ', 121 apientry = 'VKAPI_CALL ', 122 apientryp = 'VKAPI_PTR *', 123 alignFuncParam = 48) 124 ] 125 126 # Options for parameter validation layer 127 genOpts['parameter_validation.cpp'] = [ 128 ParameterValidationOutputGenerator, 129 ParameterValidationGeneratorOptions( 130 filename = 'parameter_validation.cpp', 131 directory = directory, 132 apiname = 'vulkan', 133 profile = None, 134 versions = allVersions, 135 emitversions = allVersions, 136 defaultExtensions = 'vulkan', 137 addExtensions = addExtensions, 138 removeExtensions = removeExtensions, 139 prefixText = prefixStrings + vkPrefixStrings, 140 protectFeature = False, 141 apicall = 'VKAPI_ATTR ', 142 apientry = 'VKAPI_CALL ', 143 apientryp = 'VKAPI_PTR *', 144 alignFuncParam = 48) 145 ] 146 147 # Options for unique objects layer 148 genOpts['unique_objects_wrappers.h'] = [ 149 UniqueObjectsOutputGenerator, 150 UniqueObjectsGeneratorOptions( 151 filename = 'unique_objects_wrappers.h', 152 directory = directory, 153 apiname = 'vulkan', 154 profile = None, 155 versions = allVersions, 156 emitversions = allVersions, 157 defaultExtensions = 'vulkan', 158 addExtensions = addExtensions, 159 removeExtensions = removeExtensions, 160 prefixText = prefixStrings + vkPrefixStrings, 161 protectFeature = False, 162 apicall = 'VKAPI_ATTR ', 163 apientry = 'VKAPI_CALL ', 164 apientryp = 'VKAPI_PTR *', 165 alignFuncParam = 48) 166 ] 167 168 # Options for object_tracker layer 169 genOpts['object_tracker.cpp'] = [ 170 ObjectTrackerOutputGenerator, 171 ObjectTrackerGeneratorOptions( 172 filename = 'object_tracker.cpp', 173 directory = directory, 174 apiname = 'vulkan', 175 profile = None, 176 versions = allVersions, 177 emitversions = allVersions, 178 defaultExtensions = 'vulkan', 179 addExtensions = addExtensions, 180 removeExtensions = removeExtensions, 181 prefixText = prefixStrings + vkPrefixStrings, 182 protectFeature = False, 183 apicall = 'VKAPI_ATTR ', 184 apientry = 'VKAPI_CALL ', 185 apientryp = 'VKAPI_PTR *', 186 alignFuncParam = 48) 187 ] 188 189 # Options for dispatch table helper generator 190 genOpts['vk_dispatch_table_helper.h'] = [ 191 DispatchTableHelperOutputGenerator, 192 DispatchTableHelperOutputGeneratorOptions( 193 filename = 'vk_dispatch_table_helper.h', 194 directory = directory, 195 apiname = 'vulkan', 196 profile = None, 197 versions = allVersions, 198 emitversions = allVersions, 199 defaultExtensions = 'vulkan', 200 addExtensions = addExtensions, 201 removeExtensions = removeExtensions, 202 prefixText = prefixStrings + vkPrefixStrings, 203 protectFeature = False, 204 apicall = 'VKAPI_ATTR ', 205 apientry = 'VKAPI_CALL ', 206 apientryp = 'VKAPI_PTR *', 207 alignFuncParam = 48) 208 ] 209 210 # Options for Layer dispatch table generator 211 genOpts['vk_layer_dispatch_table.h'] = [ 212 LoaderExtensionOutputGenerator, 213 LoaderExtensionGeneratorOptions( 214 filename = 'vk_layer_dispatch_table.h', 215 directory = directory, 216 apiname = 'vulkan', 217 profile = None, 218 versions = allVersions, 219 emitversions = allVersions, 220 defaultExtensions = 'vulkan', 221 addExtensions = addExtensions, 222 removeExtensions = removeExtensions, 223 prefixText = prefixStrings + vkPrefixStrings, 224 protectFeature = False, 225 apicall = 'VKAPI_ATTR ', 226 apientry = 'VKAPI_CALL ', 227 apientryp = 'VKAPI_PTR *', 228 alignFuncParam = 48) 229 ] 230 231 # Options for loader extension source generator 232 genOpts['vk_loader_extensions.h'] = [ 233 LoaderExtensionOutputGenerator, 234 LoaderExtensionGeneratorOptions( 235 filename = 'vk_loader_extensions.h', 236 directory = directory, 237 apiname = 'vulkan', 238 profile = None, 239 versions = allVersions, 240 emitversions = allVersions, 241 defaultExtensions = 'vulkan', 242 addExtensions = addExtensions, 243 removeExtensions = removeExtensions, 244 prefixText = prefixStrings + vkPrefixStrings, 245 protectFeature = False, 246 apicall = 'VKAPI_ATTR ', 247 apientry = 'VKAPI_CALL ', 248 apientryp = 'VKAPI_PTR *', 249 alignFuncParam = 48) 250 ] 251 252 # Options for loader extension source generator 253 genOpts['vk_loader_extensions.c'] = [ 254 LoaderExtensionOutputGenerator, 255 LoaderExtensionGeneratorOptions( 256 filename = 'vk_loader_extensions.c', 257 directory = directory, 258 apiname = 'vulkan', 259 profile = None, 260 versions = allVersions, 261 emitversions = allVersions, 262 defaultExtensions = 'vulkan', 263 addExtensions = addExtensions, 264 removeExtensions = removeExtensions, 265 prefixText = prefixStrings + vkPrefixStrings, 266 protectFeature = False, 267 apicall = 'VKAPI_ATTR ', 268 apientry = 'VKAPI_CALL ', 269 apientryp = 'VKAPI_PTR *', 270 alignFuncParam = 48) 271 ] 272 273 # Helper file generator options for vk_enum_string_helper.h 274 genOpts['vk_enum_string_helper.h'] = [ 275 HelperFileOutputGenerator, 276 HelperFileOutputGeneratorOptions( 277 filename = 'vk_enum_string_helper.h', 278 directory = directory, 279 apiname = 'vulkan', 280 profile = None, 281 versions = allVersions, 282 emitversions = allVersions, 283 defaultExtensions = 'vulkan', 284 addExtensions = addExtensions, 285 removeExtensions = removeExtensions, 286 prefixText = prefixStrings + vkPrefixStrings, 287 protectFeature = False, 288 apicall = 'VKAPI_ATTR ', 289 apientry = 'VKAPI_CALL ', 290 apientryp = 'VKAPI_PTR *', 291 alignFuncParam = 48, 292 helper_file_type = 'enum_string_header') 293 ] 294 295 # Helper file generator options for vk_struct_size_helper.h 296 genOpts['vk_struct_size_helper.h'] = [ 297 HelperFileOutputGenerator, 298 HelperFileOutputGeneratorOptions( 299 filename = 'vk_struct_size_helper.h', 300 directory = directory, 301 apiname = 'vulkan', 302 profile = None, 303 versions = allVersions, 304 emitversions = allVersions, 305 defaultExtensions = 'vulkan', 306 addExtensions = addExtensions, 307 removeExtensions = removeExtensions, 308 prefixText = prefixStrings + vkPrefixStrings, 309 protectFeature = False, 310 apicall = 'VKAPI_ATTR ', 311 apientry = 'VKAPI_CALL ', 312 apientryp = 'VKAPI_PTR *', 313 alignFuncParam = 48, 314 helper_file_type = 'struct_size_header') 315 ] 316 317 # Helper file generator options for vk_struct_size_helper.c 318 genOpts['vk_struct_size_helper.c'] = [ 319 HelperFileOutputGenerator, 320 HelperFileOutputGeneratorOptions( 321 filename = 'vk_struct_size_helper.c', 322 directory = directory, 323 apiname = 'vulkan', 324 profile = None, 325 versions = allVersions, 326 emitversions = allVersions, 327 defaultExtensions = 'vulkan', 328 addExtensions = addExtensions, 329 removeExtensions = removeExtensions, 330 prefixText = prefixStrings + vkPrefixStrings, 331 protectFeature = False, 332 apicall = 'VKAPI_ATTR ', 333 apientry = 'VKAPI_CALL ', 334 apientryp = 'VKAPI_PTR *', 335 alignFuncParam = 48, 336 helper_file_type = 'struct_size_source') 337 ] 338 339 # Helper file generator options for vk_safe_struct.h 340 genOpts['vk_safe_struct.h'] = [ 341 HelperFileOutputGenerator, 342 HelperFileOutputGeneratorOptions( 343 filename = 'vk_safe_struct.h', 344 directory = directory, 345 apiname = 'vulkan', 346 profile = None, 347 versions = allVersions, 348 emitversions = allVersions, 349 defaultExtensions = 'vulkan', 350 addExtensions = addExtensions, 351 removeExtensions = removeExtensions, 352 prefixText = prefixStrings + vkPrefixStrings, 353 protectFeature = False, 354 apicall = 'VKAPI_ATTR ', 355 apientry = 'VKAPI_CALL ', 356 apientryp = 'VKAPI_PTR *', 357 alignFuncParam = 48, 358 helper_file_type = 'safe_struct_header') 359 ] 360 361 # Helper file generator options for vk_safe_struct.cpp 362 genOpts['vk_safe_struct.cpp'] = [ 363 HelperFileOutputGenerator, 364 HelperFileOutputGeneratorOptions( 365 filename = 'vk_safe_struct.cpp', 366 directory = directory, 367 apiname = 'vulkan', 368 profile = None, 369 versions = allVersions, 370 emitversions = allVersions, 371 defaultExtensions = 'vulkan', 372 addExtensions = addExtensions, 373 removeExtensions = removeExtensions, 374 prefixText = prefixStrings + vkPrefixStrings, 375 protectFeature = False, 376 apicall = 'VKAPI_ATTR ', 377 apientry = 'VKAPI_CALL ', 378 apientryp = 'VKAPI_PTR *', 379 alignFuncParam = 48, 380 helper_file_type = 'safe_struct_source') 381 ] 382 383 # Helper file generator options for vk_object_types.h 384 genOpts['vk_object_types.h'] = [ 385 HelperFileOutputGenerator, 386 HelperFileOutputGeneratorOptions( 387 filename = 'vk_object_types.h', 388 directory = directory, 389 apiname = 'vulkan', 390 profile = None, 391 versions = allVersions, 392 emitversions = allVersions, 393 defaultExtensions = 'vulkan', 394 addExtensions = addExtensions, 395 removeExtensions = removeExtensions, 396 prefixText = prefixStrings + vkPrefixStrings, 397 protectFeature = False, 398 apicall = 'VKAPI_ATTR ', 399 apientry = 'VKAPI_CALL ', 400 apientryp = 'VKAPI_PTR *', 401 alignFuncParam = 48, 402 helper_file_type = 'object_types_header') 403 ] 404 405 # Helper file generator options for extension_helper.h 406 genOpts['vk_extension_helper.h'] = [ 407 HelperFileOutputGenerator, 408 HelperFileOutputGeneratorOptions( 409 filename = 'vk_extension_helper.h', 410 directory = directory, 411 apiname = 'vulkan', 412 profile = None, 413 versions = allVersions, 414 emitversions = allVersions, 415 defaultExtensions = 'vulkan', 416 addExtensions = addExtensions, 417 removeExtensions = removeExtensions, 418 prefixText = prefixStrings + vkPrefixStrings, 419 protectFeature = False, 420 apicall = 'VKAPI_ATTR ', 421 apientry = 'VKAPI_CALL ', 422 apientryp = 'VKAPI_PTR *', 423 alignFuncParam = 48, 424 helper_file_type = 'extension_helper_header') 425 ] 426 427 # Helper file generator options for typemap_helper.h 428 genOpts['vk_typemap_helper.h'] = [ 429 HelperFileOutputGenerator, 430 HelperFileOutputGeneratorOptions( 431 filename = 'vk_typemap_helper.h', 432 directory = directory, 433 apiname = 'vulkan', 434 profile = None, 435 versions = allVersions, 436 emitversions = allVersions, 437 defaultExtensions = 'vulkan', 438 addExtensions = addExtensions, 439 removeExtensions = removeExtensions, 440 prefixText = prefixStrings + vkPrefixStrings, 441 protectFeature = False, 442 apicall = 'VKAPI_ATTR ', 443 apientry = 'VKAPI_CALL ', 444 apientryp = 'VKAPI_PTR *', 445 alignFuncParam = 48, 446 helper_file_type = 'typemap_helper_header') 447 ] 448 449 # Options for mock ICD header 450 genOpts['mock_icd.h'] = [ 451 MockICDOutputGenerator, 452 MockICDGeneratorOptions( 453 filename = 'mock_icd.h', 454 directory = directory, 455 apiname = 'vulkan', 456 profile = None, 457 versions = allVersions, 458 emitversions = allVersions, 459 defaultExtensions = 'vulkan', 460 addExtensions = addExtensions, 461 removeExtensions = removeExtensions, 462 prefixText = prefixStrings + vkPrefixStrings, 463 protectFeature = False, 464 apicall = 'VKAPI_ATTR ', 465 apientry = 'VKAPI_CALL ', 466 apientryp = 'VKAPI_PTR *', 467 alignFuncParam = 48, 468 helper_file_type = 'mock_icd_header') 469 ] 470 471 # Options for mock ICD cpp 472 genOpts['mock_icd.cpp'] = [ 473 MockICDOutputGenerator, 474 MockICDGeneratorOptions( 475 filename = 'mock_icd.cpp', 476 directory = directory, 477 apiname = 'vulkan', 478 profile = None, 479 versions = allVersions, 480 emitversions = allVersions, 481 defaultExtensions = 'vulkan', 482 addExtensions = addExtensions, 483 removeExtensions = removeExtensions, 484 prefixText = prefixStrings + vkPrefixStrings, 485 protectFeature = False, 486 apicall = 'VKAPI_ATTR ', 487 apientry = 'VKAPI_CALL ', 488 apientryp = 'VKAPI_PTR *', 489 alignFuncParam = 48, 490 helper_file_type = 'mock_icd_source') 491 ] 492 493# Generate a target based on the options in the matching genOpts{} object. 494# This is encapsulated in a function so it can be profiled and/or timed. 495# The args parameter is an parsed argument object containing the following 496# fields that are used: 497# target - target to generate 498# directory - directory to generate it in 499# protect - True if re-inclusion wrappers should be created 500# extensions - list of additional extensions to include in generated 501# interfaces 502def genTarget(args): 503 global genOpts 504 505 # Create generator options with specified parameters 506 makeGenOpts(extensions = args.extension, 507 removeExtensions = args.removeExtension, 508 protect = args.protect, 509 directory = args.directory) 510 511 if (args.target in genOpts.keys()): 512 createGenerator = genOpts[args.target][0] 513 options = genOpts[args.target][1] 514 515 if not args.quiet: 516 write('* Building', options.filename, file=sys.stderr) 517 518 startTimer(args.time) 519 gen = createGenerator(errFile=errWarn, 520 warnFile=errWarn, 521 diagFile=diag) 522 reg.setGenerator(gen) 523 reg.apiGen(options) 524 525 if not args.quiet: 526 write('* Generated', options.filename, file=sys.stderr) 527 endTimer(args.time, '* Time to generate ' + options.filename + ' =') 528 else: 529 write('No generator options for unknown target:', 530 args.target, file=sys.stderr) 531 532# -extension name - may be a single extension name, a a space-separated list 533# of names, or a regular expression. 534if __name__ == '__main__': 535 parser = argparse.ArgumentParser() 536 537 parser.add_argument('-extension', action='append', 538 default=[], 539 help='Specify an extension or extensions to add to targets') 540 parser.add_argument('-removeExtension', action='append', 541 default=[], 542 help='Specify an extension or extensions to remove from targets') 543 parser.add_argument('-debug', action='store_true', 544 help='Enable debugging') 545 parser.add_argument('-dump', action='store_true', 546 help='Enable dump to stderr') 547 parser.add_argument('-diagfile', action='store', 548 default=None, 549 help='Write diagnostics to specified file') 550 parser.add_argument('-errfile', action='store', 551 default=None, 552 help='Write errors and warnings to specified file instead of stderr') 553 parser.add_argument('-noprotect', dest='protect', action='store_false', 554 help='Disable inclusion protection in output headers') 555 parser.add_argument('-profile', action='store_true', 556 help='Enable profiling') 557 parser.add_argument('-registry', action='store', 558 default='vk.xml', 559 help='Use specified registry file instead of vk.xml') 560 parser.add_argument('-time', action='store_true', 561 help='Enable timing') 562 parser.add_argument('-validate', action='store_true', 563 help='Enable group validation') 564 parser.add_argument('-o', action='store', dest='directory', 565 default='.', 566 help='Create target and related files in specified directory') 567 parser.add_argument('target', metavar='target', nargs='?', 568 help='Specify target') 569 parser.add_argument('-quiet', action='store_true', default=False, 570 help='Suppress script output during normal execution.') 571 572 args = parser.parse_args() 573 574 # This splits arguments which are space-separated lists 575 args.extension = [name for arg in args.extension for name in arg.split()] 576 577 # Load & parse registry 578 reg = Registry() 579 580 startTimer(args.time) 581 tree = etree.parse(args.registry) 582 endTimer(args.time, '* Time to make ElementTree =') 583 584 startTimer(args.time) 585 reg.loadElementTree(tree) 586 endTimer(args.time, '* Time to parse ElementTree =') 587 588 if (args.validate): 589 reg.validateGroups() 590 591 if (args.dump): 592 write('* Dumping registry to regdump.txt', file=sys.stderr) 593 reg.dumpReg(filehandle = open('regdump.txt', 'w', encoding='utf-8')) 594 595 # create error/warning & diagnostic files 596 if (args.errfile): 597 errWarn = open(args.errfile, 'w', encoding='utf-8') 598 else: 599 errWarn = sys.stderr 600 601 if (args.diagfile): 602 diag = open(args.diagfile, 'w', encoding='utf-8') 603 else: 604 diag = None 605 606 if (args.debug): 607 pdb.run('genTarget(args)') 608 elif (args.profile): 609 import cProfile, pstats 610 cProfile.run('genTarget(args)', 'profile.txt') 611 p = pstats.Stats('profile.txt') 612 p.strip_dirs().sort_stats('time').print_stats(50) 613 else: 614 genTarget(args) 615