Home | History | Annotate | Download | only in scripts
      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 
     23 import os
     24 import re
     25 import sys
     26 
     27 sys.path.append(os.path.join(os.path.dirname(__file__), "..", "..", "..", "scripts"))
     28 
     29 from build.common import DEQP_DIR
     30 from khr_util.format import indentLines, writeInlFile
     31 
     32 VULKAN_H	= os.path.join(os.path.dirname(__file__), "src", "vulkan.h.in")
     33 VULKAN_DIR	= os.path.join(os.path.dirname(__file__), "..", "framework", "vulkan")
     34 
     35 INL_HEADER = """\
     36 /* WARNING: This is auto-generated file. Do not modify, since changes will
     37  * be lost! Modify the generating script instead.
     38  */\
     39 """
     40 
     41 PLATFORM_FUNCTIONS	= [
     42 	"vkCreateInstance",
     43 	"vkGetInstanceProcAddr",
     44 	"vkEnumerateInstanceExtensionProperties",
     45 	"vkEnumerateInstanceLayerProperties",
     46 ]
     47 INSTANCE_FUNCTIONS	= [
     48 	"vkDestroyInstance",
     49 	"vkEnumeratePhysicalDevices",
     50 	"vkGetPhysicalDeviceFeatures",
     51 	"vkGetPhysicalDeviceFormatProperties",
     52 	"vkGetPhysicalDeviceImageFormatProperties",
     53 	"vkGetPhysicalDeviceSparseImageFormatProperties",
     54 	"vkGetPhysicalDeviceLimits",
     55 	"vkGetPhysicalDeviceProperties",
     56 	"vkGetPhysicalDeviceQueueFamilyProperties",
     57 	"vkGetPhysicalDeviceMemoryProperties",
     58 	"vkEnumerateDeviceExtensionProperties",
     59 	"vkEnumerateDeviceLayerProperties",
     60 	"vkCreateDevice",
     61 	"vkGetDeviceProcAddr",
     62 
     63 	# VK_KHR_surface
     64 	"vkDestroySurfaceKHR",
     65 	"vkGetPhysicalDeviceSurfaceSupportKHR",
     66 	"vkGetPhysicalDeviceSurfaceCapabilitiesKHR",
     67 	"vkGetPhysicalDeviceSurfaceFormatsKHR",
     68 	"vkGetPhysicalDeviceSurfacePresentModesKHR",
     69 
     70 	# VK_KHR_display
     71 	"vkGetPhysicalDeviceDisplayPropertiesKHR",
     72 	"vkGetPhysicalDeviceDisplayPlanePropertiesKHR",
     73 	"vkGetDisplayPlaneSupportedDisplaysKHR",
     74 	"vkGetDisplayModePropertiesKHR",
     75 	"vkCreateDisplayModeKHR",
     76 	"vkGetDisplayPlaneCapabilitiesKHR",
     77 	"vkCreateDisplayPlaneSurfaceKHR",
     78 
     79 	# VK_KHR_xlib_surface
     80 	"vkCreateXlibSurfaceKHR",
     81 	"vkGetPhysicalDeviceXlibPresentationSupportKHR",
     82 
     83 	# VK_KHR_xcb_surface
     84 	"vkCreateXcbSurfaceKHR",
     85 	"vkGetPhysicalDeviceXcbPresentationSupportKHR",
     86 
     87 	# VK_KHR_wayland_surface
     88 	"vkCreateWaylandSurfaceKHR",
     89 	"vkGetPhysicalDeviceWaylandPresentationSupportKHR",
     90 
     91 	# VK_KHR_mir_surface
     92 	"vkCreateMirSurfaceKHR",
     93 	"vkGetPhysicalDeviceMirPresentationSupportKHR",
     94 
     95 	# VK_KHR_android_surface
     96 	"vkCreateAndroidSurfaceKHR",
     97 
     98 	# VK_KHR_win32_surface
     99 	"vkCreateWin32SurfaceKHR",
    100 	"vkGetPhysicalDeviceWin32PresentationSupportKHR",
    101 
    102 	# VK_KHR_get_physical_device_properties2
    103 	"vkGetPhysicalDeviceFeatures2KHR",
    104 	"vkGetPhysicalDeviceProperties2KHR",
    105 	"vkGetPhysicalDeviceFormatProperties2KHR",
    106 	"vkGetPhysicalDeviceQueueFamilyProperties2KHR",
    107 	"vkGetPhysicalDeviceImageFormatProperties2KHR",
    108 	"vkGetPhysicalDeviceMemoryProperties2KHR",
    109 	"vkGetPhysicalDeviceSparseImageFormatProperties2KHR",
    110 
    111 	# VK_EXT_debug_report
    112 	"vkCreateDebugReportCallbackEXT",
    113 	"vkDestroyDebugReportCallbackEXT",
    114 	"vkDebugReportMessageEXT",
    115 
    116 	# VK_NV_external_memory_capabilities
    117 	"vkGetPhysicalDeviceExternalImageFormatPropertiesNV",
    118 
    119 	# VK_KHR_get_surface_capabilities2
    120 	"vkGetPhysicalDeviceSurfaceCapabilities2KHR",
    121 	"vkGetPhysicalDeviceSurfaceFormats2KHR",
    122 ]
    123 
    124 DEFINITIONS			= [
    125 	("VK_API_VERSION",						"deUint32"),
    126 	("VK_MAX_PHYSICAL_DEVICE_NAME_SIZE",	"size_t"),
    127 	("VK_MAX_EXTENSION_NAME_SIZE",			"size_t"),
    128 	("VK_UUID_SIZE",						"size_t"),
    129 	("VK_MAX_MEMORY_TYPES",					"size_t"),
    130 	("VK_MAX_MEMORY_HEAPS",					"size_t"),
    131 	("VK_MAX_DESCRIPTION_SIZE",				"size_t"),
    132 	("VK_ATTACHMENT_UNUSED",				"deUint32"),
    133 	("VK_SUBPASS_EXTERNAL",					"deUint32"),
    134 	("VK_QUEUE_FAMILY_IGNORED",				"deUint32"),
    135 	("VK_REMAINING_MIP_LEVELS",				"deUint32"),
    136 	("VK_REMAINING_ARRAY_LAYERS",			"deUint32"),
    137 	("VK_WHOLE_SIZE",						"vk::VkDeviceSize"),
    138 	("VK_TRUE",								"vk::VkBool32"),
    139 	("VK_FALSE",							"vk::VkBool32"),
    140 ]
    141 
    142 PLATFORM_TYPES		= [
    143 	# VK_KHR_xlib_surface
    144 	("Display*",					"XlibDisplayPtr",				"void*"),
    145 	("Window",						"XlibWindow",					"deUintptr",),
    146 	("VisualID",					"XlibVisualID",					"deUint32"),
    147 
    148 	# VK_KHR_xcb_surface
    149 	("xcb_connection_t*",			"XcbConnectionPtr",				"void*"),
    150 	("xcb_window_t",				"XcbWindow",					"deUintptr"),
    151 	("xcb_visualid_t",				"XcbVisualid",					"deUint32"),
    152 
    153 	# VK_KHR_wayland_surface
    154 	("struct wl_display*",			"WaylandDisplayPtr",			"void*"),
    155 	("struct wl_surface*",			"WaylandSurfacePtr",			"void*"),
    156 
    157 	# VK_KHR_mir_surface
    158 	("MirConnection*",				"MirConnectionPtr",				"void*"),
    159 	("MirSurface*",					"MirSurfacePtr",				"void*"),
    160 
    161 	# VK_KHR_android_surface
    162 	("ANativeWindow*",				"AndroidNativeWindowPtr",		"void*"),
    163 
    164 	# VK_KHR_win32_surface
    165 	("HINSTANCE",					"Win32InstanceHandle",			"void*"),
    166 	("HWND",						"Win32WindowHandle",			"void*"),
    167 	("HANDLE",						"Win32Handle",					"void*"),
    168 	("const SECURITY_ATTRIBUTES*",	"Win32SecurityAttributesPtr",	"const void*"),
    169 ]
    170 PLATFORM_TYPE_NAMESPACE	= "pt"
    171 TYPE_SUBSTITUTIONS		= [
    172 	("uint8_t",		"deUint8"),
    173 	("uint16_t",	"deUint16"),
    174 	("uint32_t",	"deUint32"),
    175 	("uint64_t",	"deUint64"),
    176 	("int8_t",		"deInt8"),
    177 	("int16_t",		"deInt16"),
    178 	("int32_t",		"deInt32"),
    179 	("int64_t",		"deInt64"),
    180 	("bool32_t",	"deUint32"),
    181 	("size_t",		"deUintptr"),
    182 
    183 	# Platform-specific
    184 	("DWORD",		"deUint32"),
    185 	("HANDLE*",		PLATFORM_TYPE_NAMESPACE + "::" + "Win32Handle*")
    186 ]
    187 
    188 EXTENSION_POSTFIXES		= ["KHR", "EXT", "NV", "NVX", "KHX"]
    189 
    190 class Handle:
    191 	TYPE_DISP		= 0
    192 	TYPE_NONDISP	= 1
    193 
    194 	def __init__ (self, type, name):
    195 		self.type	= type
    196 		self.name	= name
    197 
    198 	def getHandleType (self):
    199 		name = re.sub(r'([a-z])([A-Z])', r'\1_\2', self.name)
    200 		return "HANDLE_TYPE_" + name[3:].upper()
    201 
    202 class Enum:
    203 	def __init__ (self, name, values):
    204 		self.name	= name
    205 		self.values	= values
    206 
    207 class Bitfield:
    208 	def __init__ (self, name, values):
    209 		self.name	= name
    210 		self.values	= values
    211 
    212 class Variable:
    213 	def __init__ (self, type, name, arraySize = None):
    214 		self.type		= type
    215 		self.name		= name
    216 		self.arraySize	= arraySize
    217 
    218 class CompositeType:
    219 	CLASS_STRUCT	= 0
    220 	CLASS_UNION		= 1
    221 
    222 	def __init__ (self, typeClass, name, members):
    223 		self.typeClass	= typeClass
    224 		self.name		= name
    225 		self.members	= members
    226 
    227 	def getClassName (self):
    228 		names = {CompositeType.CLASS_STRUCT: 'struct', CompositeType.CLASS_UNION: 'union'}
    229 		return names[self.typeClass]
    230 
    231 class Function:
    232 	TYPE_PLATFORM		= 0 # Not bound to anything
    233 	TYPE_INSTANCE		= 1 # Bound to VkInstance
    234 	TYPE_DEVICE			= 2 # Bound to VkDevice
    235 
    236 	def __init__ (self, name, returnType, arguments):
    237 		self.name		= name
    238 		self.returnType	= returnType
    239 		self.arguments	= arguments
    240 
    241 	def getType (self):
    242 		if self.name in PLATFORM_FUNCTIONS:
    243 			return Function.TYPE_PLATFORM
    244 		elif self.name in INSTANCE_FUNCTIONS:
    245 			return Function.TYPE_INSTANCE
    246 		else:
    247 			return Function.TYPE_DEVICE
    248 
    249 class API:
    250 	def __init__ (self, definitions, handles, enums, bitfields, compositeTypes, functions):
    251 		self.definitions	= definitions
    252 		self.handles		= handles
    253 		self.enums			= enums
    254 		self.bitfields		= bitfields
    255 		self.compositeTypes	= compositeTypes
    256 		self.functions		= functions
    257 
    258 def readFile (filename):
    259 	with open(filename, 'rb') as f:
    260 		return f.read()
    261 
    262 IDENT_PTRN	= r'[a-zA-Z_][a-zA-Z0-9_]*'
    263 TYPE_PTRN	= r'[a-zA-Z_][a-zA-Z0-9_ \t*]*'
    264 
    265 def fixupEnumValues (values):
    266 	fixed = []
    267 	for name, value in values:
    268 		if "_BEGIN_RANGE" in name or "_END_RANGE" in name:
    269 			continue
    270 		fixed.append((name, value))
    271 	return fixed
    272 
    273 def fixupType (type):
    274 	for platformType, substitute, compat in PLATFORM_TYPES:
    275 		if type == platformType:
    276 			return PLATFORM_TYPE_NAMESPACE + "::" + substitute
    277 
    278 	for src, dst in TYPE_SUBSTITUTIONS:
    279 		type = type.replace(src, dst)
    280 
    281 	return type
    282 
    283 def fixupFunction (function):
    284 	fixedArgs		= [Variable(fixupType(a.type), a.name, a.arraySize) for a in function.arguments]
    285 	fixedReturnType	= fixupType(function.returnType)
    286 
    287 	return Function(function.name, fixedReturnType, fixedArgs)
    288 
    289 def getInterfaceName (function):
    290 	assert function.name[:2] == "vk"
    291 	return function.name[2].lower() + function.name[3:]
    292 
    293 def getFunctionTypeName (function):
    294 	assert function.name[:2] == "vk"
    295 	return function.name[2:] + "Func"
    296 
    297 def endsWith (str, postfix):
    298 	return str[-len(postfix):] == postfix
    299 
    300 def splitNameExtPostfix (name):
    301 	knownExtPostfixes = EXTENSION_POSTFIXES
    302 	for postfix in knownExtPostfixes:
    303 		if endsWith(name, postfix):
    304 			return (name[:-len(postfix)], postfix)
    305 	return (name, "")
    306 
    307 def getBitEnumNameForBitfield (bitfieldName):
    308 	bitfieldName, postfix = splitNameExtPostfix(bitfieldName)
    309 
    310 	assert bitfieldName[-1] == "s"
    311 	return bitfieldName[:-1] + "Bits" + postfix
    312 
    313 def getBitfieldNameForBitEnum (bitEnumName):
    314 	bitEnumName, postfix = splitNameExtPostfix(bitEnumName)
    315 
    316 	assert bitEnumName[-4:] == "Bits"
    317 	return bitEnumName[:-4] + "s" + postfix
    318 
    319 def parsePreprocDefinedValue (src, name):
    320 	definition = re.search(r'#\s*define\s+' + name + r'\s+([^\n]+)\n', src)
    321 	if definition is None:
    322 		raise Exception("No such definition: %s" % name)
    323 	value = definition.group(1).strip()
    324 
    325 	if value == "UINT32_MAX":
    326 		value = "(~0u)"
    327 
    328 	return value
    329 
    330 def parseEnum (name, src):
    331 	keyValuePtrn	= '(' + IDENT_PTRN + r')\s*=\s*([^\s,}]+)\s*[,}]'
    332 	matches			= re.findall(keyValuePtrn, src)
    333 
    334 	return Enum(name, fixupEnumValues(matches))
    335 
    336 # \note Parses raw enums, some are mapped to bitfields later
    337 def parseEnums (src):
    338 	matches	= re.findall(r'typedef enum(\s*' + IDENT_PTRN + r')?\s*{([^}]*)}\s*(' + IDENT_PTRN + r')\s*;', src)
    339 	enums	= []
    340 
    341 	for enumname, contents, typename in matches:
    342 		enums.append(parseEnum(typename, contents))
    343 
    344 	return enums
    345 
    346 def parseCompositeType (type, name, src):
    347 	# \todo [pyry] Array support is currently a hack (size coupled with name)
    348 	typeNamePtrn	= r'(' + TYPE_PTRN + ')(\s' + IDENT_PTRN + r'(\[[^\]]+\])*)\s*;'
    349 	matches			= re.findall(typeNamePtrn, src)
    350 	members			= [Variable(fixupType(t.strip()), n.strip()) for t, n, a in matches]
    351 
    352 	return CompositeType(type, name, members)
    353 
    354 def parseCompositeTypes (src):
    355 	typeMap	= { 'struct': CompositeType.CLASS_STRUCT, 'union': CompositeType.CLASS_UNION }
    356 	matches	= re.findall(r'typedef (struct|union)(\s*' + IDENT_PTRN + r')?\s*{([^}]*)}\s*(' + IDENT_PTRN + r')\s*;', src)
    357 	types	= []
    358 
    359 	for type, structname, contents, typename in matches:
    360 		types.append(parseCompositeType(typeMap[type], typename, contents))
    361 
    362 	return types
    363 
    364 def parseHandles (src):
    365 	matches	= re.findall(r'VK_DEFINE(_NON_DISPATCHABLE|)_HANDLE\((' + IDENT_PTRN + r')\)[ \t]*[\n\r]', src)
    366 	handles	= []
    367 	typeMap	= {'': Handle.TYPE_DISP, '_NON_DISPATCHABLE': Handle.TYPE_NONDISP}
    368 
    369 	for type, name in matches:
    370 		handle = Handle(typeMap[type], name)
    371 		handles.append(handle)
    372 
    373 	return handles
    374 
    375 def parseArgList (src):
    376 	typeNamePtrn	= r'(' + TYPE_PTRN + ')(\s' + IDENT_PTRN + r')(\[[^\]]+\])?'
    377 	args			= []
    378 
    379 	for rawArg in src.split(','):
    380 		m = re.search(typeNamePtrn, rawArg)
    381 		args.append(Variable(m.group(1).strip(), m.group(2).strip(), m.group(3)))
    382 
    383 	return args
    384 
    385 def parseFunctions (src):
    386 	ptrn		= r'VKAPI_ATTR\s+(' + TYPE_PTRN + ')VKAPI_CALL\s+(' + IDENT_PTRN + r')\s*\(([^)]*)\)\s*;'
    387 	matches		= re.findall(ptrn, src)
    388 	functions	= []
    389 
    390 	for returnType, name, argList in matches:
    391 		functions.append(Function(name.strip(), returnType.strip(), parseArgList(argList)))
    392 
    393 	return [fixupFunction(f) for f in functions]
    394 
    395 def parseBitfieldNames (src):
    396 	ptrn		= r'typedef\s+VkFlags\s(' + IDENT_PTRN + r')\s*;'
    397 	matches		= re.findall(ptrn, src)
    398 
    399 	return matches
    400 
    401 def parseAPI (src):
    402 	definitions		= [(name, type, parsePreprocDefinedValue(src, name)) for name, type in DEFINITIONS]
    403 	rawEnums		= parseEnums(src)
    404 	bitfieldNames	= parseBitfieldNames(src)
    405 	enums			= []
    406 	bitfields		= []
    407 	bitfieldEnums	= set([getBitEnumNameForBitfield(n) for n in bitfieldNames])
    408 
    409 	for enum in rawEnums:
    410 		if enum.name in bitfieldEnums:
    411 			bitfields.append(Bitfield(getBitfieldNameForBitEnum(enum.name), enum.values))
    412 		else:
    413 			enums.append(enum)
    414 
    415 	for bitfieldName in bitfieldNames:
    416 		if not bitfieldName in [bitfield.name for bitfield in bitfields]:
    417 			# Add empty bitfield
    418 			bitfields.append(Bitfield(bitfieldName, []))
    419 
    420 	return API(
    421 		definitions		= definitions,
    422 		handles			= parseHandles(src),
    423 		enums			= enums,
    424 		bitfields		= bitfields,
    425 		compositeTypes	= parseCompositeTypes(src),
    426 		functions		= parseFunctions(src))
    427 
    428 def writeHandleType (api, filename):
    429 	def gen ():
    430 		yield "enum HandleType"
    431 		yield "{"
    432 		yield "\t%s = 0," % api.handles[0].getHandleType()
    433 		for handle in api.handles[1:]:
    434 			yield "\t%s," % handle.getHandleType()
    435 		yield "\tHANDLE_TYPE_LAST"
    436 		yield "};"
    437 		yield ""
    438 
    439 	writeInlFile(filename, INL_HEADER, gen())
    440 
    441 def getEnumValuePrefix (enum):
    442 	prefix = enum.name[0]
    443 	for i in range(1, len(enum.name)):
    444 		if enum.name[i].isupper() and not enum.name[i-1].isupper():
    445 			prefix += "_"
    446 		prefix += enum.name[i].upper()
    447 	return prefix
    448 
    449 def parseInt (value):
    450 	if value[:2] == "0x":
    451 		return int(value, 16)
    452 	else:
    453 		return int(value, 10)
    454 
    455 def areEnumValuesLinear (enum):
    456 	curIndex = 0
    457 	for name, value in enum.values:
    458 		if parseInt(value) != curIndex:
    459 			return False
    460 		curIndex += 1
    461 	return True
    462 
    463 def genEnumSrc (enum):
    464 	yield "enum %s" % enum.name
    465 	yield "{"
    466 
    467 	for line in indentLines(["\t%s\t= %s," % v for v in enum.values]):
    468 		yield line
    469 
    470 	if areEnumValuesLinear(enum):
    471 		yield ""
    472 		yield "\t%s_LAST" % getEnumValuePrefix(enum)
    473 
    474 	yield "};"
    475 
    476 def genBitfieldSrc (bitfield):
    477 	if len(bitfield.values) > 0:
    478 		yield "enum %s" % getBitEnumNameForBitfield(bitfield.name)
    479 		yield "{"
    480 		for line in indentLines(["\t%s\t= %s," % v for v in bitfield.values]):
    481 			yield line
    482 		yield "};"
    483 
    484 	yield "typedef deUint32 %s;" % bitfield.name
    485 
    486 def genCompositeTypeSrc (type):
    487 	yield "%s %s" % (type.getClassName(), type.name)
    488 	yield "{"
    489 	for line in indentLines(["\t%s\t%s;" % (m.type, m.name) for m in type.members]):
    490 		yield line
    491 	yield "};"
    492 
    493 def genHandlesSrc (handles):
    494 	def genLines (handles):
    495 		for handle in handles:
    496 			if handle.type == Handle.TYPE_DISP:
    497 				yield "VK_DEFINE_HANDLE\t(%s,\t%s);" % (handle.name, handle.getHandleType())
    498 			elif handle.type == Handle.TYPE_NONDISP:
    499 				yield "VK_DEFINE_NON_DISPATCHABLE_HANDLE\t(%s,\t%s);" % (handle.name, handle.getHandleType())
    500 
    501 	for line in indentLines(genLines(handles)):
    502 		yield line
    503 
    504 def writeBasicTypes (api, filename):
    505 	def gen ():
    506 		for line in indentLines(["#define %s\t(static_cast<%s>\t(%s))" % (name, type, value) for name, type, value in api.definitions]):
    507 			yield line
    508 		yield ""
    509 		for line in genHandlesSrc(api.handles):
    510 			yield line
    511 		yield ""
    512 		for enum in api.enums:
    513 			for line in genEnumSrc(enum):
    514 				yield line
    515 			yield ""
    516 		for bitfield in api.bitfields:
    517 			for line in genBitfieldSrc(bitfield):
    518 				yield line
    519 			yield ""
    520 		for line in indentLines(["VK_DEFINE_PLATFORM_TYPE(%s,\t%s);" % (s, c) for n, s, c in PLATFORM_TYPES]):
    521 			yield line
    522 
    523 	writeInlFile(filename, INL_HEADER, gen())
    524 
    525 def writeCompositeTypes (api, filename):
    526 	def gen ():
    527 		for type in api.compositeTypes:
    528 			for line in genCompositeTypeSrc(type):
    529 				yield line
    530 			yield ""
    531 
    532 	writeInlFile(filename, INL_HEADER, gen())
    533 
    534 def argListToStr (args):
    535 	return ", ".join("%s %s%s" % (v.type, v.name, v.arraySize if v.arraySize != None else "") for v in args)
    536 
    537 def writeInterfaceDecl (api, filename, functionTypes, concrete):
    538 	def genProtos ():
    539 		postfix = "" if concrete else " = 0"
    540 		for function in api.functions:
    541 			if function.getType() in functionTypes:
    542 				yield "virtual %s\t%s\t(%s) const%s;" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments), postfix)
    543 
    544 	writeInlFile(filename, INL_HEADER, indentLines(genProtos()))
    545 
    546 def writeFunctionPtrTypes (api, filename):
    547 	def genTypes ():
    548 		for function in api.functions:
    549 			yield "typedef VKAPI_ATTR %s\t(VKAPI_CALL* %s)\t(%s);" % (function.returnType, getFunctionTypeName(function), argListToStr(function.arguments))
    550 
    551 	writeInlFile(filename, INL_HEADER, indentLines(genTypes()))
    552 
    553 def writeFunctionPointers (api, filename, functionTypes):
    554 	writeInlFile(filename, INL_HEADER, indentLines(["%s\t%s;" % (getFunctionTypeName(function), getInterfaceName(function)) for function in api.functions if function.getType() in functionTypes]))
    555 
    556 def writeInitFunctionPointers (api, filename, functionTypes, cond = None):
    557 	def makeInitFunctionPointers ():
    558 		for function in api.functions:
    559 			if function.getType() in functionTypes and (cond == None or cond(function)):
    560 				yield "m_vk.%s\t= (%s)\tGET_PROC_ADDR(\"%s\");" % (getInterfaceName(function), getFunctionTypeName(function), function.name)
    561 
    562 	writeInlFile(filename, INL_HEADER, indentLines(makeInitFunctionPointers()))
    563 
    564 def writeFuncPtrInterfaceImpl (api, filename, functionTypes, className):
    565 	def makeFuncPtrInterfaceImpl ():
    566 		for function in api.functions:
    567 			if function.getType() in functionTypes:
    568 				yield ""
    569 				yield "%s %s::%s (%s) const" % (function.returnType, className, getInterfaceName(function), argListToStr(function.arguments))
    570 				yield "{"
    571 				yield "	%sm_vk.%s(%s);" % ("return " if function.returnType != "void" else "", getInterfaceName(function), ", ".join(a.name for a in function.arguments))
    572 				yield "}"
    573 
    574 	writeInlFile(filename, INL_HEADER, makeFuncPtrInterfaceImpl())
    575 
    576 def writeStrUtilProto (api, filename):
    577 	def makeStrUtilProto ():
    578 		for line in indentLines(["const char*\tget%sName\t(%s value);" % (enum.name[2:], enum.name) for enum in api.enums]):
    579 			yield line
    580 		yield ""
    581 		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]):
    582 			yield line
    583 		yield ""
    584 		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]):
    585 			yield line
    586 		yield ""
    587 		for line in indentLines(["tcu::Format::Bitfield<32>\tget%sStr\t(%s value);" % (bitfield.name[2:], bitfield.name) for bitfield in api.bitfields]):
    588 			yield line
    589 		yield ""
    590 		for line in indentLines(["std::ostream&\toperator<<\t(std::ostream& s, const %s& value);" % (s.name) for s in api.compositeTypes]):
    591 			yield line
    592 
    593 	writeInlFile(filename, INL_HEADER, makeStrUtilProto())
    594 
    595 def writeStrUtilImpl (api, filename):
    596 	def makeStrUtilImpl ():
    597 		for line in indentLines(["template<> const char*\tgetTypeName<%s>\t(void) { return \"%s\";\t}" % (handle.name, handle.name) for handle in api.handles]):
    598 			yield line
    599 
    600 		yield ""
    601 		yield "namespace %s" % PLATFORM_TYPE_NAMESPACE
    602 		yield "{"
    603 
    604 		for line in indentLines("std::ostream& operator<< (std::ostream& s, %s\tv) { return s << tcu::toHex(v.internal); }" % s for n, s, c in PLATFORM_TYPES):
    605 			yield line
    606 
    607 		yield "}"
    608 
    609 		for enum in api.enums:
    610 			yield ""
    611 			yield "const char* get%sName (%s value)" % (enum.name[2:], enum.name)
    612 			yield "{"
    613 			yield "\tswitch (value)"
    614 			yield "\t{"
    615 			for line in indentLines(["\t\tcase %s:\treturn \"%s\";" % (n, n) for n, v in enum.values] + ["\t\tdefault:\treturn DE_NULL;"]):
    616 				yield line
    617 			yield "\t}"
    618 			yield "}"
    619 
    620 		for bitfield in api.bitfields:
    621 			yield ""
    622 			yield "tcu::Format::Bitfield<32> get%sStr (%s value)" % (bitfield.name[2:], bitfield.name)
    623 			yield "{"
    624 
    625 			if len(bitfield.values) > 0:
    626 				yield "\tstatic const tcu::Format::BitDesc s_desc[] ="
    627 				yield "\t{"
    628 				for line in indentLines(["\t\ttcu::Format::BitDesc(%s,\t\"%s\")," % (n, n) for n, v in bitfield.values]):
    629 					yield line
    630 				yield "\t};"
    631 				yield "\treturn tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));"
    632 			else:
    633 				yield "\treturn tcu::Format::Bitfield<32>(value, DE_NULL, DE_NULL);"
    634 
    635 			yield "}"
    636 
    637 		bitfieldTypeNames = set([bitfield.name for bitfield in api.bitfields])
    638 
    639 		for type in api.compositeTypes:
    640 			yield ""
    641 			yield "std::ostream& operator<< (std::ostream& s, const %s& value)" % type.name
    642 			yield "{"
    643 			yield "\ts << \"%s = {\\n\";" % type.name
    644 			for member in type.members:
    645 				memberName	= member.name
    646 				valFmt		= None
    647 				newLine		= ""
    648 				if member.type in bitfieldTypeNames:
    649 					valFmt = "get%sStr(value.%s)" % (member.type[2:], member.name)
    650 				elif member.type == "const char*" or member.type == "char*":
    651 					valFmt = "getCharPtrStr(value.%s)" % member.name
    652 				elif '[' in member.name:
    653 					baseName = member.name[:member.name.find('[')]
    654 					if baseName in ["extensionName", "deviceName", "layerName", "description"]:
    655 						valFmt = "(const char*)value.%s" % baseName
    656 					elif member.type == 'char' or member.type == 'deUint8':
    657 						newLine = "'\\n' << "
    658 						valFmt = "tcu::formatArray(tcu::Format::HexIterator<%s>(DE_ARRAY_BEGIN(value.%s)), tcu::Format::HexIterator<%s>(DE_ARRAY_END(value.%s)))" % (member.type, baseName, member.type, baseName)
    659 					else:
    660 						if baseName == "memoryTypes" or baseName == "memoryHeaps":
    661 							endIter = "DE_ARRAY_BEGIN(value.%s) + value.%sCount" % (baseName, baseName[:-1])
    662 						else:
    663 							endIter = "DE_ARRAY_END(value.%s)" % baseName
    664 						newLine = "'\\n' << "
    665 						valFmt = "tcu::formatArray(DE_ARRAY_BEGIN(value.%s), %s)" % (baseName, endIter)
    666 					memberName = baseName
    667 				else:
    668 					valFmt = "value.%s" % member.name
    669 				yield ("\ts << \"\\t%s = \" << " % memberName) + newLine + valFmt + " << '\\n';"
    670 			yield "\ts << '}';"
    671 			yield "\treturn s;"
    672 			yield "}"
    673 
    674 
    675 	writeInlFile(filename, INL_HEADER, makeStrUtilImpl())
    676 
    677 class ConstructorFunction:
    678 	def __init__ (self, type, name, objectType, iface, arguments):
    679 		self.type		= type
    680 		self.name		= name
    681 		self.objectType	= objectType
    682 		self.iface		= iface
    683 		self.arguments	= arguments
    684 
    685 def getConstructorFunctions (api):
    686 	funcs = []
    687 	for function in api.functions:
    688 		if (function.name[:8] == "vkCreate" or function.name == "vkAllocateMemory") and not "createInfoCount" in [a.name for a in function.arguments]:
    689 			if function.name == "vkCreateDisplayModeKHR":
    690 				continue # No way to delete display modes (bug?)
    691 
    692 			# \todo [pyry] Rather hacky
    693 			iface = None
    694 			if function.getType() == Function.TYPE_PLATFORM:
    695 				iface = Variable("const PlatformInterface&", "vk")
    696 			elif function.getType() == Function.TYPE_INSTANCE:
    697 				iface = Variable("const InstanceInterface&", "vk")
    698 			else:
    699 				iface = Variable("const DeviceInterface&", "vk")
    700 
    701 			assert function.arguments[-2].type == "const VkAllocationCallbacks*"
    702 
    703 			objectType	= function.arguments[-1].type.replace("*", "").strip()
    704 			arguments	= function.arguments[:-1]
    705 			funcs.append(ConstructorFunction(function.getType(), getInterfaceName(function), objectType, iface, arguments))
    706 	return funcs
    707 
    708 def writeRefUtilProto (api, filename):
    709 	functions	= getConstructorFunctions(api)
    710 
    711 	def makeRefUtilProto ():
    712 		unindented = []
    713 		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]):
    714 			yield line
    715 
    716 	writeInlFile(filename, INL_HEADER, makeRefUtilProto())
    717 
    718 def writeRefUtilImpl (api, filename):
    719 	functions = getConstructorFunctions(api)
    720 
    721 	def makeRefUtilImpl ():
    722 		yield "namespace refdetails"
    723 		yield "{"
    724 		yield ""
    725 
    726 		for function in api.functions:
    727 			if function.getType() == Function.TYPE_DEVICE \
    728 			   and (function.name[:9] == "vkDestroy" or function.name == "vkFreeMemory") \
    729 			   and not function.name == "vkDestroyDevice":
    730 				objectType = function.arguments[-2].type
    731 				yield "template<>"
    732 				yield "void Deleter<%s>::operator() (%s obj) const" % (objectType, objectType)
    733 				yield "{"
    734 				yield "\tm_deviceIface->%s(m_device, obj, m_allocator);" % (getInterfaceName(function))
    735 				yield "}"
    736 				yield ""
    737 
    738 		yield "} // refdetails"
    739 		yield ""
    740 
    741 		for function in functions:
    742 			if function.type == Function.TYPE_DEVICE:
    743 				dtorObj = "device"
    744 			elif function.type == Function.TYPE_INSTANCE:
    745 				if function.name == "createDevice":
    746 					dtorObj = "object"
    747 				else:
    748 					dtorObj = "instance"
    749 			else:
    750 				dtorObj = "object"
    751 
    752 			yield "Move<%s> %s (%s)" % (function.objectType, function.name, argListToStr([function.iface] + function.arguments))
    753 			yield "{"
    754 			yield "\t%s object = 0;" % function.objectType
    755 			yield "\tVK_CHECK(vk.%s(%s));" % (function.name, ", ".join([a.name for a in function.arguments] + ["&object"]))
    756 			yield "\treturn Move<%s>(check<%s>(object), Deleter<%s>(%s));" % (function.objectType, function.objectType, function.objectType, ", ".join(["vk", dtorObj, function.arguments[-1].name]))
    757 			yield "}"
    758 			yield ""
    759 
    760 	writeInlFile(filename, INL_HEADER, makeRefUtilImpl())
    761 
    762 def writeNullDriverImpl (api, filename):
    763 	def genNullDriverImpl ():
    764 		specialFuncNames	= [
    765 				"vkCreateGraphicsPipelines",
    766 				"vkCreateComputePipelines",
    767 				"vkGetInstanceProcAddr",
    768 				"vkGetDeviceProcAddr",
    769 				"vkEnumeratePhysicalDevices",
    770 				"vkGetPhysicalDeviceFeatures",
    771 				"vkGetPhysicalDeviceProperties",
    772 				"vkGetPhysicalDeviceQueueFamilyProperties",
    773 				"vkGetPhysicalDeviceMemoryProperties",
    774 				"vkGetPhysicalDeviceFormatProperties",
    775 				"vkGetPhysicalDeviceImageFormatProperties",
    776 				"vkGetDeviceQueue",
    777 				"vkGetBufferMemoryRequirements",
    778 				"vkGetImageMemoryRequirements",
    779 				"vkMapMemory",
    780 				"vkAllocateDescriptorSets",
    781 				"vkFreeDescriptorSets",
    782 				"vkResetDescriptorPool",
    783 				"vkAllocateCommandBuffers",
    784 				"vkFreeCommandBuffers",
    785 				"vkCreateDisplayModeKHR",
    786 				"vkCreateSharedSwapchainsKHR",
    787 			]
    788 		specialFuncs		= [f for f in api.functions if f.name in specialFuncNames]
    789 		createFuncs			= [f for f in api.functions if (f.name[:8] == "vkCreate" or f.name == "vkAllocateMemory") and not f in specialFuncs]
    790 		destroyFuncs		= [f for f in api.functions if (f.name[:9] == "vkDestroy" or f.name == "vkFreeMemory") and not f in specialFuncs]
    791 		dummyFuncs			= [f for f in api.functions if f not in specialFuncs + createFuncs + destroyFuncs]
    792 
    793 		def getHandle (name):
    794 			for handle in api.handles:
    795 				if handle.name == name:
    796 					return handle
    797 			raise Exception("No such handle: %s" % name)
    798 
    799 		for function in createFuncs:
    800 			objectType	= function.arguments[-1].type.replace("*", "").strip()
    801 			argsStr		= ", ".join([a.name for a in function.arguments[:-1]])
    802 
    803 			yield "VKAPI_ATTR %s VKAPI_CALL %s (%s)" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments))
    804 			yield "{"
    805 			yield "\tDE_UNREF(%s);" % function.arguments[-2].name
    806 
    807 			if getHandle(objectType).type == Handle.TYPE_NONDISP:
    808 				yield "\tVK_NULL_RETURN((*%s = allocateNonDispHandle<%s, %s>(%s)));" % (function.arguments[-1].name, objectType[2:], objectType, argsStr)
    809 			else:
    810 				yield "\tVK_NULL_RETURN((*%s = allocateHandle<%s, %s>(%s)));" % (function.arguments[-1].name, objectType[2:], objectType, argsStr)
    811 
    812 			yield "}"
    813 			yield ""
    814 
    815 		for function in destroyFuncs:
    816 			objectArg	= function.arguments[-2]
    817 
    818 			yield "VKAPI_ATTR %s VKAPI_CALL %s (%s)" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments))
    819 			yield "{"
    820 			for arg in function.arguments[:-2]:
    821 				yield "\tDE_UNREF(%s);" % arg.name
    822 
    823 			if getHandle(objectArg.type).type == Handle.TYPE_NONDISP:
    824 				yield "\tfreeNonDispHandle<%s, %s>(%s, %s);" % (objectArg.type[2:], objectArg.type, objectArg.name, function.arguments[-1].name)
    825 			else:
    826 				yield "\tfreeHandle<%s, %s>(%s, %s);" % (objectArg.type[2:], objectArg.type, objectArg.name, function.arguments[-1].name)
    827 
    828 			yield "}"
    829 			yield ""
    830 
    831 		for function in dummyFuncs:
    832 			yield "VKAPI_ATTR %s VKAPI_CALL %s (%s)" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments))
    833 			yield "{"
    834 			for arg in function.arguments:
    835 				yield "\tDE_UNREF(%s);" % arg.name
    836 			if function.returnType != "void":
    837 				yield "\treturn VK_SUCCESS;"
    838 			yield "}"
    839 			yield ""
    840 
    841 		def genFuncEntryTable (type, name):
    842 			funcs = [f for f in api.functions if f.getType() == type]
    843 
    844 			yield "static const tcu::StaticFunctionLibrary::Entry %s[] =" % name
    845 			yield "{"
    846 			for line in indentLines(["\tVK_NULL_FUNC_ENTRY(%s,\t%s)," % (function.name, getInterfaceName(function)) for function in funcs]):
    847 				yield line
    848 			yield "};"
    849 			yield ""
    850 
    851 		# Func tables
    852 		for line in genFuncEntryTable(Function.TYPE_PLATFORM, "s_platformFunctions"):
    853 			yield line
    854 
    855 		for line in genFuncEntryTable(Function.TYPE_INSTANCE, "s_instanceFunctions"):
    856 			yield line
    857 
    858 		for line in genFuncEntryTable(Function.TYPE_DEVICE, "s_deviceFunctions"):
    859 			yield line
    860 
    861 
    862 	writeInlFile(filename, INL_HEADER, genNullDriverImpl())
    863 
    864 def writeTypeUtil (api, filename):
    865 	# Structs filled by API queries are not often used in test code
    866 	QUERY_RESULT_TYPES = set([
    867 			"VkPhysicalDeviceFeatures",
    868 			"VkPhysicalDeviceLimits",
    869 			"VkFormatProperties",
    870 			"VkImageFormatProperties",
    871 			"VkPhysicalDeviceSparseProperties",
    872 			"VkQueueFamilyProperties",
    873 			"VkMemoryType",
    874 			"VkMemoryHeap",
    875 		])
    876 	COMPOSITE_TYPES = set([t.name for t in api.compositeTypes])
    877 
    878 	def isSimpleStruct (type):
    879 		def hasArrayMember (type):
    880 			for member in type.members:
    881 				if "[" in member.name:
    882 					return True
    883 			return False
    884 
    885 		def hasCompositeMember (type):
    886 			for member in type.members:
    887 				if member.type in COMPOSITE_TYPES:
    888 					return True
    889 			return False
    890 
    891 		return type.typeClass == CompositeType.CLASS_STRUCT and \
    892 			   type.members[0].type != "VkStructureType" and \
    893 			   not type.name in QUERY_RESULT_TYPES and \
    894 			   not hasArrayMember(type) and \
    895 			   not hasCompositeMember(type)
    896 
    897 	def gen ():
    898 		for type in api.compositeTypes:
    899 			if not isSimpleStruct(type):
    900 				continue
    901 
    902 			yield ""
    903 			yield "inline %s make%s (%s)" % (type.name, type.name[2:], argListToStr(type.members))
    904 			yield "{"
    905 			yield "\t%s res;" % type.name
    906 			for line in indentLines(["\tres.%s\t= %s;" % (m.name, m.name) for m in type.members]):
    907 				yield line
    908 			yield "\treturn res;"
    909 			yield "}"
    910 
    911 	writeInlFile(filename, INL_HEADER, gen())
    912 
    913 if __name__ == "__main__":
    914 	src				= readFile(VULKAN_H)
    915 	api				= parseAPI(src)
    916 	platformFuncs	= set([Function.TYPE_PLATFORM])
    917 	instanceFuncs	= set([Function.TYPE_INSTANCE])
    918 	deviceFuncs		= set([Function.TYPE_DEVICE])
    919 
    920 	writeHandleType				(api, os.path.join(VULKAN_DIR, "vkHandleType.inl"))
    921 	writeBasicTypes				(api, os.path.join(VULKAN_DIR, "vkBasicTypes.inl"))
    922 	writeCompositeTypes			(api, os.path.join(VULKAN_DIR, "vkStructTypes.inl"))
    923 	writeInterfaceDecl			(api, os.path.join(VULKAN_DIR, "vkVirtualPlatformInterface.inl"),		functionTypes = platformFuncs,	concrete = False)
    924 	writeInterfaceDecl			(api, os.path.join(VULKAN_DIR, "vkVirtualInstanceInterface.inl"),		functionTypes = instanceFuncs,	concrete = False)
    925 	writeInterfaceDecl			(api, os.path.join(VULKAN_DIR, "vkVirtualDeviceInterface.inl"),			functionTypes = deviceFuncs,	concrete = False)
    926 	writeInterfaceDecl			(api, os.path.join(VULKAN_DIR, "vkConcretePlatformInterface.inl"),		functionTypes = platformFuncs,	concrete = True)
    927 	writeInterfaceDecl			(api, os.path.join(VULKAN_DIR, "vkConcreteInstanceInterface.inl"),		functionTypes = instanceFuncs,	concrete = True)
    928 	writeInterfaceDecl			(api, os.path.join(VULKAN_DIR, "vkConcreteDeviceInterface.inl"),		functionTypes = deviceFuncs,	concrete = True)
    929 	writeFunctionPtrTypes		(api, os.path.join(VULKAN_DIR, "vkFunctionPointerTypes.inl"))
    930 	writeFunctionPointers		(api, os.path.join(VULKAN_DIR, "vkPlatformFunctionPointers.inl"),		functionTypes = platformFuncs)
    931 	writeFunctionPointers		(api, os.path.join(VULKAN_DIR, "vkInstanceFunctionPointers.inl"),		functionTypes = instanceFuncs)
    932 	writeFunctionPointers		(api, os.path.join(VULKAN_DIR, "vkDeviceFunctionPointers.inl"),			functionTypes = deviceFuncs)
    933 	writeInitFunctionPointers	(api, os.path.join(VULKAN_DIR, "vkInitPlatformFunctionPointers.inl"),	functionTypes = platformFuncs,	cond = lambda f: f.name != "vkGetInstanceProcAddr")
    934 	writeInitFunctionPointers	(api, os.path.join(VULKAN_DIR, "vkInitInstanceFunctionPointers.inl"),	functionTypes = instanceFuncs)
    935 	writeInitFunctionPointers	(api, os.path.join(VULKAN_DIR, "vkInitDeviceFunctionPointers.inl"),		functionTypes = deviceFuncs)
    936 	writeFuncPtrInterfaceImpl	(api, os.path.join(VULKAN_DIR, "vkPlatformDriverImpl.inl"),				functionTypes = platformFuncs,	className = "PlatformDriver")
    937 	writeFuncPtrInterfaceImpl	(api, os.path.join(VULKAN_DIR, "vkInstanceDriverImpl.inl"),				functionTypes = instanceFuncs,	className = "InstanceDriver")
    938 	writeFuncPtrInterfaceImpl	(api, os.path.join(VULKAN_DIR, "vkDeviceDriverImpl.inl"),				functionTypes = deviceFuncs,	className = "DeviceDriver")
    939 	writeStrUtilProto			(api, os.path.join(VULKAN_DIR, "vkStrUtil.inl"))
    940 	writeStrUtilImpl			(api, os.path.join(VULKAN_DIR, "vkStrUtilImpl.inl"))
    941 	writeRefUtilProto			(api, os.path.join(VULKAN_DIR, "vkRefUtil.inl"))
    942 	writeRefUtilImpl			(api, os.path.join(VULKAN_DIR, "vkRefUtilImpl.inl"))
    943 	writeNullDriverImpl			(api, os.path.join(VULKAN_DIR, "vkNullDriverImpl.inl"))
    944 	writeTypeUtil				(api, os.path.join(VULKAN_DIR, "vkTypeUtil.inl"))
    945