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