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