blob: 22b929199b8980e44b0e0418772f153e6ae7ff82 [file] [log] [blame]
Mark Lobodzinski2d589822016-12-12 09:44:34 -07001#!/usr/bin/python3
Mark Lobodzinskif19fef92016-10-11 15:23:51 -06002#
3# Copyright (c) 2013-2016 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
20
21#
22# LoaderAndValidationLayer Generator Additions
23from threading_generator import ThreadGeneratorOptions, ThreadOutputGenerator
24from parameter_validation_generator import ParamCheckerGeneratorOptions, ParamCheckerOutputGenerator
25from unique_objects_generator import UniqueObjectsGeneratorOptions, UniqueObjectsOutputGenerator
Mark Lobodzinskieb0b5ef2016-12-06 11:30:50 -070026from dispatch_table_generator import DispatchTableOutputGenerator, DispatchTableOutputGeneratorOptions
Mark Lobodzinskif19fef92016-10-11 15:23:51 -060027
28# Simple timer functions
29startTime = None
30
31def startTimer(timeit):
32 global startTime
33 startTime = time.clock()
34
35def endTimer(timeit, msg):
36 global startTime
37 endTime = time.clock()
38 if (timeit):
39 write(msg, endTime - startTime, file=sys.stderr)
40 startTime = None
41
42# Turn a list of strings into a regexp string matching exactly those strings
43def makeREstring(list):
44 return '^(' + '|'.join(list) + ')$'
45
46# Returns a directory of [ generator function, generator options ] indexed
47# by specified short names. The generator options incorporate the following
48# parameters:
49#
50# extensions - list of extension names to include.
51# protect - True if re-inclusion protection should be added to headers
52# directory - path to directory in which to generate the target(s)
Mark Lobodzinski2d589822016-12-12 09:44:34 -070053def makeGenOpts(extensions = [], removeExtensions = [], protect = True, directory = '.'):
Mark Lobodzinskif19fef92016-10-11 15:23:51 -060054 global genOpts
55 genOpts = {}
56
57 # Descriptive names for various regexp patterns used to select
58 # versions and extensions
59 allVersions = allExtensions = '.*'
60 noVersions = noExtensions = None
61
62 addExtensions = makeREstring(extensions)
Mark Lobodzinski2d589822016-12-12 09:44:34 -070063 removeExtensions = makeREstring(removeExtensions)
Mark Lobodzinskif19fef92016-10-11 15:23:51 -060064
65 # Copyright text prefixing all headers (list of strings).
66 prefixStrings = [
67 '/*',
68 '** Copyright (c) 2015-2016 The Khronos Group Inc.',
69 '**',
70 '** Licensed under the Apache License, Version 2.0 (the "License");',
71 '** you may not use this file except in compliance with the License.',
72 '** You may obtain a copy of the License at',
73 '**',
74 '** http://www.apache.org/licenses/LICENSE-2.0',
75 '**',
76 '** Unless required by applicable law or agreed to in writing, software',
77 '** distributed under the License is distributed on an "AS IS" BASIS,',
78 '** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.',
79 '** See the License for the specific language governing permissions and',
80 '** limitations under the License.',
81 '*/',
82 ''
83 ]
84
85 # Text specific to Vulkan headers
86 vkPrefixStrings = [
87 '/*',
88 '** This header is generated from the Khronos Vulkan XML API Registry.',
89 '**',
90 '*/',
91 ''
92 ]
93
94 # Defaults for generating re-inclusion protection wrappers (or not)
95 protectFile = protect
96 protectFeature = protect
97 protectProto = protect
98
99 #
100 # LoaderAndValidationLayer Generators
101 # Options for threading layer
102 genOpts['thread_check.h'] = [
103 ThreadOutputGenerator,
104 ThreadGeneratorOptions(
105 filename = 'thread_check.h',
106 directory = directory,
107 apiname = 'vulkan',
108 profile = None,
109 versions = allVersions,
110 emitversions = allVersions,
111 defaultExtensions = 'vulkan',
112 addExtensions = addExtensions,
113 removeExtensions = removeExtensions,
114 prefixText = prefixStrings + vkPrefixStrings,
115 protectFeature = False,
116 apicall = 'VKAPI_ATTR ',
117 apientry = 'VKAPI_CALL ',
118 apientryp = 'VKAPI_PTR *',
119 alignFuncParam = 48)
120 ]
121
122 # Options for parameter validation layer
123 genOpts['parameter_validation.h'] = [
124 ParamCheckerOutputGenerator,
125 ParamCheckerGeneratorOptions(
126 filename = 'parameter_validation.h',
127 directory = directory,
128 apiname = 'vulkan',
129 profile = None,
130 versions = allVersions,
131 emitversions = allVersions,
132 defaultExtensions = 'vulkan',
133 addExtensions = addExtensions,
134 removeExtensions = removeExtensions,
135 prefixText = prefixStrings + vkPrefixStrings,
136 protectFeature = False,
137 apicall = 'VKAPI_ATTR ',
138 apientry = 'VKAPI_CALL ',
139 apientryp = 'VKAPI_PTR *',
140 alignFuncParam = 48)
141 ]
142
143 # Options for unique objects layer
144 genOpts['unique_objects_wrappers.h'] = [
145 UniqueObjectsOutputGenerator,
146 UniqueObjectsGeneratorOptions(
147 filename = 'unique_objects_wrappers.h',
148 directory = directory,
149 apiname = 'vulkan',
150 profile = None,
151 versions = allVersions,
152 emitversions = allVersions,
153 defaultExtensions = 'vulkan',
154 addExtensions = addExtensions,
155 removeExtensions = removeExtensions,
156 prefixText = prefixStrings + vkPrefixStrings,
157 protectFeature = False,
158 apicall = 'VKAPI_ATTR ',
159 apientry = 'VKAPI_CALL ',
160 apientryp = 'VKAPI_PTR *',
161 alignFuncParam = 48)
162 ]
163
Mark Lobodzinskieb0b5ef2016-12-06 11:30:50 -0700164
165 # Options for dispatch table helper generator
166 genOpts['vk_dispatch_table_helper.h'] = [
167 DispatchTableOutputGenerator,
168 DispatchTableOutputGeneratorOptions(
169 filename = 'vk_dispatch_table_helper.h',
170 directory = directory,
171 apiname = 'vulkan',
172 profile = None,
173 versions = allVersions,
174 emitversions = allVersions,
175 defaultExtensions = 'vulkan',
176 addExtensions = addExtensions,
177 removeExtensions = removeExtensions,
178 prefixText = prefixStrings + vkPrefixStrings,
179 protectFeature = False,
180 apicall = 'VKAPI_ATTR ',
181 apientry = 'VKAPI_CALL ',
182 apientryp = 'VKAPI_PTR *',
183 alignFuncParam = 48)
184 ]
185
186
187
Mark Lobodzinskif19fef92016-10-11 15:23:51 -0600188# Generate a target based on the options in the matching genOpts{} object.
189# This is encapsulated in a function so it can be profiled and/or timed.
190# The args parameter is an parsed argument object containing the following
191# fields that are used:
192# target - target to generate
193# directory - directory to generate it in
194# protect - True if re-inclusion wrappers should be created
195# extensions - list of additional extensions to include in generated
196# interfaces
197def genTarget(args):
198 global genOpts
199
200 # Create generator options with specified parameters
201 makeGenOpts(extensions = args.extension,
Mark Lobodzinski2d589822016-12-12 09:44:34 -0700202 removeExtensions = args.removeExtension,
Mark Lobodzinskif19fef92016-10-11 15:23:51 -0600203 protect = args.protect,
204 directory = args.directory)
205
206 if (args.target in genOpts.keys()):
207 createGenerator = genOpts[args.target][0]
208 options = genOpts[args.target][1]
209
Mark Lobodzinskicbaa2cd2016-12-19 09:41:16 -0700210 if not args.quiet:
211 write('* Building', options.filename, file=sys.stderr)
Mark Lobodzinskif19fef92016-10-11 15:23:51 -0600212
213 startTimer(args.time)
214 gen = createGenerator(errFile=errWarn,
215 warnFile=errWarn,
216 diagFile=diag)
217 reg.setGenerator(gen)
218 reg.apiGen(options)
Mark Lobodzinskicbaa2cd2016-12-19 09:41:16 -0700219
220 if not args.quiet:
221 write('* Generated', options.filename, file=sys.stderr)
Mark Lobodzinskif19fef92016-10-11 15:23:51 -0600222 endTimer(args.time, '* Time to generate ' + options.filename + ' =')
223 else:
224 write('No generator options for unknown target:',
225 args.target, file=sys.stderr)
226
227# -extension name - may be a single extension name, a a space-separated list
228# of names, or a regular expression.
229if __name__ == '__main__':
230 parser = argparse.ArgumentParser()
231
232 parser.add_argument('-extension', action='append',
233 default=[],
234 help='Specify an extension or extensions to add to targets')
Mark Lobodzinski2d589822016-12-12 09:44:34 -0700235 parser.add_argument('-removeExtension', action='append',
236 default=[],
237 help='Specify an extension or extensions to remove from targets')
Mark Lobodzinskif19fef92016-10-11 15:23:51 -0600238 parser.add_argument('-debug', action='store_true',
239 help='Enable debugging')
240 parser.add_argument('-dump', action='store_true',
241 help='Enable dump to stderr')
242 parser.add_argument('-diagfile', action='store',
243 default=None,
244 help='Write diagnostics to specified file')
245 parser.add_argument('-errfile', action='store',
246 default=None,
247 help='Write errors and warnings to specified file instead of stderr')
248 parser.add_argument('-noprotect', dest='protect', action='store_false',
249 help='Disable inclusion protection in output headers')
250 parser.add_argument('-profile', action='store_true',
251 help='Enable profiling')
252 parser.add_argument('-registry', action='store',
253 default='vk.xml',
254 help='Use specified registry file instead of vk.xml')
255 parser.add_argument('-time', action='store_true',
256 help='Enable timing')
257 parser.add_argument('-validate', action='store_true',
258 help='Enable group validation')
259 parser.add_argument('-o', action='store', dest='directory',
260 default='.',
261 help='Create target and related files in specified directory')
262 parser.add_argument('target', metavar='target', nargs='?',
263 help='Specify target')
Mark Lobodzinskicbaa2cd2016-12-19 09:41:16 -0700264 parser.add_argument('-quiet', action='store_true', default=False,
265 help='Suppress script output during normal execution.')
Mark Lobodzinskif19fef92016-10-11 15:23:51 -0600266
267 args = parser.parse_args()
268
269 # This splits arguments which are space-separated lists
270 args.extension = [name for arg in args.extension for name in arg.split()]
271
272 # Load & parse registry
273 reg = Registry()
274
275 startTimer(args.time)
276 tree = etree.parse(args.registry)
277 endTimer(args.time, '* Time to make ElementTree =')
278
279 startTimer(args.time)
280 reg.loadElementTree(tree)
281 endTimer(args.time, '* Time to parse ElementTree =')
282
283 if (args.validate):
284 reg.validateGroups()
285
286 if (args.dump):
287 write('* Dumping registry to regdump.txt', file=sys.stderr)
Mark Lobodzinski2d589822016-12-12 09:44:34 -0700288 reg.dumpReg(filehandle = open('regdump.txt','w', encoding='utf-8'))
Mark Lobodzinskif19fef92016-10-11 15:23:51 -0600289
290 # create error/warning & diagnostic files
291 if (args.errfile):
Mark Lobodzinski2d589822016-12-12 09:44:34 -0700292 errWarn = open(args.errfile, 'w', encoding='utf-8')
Mark Lobodzinskif19fef92016-10-11 15:23:51 -0600293 else:
294 errWarn = sys.stderr
295
296 if (args.diagfile):
Mark Lobodzinski2d589822016-12-12 09:44:34 -0700297 diag = open(args.diagfile, 'w', encoding='utf-8')
Mark Lobodzinskif19fef92016-10-11 15:23:51 -0600298 else:
299 diag = None
300
301 if (args.debug):
302 pdb.run('genTarget(args)')
303 elif (args.profile):
304 import cProfile, pstats
305 cProfile.run('genTarget(args)', 'profile.txt')
306 p = pstats.Stats('profile.txt')
307 p.strip_dirs().sort_stats('time').print_stats(50)
308 else:
309 genTarget(args)