#!/usr/bin/python3 # # Copyright (c) 2013-2017 The Khronos Group Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import argparse, cProfile, pdb, string, sys, time from reg import * from generator import write from cgenerator import CGeneratorOptions, COutputGenerator # LoaderAndValidationLayer Generator Modifications from threading_generator import ThreadGeneratorOptions, ThreadOutputGenerator from parameter_validation_generator import ParameterValidationGeneratorOptions, ParameterValidationOutputGenerator from unique_objects_generator import UniqueObjectsGeneratorOptions, UniqueObjectsOutputGenerator from object_tracker_generator import ObjectTrackerGeneratorOptions, ObjectTrackerOutputGenerator from dispatch_table_helper_generator import DispatchTableHelperOutputGenerator, DispatchTableHelperOutputGeneratorOptions from helper_file_generator import HelperFileOutputGenerator, HelperFileOutputGeneratorOptions from loader_extension_generator import LoaderExtensionOutputGenerator, LoaderExtensionGeneratorOptions from mock_icd_generator import MockICDGeneratorOptions, MockICDOutputGenerator # Simple timer functions startTime = None def startTimer(timeit): global startTime startTime = time.clock() def endTimer(timeit, msg): global startTime endTime = time.clock() if (timeit): write(msg, endTime - startTime, file=sys.stderr) startTime = None # Turn a list of strings into a regexp string matching exactly those strings def makeREstring(list): return '^(' + '|'.join(list) + ')$' # Returns a directory of [ generator function, generator options ] indexed # by specified short names. The generator options incorporate the following # parameters: # # extensions - list of extension names to include. # protect - True if re-inclusion protection should be added to headers # directory - path to directory in which to generate the target(s) def makeGenOpts(extensions = [], removeExtensions = [], protect = True, directory = '.'): global genOpts genOpts = {} # Descriptive names for various regexp patterns used to select # versions and extensions allVersions = allExtensions = '.*' noVersions = noExtensions = None addExtensions = makeREstring(extensions) removeExtensions = makeREstring(removeExtensions) # Copyright text prefixing all headers (list of strings). prefixStrings = [ '/*', '** Copyright (c) 2015-2017 The Khronos Group Inc.', '**', '** Licensed under the Apache License, Version 2.0 (the "License");', '** you may not use this file except in compliance with the License.', '** You may obtain a copy of the License at', '**', '** http://www.apache.org/licenses/LICENSE-2.0', '**', '** Unless required by applicable law or agreed to in writing, software', '** distributed under the License is distributed on an "AS IS" BASIS,', '** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.', '** See the License for the specific language governing permissions and', '** limitations under the License.', '*/', '' ] # Text specific to Vulkan headers vkPrefixStrings = [ '/*', '** This header is generated from the Khronos Vulkan XML API Registry.', '**', '*/', '' ] # Defaults for generating re-inclusion protection wrappers (or not) protectFile = protect protectFeature = protect protectProto = protect # # LoaderAndValidationLayer Generators # Options for threading layer genOpts['thread_check.h'] = [ ThreadOutputGenerator, ThreadGeneratorOptions( filename = 'thread_check.h', directory = directory, apiname = 'vulkan', profile = None, versions = allVersions, emitversions = allVersions, defaultExtensions = 'vulkan', addExtensions = addExtensions, removeExtensions = removeExtensions, prefixText = prefixStrings + vkPrefixStrings, protectFeature = False, apicall = 'VKAPI_ATTR ', apientry = 'VKAPI_CALL ', apientryp = 'VKAPI_PTR *', alignFuncParam = 48) ] # Options for parameter validation layer genOpts['parameter_validation.cpp'] = [ ParameterValidationOutputGenerator, ParameterValidationGeneratorOptions( filename = 'parameter_validation.cpp', directory = directory, apiname = 'vulkan', profile = None, versions = allVersions, emitversions = allVersions, defaultExtensions = 'vulkan', addExtensions = addExtensions, removeExtensions = removeExtensions, prefixText = prefixStrings + vkPrefixStrings, protectFeature = False, apicall = 'VKAPI_ATTR ', apientry = 'VKAPI_CALL ', apientryp = 'VKAPI_PTR *', alignFuncParam = 48) ] # Options for unique objects layer genOpts['unique_objects_wrappers.h'] = [ UniqueObjectsOutputGenerator, UniqueObjectsGeneratorOptions( filename = 'unique_objects_wrappers.h', directory = directory, apiname = 'vulkan', profile = None, versions = allVersions, emitversions = allVersions, defaultExtensions = 'vulkan', addExtensions = addExtensions, removeExtensions = removeExtensions, prefixText = prefixStrings + vkPrefixStrings, protectFeature = False, apicall = 'VKAPI_ATTR ', apientry = 'VKAPI_CALL ', apientryp = 'VKAPI_PTR *', alignFuncParam = 48) ] # Options for object_tracker layer genOpts['object_tracker.cpp'] = [ ObjectTrackerOutputGenerator, ObjectTrackerGeneratorOptions( filename = 'object_tracker.cpp', directory = directory, apiname = 'vulkan', profile = None, versions = allVersions, emitversions = allVersions, defaultExtensions = 'vulkan', addExtensions = addExtensions, removeExtensions = removeExtensions, prefixText = prefixStrings + vkPrefixStrings, protectFeature = False, apicall = 'VKAPI_ATTR ', apientry = 'VKAPI_CALL ', apientryp = 'VKAPI_PTR *', alignFuncParam = 48) ] # Options for dispatch table helper generator genOpts['vk_dispatch_table_helper.h'] = [ DispatchTableHelperOutputGenerator, DispatchTableHelperOutputGeneratorOptions( filename = 'vk_dispatch_table_helper.h', directory = directory, apiname = 'vulkan', profile = None, versions = allVersions, emitversions = allVersions, defaultExtensions = 'vulkan', addExtensions = addExtensions, removeExtensions = removeExtensions, prefixText = prefixStrings + vkPrefixStrings, protectFeature = False, apicall = 'VKAPI_ATTR ', apientry = 'VKAPI_CALL ', apientryp = 'VKAPI_PTR *', alignFuncParam = 48) ] # Options for Layer dispatch table generator genOpts['vk_layer_dispatch_table.h'] = [ LoaderExtensionOutputGenerator, LoaderExtensionGeneratorOptions( filename = 'vk_layer_dispatch_table.h', directory = directory, apiname = 'vulkan', profile = None, versions = allVersions, emitversions = allVersions, defaultExtensions = 'vulkan', addExtensions = addExtensions, removeExtensions = removeExtensions, prefixText = prefixStrings + vkPrefixStrings, protectFeature = False, apicall = 'VKAPI_ATTR ', apientry = 'VKAPI_CALL ', apientryp = 'VKAPI_PTR *', alignFuncParam = 48) ] # Options for loader extension source generator genOpts['vk_loader_extensions.h'] = [ LoaderExtensionOutputGenerator, LoaderExtensionGeneratorOptions( filename = 'vk_loader_extensions.h', directory = directory, apiname = 'vulkan', profile = None, versions = allVersions, emitversions = allVersions, defaultExtensions = 'vulkan', addExtensions = addExtensions, removeExtensions = removeExtensions, prefixText = prefixStrings + vkPrefixStrings, protectFeature = False, apicall = 'VKAPI_ATTR ', apientry = 'VKAPI_CALL ', apientryp = 'VKAPI_PTR *', alignFuncParam = 48) ] # Options for loader extension source generator genOpts['vk_loader_extensions.c'] = [ LoaderExtensionOutputGenerator, LoaderExtensionGeneratorOptions( filename = 'vk_loader_extensions.c', directory = directory, apiname = 'vulkan', profile = None, versions = allVersions, emitversions = allVersions, defaultExtensions = 'vulkan', addExtensions = addExtensions, removeExtensions = removeExtensions, prefixText = prefixStrings + vkPrefixStrings, protectFeature = False, apicall = 'VKAPI_ATTR ', apientry = 'VKAPI_CALL ', apientryp = 'VKAPI_PTR *', alignFuncParam = 48) ] # Helper file generator options for vk_enum_string_helper.h genOpts['vk_enum_string_helper.h'] = [ HelperFileOutputGenerator, HelperFileOutputGeneratorOptions( filename = 'vk_enum_string_helper.h', directory = directory, apiname = 'vulkan', profile = None, versions = allVersions, emitversions = allVersions, defaultExtensions = 'vulkan', addExtensions = addExtensions, removeExtensions = removeExtensions, prefixText = prefixStrings + vkPrefixStrings, protectFeature = False, apicall = 'VKAPI_ATTR ', apientry = 'VKAPI_CALL ', apientryp = 'VKAPI_PTR *', alignFuncParam = 48, helper_file_type = 'enum_string_header') ] # Helper file generator options for vk_struct_size_helper.h genOpts['vk_struct_size_helper.h'] = [ HelperFileOutputGenerator, HelperFileOutputGeneratorOptions( filename = 'vk_struct_size_helper.h', directory = directory, apiname = 'vulkan', profile = None, versions = allVersions, emitversions = allVersions, defaultExtensions = 'vulkan', addExtensions = addExtensions, removeExtensions = removeExtensions, prefixText = prefixStrings + vkPrefixStrings, protectFeature = False, apicall = 'VKAPI_ATTR ', apientry = 'VKAPI_CALL ', apientryp = 'VKAPI_PTR *', alignFuncParam = 48, helper_file_type = 'struct_size_header') ] # Helper file generator options for vk_struct_size_helper.c genOpts['vk_struct_size_helper.c'] = [ HelperFileOutputGenerator, HelperFileOutputGeneratorOptions( filename = 'vk_struct_size_helper.c', directory = directory, apiname = 'vulkan', profile = None, versions = allVersions, emitversions = allVersions, defaultExtensions = 'vulkan', addExtensions = addExtensions, removeExtensions = removeExtensions, prefixText = prefixStrings + vkPrefixStrings, protectFeature = False, apicall = 'VKAPI_ATTR ', apientry = 'VKAPI_CALL ', apientryp = 'VKAPI_PTR *', alignFuncParam = 48, helper_file_type = 'struct_size_source') ] # Helper file generator options for vk_safe_struct.h genOpts['vk_safe_struct.h'] = [ HelperFileOutputGenerator, HelperFileOutputGeneratorOptions( filename = 'vk_safe_struct.h', directory = directory, apiname = 'vulkan', profile = None, versions = allVersions, emitversions = allVersions, defaultExtensions = 'vulkan', addExtensions = addExtensions, removeExtensions = removeExtensions, prefixText = prefixStrings + vkPrefixStrings, protectFeature = False, apicall = 'VKAPI_ATTR ', apientry = 'VKAPI_CALL ', apientryp = 'VKAPI_PTR *', alignFuncParam = 48, helper_file_type = 'safe_struct_header') ] # Helper file generator options for vk_safe_struct.cpp genOpts['vk_safe_struct.cpp'] = [ HelperFileOutputGenerator, HelperFileOutputGeneratorOptions( filename = 'vk_safe_struct.cpp', directory = directory, apiname = 'vulkan', profile = None, versions = allVersions, emitversions = allVersions, defaultExtensions = 'vulkan', addExtensions = addExtensions, removeExtensions = removeExtensions, prefixText = prefixStrings + vkPrefixStrings, protectFeature = False, apicall = 'VKAPI_ATTR ', apientry = 'VKAPI_CALL ', apientryp = 'VKAPI_PTR *', alignFuncParam = 48, helper_file_type = 'safe_struct_source') ] # Helper file generator options for vk_object_types.h genOpts['vk_object_types.h'] = [ HelperFileOutputGenerator, HelperFileOutputGeneratorOptions( filename = 'vk_object_types.h', directory = directory, apiname = 'vulkan', profile = None, versions = allVersions, emitversions = allVersions, defaultExtensions = 'vulkan', addExtensions = addExtensions, removeExtensions = removeExtensions, prefixText = prefixStrings + vkPrefixStrings, protectFeature = False, apicall = 'VKAPI_ATTR ', apientry = 'VKAPI_CALL ', apientryp = 'VKAPI_PTR *', alignFuncParam = 48, helper_file_type = 'object_types_header') ] # Helper file generator options for extension_helper.h genOpts['vk_extension_helper.h'] = [ HelperFileOutputGenerator, HelperFileOutputGeneratorOptions( filename = 'vk_extension_helper.h', directory = directory, apiname = 'vulkan', profile = None, versions = allVersions, emitversions = allVersions, defaultExtensions = 'vulkan', addExtensions = addExtensions, removeExtensions = removeExtensions, prefixText = prefixStrings + vkPrefixStrings, protectFeature = False, apicall = 'VKAPI_ATTR ', apientry = 'VKAPI_CALL ', apientryp = 'VKAPI_PTR *', alignFuncParam = 48, helper_file_type = 'extension_helper_header') ] # Helper file generator options for typemap_helper.h genOpts['vk_typemap_helper.h'] = [ HelperFileOutputGenerator, HelperFileOutputGeneratorOptions( filename = 'vk_typemap_helper.h', directory = directory, apiname = 'vulkan', profile = None, versions = allVersions, emitversions = allVersions, defaultExtensions = 'vulkan', addExtensions = addExtensions, removeExtensions = removeExtensions, prefixText = prefixStrings + vkPrefixStrings, protectFeature = False, apicall = 'VKAPI_ATTR ', apientry = 'VKAPI_CALL ', apientryp = 'VKAPI_PTR *', alignFuncParam = 48, helper_file_type = 'typemap_helper_header') ] # Options for mock ICD header genOpts['mock_icd.h'] = [ MockICDOutputGenerator, MockICDGeneratorOptions( filename = 'mock_icd.h', directory = directory, apiname = 'vulkan', profile = None, versions = allVersions, emitversions = allVersions, defaultExtensions = 'vulkan', addExtensions = addExtensions, removeExtensions = removeExtensions, prefixText = prefixStrings + vkPrefixStrings, protectFeature = False, apicall = 'VKAPI_ATTR ', apientry = 'VKAPI_CALL ', apientryp = 'VKAPI_PTR *', alignFuncParam = 48, helper_file_type = 'mock_icd_header') ] # Options for mock ICD cpp genOpts['mock_icd.cpp'] = [ MockICDOutputGenerator, MockICDGeneratorOptions( filename = 'mock_icd.cpp', directory = directory, apiname = 'vulkan', profile = None, versions = allVersions, emitversions = allVersions, defaultExtensions = 'vulkan', addExtensions = addExtensions, removeExtensions = removeExtensions, prefixText = prefixStrings + vkPrefixStrings, protectFeature = False, apicall = 'VKAPI_ATTR ', apientry = 'VKAPI_CALL ', apientryp = 'VKAPI_PTR *', alignFuncParam = 48, helper_file_type = 'mock_icd_source') ] # Generate a target based on the options in the matching genOpts{} object. # This is encapsulated in a function so it can be profiled and/or timed. # The args parameter is an parsed argument object containing the following # fields that are used: # target - target to generate # directory - directory to generate it in # protect - True if re-inclusion wrappers should be created # extensions - list of additional extensions to include in generated # interfaces def genTarget(args): global genOpts # Create generator options with specified parameters makeGenOpts(extensions = args.extension, removeExtensions = args.removeExtension, protect = args.protect, directory = args.directory) if (args.target in genOpts.keys()): createGenerator = genOpts[args.target][0] options = genOpts[args.target][1] if not args.quiet: write('* Building', options.filename, file=sys.stderr) startTimer(args.time) gen = createGenerator(errFile=errWarn, warnFile=errWarn, diagFile=diag) reg.setGenerator(gen) reg.apiGen(options) if not args.quiet: write('* Generated', options.filename, file=sys.stderr) endTimer(args.time, '* Time to generate ' + options.filename + ' =') else: write('No generator options for unknown target:', args.target, file=sys.stderr) # -extension name - may be a single extension name, a a space-separated list # of names, or a regular expression. if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument('-extension', action='append', default=[], help='Specify an extension or extensions to add to targets') parser.add_argument('-removeExtension', action='append', default=[], help='Specify an extension or extensions to remove from targets') parser.add_argument('-debug', action='store_true', help='Enable debugging') parser.add_argument('-dump', action='store_true', help='Enable dump to stderr') parser.add_argument('-diagfile', action='store', default=None, help='Write diagnostics to specified file') parser.add_argument('-errfile', action='store', default=None, help='Write errors and warnings to specified file instead of stderr') parser.add_argument('-noprotect', dest='protect', action='store_false', help='Disable inclusion protection in output headers') parser.add_argument('-profile', action='store_true', help='Enable profiling') parser.add_argument('-registry', action='store', default='vk.xml', help='Use specified registry file instead of vk.xml') parser.add_argument('-time', action='store_true', help='Enable timing') parser.add_argument('-validate', action='store_true', help='Enable group validation') parser.add_argument('-o', action='store', dest='directory', default='.', help='Create target and related files in specified directory') parser.add_argument('target', metavar='target', nargs='?', help='Specify target') parser.add_argument('-quiet', action='store_true', default=False, help='Suppress script output during normal execution.') args = parser.parse_args() # This splits arguments which are space-separated lists args.extension = [name for arg in args.extension for name in arg.split()] # Load & parse registry reg = Registry() startTimer(args.time) tree = etree.parse(args.registry) endTimer(args.time, '* Time to make ElementTree =') startTimer(args.time) reg.loadElementTree(tree) endTimer(args.time, '* Time to parse ElementTree =') if (args.validate): reg.validateGroups() if (args.dump): write('* Dumping registry to regdump.txt', file=sys.stderr) reg.dumpReg(filehandle = open('regdump.txt', 'w', encoding='utf-8')) # create error/warning & diagnostic files if (args.errfile): errWarn = open(args.errfile, 'w', encoding='utf-8') else: errWarn = sys.stderr if (args.diagfile): diag = open(args.diagfile, 'w', encoding='utf-8') else: diag = None if (args.debug): pdb.run('genTarget(args)') elif (args.profile): import cProfile, pstats cProfile.run('genTarget(args)', 'profile.txt') p = pstats.Stats('profile.txt') p.strip_dirs().sort_stats('time').print_stats(50) else: genTarget(args)