• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# -*- coding: utf-8 -*-
2
3#-------------------------------------------------------------------------
4# Vulkan CTS
5# ----------
6#
7# Copyright (c) 2015 Google Inc.
8#
9# Licensed under the Apache License, Version 2.0 (the "License");
10# you may not use this file except in compliance with the License.
11# You may obtain a copy of the License at
12#
13#      http://www.apache.org/licenses/LICENSE-2.0
14#
15# Unless required by applicable law or agreed to in writing, software
16# distributed under the License is distributed on an "AS IS" BASIS,
17# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18# See the License for the specific language governing permissions and
19# limitations under the License.
20#
21#-------------------------------------------------------------------------
22
23import os
24import re
25import sys
26import copy
27from itertools import chain
28from collections import OrderedDict
29
30sys.path.append(os.path.join(os.path.dirname(__file__), "..", "..", "..", "scripts"))
31
32from build.common import DEQP_DIR
33from khr_util.format import indentLines, writeInlFile
34
35VULKAN_H	= os.path.join(os.path.dirname(__file__), "src", "vulkan.h.in")
36VULKAN_DIR	= os.path.join(os.path.dirname(__file__), "..", "framework", "vulkan")
37
38INL_HEADER = """\
39/* WARNING: This is auto-generated file. Do not modify, since changes will
40 * be lost! Modify the generating script instead.
41 */\
42"""
43
44DEFINITIONS			= [
45	("VK_API_VERSION_1_0",					"deUint32"),
46	("VK_API_VERSION_1_1",					"deUint32"),
47	("VK_MAX_PHYSICAL_DEVICE_NAME_SIZE",	"size_t"),
48	("VK_MAX_EXTENSION_NAME_SIZE",			"size_t"),
49	("VK_MAX_DRIVER_NAME_SIZE_KHR",			"size_t"),
50	("VK_MAX_DRIVER_INFO_SIZE_KHR",			"size_t"),
51	("VK_UUID_SIZE",						"size_t"),
52	("VK_LUID_SIZE",						"size_t"),
53	("VK_MAX_MEMORY_TYPES",					"size_t"),
54	("VK_MAX_MEMORY_HEAPS",					"size_t"),
55	("VK_MAX_DESCRIPTION_SIZE",				"size_t"),
56	("VK_MAX_DEVICE_GROUP_SIZE",			"size_t"),
57	("VK_ATTACHMENT_UNUSED",				"deUint32"),
58	("VK_SUBPASS_EXTERNAL",					"deUint32"),
59	("VK_QUEUE_FAMILY_IGNORED",				"deUint32"),
60	("VK_QUEUE_FAMILY_EXTERNAL",			"deUint32"),
61	("VK_REMAINING_MIP_LEVELS",				"deUint32"),
62	("VK_REMAINING_ARRAY_LAYERS",			"deUint32"),
63	("VK_WHOLE_SIZE",						"vk::VkDeviceSize"),
64	("VK_TRUE",								"vk::VkBool32"),
65	("VK_FALSE",							"vk::VkBool32"),
66]
67
68PLATFORM_TYPES		= [
69	# VK_KHR_xlib_surface
70	(["Display","*"],						["XlibDisplayPtr"],				"void*"),
71	(["Window"],							["XlibWindow"],					"deUintptr",),
72	(["VisualID"],							["XlibVisualID"],				"deUint32"),
73
74	# VK_KHR_xcb_surface
75	(["xcb_connection_t", "*"],				["XcbConnectionPtr"],			"void*"),
76	(["xcb_window_t"],						["XcbWindow"],					"deUintptr"),
77	(["xcb_visualid_t"],					["XcbVisualid"],				"deUint32"),
78
79	# VK_KHR_wayland_surface
80	(["struct", "wl_display","*"],			["WaylandDisplayPtr"],			"void*"),
81	(["struct", "wl_surface", "*"],			["WaylandSurfacePtr"],			"void*"),
82
83	# VK_KHR_mir_surface
84	(["MirConnection", "*"],				["MirConnectionPtr"],			"void*"),
85	(["MirSurface", "*"],					["MirSurfacePtr"],				"void*"),
86
87	# VK_KHR_android_surface
88	(["ANativeWindow", "*"],				["AndroidNativeWindowPtr"],		"void*"),
89
90	# VK_KHR_win32_surface
91	(["HINSTANCE"],							["Win32InstanceHandle"],		"void*"),
92	(["HWND"],								["Win32WindowHandle"],			"void*"),
93	(["HANDLE"],							["Win32Handle"],				"void*"),
94	(["const", "SECURITY_ATTRIBUTES", "*"],	["Win32SecurityAttributesPtr"],	"const void*"),
95	(["AHardwareBuffer", "*"],				["AndroidHardwareBufferPtr"],	"void*"),
96
97	# VK_EXT_acquire_xlib_display
98	(["RROutput"],							["RROutput"],					"void*")
99]
100
101PLATFORM_TYPE_NAMESPACE	= "pt"
102
103TYPE_SUBSTITUTIONS		= [
104	("uint8_t",		"deUint8"),
105	("uint16_t",	"deUint16"),
106	("uint32_t",	"deUint32"),
107	("uint64_t",	"deUint64"),
108	("int8_t",		"deInt8"),
109	("int16_t",		"deInt16"),
110	("int32_t",		"deInt32"),
111	("int64_t",		"deInt64"),
112	("bool32_t",	"deUint32"),
113	("size_t",		"deUintptr"),
114
115	# Platform-specific
116	("DWORD",		"deUint32"),
117	("HANDLE*",		PLATFORM_TYPE_NAMESPACE + "::" + "Win32Handle*"),
118	("LPCWSTR",		"char*"),
119]
120
121EXTENSION_POSTFIXES				= ["KHR", "EXT", "NV", "NVX", "KHX", "NN", "MVK"]
122EXTENSION_POSTFIXES_STANDARD	= ["KHR"]
123
124def prefixName (prefix, name):
125	name = re.sub(r'([a-z0-9])([A-Z])', r'\1_\2', name[2:])
126	name = re.sub(r'([a-zA-Z])([0-9])', r'\1_\2', name)
127	name = name.upper()
128
129	name = name.replace("YCB_CR_", "YCBCR_")
130	name = name.replace("WIN_32_", "WIN32_")
131	name = name.replace("8_BIT_", "8BIT_")
132	name = name.replace("16_BIT_", "16BIT_")
133	name = name.replace("INT_64_", "INT64_")
134	name = name.replace("D_3_D_12_", "D3D12_")
135	name = name.replace("IOSSURFACE_", "IOS_SURFACE_")
136	name = name.replace("MAC_OS", "MACOS_")
137	name = name.replace("TEXTURE_LOD", "TEXTURE_LOD_")
138	name = name.replace("VIEWPORT_W", "VIEWPORT_W_")
139	name = name.replace("_IDPROPERTIES", "_ID_PROPERTIES")
140	name = name.replace("PHYSICAL_DEVICE_FLOAT_16_INT_8_FEATURES", "PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES")
141
142	return prefix + name
143
144class Version:
145	def __init__ (self, versionTuple):
146		self.major = versionTuple[0]
147		self.minor = versionTuple[1]
148		self.patch = versionTuple[2]
149
150	def getInHex (self):
151		if self.major == 1 and self.minor == 0 and self.patch == 0:
152			return "VK_API_VERSION_1_0"
153		elif self.major == 1 and self.minor == 1 and self.patch == 0:
154			return "VK_API_VERSION_1_1"
155		else:
156			hex = (self.major << 22) | (self.minor << 12) | self.patch
157			return '0x%Xu' % (hex)
158
159	def isStandardVersion (self):
160		if self.patch != 0:
161			return False
162		if self.major != 1:
163			return False
164		if self.minor != 1 and self.minor != 0:
165			return False
166		return True
167
168	def getBestRepresentation (self):
169		if self.isStandardVersion():
170			return self.getInHex()
171		return self.getDefineName()
172
173	def getDefineName (self):
174		return 'VERSION_%d_%d_%d' % (self.major, self.minor, self.patch)
175
176	def __hash__ (self):
177		return (self.major << 22) | (self.minor << 12) | self.patch
178
179	def __eq__ (self, other):
180		return self.major == other.major and self.minor == other.minor and self.patch == other.patch
181
182	def __str__ (self):
183		return self.getBestRepresentation()
184
185
186class Handle:
187	TYPE_DISP		= 0
188	TYPE_NONDISP	= 1
189
190	def __init__ (self, type, name):
191		self.type		= type
192		self.name		= name
193		self.alias		= None
194		self.isAlias	= False
195
196	def getHandleType (self):
197		return prefixName("HANDLE_TYPE_", self.name)
198
199	def checkAliasValidity (self):
200		pass
201
202	def __repr__ (self):
203		return '%s (%s, %s)' % (self.name, self.alias, self.isAlias)
204
205class Definition:
206	def __init__ (self, type, name, value):
207		self.type	= type
208		self.name	= name
209		self.value	= value
210		self.alias	= None
211		self.isAlias	= False
212
213	def __repr__ (self):
214		return '%s = %s (%s)' % (self.name, self.value, self.type)
215
216class Enum:
217	def __init__ (self, name, values):
218		self.name		= name
219		self.values		= values
220		self.alias		= None
221		self.isAlias	= False
222
223	def checkAliasValidity (self):
224		if self.alias != None:
225			if len(self.values) != len(self.alias.values):
226				raise Exception("%s has different number of flags than its alias %s." % (self.name, self.alias.name))
227			for index, value in enumerate(self.values):
228				aliasVal = self.alias.values[index]
229				if value[1] != aliasVal[1] or not (value[0].startswith(aliasVal[0]) or aliasVal[0].startswith(value[0])):
230					raise Exception("Flag %s of %s has different value than %s of %s." % (self.alias.values[index], self.alias.name, value, self.name))
231
232	def __repr__ (self):
233		return '%s (%s) %s' % (self.name, self.alias, self.values)
234
235class Bitfield:
236	def __init__ (self, name, values):
237		self.name		= name
238		self.values		= values
239		self.alias		= None
240		self.isAlias	= False
241
242	def checkAliasValidity (self):
243		if self.alias != None:
244			if len(self.values) != len(self.alias.values):
245				raise Exception("%s has different number of flags than its alias %s." % (self.name, self.alias.name))
246			for index, value in enumerate(self.values):
247				aliasVal = self.alias.values[index]
248				if value[1] != aliasVal[1] or not (value[0].startswith(aliasVal[0]) or aliasVal[0].startswith(value[0])):
249					raise Exception("Flag %s of %s has different value than %s of %s." % (self.alias.values[index], self.alias.name, value, self.name))
250
251	def __repr__ (self):
252		return '%s (%s)' % (self.name, self.alias)
253
254class Variable:
255	def __init__ (self, type, name, arraySize):
256		type		= type.replace('*',' *').replace('&',' &')
257		for src, dst in TYPE_SUBSTITUTIONS:
258			type = type.replace(src, dst)
259		self.type	= type.split(' ')
260		for platformType, substitute, compat in PLATFORM_TYPES:
261			range = self.contains(self.type, platformType)
262			if range != None:
263				self.type = self.type[:range[0]]+[PLATFORM_TYPE_NAMESPACE + '::' + substitute[0]] + substitute[1:] + self.type[range[1]:]
264				break
265		self.name		= name
266		self.arraySize	= arraySize
267
268	def contains(self, big, small):
269		for i in xrange(len(big)-len(small)+1):
270			for j in xrange(len(small)):
271				if big[i+j] != small[j]:
272					break
273			else:
274				return i, i+len(small)
275		return None
276
277	def getType (self):
278		return ' '.join(self.type).replace(' *','*').replace(' &','&')
279
280	def getAsString (self, separator):
281		return '%s%s%s%s' % (self.getType(), separator, self.name, self.arraySize)
282
283	def __repr__ (self):
284		return '<%s> <%s> <%s>' % (self.type, self.name, self.arraySize)
285
286	def __eq__ (self, other):
287		if len(self.type) != len(other.type):
288			return False
289		for index, type in enumerate(self.type):
290			if "*" == type or "&" == type or "const" == type or "volatile" == type:
291				if type != other.type[index]:
292					return False
293			elif type != other.type[index] and \
294				type not in map(lambda ext: other.type[index] + ext, EXTENSION_POSTFIXES_STANDARD) and \
295				other.type[index] not in map(lambda ext: type + ext, EXTENSION_POSTFIXES_STANDARD):
296				return False
297		return self.arraySize == other.arraySize
298
299	def __ne__ (self, other):
300		return not self == other
301
302class CompositeType:
303	CLASS_STRUCT	= 0
304	CLASS_UNION		= 1
305
306	def __init__ (self, typeClass, name, members):
307		self.typeClass	= typeClass
308		self.name		= name
309		self.members	= members
310		self.alias		= None
311		self.isAlias	= False
312
313	def getClassName (self):
314		names = {CompositeType.CLASS_STRUCT: 'struct', CompositeType.CLASS_UNION: 'union'}
315		return names[self.typeClass]
316
317	def checkAliasValidity (self):
318		if self.alias != None:
319			if len(self.members) != len(self.alias.members):
320				raise Exception("%s has different number of members than its alias %s." % (self.name, self.alias.name))
321			for index, member in enumerate(self.members ):
322				break
323				#if member != self.alias.members[index]:
324					#raise Exception("Member %s of %s is different than core member %s in %s." % (self.alias.members[index], self.alias.name, member, self.name))
325					#raise Exception("Member ",str(self.alias.members[index])," of ", str(self.alias.name)," is different than core member ", str(member)," in ", str(self.name),".")
326	def __repr__ (self):
327		return '%s (%s)' % (self.name, self.alias)
328
329class Function:
330	TYPE_PLATFORM		= 0 # Not bound to anything
331	TYPE_INSTANCE		= 1 # Bound to VkInstance
332	TYPE_DEVICE			= 2 # Bound to VkDevice
333
334	def __init__ (self, name, returnType, arguments, apiVersion = None):
335		self.name		= name
336		self.returnType	= returnType
337		self.arguments	= arguments
338		self.alias		= None
339		self.isAlias	= False
340		self.apiVersion	= apiVersion
341
342	def getType (self):
343		# Special functions
344		if self.name == "vkGetInstanceProcAddr":
345			return Function.TYPE_PLATFORM
346		assert len(self.arguments) > 0
347		firstArgType = self.arguments[0].getType()
348		if firstArgType in ["VkInstance", "VkPhysicalDevice"]:
349			return Function.TYPE_INSTANCE
350		elif firstArgType in ["VkDevice", "VkCommandBuffer", "VkQueue"]:
351			return Function.TYPE_DEVICE
352		else:
353			return Function.TYPE_PLATFORM
354
355	def checkAliasValidity (self):
356		if self.alias != None:
357			if len(self.arguments) != len(self.alias.arguments):
358				raise Exception("%s has different number of arguments than its alias %s." % (self.name, self.alias.name))
359			if self.returnType != self.alias.returnType or not (self.returnType.startswith(self.alias.returnType) or self.alias.returnType.startswith(self.returnType)):
360				raise Exception("%s has different return value's type than its alias %s." % (self.name, self.alias.name))
361			for index, argument in enumerate(self.arguments):
362				if argument != self.alias.arguments[index]:
363					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))
364
365	def __repr__ (self):
366		return '%s (%s)' % (self.name, self.alias)
367
368class Extension:
369	def __init__ (self, name, handles, enums, bitfields, compositeTypes, functions, definitions, additionalDefinitions, versionInCore):
370		self.name			= name
371		self.definitions	= definitions
372		self.additionalDefs = additionalDefinitions
373		self.handles		= handles
374		self.enums			= enums
375		self.bitfields		= bitfields
376		self.compositeTypes	= compositeTypes
377		self.functions		= functions
378		self.versionInCore	= versionInCore
379
380	def __repr__ (self):
381		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)
382
383class API:
384	def __init__ (self, definitions, handles, enums, bitfields, compositeTypes, functions, extensions):
385		self.definitions	= definitions
386		self.handles		= handles
387		self.enums			= enums
388		self.bitfields		= bitfields
389		self.compositeTypes	= compositeTypes
390		self.functions		= functions # \note contains extension functions as well
391		self.extensions		= extensions
392
393def readFile (filename):
394	with open(filename, 'rb') as f:
395		return f.read()
396
397IDENT_PTRN	= r'[a-zA-Z_][a-zA-Z0-9_]*'
398TYPE_PTRN	= r'[a-zA-Z_][a-zA-Z0-9_ \t*&]*'
399
400def fixupEnumValues (values):
401	fixed = []
402	for name, value in values:
403		if "_BEGIN_RANGE" in name or "_END_RANGE" in name:
404			continue
405		fixed.append((name, value))
406	return fixed
407
408def getInterfaceName (function):
409	assert function.name[:2] == "vk"
410	return function.name[2].lower() + function.name[3:]
411
412def getFunctionTypeName (function):
413	assert function.name[:2] == "vk"
414	return function.name[2:] + "Func"
415
416def endsWith (str, postfix):
417	return str[-len(postfix):] == postfix
418
419def splitNameExtPostfix (name):
420	knownExtPostfixes = EXTENSION_POSTFIXES
421	for postfix in knownExtPostfixes:
422		if endsWith(name, postfix):
423			return (name[:-len(postfix)], postfix)
424	return (name, "")
425
426def getBitEnumNameForBitfield (bitfieldName):
427	bitfieldName, postfix = splitNameExtPostfix(bitfieldName)
428	assert bitfieldName[-1] == "s"
429	return bitfieldName[:-1] + "Bits" + postfix
430
431def getBitfieldNameForBitEnum (bitEnumName):
432	bitEnumName, postfix = splitNameExtPostfix(bitEnumName)
433	assert bitEnumName[-4:] == "Bits"
434	return bitEnumName[:-4] + "s" + postfix
435
436def parsePreprocDefinedValue (src, name):
437	value = parsePreprocDefinedValueOptional(src, name)
438	if value is None:
439
440		raise Exception("No such definition: %s" % name)
441	return value
442
443def parsePreprocDefinedValueOptional (src, name):
444	definition = re.search(r'#\s*define\s+' + name + r'\s+([^\n]+)\n', src)
445	if definition is None:
446		return None
447	value = definition.group(1).strip()
448	if value == "UINT32_MAX":
449		value = "(~0u)"
450	return value
451
452def parseEnum (name, src):
453	keyValuePtrn	= '(' + IDENT_PTRN + r')\s*=\s*([^\s,}]+)\s*[,}]'
454	matches			= re.findall(keyValuePtrn, src)
455
456	return Enum(name, fixupEnumValues(matches))
457
458# \note Parses raw enums, some are mapped to bitfields later
459def parseEnums (src):
460	matches	= re.findall(r'typedef enum(\s*' + IDENT_PTRN + r')?\s*{([^}]*)}\s*(' + IDENT_PTRN + r')\s*;', src)
461	enums	= []
462	for enumname, contents, typename in matches:
463		enums.append(parseEnum(typename, contents))
464	return enums
465
466
467
468def parseCompositeType (type, name, src):
469	typeNamePtrn	= r'(' + TYPE_PTRN + r')(\s+' + IDENT_PTRN + r')((\[[^\]]+\])*)\s*;'
470	matches			= re.findall(typeNamePtrn, src)
471	members			= [Variable(t.strip(), n.strip(), a.strip()) for t, n, a, _ in matches]
472	return CompositeType(type, name, members)
473
474def parseCompositeTypes (src):
475	typeMap	= { 'struct': CompositeType.CLASS_STRUCT, 'union': CompositeType.CLASS_UNION }
476	matches	= re.findall(r'typedef (struct|union)(\s*' + IDENT_PTRN + r')?\s*{([^}]*)}\s*(' + IDENT_PTRN + r')\s*;', src)
477	types	= []
478	for type, structname, contents, typename in matches:
479		types.append(parseCompositeType(typeMap[type], typename, contents))
480	return types
481
482def parseHandles (src):
483	matches	= re.findall(r'VK_DEFINE(_NON_DISPATCHABLE|)_HANDLE\((' + IDENT_PTRN + r')\)[ \t]*[\n\r]', src)
484	handles	= []
485	typeMap	= {'': Handle.TYPE_DISP, '_NON_DISPATCHABLE': Handle.TYPE_NONDISP}
486	for type, name in matches:
487		handle = Handle(typeMap[type], name)
488		handles.append(handle)
489	return handles
490
491def parseArgList (src):
492	typeNamePtrn	= r'(' + TYPE_PTRN + r')(\s+' + IDENT_PTRN + r')((\[[^\]]+\])*)\s*'
493	args			= []
494	for rawArg in src.split(','):
495		m = re.search(typeNamePtrn, rawArg)
496		args.append(Variable(m.group(1).strip(), m.group(2).strip(), m.group(3)))
497	return args
498
499def removeTypeExtPostfix (name):
500	for extPostfix in EXTENSION_POSTFIXES_STANDARD:
501		if endsWith(name, extPostfix):
502			return name[0:-len(extPostfix)]
503	return None
504
505def populateAliases (objects):
506	objectsByName = {}
507	for object in objects:
508		objectsByName[object.name] = object
509	for object in objects:
510		withoutPostfix = removeTypeExtPostfix(object.name)
511		if withoutPostfix != None and withoutPostfix in objectsByName:
512			objectsByName[withoutPostfix].alias = object
513			object.isAlias = True
514	for object in objects:
515		object.checkAliasValidity()
516
517def populateAliasesWithTypedefs (objects, src):
518	objectsByName = {}
519	for object in objects:
520		objectsByName[object.name] = object
521		ptrn	= r'\s*typedef\s+' + object.name + r'\s+([^;]+)'
522		stash = re.findall(ptrn, src)
523		if len(stash) == 1:
524			objExt = copy.deepcopy(object)
525			objExt.name = stash[0]
526			object.alias = objExt
527			objExt.isAlias = True
528			objects.append(objExt)
529
530
531def removeAliasedValues (enum):
532	valueByName = {}
533	for name, value in enum.values:
534		valueByName[name] = value
535
536	def removeDefExtPostfix (name):
537		for extPostfix in EXTENSION_POSTFIXES:
538			if endsWith(name, "_" + extPostfix):
539				return name[0:-(len(extPostfix)+1)]
540		return None
541
542	newValues = []
543	for name, value in enum.values:
544		withoutPostfix = removeDefExtPostfix(name)
545		if withoutPostfix != None and withoutPostfix in valueByName and valueByName[withoutPostfix] == value:
546			continue
547		newValues.append((name, value))
548	enum.values = newValues
549
550def parseFunctions (src):
551	ptrn		= r'VKAPI_ATTR\s+(' + TYPE_PTRN + ')\s+VKAPI_CALL\s+(' + IDENT_PTRN + r')\s*\(([^)]*)\)\s*;'
552	matches		= re.findall(ptrn, src)
553	functions	= []
554	for returnType, name, argList in matches:
555		functions.append(Function(name.strip(), returnType.strip(), parseArgList(argList)))
556	return functions
557
558def parseFunctionsByVersion (src):
559	ptrnVer10	= 'VK_VERSION_1_0 1'
560	ptrnVer11	= 'VK_VERSION_1_1 1'
561	matchVer10	= re.search(ptrnVer10, src)
562	matchVer11	= re.search(ptrnVer11, src)
563	ptrn		= r'VKAPI_ATTR\s+(' + TYPE_PTRN + ')\s+VKAPI_CALL\s+(' + IDENT_PTRN + r')\s*\(([^)]*)\)\s*;'
564	regPtrn		= re.compile(ptrn)
565	matches		= regPtrn.findall(src, matchVer10.start(), matchVer11.start())
566	functions	= []
567	for returnType, name, argList in matches:
568		functions.append(Function(name.strip(), returnType.strip(), parseArgList(argList), 'VK_VERSION_1_0'))
569	matches		= regPtrn.findall(src, matchVer11.start())
570	for returnType, name, argList in matches:
571		functions.append(Function(name.strip(), returnType.strip(), parseArgList(argList), 'VK_VERSION_1_1'))
572	return functions
573
574def splitByExtension (src):
575	ptrn		= r'#define\s+[A-Z0-9_]+_EXTENSION_NAME\s+"([^"]+)"'
576	match		= "#define\s+("
577	for part in re.finditer(ptrn, src):
578		 match += part.group(1)+"|"
579	match = match[:-1] + ")\s+1"
580	parts = re.split(match, src)
581	# First part is core
582	byExtension	= [(None, parts[0])]
583	for ndx in range(1, len(parts), 2):
584		byExtension.append((parts[ndx], parts[ndx+1]))
585	return byExtension
586
587def parseDefinitions (extensionName, src):
588
589	def skipDefinition (extensionName, definition):
590		if extensionName == None:
591			return True
592		# SPEC_VERSION enums
593		if definition[0].startswith(extensionName.upper()) and definition[1].isdigit():
594			return False
595		if definition[0].startswith(extensionName.upper()):
596			return True
597		if definition[1].isdigit():
598			return True
599		return False
600
601	ptrn		= r'#define\s+([^\s]+)\s+([^\r\n]+)'
602	matches		= re.findall(ptrn, src)
603
604	return [Definition(None, match[0], match[1]) for match in matches if not skipDefinition(extensionName, match)]
605
606def parseExtensions (src, allFunctions, allCompositeTypes, allEnums, allBitfields, allHandles, allDefinitions):
607
608	def getCoreVersion (extensionTuple):
609		if not extensionTuple[0]:
610			return None
611		ptrn		= r'\/\/\s*' + extensionTuple[0] + r'\s+(DEVICE|INSTANCE)\s+([0-9_]+)'
612		coreVersion = re.search(ptrn, extensionTuple[1], re.I)
613		if coreVersion != None:
614			return [coreVersion.group(1)] + [int(number) for number in coreVersion.group(2).split('_')[:3]]
615		return None
616
617	splitSrc				= splitByExtension(src)
618	extensions				= []
619	functionsByName			= {function.name: function for function in allFunctions}
620	compositeTypesByName	= {compType.name: compType for compType in allCompositeTypes}
621	enumsByName				= {enum.name: enum for enum in allEnums}
622	bitfieldsByName			= {bitfield.name: bitfield for bitfield in allBitfields}
623	handlesByName			= {handle.name: handle for handle in allHandles}
624	definitionsByName		= {definition.name: definition for definition in allDefinitions}
625
626	for extensionName, extensionSrc in splitSrc:
627		definitions			= [Definition(type, name, parsePreprocDefinedValueOptional(extensionSrc, name)) for name, type in DEFINITIONS]
628		definitions			= [definition for definition in definitions if definition.value != None]
629		additionalDefinitions = parseDefinitions(extensionName, extensionSrc)
630		handles				= parseHandles(extensionSrc)
631		functions			= parseFunctions(extensionSrc)
632		compositeTypes		= parseCompositeTypes(extensionSrc)
633		rawEnums			= parseEnums(extensionSrc)
634		bitfieldNames		= parseBitfieldNames(extensionSrc)
635		enumBitfieldNames	= [getBitEnumNameForBitfield(name) for name in bitfieldNames]
636		enums				= [enum for enum in rawEnums if enum.name not in enumBitfieldNames]
637
638		extCoreVersion		= getCoreVersion((extensionName, extensionSrc))
639		extFunctions		= [functionsByName[function.name] for function in functions]
640		extCompositeTypes	= [compositeTypesByName[compositeType.name] for compositeType in compositeTypes]
641		extEnums			= [enumsByName[enum.name] for enum in enums]
642		extBitfields		= [bitfieldsByName[bitfieldName] for bitfieldName in bitfieldNames]
643		extHandles			= [handlesByName[handle.name] for handle in handles]
644		extDefinitions		= [definitionsByName[definition.name] for definition in definitions]
645
646		extensions.append(Extension(extensionName, extHandles, extEnums, extBitfields, extCompositeTypes, extFunctions, extDefinitions, additionalDefinitions, extCoreVersion))
647	return extensions
648
649def parseBitfieldNames (src):
650	ptrn		= r'typedef\s+VkFlags\s(' + IDENT_PTRN + r')\s*;'
651	matches		= re.findall(ptrn, src)
652
653	return matches
654
655def parseAPI (src):
656	definitions		= [Definition(type, name, parsePreprocDefinedValue(src, name)) for name, type in DEFINITIONS]
657	handles			= parseHandles(src)
658	rawEnums		= parseEnums(src)
659	bitfieldNames	= parseBitfieldNames(src)
660	enums			= []
661	bitfields		= []
662	bitfieldEnums	= set([getBitEnumNameForBitfield(n) for n in bitfieldNames if getBitEnumNameForBitfield(n) in [enum.name for enum in rawEnums]])
663	compositeTypes	= parseCompositeTypes(src)
664	allFunctions	= parseFunctionsByVersion(src)
665
666	for enum in rawEnums:
667		if enum.name in bitfieldEnums:
668			bitfields.append(Bitfield(getBitfieldNameForBitEnum(enum.name), enum.values))
669		else:
670			enums.append(enum)
671
672	for bitfieldName in bitfieldNames:
673		if not bitfieldName in [bitfield.name for bitfield in bitfields]:
674			# Add empty bitfield
675			bitfields.append(Bitfield(bitfieldName, []))
676
677	# Populate alias fields
678	populateAliasesWithTypedefs(compositeTypes, src)
679	populateAliasesWithTypedefs(enums, src)
680	populateAliasesWithTypedefs(bitfields, src)
681	populateAliases(allFunctions)
682	populateAliases(handles)
683	populateAliases(enums)
684	populateAliases(bitfields)
685	populateAliases(compositeTypes)
686
687
688	for enum in enums:
689		removeAliasedValues(enum)
690
691	extensions			= parseExtensions(src, allFunctions, compositeTypes, enums, bitfields, handles, definitions)
692
693	return API(
694		definitions		= definitions,
695		handles			= handles,
696		enums			= enums,
697		bitfields		= bitfields,
698		compositeTypes	= compositeTypes,
699		functions		= allFunctions,
700		extensions		= extensions)
701
702def splitUniqueAndDuplicatedEntries (handles):
703	listOfUniqueHandles = []
704	duplicates			= OrderedDict()
705	for handle in handles:
706		if handle.alias != None:
707			duplicates[handle.alias] = handle
708		if not handle.isAlias:
709			listOfUniqueHandles.append(handle)
710	return listOfUniqueHandles, duplicates
711
712def writeHandleType (api, filename):
713	uniqeHandles, duplicatedHandles = splitUniqueAndDuplicatedEntries(api.handles)
714
715	def genHandles ():
716		yield "\t%s\t= 0," % uniqeHandles[0].getHandleType()
717		for handle in uniqeHandles[1:]:
718			yield "\t%s," % handle.getHandleType()
719		for duplicate in duplicatedHandles:
720			yield "\t%s\t= %s," % (duplicate.getHandleType(), duplicatedHandles[duplicate].getHandleType())
721		yield "\tHANDLE_TYPE_LAST\t= %s + 1" % (uniqeHandles[-1].getHandleType())
722
723	def genHandlesBlock ():
724		yield "enum HandleType"
725		yield "{"
726
727		for line in indentLines(genHandles()):
728			yield line
729
730		yield "};"
731		yield ""
732
733	writeInlFile(filename, INL_HEADER, genHandlesBlock())
734
735def getEnumValuePrefix (enum):
736	prefix = enum.name[0]
737	for i in range(1, len(enum.name)):
738		if enum.name[i].isupper() and not enum.name[i-1].isupper():
739			prefix += "_"
740		prefix += enum.name[i].upper()
741	return prefix
742
743def parseInt (value):
744	if value[:2] == "0x":
745		return int(value, 16)
746	else:
747		return int(value, 10)
748
749def areEnumValuesLinear (enum):
750	curIndex = 0
751	for name, value in enum.values:
752		if parseInt(value) != curIndex:
753			return False
754		curIndex += 1
755	return True
756
757def genEnumSrc (enum):
758	yield "enum %s" % enum.name
759	yield "{"
760
761	for line in indentLines(["\t%s\t= %s," % v for v in enum.values]):
762		yield line
763
764	if areEnumValuesLinear(enum):
765		yield ""
766		yield "\t%s_LAST" % getEnumValuePrefix(enum)
767
768	yield "};"
769
770def genBitfieldSrc (bitfield):
771	if len(bitfield.values) > 0:
772		yield "enum %s" % getBitEnumNameForBitfield(bitfield.name)
773		yield "{"
774		for line in indentLines(["\t%s\t= %s," % v for v in bitfield.values]):
775			yield line
776		yield "};"
777	yield "typedef deUint32 %s;" % bitfield.name
778
779def genCompositeTypeSrc (type):
780	yield "%s %s" % (type.getClassName(), type.name)
781	yield "{"
782	for line in indentLines(['\t'+m.getAsString('\t')+';' for m in type.members]):
783		yield line
784	yield "};"
785
786def genHandlesSrc (handles):
787	uniqeHandles, duplicatedHandles = splitUniqueAndDuplicatedEntries(handles)
788
789	def genLines (handles):
790		for handle in uniqeHandles:
791			if handle.type == Handle.TYPE_DISP:
792				yield "VK_DEFINE_HANDLE\t(%s,\t%s);" % (handle.name, handle.getHandleType())
793			elif handle.type == Handle.TYPE_NONDISP:
794				yield "VK_DEFINE_NON_DISPATCHABLE_HANDLE\t(%s,\t%s);" % (handle.name, handle.getHandleType())
795
796		for duplicate in duplicatedHandles:
797			if duplicate.type == Handle.TYPE_DISP:
798				yield "VK_DEFINE_HANDLE\t(%s,\t%s);" % (duplicate.name, duplicatedHandles[duplicate].getHandleType())
799			elif duplicate.type == Handle.TYPE_NONDISP:
800				yield "VK_DEFINE_NON_DISPATCHABLE_HANDLE\t(%s,\t%s);" % (duplicate.name, duplicatedHandles[duplicate].getHandleType())
801
802	for line in indentLines(genLines(handles)):
803		yield line
804
805def genDefinitionsSrc (definitions):
806	for line in ["#define %s\t(static_cast<%s>\t(%s))" % (definition.name, definition.type, definition.value) for definition in definitions]:
807		yield line
808
809def genDefinitionsAliasSrc (definitions):
810	for line in ["#define %s\t%s" % (definition.name, definitions[definition].name) for definition in definitions]:
811		if definition.value != definitions[definition].value and definition.value != definitions[definition].name:
812			raise Exception("Value of %s (%s) is different than core definition value %s (%s)." % (definition.name, definition.value, definitions[definition].name, definitions[definition].value))
813		yield line
814
815def writeBasicTypes (api, filename):
816
817	def gen ():
818		definitionsCore, definitionDuplicates = splitUniqueAndDuplicatedEntries(api.definitions)
819
820		for line in indentLines(chain(genDefinitionsSrc(definitionsCore), genDefinitionsAliasSrc(definitionDuplicates))):
821			yield line
822		yield ""
823
824		for line in genHandlesSrc(api.handles):
825			yield line
826		yield ""
827
828		for enum in api.enums:
829			if not enum.isAlias:
830				for line in genEnumSrc(enum):
831					yield line
832			yield ""
833
834		for bitfield in api.bitfields:
835			if not bitfield.isAlias:
836				for line in genBitfieldSrc(bitfield):
837					yield line
838			yield ""
839		for line in indentLines(["VK_DEFINE_PLATFORM_TYPE(%s,\t%s);" % (s[0], c) for n, s, c in PLATFORM_TYPES]):
840			yield line
841
842		for ext in api.extensions:
843			if ext.additionalDefs != None:
844				for definition in ext.additionalDefs:
845					yield "#define " + definition.name + " " + definition.value
846	writeInlFile(filename, INL_HEADER, gen())
847
848def writeCompositeTypes (api, filename):
849	def gen ():
850		for type in api.compositeTypes:
851			type.checkAliasValidity()
852
853			if not type.isAlias:
854				for line in genCompositeTypeSrc(type):
855					yield line
856			yield ""
857
858	writeInlFile(filename, INL_HEADER, gen())
859
860def argListToStr (args):
861	return ", ".join(v.getAsString(' ') for v in args)
862
863def writeInterfaceDecl (api, filename, functionTypes, concrete):
864	def genProtos ():
865		postfix = "" if concrete else " = 0"
866		for function in api.functions:
867			if not function.getType() in functionTypes:
868				continue
869			if not function.isAlias:
870				yield "virtual %s\t%s\t(%s) const%s;" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments), postfix)
871
872	writeInlFile(filename, INL_HEADER, indentLines(genProtos()))
873
874def writeFunctionPtrTypes (api, filename):
875	def genTypes ():
876		for function in api.functions:
877			yield "typedef VKAPI_ATTR %s\t(VKAPI_CALL* %s)\t(%s);" % (function.returnType, getFunctionTypeName(function), argListToStr(function.arguments))
878
879	writeInlFile(filename, INL_HEADER, indentLines(genTypes()))
880
881def writeFunctionPointers (api, filename, functionTypes):
882	def FunctionsYielder ():
883		for function in api.functions:
884			if function.getType() in functionTypes:
885				if function.isAlias:
886					if function.getType() == Function.TYPE_INSTANCE and function.arguments[0].getType() == "VkPhysicalDevice":
887						yield "%s\t%s;" % (getFunctionTypeName(function), getInterfaceName(function))
888				else:
889					yield "%s\t%s;" % (getFunctionTypeName(function), getInterfaceName(function))
890
891	writeInlFile(filename, INL_HEADER, indentLines(FunctionsYielder()))
892
893def writeInitFunctionPointers (api, filename, functionTypes, cond = None):
894	def makeInitFunctionPointers ():
895		for function in api.functions:
896			if function.getType() in functionTypes and (cond == None or cond(function)):
897				interfaceName = getInterfaceName(function)
898				if function.isAlias:
899					if function.getType() == Function.TYPE_INSTANCE and function.arguments[0].getType() == "VkPhysicalDevice":
900						yield "m_vk.%s\t= (%s)\tGET_PROC_ADDR(\"%s\");" % (getInterfaceName(function), getFunctionTypeName(function), function.name)
901				else:
902					yield "m_vk.%s\t= (%s)\tGET_PROC_ADDR(\"%s\");" % (getInterfaceName(function), getFunctionTypeName(function), function.name)
903					if function.alias != None:
904						yield "if (!m_vk.%s)" % (getInterfaceName(function))
905						yield "    m_vk.%s\t= (%s)\tGET_PROC_ADDR(\"%s\");" % (getInterfaceName(function), getFunctionTypeName(function), function.alias.name)
906	lines = [line.replace('    ', '\t') for line in indentLines(makeInitFunctionPointers())]
907	writeInlFile(filename, INL_HEADER, lines)
908
909def writeFuncPtrInterfaceImpl (api, filename, functionTypes, className):
910	def makeFuncPtrInterfaceImpl ():
911		for function in api.functions:
912			if function.getType() in functionTypes and not function.isAlias:
913				yield ""
914				yield "%s %s::%s (%s) const" % (function.returnType, className, getInterfaceName(function), argListToStr(function.arguments))
915				yield "{"
916				if function.name == "vkEnumerateInstanceVersion":
917					yield "	if (m_vk.enumerateInstanceVersion)"
918					yield "		return m_vk.enumerateInstanceVersion(pApiVersion);"
919					yield ""
920					yield "	*pApiVersion = VK_API_VERSION_1_0;"
921					yield "	return VK_SUCCESS;"
922				elif function.getType() == Function.TYPE_INSTANCE and function.arguments[0].getType() == "VkPhysicalDevice" and function.alias != None:
923					yield "	vk::VkPhysicalDeviceProperties props;"
924					yield "	m_vk.getPhysicalDeviceProperties(physicalDevice, &props);"
925					yield "	if (props.apiVersion >= VK_API_VERSION_1_1)"
926					yield "		%sm_vk.%s(%s);" % ("return " if function.returnType != "void" else "", getInterfaceName(function), ", ".join(a.name for a in function.arguments))
927					yield "	else"
928					yield "		%sm_vk.%s(%s);" % ("return " if function.returnType != "void" else "", getInterfaceName(function.alias), ", ".join(a.name for a in function.arguments))
929				else:
930					yield "	%sm_vk.%s(%s);" % ("return " if function.returnType != "void" else "", getInterfaceName(function), ", ".join(a.name for a in function.arguments))
931				yield "}"
932
933	writeInlFile(filename, INL_HEADER, makeFuncPtrInterfaceImpl())
934
935def writeStrUtilProto (api, filename):
936	def makeStrUtilProto ():
937		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]):
938			yield line
939		yield ""
940		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]):
941			yield line
942		yield ""
943		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]):
944			yield line
945		yield ""
946		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]):
947			yield line
948		yield ""
949		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]):
950			yield line
951
952	writeInlFile(filename, INL_HEADER, makeStrUtilProto())
953
954def writeStrUtilImpl (api, filename):
955	def makeStrUtilImpl ():
956		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]):
957			yield line
958
959		yield ""
960		yield "namespace %s" % PLATFORM_TYPE_NAMESPACE
961		yield "{"
962
963		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):
964			yield line
965
966		yield "}"
967
968		for enum in api.enums:
969			if enum.isAlias:
970				continue
971			yield ""
972			yield "const char* get%sName (%s value)" % (enum.name[2:], enum.name)
973			yield "{"
974			yield "\tswitch (value)"
975			yield "\t{"
976			for line in indentLines(["\t\tcase %s:\treturn \"%s\";" % (n, n) for n, v in enum.values] + ["\t\tdefault:\treturn DE_NULL;"]):
977				yield line
978			yield "\t}"
979			yield "}"
980
981		for bitfield in api.bitfields:
982			if bitfield.isAlias:
983				continue
984			yield ""
985			yield "tcu::Format::Bitfield<32> get%sStr (%s value)" % (bitfield.name[2:], bitfield.name)
986			yield "{"
987
988			if len(bitfield.values) > 0:
989				yield "\tstatic const tcu::Format::BitDesc s_desc[] ="
990				yield "\t{"
991				for line in indentLines(["\t\ttcu::Format::BitDesc(%s,\t\"%s\")," % (n, n) for n, v in bitfield.values]):
992					yield line
993				yield "\t};"
994				yield "\treturn tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));"
995			else:
996				yield "\treturn tcu::Format::Bitfield<32>(value, DE_NULL, DE_NULL);"
997			yield "}"
998
999		bitfieldTypeNames = set([bitfield.name for bitfield in api.bitfields])
1000
1001		for type in api.compositeTypes:
1002			if not type.isAlias:
1003				yield ""
1004				yield "std::ostream& operator<< (std::ostream& s, const %s& value)" % type.name
1005				yield "{"
1006				yield "\ts << \"%s = {\\n\";" % type.name
1007				for member in type.members:
1008					memberName	= member.name
1009					valFmt		= None
1010					newLine		= ""
1011					if member.getType() in bitfieldTypeNames:
1012						valFmt = "get%sStr(value.%s)" % (member.getType()[2:], member.name)
1013					elif member.getType() == "const char*" or member.getType() == "char*":
1014						valFmt = "getCharPtrStr(value.%s)" % member.name
1015					elif member.arraySize != '':
1016						if member.name in ["extensionName", "deviceName", "layerName", "description"]:
1017							valFmt = "(const char*)value.%s" % member.name
1018						elif member.getType() == 'char' or member.getType() == 'deUint8':
1019							newLine = "'\\n' << "
1020							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)
1021						else:
1022							if member.name == "memoryTypes" or member.name == "memoryHeaps":
1023								endIter = "DE_ARRAY_BEGIN(value.%s) + value.%sCount" % (member.name, member.name[:-1])
1024							else:
1025								endIter = "DE_ARRAY_END(value.%s)" % member.name
1026							newLine = "'\\n' << "
1027							valFmt	= "tcu::formatArray(DE_ARRAY_BEGIN(value.%s), %s)" % (member.name, endIter)
1028						memberName = member.name
1029					else:
1030						valFmt = "value.%s" % member.name
1031					yield ("\ts << \"\\t%s = \" << " % memberName) + newLine + valFmt + " << '\\n';"
1032				yield "\ts << '}';"
1033				yield "\treturn s;"
1034				yield "}"
1035	writeInlFile(filename, INL_HEADER, makeStrUtilImpl())
1036
1037class ConstructorFunction:
1038	def __init__ (self, type, name, objectType, ifaceArgs, arguments):
1039		self.type		= type
1040		self.name		= name
1041		self.objectType	= objectType
1042		self.ifaceArgs	= ifaceArgs
1043		self.arguments	= arguments
1044
1045def getConstructorFunctions (api):
1046	funcs = []
1047	ifacesDict = {
1048		Function.TYPE_PLATFORM: [Variable("const PlatformInterface&", "vk", "")],
1049		Function.TYPE_INSTANCE: [Variable("const InstanceInterface&", "vk", "")],
1050		Function.TYPE_DEVICE: [Variable("const DeviceInterface&", "vk", "")]
1051	}
1052	for function in api.functions:
1053		if function.isAlias:
1054			continue
1055		if (function.name[:8] == "vkCreate" or function.name == "vkAllocateMemory") and not "createInfoCount" in [a.name for a in function.arguments]:
1056			if function.name == "vkCreateDisplayModeKHR":
1057				continue # No way to delete display modes (bug?)
1058
1059			# \todo [pyry] Rather hacky
1060			ifaceArgs = ifacesDict[function.getType()]
1061			if function.name == "vkCreateDevice":
1062				ifaceArgs = [Variable("const PlatformInterface&", "vkp", ""), Variable("VkInstance", "instance", "")] + ifaceArgs
1063
1064			assert (function.arguments[-2].type == ["const", "VkAllocationCallbacks", "*"])
1065
1066			objectType	= function.arguments[-1].type[0] #not getType() but type[0] on purpose
1067			arguments	= function.arguments[:-1]
1068			funcs.append(ConstructorFunction(function.getType(), getInterfaceName(function), objectType, ifaceArgs, arguments))
1069	return funcs
1070
1071def addVersionDefines(versionSpectrum):
1072	output = ["#define " + ver.getDefineName() + " " + ver.getInHex() for ver in versionSpectrum if not ver.isStandardVersion()]
1073	return output
1074
1075def removeVersionDefines(versionSpectrum):
1076	output = ["#undef " + ver.getDefineName() for ver in versionSpectrum if not ver.isStandardVersion()]
1077	return output
1078
1079def writeRefUtilProto (api, filename):
1080	functions = getConstructorFunctions(api)
1081
1082	def makeRefUtilProto ():
1083		unindented = []
1084		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]):
1085			yield line
1086
1087	writeInlFile(filename, INL_HEADER, makeRefUtilProto())
1088
1089def writeRefUtilImpl (api, filename):
1090	functions = getConstructorFunctions(api)
1091
1092	def makeRefUtilImpl ():
1093		yield "namespace refdetails"
1094		yield "{"
1095		yield ""
1096
1097		for function in api.functions:
1098			if function.getType() == Function.TYPE_DEVICE \
1099			and (function.name[:9] == "vkDestroy" or function.name == "vkFreeMemory") \
1100			and not function.name == "vkDestroyDevice" \
1101			and not function.isAlias:
1102				objectType = function.arguments[-2].getType()
1103				yield "template<>"
1104				yield "void Deleter<%s>::operator() (%s obj) const" % (objectType, objectType)
1105				yield "{"
1106				yield "\tm_deviceIface->%s(m_device, obj, m_allocator);" % (getInterfaceName(function))
1107				yield "}"
1108				yield ""
1109
1110		yield "} // refdetails"
1111		yield ""
1112
1113		dtorDict = {
1114			Function.TYPE_PLATFORM: "object",
1115			Function.TYPE_INSTANCE: "instance",
1116			Function.TYPE_DEVICE: "device"
1117		}
1118
1119		for function in functions:
1120			deleterArgsString = ''
1121			if function.name == "createDevice":
1122				# createDevice requires two additional parameters to setup VkDevice deleter
1123				deleterArgsString = "vkp, instance, object, " +  function.arguments[-1].name
1124			else:
1125				deleterArgsString = "vk, %s, %s" % (dtorDict[function.type], function.arguments[-1].name)
1126
1127			yield "Move<%s> %s (%s)" % (function.objectType, function.name, argListToStr(function.ifaceArgs + function.arguments))
1128			yield "{"
1129			yield "\t%s object = 0;" % function.objectType
1130			yield "\tVK_CHECK(vk.%s(%s));" % (function.name, ", ".join([a.name for a in function.arguments] + ["&object"]))
1131			yield "\treturn Move<%s>(check<%s>(object), Deleter<%s>(%s));" % (function.objectType, function.objectType, function.objectType, deleterArgsString)
1132			yield "}"
1133			yield ""
1134
1135	writeInlFile(filename, INL_HEADER, makeRefUtilImpl())
1136
1137def writeStructTraitsImpl (api, filename):
1138	def gen ():
1139		for type in api.compositeTypes:
1140			if type.getClassName() == "struct" and type.members[0].name == "sType" and not type.isAlias:
1141				yield "template<> VkStructureType getStructureType<%s> (void)" % type.name
1142				yield "{"
1143				yield "\treturn %s;" % prefixName("VK_STRUCTURE_TYPE_", type.name)
1144				yield "}"
1145				yield ""
1146
1147	writeInlFile(filename, INL_HEADER, gen())
1148
1149def writeNullDriverImpl (api, filename):
1150	def genNullDriverImpl ():
1151		specialFuncNames	= [
1152				"vkCreateGraphicsPipelines",
1153				"vkCreateComputePipelines",
1154				"vkGetInstanceProcAddr",
1155				"vkGetDeviceProcAddr",
1156				"vkEnumeratePhysicalDevices",
1157				"vkEnumerateInstanceExtensionProperties",
1158				"vkEnumerateDeviceExtensionProperties",
1159				"vkGetPhysicalDeviceFeatures",
1160				"vkGetPhysicalDeviceFeatures2KHR",
1161				"vkGetPhysicalDeviceProperties",
1162				"vkGetPhysicalDeviceProperties2KHR",
1163				"vkGetPhysicalDeviceQueueFamilyProperties",
1164				"vkGetPhysicalDeviceMemoryProperties",
1165				"vkGetPhysicalDeviceFormatProperties",
1166				"vkGetPhysicalDeviceImageFormatProperties",
1167				"vkGetDeviceQueue",
1168				"vkGetBufferMemoryRequirements",
1169				"vkGetBufferMemoryRequirements2KHR",
1170				"vkGetImageMemoryRequirements",
1171				"vkGetImageMemoryRequirements2KHR",
1172				"vkAllocateMemory",
1173				"vkMapMemory",
1174				"vkUnmapMemory",
1175				"vkAllocateDescriptorSets",
1176				"vkFreeDescriptorSets",
1177				"vkResetDescriptorPool",
1178				"vkAllocateCommandBuffers",
1179				"vkFreeCommandBuffers",
1180				"vkCreateDisplayModeKHR",
1181				"vkCreateSharedSwapchainsKHR",
1182				"vkGetPhysicalDeviceExternalBufferPropertiesKHR",
1183				"vkGetPhysicalDeviceImageFormatProperties2KHR",
1184				"vkGetMemoryAndroidHardwareBufferANDROID",
1185			]
1186
1187		coreFunctions		= [f for f in api.functions if not f.isAlias]
1188		specialFuncs		= [f for f in coreFunctions if f.name in specialFuncNames]
1189		createFuncs			= [f for f in coreFunctions if (f.name[:8] == "vkCreate" or f.name == "vkAllocateMemory") and not f in specialFuncs]
1190		destroyFuncs		= [f for f in coreFunctions if (f.name[:9] == "vkDestroy" or f.name == "vkFreeMemory") and not f in specialFuncs]
1191		dummyFuncs			= [f for f in coreFunctions if f not in specialFuncs + createFuncs + destroyFuncs]
1192
1193		def getHandle (name):
1194			for handle in api.handles:
1195				if handle.name == name[0]:
1196					return handle
1197			raise Exception("No such handle: %s" % name)
1198
1199		for function in createFuncs:
1200			objectType	= function.arguments[-1].type[:-1]
1201			argsStr		= ", ".join([a.name for a in function.arguments[:-1]])
1202
1203			yield "VKAPI_ATTR %s VKAPI_CALL %s (%s)" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments))
1204			yield "{"
1205			yield "\tDE_UNREF(%s);" % function.arguments[-2].name
1206
1207			if getHandle(objectType).type == Handle.TYPE_NONDISP:
1208				yield "\tVK_NULL_RETURN((*%s = allocateNonDispHandle<%s, %s>(%s)));" % (function.arguments[-1].name, objectType[0][2:], objectType[0], argsStr)
1209			else:
1210				yield "\tVK_NULL_RETURN((*%s = allocateHandle<%s, %s>(%s)));" % (function.arguments[-1].name, objectType[0][2:], objectType[0], argsStr)
1211			yield "}"
1212			yield ""
1213
1214		for function in destroyFuncs:
1215			objectArg	= function.arguments[-2]
1216
1217			yield "VKAPI_ATTR %s VKAPI_CALL %s (%s)" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments))
1218			yield "{"
1219			for arg in function.arguments[:-2]:
1220				yield "\tDE_UNREF(%s);" % arg.name
1221
1222			if getHandle(objectArg.type).type == Handle.TYPE_NONDISP:
1223				yield "\tfreeNonDispHandle<%s, %s>(%s, %s);" % (objectArg.getType()[2:], objectArg.getType(), objectArg.name, function.arguments[-1].name)
1224			else:
1225				yield "\tfreeHandle<%s, %s>(%s, %s);" % (objectArg.getType()[2:], objectArg.getType(), objectArg.name, function.arguments[-1].name)
1226
1227			yield "}"
1228			yield ""
1229
1230		for function in dummyFuncs:
1231			yield "VKAPI_ATTR %s VKAPI_CALL %s (%s)" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments))
1232			yield "{"
1233			for arg in function.arguments:
1234				yield "\tDE_UNREF(%s);" % arg.name
1235			if function.returnType != "void":
1236				yield "\treturn VK_SUCCESS;"
1237			yield "}"
1238			yield ""
1239
1240		def genFuncEntryTable (type, name):
1241			funcs = [f for f in api.functions if f.getType() == type]
1242			refFuncs = {}
1243			for f in api.functions:
1244				if f.alias != None:
1245					refFuncs[f.alias] = f
1246
1247			yield "static const tcu::StaticFunctionLibrary::Entry %s[] =" % name
1248			yield "{"
1249			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]):
1250				yield line
1251			yield "};"
1252			yield ""
1253
1254		# Func tables
1255		for line in genFuncEntryTable(Function.TYPE_PLATFORM, "s_platformFunctions"):
1256			yield line
1257
1258		for line in genFuncEntryTable(Function.TYPE_INSTANCE, "s_instanceFunctions"):
1259			yield line
1260
1261		for line in genFuncEntryTable(Function.TYPE_DEVICE, "s_deviceFunctions"):
1262			yield line
1263
1264	writeInlFile(filename, INL_HEADER, genNullDriverImpl())
1265
1266def writeTypeUtil (api, filename):
1267	# Structs filled by API queries are not often used in test code
1268	QUERY_RESULT_TYPES = set([
1269			"VkPhysicalDeviceFeatures",
1270			"VkPhysicalDeviceLimits",
1271			"VkFormatProperties",
1272			"VkImageFormatProperties",
1273			"VkPhysicalDeviceSparseProperties",
1274			"VkQueueFamilyProperties",
1275			"VkMemoryType",
1276			"VkMemoryHeap",
1277		])
1278	COMPOSITE_TYPES = set([t.name for t in api.compositeTypes if not t.isAlias])
1279
1280	def isSimpleStruct (type):
1281		def hasArrayMember (type):
1282			for member in type.members:
1283				if member.arraySize != '':
1284					return True
1285			return False
1286
1287		def hasCompositeMember (type):
1288			for member in type.members:
1289				if member.getType() in COMPOSITE_TYPES:
1290					return True
1291			return False
1292
1293		return type.typeClass == CompositeType.CLASS_STRUCT and \
1294		type.members[0].getType() != "VkStructureType" and \
1295		not type.name in QUERY_RESULT_TYPES and \
1296		not hasArrayMember(type) and \
1297		not hasCompositeMember(type)
1298
1299	def gen ():
1300		for type in api.compositeTypes:
1301			if not isSimpleStruct(type) or type.isAlias:
1302				continue
1303
1304			yield ""
1305			yield "inline %s make%s (%s)" % (type.name, type.name[2:], argListToStr(type.members))
1306			yield "{"
1307			yield "\t%s res;" % type.name
1308			for line in indentLines(["\tres.%s\t= %s;" % (m.name, m.name) for m in type.members]):
1309				yield line
1310			yield "\treturn res;"
1311			yield "}"
1312
1313	writeInlFile(filename, INL_HEADER, gen())
1314
1315def writeSupportedExtenions(api, filename):
1316
1317	def writeExtensionsForVersions(map):
1318		result = []
1319		for version in map:
1320			result.append("	if (coreVersion >= " + str(version) + ")")
1321			result.append("	{")
1322			for extension in map[version]:
1323				result.append('		dst.push_back("' + extension.name + '");')
1324			result.append("	}")
1325
1326		return result
1327
1328	instanceMap		= {}
1329	deviceMap		= {}
1330	versionSet		= set()
1331
1332	for ext in api.extensions:
1333		if ext.versionInCore != None:
1334			if ext.versionInCore[0] == 'INSTANCE':
1335				list = instanceMap.get(Version(ext.versionInCore[1:]))
1336				instanceMap[Version(ext.versionInCore[1:])] = list + [ext] if list else [ext]
1337			else:
1338				list = deviceMap.get(Version(ext.versionInCore[1:]))
1339				deviceMap[Version(ext.versionInCore[1:])] = list + [ext] if list else [ext]
1340			versionSet.add(Version(ext.versionInCore[1:]))
1341
1342	lines = addVersionDefines(versionSet) + [
1343	"",
1344	"void getCoreDeviceExtensionsImpl (deUint32 coreVersion, ::std::vector<const char*>&%s)" % (" dst" if len(deviceMap) != 0 else ""),
1345	"{"] + writeExtensionsForVersions(deviceMap) + [
1346	"}",
1347	"",
1348	"void getCoreInstanceExtensionsImpl (deUint32 coreVersion, ::std::vector<const char*>&%s)" % (" dst" if len(instanceMap) != 0 else ""),
1349	"{"] + writeExtensionsForVersions(instanceMap) + [
1350	"}",
1351	""] + removeVersionDefines(versionSet)
1352	writeInlFile(filename, INL_HEADER, lines)
1353
1354def writeCoreFunctionalities(api, filename):
1355	functionOriginValues = ["FUNCTIONORIGIN_PLATFORM", "FUNCTIONORIGIN_INSTANCE", "FUNCTIONORIGIN_DEVICE"]
1356
1357	lines = addVersionDefines([Version((1, 0, 0)), Version((1, 1, 0))]) + [
1358	"",
1359	'enum FunctionOrigin', '{'] + [line for line in indentLines([
1360	'\t' + functionOriginValues[0] + '\t= 0,',
1361	'\t' + functionOriginValues[1] + ',',
1362	'\t' + functionOriginValues[2]])] + [
1363	"};",
1364	"",
1365	"typedef ::std::pair<const char*, FunctionOrigin> FunctionInfo;",
1366	"typedef ::std::vector<FunctionInfo> FunctionInfosList;",
1367	"typedef ::std::map<deUint32, FunctionInfosList> ApisMap;",
1368	"",
1369	"void initApisMap (ApisMap& apis)",
1370	"{",
1371	"	apis.clear();",
1372	"	apis.insert(::std::pair<deUint32, FunctionInfosList>(" + str(Version((1, 0, 0))) + ", FunctionInfosList()));",
1373	"	apis.insert(::std::pair<deUint32, FunctionInfosList>(" + str(Version((1, 1, 0))) + ", FunctionInfosList()));",
1374	""]
1375
1376	def list10Funcs ():
1377		for fun in api.functions:
1378			if fun.apiVersion == 'VK_VERSION_1_0':
1379				insert = '	apis[' + str(Version((1, 0, 0))) + '].push_back(FunctionInfo("' + fun.name + '",\t' + functionOriginValues[fun.getType()] + '));'
1380				yield insert
1381
1382	def listAllFuncs ():
1383		for fun in api.extensions[0].functions:
1384			insert = '	apis[' + str(Version((1, 1, 0))) + '].push_back(FunctionInfo("' + fun.name + '",\t' + functionOriginValues[fun.getType()] + '));'
1385			yield insert
1386
1387	lines = lines + [line for line in indentLines(list10Funcs())]
1388	lines.append("")
1389	lines = lines + [line for line in indentLines(listAllFuncs())]
1390
1391	lines.append("}")
1392	lines.append("")
1393	lines = lines + removeVersionDefines([Version((1, 0, 0)), Version((1, 1, 0))])
1394
1395	writeInlFile(filename, INL_HEADER, lines)
1396
1397if __name__ == "__main__":
1398	src				= readFile(VULKAN_H)
1399	api				= parseAPI(src)
1400
1401	platformFuncs	= [Function.TYPE_PLATFORM]
1402	instanceFuncs	= [Function.TYPE_INSTANCE]
1403	deviceFuncs		= [Function.TYPE_DEVICE]
1404
1405	writeHandleType				(api, os.path.join(VULKAN_DIR, "vkHandleType.inl"))
1406	writeBasicTypes				(api, os.path.join(VULKAN_DIR, "vkBasicTypes.inl"))
1407	writeCompositeTypes			(api, os.path.join(VULKAN_DIR, "vkStructTypes.inl"))
1408	writeInterfaceDecl			(api, os.path.join(VULKAN_DIR, "vkVirtualPlatformInterface.inl"),		platformFuncs,	False)
1409	writeInterfaceDecl			(api, os.path.join(VULKAN_DIR, "vkVirtualInstanceInterface.inl"),		instanceFuncs,	False)
1410	writeInterfaceDecl			(api, os.path.join(VULKAN_DIR, "vkVirtualDeviceInterface.inl"),			deviceFuncs,	False)
1411	writeInterfaceDecl			(api, os.path.join(VULKAN_DIR, "vkConcretePlatformInterface.inl"),		platformFuncs,	True)
1412	writeInterfaceDecl			(api, os.path.join(VULKAN_DIR, "vkConcreteInstanceInterface.inl"),		instanceFuncs,	True)
1413	writeInterfaceDecl			(api, os.path.join(VULKAN_DIR, "vkConcreteDeviceInterface.inl"),		deviceFuncs,	True)
1414	writeFunctionPtrTypes		(api, os.path.join(VULKAN_DIR, "vkFunctionPointerTypes.inl"))
1415	writeFunctionPointers		(api, os.path.join(VULKAN_DIR, "vkPlatformFunctionPointers.inl"),		platformFuncs)
1416	writeFunctionPointers		(api, os.path.join(VULKAN_DIR, "vkInstanceFunctionPointers.inl"),		instanceFuncs)
1417	writeFunctionPointers		(api, os.path.join(VULKAN_DIR, "vkDeviceFunctionPointers.inl"),			deviceFuncs)
1418	writeInitFunctionPointers	(api, os.path.join(VULKAN_DIR, "vkInitPlatformFunctionPointers.inl"),	platformFuncs,	lambda f: f.name != "vkGetInstanceProcAddr")
1419	writeInitFunctionPointers	(api, os.path.join(VULKAN_DIR, "vkInitInstanceFunctionPointers.inl"),	instanceFuncs)
1420	writeInitFunctionPointers	(api, os.path.join(VULKAN_DIR, "vkInitDeviceFunctionPointers.inl"),		deviceFuncs)
1421	writeFuncPtrInterfaceImpl	(api, os.path.join(VULKAN_DIR, "vkPlatformDriverImpl.inl"),				platformFuncs,	"PlatformDriver")
1422	writeFuncPtrInterfaceImpl	(api, os.path.join(VULKAN_DIR, "vkInstanceDriverImpl.inl"),				instanceFuncs,	"InstanceDriver")
1423	writeFuncPtrInterfaceImpl	(api, os.path.join(VULKAN_DIR, "vkDeviceDriverImpl.inl"),				deviceFuncs,	"DeviceDriver")
1424	writeStrUtilProto			(api, os.path.join(VULKAN_DIR, "vkStrUtil.inl"))
1425	writeStrUtilImpl			(api, os.path.join(VULKAN_DIR, "vkStrUtilImpl.inl"))
1426	writeRefUtilProto			(api, os.path.join(VULKAN_DIR, "vkRefUtil.inl"))
1427	writeRefUtilImpl			(api, os.path.join(VULKAN_DIR, "vkRefUtilImpl.inl"))
1428	writeStructTraitsImpl		(api, os.path.join(VULKAN_DIR, "vkGetStructureTypeImpl.inl"))
1429	writeNullDriverImpl			(api, os.path.join(VULKAN_DIR, "vkNullDriverImpl.inl"))
1430	writeTypeUtil				(api, os.path.join(VULKAN_DIR, "vkTypeUtil.inl"))
1431	writeSupportedExtenions		(api, os.path.join(VULKAN_DIR, "vkSupportedExtensions.inl"))
1432	writeCoreFunctionalities	(api, os.path.join(VULKAN_DIR, "vkCoreFunctionalities.inl"))
1433