• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# -*- coding: utf-8 -*-
2
3#-------------------------------------------------------------------------
4# Vulkan CTS
5# ----------
6#
7# Copyright (c) 2015 Google Inc.
8#
9# Licensed under the Apache License, Version 2.0 (the "License");
10# you may not use this file except in compliance with the License.
11# You may obtain a copy of the License at
12#
13#      http://www.apache.org/licenses/LICENSE-2.0
14#
15# Unless required by applicable law or agreed to in writing, software
16# distributed under the License is distributed on an "AS IS" BASIS,
17# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18# See the License for the specific language governing permissions and
19# limitations under the License.
20#
21#-------------------------------------------------------------------------
22
23import os
24import re
25import sys
26
27sys.path.append(os.path.join(os.path.dirname(__file__), "..", "..", "..", "scripts"))
28
29from build.common import DEQP_DIR
30from khr_util.format import indentLines, writeInlFile
31
32VULKAN_H	= os.path.join(os.path.dirname(__file__), "src", "vulkan.h.in")
33VULKAN_DIR	= os.path.join(os.path.dirname(__file__), "..", "framework", "vulkan")
34
35INL_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
41PLATFORM_FUNCTIONS	= [
42	"vkCreateInstance",
43	"vkGetInstanceProcAddr",
44	"vkEnumerateInstanceExtensionProperties",
45	"vkEnumerateInstanceLayerProperties",
46]
47INSTANCE_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
124DEFINITIONS			= [
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
142PLATFORM_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]
170PLATFORM_TYPE_NAMESPACE	= "pt"
171TYPE_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
188EXTENSION_POSTFIXES		= ["KHR", "EXT", "NV", "NVX", "KHX"]
189
190class 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
202class Enum:
203	def __init__ (self, name, values):
204		self.name	= name
205		self.values	= values
206
207class Bitfield:
208	def __init__ (self, name, values):
209		self.name	= name
210		self.values	= values
211
212class Variable:
213	def __init__ (self, type, name, arraySize = None):
214		self.type		= type
215		self.name		= name
216		self.arraySize	= arraySize
217
218class 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
231class 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
249class 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
258def readFile (filename):
259	with open(filename, 'rb') as f:
260		return f.read()
261
262IDENT_PTRN	= r'[a-zA-Z_][a-zA-Z0-9_]*'
263TYPE_PTRN	= r'[a-zA-Z_][a-zA-Z0-9_ \t*]*'
264
265def 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
273def 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
283def 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
289def getInterfaceName (function):
290	assert function.name[:2] == "vk"
291	return function.name[2].lower() + function.name[3:]
292
293def getFunctionTypeName (function):
294	assert function.name[:2] == "vk"
295	return function.name[2:] + "Func"
296
297def endsWith (str, postfix):
298	return str[-len(postfix):] == postfix
299
300def 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
307def getBitEnumNameForBitfield (bitfieldName):
308	bitfieldName, postfix = splitNameExtPostfix(bitfieldName)
309
310	assert bitfieldName[-1] == "s"
311	return bitfieldName[:-1] + "Bits" + postfix
312
313def getBitfieldNameForBitEnum (bitEnumName):
314	bitEnumName, postfix = splitNameExtPostfix(bitEnumName)
315
316	assert bitEnumName[-4:] == "Bits"
317	return bitEnumName[:-4] + "s" + postfix
318
319def 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
330def 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
337def 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
346def 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
354def 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
364def 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
375def 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
385def 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
395def parseBitfieldNames (src):
396	ptrn		= r'typedef\s+VkFlags\s(' + IDENT_PTRN + r')\s*;'
397	matches		= re.findall(ptrn, src)
398
399	return matches
400
401def 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
428def 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
441def 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
449def parseInt (value):
450	if value[:2] == "0x":
451		return int(value, 16)
452	else:
453		return int(value, 10)
454
455def 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
463def 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
476def 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
486def 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
493def 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
504def 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
525def 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
534def argListToStr (args):
535	return ", ".join("%s %s%s" % (v.type, v.name, v.arraySize if v.arraySize != None else "") for v in args)
536
537def 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
546def 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
553def 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
556def 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
564def 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
576def 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
595def 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
677class 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
685def 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
708def 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
718def 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
762def 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
864def 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
913if __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