Home | History | Annotate | Download | only in vulkan-validation-layers
      1 #!/usr/bin/env python
      2 #
      3 # Copyright (c) 2013-2015 The Khronos Group Inc.
      4 #
      5 # Permission is hereby granted, free of charge, to any person obtaining a
      6 # copy of this software and/or associated documentation files (the
      7 # "Materials"), to deal in the Materials without restriction, including
      8 # without limitation the rights to use, copy, modify, merge, publish,
      9 # distribute, sublicense, and/or sell copies of the Materials, and to
     10 # permit persons to whom the Materials are furnished to do so, subject to
     11 # the following conditions:
     12 #
     13 # The above copyright notice and this permission notice shall be included
     14 # in all copies or substantial portions of the Materials.
     15 #
     16 # THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     17 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     18 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     19 # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
     20 # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     21 # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     22 # MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
     23 
     24 import sys, time, pdb, string, cProfile
     25 from reg import *
     26 from generator import write, CGeneratorOptions, COutputGenerator, DocGeneratorOptions, DocOutputGenerator, PyOutputGenerator, ValidityOutputGenerator, HostSynchronizationOutputGenerator, ThreadGeneratorOptions, ThreadOutputGenerator
     27 from generator import ParamCheckerGeneratorOptions, ParamCheckerOutputGenerator
     28 
     29 # debug - start header generation in debugger
     30 # dump - dump registry after loading
     31 # profile - enable Python profiling
     32 # protect - whether to use #ifndef protections
     33 # registry <filename> - use specified XML registry instead of gl.xml
     34 # target - string name of target header, or all targets if None
     35 # timeit - time length of registry loading & header generation
     36 # validate - validate return & parameter group tags against <group>
     37 debug   = False
     38 dump    = False
     39 profile = False
     40 protect = True
     41 target  = None
     42 timeit  = False
     43 validate= False
     44 # Default input / log files
     45 errFilename = None
     46 diagFilename = 'diag.txt'
     47 regFilename = 'vk.xml'
     48 
     49 if __name__ == '__main__':
     50     i = 1
     51     while (i < len(sys.argv)):
     52         arg = sys.argv[i]
     53         i = i + 1
     54         if (arg == '-debug'):
     55             write('Enabling debug (-debug)', file=sys.stderr)
     56             debug = True
     57         elif (arg == '-dump'):
     58             write('Enabling dump (-dump)', file=sys.stderr)
     59             dump = True
     60         elif (arg == '-noprotect'):
     61             write('Disabling inclusion protection in output headers', file=sys.stderr)
     62             protect = False
     63         elif (arg == '-profile'):
     64             write('Enabling profiling (-profile)', file=sys.stderr)
     65             profile = True
     66         elif (arg == '-registry'):
     67             regFilename = sys.argv[i]
     68             i = i+1
     69             write('Using registry ', regFilename, file=sys.stderr)
     70         elif (arg == '-time'):
     71             write('Enabling timing (-time)', file=sys.stderr)
     72             timeit = True
     73         elif (arg == '-validate'):
     74             write('Enabling group validation (-validate)', file=sys.stderr)
     75             validate = True
     76         elif (arg[0:1] == '-'):
     77             write('Unrecognized argument:', arg, file=sys.stderr)
     78             exit(1)
     79         else:
     80             target = arg
     81             write('Using target', target, file=sys.stderr)
     82 
     83 # Simple timer functions
     84 startTime = None
     85 def startTimer():
     86     global startTime
     87     startTime = time.clock()
     88 def endTimer(msg):
     89     global startTime
     90     endTime = time.clock()
     91     if (timeit):
     92         write(msg, endTime - startTime)
     93         startTime = None
     94 
     95 # Load & parse registry
     96 reg = Registry()
     97 
     98 startTimer()
     99 tree = etree.parse(regFilename)
    100 endTimer('Time to make ElementTree =')
    101 
    102 startTimer()
    103 reg.loadElementTree(tree)
    104 endTimer('Time to parse ElementTree =')
    105 
    106 if (validate):
    107     reg.validateGroups()
    108 
    109 if (dump):
    110     write('***************************************')
    111     write('Performing Registry dump to regdump.txt')
    112     write('***************************************')
    113     reg.dumpReg(filehandle = open('regdump.txt','w'))
    114 
    115 # Turn a list of strings into a regexp string matching exactly those strings
    116 def makeREstring(list):
    117     return '^(' + '|'.join(list) + ')$'
    118 
    119 # Descriptive names for various regexp patterns used to select
    120 # versions and extensions
    121 allVersions     = allExtensions = '.*'
    122 noVersions      = noExtensions = None
    123 
    124 # Copyright text prefixing all headers (list of strings).
    125 prefixStrings = [
    126     '/*',
    127     '** Copyright (c) 2015 The Khronos Group Inc.',
    128     '**',
    129     '** Permission is hereby granted, free of charge, to any person obtaining a',
    130     '** copy of this software and/or associated documentation files (the',
    131     '** "Materials"), to deal in the Materials without restriction, including',
    132     '** without limitation the rights to use, copy, modify, merge, publish,',
    133     '** distribute, sublicense, and/or sell copies of the Materials, and to',
    134     '** permit persons to whom the Materials are furnished to do so, subject to',
    135     '** the following conditions:',
    136     '**',
    137     '** The above copyright notice and this permission notice shall be included',
    138     '** in all copies or substantial portions of the Materials.',
    139     '**',
    140     '** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,',
    141     '** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF',
    142     '** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.',
    143     '** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY',
    144     '** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,',
    145     '** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE',
    146     '** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.',
    147     '*/',
    148     ''
    149 ]
    150 
    151 # Text specific to Vulkan headers
    152 vkPrefixStrings = [
    153     '/*',
    154     '** This header is generated from the Khronos Vulkan XML API Registry.',
    155     '**',
    156     '*/',
    157     ''
    158 ]
    159 
    160 # Defaults for generating re-inclusion protection wrappers (or not)
    161 protectFile = protect
    162 protectFeature = protect
    163 protectProto = protect
    164 
    165 buildList = [
    166     # Vulkan 1.0 - core API + extensions. To generate just the core API,
    167     # change to 'defaultExtensions = None' below.
    168     [ COutputGenerator,
    169       CGeneratorOptions(
    170         filename          = 'include/vulkan/vulkan.h',
    171         apiname           = 'vulkan',
    172         profile           = None,
    173         versions          = allVersions,
    174         emitversions      = allVersions,
    175         defaultExtensions = 'vulkan',
    176         addExtensions     = None,
    177         removeExtensions  = None,
    178         prefixText        = prefixStrings + vkPrefixStrings,
    179         genFuncPointers   = True,
    180         protectFile       = protectFile,
    181         protectFeature    = False,
    182         protectProto      = '#ifndef',
    183         protectProtoStr   = 'VK_NO_PROTOTYPES',
    184         apicall           = 'VKAPI_ATTR ',
    185         apientry          = 'VKAPI_CALL ',
    186         apientryp         = 'VKAPI_PTR *',
    187         alignFuncParam    = 48)
    188     ],
    189     # Vulkan 1.0 draft - core API include files for spec
    190     # Overwrites include subdirectories in spec source tree
    191     # The generated include files do not include the calling convention
    192     # macros (apientry etc.), unlike the header files.
    193     [ DocOutputGenerator,
    194       DocGeneratorOptions(
    195         filename          = 'vulkan-docs',
    196         apiname           = 'vulkan',
    197         profile           = None,
    198         versions          = allVersions,
    199         emitversions      = allVersions,
    200         defaultExtensions = 'vulkan',
    201         addExtensions     = None,
    202         removeExtensions  = None,
    203         prefixText        = prefixStrings + vkPrefixStrings,
    204         apicall           = '',
    205         apientry          = '',
    206         apientryp         = '*',
    207         genDirectory      = '../../doc/specs/vulkan',
    208         alignFuncParam    = 48,
    209         expandEnumerants  = False)
    210     ],
    211     # Vulkan 1.0 draft - API names to validate man/api spec includes & links
    212     #    filename          = 'vkapi.py',
    213     [ PyOutputGenerator,
    214       DocGeneratorOptions(
    215         filename          = '../../doc/specs/vulkan/vkapi.py',
    216         apiname           = 'vulkan',
    217         profile           = None,
    218         versions          = allVersions,
    219         emitversions      = allVersions,
    220         defaultExtensions = None,
    221         addExtensions     = None,
    222         removeExtensions  = None)
    223     ],
    224     # Vulkan 1.0 draft - core API include files for spec
    225     # Overwrites include subdirectories in spec source tree
    226     [ ValidityOutputGenerator,
    227       DocGeneratorOptions(
    228         filename          = 'validity',
    229         apiname           = 'vulkan',
    230         profile           = None,
    231         versions          = allVersions,
    232         emitversions      = allVersions,
    233         defaultExtensions = None,
    234         addExtensions     = None,
    235         removeExtensions  = None,
    236         genDirectory      = '../../doc/specs/vulkan')
    237     ],
    238     # Vulkan 1.0 draft - core API include files for spec
    239     # Overwrites include subdirectories in spec source tree
    240     [ HostSynchronizationOutputGenerator,
    241       DocGeneratorOptions(
    242         filename          = 'hostsynctable',
    243         apiname           = 'vulkan',
    244         profile           = None,
    245         versions          = allVersions,
    246         emitversions      = allVersions,
    247         defaultExtensions = None,
    248         addExtensions     = None,
    249         removeExtensions  = None,
    250         genDirectory      = '../../doc/specs/vulkan')
    251     ],
    252     # Vulkan 1.0 draft - thread checking layer
    253     [ ThreadOutputGenerator,
    254       ThreadGeneratorOptions(
    255         filename          = 'thread_check.h',
    256         apiname           = 'vulkan',
    257         profile           = None,
    258         versions          = allVersions,
    259         emitversions      = allVersions,
    260         defaultExtensions = 'vulkan',
    261         addExtensions     = None,
    262         removeExtensions  = None,
    263         prefixText        = prefixStrings + vkPrefixStrings,
    264         genFuncPointers   = True,
    265         protectFile       = protectFile,
    266         protectFeature    = False,
    267         protectProto      = True,
    268         protectProtoStr   = 'VK_PROTOTYPES',
    269         apicall           = '',
    270         apientry          = 'VKAPI_CALL ',
    271         apientryp         = 'VKAPI_PTR *',
    272         alignFuncParam    = 48)
    273     ],
    274     [ ParamCheckerOutputGenerator,
    275       ParamCheckerGeneratorOptions(
    276         filename          = 'parameter_validation.h',
    277         apiname           = 'vulkan',
    278         profile           = None,
    279         versions          = allVersions,
    280         emitversions      = allVersions,
    281         defaultExtensions = 'vulkan',
    282         addExtensions     = None,
    283         removeExtensions  = None,
    284         prefixText        = prefixStrings + vkPrefixStrings,
    285         genFuncPointers   = True,
    286         protectFile       = protectFile,
    287         protectFeature    = False,
    288         protectProto      = None,
    289         protectProtoStr   = 'VK_NO_PROTOTYPES',
    290         apicall           = 'VKAPI_ATTR ',
    291         apientry          = 'VKAPI_CALL ',
    292         apientryp         = 'VKAPI_PTR *',
    293         alignFuncParam    = 48)
    294     ],
    295     None
    296 ]
    297 
    298 # create error/warning & diagnostic files
    299 if (errFilename):
    300     errWarn = open(errFilename,'w')
    301 else:
    302     errWarn = sys.stderr
    303 diag = open(diagFilename, 'w')
    304 
    305 def genHeaders():
    306     # Loop over targets, building each
    307     generated = 0
    308     for item in buildList:
    309         if (item == None):
    310             break
    311         createGenerator = item[0]
    312         genOpts = item[1]
    313         if (target and target != genOpts.filename):
    314             # write('*** Skipping', genOpts.filename)
    315             continue
    316         write('*** Building', genOpts.filename)
    317         generated = generated + 1
    318         startTimer()
    319         gen = createGenerator(errFile=errWarn,
    320                               warnFile=errWarn,
    321                               diagFile=diag)
    322         reg.setGenerator(gen)
    323         reg.apiGen(genOpts)
    324         write('** Generated', genOpts.filename)
    325         endTimer('Time to generate ' + genOpts.filename + ' =')
    326     if (target and generated == 0):
    327         write('Failed to generate target:', target)
    328 
    329 if (debug):
    330     pdb.run('genHeaders()')
    331 elif (profile):
    332     import cProfile, pstats
    333     cProfile.run('genHeaders()', 'profile.txt')
    334     p = pstats.Stats('profile.txt')
    335     p.strip_dirs().sort_stats('time').print_stats(50)
    336 else:
    337     genHeaders()
    338