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