1#!/usr/bin/python3 2# 3# Copyright 2013-2024 The Khronos Group Inc. 4# 5# SPDX-License-Identifier: Apache-2.0 6 7import argparse 8import os 9import pdb 10import re 11import sys 12import copy 13import time 14import xml.etree.ElementTree as etree 15 16sys.path.append(os.path.abspath(os.path.dirname(__file__))) 17 18from cgenerator import CGeneratorOptions, COutputGenerator 19# Vulkan SC modules 20from json_parser import JSONParserGenerator, JSONParserOptions 21from schema_generator import SchemaGeneratorOptions, SchemaOutputGenerator 22from json_generator import JSONGeneratorOptions, JSONOutputGenerator 23from json_h_generator import JSONHeaderOutputGenerator, JSONHeaderGeneratorOptions 24from json_c_generator import JSONCOutputGenerator, JSONCGeneratorOptions 25 26from docgenerator import DocGeneratorOptions, DocOutputGenerator 27from extensionmetadocgenerator import (ExtensionMetaDocGeneratorOptions, 28 ExtensionMetaDocOutputGenerator) 29from interfacedocgenerator import InterfaceDocGenerator 30from generator import write 31from spirvcapgenerator import SpirvCapabilityOutputGenerator 32from hostsyncgenerator import HostSynchronizationOutputGenerator 33from formatsgenerator import FormatsOutputGenerator 34from syncgenerator import SyncOutputGenerator 35from jsgenerator import JSOutputGenerator 36from pygenerator import PyOutputGenerator 37from rubygenerator import RubyOutputGenerator 38from reflib import logDiag, logWarn, logErr, setLogFile 39from reg import Registry 40from validitygenerator import ValidityOutputGenerator 41from apiconventions import APIConventions 42 43# Simple timer functions 44startTime = None 45 46 47def startTimer(timeit): 48 global startTime 49 if timeit: 50 startTime = time.process_time() 51 52 53def endTimer(timeit, msg): 54 global startTime 55 if timeit and startTime is not None: 56 endTime = time.process_time() 57 logDiag(msg, endTime - startTime) 58 startTime = None 59 60 61def makeREstring(strings, default=None, strings_are_regex=False): 62 """Turn a list of strings into a regexp string matching exactly those strings.""" 63 if strings or default is None: 64 if not strings_are_regex: 65 strings = (re.escape(s) for s in strings) 66 return '^(' + '|'.join(strings) + ')$' 67 return default 68 69 70def makeGenOpts(args): 71 """Returns a directory of [ generator function, generator options ] indexed 72 by specified short names. The generator options incorporate the following 73 parameters: 74 75 args is an parsed argument object; see below for the fields that are used.""" 76 global genOpts 77 genOpts = {} 78 79 # Default class of extensions to include, or None 80 defaultExtensions = args.defaultExtensions 81 82 # Additional extensions to include (list of extensions) 83 extensions = args.extension 84 85 # Extensions to remove (list of extensions) 86 removeExtensions = args.removeExtensions 87 88 # Extensions to emit (list of extensions) 89 emitExtensions = args.emitExtensions 90 91 # SPIR-V capabilities / features to emit (list of extensions & capabilities) 92 emitSpirv = args.emitSpirv 93 94 # Vulkan Formats to emit 95 emitFormats = args.emitFormats 96 97 # Features to include (list of features) 98 features = args.feature 99 100 # Whether to disable inclusion protect in headers 101 protect = args.protect 102 103 # Output target directory 104 directory = args.directory 105 106 # Path to generated files, particularly apimap.py 107 genpath = args.genpath 108 109 # Generate MISRA C-friendly headers 110 misracstyle = args.misracstyle; 111 112 # Generate MISRA C++-friendly headers 113 misracppstyle = args.misracppstyle; 114 115 # Descriptive names for various regexp patterns used to select 116 # versions and extensions 117 allFormats = allSpirv = allFeatures = allExtensions = r'.*' 118 119 # Turn lists of names/patterns into matching regular expressions 120 addExtensionsPat = makeREstring(extensions, None) 121 removeExtensionsPat = makeREstring(removeExtensions, None) 122 emitExtensionsPat = makeREstring(emitExtensions, allExtensions) 123 emitSpirvPat = makeREstring(emitSpirv, allSpirv) 124 emitFormatsPat = makeREstring(emitFormats, allFormats) 125 featuresPat = makeREstring(features, allFeatures) 126 127 # Copyright text prefixing all headers (list of strings). 128 # The SPDX formatting below works around constraints of the 'reuse' tool 129 prefixStrings = [ 130 '/*', 131 '** Copyright 2015-2024 The Khronos Group Inc.', 132 '**', 133 '** SPDX-License-Identifier' + ': Apache-2.0', 134 '*/', 135 '' 136 ] 137 138 # Text specific to Vulkan headers 139 vkPrefixStrings = [ 140 '/*', 141 '** This header is generated from the Khronos Vulkan XML API Registry.', 142 '**', 143 '*/', 144 '' 145 ] 146 147 vulkanLayer = args.vulkanLayer 148 149 # Defaults for generating re-inclusion protection wrappers (or not) 150 protectFile = protect 151 152 # An API style conventions object 153 conventions = APIConventions() 154 155 if args.apiname is not None: 156 defaultAPIName = args.apiname 157 else: 158 defaultAPIName = conventions.xml_api_name 159 160 # APIs to merge 161 mergeApiNames = args.mergeApiNames 162 163 isCTS = args.isCTS 164 165 # API include files for spec and ref pages 166 # Overwrites include subdirectories in spec source tree 167 # The generated include files do not include the calling convention 168 # macros (apientry etc.), unlike the header files. 169 # Because the 1.0 core branch includes ref pages for extensions, 170 # all the extension interfaces need to be generated, even though 171 # none are used by the core spec itself. 172 genOpts['apiinc'] = [ 173 DocOutputGenerator, 174 DocGeneratorOptions( 175 conventions = conventions, 176 filename = 'timeMarker', 177 directory = directory, 178 genpath = genpath, 179 apiname = defaultAPIName, 180 profile = None, 181 versions = featuresPat, 182 emitversions = featuresPat, 183 defaultExtensions = None, 184 addExtensions = addExtensionsPat, 185 removeExtensions = removeExtensionsPat, 186 emitExtensions = emitExtensionsPat, 187 prefixText = prefixStrings + vkPrefixStrings, 188 apicall = '', 189 apientry = '', 190 apientryp = '*', 191 alignFuncParam = 48, 192 expandEnumerants = False) 193 ] 194 195 # JavaScript, Python, and Ruby representations of API information, used 196 # by scripts that do not need to load the full XML. 197 genOpts['apimap.cjs'] = [ 198 JSOutputGenerator, 199 DocGeneratorOptions( 200 conventions = conventions, 201 filename = 'apimap.cjs', 202 directory = directory, 203 genpath = None, 204 apiname = defaultAPIName, 205 profile = None, 206 versions = featuresPat, 207 emitversions = featuresPat, 208 defaultExtensions = None, 209 addExtensions = addExtensionsPat, 210 removeExtensions = removeExtensionsPat, 211 emitExtensions = emitExtensionsPat, 212 reparentEnums = False) 213 ] 214 215 genOpts['apimap.py'] = [ 216 PyOutputGenerator, 217 DocGeneratorOptions( 218 conventions = conventions, 219 filename = 'apimap.py', 220 directory = directory, 221 genpath = None, 222 apiname = defaultAPIName, 223 profile = None, 224 versions = featuresPat, 225 emitversions = featuresPat, 226 defaultExtensions = None, 227 addExtensions = addExtensionsPat, 228 removeExtensions = removeExtensionsPat, 229 emitExtensions = emitExtensionsPat, 230 reparentEnums = False) 231 ] 232 233 genOpts['apimap.rb'] = [ 234 RubyOutputGenerator, 235 DocGeneratorOptions( 236 conventions = conventions, 237 filename = 'apimap.rb', 238 directory = directory, 239 genpath = None, 240 apiname = defaultAPIName, 241 profile = None, 242 versions = featuresPat, 243 emitversions = featuresPat, 244 defaultExtensions = None, 245 addExtensions = addExtensionsPat, 246 removeExtensions = removeExtensionsPat, 247 emitExtensions = emitExtensionsPat, 248 reparentEnums = False) 249 ] 250 251 252 # API validity files for spec 253 # 254 # requireCommandAliases is set to True because we need validity files 255 # for the command something is promoted to even when the promoted-to 256 # feature is not included. This avoids wordy includes of validity files. 257 genOpts['validinc'] = [ 258 ValidityOutputGenerator, 259 DocGeneratorOptions( 260 conventions = conventions, 261 filename = 'timeMarker', 262 directory = directory, 263 genpath = None, 264 apiname = defaultAPIName, 265 profile = None, 266 versions = featuresPat, 267 emitversions = featuresPat, 268 defaultExtensions = None, 269 addExtensions = addExtensionsPat, 270 removeExtensions = removeExtensionsPat, 271 emitExtensions = emitExtensionsPat, 272 requireCommandAliases = True, 273 ) 274 ] 275 276 # API host sync table files for spec 277 genOpts['hostsyncinc'] = [ 278 HostSynchronizationOutputGenerator, 279 DocGeneratorOptions( 280 conventions = conventions, 281 filename = 'timeMarker', 282 directory = directory, 283 genpath = None, 284 apiname = defaultAPIName, 285 profile = None, 286 versions = featuresPat, 287 emitversions = featuresPat, 288 defaultExtensions = None, 289 addExtensions = addExtensionsPat, 290 removeExtensions = removeExtensionsPat, 291 emitExtensions = emitExtensionsPat, 292 reparentEnums = False) 293 ] 294 295 # Extension metainformation for spec extension appendices 296 # Includes all extensions by default, but only so that the generated 297 # 'promoted_extensions_*' files refer to all extensions that were 298 # promoted to a core version. 299 genOpts['extinc'] = [ 300 ExtensionMetaDocOutputGenerator, 301 ExtensionMetaDocGeneratorOptions( 302 conventions = conventions, 303 filename = 'timeMarker', 304 directory = directory, 305 genpath = None, 306 apiname = defaultAPIName, 307 profile = None, 308 versions = featuresPat, 309 emitversions = None, 310 defaultExtensions = defaultExtensions, 311 addExtensions = addExtensionsPat, 312 removeExtensions = None, 313 emitExtensions = emitExtensionsPat) 314 ] 315 316 # Version and extension interface docs for version/extension appendices 317 # Includes all extensions by default. 318 genOpts['interfaceinc'] = [ 319 InterfaceDocGenerator, 320 DocGeneratorOptions( 321 conventions = conventions, 322 filename = 'timeMarker', 323 directory = directory, 324 genpath = None, 325 apiname = defaultAPIName, 326 profile = None, 327 versions = featuresPat, 328 emitversions = featuresPat, 329 defaultExtensions = None, 330 addExtensions = addExtensionsPat, 331 removeExtensions = removeExtensionsPat, 332 emitExtensions = emitExtensionsPat, 333 reparentEnums = False) 334 ] 335 336 genOpts['spirvcapinc'] = [ 337 SpirvCapabilityOutputGenerator, 338 DocGeneratorOptions( 339 conventions = conventions, 340 filename = 'timeMarker', 341 directory = directory, 342 genpath = None, 343 apiname = defaultAPIName, 344 profile = None, 345 versions = featuresPat, 346 emitversions = featuresPat, 347 defaultExtensions = None, 348 addExtensions = addExtensionsPat, 349 removeExtensions = removeExtensionsPat, 350 emitExtensions = emitExtensionsPat, 351 emitSpirv = emitSpirvPat, 352 reparentEnums = False) 353 ] 354 355 # Used to generate various format chapter tables 356 genOpts['formatsinc'] = [ 357 FormatsOutputGenerator, 358 DocGeneratorOptions( 359 conventions = conventions, 360 filename = 'timeMarker', 361 directory = directory, 362 genpath = None, 363 apiname = defaultAPIName, 364 profile = None, 365 versions = featuresPat, 366 emitversions = featuresPat, 367 defaultExtensions = None, 368 addExtensions = addExtensionsPat, 369 removeExtensions = removeExtensionsPat, 370 emitExtensions = emitExtensionsPat, 371 emitFormats = emitFormatsPat, 372 reparentEnums = False) 373 ] 374 375 # Used to generate various synchronization chapter tables 376 genOpts['syncinc'] = [ 377 SyncOutputGenerator, 378 DocGeneratorOptions( 379 conventions = conventions, 380 filename = 'timeMarker', 381 directory = directory, 382 genpath = None, 383 apiname = defaultAPIName, 384 profile = None, 385 versions = featuresPat, 386 emitversions = featuresPat, 387 defaultExtensions = None, 388 addExtensions = addExtensionsPat, 389 removeExtensions = removeExtensionsPat, 390 emitExtensions = emitExtensionsPat, 391 reparentEnums = False) 392 ] 393 394 # Platform extensions, in their own header files 395 # Each element of the platforms[] array defines information for 396 # generating a single platform: 397 # [0] is the generated header file name 398 # [1] is the set of platform extensions to generate 399 # [2] is additional extensions whose interfaces should be considered, 400 # but suppressed in the output, to avoid duplicate definitions of 401 # dependent types like VkDisplayKHR and VkSurfaceKHR which come from 402 # non-platform extensions. 403 404 # Track all platform extensions, for exclusion from vulkan_core.h 405 allPlatformExtensions = [] 406 407 # Extensions suppressed for all WSI platforms (WSI extensions required 408 # by all platforms) 409 commonSuppressExtensions = [ 'VK_KHR_display', 'VK_KHR_swapchain' ] 410 411 # Extensions required and suppressed for beta "platform". This can 412 # probably eventually be derived from the requires= attributes of 413 # the extension blocks. 414 betaRequireExtensions = [ 415 'VK_KHR_portability_subset', 416 'VK_NV_displacement_micromap', 417 'VK_AMDX_shader_enqueue', 418 ] 419 420 betaSuppressExtensions = [ 421 'VK_KHR_video_queue', 422 'VK_EXT_opacity_micromap', 423 'VK_KHR_pipeline_library', 424 ] 425 426 platforms = [ 427 [ 'vulkan_android.h', [ 'VK_KHR_android_surface', 428 'VK_ANDROID_external_memory_android_hardware_buffer', 429 'VK_ANDROID_external_format_resolve' 430 ], commonSuppressExtensions + 431 [ 'VK_KHR_format_feature_flags2', 432 ] ], 433 [ 'vulkan_fuchsia.h', [ 'VK_FUCHSIA_imagepipe_surface', 434 'VK_FUCHSIA_external_memory', 435 'VK_FUCHSIA_external_semaphore', 436 'VK_FUCHSIA_buffer_collection' ], commonSuppressExtensions ], 437 [ 'vulkan_ggp.h', [ 'VK_GGP_stream_descriptor_surface', 438 'VK_GGP_frame_token' ], commonSuppressExtensions ], 439 [ 'vulkan_ios.h', [ 'VK_MVK_ios_surface' ], commonSuppressExtensions ], 440 [ 'vulkan_macos.h', [ 'VK_MVK_macos_surface' ], commonSuppressExtensions ], 441 [ 'vulkan_vi.h', [ 'VK_NN_vi_surface' ], commonSuppressExtensions ], 442 [ 'vulkan_wayland.h', [ 'VK_KHR_wayland_surface' ], commonSuppressExtensions ], 443 [ 'vulkan_win32.h', [ 'VK_.*_win32(|_.*)', 'VK_.*_winrt(|_.*)', 'VK_EXT_full_screen_exclusive' ], 444 commonSuppressExtensions + 445 [ 'VK_KHR_external_semaphore', 446 'VK_KHR_external_memory_capabilities', 447 'VK_KHR_external_fence', 448 'VK_KHR_external_fence_capabilities', 449 'VK_KHR_get_surface_capabilities2', 450 'VK_NV_external_memory_capabilities', 451 ] ], 452 [ 'vulkan_xcb.h', [ 'VK_KHR_xcb_surface' ], commonSuppressExtensions ], 453 [ 'vulkan_xlib.h', [ 'VK_KHR_xlib_surface' ], commonSuppressExtensions ], 454 [ 'vulkan_directfb.h', [ 'VK_EXT_directfb_surface' ], commonSuppressExtensions ], 455 [ 'vulkan_xlib_xrandr.h', [ 'VK_EXT_acquire_xlib_display' ], commonSuppressExtensions ], 456 [ 'vulkan_metal.h', [ 'VK_EXT_metal_surface', 457 'VK_EXT_metal_objects' ], commonSuppressExtensions ], 458 [ 'vulkan_screen.h', [ 'VK_QNX_screen_surface', 459 'VK_QNX_external_memory_screen_buffer' ], commonSuppressExtensions ], 460 [ 'vulkan_sci.h', [ 'VK_NV_external_sci_sync', 461 'VK_NV_external_sci_sync2', 462 'VK_NV_external_memory_sci_buf'], commonSuppressExtensions ], 463 [ 'vulkan_beta.h', betaRequireExtensions, betaSuppressExtensions ], 464 ] 465 466 for platform in platforms: 467 headername = platform[0] 468 469 allPlatformExtensions += platform[1] 470 471 addPlatformExtensionsRE = makeREstring( 472 platform[1] + platform[2], strings_are_regex=True) 473 emitPlatformExtensionsRE = makeREstring( 474 platform[1], strings_are_regex=True) 475 476 opts = CGeneratorOptions( 477 conventions = conventions, 478 filename = headername, 479 directory = directory, 480 genpath = None, 481 apiname = defaultAPIName, 482 mergeApiNames = mergeApiNames, 483 profile = None, 484 versions = featuresPat, 485 emitversions = None, 486 defaultExtensions = None, 487 addExtensions = addPlatformExtensionsRE, 488 removeExtensions = None, 489 emitExtensions = emitPlatformExtensionsRE, 490 prefixText = prefixStrings + vkPrefixStrings, 491 genFuncPointers = True, 492 protectFile = protectFile, 493 protectFeature = False, 494 protectProto = '#ifndef', 495 protectProtoStr = 'VK_NO_PROTOTYPES', 496 apicall = 'VKAPI_ATTR ', 497 apientry = 'VKAPI_CALL ', 498 apientryp = 'VKAPI_PTR *', 499 alignFuncParam = 48, 500 misracstyle = misracstyle, 501 misracppstyle = misracppstyle) 502 503 genOpts[headername] = [ COutputGenerator, opts ] 504 505 # Header for core API + extensions. 506 # To generate just the core API, 507 # change to 'defaultExtensions = None' below. 508 # 509 # By default this adds all enabled, non-platform extensions. 510 # It removes all platform extensions (from the platform headers options 511 # constructed above) as well as any explicitly specified removals. 512 513 removeExtensionsPat = makeREstring( 514 allPlatformExtensions + removeExtensions, None, strings_are_regex=True) 515 516 genOpts['vulkan_core.h'] = [ 517 COutputGenerator, 518 CGeneratorOptions( 519 conventions = conventions, 520 filename = 'vulkan_core.h', 521 directory = directory, 522 genpath = None, 523 apiname = defaultAPIName, 524 mergeApiNames = mergeApiNames, 525 profile = None, 526 versions = featuresPat, 527 emitversions = featuresPat, 528 defaultExtensions = defaultExtensions, 529 addExtensions = addExtensionsPat, 530 removeExtensions = removeExtensionsPat, 531 emitExtensions = emitExtensionsPat, 532 prefixText = prefixStrings + vkPrefixStrings, 533 genFuncPointers = True, 534 protectFile = protectFile, 535 protectFeature = False, 536 protectProto = '#ifndef', 537 protectProtoStr = 'VK_NO_PROTOTYPES', 538 apicall = 'VKAPI_ATTR ', 539 apientry = 'VKAPI_CALL ', 540 apientryp = 'VKAPI_PTR *', 541 alignFuncParam = 48, 542 misracstyle = misracstyle, 543 misracppstyle = misracppstyle) 544 ] 545 546 # Vulkan versions to include for SC header - SC *removes* features from 1.0/1.1/1.2 547 scVersions = makeREstring(['VK_VERSION_1_0', 'VK_VERSION_1_1', 'VK_VERSION_1_2', 'VKSC_VERSION_1_0']) 548 549 genOpts['vulkan_sc_core.h'] = [ 550 COutputGenerator, 551 CGeneratorOptions( 552 conventions = conventions, 553 filename = 'vulkan_sc_core.h', 554 directory = directory, 555 apiname = 'vulkansc', 556 profile = None, 557 versions = scVersions, 558 emitversions = scVersions, 559 defaultExtensions = 'vulkansc', 560 addExtensions = addExtensionsPat, 561 removeExtensions = removeExtensionsPat, 562 emitExtensions = emitExtensionsPat, 563 prefixText = prefixStrings + vkPrefixStrings, 564 genFuncPointers = True, 565 protectFile = protectFile, 566 protectFeature = False, 567 protectProto = '#ifndef', 568 protectProtoStr = 'VK_NO_PROTOTYPES', 569 apicall = 'VKAPI_ATTR ', 570 apientry = 'VKAPI_CALL ', 571 apientryp = 'VKAPI_PTR *', 572 alignFuncParam = 48, 573 misracstyle = misracstyle, 574 misracppstyle = misracppstyle) 575 ] 576 577 genOpts['vulkan_sc_core.hpp'] = [ 578 COutputGenerator, 579 CGeneratorOptions( 580 conventions = conventions, 581 filename = 'vulkan_sc_core.hpp', 582 directory = directory, 583 apiname = 'vulkansc', 584 profile = None, 585 versions = scVersions, 586 emitversions = scVersions, 587 defaultExtensions = 'vulkansc', 588 addExtensions = addExtensionsPat, 589 removeExtensions = removeExtensionsPat, 590 emitExtensions = emitExtensionsPat, 591 prefixText = prefixStrings + vkPrefixStrings, 592 genFuncPointers = True, 593 protectFile = protectFile, 594 protectFeature = False, 595 protectProto = '#ifndef', 596 protectProtoStr = 'VK_NO_PROTOTYPES', 597 apicall = 'VKAPI_ATTR ', 598 apientry = 'VKAPI_CALL ', 599 apientryp = 'VKAPI_PTR *', 600 alignFuncParam = 48, 601 misracstyle = misracstyle, 602 misracppstyle = misracppstyle) 603 ] 604 605 genOpts['vk.json'] = [ 606 SchemaOutputGenerator, 607 SchemaGeneratorOptions( 608 conventions = conventions, 609 filename = 'vk.json', 610 directory = directory, 611 apiname = 'vulkansc', 612 profile = None, 613 versions = scVersions, 614 emitversions = scVersions, 615 defaultExtensions = 'vulkansc', 616 addExtensions = addExtensionsPat, 617 removeExtensions = removeExtensionsPat, 618 emitExtensions = emitExtensionsPat, 619 prefixText = prefixStrings + vkPrefixStrings, 620 genFuncPointers = True, 621 protectFile = protectFile, 622 protectFeature = False, 623 protectProto = '#ifndef', 624 protectProtoStr = 'VK_NO_PROTOTYPES', 625 apicall = 'VKAPI_ATTR ', 626 apientry = 'VKAPI_CALL ', 627 apientryp = 'VKAPI_PTR *', 628 alignFuncParam = 48) 629 ] 630 631 if vulkanLayer: 632 genOpts['vulkan_json_data.hpp'] = [ 633 JSONOutputGenerator, 634 JSONGeneratorOptions( 635 conventions = conventions, 636 filename = 'vulkan_json_data.hpp', 637 directory = directory, 638 apiname = 'vulkan', 639 profile = None, 640 versions = featuresPat, 641 emitversions = featuresPat, 642 defaultExtensions = None, 643 addExtensions = addExtensionsPat, 644 removeExtensions = None, 645 emitExtensions = None, 646 vulkanLayer = vulkanLayer, 647 prefixText = prefixStrings + vkPrefixStrings, 648 genFuncPointers = True, 649 protectFile = protectFile, 650 protectFeature = False, 651 protectProto = '#ifndef', 652 protectProtoStr = 'VK_NO_PROTOTYPES', 653 apicall = 'VKAPI_ATTR ', 654 apientry = 'VKAPI_CALL ', 655 apientryp = 'VKAPI_PTR *', 656 alignFuncParam = 48) 657 ] 658 else: 659 genOpts['vulkan_json_data.hpp'] = [ 660 JSONOutputGenerator, 661 JSONGeneratorOptions( 662 conventions = conventions, 663 filename = 'vulkan_json_data.hpp', 664 directory = directory, 665 apiname = 'vulkansc', 666 profile = None, 667 versions = scVersions, 668 emitversions = scVersions, 669 defaultExtensions = 'vulkansc', 670 addExtensions = addExtensionsPat, 671 removeExtensions = removeExtensionsPat, 672 emitExtensions = emitExtensionsPat, 673 vulkanLayer = vulkanLayer, 674 prefixText = prefixStrings + vkPrefixStrings, 675 genFuncPointers = True, 676 protectFile = protectFile, 677 protectFeature = False, 678 protectProto = '#ifndef', 679 protectProtoStr = 'VK_NO_PROTOTYPES', 680 apicall = 'VKAPI_ATTR ', 681 apientry = 'VKAPI_CALL ', 682 apientryp = 'VKAPI_PTR *', 683 isCTS = isCTS, 684 alignFuncParam = 48) 685 ] 686 687 # keep any relevant platform extensions for the following generators 688 # (needed for e.g. the vulkan_sci extensions) 689 explicitRemoveExtensionsPat = makeREstring( 690 removeExtensions, None, strings_are_regex=True) 691 692 # Raw C header file generator. 693 genOpts['vulkan_json_gen.h'] = [ 694 JSONHeaderOutputGenerator, 695 JSONHeaderGeneratorOptions( 696 conventions = conventions, 697 filename = 'vulkan_json_gen.h', 698 directory = directory, 699 apiname = 'vulkansc', 700 profile = None, 701 versions = scVersions, 702 emitversions = scVersions, 703 defaultExtensions = 'vulkansc', 704 addExtensions = addExtensionsPat, 705 removeExtensions = explicitRemoveExtensionsPat, 706 emitExtensions = emitExtensionsPat, 707 prefixText = prefixStrings + vkPrefixStrings, 708 genFuncPointers = True, 709 protectFile = protectFile, 710 protectFeature = False, 711 protectProto = '#ifndef', 712 protectProtoStr = 'VK_NO_PROTOTYPES', 713 apicall = 'VKAPI_ATTR ', 714 apientry = 'VKAPI_CALL ', 715 apientryp = 'VKAPI_PTR *', 716 alignFuncParam = 48) 717 ] 718 719 # Raw C source file generator. 720 genOpts['vulkan_json_gen.c'] = [ 721 JSONCOutputGenerator, 722 JSONCGeneratorOptions( 723 conventions = conventions, 724 filename = 'vulkan_json_gen.c', 725 directory = directory, 726 apiname = 'vulkansc', 727 profile = None, 728 versions = scVersions, 729 emitversions = scVersions, 730 defaultExtensions = 'vulkansc', 731 addExtensions = addExtensionsPat, 732 removeExtensions = explicitRemoveExtensionsPat, 733 emitExtensions = emitExtensionsPat, 734 prefixText = prefixStrings + vkPrefixStrings, 735 genFuncPointers = True, 736 protectFile = protectFile, 737 protectFeature = False, 738 protectProto = '#ifndef', 739 protectProtoStr = 'VK_NO_PROTOTYPES', 740 apicall = 'VKAPI_ATTR ', 741 apientry = 'VKAPI_CALL ', 742 apientryp = 'VKAPI_PTR *', 743 alignFuncParam = 48) 744 ] 745 746 genOpts['vulkan_json_parser.hpp'] = [ 747 JSONParserGenerator, 748 JSONParserOptions( 749 conventions = conventions, 750 filename = 'vulkan_json_parser.hpp', 751 directory = directory, 752 apiname = 'vulkansc', 753 profile = None, 754 versions = scVersions, 755 emitversions = scVersions, 756 defaultExtensions = 'vulkansc', 757 addExtensions = addExtensionsPat, 758 removeExtensions = explicitRemoveExtensionsPat, 759 emitExtensions = emitExtensionsPat, 760 prefixText = prefixStrings + vkPrefixStrings, 761 genFuncPointers = True, 762 protectFile = protectFile, 763 protectFeature = False, 764 protectProto = '#ifndef', 765 protectProtoStr = 'VK_NO_PROTOTYPES', 766 apicall = 'VKAPI_ATTR ', 767 apientry = 'VKAPI_CALL ', 768 apientryp = 'VKAPI_PTR *', 769 isCTS = isCTS, 770 alignFuncParam = 48) 771 ] 772 773 # Unused - vulkan10.h target. 774 # It is possible to generate a header with just the Vulkan 1.0 + 775 # extension interfaces defined, but since the promoted KHR extensions 776 # are now defined in terms of the 1.1 interfaces, such a header is very 777 # similar to vulkan_core.h. 778 genOpts['vulkan10.h'] = [ 779 COutputGenerator, 780 CGeneratorOptions( 781 conventions = conventions, 782 filename = 'vulkan10.h', 783 directory = directory, 784 genpath = None, 785 apiname = defaultAPIName, 786 profile = None, 787 versions = 'VK_VERSION_1_0', 788 emitversions = 'VK_VERSION_1_0', 789 defaultExtensions = None, 790 addExtensions = None, 791 removeExtensions = None, 792 emitExtensions = None, 793 prefixText = prefixStrings + vkPrefixStrings, 794 genFuncPointers = True, 795 protectFile = protectFile, 796 protectFeature = False, 797 protectProto = '#ifndef', 798 protectProtoStr = 'VK_NO_PROTOTYPES', 799 apicall = 'VKAPI_ATTR ', 800 apientry = 'VKAPI_CALL ', 801 apientryp = 'VKAPI_PTR *', 802 alignFuncParam = 48, 803 misracstyle = misracstyle, 804 misracppstyle = misracppstyle) 805 ] 806 807 # Video header target - combines all video extension dependencies into a 808 # single header, at present. 809 genOpts['vk_video.h'] = [ 810 COutputGenerator, 811 CGeneratorOptions( 812 conventions = conventions, 813 filename = 'vk_video.h', 814 directory = directory, 815 genpath = None, 816 apiname = 'vulkan', 817 profile = None, 818 versions = None, 819 emitversions = None, 820 defaultExtensions = defaultExtensions, 821 addExtensions = addExtensionsPat, 822 removeExtensions = removeExtensionsPat, 823 emitExtensions = emitExtensionsPat, 824 prefixText = prefixStrings + vkPrefixStrings, 825 genFuncPointers = True, 826 protectFile = protectFile, 827 protectFeature = False, 828 protectProto = '#ifndef', 829 protectProtoStr = 'VK_NO_PROTOTYPES', 830 apicall = '', 831 apientry = '', 832 apientryp = '', 833 alignFuncParam = 48, 834 misracstyle = misracstyle, 835 misracppstyle = misracppstyle) 836 ] 837 838 # Video extension 'Std' interfaces, each in its own header files 839 # These are not Vulkan extensions, or a part of the Vulkan API at all. 840 # They are treated in a similar fashion for generation purposes, but 841 # all required APIs for each interface must be explicitly required. 842 # 843 # Each element of the videoStd[] array is an extension name defining an 844 # interface, and is also the basis for the generated header file name. 845 846 videoStd = [ 847 'vulkan_video_codecs_common', 848 'vulkan_video_codec_h264std', 849 'vulkan_video_codec_h264std_decode', 850 'vulkan_video_codec_h264std_encode', 851 'vulkan_video_codec_h265std', 852 'vulkan_video_codec_h265std_decode', 853 'vulkan_video_codec_h265std_encode', 854 ] 855 856 # Unused at present 857 # addExtensionRE = makeREstring(videoStd) 858 for codec in videoStd: 859 headername = f'{codec}.h' 860 861 # Consider all of the codecs 'extensions', but only emit this one 862 emitExtensionRE = makeREstring([codec]) 863 864 opts = CGeneratorOptions( 865 conventions = conventions, 866 filename = headername, 867 directory = directory, 868 genpath = None, 869 apiname = defaultAPIName, 870 mergeApiNames = mergeApiNames, 871 profile = None, 872 versions = None, 873 emitversions = None, 874 defaultExtensions = None, 875 addExtensions = emitExtensionRE, 876 removeExtensions = None, 877 emitExtensions = emitExtensionRE, 878 requireDepends = False, 879 prefixText = prefixStrings + vkPrefixStrings, 880 genFuncPointers = False, 881 protectFile = protectFile, 882 protectFeature = False, 883 alignFuncParam = 48, 884 ) 885 886 genOpts[headername] = [ COutputGenerator, opts ] 887 888 # Unused - vulkan11.h target. 889 # It is possible to generate a header with just the Vulkan 1.0 + 890 # extension interfaces defined, but since the promoted KHR extensions 891 # are now defined in terms of the 1.1 interfaces, such a header is very 892 # similar to vulkan_core.h. 893 genOpts['vulkan11.h'] = [ 894 COutputGenerator, 895 CGeneratorOptions( 896 conventions = conventions, 897 filename = 'vulkan11.h', 898 directory = directory, 899 genpath = None, 900 apiname = defaultAPIName, 901 profile = None, 902 versions = '^VK_VERSION_1_[01]$', 903 emitversions = '^VK_VERSION_1_[01]$', 904 defaultExtensions = None, 905 addExtensions = None, 906 removeExtensions = None, 907 emitExtensions = None, 908 prefixText = prefixStrings + vkPrefixStrings, 909 genFuncPointers = True, 910 protectFile = protectFile, 911 protectFeature = False, 912 protectProto = '#ifndef', 913 protectProtoStr = 'VK_NO_PROTOTYPES', 914 apicall = 'VKAPI_ATTR ', 915 apientry = 'VKAPI_CALL ', 916 apientryp = 'VKAPI_PTR *', 917 alignFuncParam = 48, 918 misracstyle = misracstyle, 919 misracppstyle = misracppstyle) 920 ] 921 922 genOpts['alias.h'] = [ 923 COutputGenerator, 924 CGeneratorOptions( 925 conventions = conventions, 926 filename = 'alias.h', 927 directory = directory, 928 genpath = None, 929 apiname = defaultAPIName, 930 profile = None, 931 versions = featuresPat, 932 emitversions = featuresPat, 933 defaultExtensions = defaultExtensions, 934 addExtensions = None, 935 removeExtensions = removeExtensionsPat, 936 emitExtensions = emitExtensionsPat, 937 prefixText = None, 938 genFuncPointers = False, 939 protectFile = False, 940 protectFeature = False, 941 protectProto = '', 942 protectProtoStr = '', 943 apicall = '', 944 apientry = '', 945 apientryp = '', 946 alignFuncParam = 36) 947 ] 948 949 950def genTarget(args): 951 """Create an API generator and corresponding generator options based on 952 the requested target and command line options. 953 954 This is encapsulated in a function so it can be profiled and/or timed. 955 The args parameter is an parsed argument object containing the following 956 fields that are used: 957 958 - target - target to generate 959 - directory - directory to generate it in 960 - protect - True if re-inclusion wrappers should be created 961 - extensions - list of additional extensions to include in generated interfaces""" 962 963 # Create generator options with parameters specified on command line 964 makeGenOpts(args) 965 966 # Select a generator matching the requested target 967 if args.target in genOpts: 968 createGenerator = genOpts[args.target][0] 969 options = genOpts[args.target][1] 970 971 logDiag('* Building', options.filename) 972 logDiag('* options.versions =', options.versions) 973 logDiag('* options.emitversions =', options.emitversions) 974 logDiag('* options.defaultExtensions =', options.defaultExtensions) 975 logDiag('* options.addExtensions =', options.addExtensions) 976 logDiag('* options.removeExtensions =', options.removeExtensions) 977 logDiag('* options.emitExtensions =', options.emitExtensions) 978 logDiag('* options.emitSpirv =', options.emitSpirv) 979 logDiag('* options.emitFormats =', options.emitFormats) 980 981 gen = createGenerator(errFile=errWarn, 982 warnFile=errWarn, 983 diagFile=diag) 984 return (gen, options) 985 else: 986 logErr('No generator options for unknown target:', args.target) 987 return None 988 989 990# -feature name 991# -extension name 992# For both, "name" may be a single name, or a space-separated list 993# of names, or a regular expression. 994if __name__ == '__main__': 995 parser = argparse.ArgumentParser() 996 997 parser.add_argument('-apiname', action='store', 998 default=None, 999 help='Specify API to generate (defaults to repository-specific conventions object value)') 1000 parser.add_argument('-mergeApiNames', action='store', 1001 default=None, 1002 help='Specify a comma separated list of APIs to merge into the target API') 1003 parser.add_argument('-defaultExtensions', action='store', 1004 default=APIConventions().xml_api_name, 1005 help='Specify a single class of extensions to add to targets') 1006 parser.add_argument('-extension', action='append', 1007 default=[], 1008 help='Specify an extension or extensions to add to targets') 1009 parser.add_argument('-removeExtensions', action='append', 1010 default=[], 1011 help='Specify an extension or extensions to remove from targets') 1012 parser.add_argument('-emitExtensions', action='append', 1013 default=[], 1014 help='Specify an extension or extensions to emit in targets') 1015 parser.add_argument('-emitSpirv', action='append', 1016 default=[], 1017 help='Specify a SPIR-V extension or capability to emit in targets') 1018 parser.add_argument('-emitFormats', action='append', 1019 default=[], 1020 help='Specify Vulkan Formats to emit in targets') 1021 parser.add_argument('-feature', action='append', 1022 default=[], 1023 help='Specify a core API feature name or names to add to targets') 1024 parser.add_argument('-debug', action='store_true', 1025 help='Enable debugging') 1026 parser.add_argument('-dump', action='store_true', 1027 help='Enable dump to stderr') 1028 parser.add_argument('-diagfile', action='store', 1029 default=None, 1030 help='Write diagnostics to specified file') 1031 parser.add_argument('-errfile', action='store', 1032 default=None, 1033 help='Write errors and warnings to specified file instead of stderr') 1034 parser.add_argument('-noprotect', dest='protect', action='store_false', 1035 help='Disable inclusion protection in output headers') 1036 parser.add_argument('-profile', action='store_true', 1037 help='Enable profiling') 1038 parser.add_argument('-registry', action='store', 1039 default='vk.xml', 1040 help='Use specified registry file instead of vk.xml') 1041 parser.add_argument('-time', action='store_true', 1042 help='Enable timing') 1043 parser.add_argument('-genpath', action='store', default='gen', 1044 help='Path to generated files') 1045 parser.add_argument('-o', action='store', dest='directory', 1046 default='.', 1047 help='Create target and related files in specified directory') 1048 parser.add_argument('target', metavar='target', nargs='?', 1049 help='Specify target') 1050 parser.add_argument('-quiet', action='store_true', default=True, 1051 help='Suppress script output during normal execution.') 1052 parser.add_argument('-verbose', action='store_false', dest='quiet', default=True, 1053 help='Enable script output during normal execution.') 1054 parser.add_argument('--vulkanLayer', action='store_true', dest='vulkanLayer', 1055 help='Enable scripts to generate VK specific vulkan_json_data.hpp for json_gen_layer.') 1056 parser.add_argument('-misracstyle', dest='misracstyle', action='store_true', 1057 help='generate MISRA C-friendly headers') 1058 parser.add_argument('-misracppstyle', dest='misracppstyle', action='store_true', 1059 help='generate MISRA C++-friendly headers') 1060 parser.add_argument('--iscts', action='store_true', dest='isCTS', 1061 help='Specify if this should generate CTS compatible code') 1062 1063 args = parser.parse_args() 1064 1065 # This splits arguments which are space-separated lists 1066 args.feature = [name for arg in args.feature for name in arg.split()] 1067 args.extension = [name for arg in args.extension for name in arg.split()] 1068 1069 # create error/warning & diagnostic files 1070 if args.errfile: 1071 errWarn = open(args.errfile, 'w', encoding='utf-8') 1072 else: 1073 errWarn = sys.stderr 1074 1075 if args.diagfile: 1076 diag = open(args.diagfile, 'w', encoding='utf-8') 1077 else: 1078 diag = None 1079 1080 if args.time: 1081 # Log diagnostics and warnings 1082 setLogFile(setDiag = True, setWarn = True, filename = '-') 1083 1084 # Create the API generator & generator options 1085 (gen, options) = genTarget(args) 1086 1087 # Create the registry object with the specified generator and generator 1088 # options. The options are set before XML loading as they may affect it. 1089 reg = Registry(gen, options) 1090 1091 # Parse the specified registry XML into an ElementTree object 1092 startTimer(args.time) 1093 tree = etree.parse(args.registry) 1094 endTimer(args.time, '* Time to make ElementTree =') 1095 1096 # Load the XML tree into the registry object 1097 startTimer(args.time) 1098 reg.loadElementTree(tree) 1099 endTimer(args.time, '* Time to parse ElementTree =') 1100 1101 if args.dump: 1102 logDiag('* Dumping registry to regdump.txt') 1103 reg.dumpReg(filehandle=open('regdump.txt', 'w', encoding='utf-8')) 1104 1105 # Finally, use the output generator to create the requested target 1106 if args.debug: 1107 pdb.run('reg.apiGen()') 1108 else: 1109 startTimer(args.time) 1110 reg.apiGen() 1111 endTimer(args.time, '* Time to generate ' + options.filename + ' =') 1112 1113 if not args.quiet: 1114 logDiag('* Generated', options.filename) 1115