blob: becf5804d4509e154c896715acd8ec1b4b4bad6b [file] [log] [blame]
Mark Lobodzinski0a79de42018-05-04 09:33:39 -06001#!/usr/bin/python3
2#
Jon Leechec2db852021-02-02 01:30:19 -08003# Copyright 2013-2021 The Khronos Group Inc.
Mark Lobodzinski0a79de42018-05-04 09:33:39 -06004#
Jon Leech9d2dfca2020-06-08 04:31:23 -07005# SPDX-License-Identifier: Apache-2.0
Mark Lobodzinski0a79de42018-05-04 09:33:39 -06006
Jon Leech171949d2019-04-16 05:57:09 -07007import argparse
8import pdb
9import re
10import sys
11import time
12import xml.etree.ElementTree as etree
13
Mark Lobodzinski0a79de42018-05-04 09:33:39 -060014from cgenerator import CGeneratorOptions, COutputGenerator
15from docgenerator import DocGeneratorOptions, DocOutputGenerator
Jon Leech171949d2019-04-16 05:57:09 -070016from extensionmetadocgenerator import (ExtensionMetaDocGeneratorOptions,
17 ExtensionMetaDocOutputGenerator)
Jon Leech0c5351f2020-05-04 03:42:53 -070018from interfacedocgenerator import InterfaceDocGenerator
Jon Leech171949d2019-04-16 05:57:09 -070019from generator import write
Jon Leech87451c52020-11-01 22:37:12 -080020from spirvcapgenerator import SpirvCapabilityOutputGenerator
Mark Lobodzinski0a79de42018-05-04 09:33:39 -060021from hostsyncgenerator import HostSynchronizationOutputGenerator
Jon Leech171949d2019-04-16 05:57:09 -070022from pygenerator import PyOutputGenerator
Jon Leech0c5351f2020-05-04 03:42:53 -070023from reflib import logDiag, logWarn, setLogFile
Jon Leech171949d2019-04-16 05:57:09 -070024from reg import Registry
25from validitygenerator import ValidityOutputGenerator
Jon Leech71be0a42019-03-20 02:20:31 -070026from vkconventions import VulkanConventions
Mark Lobodzinski0a79de42018-05-04 09:33:39 -060027
Jon Leech42ad3f92019-09-08 21:57:00 -070028
Mark Lobodzinski0a79de42018-05-04 09:33:39 -060029# Simple timer functions
30startTime = None
31
Jon Leech171949d2019-04-16 05:57:09 -070032
Mark Lobodzinski0a79de42018-05-04 09:33:39 -060033def startTimer(timeit):
34 global startTime
Shannon McPherson7f02d9b2019-02-04 09:56:53 -070035 if timeit:
36 startTime = time.process_time()
Mark Lobodzinski0a79de42018-05-04 09:33:39 -060037
Jon Leech42ad3f92019-09-08 21:57:00 -070038
Mark Lobodzinski0a79de42018-05-04 09:33:39 -060039def endTimer(timeit, msg):
40 global startTime
Shannon McPherson7f02d9b2019-02-04 09:56:53 -070041 if timeit:
42 endTime = time.process_time()
Jon Leech0c5351f2020-05-04 03:42:53 -070043 logDiag(msg, endTime - startTime)
Mark Lobodzinski0a79de42018-05-04 09:33:39 -060044 startTime = None
45
Jon Leech4ee33d22019-08-17 15:58:46 -070046
47def makeREstring(strings, default=None, strings_are_regex=False):
48 """Turn a list of strings into a regexp string matching exactly those strings."""
49 if strings or default is None:
50 if not strings_are_regex:
51 strings = (re.escape(s) for s in strings)
52 return '^(' + '|'.join(strings) + ')$'
53 return default
Mark Lobodzinski0a79de42018-05-04 09:33:39 -060054
Jon Leech42ad3f92019-09-08 21:57:00 -070055
Mark Lobodzinski0a79de42018-05-04 09:33:39 -060056def makeGenOpts(args):
Jon Leech42ad3f92019-09-08 21:57:00 -070057 """Returns a directory of [ generator function, generator options ] indexed
58 by specified short names. The generator options incorporate the following
59 parameters:
60
61 args is an parsed argument object; see below for the fields that are used."""
Mark Lobodzinski0a79de42018-05-04 09:33:39 -060062 global genOpts
63 genOpts = {}
64
65 # Default class of extensions to include, or None
66 defaultExtensions = args.defaultExtensions
67
68 # Additional extensions to include (list of extensions)
69 extensions = args.extension
70
71 # Extensions to remove (list of extensions)
72 removeExtensions = args.removeExtensions
73
74 # Extensions to emit (list of extensions)
75 emitExtensions = args.emitExtensions
76
Jon Leech87451c52020-11-01 22:37:12 -080077 # SPIR-V capabilities / features to emit (list of extensions & capabilities)
78 emitSpirv = args.emitSpirv
79
Mark Lobodzinski0a79de42018-05-04 09:33:39 -060080 # Features to include (list of features)
81 features = args.feature
82
83 # Whether to disable inclusion protect in headers
84 protect = args.protect
85
86 # Output target directory
87 directory = args.directory
88
Jon Leechdb1a98c2020-06-01 04:52:39 -070089 # Path to generated files, particularly api.py
90 genpath = args.genpath
91
Jon Leeche1d8c492021-03-29 01:18:51 -070092 # Generate MISRA C-friendly headers
93 misracstyle = args.misracstyle;
94
95 # Generate MISRA C++-friendly headers
96 misracppstyle = args.misracppstyle;
97
Mark Lobodzinski0a79de42018-05-04 09:33:39 -060098 # Descriptive names for various regexp patterns used to select
99 # versions and extensions
Jon Leech87451c52020-11-01 22:37:12 -0800100 allSpirv = allFeatures = allExtensions = r'.*'
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600101
102 # Turn lists of names/patterns into matching regular expressions
103 addExtensionsPat = makeREstring(extensions, None)
104 removeExtensionsPat = makeREstring(removeExtensions, None)
105 emitExtensionsPat = makeREstring(emitExtensions, allExtensions)
Jon Leech87451c52020-11-01 22:37:12 -0800106 emitSpirvPat = makeREstring(emitSpirv, allSpirv)
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600107 featuresPat = makeREstring(features, allFeatures)
108
109 # Copyright text prefixing all headers (list of strings).
Jon Leechf3152452020-06-15 02:00:56 -0700110 # The SPDX formatting below works around constraints of the 'reuse' tool
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600111 prefixStrings = [
112 '/*',
Jon Leechec2db852021-02-02 01:30:19 -0800113 '** Copyright 2015-2021 The Khronos Group Inc.',
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600114 '**',
Jon Leechf3152452020-06-15 02:00:56 -0700115 '** SPDX' + '-License-Identifier: Apache-2.0',
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600116 '*/',
117 ''
118 ]
119
120 # Text specific to Vulkan headers
121 vkPrefixStrings = [
122 '/*',
123 '** This header is generated from the Khronos Vulkan XML API Registry.',
124 '**',
125 '*/',
126 ''
127 ]
128
129 # Defaults for generating re-inclusion protection wrappers (or not)
130 protectFile = protect
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600131
Jon Leech71be0a42019-03-20 02:20:31 -0700132 # An API style conventions object
133 conventions = VulkanConventions()
134
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600135 # API include files for spec and ref pages
136 # Overwrites include subdirectories in spec source tree
137 # The generated include files do not include the calling convention
138 # macros (apientry etc.), unlike the header files.
139 # Because the 1.0 core branch includes ref pages for extensions,
140 # all the extension interfaces need to be generated, even though
141 # none are used by the core spec itself.
142 genOpts['apiinc'] = [
143 DocOutputGenerator,
144 DocGeneratorOptions(
Jon Leech71be0a42019-03-20 02:20:31 -0700145 conventions = conventions,
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600146 filename = 'timeMarker',
147 directory = directory,
Jon Leechdb1a98c2020-06-01 04:52:39 -0700148 genpath = genpath,
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600149 apiname = 'vulkan',
150 profile = None,
151 versions = featuresPat,
152 emitversions = featuresPat,
153 defaultExtensions = None,
154 addExtensions = addExtensionsPat,
155 removeExtensions = removeExtensionsPat,
156 emitExtensions = emitExtensionsPat,
157 prefixText = prefixStrings + vkPrefixStrings,
158 apicall = '',
159 apientry = '',
160 apientryp = '*',
161 alignFuncParam = 48,
162 expandEnumerants = False)
163 ]
164
Jon Leech09531f22020-05-15 04:54:44 -0700165 # Python representation of API information, used by scripts that
166 # don't need to load the full XML.
167 genOpts['api.py'] = [
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600168 PyOutputGenerator,
169 DocGeneratorOptions(
Jon Leech71be0a42019-03-20 02:20:31 -0700170 conventions = conventions,
Jon Leech09531f22020-05-15 04:54:44 -0700171 filename = 'api.py',
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600172 directory = directory,
Jon Leechdb1a98c2020-06-01 04:52:39 -0700173 genpath = None,
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600174 apiname = 'vulkan',
175 profile = None,
176 versions = featuresPat,
177 emitversions = featuresPat,
178 defaultExtensions = None,
179 addExtensions = addExtensionsPat,
180 removeExtensions = removeExtensionsPat,
Jon Leech09531f22020-05-15 04:54:44 -0700181 emitExtensions = emitExtensionsPat,
182 reparentEnums = False)
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600183 ]
184
185 # API validity files for spec
186 genOpts['validinc'] = [
187 ValidityOutputGenerator,
188 DocGeneratorOptions(
Jon Leech71be0a42019-03-20 02:20:31 -0700189 conventions = conventions,
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600190 filename = 'timeMarker',
191 directory = directory,
Jon Leechdb1a98c2020-06-01 04:52:39 -0700192 genpath = None,
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600193 apiname = 'vulkan',
194 profile = None,
195 versions = featuresPat,
196 emitversions = featuresPat,
197 defaultExtensions = None,
198 addExtensions = addExtensionsPat,
199 removeExtensions = removeExtensionsPat,
200 emitExtensions = emitExtensionsPat)
201 ]
202
203 # API host sync table files for spec
204 genOpts['hostsyncinc'] = [
205 HostSynchronizationOutputGenerator,
206 DocGeneratorOptions(
Jon Leech71be0a42019-03-20 02:20:31 -0700207 conventions = conventions,
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600208 filename = 'timeMarker',
209 directory = directory,
Jon Leechdb1a98c2020-06-01 04:52:39 -0700210 genpath = None,
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600211 apiname = 'vulkan',
212 profile = None,
213 versions = featuresPat,
214 emitversions = featuresPat,
215 defaultExtensions = None,
216 addExtensions = addExtensionsPat,
217 removeExtensions = removeExtensionsPat,
Jon Leech0c5351f2020-05-04 03:42:53 -0700218 emitExtensions = emitExtensionsPat,
219 reparentEnums = False)
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600220 ]
221
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600222 # Extension metainformation for spec extension appendices
Jon Leech0c5351f2020-05-04 03:42:53 -0700223 # Includes all extensions by default, but only so that the generated
224 # 'promoted_extensions_*' files refer to all extensions that were
225 # promoted to a core version.
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600226 genOpts['extinc'] = [
227 ExtensionMetaDocOutputGenerator,
228 ExtensionMetaDocGeneratorOptions(
Jon Leech71be0a42019-03-20 02:20:31 -0700229 conventions = conventions,
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600230 filename = 'timeMarker',
231 directory = directory,
Jon Leechdb1a98c2020-06-01 04:52:39 -0700232 genpath = None,
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600233 apiname = 'vulkan',
234 profile = None,
235 versions = featuresPat,
236 emitversions = None,
237 defaultExtensions = defaultExtensions,
Jon Leech0c5351f2020-05-04 03:42:53 -0700238 addExtensions = addExtensionsPat,
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600239 removeExtensions = None,
240 emitExtensions = emitExtensionsPat)
241 ]
242
Jon Leech0c5351f2020-05-04 03:42:53 -0700243 # Version and extension interface docs for version/extension appendices
244 # Includes all extensions by default.
245 genOpts['interfaceinc'] = [
246 InterfaceDocGenerator,
247 DocGeneratorOptions(
248 conventions = conventions,
249 filename = 'timeMarker',
250 directory = directory,
Jon Leechdb1a98c2020-06-01 04:52:39 -0700251 genpath = None,
Jon Leech0c5351f2020-05-04 03:42:53 -0700252 apiname = 'vulkan',
253 profile = None,
254 versions = featuresPat,
255 emitversions = featuresPat,
256 defaultExtensions = None,
257 addExtensions = addExtensionsPat,
258 removeExtensions = removeExtensionsPat,
259 emitExtensions = emitExtensionsPat,
260 reparentEnums = False)
261 ]
262
Jon Leech87451c52020-11-01 22:37:12 -0800263 genOpts['spirvcapinc'] = [
264 SpirvCapabilityOutputGenerator,
265 DocGeneratorOptions(
266 conventions = conventions,
267 filename = 'timeMarker',
268 directory = directory,
269 genpath = None,
270 apiname = 'vulkan',
271 profile = None,
272 versions = featuresPat,
273 emitversions = featuresPat,
274 defaultExtensions = None,
275 addExtensions = addExtensionsPat,
276 removeExtensions = removeExtensionsPat,
277 emitExtensions = emitExtensionsPat,
278 emitSpirv = emitSpirvPat,
279 reparentEnums = False)
280 ]
281
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600282 # Platform extensions, in their own header files
283 # Each element of the platforms[] array defines information for
284 # generating a single platform:
285 # [0] is the generated header file name
286 # [1] is the set of platform extensions to generate
287 # [2] is additional extensions whose interfaces should be considered,
288 # but suppressed in the output, to avoid duplicate definitions of
289 # dependent types like VkDisplayKHR and VkSurfaceKHR which come from
290 # non-platform extensions.
291
292 # Track all platform extensions, for exclusion from vulkan_core.h
293 allPlatformExtensions = []
294
Jon Leech26341b42020-03-17 05:02:49 -0700295 # Extensions suppressed for all WSI platforms (WSI extensions required
296 # by all platforms)
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600297 commonSuppressExtensions = [ 'VK_KHR_display', 'VK_KHR_swapchain' ]
298
Jon Leech26341b42020-03-17 05:02:49 -0700299 # Extensions required and suppressed for beta "platform". This can
300 # probably eventually be derived from the requires= attributes of
301 # the extension blocks.
Jon Leeche01b0062021-04-13 02:38:07 -0700302 betaRequireExtensions = [
303 'VK_KHR_portability_subset',
304 'VK_KHR_video_queue',
305 'VK_KHR_video_decode_queue',
306 'VK_KHR_video_encode_queue',
307 'VK_EXT_video_decode_h264',
308 'VK_EXT_video_decode_h265',
309 'VK_EXT_video_encode_h264',
310 ]
311
Jon Leechd2308182020-11-22 23:49:55 -0800312 betaSuppressExtensions = []
Jon Leech26341b42020-03-17 05:02:49 -0700313
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600314 platforms = [
315 [ 'vulkan_android.h', [ 'VK_KHR_android_surface',
316 'VK_ANDROID_external_memory_android_hardware_buffer'
317 ], commonSuppressExtensions ],
Jon Leecha8d6ab12021-03-21 20:23:34 -0700318 [ 'vulkan_fuchsia.h', [ 'VK_FUCHSIA_imagepipe_surface',
319 'VK_FUCHSIA_external_memory',
320 'VK_FUCHSIA_external_semaphore' ], commonSuppressExtensions ],
Jon Leech71be0a42019-03-20 02:20:31 -0700321 [ 'vulkan_ggp.h', [ 'VK_GGP_stream_descriptor_surface',
322 'VK_GGP_frame_token' ], commonSuppressExtensions ],
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600323 [ 'vulkan_ios.h', [ 'VK_MVK_ios_surface' ], commonSuppressExtensions ],
324 [ 'vulkan_macos.h', [ 'VK_MVK_macos_surface' ], commonSuppressExtensions ],
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600325 [ 'vulkan_vi.h', [ 'VK_NN_vi_surface' ], commonSuppressExtensions ],
326 [ 'vulkan_wayland.h', [ 'VK_KHR_wayland_surface' ], commonSuppressExtensions ],
Jon Leech7dbd74f2019-03-21 04:09:20 -0700327 [ 'vulkan_win32.h', [ 'VK_.*_win32(|_.*)', 'VK_EXT_full_screen_exclusive' ],
328 commonSuppressExtensions +
329 [ 'VK_KHR_external_semaphore',
330 'VK_KHR_external_memory_capabilities',
331 'VK_KHR_external_fence',
332 'VK_KHR_external_fence_capabilities',
333 'VK_KHR_get_surface_capabilities2',
334 'VK_NV_external_memory_capabilities',
335 ] ],
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600336 [ 'vulkan_xcb.h', [ 'VK_KHR_xcb_surface' ], commonSuppressExtensions ],
337 [ 'vulkan_xlib.h', [ 'VK_KHR_xlib_surface' ], commonSuppressExtensions ],
Jon Leechdb06fce2020-07-04 00:33:22 -0700338 [ 'vulkan_directfb.h', [ 'VK_EXT_directfb_surface' ], commonSuppressExtensions ],
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600339 [ 'vulkan_xlib_xrandr.h', [ 'VK_EXT_acquire_xlib_display' ], commonSuppressExtensions ],
Jon Leech982f0f82019-03-04 03:28:11 -0800340 [ 'vulkan_metal.h', [ 'VK_EXT_metal_surface' ], commonSuppressExtensions ],
Jon Leecha6a971a2021-02-28 22:50:55 -0800341 [ 'vulkan_screen.h', [ 'VK_QNX_screen_surface' ], commonSuppressExtensions ],
Jon Leech26341b42020-03-17 05:02:49 -0700342 [ 'vulkan_beta.h', betaRequireExtensions, betaSuppressExtensions ],
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600343 ]
344
345 for platform in platforms:
346 headername = platform[0]
347
348 allPlatformExtensions += platform[1]
349
Jon Leech4ee33d22019-08-17 15:58:46 -0700350 addPlatformExtensionsRE = makeREstring(
351 platform[1] + platform[2], strings_are_regex=True)
352 emitPlatformExtensionsRE = makeREstring(
353 platform[1], strings_are_regex=True)
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600354
355 opts = CGeneratorOptions(
Jon Leech71be0a42019-03-20 02:20:31 -0700356 conventions = conventions,
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600357 filename = headername,
358 directory = directory,
Jon Leechdb1a98c2020-06-01 04:52:39 -0700359 genpath = None,
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600360 apiname = 'vulkan',
361 profile = None,
362 versions = featuresPat,
363 emitversions = None,
364 defaultExtensions = None,
365 addExtensions = addPlatformExtensionsRE,
366 removeExtensions = None,
367 emitExtensions = emitPlatformExtensionsRE,
368 prefixText = prefixStrings + vkPrefixStrings,
369 genFuncPointers = True,
370 protectFile = protectFile,
371 protectFeature = False,
372 protectProto = '#ifndef',
373 protectProtoStr = 'VK_NO_PROTOTYPES',
374 apicall = 'VKAPI_ATTR ',
375 apientry = 'VKAPI_CALL ',
376 apientryp = 'VKAPI_PTR *',
Jon Leeche1d8c492021-03-29 01:18:51 -0700377 alignFuncParam = 48,
378 misracstyle = misracstyle,
379 misracppstyle = misracppstyle)
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600380
381 genOpts[headername] = [ COutputGenerator, opts ]
382
383 # Header for core API + extensions.
384 # To generate just the core API,
385 # change to 'defaultExtensions = None' below.
386 #
387 # By default this adds all enabled, non-platform extensions.
388 # It removes all platform extensions (from the platform headers options
389 # constructed above) as well as any explicitly specified removals.
390
Jon Leech4ee33d22019-08-17 15:58:46 -0700391 removeExtensionsPat = makeREstring(
392 allPlatformExtensions + removeExtensions, None, strings_are_regex=True)
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600393
394 genOpts['vulkan_core.h'] = [
395 COutputGenerator,
396 CGeneratorOptions(
Jon Leech71be0a42019-03-20 02:20:31 -0700397 conventions = conventions,
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600398 filename = 'vulkan_core.h',
399 directory = directory,
Jon Leechdb1a98c2020-06-01 04:52:39 -0700400 genpath = None,
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600401 apiname = 'vulkan',
402 profile = None,
403 versions = featuresPat,
404 emitversions = featuresPat,
405 defaultExtensions = defaultExtensions,
Jon Leech8188e3f2020-06-21 00:03:40 -0700406 addExtensions = addExtensionsPat,
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600407 removeExtensions = removeExtensionsPat,
408 emitExtensions = emitExtensionsPat,
409 prefixText = prefixStrings + vkPrefixStrings,
410 genFuncPointers = True,
411 protectFile = protectFile,
412 protectFeature = False,
413 protectProto = '#ifndef',
414 protectProtoStr = 'VK_NO_PROTOTYPES',
415 apicall = 'VKAPI_ATTR ',
416 apientry = 'VKAPI_CALL ',
417 apientryp = 'VKAPI_PTR *',
Jon Leeche1d8c492021-03-29 01:18:51 -0700418 alignFuncParam = 48,
419 misracstyle = misracstyle,
420 misracppstyle = misracppstyle)
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600421 ]
422
423 # Unused - vulkan10.h target.
424 # It is possible to generate a header with just the Vulkan 1.0 +
425 # extension interfaces defined, but since the promoted KHR extensions
426 # are now defined in terms of the 1.1 interfaces, such a header is very
427 # similar to vulkan_core.h.
428 genOpts['vulkan10.h'] = [
429 COutputGenerator,
430 CGeneratorOptions(
Jon Leech71be0a42019-03-20 02:20:31 -0700431 conventions = conventions,
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600432 filename = 'vulkan10.h',
433 directory = directory,
Jon Leechdb1a98c2020-06-01 04:52:39 -0700434 genpath = None,
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600435 apiname = 'vulkan',
436 profile = None,
437 versions = 'VK_VERSION_1_0',
438 emitversions = 'VK_VERSION_1_0',
Jon Leechdb1a98c2020-06-01 04:52:39 -0700439 defaultExtensions = None,
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600440 addExtensions = None,
Jon Leechdb1a98c2020-06-01 04:52:39 -0700441 removeExtensions = None,
442 emitExtensions = None,
443 prefixText = prefixStrings + vkPrefixStrings,
444 genFuncPointers = True,
445 protectFile = protectFile,
446 protectFeature = False,
447 protectProto = '#ifndef',
448 protectProtoStr = 'VK_NO_PROTOTYPES',
449 apicall = 'VKAPI_ATTR ',
450 apientry = 'VKAPI_CALL ',
451 apientryp = 'VKAPI_PTR *',
Jon Leeche1d8c492021-03-29 01:18:51 -0700452 alignFuncParam = 48,
453 misracstyle = misracstyle,
454 misracppstyle = misracppstyle)
Jon Leechdb1a98c2020-06-01 04:52:39 -0700455 ]
456
457 # Unused - vulkan11.h target.
458 # It is possible to generate a header with just the Vulkan 1.0 +
459 # extension interfaces defined, but since the promoted KHR extensions
460 # are now defined in terms of the 1.1 interfaces, such a header is very
461 # similar to vulkan_core.h.
462 genOpts['vulkan11.h'] = [
463 COutputGenerator,
464 CGeneratorOptions(
465 conventions = conventions,
466 filename = 'vulkan11.h',
467 directory = directory,
468 genpath = None,
469 apiname = 'vulkan',
470 profile = None,
471 versions = '^VK_VERSION_1_[01]$',
472 emitversions = '^VK_VERSION_1_[01]$',
473 defaultExtensions = None,
474 addExtensions = None,
475 removeExtensions = None,
476 emitExtensions = None,
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600477 prefixText = prefixStrings + vkPrefixStrings,
478 genFuncPointers = True,
479 protectFile = protectFile,
480 protectFeature = False,
481 protectProto = '#ifndef',
482 protectProtoStr = 'VK_NO_PROTOTYPES',
483 apicall = 'VKAPI_ATTR ',
484 apientry = 'VKAPI_CALL ',
485 apientryp = 'VKAPI_PTR *',
Jon Leeche1d8c492021-03-29 01:18:51 -0700486 alignFuncParam = 48,
487 misracstyle = misracstyle,
488 misracppstyle = misracppstyle)
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600489 ]
490
491 genOpts['alias.h'] = [
492 COutputGenerator,
493 CGeneratorOptions(
Jon Leech71be0a42019-03-20 02:20:31 -0700494 conventions = conventions,
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600495 filename = 'alias.h',
496 directory = directory,
Jon Leechdb1a98c2020-06-01 04:52:39 -0700497 genpath = None,
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600498 apiname = 'vulkan',
499 profile = None,
500 versions = featuresPat,
501 emitversions = featuresPat,
502 defaultExtensions = defaultExtensions,
503 addExtensions = None,
504 removeExtensions = removeExtensionsPat,
505 emitExtensions = emitExtensionsPat,
506 prefixText = None,
507 genFuncPointers = False,
508 protectFile = False,
509 protectFeature = False,
510 protectProto = '',
511 protectProtoStr = '',
512 apicall = '',
513 apientry = '',
514 apientryp = '',
515 alignFuncParam = 36)
516 ]
517
Jon Leech42ad3f92019-09-08 21:57:00 -0700518
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600519def genTarget(args):
Jon Leech0c5351f2020-05-04 03:42:53 -0700520 """Create an API generator and corresponding generator options based on
521 the requested target and command line options.
Jon Leech42ad3f92019-09-08 21:57:00 -0700522
523 This is encapsulated in a function so it can be profiled and/or timed.
524 The args parameter is an parsed argument object containing the following
525 fields that are used:
526
527 - target - target to generate
528 - directory - directory to generate it in
529 - protect - True if re-inclusion wrappers should be created
530 - extensions - list of additional extensions to include in generated interfaces"""
Jon Leech0c5351f2020-05-04 03:42:53 -0700531
532 # Create generator options with parameters specified on command line
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600533 makeGenOpts(args)
534
Jon Leech87451c52020-11-01 22:37:12 -0800535 # pdb.set_trace()
536
Jon Leech0c5351f2020-05-04 03:42:53 -0700537 # Select a generator matching the requested target
Jon Leech171949d2019-04-16 05:57:09 -0700538 if args.target in genOpts:
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600539 createGenerator = genOpts[args.target][0]
540 options = genOpts[args.target][1]
541
Jon Leech0c5351f2020-05-04 03:42:53 -0700542 logDiag('* Building', options.filename)
543 logDiag('* options.versions =', options.versions)
544 logDiag('* options.emitversions =', options.emitversions)
545 logDiag('* options.defaultExtensions =', options.defaultExtensions)
546 logDiag('* options.addExtensions =', options.addExtensions)
547 logDiag('* options.removeExtensions =', options.removeExtensions)
548 logDiag('* options.emitExtensions =', options.emitExtensions)
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600549
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600550 gen = createGenerator(errFile=errWarn,
551 warnFile=errWarn,
552 diagFile=diag)
Jon Leech0c5351f2020-05-04 03:42:53 -0700553 return (gen, options)
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600554 else:
Jon Leech0c5351f2020-05-04 03:42:53 -0700555 logErr('No generator options for unknown target:', args.target)
556 return None
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600557
Jon Leech171949d2019-04-16 05:57:09 -0700558
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600559# -feature name
560# -extension name
561# For both, "name" may be a single name, or a space-separated list
562# of names, or a regular expression.
563if __name__ == '__main__':
564 parser = argparse.ArgumentParser()
565
566 parser.add_argument('-defaultExtensions', action='store',
567 default='vulkan',
568 help='Specify a single class of extensions to add to targets')
569 parser.add_argument('-extension', action='append',
570 default=[],
571 help='Specify an extension or extensions to add to targets')
572 parser.add_argument('-removeExtensions', action='append',
573 default=[],
574 help='Specify an extension or extensions to remove from targets')
575 parser.add_argument('-emitExtensions', action='append',
576 default=[],
577 help='Specify an extension or extensions to emit in targets')
Jon Leech87451c52020-11-01 22:37:12 -0800578 parser.add_argument('-emitSpirv', action='append',
579 default=[],
580 help='Specify a SPIR-V extension or capability to emit in targets')
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600581 parser.add_argument('-feature', action='append',
582 default=[],
583 help='Specify a core API feature name or names to add to targets')
584 parser.add_argument('-debug', action='store_true',
585 help='Enable debugging')
586 parser.add_argument('-dump', action='store_true',
587 help='Enable dump to stderr')
588 parser.add_argument('-diagfile', action='store',
589 default=None,
590 help='Write diagnostics to specified file')
591 parser.add_argument('-errfile', action='store',
592 default=None,
593 help='Write errors and warnings to specified file instead of stderr')
594 parser.add_argument('-noprotect', dest='protect', action='store_false',
595 help='Disable inclusion protection in output headers')
596 parser.add_argument('-profile', action='store_true',
597 help='Enable profiling')
598 parser.add_argument('-registry', action='store',
599 default='vk.xml',
600 help='Use specified registry file instead of vk.xml')
601 parser.add_argument('-time', action='store_true',
602 help='Enable timing')
603 parser.add_argument('-validate', action='store_true',
Jon Leech9e62d022021-08-29 15:03:29 -0700604 help='Validate the registry properties and exit')
Jon Leechdb1a98c2020-06-01 04:52:39 -0700605 parser.add_argument('-genpath', action='store', default='gen',
606 help='Path to generated files')
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600607 parser.add_argument('-o', action='store', dest='directory',
608 default='.',
609 help='Create target and related files in specified directory')
610 parser.add_argument('target', metavar='target', nargs='?',
611 help='Specify target')
612 parser.add_argument('-quiet', action='store_true', default=True,
613 help='Suppress script output during normal execution.')
614 parser.add_argument('-verbose', action='store_false', dest='quiet', default=True,
615 help='Enable script output during normal execution.')
Jon Leeche1d8c492021-03-29 01:18:51 -0700616 parser.add_argument('-misracstyle', dest='misracstyle', action='store_true',
617 help='generate MISRA C-friendly headers')
618 parser.add_argument('-misracppstyle', dest='misracppstyle', action='store_true',
619 help='generate MISRA C++-friendly headers')
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600620
621 args = parser.parse_args()
622
623 # This splits arguments which are space-separated lists
624 args.feature = [name for arg in args.feature for name in arg.split()]
625 args.extension = [name for arg in args.extension for name in arg.split()]
626
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600627 # create error/warning & diagnostic files
Jon Leech71be0a42019-03-20 02:20:31 -0700628 if args.errfile:
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600629 errWarn = open(args.errfile, 'w', encoding='utf-8')
630 else:
631 errWarn = sys.stderr
632
Jon Leech71be0a42019-03-20 02:20:31 -0700633 if args.diagfile:
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600634 diag = open(args.diagfile, 'w', encoding='utf-8')
635 else:
636 diag = None
637
Jon Leech9e62d022021-08-29 15:03:29 -0700638 (gen, options) = (None, None)
639 if not args.validate:
640 # Create the API generator & generator options
641 (gen, options) = genTarget(args)
Jon Leech0c5351f2020-05-04 03:42:53 -0700642
643 # Create the registry object with the specified generator and generator
644 # options. The options are set before XML loading as they may affect it.
645 reg = Registry(gen, options)
646
647 # Parse the specified registry XML into an ElementTree object
648 startTimer(args.time)
649 tree = etree.parse(args.registry)
650 endTimer(args.time, '* Time to make ElementTree =')
651
652 # Load the XML tree into the registry object
653 startTimer(args.time)
654 reg.loadElementTree(tree)
655 endTimer(args.time, '* Time to parse ElementTree =')
656
657 if args.validate:
Jon Leech9e62d022021-08-29 15:03:29 -0700658 success = reg.validateRegistry()
659 sys.exit(0 if success else 1)
Jon Leech0c5351f2020-05-04 03:42:53 -0700660
661 if args.dump:
662 logDiag('* Dumping registry to regdump.txt')
663 reg.dumpReg(filehandle=open('regdump.txt', 'w', encoding='utf-8'))
664
665 # Finally, use the output generator to create the requested target
Jon Leech71be0a42019-03-20 02:20:31 -0700666 if args.debug:
Jon Leech0c5351f2020-05-04 03:42:53 -0700667 pdb.run('reg.apiGen()')
Mark Lobodzinski0a79de42018-05-04 09:33:39 -0600668 else:
Jon Leech0c5351f2020-05-04 03:42:53 -0700669 startTimer(args.time)
670 reg.apiGen()
671 endTimer(args.time, '* Time to generate ' + options.filename + ' =')
672
673 if not args.quiet:
674 logDiag('* Generated', options.filename)