blob: 7f67012ec14d078fc4cb4a9975519100b0bd06a4 [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 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,
206 helper_file_type = 'enum_string_helper')
Mark Lobodzinski41d9bb32016-12-27 13:50:05 -0700207 ]
208
Mark Lobodzinski79839b72016-12-28 08:49:29 -0700209 # Helper file generator options for vk_test.h
210 genOpts['vk_test.h'] = [
211 HelperFileOutputGenerator,
212 HelperFileOutputGeneratorOptions(
213 filename = 'vk_test.h',
214 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,
228 helper_file_type = 'test')
229 ]
Mark Lobodzinski41d9bb32016-12-27 13:50:05 -0700230
Mark Lobodzinskieb0b5ef2016-12-06 11:30:50 -0700231
232
Mark Lobodzinskif19fef92016-10-11 15:23:51 -0600233# Generate a target based on the options in the matching genOpts{} object.
234# This is encapsulated in a function so it can be profiled and/or timed.
235# The args parameter is an parsed argument object containing the following
236# fields that are used:
237# target - target to generate
238# directory - directory to generate it in
239# protect - True if re-inclusion wrappers should be created
240# extensions - list of additional extensions to include in generated
241# interfaces
242def genTarget(args):
243 global genOpts
244
245 # Create generator options with specified parameters
246 makeGenOpts(extensions = args.extension,
Mark Lobodzinski2d589822016-12-12 09:44:34 -0700247 removeExtensions = args.removeExtension,
Mark Lobodzinskif19fef92016-10-11 15:23:51 -0600248 protect = args.protect,
249 directory = args.directory)
250
251 if (args.target in genOpts.keys()):
252 createGenerator = genOpts[args.target][0]
253 options = genOpts[args.target][1]
254
Mark Lobodzinskicbaa2cd2016-12-19 09:41:16 -0700255 if not args.quiet:
256 write('* Building', options.filename, file=sys.stderr)
Mark Lobodzinskif19fef92016-10-11 15:23:51 -0600257
258 startTimer(args.time)
259 gen = createGenerator(errFile=errWarn,
260 warnFile=errWarn,
261 diagFile=diag)
262 reg.setGenerator(gen)
263 reg.apiGen(options)
Mark Lobodzinskicbaa2cd2016-12-19 09:41:16 -0700264
265 if not args.quiet:
266 write('* Generated', options.filename, file=sys.stderr)
Mark Lobodzinskif19fef92016-10-11 15:23:51 -0600267 endTimer(args.time, '* Time to generate ' + options.filename + ' =')
268 else:
269 write('No generator options for unknown target:',
270 args.target, file=sys.stderr)
271
272# -extension name - may be a single extension name, a a space-separated list
273# of names, or a regular expression.
274if __name__ == '__main__':
275 parser = argparse.ArgumentParser()
276
277 parser.add_argument('-extension', action='append',
278 default=[],
279 help='Specify an extension or extensions to add to targets')
Mark Lobodzinski2d589822016-12-12 09:44:34 -0700280 parser.add_argument('-removeExtension', action='append',
281 default=[],
282 help='Specify an extension or extensions to remove from targets')
Mark Lobodzinskif19fef92016-10-11 15:23:51 -0600283 parser.add_argument('-debug', action='store_true',
284 help='Enable debugging')
285 parser.add_argument('-dump', action='store_true',
286 help='Enable dump to stderr')
287 parser.add_argument('-diagfile', action='store',
288 default=None,
289 help='Write diagnostics to specified file')
290 parser.add_argument('-errfile', action='store',
291 default=None,
292 help='Write errors and warnings to specified file instead of stderr')
293 parser.add_argument('-noprotect', dest='protect', action='store_false',
294 help='Disable inclusion protection in output headers')
295 parser.add_argument('-profile', action='store_true',
296 help='Enable profiling')
297 parser.add_argument('-registry', action='store',
298 default='vk.xml',
299 help='Use specified registry file instead of vk.xml')
300 parser.add_argument('-time', action='store_true',
301 help='Enable timing')
302 parser.add_argument('-validate', action='store_true',
303 help='Enable group validation')
304 parser.add_argument('-o', action='store', dest='directory',
305 default='.',
306 help='Create target and related files in specified directory')
307 parser.add_argument('target', metavar='target', nargs='?',
308 help='Specify target')
Mark Lobodzinskicbaa2cd2016-12-19 09:41:16 -0700309 parser.add_argument('-quiet', action='store_true', default=False,
310 help='Suppress script output during normal execution.')
Mark Lobodzinskif19fef92016-10-11 15:23:51 -0600311
312 args = parser.parse_args()
313
314 # This splits arguments which are space-separated lists
315 args.extension = [name for arg in args.extension for name in arg.split()]
316
317 # Load & parse registry
318 reg = Registry()
319
320 startTimer(args.time)
321 tree = etree.parse(args.registry)
322 endTimer(args.time, '* Time to make ElementTree =')
323
324 startTimer(args.time)
325 reg.loadElementTree(tree)
326 endTimer(args.time, '* Time to parse ElementTree =')
327
328 if (args.validate):
329 reg.validateGroups()
330
331 if (args.dump):
332 write('* Dumping registry to regdump.txt', file=sys.stderr)
Mark Lobodzinski2d589822016-12-12 09:44:34 -0700333 reg.dumpReg(filehandle = open('regdump.txt','w', encoding='utf-8'))
Mark Lobodzinskif19fef92016-10-11 15:23:51 -0600334
335 # create error/warning & diagnostic files
336 if (args.errfile):
Mark Lobodzinski2d589822016-12-12 09:44:34 -0700337 errWarn = open(args.errfile, 'w', encoding='utf-8')
Mark Lobodzinskif19fef92016-10-11 15:23:51 -0600338 else:
339 errWarn = sys.stderr
340
341 if (args.diagfile):
Mark Lobodzinski2d589822016-12-12 09:44:34 -0700342 diag = open(args.diagfile, 'w', encoding='utf-8')
Mark Lobodzinskif19fef92016-10-11 15:23:51 -0600343 else:
344 diag = None
345
346 if (args.debug):
347 pdb.run('genTarget(args)')
348 elif (args.profile):
349 import cProfile, pstats
350 cProfile.run('genTarget(args)', 'profile.txt')
351 p = pstats.Stats('profile.txt')
352 p.strip_dirs().sort_stats('time').print_stats(50)
353 else:
354 genTarget(args)