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