#!/usr/bin/env python
#
# Copyright (c) 2013-2016 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 sys, time, pdb, string, cProfile
from reg import *
from generator import write, CGeneratorOptions, COutputGenerator, DocGeneratorOptions, DocOutputGenerator, PyOutputGenerator, ValidityOutputGenerator, HostSynchronizationOutputGenerator, ThreadGeneratorOptions, ThreadOutputGenerator
from generator import ParamCheckerGeneratorOptions, ParamCheckerOutputGenerator
# debug - start header generation in debugger
# dump - dump registry after loading
# profile - enable Python profiling
# protect - whether to use #ifndef protections
# registry <filename> - use specified XML registry instead of gl.xml
# target - string name of target header, or all targets if None
# timeit - time length of registry loading & header generation
# validate - validate return & parameter group tags against <group>
debug = False
dump = False
profile = False
protect = True
target = None
timeit = False
validate= False
# Default input / log files
errFilename = None
diagFilename = 'diag.txt'
regFilename = 'vk.xml'
outDir = '.'
if __name__ == '__main__':
i = 1
while (i < len(sys.argv)):
arg = sys.argv[i]
i = i + 1
if (arg == '-debug'):
write('Enabling debug (-debug)', file=sys.stderr)
debug = True
elif (arg == '-dump'):
write('Enabling dump (-dump)', file=sys.stderr)
dump = True
elif (arg == '-noprotect'):
write('Disabling inclusion protection in output headers', file=sys.stderr)
protect = False
elif (arg == '-profile'):
write('Enabling profiling (-profile)', file=sys.stderr)
profile = True
elif (arg == '-registry'):
regFilename = sys.argv[i]
i = i+1
write('Using registry ', regFilename, file=sys.stderr)
elif (arg == '-time'):
write('Enabling timing (-time)', file=sys.stderr)
timeit = True
elif (arg == '-validate'):
write('Enabling group validation (-validate)', file=sys.stderr)
validate = True
elif (arg == '-outdir'):
outDir = sys.argv[i]
i = i+1
write('Using output directory ', outDir, file=sys.stderr)
elif (arg[0:1] == '-'):
write('Unrecognized argument:', arg, file=sys.stderr)
exit(1)
else:
target = arg
write('Using target', target, file=sys.stderr)
# Simple timer functions
startTime = None
def startTimer():
global startTime
startTime = time.clock()
def endTimer(msg):
global startTime
endTime = time.clock()
if (timeit):
write(msg, endTime - startTime)
startTime = None
# Load & parse registry
reg = Registry()
startTimer()
tree = etree.parse(regFilename)
endTimer('Time to make ElementTree =')
startTimer()
reg.loadElementTree(tree)
endTimer('Time to parse ElementTree =')
if (validate):
reg.validateGroups()
if (dump):
write('***************************************')
write('Performing Registry dump to regdump.txt')
write('***************************************')
reg.dumpReg(filehandle = open('regdump.txt','w'))
# Turn a list of strings into a regexp string matching exactly those strings
def makeREstring(list):
return '^(' + '|'.join(list) + ')$'
# Descriptive names for various regexp patterns used to select
# versions and extensions
allVersions = allExtensions = '.*'
noVersions = noExtensions = None
# Copyright text prefixing all headers (list of strings).
prefixStrings = [
'/*',
'** Copyright (c) 2015-2016 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
buildList = [
# Vulkan 1.0 - header for core API + extensions.
# To generate just the core API,
# change to 'defaultExtensions = None' below.
[ COutputGenerator,
CGeneratorOptions(
filename = 'include/vulkan/vulkan.h',
apiname = 'vulkan',
profile = None,
versions = allVersions,
emitversions = allVersions,
defaultExtensions = 'vulkan',
addExtensions = None,
removeExtensions = None,
prefixText = prefixStrings + vkPrefixStrings,
genFuncPointers = True,
protectFile = protectFile,
protectFeature = False,
protectProto = '#ifndef',
protectProtoStr = 'VK_NO_PROTOTYPES',
apicall = 'VKAPI_ATTR ',
apientry = 'VKAPI_CALL ',
apientryp = 'VKAPI_PTR *',
alignFuncParam = 48)
],
# Vulkan 1.0 draft - API include files for spec and ref pages
# Overwrites include subdirectories in spec source tree
# The generated include files do not include the calling convention
# macros (apientry etc.), unlike the header files.
# Because the 1.0 core branch includes ref pages for extensions,
# all the extension interfaces need to be generated, even though
# none are used by the core spec itself.
[ DocOutputGenerator,
DocGeneratorOptions(
filename = 'vulkan-docs',
apiname = 'vulkan',
profile = None,
versions = allVersions,
emitversions = allVersions,
defaultExtensions = None,
addExtensions =
makeREstring([
'VK_KHR_sampler_mirror_clamp_to_edge',
]),
removeExtensions =
makeREstring([
]),
prefixText = prefixStrings + vkPrefixStrings,
apicall = '',
apientry = '',
apientryp = '*',
genDirectory = '../../doc/specs/vulkan',
alignFuncParam = 48,
expandEnumerants = False)
],
# Vulkan 1.0 draft - API names to validate man/api spec includes & links
[ PyOutputGenerator,
DocGeneratorOptions(
filename = '../../doc/specs/vulkan/vkapi.py',
apiname = 'vulkan',
profile = None,
versions = allVersions,
emitversions = allVersions,
defaultExtensions = None,
addExtensions =
makeREstring([
'VK_KHR_sampler_mirror_clamp_to_edge',
]),
removeExtensions =
makeREstring([
]))
],
# Vulkan 1.0 draft - core API validity files for spec
# Overwrites validity subdirectories in spec source tree
[ ValidityOutputGenerator,
DocGeneratorOptions(
filename = 'validity',
apiname = 'vulkan',
profile = None,
versions = allVersions,
emitversions = allVersions,
defaultExtensions = None,
addExtensions =
makeREstring([
'VK_KHR_sampler_mirror_clamp_to_edge',
]),
removeExtensions =
makeREstring([
]),
genDirectory = '../../doc/specs/vulkan')
],
# Vulkan 1.0 draft - core API host sync table files for spec
# Overwrites subdirectory in spec source tree
[ HostSynchronizationOutputGenerator,
DocGeneratorOptions(
filename = 'hostsynctable',
apiname = 'vulkan',
profile = None,
versions = allVersions,
emitversions = allVersions,
defaultExtensions = None,
addExtensions =
makeREstring([
'VK_KHR_sampler_mirror_clamp_to_edge',
]),
removeExtensions =
makeREstring([
]),
genDirectory = '../../doc/specs/vulkan')
],
# Vulkan 1.0 draft - thread checking layer
[ ThreadOutputGenerator,
ThreadGeneratorOptions(
filename = 'thread_check.h',
apiname = 'vulkan',
profile = None,
versions = allVersions,
emitversions = allVersions,
defaultExtensions = 'vulkan',
addExtensions = None,
removeExtensions = None,
prefixText = prefixStrings + vkPrefixStrings,
genFuncPointers = True,
protectFile = protectFile,
protectFeature = False,
protectProto = True,
protectProtoStr = 'VK_PROTOTYPES',
apicall = 'VKAPI_ATTR ',
apientry = 'VKAPI_CALL ',
apientryp = 'VKAPI_PTR *',
alignFuncParam = 48,
genDirectory = outDir)
],
[ ParamCheckerOutputGenerator,
ParamCheckerGeneratorOptions(
filename = 'parameter_validation.h',
apiname = 'vulkan',
profile = None,
versions = allVersions,
emitversions = allVersions,
defaultExtensions = 'vulkan',
addExtensions = None,
removeExtensions = None,
prefixText = prefixStrings + vkPrefixStrings,
genFuncPointers = True,
protectFile = protectFile,
protectFeature = False,
protectProto = None,
protectProtoStr = 'VK_NO_PROTOTYPES',
apicall = 'VKAPI_ATTR ',
apientry = 'VKAPI_CALL ',
apientryp = 'VKAPI_PTR *',
alignFuncParam = 48,
genDirectory = outDir)
],
None
]
# create error/warning & diagnostic files
if (errFilename):
errWarn = open(errFilename,'w')
else:
errWarn = sys.stderr
diag = open(diagFilename, 'w')
# check that output directory exists
if (not os.path.isdir(outDir)):
write('Output directory does not exist: ', outDir)
raise
def genHeaders():
# Loop over targets, building each
generated = 0
for item in buildList:
if (item == None):
break
createGenerator = item[0]
genOpts = item[1]
if (target and target != genOpts.filename):
# write('*** Skipping', genOpts.filename)
continue
write('*** Building', genOpts.filename)
generated = generated + 1
startTimer()
gen = createGenerator(errFile=errWarn,
warnFile=errWarn,
diagFile=diag)
reg.setGenerator(gen)
reg.apiGen(genOpts)
write('** Generated', genOpts.filename)
endTimer('Time to generate ' + genOpts.filename + ' =')
if (target and generated == 0):
write('Failed to generate target:', target)
if (debug):
pdb.run('genHeaders()')
elif (profile):
import cProfile, pstats
cProfile.run('genHeaders()', 'profile.txt')
p = pstats.Stats('profile.txt')
p.strip_dirs().sort_stats('time').print_stats(50)
else:
genHeaders()