blob: 0be5d3eada10d0113fa547a9b8c954709748760c [file] [log] [blame]
Mark Lobodzinski2d589822016-12-12 09:44:34 -07001#!/usr/bin/python3
Mark Lobodzinskif19fef92016-10-11 15:23:51 -06002#
Mark Lobodzinski733f7f42017-01-10 11:42:22 -07003# Copyright (c) 2013-2017 The Khronos Group Inc.
Mark Lobodzinskif19fef92016-10-11 15:23:51 -06004#
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
Mark Lobodzinski36c33862017-02-13 10:15:53 -070020from cgenerator import CGeneratorOptions, COutputGenerator
21# LoaderAndValidationLayer Generator Modifications
Mark Lobodzinskif19fef92016-10-11 15:23:51 -060022from threading_generator import ThreadGeneratorOptions, ThreadOutputGenerator
23from parameter_validation_generator import ParamCheckerGeneratorOptions, ParamCheckerOutputGenerator
24from unique_objects_generator import UniqueObjectsGeneratorOptions, UniqueObjectsOutputGenerator
Mark Lobodzinskieb0b5ef2016-12-06 11:30:50 -070025from dispatch_table_generator import DispatchTableOutputGenerator, DispatchTableOutputGeneratorOptions
Mark Lobodzinski41d9bb32016-12-27 13:50:05 -070026from helper_file_generator import HelperFileOutputGenerator, HelperFileOutputGeneratorOptions
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 '/*',
Mark Lobodzinski36c33862017-02-13 10:15:53 -070068 '** Copyright (c) 2015-2017 The Khronos Group Inc.',
Mark Lobodzinskif19fef92016-10-11 15:23:51 -060069 '**',
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
Mark Lobodzinski36c33862017-02-13 10:15:53 -070099
100 #
Mark Lobodzinskif19fef92016-10-11 15:23:51 -0600101 # LoaderAndValidationLayer Generators
102 # Options for threading layer
103 genOpts['thread_check.h'] = [
104 ThreadOutputGenerator,
105 ThreadGeneratorOptions(
106 filename = 'thread_check.h',
107 directory = directory,
108 apiname = 'vulkan',
109 profile = None,
110 versions = allVersions,
111 emitversions = allVersions,
112 defaultExtensions = 'vulkan',
113 addExtensions = addExtensions,
114 removeExtensions = removeExtensions,
115 prefixText = prefixStrings + vkPrefixStrings,
116 protectFeature = False,
117 apicall = 'VKAPI_ATTR ',
118 apientry = 'VKAPI_CALL ',
119 apientryp = 'VKAPI_PTR *',
120 alignFuncParam = 48)
121 ]
122
123 # Options for parameter validation layer
124 genOpts['parameter_validation.h'] = [
125 ParamCheckerOutputGenerator,
126 ParamCheckerGeneratorOptions(
127 filename = 'parameter_validation.h',
128 directory = directory,
129 apiname = 'vulkan',
130 profile = None,
131 versions = allVersions,
132 emitversions = allVersions,
133 defaultExtensions = 'vulkan',
134 addExtensions = addExtensions,
135 removeExtensions = removeExtensions,
136 prefixText = prefixStrings + vkPrefixStrings,
137 protectFeature = False,
138 apicall = 'VKAPI_ATTR ',
139 apientry = 'VKAPI_CALL ',
140 apientryp = 'VKAPI_PTR *',
141 alignFuncParam = 48)
142 ]
143
144 # Options for unique objects layer
145 genOpts['unique_objects_wrappers.h'] = [
146 UniqueObjectsOutputGenerator,
147 UniqueObjectsGeneratorOptions(
148 filename = 'unique_objects_wrappers.h',
149 directory = directory,
150 apiname = 'vulkan',
151 profile = None,
152 versions = allVersions,
153 emitversions = allVersions,
154 defaultExtensions = 'vulkan',
155 addExtensions = addExtensions,
156 removeExtensions = removeExtensions,
157 prefixText = prefixStrings + vkPrefixStrings,
158 protectFeature = False,
159 apicall = 'VKAPI_ATTR ',
160 apientry = 'VKAPI_CALL ',
161 apientryp = 'VKAPI_PTR *',
162 alignFuncParam = 48)
163 ]
164
Mark Lobodzinskieb0b5ef2016-12-06 11:30:50 -0700165
166 # Options for dispatch table helper generator
167 genOpts['vk_dispatch_table_helper.h'] = [
168 DispatchTableOutputGenerator,
169 DispatchTableOutputGeneratorOptions(
170 filename = 'vk_dispatch_table_helper.h',
171 directory = directory,
172 apiname = 'vulkan',
173 profile = None,
174 versions = allVersions,
175 emitversions = allVersions,
176 defaultExtensions = 'vulkan',
177 addExtensions = addExtensions,
178 removeExtensions = removeExtensions,
179 prefixText = prefixStrings + vkPrefixStrings,
180 protectFeature = False,
181 apicall = 'VKAPI_ATTR ',
182 apientry = 'VKAPI_CALL ',
183 apientryp = 'VKAPI_PTR *',
184 alignFuncParam = 48)
185 ]
186
Mark Lobodzinski79839b72016-12-28 08:49:29 -0700187 # Helper file generator options for vk_enum_string_helper.h
Mark Lobodzinski41d9bb32016-12-27 13:50:05 -0700188 genOpts['vk_enum_string_helper.h'] = [
189 HelperFileOutputGenerator,
190 HelperFileOutputGeneratorOptions(
191 filename = 'vk_enum_string_helper.h',
192 directory = directory,
193 apiname = 'vulkan',
194 profile = None,
195 versions = allVersions,
196 emitversions = allVersions,
197 defaultExtensions = 'vulkan',
198 addExtensions = addExtensions,
199 removeExtensions = removeExtensions,
200 prefixText = prefixStrings + vkPrefixStrings,
201 protectFeature = False,
202 apicall = 'VKAPI_ATTR ',
203 apientry = 'VKAPI_CALL ',
204 apientryp = 'VKAPI_PTR *',
Mark Lobodzinski79839b72016-12-28 08:49:29 -0700205 alignFuncParam = 48,
Mark Lobodzinski46d388f2016-12-28 10:46:26 -0700206 helper_file_type = 'enum_string_header')
Mark Lobodzinski41d9bb32016-12-27 13:50:05 -0700207 ]
208
Mark Lobodzinski46d388f2016-12-28 10:46:26 -0700209 # Helper file generator options for vk_struct_size_helper.h
210 genOpts['vk_struct_size_helper.h'] = [
Mark Lobodzinski79839b72016-12-28 08:49:29 -0700211 HelperFileOutputGenerator,
212 HelperFileOutputGeneratorOptions(
Mark Lobodzinski46d388f2016-12-28 10:46:26 -0700213 filename = 'vk_struct_size_helper.h',
Mark Lobodzinski79839b72016-12-28 08:49:29 -0700214 directory = directory,
215 apiname = 'vulkan',
216 profile = None,
217 versions = allVersions,
218 emitversions = allVersions,
219 defaultExtensions = 'vulkan',
220 addExtensions = addExtensions,
221 removeExtensions = removeExtensions,
222 prefixText = prefixStrings + vkPrefixStrings,
223 protectFeature = False,
224 apicall = 'VKAPI_ATTR ',
225 apientry = 'VKAPI_CALL ',
226 apientryp = 'VKAPI_PTR *',
227 alignFuncParam = 48,
Mark Lobodzinski46d388f2016-12-28 10:46:26 -0700228 helper_file_type = 'struct_size_header')
229 ]
230
231 # Helper file generator options for vk_struct_size_helper.c
232 genOpts['vk_struct_size_helper.c'] = [
233 HelperFileOutputGenerator,
234 HelperFileOutputGeneratorOptions(
235 filename = 'vk_struct_size_helper.c',
236 directory = directory,
237 apiname = 'vulkan',
238 profile = None,
239 versions = allVersions,
240 emitversions = allVersions,
241 defaultExtensions = 'vulkan',
242 addExtensions = addExtensions,
243 removeExtensions = removeExtensions,
244 prefixText = prefixStrings + vkPrefixStrings,
245 protectFeature = False,
246 apicall = 'VKAPI_ATTR ',
247 apientry = 'VKAPI_CALL ',
248 apientryp = 'VKAPI_PTR *',
249 alignFuncParam = 48,
250 helper_file_type = 'struct_size_source')
Mark Lobodzinski79839b72016-12-28 08:49:29 -0700251 ]
Mark Lobodzinski41d9bb32016-12-27 13:50:05 -0700252
Mark Lobodzinskiaf631782017-01-03 10:55:13 -0700253 # Helper file generator options for vk_safe_struct.h
254 genOpts['vk_safe_struct.h'] = [
255 HelperFileOutputGenerator,
256 HelperFileOutputGeneratorOptions(
257 filename = 'vk_safe_struct.h',
258 directory = directory,
259 apiname = 'vulkan',
260 profile = None,
261 versions = allVersions,
262 emitversions = allVersions,
263 defaultExtensions = 'vulkan',
264 addExtensions = addExtensions,
265 removeExtensions = removeExtensions,
266 prefixText = prefixStrings + vkPrefixStrings,
267 protectFeature = False,
268 apicall = 'VKAPI_ATTR ',
269 apientry = 'VKAPI_CALL ',
270 apientryp = 'VKAPI_PTR *',
271 alignFuncParam = 48,
272 helper_file_type = 'safe_struct_header')
273 ]
274
275 # Helper file generator options for vk_safe_struct.cpp
276 genOpts['vk_safe_struct.cpp'] = [
277 HelperFileOutputGenerator,
278 HelperFileOutputGeneratorOptions(
279 filename = 'vk_safe_struct.cpp',
280 directory = directory,
281 apiname = 'vulkan',
282 profile = None,
283 versions = allVersions,
284 emitversions = allVersions,
285 defaultExtensions = 'vulkan',
286 addExtensions = addExtensions,
287 removeExtensions = removeExtensions,
288 prefixText = prefixStrings + vkPrefixStrings,
289 protectFeature = False,
290 apicall = 'VKAPI_ATTR ',
291 apientry = 'VKAPI_CALL ',
292 apientryp = 'VKAPI_PTR *',
293 alignFuncParam = 48,
294 helper_file_type = 'safe_struct_source')
295 ]
296
Mark Lobodzinskif19fef92016-10-11 15:23:51 -0600297# Generate a target based on the options in the matching genOpts{} object.
298# This is encapsulated in a function so it can be profiled and/or timed.
299# The args parameter is an parsed argument object containing the following
300# fields that are used:
301# target - target to generate
302# directory - directory to generate it in
303# protect - True if re-inclusion wrappers should be created
304# extensions - list of additional extensions to include in generated
305# interfaces
306def genTarget(args):
307 global genOpts
308
309 # Create generator options with specified parameters
310 makeGenOpts(extensions = args.extension,
Mark Lobodzinski2d589822016-12-12 09:44:34 -0700311 removeExtensions = args.removeExtension,
Mark Lobodzinskif19fef92016-10-11 15:23:51 -0600312 protect = args.protect,
313 directory = args.directory)
314
315 if (args.target in genOpts.keys()):
316 createGenerator = genOpts[args.target][0]
317 options = genOpts[args.target][1]
318
Mark Lobodzinskicbaa2cd2016-12-19 09:41:16 -0700319 if not args.quiet:
320 write('* Building', options.filename, file=sys.stderr)
Mark Lobodzinskif19fef92016-10-11 15:23:51 -0600321
322 startTimer(args.time)
323 gen = createGenerator(errFile=errWarn,
324 warnFile=errWarn,
325 diagFile=diag)
326 reg.setGenerator(gen)
327 reg.apiGen(options)
Mark Lobodzinskicbaa2cd2016-12-19 09:41:16 -0700328
329 if not args.quiet:
330 write('* Generated', options.filename, file=sys.stderr)
Mark Lobodzinskif19fef92016-10-11 15:23:51 -0600331 endTimer(args.time, '* Time to generate ' + options.filename + ' =')
332 else:
333 write('No generator options for unknown target:',
334 args.target, file=sys.stderr)
335
336# -extension name - may be a single extension name, a a space-separated list
337# of names, or a regular expression.
338if __name__ == '__main__':
339 parser = argparse.ArgumentParser()
340
341 parser.add_argument('-extension', action='append',
342 default=[],
343 help='Specify an extension or extensions to add to targets')
Mark Lobodzinski2d589822016-12-12 09:44:34 -0700344 parser.add_argument('-removeExtension', action='append',
345 default=[],
346 help='Specify an extension or extensions to remove from targets')
Mark Lobodzinskif19fef92016-10-11 15:23:51 -0600347 parser.add_argument('-debug', action='store_true',
348 help='Enable debugging')
349 parser.add_argument('-dump', action='store_true',
350 help='Enable dump to stderr')
351 parser.add_argument('-diagfile', action='store',
352 default=None,
353 help='Write diagnostics to specified file')
354 parser.add_argument('-errfile', action='store',
355 default=None,
356 help='Write errors and warnings to specified file instead of stderr')
357 parser.add_argument('-noprotect', dest='protect', action='store_false',
358 help='Disable inclusion protection in output headers')
359 parser.add_argument('-profile', action='store_true',
360 help='Enable profiling')
361 parser.add_argument('-registry', action='store',
362 default='vk.xml',
363 help='Use specified registry file instead of vk.xml')
364 parser.add_argument('-time', action='store_true',
365 help='Enable timing')
366 parser.add_argument('-validate', action='store_true',
367 help='Enable group validation')
368 parser.add_argument('-o', action='store', dest='directory',
369 default='.',
370 help='Create target and related files in specified directory')
371 parser.add_argument('target', metavar='target', nargs='?',
372 help='Specify target')
Mark Lobodzinskicbaa2cd2016-12-19 09:41:16 -0700373 parser.add_argument('-quiet', action='store_true', default=False,
374 help='Suppress script output during normal execution.')
Mark Lobodzinskif19fef92016-10-11 15:23:51 -0600375
376 args = parser.parse_args()
377
378 # This splits arguments which are space-separated lists
379 args.extension = [name for arg in args.extension for name in arg.split()]
380
381 # Load & parse registry
382 reg = Registry()
383
384 startTimer(args.time)
385 tree = etree.parse(args.registry)
386 endTimer(args.time, '* Time to make ElementTree =')
387
388 startTimer(args.time)
389 reg.loadElementTree(tree)
390 endTimer(args.time, '* Time to parse ElementTree =')
391
392 if (args.validate):
393 reg.validateGroups()
394
395 if (args.dump):
396 write('* Dumping registry to regdump.txt', file=sys.stderr)
Mark Lobodzinski36c33862017-02-13 10:15:53 -0700397 reg.dumpReg(filehandle = open('regdump.txt', 'w', encoding='utf-8'))
Mark Lobodzinskif19fef92016-10-11 15:23:51 -0600398
399 # create error/warning & diagnostic files
400 if (args.errfile):
Mark Lobodzinski2d589822016-12-12 09:44:34 -0700401 errWarn = open(args.errfile, 'w', encoding='utf-8')
Mark Lobodzinskif19fef92016-10-11 15:23:51 -0600402 else:
403 errWarn = sys.stderr
404
405 if (args.diagfile):
Mark Lobodzinski2d589822016-12-12 09:44:34 -0700406 diag = open(args.diagfile, 'w', encoding='utf-8')
Mark Lobodzinskif19fef92016-10-11 15:23:51 -0600407 else:
408 diag = None
409
410 if (args.debug):
411 pdb.run('genTarget(args)')
412 elif (args.profile):
413 import cProfile, pstats
414 cProfile.run('genTarget(args)', 'profile.txt')
415 p = pstats.Stats('profile.txt')
416 p.strip_dirs().sort_stats('time').print_stats(50)
417 else:
418 genTarget(args)