blob: 54293762d83c85a66b3748cb74a91ce410e192ed [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 Lobodzinski41d9bb32016-12-27 13:50:05 -070027from helper_file_generator import HelperFileOutputGenerator, HelperFileOutputGeneratorOptions
Mark Lobodzinskif19fef92016-10-11 15:23:51 -060028
29# Simple timer functions
30startTime = None
31
32def startTimer(timeit):
33 global startTime
34 startTime = time.clock()
35
36def endTimer(timeit, msg):
37 global startTime
38 endTime = time.clock()
39 if (timeit):
40 write(msg, endTime - startTime, file=sys.stderr)
41 startTime = None
42
43# Turn a list of strings into a regexp string matching exactly those strings
44def makeREstring(list):
45 return '^(' + '|'.join(list) + ')$'
46
47# Returns a directory of [ generator function, generator options ] indexed
48# by specified short names. The generator options incorporate the following
49# parameters:
50#
51# extensions - list of extension names to include.
52# protect - True if re-inclusion protection should be added to headers
53# directory - path to directory in which to generate the target(s)
Mark Lobodzinski2d589822016-12-12 09:44:34 -070054def makeGenOpts(extensions = [], removeExtensions = [], protect = True, directory = '.'):
Mark Lobodzinskif19fef92016-10-11 15:23:51 -060055 global genOpts
56 genOpts = {}
57
58 # Descriptive names for various regexp patterns used to select
59 # versions and extensions
60 allVersions = allExtensions = '.*'
61 noVersions = noExtensions = None
62
63 addExtensions = makeREstring(extensions)
Mark Lobodzinski2d589822016-12-12 09:44:34 -070064 removeExtensions = makeREstring(removeExtensions)
Mark Lobodzinskif19fef92016-10-11 15:23:51 -060065
66 # Copyright text prefixing all headers (list of strings).
67 prefixStrings = [
68 '/*',
69 '** Copyright (c) 2015-2016 The Khronos Group Inc.',
70 '**',
71 '** Licensed under the Apache License, Version 2.0 (the "License");',
72 '** you may not use this file except in compliance with the License.',
73 '** You may obtain a copy of the License at',
74 '**',
75 '** http://www.apache.org/licenses/LICENSE-2.0',
76 '**',
77 '** Unless required by applicable law or agreed to in writing, software',
78 '** distributed under the License is distributed on an "AS IS" BASIS,',
79 '** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.',
80 '** See the License for the specific language governing permissions and',
81 '** limitations under the License.',
82 '*/',
83 ''
84 ]
85
86 # Text specific to Vulkan headers
87 vkPrefixStrings = [
88 '/*',
89 '** This header is generated from the Khronos Vulkan XML API Registry.',
90 '**',
91 '*/',
92 ''
93 ]
94
95 # Defaults for generating re-inclusion protection wrappers (or not)
96 protectFile = protect
97 protectFeature = protect
98 protectProto = protect
99
100 #
101 # 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 Lobodzinski41d9bb32016-12-27 13:50:05 -0700187 # Options for helper file generator
188 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 *',
205 alignFuncParam = 48)
206 ]
207
208
Mark Lobodzinskieb0b5ef2016-12-06 11:30:50 -0700209
210
Mark Lobodzinskif19fef92016-10-11 15:23:51 -0600211# Generate a target based on the options in the matching genOpts{} object.
212# This is encapsulated in a function so it can be profiled and/or timed.
213# The args parameter is an parsed argument object containing the following
214# fields that are used:
215# target - target to generate
216# directory - directory to generate it in
217# protect - True if re-inclusion wrappers should be created
218# extensions - list of additional extensions to include in generated
219# interfaces
220def genTarget(args):
221 global genOpts
222
223 # Create generator options with specified parameters
224 makeGenOpts(extensions = args.extension,
Mark Lobodzinski2d589822016-12-12 09:44:34 -0700225 removeExtensions = args.removeExtension,
Mark Lobodzinskif19fef92016-10-11 15:23:51 -0600226 protect = args.protect,
227 directory = args.directory)
228
229 if (args.target in genOpts.keys()):
230 createGenerator = genOpts[args.target][0]
231 options = genOpts[args.target][1]
232
Mark Lobodzinskicbaa2cd2016-12-19 09:41:16 -0700233 if not args.quiet:
234 write('* Building', options.filename, file=sys.stderr)
Mark Lobodzinskif19fef92016-10-11 15:23:51 -0600235
236 startTimer(args.time)
237 gen = createGenerator(errFile=errWarn,
238 warnFile=errWarn,
239 diagFile=diag)
240 reg.setGenerator(gen)
241 reg.apiGen(options)
Mark Lobodzinskicbaa2cd2016-12-19 09:41:16 -0700242
243 if not args.quiet:
244 write('* Generated', options.filename, file=sys.stderr)
Mark Lobodzinskif19fef92016-10-11 15:23:51 -0600245 endTimer(args.time, '* Time to generate ' + options.filename + ' =')
246 else:
247 write('No generator options for unknown target:',
248 args.target, file=sys.stderr)
249
250# -extension name - may be a single extension name, a a space-separated list
251# of names, or a regular expression.
252if __name__ == '__main__':
253 parser = argparse.ArgumentParser()
254
255 parser.add_argument('-extension', action='append',
256 default=[],
257 help='Specify an extension or extensions to add to targets')
Mark Lobodzinski2d589822016-12-12 09:44:34 -0700258 parser.add_argument('-removeExtension', action='append',
259 default=[],
260 help='Specify an extension or extensions to remove from targets')
Mark Lobodzinskif19fef92016-10-11 15:23:51 -0600261 parser.add_argument('-debug', action='store_true',
262 help='Enable debugging')
263 parser.add_argument('-dump', action='store_true',
264 help='Enable dump to stderr')
265 parser.add_argument('-diagfile', action='store',
266 default=None,
267 help='Write diagnostics to specified file')
268 parser.add_argument('-errfile', action='store',
269 default=None,
270 help='Write errors and warnings to specified file instead of stderr')
271 parser.add_argument('-noprotect', dest='protect', action='store_false',
272 help='Disable inclusion protection in output headers')
273 parser.add_argument('-profile', action='store_true',
274 help='Enable profiling')
275 parser.add_argument('-registry', action='store',
276 default='vk.xml',
277 help='Use specified registry file instead of vk.xml')
278 parser.add_argument('-time', action='store_true',
279 help='Enable timing')
280 parser.add_argument('-validate', action='store_true',
281 help='Enable group validation')
282 parser.add_argument('-o', action='store', dest='directory',
283 default='.',
284 help='Create target and related files in specified directory')
285 parser.add_argument('target', metavar='target', nargs='?',
286 help='Specify target')
Mark Lobodzinskicbaa2cd2016-12-19 09:41:16 -0700287 parser.add_argument('-quiet', action='store_true', default=False,
288 help='Suppress script output during normal execution.')
Mark Lobodzinskif19fef92016-10-11 15:23:51 -0600289
290 args = parser.parse_args()
291
292 # This splits arguments which are space-separated lists
293 args.extension = [name for arg in args.extension for name in arg.split()]
294
295 # Load & parse registry
296 reg = Registry()
297
298 startTimer(args.time)
299 tree = etree.parse(args.registry)
300 endTimer(args.time, '* Time to make ElementTree =')
301
302 startTimer(args.time)
303 reg.loadElementTree(tree)
304 endTimer(args.time, '* Time to parse ElementTree =')
305
306 if (args.validate):
307 reg.validateGroups()
308
309 if (args.dump):
310 write('* Dumping registry to regdump.txt', file=sys.stderr)
Mark Lobodzinski2d589822016-12-12 09:44:34 -0700311 reg.dumpReg(filehandle = open('regdump.txt','w', encoding='utf-8'))
Mark Lobodzinskif19fef92016-10-11 15:23:51 -0600312
313 # create error/warning & diagnostic files
314 if (args.errfile):
Mark Lobodzinski2d589822016-12-12 09:44:34 -0700315 errWarn = open(args.errfile, 'w', encoding='utf-8')
Mark Lobodzinskif19fef92016-10-11 15:23:51 -0600316 else:
317 errWarn = sys.stderr
318
319 if (args.diagfile):
Mark Lobodzinski2d589822016-12-12 09:44:34 -0700320 diag = open(args.diagfile, 'w', encoding='utf-8')
Mark Lobodzinskif19fef92016-10-11 15:23:51 -0600321 else:
322 diag = None
323
324 if (args.debug):
325 pdb.run('genTarget(args)')
326 elif (args.profile):
327 import cProfile, pstats
328 cProfile.run('genTarget(args)', 'profile.txt')
329 p = pstats.Stats('profile.txt')
330 p.strip_dirs().sort_stats('time').print_stats(50)
331 else:
332 genTarget(args)