blob: c34c8a4d1df75b4fd32b366105402e4fe67a348c [file] [log] [blame]
Mike Stroyandee76ef2016-01-07 15:35:37 -07001#!/usr/bin/env python
2#
Dustin Graves94f19142016-05-10 16:44:16 -06003# Copyright (c) 2013-2016 The Khronos Group Inc.
Mike Stroyandee76ef2016-01-07 15:35:37 -07004#
Jon Ashburn3ebf1252016-04-19 11:30:31 -06005# 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
Mike Stroyandee76ef2016-01-07 15:35:37 -07008#
Jon Ashburn3ebf1252016-04-19 11:30:31 -06009# http://www.apache.org/licenses/LICENSE-2.0
Mike Stroyandee76ef2016-01-07 15:35:37 -070010#
Jon Ashburn3ebf1252016-04-19 11:30:31 -060011# 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.
Mike Stroyandee76ef2016-01-07 15:35:37 -070016
17import sys, time, pdb, string, cProfile
18from reg import *
Mike Stroyan845bdc42015-11-02 15:30:20 -070019from generator import write, CGeneratorOptions, COutputGenerator, DocGeneratorOptions, DocOutputGenerator, PyOutputGenerator, ValidityOutputGenerator, HostSynchronizationOutputGenerator, ThreadGeneratorOptions, ThreadOutputGenerator
Dustin Gravesdfa6acf2016-02-11 10:10:14 -070020from generator import ParamCheckerGeneratorOptions, ParamCheckerOutputGenerator
Mark Lobodzinskidc3bd852016-09-06 16:12:23 -060021from generator import UniqueObjectsGeneratorOptions, UniqueObjectsOutputGenerator
Mike Stroyandee76ef2016-01-07 15:35:37 -070022
23# debug - start header generation in debugger
24# dump - dump registry after loading
25# profile - enable Python profiling
26# protect - whether to use #ifndef protections
27# registry <filename> - use specified XML registry instead of gl.xml
28# target - string name of target header, or all targets if None
29# timeit - time length of registry loading & header generation
30# validate - validate return & parameter group tags against <group>
31debug = False
32dump = False
33profile = False
34protect = True
35target = None
36timeit = False
37validate= False
38# Default input / log files
39errFilename = None
40diagFilename = 'diag.txt'
41regFilename = 'vk.xml'
Jamie Madille6f08932016-05-04 08:17:33 -070042outDir = '.'
Mike Stroyandee76ef2016-01-07 15:35:37 -070043
44if __name__ == '__main__':
45 i = 1
46 while (i < len(sys.argv)):
47 arg = sys.argv[i]
48 i = i + 1
49 if (arg == '-debug'):
50 write('Enabling debug (-debug)', file=sys.stderr)
51 debug = True
52 elif (arg == '-dump'):
53 write('Enabling dump (-dump)', file=sys.stderr)
54 dump = True
55 elif (arg == '-noprotect'):
56 write('Disabling inclusion protection in output headers', file=sys.stderr)
57 protect = False
58 elif (arg == '-profile'):
59 write('Enabling profiling (-profile)', file=sys.stderr)
60 profile = True
61 elif (arg == '-registry'):
62 regFilename = sys.argv[i]
63 i = i+1
64 write('Using registry ', regFilename, file=sys.stderr)
65 elif (arg == '-time'):
66 write('Enabling timing (-time)', file=sys.stderr)
67 timeit = True
68 elif (arg == '-validate'):
69 write('Enabling group validation (-validate)', file=sys.stderr)
70 validate = True
Jamie Madille6f08932016-05-04 08:17:33 -070071 elif (arg == '-outdir'):
72 outDir = sys.argv[i]
73 i = i+1
74 write('Using output directory ', outDir, file=sys.stderr)
Mike Stroyandee76ef2016-01-07 15:35:37 -070075 elif (arg[0:1] == '-'):
76 write('Unrecognized argument:', arg, file=sys.stderr)
77 exit(1)
78 else:
79 target = arg
80 write('Using target', target, file=sys.stderr)
81
82# Simple timer functions
83startTime = None
84def startTimer():
85 global startTime
86 startTime = time.clock()
87def endTimer(msg):
88 global startTime
89 endTime = time.clock()
90 if (timeit):
91 write(msg, endTime - startTime)
92 startTime = None
93
94# Load & parse registry
95reg = Registry()
96
97startTimer()
98tree = etree.parse(regFilename)
99endTimer('Time to make ElementTree =')
100
101startTimer()
102reg.loadElementTree(tree)
103endTimer('Time to parse ElementTree =')
104
105if (validate):
106 reg.validateGroups()
107
108if (dump):
109 write('***************************************')
110 write('Performing Registry dump to regdump.txt')
111 write('***************************************')
112 reg.dumpReg(filehandle = open('regdump.txt','w'))
113
114# Turn a list of strings into a regexp string matching exactly those strings
115def makeREstring(list):
116 return '^(' + '|'.join(list) + ')$'
117
118# Descriptive names for various regexp patterns used to select
119# versions and extensions
120allVersions = allExtensions = '.*'
121noVersions = noExtensions = None
122
123# Copyright text prefixing all headers (list of strings).
124prefixStrings = [
125 '/*',
Dustin Graves3ff520c2016-03-28 16:17:38 -0600126 '** Copyright (c) 2015-2016 The Khronos Group Inc.',
Mike Stroyandee76ef2016-01-07 15:35:37 -0700127 '**',
Jon Ashburn3ebf1252016-04-19 11:30:31 -0600128 '** Licensed under the Apache License, Version 2.0 (the "License");',
129 '** you may not use this file except in compliance with the License.',
130 '** You may obtain a copy of the License at',
Mike Stroyandee76ef2016-01-07 15:35:37 -0700131 '**',
Jon Ashburn3ebf1252016-04-19 11:30:31 -0600132 '** http://www.apache.org/licenses/LICENSE-2.0',
Mike Stroyandee76ef2016-01-07 15:35:37 -0700133 '**',
Jon Ashburn3ebf1252016-04-19 11:30:31 -0600134 '** Unless required by applicable law or agreed to in writing, software',
135 '** distributed under the License is distributed on an "AS IS" BASIS,',
136 '** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.',
137 '** See the License for the specific language governing permissions and',
138 '** limitations under the License.',
Mike Stroyandee76ef2016-01-07 15:35:37 -0700139 '*/',
140 ''
141]
142
143# Text specific to Vulkan headers
144vkPrefixStrings = [
145 '/*',
146 '** This header is generated from the Khronos Vulkan XML API Registry.',
147 '**',
148 '*/',
149 ''
150]
151
152# Defaults for generating re-inclusion protection wrappers (or not)
153protectFile = protect
154protectFeature = protect
155protectProto = protect
156
157buildList = [
Dustin Graves3ff520c2016-03-28 16:17:38 -0600158 # Vulkan 1.0 - header for core API + extensions.
159 # To generate just the core API,
Mike Stroyandee76ef2016-01-07 15:35:37 -0700160 # change to 'defaultExtensions = None' below.
161 [ COutputGenerator,
162 CGeneratorOptions(
Mike Stroyan845bdc42015-11-02 15:30:20 -0700163 filename = 'include/vulkan/vulkan.h',
Mike Stroyandee76ef2016-01-07 15:35:37 -0700164 apiname = 'vulkan',
165 profile = None,
166 versions = allVersions,
167 emitversions = allVersions,
168 defaultExtensions = 'vulkan',
169 addExtensions = None,
170 removeExtensions = None,
171 prefixText = prefixStrings + vkPrefixStrings,
172 genFuncPointers = True,
173 protectFile = protectFile,
174 protectFeature = False,
175 protectProto = '#ifndef',
176 protectProtoStr = 'VK_NO_PROTOTYPES',
177 apicall = 'VKAPI_ATTR ',
178 apientry = 'VKAPI_CALL ',
179 apientryp = 'VKAPI_PTR *',
180 alignFuncParam = 48)
181 ],
Dustin Graves3ff520c2016-03-28 16:17:38 -0600182 # Vulkan 1.0 draft - API include files for spec and ref pages
Mike Stroyandee76ef2016-01-07 15:35:37 -0700183 # Overwrites include subdirectories in spec source tree
184 # The generated include files do not include the calling convention
185 # macros (apientry etc.), unlike the header files.
Dustin Graves3ff520c2016-03-28 16:17:38 -0600186 # Because the 1.0 core branch includes ref pages for extensions,
187 # all the extension interfaces need to be generated, even though
188 # none are used by the core spec itself.
Mike Stroyandee76ef2016-01-07 15:35:37 -0700189 [ DocOutputGenerator,
190 DocGeneratorOptions(
191 filename = 'vulkan-docs',
192 apiname = 'vulkan',
193 profile = None,
194 versions = allVersions,
195 emitversions = allVersions,
Dustin Graves3ff520c2016-03-28 16:17:38 -0600196 defaultExtensions = None,
197 addExtensions =
198 makeREstring([
199 'VK_KHR_sampler_mirror_clamp_to_edge',
200 ]),
201 removeExtensions =
202 makeREstring([
203 ]),
Mike Stroyandee76ef2016-01-07 15:35:37 -0700204 prefixText = prefixStrings + vkPrefixStrings,
205 apicall = '',
206 apientry = '',
207 apientryp = '*',
208 genDirectory = '../../doc/specs/vulkan',
209 alignFuncParam = 48,
210 expandEnumerants = False)
211 ],
212 # Vulkan 1.0 draft - API names to validate man/api spec includes & links
Mike Stroyandee76ef2016-01-07 15:35:37 -0700213 [ PyOutputGenerator,
214 DocGeneratorOptions(
215 filename = '../../doc/specs/vulkan/vkapi.py',
216 apiname = 'vulkan',
217 profile = None,
218 versions = allVersions,
219 emitversions = allVersions,
220 defaultExtensions = None,
Dustin Graves3ff520c2016-03-28 16:17:38 -0600221 addExtensions =
222 makeREstring([
223 'VK_KHR_sampler_mirror_clamp_to_edge',
224 ]),
225 removeExtensions =
226 makeREstring([
227 ]))
Mike Stroyandee76ef2016-01-07 15:35:37 -0700228 ],
Dustin Graves3ff520c2016-03-28 16:17:38 -0600229 # Vulkan 1.0 draft - core API validity files for spec
230 # Overwrites validity subdirectories in spec source tree
Mike Stroyandee76ef2016-01-07 15:35:37 -0700231 [ ValidityOutputGenerator,
232 DocGeneratorOptions(
233 filename = 'validity',
234 apiname = 'vulkan',
235 profile = None,
236 versions = allVersions,
237 emitversions = allVersions,
238 defaultExtensions = None,
Dustin Graves3ff520c2016-03-28 16:17:38 -0600239 addExtensions =
240 makeREstring([
241 'VK_KHR_sampler_mirror_clamp_to_edge',
242 ]),
243 removeExtensions =
244 makeREstring([
245 ]),
Mike Stroyandee76ef2016-01-07 15:35:37 -0700246 genDirectory = '../../doc/specs/vulkan')
247 ],
Dustin Graves3ff520c2016-03-28 16:17:38 -0600248 # Vulkan 1.0 draft - core API host sync table files for spec
249 # Overwrites subdirectory in spec source tree
Mike Stroyandee76ef2016-01-07 15:35:37 -0700250 [ HostSynchronizationOutputGenerator,
251 DocGeneratorOptions(
252 filename = 'hostsynctable',
253 apiname = 'vulkan',
254 profile = None,
255 versions = allVersions,
256 emitversions = allVersions,
257 defaultExtensions = None,
Dustin Graves3ff520c2016-03-28 16:17:38 -0600258 addExtensions =
259 makeREstring([
260 'VK_KHR_sampler_mirror_clamp_to_edge',
261 ]),
262 removeExtensions =
263 makeREstring([
264 ]),
Mike Stroyandee76ef2016-01-07 15:35:37 -0700265 genDirectory = '../../doc/specs/vulkan')
266 ],
Mike Stroyan845bdc42015-11-02 15:30:20 -0700267 # Vulkan 1.0 draft - thread checking layer
268 [ ThreadOutputGenerator,
269 ThreadGeneratorOptions(
270 filename = 'thread_check.h',
271 apiname = 'vulkan',
272 profile = None,
273 versions = allVersions,
274 emitversions = allVersions,
275 defaultExtensions = 'vulkan',
276 addExtensions = None,
277 removeExtensions = None,
278 prefixText = prefixStrings + vkPrefixStrings,
279 genFuncPointers = True,
280 protectFile = protectFile,
281 protectFeature = False,
282 protectProto = True,
283 protectProtoStr = 'VK_PROTOTYPES',
Chia-I Wuab461772016-05-16 11:48:11 +0800284 apicall = 'VKAPI_ATTR ',
Mike Stroyan845bdc42015-11-02 15:30:20 -0700285 apientry = 'VKAPI_CALL ',
286 apientryp = 'VKAPI_PTR *',
Jamie Madille6f08932016-05-04 08:17:33 -0700287 alignFuncParam = 48,
288 genDirectory = outDir)
Mike Stroyan845bdc42015-11-02 15:30:20 -0700289 ],
Dustin Gravesdfa6acf2016-02-11 10:10:14 -0700290 [ ParamCheckerOutputGenerator,
291 ParamCheckerGeneratorOptions(
Mark Lobodzinski739391a2016-03-17 15:08:18 -0600292 filename = 'parameter_validation.h',
Dustin Gravesdfa6acf2016-02-11 10:10:14 -0700293 apiname = 'vulkan',
294 profile = None,
295 versions = allVersions,
296 emitversions = allVersions,
297 defaultExtensions = 'vulkan',
298 addExtensions = None,
299 removeExtensions = None,
300 prefixText = prefixStrings + vkPrefixStrings,
301 genFuncPointers = True,
302 protectFile = protectFile,
303 protectFeature = False,
304 protectProto = None,
305 protectProtoStr = 'VK_NO_PROTOTYPES',
306 apicall = 'VKAPI_ATTR ',
307 apientry = 'VKAPI_CALL ',
308 apientryp = 'VKAPI_PTR *',
Jamie Madille6f08932016-05-04 08:17:33 -0700309 alignFuncParam = 48,
310 genDirectory = outDir)
Dustin Gravesdfa6acf2016-02-11 10:10:14 -0700311 ],
Mark Lobodzinskidc3bd852016-09-06 16:12:23 -0600312 [ UniqueObjectsOutputGenerator,
313 UniqueObjectsGeneratorOptions(
314 filename = 'unique_objects_wrappers.h',
315 apiname = 'vulkan',
316 profile = None,
317 versions = allVersions,
318 emitversions = allVersions,
319 defaultExtensions = 'vulkan',
320 addExtensions = None,
321 removeExtensions = None,
322 prefixText = prefixStrings + vkPrefixStrings,
323 genFuncPointers = True,
324 protectFile = False,
325 protectFeature = False,
326 protectProto = None,
327 protectProtoStr = 'VK_NO_PROTOTYPES',
328 apicall = 'VKAPI_ATTR ',
329 apientry = 'VKAPI_CALL ',
330 apientryp = 'VKAPI_PTR *',
331 alignFuncParam = 48,
332 genDirectory = outDir)
333 ],
Mike Stroyandee76ef2016-01-07 15:35:37 -0700334 None
335]
336
337# create error/warning & diagnostic files
338if (errFilename):
339 errWarn = open(errFilename,'w')
340else:
341 errWarn = sys.stderr
342diag = open(diagFilename, 'w')
343
Jamie Madille6f08932016-05-04 08:17:33 -0700344# check that output directory exists
345if (not os.path.isdir(outDir)):
346 write('Output directory does not exist: ', outDir)
347 raise
348
Mike Stroyandee76ef2016-01-07 15:35:37 -0700349def genHeaders():
350 # Loop over targets, building each
351 generated = 0
352 for item in buildList:
353 if (item == None):
354 break
355 createGenerator = item[0]
356 genOpts = item[1]
357 if (target and target != genOpts.filename):
358 # write('*** Skipping', genOpts.filename)
359 continue
360 write('*** Building', genOpts.filename)
361 generated = generated + 1
362 startTimer()
363 gen = createGenerator(errFile=errWarn,
364 warnFile=errWarn,
365 diagFile=diag)
366 reg.setGenerator(gen)
367 reg.apiGen(genOpts)
368 write('** Generated', genOpts.filename)
369 endTimer('Time to generate ' + genOpts.filename + ' =')
370 if (target and generated == 0):
371 write('Failed to generate target:', target)
372
373if (debug):
374 pdb.run('genHeaders()')
375elif (profile):
376 import cProfile, pstats
377 cProfile.run('genHeaders()', 'profile.txt')
378 p = pstats.Stats('profile.txt')
379 p.strip_dirs().sort_stats('time').print_stats(50)
380else:
381 genHeaders()