blob: 63b8bab849e585614e028517b38615cdd81fc7f1 [file] [log] [blame]
Mark Lobodzinskif19fef92016-10-11 15:23:51 -06001#!/usr/bin/env python
2#
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)
53def makeGenOpts(extensions = [], protect = True, directory = '.'):
54 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)
63 removeExtensions = makeREstring([])
64
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,
202 protect = args.protect,
203 directory = args.directory)
204
205 if (args.target in genOpts.keys()):
206 createGenerator = genOpts[args.target][0]
207 options = genOpts[args.target][1]
208
209 write('* Building', options.filename, file=sys.stderr)
210
211 startTimer(args.time)
212 gen = createGenerator(errFile=errWarn,
213 warnFile=errWarn,
214 diagFile=diag)
215 reg.setGenerator(gen)
216 reg.apiGen(options)
217 write('* Generated', options.filename, file=sys.stderr)
218 endTimer(args.time, '* Time to generate ' + options.filename + ' =')
219 else:
220 write('No generator options for unknown target:',
221 args.target, file=sys.stderr)
222
223# -extension name - may be a single extension name, a a space-separated list
224# of names, or a regular expression.
225if __name__ == '__main__':
226 parser = argparse.ArgumentParser()
227
228 parser.add_argument('-extension', action='append',
229 default=[],
230 help='Specify an extension or extensions to add to targets')
231 parser.add_argument('-debug', action='store_true',
232 help='Enable debugging')
233 parser.add_argument('-dump', action='store_true',
234 help='Enable dump to stderr')
235 parser.add_argument('-diagfile', action='store',
236 default=None,
237 help='Write diagnostics to specified file')
238 parser.add_argument('-errfile', action='store',
239 default=None,
240 help='Write errors and warnings to specified file instead of stderr')
241 parser.add_argument('-noprotect', dest='protect', action='store_false',
242 help='Disable inclusion protection in output headers')
243 parser.add_argument('-profile', action='store_true',
244 help='Enable profiling')
245 parser.add_argument('-registry', action='store',
246 default='vk.xml',
247 help='Use specified registry file instead of vk.xml')
248 parser.add_argument('-time', action='store_true',
249 help='Enable timing')
250 parser.add_argument('-validate', action='store_true',
251 help='Enable group validation')
252 parser.add_argument('-o', action='store', dest='directory',
253 default='.',
254 help='Create target and related files in specified directory')
255 parser.add_argument('target', metavar='target', nargs='?',
256 help='Specify target')
257
258 args = parser.parse_args()
259
260 # This splits arguments which are space-separated lists
261 args.extension = [name for arg in args.extension for name in arg.split()]
262
263 # Load & parse registry
264 reg = Registry()
265
266 startTimer(args.time)
267 tree = etree.parse(args.registry)
268 endTimer(args.time, '* Time to make ElementTree =')
269
270 startTimer(args.time)
271 reg.loadElementTree(tree)
272 endTimer(args.time, '* Time to parse ElementTree =')
273
274 if (args.validate):
275 reg.validateGroups()
276
277 if (args.dump):
278 write('* Dumping registry to regdump.txt', file=sys.stderr)
279 reg.dumpReg(filehandle = open('regdump.txt','w'))
280
281 # create error/warning & diagnostic files
282 if (args.errfile):
283 errWarn = open(args.errfile, 'w')
284 else:
285 errWarn = sys.stderr
286
287 if (args.diagfile):
288 diag = open(args.diagfile, 'w')
289 else:
290 diag = None
291
292 if (args.debug):
293 pdb.run('genTarget(args)')
294 elif (args.profile):
295 import cProfile, pstats
296 cProfile.run('genTarget(args)', 'profile.txt')
297 p = pstats.Stats('profile.txt')
298 p.strip_dirs().sort_stats('time').print_stats(50)
299 else:
300 genTarget(args)