• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# -*- coding: utf-8 -*-
2
3#-------------------------------------------------------------------------
4# Vulkan CTS
5# ----------
6#
7# Copyright (c) 2015 Google Inc.
8#
9# Licensed under the Apache License, Version 2.0 (the "License");
10# you may not use this file except in compliance with the License.
11# You may obtain a copy of the License at
12#
13#      http://www.apache.org/licenses/LICENSE-2.0
14#
15# Unless required by applicable law or agreed to in writing, software
16# distributed under the License is distributed on an "AS IS" BASIS,
17# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18# See the License for the specific language governing permissions and
19# limitations under the License.
20#
21#-------------------------------------------------------------------------
22
23import os
24import re
25import sys
26import copy
27from itertools import chain
28from collections import OrderedDict
29
30sys.path.append(os.path.join(os.path.dirname(__file__), "..", "..", "..", "scripts"))
31
32from build.common import DEQP_DIR
33from khr_util.format import indentLines, writeInlFile
34
35VULKAN_H_DIR	= os.path.join(os.path.dirname(__file__), "src")
36VULKAN_DIR		= os.path.join(os.path.dirname(__file__), "..", "framework", "vulkan")
37
38INL_HEADER = """\
39/* WARNING: This is auto-generated file. Do not modify, since changes will
40 * be lost! Modify the generating script instead.
41 */\
42"""
43
44DEFINITIONS			= [
45	("VK_MAX_PHYSICAL_DEVICE_NAME_SIZE",	"size_t"),
46	("VK_MAX_EXTENSION_NAME_SIZE",			"size_t"),
47	("VK_MAX_DRIVER_NAME_SIZE",				"size_t"),
48	("VK_MAX_DRIVER_INFO_SIZE",				"size_t"),
49	("VK_UUID_SIZE",						"size_t"),
50	("VK_LUID_SIZE",						"size_t"),
51	("VK_MAX_MEMORY_TYPES",					"size_t"),
52	("VK_MAX_MEMORY_HEAPS",					"size_t"),
53	("VK_MAX_DESCRIPTION_SIZE",				"size_t"),
54	("VK_MAX_DEVICE_GROUP_SIZE",			"size_t"),
55	("VK_ATTACHMENT_UNUSED",				"deUint32"),
56	("VK_SUBPASS_EXTERNAL",					"deUint32"),
57	("VK_QUEUE_FAMILY_IGNORED",				"deUint32"),
58	("VK_QUEUE_FAMILY_EXTERNAL",			"deUint32"),
59	("VK_REMAINING_MIP_LEVELS",				"deUint32"),
60	("VK_REMAINING_ARRAY_LAYERS",			"deUint32"),
61	("VK_WHOLE_SIZE",						"vk::VkDeviceSize"),
62	("VK_TRUE",								"vk::VkBool32"),
63	("VK_FALSE",							"vk::VkBool32"),
64]
65
66PLATFORM_TYPES		= [
67	# VK_KHR_xlib_surface
68	(["Display","*"],						["XlibDisplayPtr"],				"void*"),
69	(["Window"],							["XlibWindow"],					"deUintptr",),
70	(["VisualID"],							["XlibVisualID"],				"deUint32"),
71
72	# VK_KHR_xcb_surface
73	(["xcb_connection_t", "*"],				["XcbConnectionPtr"],			"void*"),
74	(["xcb_window_t"],						["XcbWindow"],					"deUintptr"),
75	(["xcb_visualid_t"],					["XcbVisualid"],				"deUint32"),
76
77	# VK_KHR_wayland_surface
78	(["struct", "wl_display","*"],			["WaylandDisplayPtr"],			"void*"),
79	(["struct", "wl_surface", "*"],			["WaylandSurfacePtr"],			"void*"),
80
81	# VK_KHR_mir_surface
82	(["MirConnection", "*"],				["MirConnectionPtr"],			"void*"),
83	(["MirSurface", "*"],					["MirSurfacePtr"],				"void*"),
84
85	# VK_KHR_android_surface
86	(["ANativeWindow", "*"],				["AndroidNativeWindowPtr"],		"void*"),
87
88	# VK_KHR_win32_surface
89	(["HINSTANCE"],							["Win32InstanceHandle"],		"void*"),
90	(["HWND"],								["Win32WindowHandle"],			"void*"),
91	(["HANDLE"],							["Win32Handle"],				"void*"),
92	(["const", "SECURITY_ATTRIBUTES", "*"],	["Win32SecurityAttributesPtr"],	"const void*"),
93	(["AHardwareBuffer", "*"],				["AndroidHardwareBufferPtr"],	"void*"),
94	(["HMONITOR"],							["Win32MonitorHandle"],			"void*"),
95	(["LPCWSTR"],							["Win32LPCWSTR"],				"const void*"),
96
97	# VK_EXT_acquire_xlib_display
98	(["RROutput"],							["RROutput"],					"void*"),
99
100	(["zx_handle_t"],						["zx_handle_t"],				"deInt32"),
101	(["GgpFrameToken"],						["GgpFrameToken"],				"deInt32"),
102	(["GgpStreamDescriptor"],				["GgpStreamDescriptor"],		"deInt32"),
103	(["CAMetalLayer"],						["CAMetalLayer"],				"void*"),
104]
105
106PLATFORM_TYPE_NAMESPACE	= "pt"
107
108TYPE_SUBSTITUTIONS		= [
109	("uint8_t",		"deUint8"),
110	("uint16_t",	"deUint16"),
111	("uint32_t",	"deUint32"),
112	("uint64_t",	"deUint64"),
113	("int8_t",		"deInt8"),
114	("int16_t",		"deInt16"),
115	("int32_t",		"deInt32"),
116	("int64_t",		"deInt64"),
117	("bool32_t",	"deUint32"),
118	("size_t",		"deUintptr"),
119
120	# Platform-specific
121	("DWORD",		"deUint32"),
122	("HANDLE*",		PLATFORM_TYPE_NAMESPACE + "::" + "Win32Handle*"),
123]
124
125EXTENSION_POSTFIXES				= ["KHR", "EXT", "NV", "NVX", "KHX", "NN", "MVK", "FUCHSIA", "GGP", "AMD"]
126EXTENSION_POSTFIXES_STANDARD	= ["KHR", "EXT"]
127
128def prefixName (prefix, name):
129	name = re.sub(r'([a-z0-9])([A-Z])', r'\1_\2', name[2:])
130	name = re.sub(r'([a-zA-Z])([0-9])', r'\1_\2', name)
131	name = name.upper()
132
133	name = name.replace("YCB_CR_", "YCBCR_")
134	name = name.replace("WIN_32_", "WIN32_")
135	name = name.replace("8_BIT_", "8BIT_")
136	name = name.replace("16_BIT_", "16BIT_")
137	name = name.replace("INT_64_", "INT64_")
138	name = name.replace("D_3_D_12_", "D3D12_")
139	name = name.replace("IOSSURFACE_", "IOS_SURFACE_")
140	name = name.replace("MAC_OS", "MACOS_")
141	name = name.replace("TEXTURE_LOD", "TEXTURE_LOD_")
142	name = name.replace("VIEWPORT_W", "VIEWPORT_W_")
143	name = name.replace("_IDPROPERTIES", "_ID_PROPERTIES")
144	name = name.replace("PHYSICAL_DEVICE_SHADER_FLOAT_16_INT_8_FEATURES", "PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES")
145	name = name.replace("_PCIBUS_", "_PCI_BUS_")
146	name = name.replace("ASTCD", "ASTC_D")
147	name = name.replace("AABBNV", "AABB_NV")
148	name = name.replace("IMAGE_PIPE", "IMAGEPIPE")
149	name = name.replace("SMBUILTINS", "SM_BUILTINS")
150	name = name.replace("ASTCHDRFEATURES", "ASTC_HDR_FEATURES")
151	name = name.replace("UINT_8", "UINT8")
152	name = name.replace("VULKAN_11_FEATURES", "VULKAN_1_1_FEATURES")
153	name = name.replace("VULKAN_11_PROPERTIES", "VULKAN_1_1_PROPERTIES")
154	name = name.replace("VULKAN_12_FEATURES", "VULKAN_1_2_FEATURES")
155	name = name.replace("VULKAN_12_PROPERTIES", "VULKAN_1_2_PROPERTIES")
156	name = name.replace("INT_8_", "INT8_")
157	name = name.replace("AABBNV", "AABB_NV")
158	name = name.replace("_H_264_", "_H264_")
159	name = name.replace("_H_265_", "_H265_")
160
161	return prefix + name
162
163class Version:
164	def __init__ (self, versionTuple):
165		self.major = versionTuple[0]
166		self.minor = versionTuple[1]
167		self.patch = versionTuple[2]
168
169	def getInHex (self):
170		if self.patch == 0:
171			return "VK_API_VERSION_%d_%d" % (self.major, self.minor)
172		return '0x%Xu' % (hash(self))
173
174	def isStandardVersion (self):
175		if self.patch != 0:
176			return False
177		if self.major != 1:
178			return False
179		return True
180
181	def getBestRepresentation (self):
182		if self.isStandardVersion():
183			return self.getInHex()
184		return self.getDefineName()
185
186	def getDefineName (self):
187		return 'VERSION_%d_%d_%d' % (self.major, self.minor, self.patch)
188
189	def __hash__ (self):
190		return (self.major << 22) | (self.minor << 12) | self.patch
191
192	def __eq__ (self, other):
193		return self.major == other.major and self.minor == other.minor and self.patch == other.patch
194
195	def __str__ (self):
196		return self.getBestRepresentation()
197
198
199class Handle:
200	TYPE_DISP		= 0
201	TYPE_NONDISP	= 1
202
203	def __init__ (self, type, name):
204		self.type		= type
205		self.name		= name
206		self.alias		= None
207		self.isAlias	= False
208
209	def getHandleType (self):
210		return prefixName("HANDLE_TYPE_", self.name)
211
212	def checkAliasValidity (self):
213		pass
214
215	def __repr__ (self):
216		return '%s (%s, %s)' % (self.name, self.alias, self.isAlias)
217
218class Definition:
219	def __init__ (self, type, name, value):
220		self.type	= type
221		self.name	= name
222		self.value	= value
223		self.alias	= None
224		self.isAlias	= False
225
226	def __repr__ (self):
227		return '%s = %s (%s)' % (self.name, self.value, self.type)
228
229class Enum:
230	def __init__ (self, name, values):
231		self.name		= name
232		self.values		= values
233		self.alias		= None
234		self.isAlias	= False
235
236	def checkAliasValidity (self):
237		if self.alias != None:
238			if len(self.values) != len(self.alias.values):
239				raise Exception("%s has different number of flags than its alias %s." % (self.name, self.alias.name))
240			for index, value in enumerate(self.values):
241				aliasVal = self.alias.values[index]
242				if value[1] != aliasVal[1] or not (value[0].startswith(aliasVal[0]) or aliasVal[0].startswith(value[0])):
243					raise Exception("Flag %s of %s has different value than %s of %s." % (self.alias.values[index], self.alias.name, value, self.name))
244
245	def __repr__ (self):
246		return '%s (%s) %s' % (self.name, self.alias, self.values)
247
248class Bitfield:
249	def __init__ (self, name, values):
250		self.name		= name
251		self.values		= values
252		self.alias		= None
253		self.isAlias	= False
254
255	def checkAliasValidity (self):
256		if self.alias != None:
257			if len(self.values) != len(self.alias.values):
258				raise Exception("%s has different number of flags than its alias %s." % (self.name, self.alias.name))
259			for index, value in enumerate(self.values):
260				aliasVal = self.alias.values[index]
261				if value[1] != aliasVal[1] or not (value[0].startswith(aliasVal[0]) or aliasVal[0].startswith(value[0])):
262					raise Exception("Flag %s of %s has different value than %s of %s." % (self.alias.values[index], self.alias.name, value, self.name))
263
264	def __repr__ (self):
265		return '%s (%s)' % (self.name, self.alias)
266
267class Variable:
268	def __init__ (self, type, name, arraySizeOrFieldWidth):
269		type		= type.replace('*',' *').replace('&',' &')
270		for src, dst in TYPE_SUBSTITUTIONS:
271			type = type.replace(src, dst)
272		self.type	= type.split(' ')
273		for platformType, substitute, compat in PLATFORM_TYPES:
274			range = self.contains(self.type, platformType)
275			if range != None:
276				self.type = self.type[:range[0]]+[PLATFORM_TYPE_NAMESPACE + '::' + substitute[0]] + substitute[1:] + self.type[range[1]:]
277				break
278		self.name		= name
279		if len(arraySizeOrFieldWidth) > 0 and arraySizeOrFieldWidth[0] == ':':
280			self.arraySize	= ''
281			self.fieldWidth = arraySizeOrFieldWidth
282		else:
283			self.arraySize	= arraySizeOrFieldWidth
284			self.fieldWidth = ''
285
286	def contains(self, big, small):
287		for i in range(len(big)-len(small)+1):
288			for j in range(len(small)):
289				if big[i+j] != small[j]:
290					break
291			else:
292				return i, i+len(small)
293		return None
294
295	def getType (self):
296		return ' '.join(self.type).replace(' *','*').replace(' &','&')
297
298	def getAsString (self, separator):
299		return '%s%s%s%s%s' % (self.getType(), separator, self.name, self.arraySize, self.fieldWidth)
300
301	def getAsStringForArgumentList (self, separator):
302		return '%s%s%s%s' % (self.getType(), separator, self.name, self.arraySize)
303
304	def __repr__ (self):
305		return '<%s> <%s> <%s>' % (self.type, self.name, self.arraySize)
306
307	def __eq__ (self, other):
308		if len(self.type) != len(other.type):
309			return False
310		for index, type in enumerate(self.type):
311			if "*" == type or "&" == type or "const" == type or "volatile" == type:
312				if type != other.type[index]:
313					return False
314			elif type != other.type[index] and \
315				type not in map(lambda ext: other.type[index] + ext, EXTENSION_POSTFIXES_STANDARD) and \
316				other.type[index] not in map(lambda ext: type + ext, EXTENSION_POSTFIXES_STANDARD):
317				return False
318		return self.arraySize == other.arraySize
319
320	def __ne__ (self, other):
321		return not self == other
322
323class CompositeType:
324	CLASS_STRUCT	= 0
325	CLASS_UNION		= 1
326
327	def __init__ (self, typeClass, name, members, apiVersion = None):
328		self.typeClass	= typeClass
329		self.name		= name
330		self.members	= members
331		self.alias		= None
332		self.isAlias	= False
333		self.apiVersion	= apiVersion
334
335	def getClassName (self):
336		names = {CompositeType.CLASS_STRUCT: 'struct', CompositeType.CLASS_UNION: 'union'}
337		return names[self.typeClass]
338
339	def checkAliasValidity (self):
340		if self.alias != None:
341			if len(self.members) != len(self.alias.members):
342				raise Exception("%s has different number of members than its alias %s." % (self.name, self.alias.name))
343			for index, member in enumerate(self.members ):
344				break
345				#if member != self.alias.members[index]:
346					#raise Exception("Member %s of %s is different than core member %s in %s." % (self.alias.members[index], self.alias.name, member, self.name))
347					#raise Exception("Member ",str(self.alias.members[index])," of ", str(self.alias.name)," is different than core member ", str(member)," in ", str(self.name),".")
348	def __repr__ (self):
349		return '%s (%s)' % (self.name, self.alias)
350
351class Function:
352	TYPE_PLATFORM		= 0 # Not bound to anything
353	TYPE_INSTANCE		= 1 # Bound to VkInstance
354	TYPE_DEVICE			= 2 # Bound to VkDevice
355
356	def __init__ (self, name, returnType, arguments, apiVersion = None):
357		self.name		= name
358		self.returnType	= returnType
359		self.arguments	= arguments
360		self.alias		= None
361		self.isAlias	= False
362		self.apiVersion	= apiVersion
363
364	def getType (self):
365		# Special functions
366		if self.name == "vkGetInstanceProcAddr":
367			return Function.TYPE_PLATFORM
368		assert len(self.arguments) > 0
369		firstArgType = self.arguments[0].getType()
370		if firstArgType in ["VkInstance", "VkPhysicalDevice"]:
371			return Function.TYPE_INSTANCE
372		elif firstArgType in ["VkDevice", "VkCommandBuffer", "VkQueue"]:
373			return Function.TYPE_DEVICE
374		else:
375			return Function.TYPE_PLATFORM
376
377	def checkAliasValidity (self):
378		if self.alias != None:
379			if len(self.arguments) != len(self.alias.arguments):
380				raise Exception("%s has different number of arguments than its alias %s." % (self.name, self.alias.name))
381			if self.returnType != self.alias.returnType or not (self.returnType.startswith(self.alias.returnType) or self.alias.returnType.startswith(self.returnType)):
382				raise Exception("%s has different return value's type than its alias %s." % (self.name, self.alias.name))
383			for index, argument in enumerate(self.arguments):
384				if argument != self.alias.arguments[index]:
385					raise Exception("argument %s: \"%s\" of %s is different than \"%s\" of %s." % (index, self.alias.arguments[index].getAsString(' '), self.alias.name, argument.getAsString(' '), self.name))
386
387	def __repr__ (self):
388		return '%s (%s)' % (self.name, self.alias)
389
390class Extension:
391	def __init__ (self, name, handles, enums, bitfields, compositeTypes, functions, definitions, additionalDefinitions, typedefs, versionInCore):
392		self.name			= name
393		self.definitions	= definitions
394		self.additionalDefs = additionalDefinitions
395		self.handles		= handles
396		self.enums			= enums
397		self.bitfields		= bitfields
398		self.compositeTypes	= compositeTypes
399		self.functions		= functions
400		self.typedefs		= typedefs
401		self.versionInCore	= versionInCore
402
403	def __repr__ (self):
404		return 'EXT:\n%s ->\nENUMS:\n%s\nCOMPOS:\n%s\nFUNCS:\n%s\nBITF:\n%s\nHAND:\n%s\nDEFS:\n%s\n' % (self.name, self.enums, self.compositeTypes, self.functions, self.bitfields, self.handles, self.definitions, self.versionInCore)
405
406class API:
407	def __init__ (self, versions, definitions, handles, enums, bitfields, bitfields64, compositeTypes, functions, extensions):
408		self.versions		= versions
409		self.definitions	= definitions
410		self.handles		= handles
411		self.enums			= enums
412		self.bitfields		= bitfields
413		self.bitfields64	= bitfields64
414		self.compositeTypes	= compositeTypes
415		self.functions		= functions # \note contains extension functions as well
416		self.extensions		= extensions
417
418def readFile (filename):
419	with open(filename, 'rt') as f:
420		return f.read()
421
422IDENT_PTRN	= r'[a-zA-Z_][a-zA-Z0-9_]*'
423WIDTH_PTRN	= r'[:0-9]*'
424TYPE_PTRN	= r'[a-zA-Z_][a-zA-Z0-9_ \t*&]*'
425
426def getInterfaceName (function):
427	assert function.name[:2] == "vk"
428	return function.name[2].lower() + function.name[3:]
429
430def getFunctionTypeName (function):
431	assert function.name[:2] == "vk"
432	return function.name[2:] + "Func"
433
434def endsWith (str, postfix):
435	return str[-len(postfix):] == postfix
436
437def splitNameExtPostfix (name):
438	knownExtPostfixes = EXTENSION_POSTFIXES
439	for postfix in knownExtPostfixes:
440		if endsWith(name, postfix):
441			return (name[:-len(postfix)], postfix)
442	return (name, "")
443
444def getBitEnumNameForBitfield (bitfieldName):
445	bitfieldName, postfix = splitNameExtPostfix(bitfieldName)
446	assert bitfieldName[-1] == "s"
447	return bitfieldName[:-1] + "Bits" + postfix
448
449def getBitfieldNameForBitEnum (bitEnumName):
450	bitEnumName, postfix = splitNameExtPostfix(bitEnumName)
451	assert bitEnumName[-4:] == "Bits"
452	return bitEnumName[:-4] + "s" + postfix
453
454def parsePreprocDefinedValue (src, name):
455	value = parsePreprocDefinedValueOptional(src, name)
456	if value is None:
457		raise Exception("No such definition: %s" % name)
458	return value
459
460def parsePreprocDefinedValueOptional (src, name):
461	definition = re.search(r'#\s*define\s+' + name + r'\s+([^\n]+)\n', src)
462	if definition is None:
463		return None
464	value = definition.group(1).strip()
465	if value == "UINT32_MAX":
466		value = "(~0u)"
467	return value
468
469def parseEnum (name, src):
470	keyValuePtrn = '(' + IDENT_PTRN + r')\s*=\s*([^\s,\n}]+)\s*[,\n}]'
471	return Enum(name, re.findall(keyValuePtrn, src))
472
473# \note Parses raw enums, some are mapped to bitfields later
474def parseEnums (src):
475	matches	= re.findall(r'typedef enum(\s*' + IDENT_PTRN + r')?\s*{([^}]*)}\s*(' + IDENT_PTRN + r')\s*;', src)
476	enums	= []
477	for enumname, contents, typename in matches:
478		enums.append(parseEnum(typename, contents))
479	return enums
480
481def parseCompositeType (type, name, src):
482	typeNamePtrn	= r'(' + TYPE_PTRN + r')(\s+' + IDENT_PTRN + r')((\[[^\]]+\]|\s*:\s*[0-9]+)*)\s*;'
483	matches			= re.findall(typeNamePtrn, src)
484	members			= [Variable(t.strip(), n.strip(), a.replace(' ', '')) for t, n, a, _ in matches]
485	return CompositeType(type, name, members)
486
487def parseCompositeTypes (src):
488	typeMap	= { 'struct': CompositeType.CLASS_STRUCT, 'union': CompositeType.CLASS_UNION }
489	matches	= re.findall(r'typedef (struct|union)(\s*' + IDENT_PTRN + r')?\s*{([^}]*)}\s*(' + IDENT_PTRN + r')\s*;', src)
490	types	= []
491	for type, structname, contents, typename in matches:
492		types.append(parseCompositeType(typeMap[type], typename, contents))
493	return types
494
495def parseCompositeTypesByVersion (src, versionsData):
496
497	# find occurence of extension is a place where
498	# we cant assign apiVersion to found structures
499	extPtrn		= r'#define\s+[A-Z0-9_]+_EXTENSION_NAME\s+"([^"]+)"'
500	versionEnd	= re.search(extPtrn, src)
501	versions	= [Version((v[2], v[3], 0)) for v in versionsData]
502	versions.append(None)
503
504	# construct list of locations where version definitions start, and add the end of the file to it
505	sectionLocations = [versionDef[1] for versionDef in versionsData]
506	sectionLocations.append(versionEnd.start())
507	sectionLocations.append(len(src))
508
509	# construct function declaration pattern
510	ptrn		= r'typedef (struct|union)(\s*' + IDENT_PTRN + r')?\s*{([^}]*)}\s*(' + IDENT_PTRN + r')\s*;'
511	regPtrn		= re.compile(ptrn)
512	types		= []
513	typeMap		= { 'struct': CompositeType.CLASS_STRUCT, 'union': CompositeType.CLASS_UNION }
514
515	# iterate over all versions and find all structure definitions
516	for index, v in enumerate(versions):
517		matches = regPtrn.findall(src, sectionLocations[index], sectionLocations[index+1])
518		for type, structname, contents, typename in matches:
519			compositeType = parseCompositeType(typeMap[type], typename, contents)
520			compositeType.apiVersion = v
521			types.append(compositeType)
522	return types
523
524def parseVersions (src):
525	# returns list of tuples each with four items:
526	# 1. string with version token (without ' 1' at the end)
527	# 2. starting point off version specific definitions in vulkan.h.in
528	# 3. major version number
529	# 4. minor version number
530	return [(m.group()[:-2], m.start(), int(m.group(1)), int(m.group(2))) for m in re.finditer('VK_VERSION_([1-9])_([0-9]) 1', src)]
531
532def parseHandles (src):
533	matches	= re.findall(r'VK_DEFINE(_NON_DISPATCHABLE|)_HANDLE\((' + IDENT_PTRN + r')\)[ \t]*[\n\r]', src)
534	handles	= []
535	typeMap	= {'': Handle.TYPE_DISP, '_NON_DISPATCHABLE': Handle.TYPE_NONDISP}
536	for type, name in matches:
537		handle = Handle(typeMap[type], name)
538		handles.append(handle)
539	return handles
540
541def parseArgList (src):
542	typeNamePtrn	= r'(' + TYPE_PTRN + r')(\s+' + IDENT_PTRN + r')((\[[^\]]+\])*)\s*'
543	args			= []
544	for rawArg in src.split(','):
545		m = re.search(typeNamePtrn, rawArg)
546		args.append(Variable(m.group(1).strip(), m.group(2).strip(), m.group(3)))
547	return args
548
549def removeTypeExtPostfix (name):
550	for extPostfix in EXTENSION_POSTFIXES_STANDARD:
551		if endsWith(name, extPostfix):
552			return name[0:-len(extPostfix)]
553	return None
554
555def populateExtensionAliases(allObjects, extensionObjects):
556	for object in extensionObjects:
557		withoutPostfix = removeTypeExtPostfix(object.name)
558		if withoutPostfix != None and withoutPostfix in allObjects:
559			# max 1 alias is assumed by functions in this file
560			assert allObjects[withoutPostfix].alias == None
561			allObjects[withoutPostfix].alias = object
562			object.isAlias = True
563	for object in extensionObjects:
564		object.checkAliasValidity()
565
566def populateAliasesWithTypedefs (objects, src):
567	objectsByName = {}
568	for object in objects:
569		objectsByName[object.name] = object
570		ptrn	= r'\s*typedef\s+' + object.name + r'\s+([^;]+)'
571		stash = re.findall(ptrn, src)
572		if len(stash) == 1:
573			objExt = copy.deepcopy(object)
574			objExt.name = stash[0]
575			object.alias = objExt
576			objExt.isAlias = True
577			objects.append(objExt)
578
579def removeAliasedValues (enum):
580	valueByName = {}
581	for name, value in enum.values:
582		valueByName[name] = value
583
584	def removeDefExtPostfix (name):
585		for extPostfix in EXTENSION_POSTFIXES:
586			if endsWith(name, "_" + extPostfix):
587				return name[0:-(len(extPostfix)+1)]
588		return None
589
590	newValues = []
591	for name, value in enum.values:
592		withoutPostfix = removeDefExtPostfix(name)
593		if withoutPostfix != None and withoutPostfix in valueByName and valueByName[withoutPostfix] == value:
594			continue
595		newValues.append((name, value))
596	enum.values = newValues
597
598def parseFunctions (src):
599	ptrn		= r'VKAPI_ATTR\s+(' + TYPE_PTRN + ')\s+VKAPI_CALL\s+(' + IDENT_PTRN + r')\s*\(([^)]*)\)\s*;'
600	matches		= re.findall(ptrn, src)
601	functions	= []
602	for returnType, name, argList in matches:
603		functions.append(Function(name.strip(), returnType.strip(), parseArgList(argList)))
604	return functions
605
606def parseFunctionsByVersion (src, versions):
607	# construct list of locations where version definitions start, and add the end of the file to it
608	sectionLocations = [versionDef[1] for versionDef in versions]
609	sectionLocations.append(len(src))
610
611	# construct function declaration pattern
612	ptrn		= r'VKAPI_ATTR\s+(' + TYPE_PTRN + ')\s+VKAPI_CALL\s+(' + IDENT_PTRN + r')\s*\(([^)]*)\)\s*;'
613	regPtrn		= re.compile(ptrn)
614	functions	= []
615
616	# iterate over all versions and find all function definitions
617	for index, v in enumerate(versions):
618		matches = regPtrn.findall(src, sectionLocations[index], sectionLocations[index+1])
619		for returnType, name, argList in matches:
620			functions.append(Function(name.strip(), returnType.strip(), parseArgList(argList), v[0]))
621	return functions
622
623def splitByExtension (src):
624	ptrn		= r'#define\s+[A-Z0-9_]+_EXTENSION_NAME\s+"([^"]+)"'
625	# Construct long pattern that will be used to split whole source by extensions
626	match		= "#define\s+("
627	for part in re.finditer(ptrn, src):
628		 match += part.group(1)+"|"
629	match = match[:-1] + ")\s+1"
630	parts = re.split(match, src)
631
632	# First part is core, following tuples contain extension name and all its definitions
633	byExtension	= [(None, parts[0])]
634	for ndx in range(1, len(parts), 2):
635		byExtension.append((parts[ndx], parts[ndx+1]))
636	return byExtension
637
638def parseDefinitions (extensionName, src):
639
640	def skipDefinition (extensionName, definition):
641		if extensionName == None:
642			return True
643		extNameUpper = extensionName.upper()
644		extNameUpper = extNameUpper.replace("VK_KHR_SYNCHRONIZATION2", "VK_KHR_SYNCHRONIZATION_2")
645		extNameUpper = extNameUpper.replace("VK_INTEL_SHADER_INTEGER_FUNCTIONS2", "VK_INTEL_SHADER_INTEGER_FUNCTIONS_2")
646		extNameUpper = extNameUpper.replace("VK_EXT_ROBUSTNESS2", "VK_EXT_ROBUSTNESS_2")
647		extNameUpper = extNameUpper.replace("VK_EXT_FRAGMENT_DENSITY_MAP2", "VK_EXT_FRAGMENT_DENSITY_MAP_2")
648		extNameUpper = extNameUpper.replace("VK_AMD_SHADER_CORE_PROPERTIES2", "VK_AMD_SHADER_CORE_PROPERTIES_2")
649		extNameUpper = extNameUpper.replace("VK_EXT_EXTENDED_DYNAMIC_STATE2", "VK_EXT_EXTENDED_DYNAMIC_STATE_2")
650		# SPEC_VERSION enums
651		if definition[0].startswith(extNameUpper) and definition[1].isdigit():
652			return False
653		if definition[0].startswith(extNameUpper):
654			return True
655		if definition[1].isdigit():
656			return True
657		return False
658
659	ptrn		= r'#define\s+([^\s]+)\s+([^\r\n]+)'
660	matches		= re.findall(ptrn, src)
661
662	return [Definition(None, match[0], match[1]) for match in matches if not skipDefinition(extensionName, match)]
663
664def parseTypedefs (src):
665
666	ptrn		= r'typedef\s+([^\s]+)\s+([^\r\n]+);'
667	matches		= re.findall(ptrn, src)
668
669	return [Definition(None, match[0], match[1]) for match in matches]
670
671def parseExtensions (src, versions, allFunctions, allCompositeTypes, allEnums, allBitfields, allHandles, allDefinitions):
672
673	def getCoreVersion (extensionName, extensionsData):
674		# returns None when extension was not added to core for any Vulkan version
675		# returns array containing DEVICE or INSTANCE string followed by the vulkan version in which this extension is core
676		# note that this function is also called for vulkan 1.0 source for which extName is None
677		if not extensionName:
678			return None
679		ptrn		= extensionName + r'\s+(DEVICE|INSTANCE)\s+([0-9_]+)'
680		coreVersion = re.search(ptrn, extensionsData, re.I)
681		if coreVersion != None:
682			return [coreVersion.group(1)] + [int(number) for number in coreVersion.group(2).split('_')[:3]]
683		return None
684
685	extensionsData			= readFile(os.path.join(VULKAN_H_DIR, "extensions_data.txt"))
686	splitSrc				= splitByExtension(src)
687	extensions				= []
688	functionsByName			= {function.name: function for function in allFunctions}
689	compositeTypesByName	= {compType.name: compType for compType in allCompositeTypes}
690	enumsByName				= {enum.name: enum for enum in allEnums}
691	bitfieldsByName			= {bitfield.name: bitfield for bitfield in allBitfields}
692	handlesByName			= {handle.name: handle for handle in allHandles}
693	definitionsByName		= {definition.name: definition for definition in allDefinitions}
694
695	for extensionName, extensionSrc in splitSrc:
696		definitions			= [Definition("deUint32", v.getInHex(), parsePreprocDefinedValueOptional(extensionSrc, v.getInHex())) for v in versions]
697		definitions.extend([Definition(type, name, parsePreprocDefinedValueOptional(extensionSrc, name)) for name, type in DEFINITIONS])
698		definitions			= [definition for definition in definitions if definition.value != None]
699		additionalDefinitions = parseDefinitions(extensionName, extensionSrc)
700		handles				= parseHandles(extensionSrc)
701		functions			= parseFunctions(extensionSrc)
702		compositeTypes		= parseCompositeTypes(extensionSrc)
703		rawEnums			= parseEnums(extensionSrc)
704		bitfieldNames		= parseBitfieldNames(extensionSrc)
705		typedefs			= parseTypedefs(extensionSrc)
706		enumBitfieldNames	= [getBitEnumNameForBitfield(name) for name in bitfieldNames]
707		enums				= [enum for enum in rawEnums if enum.name not in enumBitfieldNames]
708
709		extCoreVersion		= getCoreVersion(extensionName, extensionsData)
710		extFunctions		= [functionsByName[function.name] for function in functions]
711		extCompositeTypes	= [compositeTypesByName[compositeType.name] for compositeType in compositeTypes]
712		extEnums			= [enumsByName[enum.name] for enum in enums]
713		extBitfields		= [bitfieldsByName[bitfieldName] for bitfieldName in bitfieldNames]
714		extHandles			= [handlesByName[handle.name] for handle in handles]
715		extDefinitions		= [definitionsByName[definition.name] for definition in definitions]
716
717		if extCoreVersion != None:
718			populateExtensionAliases(functionsByName, extFunctions)
719			populateExtensionAliases(handlesByName, extHandles)
720			populateExtensionAliases(enumsByName, extEnums)
721			populateExtensionAliases(bitfieldsByName, extBitfields)
722			populateExtensionAliases(compositeTypesByName, extCompositeTypes)
723		extensions.append(Extension(extensionName, extHandles, extEnums, extBitfields, extCompositeTypes, extFunctions, extDefinitions, additionalDefinitions, typedefs, extCoreVersion))
724	return extensions
725
726def parseBitfieldNames (src):
727	ptrn		= r'typedef\s+VkFlags\s(' + IDENT_PTRN + r')\s*;'
728	matches		= re.findall(ptrn, src)
729
730	return matches
731
732def parse64bitBitfieldNames (src):
733	ptrn		= r'typedef\s+VkFlags64\s(' + IDENT_PTRN + r')\s*;'
734	matches		= re.findall(ptrn, src)
735
736	return matches
737
738def parse64bitBitfieldValues (src, bitfieldNamesList):
739
740	bitfields64 = []
741	for bitfieldName in bitfieldNamesList:
742		ptrn		= r'static const ' + bitfieldName + r'\s*(' + IDENT_PTRN + r')\s*=\s*([a-zA-Z0-9_]+)\s*;'
743		matches		= re.findall(ptrn, src)
744		bitfields64.append(Bitfield(bitfieldName, matches))
745
746	return bitfields64
747
748def parseAPI (src):
749	versionsData	= parseVersions(src)
750	versions		= [Version((v[2], v[3], 0)) for v in versionsData]
751	definitions		= [Definition("deUint32", v.getInHex(), parsePreprocDefinedValue(src, v.getInHex())) for v in versions] +\
752					  [Definition(type, name, parsePreprocDefinedValue(src, name)) for name, type in DEFINITIONS]
753
754	handles				= parseHandles(src)
755	rawEnums			= parseEnums(src)
756	bitfieldNames		= parseBitfieldNames(src)
757	bitfieldEnums		= set([getBitEnumNameForBitfield(n) for n in bitfieldNames if getBitEnumNameForBitfield(n) in [enum.name for enum in rawEnums]])
758	bitfield64Names		= parse64bitBitfieldNames(src)
759	bitfields64			= parse64bitBitfieldValues(src, bitfield64Names)
760	enums				= []
761	bitfields			= []
762	compositeTypes		= parseCompositeTypesByVersion(src, versionsData)
763	allFunctions		= parseFunctionsByVersion(src, versionsData)
764
765	for enum in rawEnums:
766		if enum.name in bitfieldEnums:
767			bitfields.append(Bitfield(getBitfieldNameForBitEnum(enum.name), enum.values))
768		else:
769			enums.append(enum)
770
771	for bitfieldName in bitfieldNames:
772		if not bitfieldName in [bitfield.name for bitfield in bitfields]:
773			# Add empty bitfield
774			bitfields.append(Bitfield(bitfieldName, []))
775
776	extensions = parseExtensions(src, versions, allFunctions, compositeTypes, enums, bitfields, handles, definitions)
777
778	# Populate alias fields
779	populateAliasesWithTypedefs(compositeTypes, src)
780	populateAliasesWithTypedefs(enums, src)
781	populateAliasesWithTypedefs(bitfields, src)
782	populateAliasesWithTypedefs(handles, src)
783
784	for enum in enums:
785		removeAliasedValues(enum)
786
787	# Make generator to create Deleter<VkAccelerationStructureNV>
788	for f in allFunctions:
789		if (f.name == 'vkDestroyAccelerationStructureNV'):
790			f.arguments[1].type[0] = 'VkAccelerationStructureNV'
791
792	# Dealias handles VkAccelerationStructureNV and VkAccelerationStructureKHR
793	for handle in handles:
794		if handle.name == 'VkAccelerationStructureKHR':
795			handle.alias = None
796		if handle.name == 'VkAccelerationStructureNV':
797			handle.isAlias = False
798	return API(
799		versions		= versions,
800		definitions		= definitions,
801		handles			= handles,
802		enums			= enums,
803		bitfields		= bitfields,
804		bitfields64		= bitfields64,
805		compositeTypes	= compositeTypes,
806		functions		= allFunctions,
807		extensions		= extensions)
808
809def splitUniqueAndDuplicatedEntries (handles):
810	listOfUniqueHandles = []
811	duplicates			= OrderedDict()
812	for handle in handles:
813		if handle.alias != None:
814			duplicates[handle.alias] = handle
815		if not handle.isAlias:
816			listOfUniqueHandles.append(handle)
817	return listOfUniqueHandles, duplicates
818
819def writeHandleType (api, filename):
820	uniqeHandles, duplicatedHandles = splitUniqueAndDuplicatedEntries(api.handles)
821
822	def genHandles ():
823		yield "\t%s\t= 0," % uniqeHandles[0].getHandleType()
824		for handle in uniqeHandles[1:]:
825			yield "\t%s," % handle.getHandleType()
826		for duplicate in duplicatedHandles:
827			yield "\t%s\t= %s," % (duplicate.getHandleType(), duplicatedHandles[duplicate].getHandleType())
828		yield "\tHANDLE_TYPE_LAST\t= %s + 1" % (uniqeHandles[-1].getHandleType())
829
830	def genHandlesBlock ():
831		yield "enum HandleType"
832		yield "{"
833
834		for line in indentLines(genHandles()):
835			yield line
836
837		yield "};"
838		yield ""
839
840	writeInlFile(filename, INL_HEADER, genHandlesBlock())
841
842def getEnumValuePrefix (enum):
843	prefix = enum.name[0]
844	for i in range(1, len(enum.name)):
845		if enum.name[i].isupper() and not enum.name[i-1].isupper():
846			prefix += "_"
847		prefix += enum.name[i].upper()
848	return prefix
849
850def parseInt (value):
851	if value[:2] == "0x":
852		return int(value, 16)
853	else:
854		return int(value, 10)
855
856def areEnumValuesLinear (enum):
857	curIndex = 0
858	for name, value in enum.values:
859		if value[:2] != "VK":
860			intValue = parseInt(value)
861			if intValue != curIndex:
862				# consider enums containing *_MAX_ENUM = 0x7FFFFFFF as linear
863				if intValue == 0x7FFFFFFF:
864					return True
865				return False
866			curIndex += 1
867	return True
868
869def genEnumSrc (enum):
870	yield "enum %s" % enum.name
871	yield "{"
872
873	lines = ["\t%s\t= %s," % v for v in enum.values]
874	if areEnumValuesLinear(enum):
875		lastItem = "\t%s_LAST," % getEnumValuePrefix(enum)
876		if parseInt(enum.values[-1][1]) == 0x7FFFFFFF:
877			# if last enum item is *_MAX_ENUM then we need to make sure
878			# it stays last entry also if we append *_LAST to generated
879			# source (without this value of *_LAST won't be correct)
880			lines.insert(-1, lastItem)
881		else:
882			lines.append(lastItem)
883
884	for line in indentLines(lines):
885		yield line
886
887	yield "};"
888
889def genBitfieldSrc (bitfield):
890	if len(bitfield.values) > 0:
891		yield "enum %s" % getBitEnumNameForBitfield(bitfield.name)
892		yield "{"
893		for line in indentLines(["\t%s\t= %s," % v for v in bitfield.values]):
894			yield line
895		yield "};"
896	yield "typedef deUint32 %s;" % bitfield.name
897
898def genBitfield64Src (bitfield64):
899	yield "typedef deUint64 %s;" % bitfield64.name
900	if len(bitfield64.values) > 0:
901		ptrn = "static const " + bitfield64.name + " %s\t= %s;"
902		for line in indentLines([ptrn % v for v in bitfield64.values]):
903			yield line
904		yield ""
905
906def genCompositeTypeSrc (type):
907	yield "%s %s" % (type.getClassName(), type.name)
908	yield "{"
909	for line in indentLines(['\t'+m.getAsString('\t')+';' for m in type.members]):
910		yield line
911	yield "};"
912
913def genHandlesSrc (handles):
914	uniqeHandles, duplicatedHandles = splitUniqueAndDuplicatedEntries(handles)
915
916	def genLines (handles):
917		for handle in uniqeHandles:
918			if handle.type == Handle.TYPE_DISP:
919				yield "VK_DEFINE_HANDLE\t(%s,\t%s);" % (handle.name, handle.getHandleType())
920			elif handle.type == Handle.TYPE_NONDISP:
921				yield "VK_DEFINE_NON_DISPATCHABLE_HANDLE\t(%s,\t%s);" % (handle.name, handle.getHandleType())
922
923		for duplicate in duplicatedHandles:
924			if duplicate.type == Handle.TYPE_DISP:
925				yield "VK_DEFINE_HANDLE\t(%s,\t%s);" % (duplicate.name, duplicatedHandles[duplicate].getHandleType())
926			elif duplicate.type == Handle.TYPE_NONDISP:
927				yield "VK_DEFINE_NON_DISPATCHABLE_HANDLE\t(%s,\t%s);" % (duplicate.name, duplicatedHandles[duplicate].getHandleType())
928
929	for line in indentLines(genLines(handles)):
930		yield line
931
932def stripTrailingComment(str):
933	index = str.find("//")
934	if index == -1:
935		return str
936	return str[:index]
937
938def genDefinitionsSrc (definitions):
939	for line in ["#define %s\t(static_cast<%s>\t(%s))" % (definition.name, definition.type, stripTrailingComment(definition.value)) for definition in definitions]:
940		yield line
941
942def genDefinitionsAliasSrc (definitions):
943	for line in ["#define %s\t%s" % (definition.name, definitions[definition].name) for definition in definitions]:
944		if definition.value != definitions[definition].value and definition.value != definitions[definition].name:
945			raise Exception("Value of %s (%s) is different than core definition value %s (%s)." % (definition.name, definition.value, definitions[definition].name, definitions[definition].value))
946		yield line
947
948def genMaxFrameworkVersion (definitions):
949	maxApiVersionMajor = 1
950	maxApiVersionMinor = 0
951	for definition in definitions:
952		match = re.match("VK_API_VERSION_(\d+)_(\d+)", definition.name)
953		if match:
954			apiVersionMajor = int(match.group(1))
955			apiVersionMinor = int(match.group(2))
956			if apiVersionMajor > maxApiVersionMajor:
957				maxApiVersionMajor = apiVersionMajor
958				maxApiVersionMinor = apiVersionMinor
959			elif apiVersionMajor == maxApiVersionMajor and apiVersionMinor > maxApiVersionMinor:
960				maxApiVersionMinor = apiVersionMinor
961	yield "#define VK_API_MAX_FRAMEWORK_VERSION\tVK_API_VERSION_%d_%d" % (maxApiVersionMajor, maxApiVersionMinor)
962
963def writeBasicTypes (api, filename):
964
965	def gen ():
966		definitionsCore, definitionDuplicates = splitUniqueAndDuplicatedEntries(api.definitions)
967
968		for line in indentLines(chain(genDefinitionsSrc(definitionsCore), genMaxFrameworkVersion(definitionsCore), genDefinitionsAliasSrc(definitionDuplicates))):
969			yield line
970		yield ""
971
972		for line in genHandlesSrc(api.handles):
973			yield line
974		yield ""
975
976		for enum in api.enums:
977			if not enum.isAlias:
978				for line in genEnumSrc(enum):
979					yield line
980			else:
981				for enum2 in api.enums:
982					if enum2.alias == enum:
983						yield "typedef %s %s;" % (enum2.name, enum.name)
984			yield ""
985
986		for bitfield in api.bitfields:
987			if not bitfield.isAlias:
988				for line in genBitfieldSrc(bitfield):
989					yield line
990			else:
991				for bitfield2 in api.bitfields:
992					if bitfield2.alias == bitfield:
993						yield "typedef %s %s;" % (bitfield2.name, bitfield.name)
994			yield ""
995
996		for bitfield64 in api.bitfields64:
997			for line in genBitfield64Src(bitfield64):
998				yield line
999
1000		for line in indentLines(["VK_DEFINE_PLATFORM_TYPE(%s,\t%s);" % (s[0], c) for n, s, c in PLATFORM_TYPES]):
1001			yield line
1002
1003		for ext in api.extensions:
1004			if ext.additionalDefs != None:
1005				for definition in ext.additionalDefs:
1006					yield "#define " + definition.name + " " + definition.value
1007
1008	writeInlFile(filename, INL_HEADER, gen())
1009
1010def writeCompositeTypes (api, filename):
1011	def gen ():
1012		for type in api.compositeTypes:
1013			type.checkAliasValidity()
1014
1015			if not type.isAlias:
1016				for line in genCompositeTypeSrc(type):
1017					yield line
1018			else:
1019				for type2 in api.compositeTypes:
1020					if type2.alias == type:
1021						yield "typedef %s %s;" % (type2.name, type.name)
1022			yield ""
1023
1024	writeInlFile(filename, INL_HEADER, gen())
1025
1026def argListToStr (args):
1027	return ", ".join(v.getAsStringForArgumentList(' ') for v in args)
1028
1029def writeInterfaceDecl (api, filename, functionTypes, concrete):
1030	def genProtos ():
1031		postfix = "" if concrete else " = 0"
1032		for function in api.functions:
1033			if not function.getType() in functionTypes:
1034				continue
1035			if not function.isAlias:
1036				yield "virtual %s\t%s\t(%s) const%s;" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments), postfix)
1037
1038	writeInlFile(filename, INL_HEADER, indentLines(genProtos()))
1039
1040def writeFunctionPtrTypes (api, filename):
1041	def genTypes ():
1042		for function in api.functions:
1043			yield "typedef VKAPI_ATTR %s\t(VKAPI_CALL* %s)\t(%s);" % (function.returnType, getFunctionTypeName(function), argListToStr(function.arguments))
1044
1045	writeInlFile(filename, INL_HEADER, indentLines(genTypes()))
1046
1047def writeFunctionPointers (api, filename, functionTypes):
1048	def FunctionsYielder ():
1049		for function in api.functions:
1050			if function.getType() in functionTypes:
1051				if function.isAlias:
1052					if function.getType() == Function.TYPE_INSTANCE and function.arguments[0].getType() == "VkPhysicalDevice":
1053						yield "%s\t%s;" % (getFunctionTypeName(function), getInterfaceName(function))
1054				else:
1055					yield "%s\t%s;" % (getFunctionTypeName(function), getInterfaceName(function))
1056
1057	writeInlFile(filename, INL_HEADER, indentLines(FunctionsYielder()))
1058
1059def writeInitFunctionPointers (api, filename, functionTypes, cond = None):
1060	def makeInitFunctionPointers ():
1061		for function in api.functions:
1062			if function.getType() in functionTypes and (cond == None or cond(function)):
1063				interfaceName = getInterfaceName(function)
1064				if function.isAlias:
1065					if function.getType() == Function.TYPE_INSTANCE and function.arguments[0].getType() == "VkPhysicalDevice":
1066						yield "m_vk.%s\t= (%s)\tGET_PROC_ADDR(\"%s\");" % (getInterfaceName(function), getFunctionTypeName(function), function.name)
1067				else:
1068					yield "m_vk.%s\t= (%s)\tGET_PROC_ADDR(\"%s\");" % (getInterfaceName(function), getFunctionTypeName(function), function.name)
1069					if function.alias != None:
1070						yield "if (!m_vk.%s)" % (getInterfaceName(function))
1071						yield "    m_vk.%s\t= (%s)\tGET_PROC_ADDR(\"%s\");" % (getInterfaceName(function), getFunctionTypeName(function), function.alias.name)
1072	lines = [line.replace('    ', '\t') for line in indentLines(makeInitFunctionPointers())]
1073	writeInlFile(filename, INL_HEADER, lines)
1074
1075def writeFuncPtrInterfaceImpl (api, filename, functionTypes, className):
1076	def makeFuncPtrInterfaceImpl ():
1077		for function in api.functions:
1078			if function.getType() in functionTypes and not function.isAlias:
1079				yield ""
1080				yield "%s %s::%s (%s) const" % (function.returnType, className, getInterfaceName(function), argListToStr(function.arguments))
1081				yield "{"
1082				if function.name == "vkEnumerateInstanceVersion":
1083					yield "	if (m_vk.enumerateInstanceVersion)"
1084					yield "		return m_vk.enumerateInstanceVersion(pApiVersion);"
1085					yield ""
1086					yield "	*pApiVersion = VK_API_VERSION_1_0;"
1087					yield "	return VK_SUCCESS;"
1088				elif function.getType() == Function.TYPE_INSTANCE and function.arguments[0].getType() == "VkPhysicalDevice" and function.alias != None:
1089					yield "	vk::VkPhysicalDeviceProperties props;"
1090					yield "	m_vk.getPhysicalDeviceProperties(physicalDevice, &props);"
1091					yield "	if (props.apiVersion >= VK_API_VERSION_1_1)"
1092					yield "		%sm_vk.%s(%s);" % ("return " if function.returnType != "void" else "", getInterfaceName(function), ", ".join(a.name for a in function.arguments))
1093					yield "	else"
1094					yield "		%sm_vk.%s(%s);" % ("return " if function.returnType != "void" else "", getInterfaceName(function.alias), ", ".join(a.name for a in function.arguments))
1095				else:
1096					yield "	%sm_vk.%s(%s);" % ("return " if function.returnType != "void" else "", getInterfaceName(function), ", ".join(a.name for a in function.arguments))
1097				yield "}"
1098
1099	writeInlFile(filename, INL_HEADER, makeFuncPtrInterfaceImpl())
1100
1101def writeStrUtilProto (api, filename):
1102	def makeStrUtilProto ():
1103		for line in indentLines(["const char*\tget%sName\t(%s value);" % (enum.name[2:], enum.name) for enum in api.enums if not enum.isAlias]):
1104			yield line
1105		yield ""
1106		for line in indentLines(["inline tcu::Format::Enum<%s>\tget%sStr\t(%s value)\t{ return tcu::Format::Enum<%s>(get%sName, value);\t}" % (e.name, e.name[2:], e.name, e.name, e.name[2:]) for e in api.enums if not e.isAlias]):
1107			yield line
1108		yield ""
1109		for line in indentLines(["inline std::ostream&\toperator<<\t(std::ostream& s, %s value)\t{ return s << get%sStr(value);\t}" % (e.name, e.name[2:]) for e in api.enums if not e.isAlias]):
1110			yield line
1111		yield ""
1112		for line in indentLines(["tcu::Format::Bitfield<32>\tget%sStr\t(%s value);" % (bitfield.name[2:], bitfield.name) for bitfield in api.bitfields if not bitfield.isAlias or bitfield.name=='VkBuildAccelerationStructureFlagsNV']):
1113			yield line
1114		yield ""
1115		for line in indentLines(["std::ostream&\toperator<<\t(std::ostream& s, const %s& value);" % (s.name) for s in api.compositeTypes if not s.isAlias]):
1116			yield line
1117
1118	writeInlFile(filename, INL_HEADER, makeStrUtilProto())
1119
1120def writeStrUtilImpl (api, filename):
1121	def makeStrUtilImpl ():
1122		for line in indentLines(["template<> const char*\tgetTypeName<%s>\t(void) { return \"%s\";\t}" % (handle.name, handle.name) for handle in api.handles if not handle.isAlias]):
1123			yield line
1124
1125		yield ""
1126		yield "namespace %s" % PLATFORM_TYPE_NAMESPACE
1127		yield "{"
1128
1129		for line in indentLines("std::ostream& operator<< (std::ostream& s, %s\tv) { return s << tcu::toHex(v.internal); }" % ''.join(s) for n, s, c in PLATFORM_TYPES):
1130			yield line
1131
1132		yield "}"
1133
1134		for enum in api.enums:
1135			if enum.isAlias:
1136				continue
1137			yield ""
1138			yield "const char* get%sName (%s value)" % (enum.name[2:], enum.name)
1139			yield "{"
1140			yield "\tswitch (value)"
1141			yield "\t{"
1142			for line in indentLines(["\t\tcase %s:\treturn \"%s\";" % (n, n) for n, v in enum.values if v[:2] != "VK"] + ["\t\tdefault:\treturn DE_NULL;"]):
1143				yield line
1144			yield "\t}"
1145			yield "}"
1146
1147		for bitfield in api.bitfields:
1148			if bitfield.isAlias:
1149				if bitfield.name != 'VkBuildAccelerationStructureFlagsNV':
1150					continue
1151			yield ""
1152			yield "tcu::Format::Bitfield<32> get%sStr (%s value)" % (bitfield.name[2:], bitfield.name)
1153			yield "{"
1154
1155			if len(bitfield.values) > 0:
1156				yield "\tstatic const tcu::Format::BitDesc s_desc[] ="
1157				yield "\t{"
1158				for line in indentLines(["\t\ttcu::Format::BitDesc(%s,\t\"%s\")," % (n, n) for n, v in bitfield.values]):
1159					yield line
1160				yield "\t};"
1161				yield "\treturn tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));"
1162			else:
1163				yield "\treturn tcu::Format::Bitfield<32>(value, DE_NULL, DE_NULL);"
1164			yield "}"
1165
1166		bitfieldTypeNames = set([bitfield.name for bitfield in api.bitfields])
1167
1168		for type in api.compositeTypes:
1169			if not type.isAlias:
1170				yield ""
1171				yield "std::ostream& operator<< (std::ostream& s, const %s& value)" % type.name
1172				yield "{"
1173				yield "\ts << \"%s = {\\n\";" % type.name
1174				for member in type.members:
1175					memberName	= member.name
1176					valFmt		= None
1177					newLine		= ""
1178					if member.getType() in bitfieldTypeNames:
1179						valFmt = "get%sStr(value.%s)" % (member.getType()[2:], member.name)
1180					elif member.getType() == "const char*" or member.getType() == "char*":
1181						valFmt = "getCharPtrStr(value.%s)" % member.name
1182					elif member.getType() == PLATFORM_TYPE_NAMESPACE + "::Win32LPCWSTR":
1183						valFmt = "getWStr(value.%s)" % member.name
1184					elif member.arraySize != '':
1185						singleDimensional = not '][' in member.arraySize
1186						if member.name in ["extensionName", "deviceName", "layerName", "description"]:
1187							valFmt = "(const char*)value.%s" % member.name
1188						elif singleDimensional and (member.getType() == 'char' or member.getType() == 'deUint8'):
1189							newLine = "'\\n' << "
1190							valFmt	= "tcu::formatArray(tcu::Format::HexIterator<%s>(DE_ARRAY_BEGIN(value.%s)), tcu::Format::HexIterator<%s>(DE_ARRAY_END(value.%s)))" % (member.getType(), member.name, member.getType(), member.name)
1191						else:
1192							if member.name == "memoryTypes" or member.name == "memoryHeaps":
1193								endIter = "DE_ARRAY_BEGIN(value.%s) + value.%sCount" % (member.name, member.name[:-1])
1194							else:
1195								endIter = "DE_ARRAY_END(value.%s)" % member.name
1196							newLine = "'\\n' << "
1197							valFmt	= "tcu::formatArray(DE_ARRAY_BEGIN(value.%s), %s)" % (member.name, endIter)
1198						memberName = member.name
1199					else:
1200						valFmt = "value.%s" % member.name
1201					yield ("\ts << \"\\t%s = \" << " % memberName) + newLine + valFmt + " << '\\n';"
1202				yield "\ts << '}';"
1203				yield "\treturn s;"
1204				yield "}"
1205	writeInlFile(filename, INL_HEADER, makeStrUtilImpl())
1206
1207
1208def writeObjTypeImpl (api, filename):
1209	def makeObjTypeImpl ():
1210
1211		yield "namespace vk"
1212		yield "{"
1213
1214		yield "template<typename T> VkObjectType getObjectType	(void);"
1215
1216		for line in indentLines(["template<> inline VkObjectType\tgetObjectType<%s>\t(void) { return %s;\t}" % (handle.name, prefixName("VK_OBJECT_TYPE_", handle.name)) for handle in api.handles if not handle.isAlias]):
1217			yield line
1218
1219		yield "}"
1220
1221	writeInlFile(filename, INL_HEADER, makeObjTypeImpl())
1222
1223class ConstructorFunction:
1224	def __init__ (self, type, name, objectType, ifaceArgs, arguments):
1225		self.type		= type
1226		self.name		= name
1227		self.objectType	= objectType
1228		self.ifaceArgs	= ifaceArgs
1229		self.arguments	= arguments
1230
1231def getConstructorFunctions (api):
1232	funcs = []
1233	ifacesDict = {
1234		Function.TYPE_PLATFORM: [Variable("const PlatformInterface&", "vk", "")],
1235		Function.TYPE_INSTANCE: [Variable("const InstanceInterface&", "vk", "")],
1236		Function.TYPE_DEVICE: [Variable("const DeviceInterface&", "vk", "")]
1237	}
1238	for function in api.functions:
1239		if function.isAlias:
1240			continue
1241		if (function.name[:8] == "vkCreate" or function.name == "vkAllocateMemory") and not "createInfoCount" in [a.name for a in function.arguments]:
1242			if function.name == "vkCreateDisplayModeKHR":
1243				continue # No way to delete display modes (bug?)
1244
1245			# \todo [pyry] Rather hacky
1246			ifaceArgs = ifacesDict[function.getType()]
1247			if function.name == "vkCreateDevice":
1248				ifaceArgs = [Variable("const PlatformInterface&", "vkp", ""), Variable("VkInstance", "instance", "")] + ifaceArgs
1249
1250			assert (function.arguments[-2].type == ["const", "VkAllocationCallbacks", "*"])
1251
1252			objectType	= function.arguments[-1].type[0] #not getType() but type[0] on purpose
1253			arguments	= function.arguments[:-1]
1254			funcs.append(ConstructorFunction(function.getType(), getInterfaceName(function), objectType, ifaceArgs, arguments))
1255	return funcs
1256
1257def addVersionDefines(versionSpectrum):
1258	output = ["#define " + ver.getDefineName() + " " + ver.getInHex() for ver in versionSpectrum if not ver.isStandardVersion()]
1259	return output
1260
1261def removeVersionDefines(versionSpectrum):
1262	output = ["#undef " + ver.getDefineName() for ver in versionSpectrum if not ver.isStandardVersion()]
1263	return output
1264
1265def writeRefUtilProto (api, filename):
1266	functions = getConstructorFunctions(api)
1267
1268	def makeRefUtilProto ():
1269		unindented = []
1270		for line in indentLines(["Move<%s>\t%s\t(%s = DE_NULL);" % (function.objectType, function.name, argListToStr(function.ifaceArgs + function.arguments)) for function in functions]):
1271			yield line
1272
1273	writeInlFile(filename, INL_HEADER, makeRefUtilProto())
1274
1275def writeRefUtilImpl (api, filename):
1276	functions = getConstructorFunctions(api)
1277
1278	def makeRefUtilImpl ():
1279		yield "namespace refdetails"
1280		yield "{"
1281		yield ""
1282
1283		for function in api.functions:
1284			if function.getType() == Function.TYPE_DEVICE \
1285			and (function.name[:9] == "vkDestroy" or function.name == "vkFreeMemory") \
1286			and not function.name == "vkDestroyDevice" \
1287			and not function.isAlias:
1288				objectType = function.arguments[-2].getType()
1289				yield "template<>"
1290				yield "void Deleter<%s>::operator() (%s obj) const" % (objectType, objectType)
1291				yield "{"
1292				yield "\tm_deviceIface->%s(m_device, obj, m_allocator);" % (getInterfaceName(function))
1293				yield "}"
1294				yield ""
1295
1296		yield "} // refdetails"
1297		yield ""
1298
1299		dtorDict = {
1300			Function.TYPE_PLATFORM: "object",
1301			Function.TYPE_INSTANCE: "instance",
1302			Function.TYPE_DEVICE: "device"
1303		}
1304
1305		for function in functions:
1306			deleterArgsString = ''
1307			if function.name == "createDevice":
1308				# createDevice requires two additional parameters to setup VkDevice deleter
1309				deleterArgsString = "vkp, instance, object, " +  function.arguments[-1].name
1310			else:
1311				deleterArgsString = "vk, %s, %s" % (dtorDict[function.type], function.arguments[-1].name)
1312
1313			yield "Move<%s> %s (%s)" % (function.objectType, function.name, argListToStr(function.ifaceArgs + function.arguments))
1314			yield "{"
1315			yield "\t%s object = 0;" % function.objectType
1316			yield "\tVK_CHECK(vk.%s(%s));" % (function.name, ", ".join([a.name for a in function.arguments] + ["&object"]))
1317			yield "\treturn Move<%s>(check<%s>(object), Deleter<%s>(%s));" % (function.objectType, function.objectType, function.objectType, deleterArgsString)
1318			yield "}"
1319			yield ""
1320
1321	writeInlFile(filename, INL_HEADER, makeRefUtilImpl())
1322
1323def writeStructTraitsImpl (api, filename):
1324	def gen ():
1325		for type in api.compositeTypes:
1326			if type.getClassName() == "struct" and type.members[0].name == "sType" and not type.isAlias and type.name != "VkBaseOutStructure" and type.name != "VkBaseInStructure":
1327				yield "template<> VkStructureType getStructureType<%s> (void)" % type.name
1328				yield "{"
1329				yield "\treturn %s;" % prefixName("VK_STRUCTURE_TYPE_", type.name)
1330				yield "}"
1331				yield ""
1332
1333	writeInlFile(filename, INL_HEADER, gen())
1334
1335def writeNullDriverImpl (api, filename):
1336	def genNullDriverImpl ():
1337		specialFuncNames	= [
1338				"vkCreateGraphicsPipelines",
1339				"vkCreateComputePipelines",
1340				"vkCreateRayTracingPipelinesNV",
1341				"vkCreateRayTracingPipelinesKHR",
1342				"vkGetInstanceProcAddr",
1343				"vkGetDeviceProcAddr",
1344				"vkEnumeratePhysicalDevices",
1345				"vkEnumerateInstanceExtensionProperties",
1346				"vkEnumerateDeviceExtensionProperties",
1347				"vkGetPhysicalDeviceFeatures",
1348				"vkGetPhysicalDeviceFeatures2KHR",
1349				"vkGetPhysicalDeviceProperties",
1350				"vkGetPhysicalDeviceProperties2KHR",
1351				"vkGetPhysicalDeviceQueueFamilyProperties",
1352				"vkGetPhysicalDeviceMemoryProperties",
1353				"vkGetPhysicalDeviceFormatProperties",
1354				"vkGetPhysicalDeviceImageFormatProperties",
1355				"vkGetDeviceQueue",
1356				"vkGetBufferMemoryRequirements",
1357				"vkGetBufferMemoryRequirements2KHR",
1358				"vkGetImageMemoryRequirements",
1359				"vkGetImageMemoryRequirements2KHR",
1360				"vkAllocateMemory",
1361				"vkMapMemory",
1362				"vkUnmapMemory",
1363				"vkAllocateDescriptorSets",
1364				"vkFreeDescriptorSets",
1365				"vkResetDescriptorPool",
1366				"vkAllocateCommandBuffers",
1367				"vkFreeCommandBuffers",
1368				"vkCreateDisplayModeKHR",
1369				"vkCreateSharedSwapchainsKHR",
1370				"vkGetPhysicalDeviceExternalBufferPropertiesKHR",
1371				"vkGetPhysicalDeviceImageFormatProperties2KHR",
1372				"vkGetMemoryAndroidHardwareBufferANDROID",
1373			]
1374
1375		coreFunctions		= [f for f in api.functions if not f.isAlias]
1376		specialFuncs		= [f for f in coreFunctions if f.name in specialFuncNames]
1377		createFuncs			= [f for f in coreFunctions if (f.name[:8] == "vkCreate" or f.name == "vkAllocateMemory") and not f in specialFuncs]
1378		destroyFuncs		= [f for f in coreFunctions if (f.name[:9] == "vkDestroy" or f.name == "vkFreeMemory") and not f in specialFuncs]
1379		dummyFuncs			= [f for f in coreFunctions if f not in specialFuncs + createFuncs + destroyFuncs]
1380
1381		def getHandle (name):
1382			for handle in api.handles:
1383				if handle.name == name[0]:
1384					return handle
1385			raise Exception("No such handle: %s" % name)
1386
1387		for function in createFuncs:
1388			objectType	= function.arguments[-1].type[:-1]
1389			argsStr		= ", ".join([a.name for a in function.arguments[:-1]])
1390
1391			yield "VKAPI_ATTR %s VKAPI_CALL %s (%s)" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments))
1392			yield "{"
1393			yield "\tDE_UNREF(%s);" % function.arguments[-2].name
1394
1395			if getHandle(objectType).type == Handle.TYPE_NONDISP:
1396				yield "\tVK_NULL_RETURN((*%s = allocateNonDispHandle<%s, %s>(%s)));" % (function.arguments[-1].name, objectType[0][2:], objectType[0], argsStr)
1397			else:
1398				yield "\tVK_NULL_RETURN((*%s = allocateHandle<%s, %s>(%s)));" % (function.arguments[-1].name, objectType[0][2:], objectType[0], argsStr)
1399			yield "}"
1400			yield ""
1401
1402		for function in destroyFuncs:
1403			objectArg	= function.arguments[-2]
1404
1405			yield "VKAPI_ATTR %s VKAPI_CALL %s (%s)" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments))
1406			yield "{"
1407			for arg in function.arguments[:-2]:
1408				yield "\tDE_UNREF(%s);" % arg.name
1409
1410			if getHandle(objectArg.type).type == Handle.TYPE_NONDISP:
1411				yield "\tfreeNonDispHandle<%s, %s>(%s, %s);" % (objectArg.getType()[2:], objectArg.getType(), objectArg.name, function.arguments[-1].name)
1412			else:
1413				yield "\tfreeHandle<%s, %s>(%s, %s);" % (objectArg.getType()[2:], objectArg.getType(), objectArg.name, function.arguments[-1].name)
1414
1415			yield "}"
1416			yield ""
1417
1418		for function in dummyFuncs:
1419			yield "VKAPI_ATTR %s VKAPI_CALL %s (%s)" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments))
1420			yield "{"
1421			for arg in function.arguments:
1422				yield "\tDE_UNREF(%s);" % arg.name
1423			if function.returnType != "void":
1424				yield "\treturn VK_SUCCESS;"
1425			yield "}"
1426			yield ""
1427
1428		def genFuncEntryTable (type, name):
1429			funcs = [f for f in api.functions if f.getType() == type]
1430			refFuncs = {}
1431			for f in api.functions:
1432				if f.alias != None:
1433					refFuncs[f.alias] = f
1434
1435			yield "static const tcu::StaticFunctionLibrary::Entry %s[] =" % name
1436			yield "{"
1437			for line in indentLines(["\tVK_NULL_FUNC_ENTRY(%s,\t%s)," % (function.name, getInterfaceName(function if not function.isAlias else refFuncs[function])) for function in funcs]):
1438				yield line
1439			yield "};"
1440			yield ""
1441
1442		# Func tables
1443		for line in genFuncEntryTable(Function.TYPE_PLATFORM, "s_platformFunctions"):
1444			yield line
1445
1446		for line in genFuncEntryTable(Function.TYPE_INSTANCE, "s_instanceFunctions"):
1447			yield line
1448
1449		for line in genFuncEntryTable(Function.TYPE_DEVICE, "s_deviceFunctions"):
1450			yield line
1451
1452	writeInlFile(filename, INL_HEADER, genNullDriverImpl())
1453
1454def writeTypeUtil (api, filename):
1455	# Structs filled by API queries are not often used in test code
1456	QUERY_RESULT_TYPES = set([
1457			"VkPhysicalDeviceFeatures",
1458			"VkPhysicalDeviceLimits",
1459			"VkFormatProperties",
1460			"VkImageFormatProperties",
1461			"VkPhysicalDeviceSparseProperties",
1462			"VkQueueFamilyProperties",
1463			"VkMemoryType",
1464			"VkMemoryHeap",
1465			"StdVideoH264SpsVuiFlags",
1466			"StdVideoH264SpsFlags",
1467			"StdVideoH264PpsFlags",
1468			"StdVideoDecodeH264PictureInfoFlags",
1469			"StdVideoDecodeH264ReferenceInfoFlags",
1470			"StdVideoDecodeH264MvcElementFlags",
1471			"StdVideoEncodeH264SliceHeaderFlags",
1472			"StdVideoEncodeH264PictureInfoFlags",
1473			"StdVideoEncodeH264RefMgmtFlags",
1474			"StdVideoH265HrdFlags",
1475			"StdVideoH265VpsFlags",
1476			"StdVideoH265SpsVuiFlags",
1477			"StdVideoH265SpsFlags",
1478			"StdVideoH265PpsFlags",
1479			"StdVideoDecodeH265PictureInfoFlags",
1480			"StdVideoDecodeH265ReferenceInfoFlags",
1481			"StdVideoEncodeH265PictureInfoFlags"
1482		])
1483	COMPOSITE_TYPES = set([t.name for t in api.compositeTypes if not t.isAlias])
1484
1485	def isSimpleStruct (type):
1486		def hasArrayMember (type):
1487			for member in type.members:
1488				if member.arraySize != '':
1489					return True
1490			return False
1491
1492		def hasCompositeMember (type):
1493			for member in type.members:
1494				if member.getType() in COMPOSITE_TYPES:
1495					return True
1496			return False
1497
1498		return type.typeClass == CompositeType.CLASS_STRUCT and \
1499		type.members[0].getType() != "VkStructureType" and \
1500		not type.name in QUERY_RESULT_TYPES and \
1501		not hasArrayMember(type) and \
1502		not hasCompositeMember(type)
1503
1504	def gen ():
1505		for type in api.compositeTypes:
1506			if not isSimpleStruct(type) or type.isAlias:
1507				continue
1508
1509			name = type.name[2:] if type.name[:2].lower() == "vk" else type.name
1510
1511			yield ""
1512			yield "inline %s make%s (%s)" % (type.name, name, argListToStr(type.members))
1513			yield "{"
1514			yield "\t%s res;" % type.name
1515			for line in indentLines(["\tres.%s\t= %s;" % (m.name, m.name) for m in type.members]):
1516				yield line
1517			yield "\treturn res;"
1518			yield "}"
1519
1520	writeInlFile(filename, INL_HEADER, gen())
1521
1522def writeDriverIds(filename):
1523
1524	driverIdsString = []
1525	driverIdsString.append("static const struct\n"
1526					 "{\n"
1527					 "\tstd::string driver;\n"
1528					 "\tdeUint32 id;\n"
1529					 "} driverIds [] =\n"
1530					 "{")
1531
1532	vulkanCore = readFile(os.path.join(VULKAN_H_DIR, "vulkan_core.h"))
1533
1534	items = re.search(r'(?:typedef\s+enum\s+VkDriverId\s*{)((.*\n)*)(?:}\s*VkDriverId\s*;)', vulkanCore).group(1).split(',')
1535	driverItems = dict()
1536	for item in items:
1537		item.strip()
1538		splitted = item.split('=')
1539		key = splitted[0].strip()
1540		value_str = splitted[1].strip()
1541		try: # is this previously defined value?
1542			value = driverItems[value_str]
1543		except:
1544			value = value_str
1545			value_str = ""
1546		if value_str:
1547			value_str = "\t// " + value_str
1548		driverItems[key] = value
1549		if not item == items[-1]:
1550			driverIdsString.append("\t{\"" + key + "\"" + ", " + value + "}," + value_str)
1551		else:
1552			driverIdsString.append("\t{\"" + key + "\"" + ", " + value + "}" + value_str)
1553		driverItems[key] = value
1554
1555	driverIdsString.append("};")
1556
1557	writeInlFile(filename, INL_HEADER, driverIdsString)
1558
1559
1560def writeSupportedExtenions(api, filename):
1561
1562	def writeExtensionsForVersions(map):
1563		result = []
1564		for version in map:
1565			result.append("	if (coreVersion >= " + str(version) + ")")
1566			result.append("	{")
1567			for extension in map[version]:
1568				result.append('		dst.push_back("' + extension.name + '");')
1569			result.append("	}")
1570
1571		return result
1572
1573	instanceMap		= {}
1574	deviceMap		= {}
1575	versionSet		= set()
1576
1577	for ext in api.extensions:
1578		if ext.versionInCore != None:
1579			if ext.versionInCore[0] == 'INSTANCE':
1580				list = instanceMap.get(Version(ext.versionInCore[1:]))
1581				instanceMap[Version(ext.versionInCore[1:])] = list + [ext] if list else [ext]
1582			else:
1583				list = deviceMap.get(Version(ext.versionInCore[1:]))
1584				deviceMap[Version(ext.versionInCore[1:])] = list + [ext] if list else [ext]
1585			versionSet.add(Version(ext.versionInCore[1:]))
1586
1587	lines = addVersionDefines(versionSet) + [
1588	"",
1589	"void getCoreDeviceExtensionsImpl (deUint32 coreVersion, ::std::vector<const char*>&%s)" % (" dst" if len(deviceMap) != 0 else ""),
1590	"{"] + writeExtensionsForVersions(deviceMap) + [
1591	"}",
1592	"",
1593	"void getCoreInstanceExtensionsImpl (deUint32 coreVersion, ::std::vector<const char*>&%s)" % (" dst" if len(instanceMap) != 0 else ""),
1594	"{"] + writeExtensionsForVersions(instanceMap) + [
1595	"}",
1596	""] + removeVersionDefines(versionSet)
1597	writeInlFile(filename, INL_HEADER, lines)
1598
1599def writeExtensionFunctions (api, filename):
1600
1601	def isInstanceExtension (ext):
1602		if ext.name and ext.functions:
1603			if ext.functions[0].getType() == Function.TYPE_INSTANCE:
1604				return True
1605			else:
1606				return False
1607
1608	def isDeviceExtension (ext):
1609		if ext.name and ext.functions:
1610			if ext.functions[0].getType() == Function.TYPE_DEVICE:
1611				return True
1612			else:
1613				return False
1614
1615	def writeExtensionNameArrays ():
1616		instanceExtensionNames = []
1617		deviceExtensionNames = []
1618		for ext in api.extensions:
1619			if ext.name and isInstanceExtension(ext):
1620				instanceExtensionNames += [ext.name]
1621			elif ext.name and isDeviceExtension(ext):
1622				deviceExtensionNames += [ext.name]
1623		yield '::std::string instanceExtensionNames[] =\n{'
1624		for instanceExtName in instanceExtensionNames:
1625			if (instanceExtName == instanceExtensionNames[len(instanceExtensionNames) - 1]):
1626				yield '\t"%s"' % instanceExtName
1627			else:
1628				yield '\t"%s",' % instanceExtName
1629		yield '};\n'
1630		yield '::std::string deviceExtensionNames[] =\n{'
1631		for deviceExtName in deviceExtensionNames:
1632			if (deviceExtName == deviceExtensionNames[len(deviceExtensionNames) - 1]):
1633				yield '\t"%s"' % deviceExtName
1634			else:
1635				yield '\t"%s",' % deviceExtName
1636		yield '};'
1637
1638	def writeExtensionFunctions (functionType):
1639		isFirstWrite = True
1640		dg_list = []	# Device groups functions need special casing, as Vulkan 1.0 keeps them in VK_KHR_device_groups whereas 1.1 moved them into VK_KHR_swapchain
1641		if functionType == Function.TYPE_INSTANCE:
1642			yield 'void getInstanceExtensionFunctions (deUint32 apiVersion, ::std::string extName, ::std::vector<const char*>& functions)\n{'
1643			dg_list = ["vkGetPhysicalDevicePresentRectanglesKHR"]
1644		elif functionType == Function.TYPE_DEVICE:
1645			yield 'void getDeviceExtensionFunctions (deUint32 apiVersion, ::std::string extName, ::std::vector<const char*>& functions)\n{'
1646			dg_list = ["vkGetDeviceGroupPresentCapabilitiesKHR", "vkGetDeviceGroupSurfacePresentModesKHR", "vkAcquireNextImage2KHR"]
1647		for ext in api.extensions:
1648			funcNames = []
1649			if ext.name:
1650				for func in ext.functions:
1651					if func.getType() == functionType:
1652						# only add functions with same vendor as extension
1653						# this is a workaroudn for entrypoints requiring more
1654						# than one excetions and lack of the dependency in vulkan_core.h
1655						vendor = ext.name.split('_')[1]
1656						if func.name.endswith(vendor):
1657							funcNames.append(func.name)
1658			if ext.name:
1659				yield '\tif (extName == "%s")' % ext.name
1660				yield '\t{'
1661				for funcName in funcNames:
1662					if funcName in dg_list:
1663						yield '\t\tif(apiVersion >= VK_API_VERSION_1_1) functions.push_back("%s");' % funcName
1664					else:
1665						yield '\t\tfunctions.push_back("%s");' % funcName
1666				if ext.name == "VK_KHR_device_group":
1667					for dg_func in dg_list:
1668						yield '\t\tif(apiVersion < VK_API_VERSION_1_1) functions.push_back("%s");' % dg_func
1669				yield '\t\treturn;'
1670				yield '\t}'
1671				isFirstWrite = False
1672		if not isFirstWrite:
1673			yield '\tDE_FATAL("Extension name not found");'
1674			yield '}'
1675
1676	lines = ['']
1677	for line in writeExtensionFunctions(Function.TYPE_INSTANCE):
1678		lines += [line]
1679	lines += ['']
1680	for line in writeExtensionFunctions(Function.TYPE_DEVICE):
1681		lines += [line]
1682	lines += ['']
1683	for line in writeExtensionNameArrays():
1684		lines += [line]
1685
1686	writeInlFile(filename, INL_HEADER, lines)
1687
1688def writeCoreFunctionalities(api, filename):
1689	functionOriginValues    = ["FUNCTIONORIGIN_PLATFORM", "FUNCTIONORIGIN_INSTANCE", "FUNCTIONORIGIN_DEVICE"]
1690	lines					= addVersionDefines(api.versions) + [
1691	"",
1692	'enum FunctionOrigin', '{'] + [line for line in indentLines([
1693	'\t' + functionOriginValues[0] + '\t= 0,',
1694	'\t' + functionOriginValues[1] + ',',
1695	'\t' + functionOriginValues[2]])] + [
1696	"};",
1697	"",
1698	"typedef ::std::pair<const char*, FunctionOrigin> FunctionInfo;",
1699	"typedef ::std::vector<FunctionInfo> FunctionInfosList;",
1700	"typedef ::std::map<deUint32, FunctionInfosList> ApisMap;",
1701	"",
1702	"void initApisMap (ApisMap& apis)",
1703	"{",
1704	"	apis.clear();"] + [
1705	"	apis.insert(::std::pair<deUint32, FunctionInfosList>(" + str(v) + ", FunctionInfosList()));" for v in api.versions] + [
1706	""]
1707
1708	apiVersions = []
1709	for index, v in enumerate(api.versions):
1710		funcs = []
1711		apiVersions.append("VK_VERSION_{0}_{1}".format(v.major, v.minor))
1712		# iterate over all functions that are core in latest vulkan version
1713		# note that first item in api.extension array are actually all definitions that are in vulkan.h.in before section with extensions
1714		for fun in api.extensions[0].functions:
1715			if fun.apiVersion in apiVersions:
1716				funcs.append('	apis[' + str(v) + '].push_back(FunctionInfo("' + fun.name + '",\t' + functionOriginValues[fun.getType()] + '));')
1717		lines = lines + [line for line in indentLines(funcs)] + [""]
1718
1719	lines = lines + ["}", ""] + removeVersionDefines(api.versions)
1720	writeInlFile(filename, INL_HEADER, lines)
1721
1722def writeDeviceFeatures2(api, filename):
1723	# list of structures that should be tested with getPhysicalDeviceFeatures2
1724	# this is not posible to determine from vulkan_core.h, if new feature structures
1725	# are added they should be manualy added to this list
1726	testedStructures = [
1727		'VkPhysicalDeviceConditionalRenderingFeaturesEXT',
1728		'VkPhysicalDeviceScalarBlockLayoutFeatures',
1729		'VkPhysicalDevicePerformanceQueryFeaturesKHR',
1730		'VkPhysicalDevice16BitStorageFeatures',
1731		'VkPhysicalDeviceMultiviewFeatures',
1732		'VkPhysicalDeviceProtectedMemoryFeatures',
1733		'VkPhysicalDeviceSamplerYcbcrConversionFeatures',
1734		'VkPhysicalDeviceVariablePointersFeatures',
1735		'VkPhysicalDevice8BitStorageFeatures',
1736		'VkPhysicalDeviceShaderAtomicInt64Features',
1737		'VkPhysicalDeviceShaderFloat16Int8Features',
1738		'VkPhysicalDeviceBufferDeviceAddressFeaturesEXT',
1739		'VkPhysicalDeviceBufferDeviceAddressFeatures',
1740		'VkPhysicalDeviceDescriptorIndexingFeatures',
1741		'VkPhysicalDeviceTimelineSemaphoreFeatures',
1742		'VkPhysicalDeviceFragmentDensityMapFeaturesEXT',
1743		'VkPhysicalDeviceFragmentDensityMap2FeaturesEXT'
1744	]
1745	# helper class used to encapsulate all data needed during generation
1746	class StructureDetail:
1747		def __init__ (self, name):
1748			nameResult			= re.search('(.*)Features(.*)', name[len('VkPhysicalDevice'):])
1749			nameSplitUp			= ''
1750			# generate structure type name from structure name
1751			# note that sometimes digits are separated with '_':
1752			# VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_2_FEATURES_EXT
1753			# but mostly they are not:
1754			# VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES
1755			if (nameResult.group(1) == 'FragmentDensityMap2'):
1756				nameSplitUp		= ['FRAGMENT', 'DENSITY', 'MAP', '2', 'FEATURES']
1757			else:
1758				nameSplit		= re.findall(r'[1-9A-Z]+(?:[a-z1-9]+|[A-Z]*(?=[A-Z]|$))', nameResult.group(1))
1759				nameSplitUp		= map(str.upper, nameSplit)
1760				nameSplitUp		= list(nameSplitUp) + ['FEATURES']
1761			# check if there is extension suffix
1762			if (len(nameResult.group(2)) != 0):
1763				nameSplitUp.append(nameResult.group(2))
1764			self.name			= name
1765			self.sType			= 'VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_' + '_'.join(nameSplitUp)
1766			self.instanceName	= 'd' + name[11:]
1767			self.flagName		= 'is' + name[16:]
1768			self.extension		= None
1769			self.major			= None
1770			self.minor			= None
1771			self.members		= []
1772	# helper extension class used in algorith below
1773	class StructureFoundContinueToNextOne(Exception):
1774		pass
1775	testedStructureDetail = [StructureDetail(struct) for struct in testedStructures]
1776	# iterate over all searched structures and find extensions that enable them
1777	for structureDetail in testedStructureDetail:
1778		try:
1779			# iterate over all extensions
1780			for extension in api.extensions[1:]:
1781				# check composite types and typedefs in case extension is part of core
1782				for structureList in [extension.compositeTypes, extension.typedefs]:
1783					# iterate over all structures added by extension
1784					for extensionStructure in structureList:
1785						# compare checked structure name to name of structure from extension
1786						if structureDetail.name == extensionStructure.name:
1787							structureDetail.extension = extension.name
1788							if extension.versionInCore is not None:
1789								structureDetail.major = extension.versionInCore[1]
1790								structureDetail.minor = extension.versionInCore[2]
1791							raise StructureFoundContinueToNextOne
1792		except StructureFoundContinueToNextOne:
1793			continue
1794	for structureDetail in testedStructureDetail:
1795		for compositeType in api.compositeTypes:
1796			if structureDetail.name != compositeType.name:
1797				continue
1798			structureMembers = compositeType.members[2:]
1799			structureDetail.members = [m.name for m in structureMembers]
1800			if structureDetail.major is not None:
1801				break
1802			# if structure was not added with extension then check if
1803			# it was added directly with one of vulkan versions
1804			apiVersion = compositeType.apiVersion
1805			if apiVersion is None:
1806				continue
1807			structureDetail.major = apiVersion.major
1808			structureDetail.minor = apiVersion.minor
1809			break
1810	# generate file content
1811	structureDefinitions = []
1812	featureEnabledFlags = []
1813	clearStructures = []
1814	structureChain = []
1815	logStructures = []
1816	verifyStructures = []
1817	for index, structureDetail in enumerate(testedStructureDetail):
1818		# create two instances of each structure
1819		nameSpacing = '\t' * int((55 - len(structureDetail.name)) / 4)
1820		structureDefinitions.append(structureDetail.name + nameSpacing + structureDetail.instanceName + '[count];')
1821		# create flags that check if proper extension or vulkan version is available
1822		condition	= ''
1823		extension	= structureDetail.extension
1824		major		= structureDetail.major
1825		if extension is not None:
1826			condition = ' checkExtension(properties, "' + extension + '")'
1827		if major is not None:
1828			if condition != '':
1829				condition += '\t' * int((39 - len(extension)) / 4) + '|| '
1830			else:
1831				condition += '\t' * 17 + '   '
1832			condition += 'context.contextSupports(vk::ApiVersion(' + str(major) + ', ' + str(structureDetail.minor) + ', 0))'
1833		condition += ';'
1834		nameSpacing = '\t' * int((40 - len(structureDetail.flagName)) / 4)
1835		featureEnabledFlags.append('const bool ' + structureDetail.flagName + nameSpacing + '=' + condition)
1836		# clear memory of each structure
1837		nameSpacing = '\t' * int((43 - len(structureDetail.instanceName)) / 4)
1838		clearStructures.append('\tdeMemset(&' + structureDetail.instanceName + '[ndx],' + nameSpacing + '0xFF * ndx, sizeof(' + structureDetail.name + '));')
1839		# construct structure chain
1840		nextInstanceName = 'DE_NULL';
1841		if index < len(testedStructureDetail)-1:
1842			nextInstanceName = '&' + testedStructureDetail[index+1].instanceName + '[ndx]'
1843		structureChain.append('\t' + structureDetail.instanceName + '[ndx].sType = ' + structureDetail.sType + ';')
1844		structureChain.append('\t' + structureDetail.instanceName + '[ndx].pNext = ' + nextInstanceName + ';\n')
1845		# construct log section
1846		logStructures.append('if (' + structureDetail.flagName + ')')
1847		logStructures.append('\tlog << TestLog::Message << ' + structureDetail.instanceName + '[0] << TestLog::EndMessage;')
1848		#construct verification section
1849		verifyStructures.append('if (' + structureDetail.flagName + ' &&')
1850		for index, m in enumerate(structureDetail.members):
1851			prefix = '\t(' if index == 0 else '\t '
1852			postfix = '))' if index == len(structureDetail.members)-1 else ' ||'
1853			verifyStructures.append(prefix + structureDetail.instanceName + '[0].' + m + ' != ' + structureDetail.instanceName + '[1].' + m + postfix)
1854		verifyStructures.append('{\n\t\tTCU_FAIL("Mismatch between ' + structureDetail.name + '");\n}')
1855	# construct file content
1856	stream = []
1857	stream.extend(structureDefinitions)
1858	stream.append('')
1859	stream.extend(featureEnabledFlags)
1860	stream.append('\nfor (int ndx = 0; ndx < count; ++ndx)\n{')
1861	stream.extend(clearStructures)
1862	stream.append('')
1863	stream.extend(structureChain)
1864	stream.append('\tdeMemset(&extFeatures.features, 0xcd, sizeof(extFeatures.features));\n'
1865				  '\textFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;\n'
1866				  '\textFeatures.pNext = &' + testedStructureDetail[0].instanceName + '[ndx];\n'
1867				  '\tvki.getPhysicalDeviceFeatures2(physicalDevice, &extFeatures);\n}\n')
1868	stream.extend(logStructures)
1869	stream.append('')
1870	stream.extend(verifyStructures)
1871	writeInlFile(filename, INL_HEADER, stream)
1872
1873def generateDeviceFeaturesDefs(src):
1874	# look for definitions
1875	ptrnSType	= r'VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_(\w+)_FEATURES(\w*)\s*='
1876	matches		= re.findall(ptrnSType, src, re.M)
1877	matches		= sorted(matches, key=lambda m: m[0])
1878	# construct final list
1879	defs = []
1880	for sType, sSuffix in matches:
1881		structName			= re.sub("[_0-9][a-z]", lambda match: match.group(0).upper(), sType.capitalize()).replace('_', '')
1882		ptrnStructName		= r'\s*typedef\s+struct\s+(VkPhysicalDevice' + structName + 'Features' + sSuffix.replace('_', '') + ')'
1883		matchStructName		= re.search(ptrnStructName, src, re.IGNORECASE)
1884		if matchStructName:
1885			# handle special cases
1886			if sType == "EXCLUSIVE_SCISSOR":
1887				sType = "SCISSOR_EXCLUSIVE"
1888			elif sType == "ASTC_DECODE":
1889				sType = "ASTC_DECODE_MODE"
1890			if sType in {'VULKAN_1_1', 'VULKAN_1_2'}:
1891				continue
1892			# end handling special cases
1893			ptrnExtensionName	= r'^\s*#define\s+(\w+' + sSuffix + '_' + sType + '_EXTENSION_NAME).+$'
1894			matchExtensionName	= re.search(ptrnExtensionName, src, re.M)
1895			ptrnSpecVersion		= r'^\s*#define\s+(\w+' + sSuffix + '_' + sType + '_SPEC_VERSION).+$'
1896			matchSpecVersion	= re.search(ptrnSpecVersion, src, re.M)
1897			defs.append( (sType, '', sSuffix, matchStructName.group(1), \
1898							matchExtensionName.group(0)	if matchExtensionName	else None,
1899							matchExtensionName.group(1)	if matchExtensionName	else None,
1900							matchSpecVersion.group(1)	if matchSpecVersion		else '0') )
1901	return defs
1902
1903def generateDevicePropertiesDefs(src):
1904	# look for definitions
1905	ptrnSType	= r'VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_(\w+)_PROPERTIES(\w*)\s*='
1906	matches		= re.findall(ptrnSType, src, re.M)
1907	matches		= sorted(matches, key=lambda m: m[0])
1908	# construct final list
1909	defs = []
1910	for sType, sSuffix in matches:
1911		# handle special cases
1912		if sType in {'VULKAN_1_1', 'VULKAN_1_2', 'GROUP', 'MEMORY_BUDGET', 'MEMORY', 'TOOL'}:
1913			continue
1914		# there are cases like VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_2_AMD
1915		# where 2 is after PROPERTIES - to handle this we need to split suffix to two parts
1916		sVerSuffix = ''
1917		sExtSuffix = sSuffix
1918		suffixStart = sSuffix.rfind('_')
1919		if suffixStart > 0:
1920			sVerSuffix = sSuffix[:suffixStart]
1921			sExtSuffix = sSuffix[suffixStart:]
1922		# handle special case
1923		if sType == "ID":
1924			structName	= sType
1925		else:
1926			structName	= re.sub("[_0-9][a-z]", lambda match: match.group(0).upper(), sType.capitalize()).replace('_', '')
1927		ptrnStructName		= r'\s*typedef\s+struct\s+(VkPhysicalDevice' + structName + 'Properties' + sSuffix.replace('_', '') + ')'
1928		matchStructName		= re.search(ptrnStructName, src, re.M)
1929		if matchStructName:
1930			extType = sType
1931			if extType == "MAINTENANCE_3":
1932				extType = "MAINTENANCE3"
1933			elif extType == "DISCARD_RECTANGLE":
1934				extType = "DISCARD_RECTANGLES"
1935			elif extType == "DRIVER":
1936				extType = "DRIVER_PROPERTIES"
1937			elif extType == "POINT_CLIPPING":
1938				extType = "MAINTENANCE2"
1939			elif extType == "SHADER_CORE":
1940				extType = "SHADER_CORE_PROPERTIES"
1941			# end handling special cases
1942			ptrnExtensionName	= r'^\s*#define\s+(\w+' + sExtSuffix + '_' + extType + sVerSuffix +'[_0-9]*_EXTENSION_NAME).+$'
1943			matchExtensionName	= re.search(ptrnExtensionName, src, re.M)
1944			ptrnSpecVersion		= r'^\s*#define\s+(\w+' + sExtSuffix + '_' + extType + sVerSuffix + '[_0-9]*_SPEC_VERSION).+$'
1945			matchSpecVersion	= re.search(ptrnSpecVersion, src, re.M)
1946			defs.append( (sType, sVerSuffix, sExtSuffix, matchStructName.group(1), \
1947							matchExtensionName.group(0)	if matchExtensionName	else None,
1948							matchExtensionName.group(1)	if matchExtensionName	else None,
1949							matchSpecVersion.group	(1)	if matchSpecVersion		else '0') )
1950	return defs
1951
1952def writeDeviceFeatures(api, dfDefs, filename):
1953	# find VkPhysicalDeviceVulkan[1-9][0-9]Features blob structurs
1954	# and construct dictionary with all of their attributes
1955	blobMembers = {}
1956	blobStructs = {}
1957	blobPattern = re.compile("^VkPhysicalDeviceVulkan([1-9][0-9])Features[0-9]*$")
1958	for structureType in api.compositeTypes:
1959		match = blobPattern.match(structureType.name)
1960		if match:
1961			allMembers = [member.name for member in structureType.members]
1962			vkVersion = match.group(1)
1963			blobMembers[vkVersion] = allMembers[2:]
1964			blobStructs[vkVersion] = set()
1965	initFromBlobDefinitions = []
1966	emptyInitDefinitions = []
1967	# iterate over all feature structures
1968	allFeaturesPattern = re.compile("^VkPhysicalDevice\w+Features[1-9]*")
1969	nonExtFeaturesPattern = re.compile("^VkPhysicalDevice\w+Features[1-9]*$")
1970	for structureType in api.compositeTypes:
1971		# skip structures that are not feature structures
1972		if not allFeaturesPattern.match(structureType.name):
1973			continue
1974		# skip structures that were previously identified as blobs
1975		if blobPattern.match(structureType.name):
1976			continue
1977		if structureType.isAlias:
1978			continue
1979		# skip sType and pNext and just grab third and next attributes
1980		structureMembers = structureType.members[2:]
1981		notPartOfBlob = True
1982		if nonExtFeaturesPattern.match(structureType.name):
1983			# check if this member is part of any of the blobs
1984			for blobName, blobMemberList in blobMembers.items():
1985				# if just one member is not part of this blob go to the next blob
1986				# (we asume that all members are part of blob - no need to check all)
1987				if structureMembers[0].name not in blobMemberList:
1988					continue
1989				# add another feature structure name to this blob
1990				blobStructs[blobName].add(structureType)
1991				# add specialization for this feature structure
1992				memberCopying = ""
1993				for member in structureMembers:
1994					memberCopying += "\tfeatureType.{0} = allFeaturesBlobs.vk{1}.{0};\n".format(member.name, blobName)
1995				wholeFunction = \
1996					"template<> void initFeatureFromBlob<{0}>({0}& featureType, const AllFeaturesBlobs& allFeaturesBlobs)\n" \
1997					"{{\n" \
1998					"{1}" \
1999					"}}".format(structureType.name, memberCopying)
2000				initFromBlobDefinitions.append(wholeFunction)
2001				notPartOfBlob = False
2002				# assuming that all members are part of blob, goto next
2003				break
2004		# add empty template definition as on Fedora there are issue with
2005		# linking using just generic template - all specializations are needed
2006		if notPartOfBlob:
2007			emptyFunction = "template<> void initFeatureFromBlob<{0}>({0}&, const AllFeaturesBlobs&) {{}}"
2008			emptyInitDefinitions.append(emptyFunction.format(structureType.name))
2009	extensionDefines = []
2010	makeFeatureDescDefinitions = []
2011	featureStructWrappers = []
2012	for idx, (sType, sVerSuffix, sExtSuffix, extStruct, extLine, extName, specVer) in enumerate(dfDefs):
2013		extensionNameDefinition = extName
2014		if not extensionNameDefinition:
2015			extensionNameDefinition = 'DECL{0}_{1}_EXTENSION_NAME'.format((sExtSuffix if sExtSuffix else ''), sType)
2016		# construct defines with names
2017		if extLine:
2018			extensionDefines.append(extLine)
2019		else:
2020			extensionDefines.append('#define {0} "not_existent_feature"'.format(extensionNameDefinition))
2021		# handle special cases
2022		if sType == "SCISSOR_EXCLUSIVE":
2023			sType = "EXCLUSIVE_SCISSOR"
2024		elif sType == "ASTC_DECODE_MODE":
2025			sType = "ASTC_DECODE"
2026		# end handling special cases
2027		# construct makeFeatureDesc template function definitions
2028		sTypeName = "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_{0}_FEATURES{1}".format(sType, sVerSuffix + sExtSuffix)
2029		makeFeatureDescDefinitions.append("template<> FeatureDesc makeFeatureDesc<{0}>(void) " \
2030			"{{ return FeatureDesc{{{1}, {2}, {3}, {4}}}; }}".format(extStruct, sTypeName, extensionNameDefinition, specVer, len(dfDefs)-idx))
2031		# construct CreateFeatureStruct wrapper block
2032		featureStructWrappers.append("\t{{ createFeatureStructWrapper<{0}>, {1}, {2} }},".format(extStruct, extensionNameDefinition, specVer))
2033	# construct method that will check if structure sType is part of blob
2034	blobChecker = "bool isPartOfBlobFeatures (VkStructureType sType)\n{\n" \
2035				  "\tconst std::vector<VkStructureType> sTypeVect =" \
2036				  "\t{\n"
2037	# iterate over blobs with list of structures
2038	for blobName in sorted(blobStructs.keys()):
2039		blobChecker += "\t\t// Vulkan{0}\n".format(blobName)
2040		# iterate over all feature structures in current blob
2041		structuresList = list(blobStructs[blobName])
2042		structuresList = sorted(structuresList, key=lambda s: s.name)
2043		for structType in structuresList:
2044			# find definition of this structure in dfDefs
2045			structName = structType.name
2046			# handle special cases
2047			if structName == 'VkPhysicalDeviceShaderDrawParameterFeatures':
2048				structName = 'VkPhysicalDeviceShaderDrawParametersFeatures'
2049			# end handling special cases
2050			structDef = [s for s in dfDefs if s[3] == structName][0]
2051			sType = structDef[0]
2052			sSuffix = structDef[1] + structDef[2]
2053			# handle special cases
2054			if sType == "SCISSOR_EXCLUSIVE":
2055				sType = "EXCLUSIVE_SCISSOR"
2056			# end handling special cases
2057			sTypeName = "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_{0}_FEATURES{1}".format(sType, sSuffix)
2058			blobChecker += "\t\t{0},\n".format(sTypeName)
2059	blobChecker += "\t};\n" \
2060				   "\treturn de::contains(sTypeVect.begin(), sTypeVect.end(), sType);\n" \
2061				   "}\n"
2062	# combine all definition lists
2063	stream = [
2064	'#include "vkDeviceFeatures.hpp"\n',
2065	'namespace vk\n{']
2066	stream.extend(extensionDefines)
2067	stream.append('\n')
2068	stream.extend(initFromBlobDefinitions)
2069	stream.append('\n// generic template is not enough for some compilers')
2070	stream.extend(emptyInitDefinitions)
2071	stream.append('\n')
2072	stream.extend(makeFeatureDescDefinitions)
2073	stream.append('\n')
2074	stream.append('static const FeatureStructCreationData featureStructCreationArray[] =\n{')
2075	stream.extend(featureStructWrappers)
2076	stream.append('};\n')
2077	stream.append(blobChecker)
2078	stream.append('} // vk\n')
2079	writeInlFile(filename, INL_HEADER, stream)
2080
2081def writeDeviceProperties(api, dpDefs, filename):
2082	# find VkPhysicalDeviceVulkan[1-9][0-9]Features blob structurs
2083	# and construct dictionary with all of their attributes
2084	blobMembers = {}
2085	blobStructs = {}
2086	blobPattern = re.compile("^VkPhysicalDeviceVulkan([1-9][0-9])Properties[0-9]*$")
2087	for structureType in api.compositeTypes:
2088		match = blobPattern.match(structureType.name)
2089		if match:
2090			allMembers = [member.name for member in structureType.members]
2091			vkVersion = match.group(1)
2092			blobMembers[vkVersion] = allMembers[2:]
2093			blobStructs[vkVersion] = set()
2094	initFromBlobDefinitions = []
2095	emptyInitDefinitions = []
2096	# iterate over all property structures
2097	allPropertiesPattern = re.compile("^VkPhysicalDevice\w+Properties[1-9]*")
2098	nonExtPropertiesPattern = re.compile("^VkPhysicalDevice\w+Properties[1-9]*$")
2099	for structureType in api.compositeTypes:
2100		# skip structures that are not property structures
2101		if not allPropertiesPattern.match(structureType.name):
2102			continue
2103		# skip structures that were previously identified as blobs
2104		if blobPattern.match(structureType.name):
2105			continue
2106		if structureType.isAlias:
2107			continue
2108		# skip sType and pNext and just grab third and next attributes
2109		structureMembers = structureType.members[2:]
2110		notPartOfBlob = True
2111		if nonExtPropertiesPattern.match(structureType.name):
2112			# check if this member is part of any of the blobs
2113			for blobName, blobMemberList in blobMembers.items():
2114				# if just one member is not part of this blob go to the next blob
2115				# (we asume that all members are part of blob - no need to check all)
2116				if structureMembers[0].name not in blobMemberList:
2117					continue
2118				# add another property structure name to this blob
2119				blobStructs[blobName].add(structureType)
2120				# add specialization for this property structure
2121				memberCopying = ""
2122				for member in structureMembers:
2123					if not member.arraySize:
2124						# handle special case
2125						if structureType.name == "VkPhysicalDeviceSubgroupProperties" and "subgroup" not in member.name :
2126							blobMemberName = "subgroup" + member.name[0].capitalize() + member.name[1:]
2127							memberCopying += "\tpropertyType.{0} = allPropertiesBlobs.vk{1}.{2};\n".format(member.name, blobName, blobMemberName)
2128						# end handling special case
2129						else:
2130							memberCopying += "\tpropertyType.{0} = allPropertiesBlobs.vk{1}.{0};\n".format(member.name, blobName)
2131					else:
2132						memberCopying += "\tmemcpy(propertyType.{0}, allPropertiesBlobs.vk{1}.{0}, sizeof({2}) * {3});\n".format(member.name, blobName, member.type[0], member.arraySize[1:-1])
2133				wholeFunction = \
2134					"template<> void initPropertyFromBlob<{0}>({0}& propertyType, const AllPropertiesBlobs& allPropertiesBlobs)\n" \
2135					"{{\n" \
2136					"{1}" \
2137					"}}".format(structureType.name, memberCopying)
2138				initFromBlobDefinitions.append(wholeFunction)
2139				notPartOfBlob = False
2140				# assuming that all members are part of blob, goto next
2141				break
2142		# add empty template definition as on Fedora there are issue with
2143		# linking using just generic template - all specializations are needed
2144		if notPartOfBlob:
2145			emptyFunction = "template<> void initPropertyFromBlob<{0}>({0}&, const AllPropertiesBlobs&) {{}}"
2146			emptyInitDefinitions.append(emptyFunction.format(structureType.name))
2147	extensionDefines = []
2148	makePropertyDescDefinitions = []
2149	propertyStructWrappers = []
2150	for idx, (sType, sVerSuffix, sExtSuffix, extStruct, extLine, extName, specVer) in enumerate(dpDefs):
2151		extensionNameDefinition = extName
2152		if not extensionNameDefinition:
2153			extensionNameDefinition = 'DECL{0}_{1}_EXTENSION_NAME'.format((sExtSuffix if sExtSuffix else ''), sType)
2154		# construct defines with names
2155		if extLine:
2156			extensionDefines.append(extLine)
2157		else:
2158			extensionDefines.append('#define {0} "core_property"'.format(extensionNameDefinition))
2159		# construct makePropertyDesc template function definitions
2160		sTypeName = "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_{0}_PROPERTIES{1}".format(sType, sVerSuffix + sExtSuffix)
2161		makePropertyDescDefinitions.append("template<> PropertyDesc makePropertyDesc<{0}>(void) " \
2162			"{{ return PropertyDesc{{{1}, {2}, {3}, {4}}}; }}".format(extStruct, sTypeName, extensionNameDefinition, specVer, len(dpDefs)-idx))
2163		# construct CreateProperty struct wrapper block
2164		propertyStructWrappers.append("\t{{ createPropertyStructWrapper<{0}>, {1}, {2} }},".format(extStruct, extensionNameDefinition, specVer))
2165			# construct method that will check if structure sType is part of blob
2166	blobChecker = "bool isPartOfBlobProperties (VkStructureType sType)\n{\n" \
2167				  "\tconst std::vector<VkStructureType> sTypeVect =" \
2168				  "\t{\n"
2169	# iterate over blobs with list of structures
2170	for blobName in sorted(blobStructs.keys()):
2171		blobChecker += "\t\t// Vulkan{0}\n".format(blobName)
2172		# iterate over all feature structures in current blob
2173		structuresList = list(blobStructs[blobName])
2174		structuresList = sorted(structuresList, key=lambda s: s.name)
2175		for structType in structuresList:
2176			# find definition of this structure in dpDefs
2177			structName = structType.name
2178			structDef = [s for s in dpDefs if s[3] == structName][0]
2179			sType = structDef[0]
2180			sSuffix = structDef[1] + structDef[2]
2181			sTypeName = "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_{0}_PROPERTIES{1}".format(sType, sSuffix)
2182			blobChecker += "\t\t{0},\n".format(sTypeName)
2183	blobChecker += "\t};\n" \
2184				   "\treturn de::contains(sTypeVect.begin(), sTypeVect.end(), sType);\n" \
2185				   "}\n"
2186	# combine all definition lists
2187	stream = [
2188	'#include "vkDeviceProperties.hpp"\n',
2189	'namespace vk\n{']
2190	stream.extend(extensionDefines)
2191	stream.append('\n')
2192	stream.extend(initFromBlobDefinitions)
2193	stream.append('\n// generic template is not enough for some compilers')
2194	stream.extend(emptyInitDefinitions)
2195	stream.append('\n')
2196	stream.extend(makePropertyDescDefinitions)
2197	stream.append('\n')
2198	stream.append('static const PropertyStructCreationData propertyStructCreationArray[] =\n{')
2199	stream.extend(propertyStructWrappers)
2200	stream.append('};\n')
2201	stream.append(blobChecker)
2202	stream.append('} // vk\n')
2203	writeInlFile(filename, INL_HEADER, stream)
2204
2205def genericDeviceFeaturesWriter(dfDefs, pattern, filename):
2206	stream = []
2207	for _, _, _, extStruct, _, _, _ in dfDefs:
2208		nameSubStr = extStruct.replace("VkPhysicalDevice", "").replace("KHR", "").replace("NV", "")
2209		stream.append(pattern.format(extStruct, nameSubStr))
2210	writeInlFile(filename, INL_HEADER, indentLines(stream))
2211
2212def writeDeviceFeaturesDefaultDeviceDefs(dfDefs, filename):
2213	pattern = "const {0}&\tget{1}\t(void) const {{ return m_deviceFeatures.getFeatureType<{0}>();\t}}"
2214	genericDeviceFeaturesWriter(dfDefs, pattern, filename)
2215
2216def writeDeviceFeaturesContextDecl(dfDefs, filename):
2217	pattern = "const vk::{0}&\tget{1}\t(void) const;"
2218	genericDeviceFeaturesWriter(dfDefs, pattern, filename)
2219
2220def writeDeviceFeaturesContextDefs(dfDefs, filename):
2221	pattern = "const vk::{0}&\tContext::get{1}\t(void) const {{ return m_device->get{1}();\t}}"
2222	genericDeviceFeaturesWriter(dfDefs, pattern, filename)
2223
2224def genericDevicePropertiesWriter(dfDefs, pattern, filename):
2225	stream = []
2226	for _, _, _, extStruct, _, _, _ in dfDefs:
2227		nameSubStr = extStruct.replace("VkPhysicalDevice", "").replace("KHR", "").replace("NV", "")
2228		if extStruct == "VkPhysicalDeviceRayTracingPropertiesNV":
2229			nameSubStr += "NV"
2230		stream.append(pattern.format(extStruct, nameSubStr))
2231	writeInlFile(filename, INL_HEADER, indentLines(stream))
2232
2233def writeDevicePropertiesDefaultDeviceDefs(dfDefs, filename):
2234	pattern = "const {0}&\tget{1}\t(void) const {{ return m_deviceProperties.getPropertyType<{0}>();\t}}"
2235	genericDevicePropertiesWriter(dfDefs, pattern, filename)
2236
2237def writeDevicePropertiesContextDecl(dfDefs, filename):
2238	pattern = "const vk::{0}&\tget{1}\t(void) const;"
2239	genericDevicePropertiesWriter(dfDefs, pattern, filename)
2240
2241def writeDevicePropertiesContextDefs(dfDefs, filename):
2242	pattern = "const vk::{0}&\tContext::get{1}\t(void) const {{ return m_device->get{1}();\t}}"
2243	genericDevicePropertiesWriter(dfDefs, pattern, filename)
2244
2245def splitWithQuotation(line):
2246	result = []
2247	splitted = re.findall(r'[^"\s]\S*|".+?"', line)
2248	for s in splitted:
2249		result.append(s.replace('"', ''))
2250	return result
2251
2252def writeMandatoryFeatures(filename):
2253	stream = []
2254	pattern = r'\s*([\w]+)\s+FEATURES\s+\((.*)\)\s+REQUIREMENTS\s+\((.*)\)'
2255	mandatoryFeatures = readFile(os.path.join(VULKAN_H_DIR, "mandatory_features.txt"))
2256	matches = re.findall(pattern, mandatoryFeatures)
2257	dictStructs = {}
2258	dictData = []
2259	for m in matches:
2260		allRequirements = splitWithQuotation(m[2])
2261		dictData.append( [ m[0], m[1].strip(), allRequirements ] )
2262		if m[0] != 'VkPhysicalDeviceFeatures' :
2263			if (m[0] not in dictStructs):
2264				dictStructs[m[0]] = [m[0][2:3].lower() + m[0][3:]]
2265			if (allRequirements[0]):
2266				if (allRequirements[0] not in dictStructs[m[0]][1:]):
2267					dictStructs[m[0]].append(allRequirements[0])
2268
2269	stream.extend(['bool checkMandatoryFeatures(const vkt::Context& context)\n{',
2270				   '\tif (!context.isInstanceFunctionalitySupported("VK_KHR_get_physical_device_properties2"))',
2271				   '\t\tTCU_THROW(NotSupportedError, "Extension VK_KHR_get_physical_device_properties2 is not present");',
2272				   '',
2273				   '\tVkPhysicalDevice\t\t\t\t\tphysicalDevice\t\t= context.getPhysicalDevice();',
2274				   '\tconst InstanceInterface&\t\t\tvki\t\t\t\t\t= context.getInstanceInterface();',
2275				   '\tconst vector<VkExtensionProperties>\tdeviceExtensions\t= enumerateDeviceExtensionProperties(vki, physicalDevice, DE_NULL);',
2276				   '',
2277				   '\ttcu::TestLog& log = context.getTestContext().getLog();',
2278				   '\tvk::VkPhysicalDeviceFeatures2 coreFeatures;',
2279				   '\tdeMemset(&coreFeatures, 0, sizeof(coreFeatures));',
2280				   '\tcoreFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;',
2281				   '\tvoid** nextPtr = &coreFeatures.pNext;',
2282				   ''])
2283
2284	listStruct = sorted(dictStructs.items(), key=lambda tup: tup[0]) # sort to have same results for py2 and py3
2285	for k, v in listStruct:
2286		if (v[1].startswith("ApiVersion")):
2287			cond = '\tif (context.contextSupports(vk::' + v[1] + '))'
2288		else:
2289			cond = '\tif (vk::isDeviceExtensionSupported(context.getUsedApiVersion(), context.getDeviceExtensions(), "' + v[1] + '"))'
2290		stream.extend(['\tvk::' + k + ' ' + v[0]+ ';',
2291					'\tdeMemset(&' + v[0] + ', 0, sizeof(' + v[0] + '));',
2292					''])
2293		reqs = v[1:]
2294		if len(reqs) > 0 :
2295			cond = 'if ( '
2296			for i, req in enumerate(reqs) :
2297				if (req.startswith("ApiVersion")):
2298					cond = cond + 'context.contextSupports(vk::' + req + ')'
2299				else:
2300					cond = cond + 'isExtensionSupported(deviceExtensions, RequiredExtension("' + req + '"))'
2301				if i+1 < len(reqs) :
2302					cond = cond + ' || '
2303			cond = cond + ' )'
2304			stream.append('\t' + cond)
2305		stream.extend(['\t{',
2306					   '\t\t' + v[0] + '.sType = getStructureType<' + k + '>();',
2307					   '\t\t*nextPtr = &' + v[0] + ';',
2308					   '\t\tnextPtr  = &' + v[0] + '.pNext;',
2309					   '\t}',
2310					   ''])
2311	stream.extend(['\tcontext.getInstanceInterface().getPhysicalDeviceFeatures2(context.getPhysicalDevice(), &coreFeatures);',
2312				   '\tbool result = true;',
2313				   ''])
2314
2315	for v in dictData:
2316		structType = v[0];
2317		structName = 'coreFeatures.features';
2318		if v[0] != 'VkPhysicalDeviceFeatures' :
2319			structName = dictStructs[v[0]][0]
2320		if len(v[2]) > 0 :
2321			condition = 'if ( '
2322			for i, req in enumerate(v[2]) :
2323				if (req.startswith("ApiVersion")):
2324					condition = condition + 'context.contextSupports(vk::' + req + ')'
2325				elif '.' in req:
2326					condition = condition + req
2327				else:
2328					condition = condition + 'isExtensionSupported(deviceExtensions, RequiredExtension("' + req + '"))'
2329				if i+1 < len(v[2]) :
2330					condition = condition + ' && '
2331			condition = condition + ' )'
2332			stream.append('\t' + condition)
2333		stream.append('\t{')
2334		# Don't need to support an AND case since that would just be another line in the .txt
2335		if len(v[1].split(" ")) == 1:
2336			stream.append('\t\tif ( ' + structName + '.' + v[1] + ' == VK_FALSE )')
2337		else:
2338			condition = 'if ( '
2339			for i, feature in enumerate(v[1].split(" ")):
2340				if i != 0:
2341					condition = condition + ' && '
2342				condition = condition + '( ' + structName + '.' + feature + ' == VK_FALSE )'
2343			condition = condition + ' )'
2344			stream.append('\t\t' + condition)
2345		featureSet = v[1].replace(" ", " or ")
2346		stream.extend(['\t\t{',
2347					   '\t\t\tlog << tcu::TestLog::Message << "Mandatory feature ' + featureSet + ' not supported" << tcu::TestLog::EndMessage;',
2348					   '\t\t\tresult = false;',
2349					   '\t\t}',
2350					   '\t}',
2351					   ''])
2352	stream.append('\treturn result;')
2353	stream.append('}\n')
2354	writeInlFile(filename, INL_HEADER, stream)
2355
2356def writeExtensionList(filename, patternPart):
2357	stream = []
2358	stream.append('static const char* s_allowed{0}KhrExtensions[] =\n{{'.format(patternPart.title()))
2359	extensionsData = readFile(os.path.join(VULKAN_H_DIR, "extensions_data.txt"))
2360	pattern = r'\s*([^\s]+)\s+{0}\s*[0-9_]*'.format(patternPart)
2361	matches	= re.findall(pattern, extensionsData)
2362	for m in matches:
2363		stream.append('\t"' + m + '",')
2364	stream.append('};\n')
2365	writeInlFile(filename, INL_HEADER, stream)
2366
2367def preprocessTopInclude(src, dir):
2368	pattern = r'#include\s+"([^\n]+)"'
2369	while True:
2370		inc = re.search(pattern, src)
2371		if inc is None:
2372			return src
2373		incFileName = inc.string[inc.start(1):inc.end(1)]
2374		patternIncNamed = r'#include\s+"' + incFileName + '"'
2375		incBody = readFile(os.path.join(dir, incFileName)) if incFileName != 'vk_platform.h' else ''
2376		incBodySanitized = re.sub(pattern, '', incBody)
2377		bodyEndSanitized = re.sub(patternIncNamed, '', src[inc.end(0):])
2378		src = src[0:inc.start(0)] + incBodySanitized + bodyEndSanitized
2379	return src
2380
2381if __name__ == "__main__":
2382	# Read all .h files, with vulkan_core.h first
2383	files			= os.listdir(VULKAN_H_DIR)
2384	files			= [f for f in files if f.endswith(".h")]
2385	files.sort()
2386	files.remove("vulkan_core.h")
2387	first = ["vk_video/vulkan_video_codecs_common.h", "vulkan_core.h"]
2388	files = first + files
2389
2390	src				= ""
2391	for file in files:
2392		src += preprocessTopInclude(readFile(os.path.join(VULKAN_H_DIR,file)), VULKAN_H_DIR)
2393
2394	src = re.sub('\s*//[^\n]*', '', src)
2395	src = re.sub('\n\n', '\n', src)
2396
2397	api				= parseAPI(src)
2398
2399	platformFuncs	= [Function.TYPE_PLATFORM]
2400	instanceFuncs	= [Function.TYPE_INSTANCE]
2401	deviceFuncs		= [Function.TYPE_DEVICE]
2402
2403	dfd										= generateDeviceFeaturesDefs(src)
2404	writeDeviceFeatures						(api, dfd, os.path.join(VULKAN_DIR, "vkDeviceFeatures.inl"))
2405	writeDeviceFeaturesDefaultDeviceDefs	(dfd, os.path.join(VULKAN_DIR, "vkDeviceFeaturesForDefaultDeviceDefs.inl"))
2406	writeDeviceFeaturesContextDecl			(dfd, os.path.join(VULKAN_DIR, "vkDeviceFeaturesForContextDecl.inl"))
2407	writeDeviceFeaturesContextDefs			(dfd, os.path.join(VULKAN_DIR, "vkDeviceFeaturesForContextDefs.inl"))
2408
2409	dpd										= generateDevicePropertiesDefs(src)
2410	writeDeviceProperties					(api, dpd, os.path.join(VULKAN_DIR, "vkDeviceProperties.inl"))
2411
2412	writeDevicePropertiesDefaultDeviceDefs	(dpd, os.path.join(VULKAN_DIR, "vkDevicePropertiesForDefaultDeviceDefs.inl"))
2413	writeDevicePropertiesContextDecl		(dpd, os.path.join(VULKAN_DIR, "vkDevicePropertiesForContextDecl.inl"))
2414	writeDevicePropertiesContextDefs		(dpd, os.path.join(VULKAN_DIR, "vkDevicePropertiesForContextDefs.inl"))
2415
2416	writeHandleType							(api, os.path.join(VULKAN_DIR, "vkHandleType.inl"))
2417	writeBasicTypes							(api, os.path.join(VULKAN_DIR, "vkBasicTypes.inl"))
2418	writeCompositeTypes						(api, os.path.join(VULKAN_DIR, "vkStructTypes.inl"))
2419	writeInterfaceDecl						(api, os.path.join(VULKAN_DIR, "vkVirtualPlatformInterface.inl"),		platformFuncs,	False)
2420	writeInterfaceDecl						(api, os.path.join(VULKAN_DIR, "vkVirtualInstanceInterface.inl"),		instanceFuncs,	False)
2421	writeInterfaceDecl						(api, os.path.join(VULKAN_DIR, "vkVirtualDeviceInterface.inl"),			deviceFuncs,	False)
2422	writeInterfaceDecl						(api, os.path.join(VULKAN_DIR, "vkConcretePlatformInterface.inl"),		platformFuncs,	True)
2423	writeInterfaceDecl						(api, os.path.join(VULKAN_DIR, "vkConcreteInstanceInterface.inl"),		instanceFuncs,	True)
2424	writeInterfaceDecl						(api, os.path.join(VULKAN_DIR, "vkConcreteDeviceInterface.inl"),		deviceFuncs,	True)
2425	writeFunctionPtrTypes					(api, os.path.join(VULKAN_DIR, "vkFunctionPointerTypes.inl"))
2426	writeFunctionPointers					(api, os.path.join(VULKAN_DIR, "vkPlatformFunctionPointers.inl"),		platformFuncs)
2427	writeFunctionPointers					(api, os.path.join(VULKAN_DIR, "vkInstanceFunctionPointers.inl"),		instanceFuncs)
2428	writeFunctionPointers					(api, os.path.join(VULKAN_DIR, "vkDeviceFunctionPointers.inl"),			deviceFuncs)
2429	writeInitFunctionPointers				(api, os.path.join(VULKAN_DIR, "vkInitPlatformFunctionPointers.inl"),	platformFuncs,	lambda f: f.name != "vkGetInstanceProcAddr")
2430	writeInitFunctionPointers				(api, os.path.join(VULKAN_DIR, "vkInitInstanceFunctionPointers.inl"),	instanceFuncs)
2431	writeInitFunctionPointers				(api, os.path.join(VULKAN_DIR, "vkInitDeviceFunctionPointers.inl"),		deviceFuncs)
2432	writeFuncPtrInterfaceImpl				(api, os.path.join(VULKAN_DIR, "vkPlatformDriverImpl.inl"),				platformFuncs,	"PlatformDriver")
2433	writeFuncPtrInterfaceImpl				(api, os.path.join(VULKAN_DIR, "vkInstanceDriverImpl.inl"),				instanceFuncs,	"InstanceDriver")
2434	writeFuncPtrInterfaceImpl				(api, os.path.join(VULKAN_DIR, "vkDeviceDriverImpl.inl"),				deviceFuncs,	"DeviceDriver")
2435	writeStrUtilProto						(api, os.path.join(VULKAN_DIR, "vkStrUtil.inl"))
2436	writeStrUtilImpl						(api, os.path.join(VULKAN_DIR, "vkStrUtilImpl.inl"))
2437	writeRefUtilProto						(api, os.path.join(VULKAN_DIR, "vkRefUtil.inl"))
2438	writeRefUtilImpl						(api, os.path.join(VULKAN_DIR, "vkRefUtilImpl.inl"))
2439	writeStructTraitsImpl					(api, os.path.join(VULKAN_DIR, "vkGetStructureTypeImpl.inl"))
2440	writeNullDriverImpl						(api, os.path.join(VULKAN_DIR, "vkNullDriverImpl.inl"))
2441	writeTypeUtil							(api, os.path.join(VULKAN_DIR, "vkTypeUtil.inl"))
2442	writeSupportedExtenions					(api, os.path.join(VULKAN_DIR, "vkSupportedExtensions.inl"))
2443	writeCoreFunctionalities				(api, os.path.join(VULKAN_DIR, "vkCoreFunctionalities.inl"))
2444	writeExtensionFunctions					(api, os.path.join(VULKAN_DIR, "vkExtensionFunctions.inl"))
2445	writeDeviceFeatures2					(api, os.path.join(VULKAN_DIR, "vkDeviceFeatures2.inl"))
2446	writeMandatoryFeatures					(     os.path.join(VULKAN_DIR, "vkMandatoryFeatures.inl"))
2447	writeExtensionList						(     os.path.join(VULKAN_DIR, "vkInstanceExtensions.inl"),				'INSTANCE')
2448	writeExtensionList						(     os.path.join(VULKAN_DIR, "vkDeviceExtensions.inl"),				'DEVICE')
2449	writeDriverIds							(     os.path.join(VULKAN_DIR, "vkKnownDriverIds.inl"))
2450	writeObjTypeImpl						(api, os.path.join(VULKAN_DIR, "vkObjTypeImpl.inl"))
2451