Update Vulkan framework to API 1.0.5
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / gen_framework.py
1 # -*- coding: utf-8 -*-
2
3 #-------------------------------------------------------------------------
4 # Vulkan CTS
5 # ----------
6 #
7 # Copyright (c) 2015 Google Inc.
8 #
9 # Permission is hereby granted, free of charge, to any person obtaining a
10 # copy of this software and/or associated documentation files (the
11 # "Materials"), to deal in the Materials without restriction, including
12 # without limitation the rights to use, copy, modify, merge, publish,
13 # distribute, sublicense, and/or sell copies of the Materials, and to
14 # permit persons to whom the Materials are furnished to do so, subject to
15 # the following conditions:
16 #
17 # The above copyright notice(s) and this permission notice shall be
18 # included in all copies or substantial portions of the Materials.
19 #
20 # THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
24 # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25 # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26 # MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
27 #
28 #-------------------------------------------------------------------------
29
30 import os
31 import re
32 import sys
33
34 sys.path.append(os.path.join(os.path.dirname(__file__), "..", "..", "scripts"))
35
36 from build.common import DEQP_DIR
37 from khr_util.format import indentLines, writeInlFile
38
39 VULKAN_DIR = os.path.join(os.path.dirname(__file__), "framework", "vulkan")
40
41 INL_HEADER = """\
42 /* WARNING: This is auto-generated file. Do not modify, since changes will
43  * be lost! Modify the generating script instead.
44  */\
45 """
46
47 PLATFORM_FUNCTIONS      = [
48         "vkCreateInstance",
49         "vkGetInstanceProcAddr",
50         "vkEnumerateInstanceExtensionProperties",
51         "vkEnumerateInstanceLayerProperties",
52 ]
53 INSTANCE_FUNCTIONS      = [
54         "vkDestroyInstance",
55         "vkEnumeratePhysicalDevices",
56         "vkGetPhysicalDeviceFeatures",
57         "vkGetPhysicalDeviceFormatProperties",
58         "vkGetPhysicalDeviceImageFormatProperties",
59         "vkGetPhysicalDeviceLimits",
60         "vkGetPhysicalDeviceProperties",
61         "vkGetPhysicalDeviceQueueFamilyProperties",
62         "vkGetPhysicalDeviceMemoryProperties",
63         "vkEnumerateDeviceExtensionProperties",
64         "vkEnumerateDeviceLayerProperties",
65         "vkCreateDevice",
66         "vkGetDeviceProcAddr",
67         "vkCreateDebugReportCallbackEXT",
68         "vkDestroyDebugReportCallbackEXT",
69         "vkDebugReportMessageEXT",
70 ]
71
72 DEFINITIONS                     = [
73         "VK_API_VERSION",
74         "VK_MAX_PHYSICAL_DEVICE_NAME_SIZE",
75         "VK_MAX_EXTENSION_NAME_SIZE",
76         "VK_UUID_SIZE",
77         "VK_MAX_MEMORY_TYPES",
78         "VK_MAX_MEMORY_HEAPS",
79         "VK_MAX_DESCRIPTION_SIZE",
80         "VK_ATTACHMENT_UNUSED",
81 ]
82
83 class Handle:
84         TYPE_DISP               = 0
85         TYPE_NONDISP    = 1
86
87         def __init__ (self, type, name):
88                 self.type       = type
89                 self.name       = name
90
91         def getHandleType (self):
92                 name = re.sub(r'([a-z])([A-Z])', r'\1_\2', self.name)
93                 return "HANDLE_TYPE_" + name[3:].upper()
94
95 class Enum:
96         def __init__ (self, name, values):
97                 self.name       = name
98                 self.values     = values
99
100 class Bitfield:
101         def __init__ (self, name, values):
102                 self.name       = name
103                 self.values     = values
104
105 class Variable:
106         def __init__ (self, type, name, arraySize = None):
107                 self.type               = type
108                 self.name               = name
109                 self.arraySize  = arraySize
110
111 class CompositeType:
112         CLASS_STRUCT    = 0
113         CLASS_UNION             = 1
114
115         def __init__ (self, typeClass, name, members):
116                 self.typeClass  = typeClass
117                 self.name               = name
118                 self.members    = members
119
120         def getClassName (self):
121                 names = {CompositeType.CLASS_STRUCT: 'struct', CompositeType.CLASS_UNION: 'union'}
122                 return names[self.typeClass]
123
124 class Function:
125         TYPE_PLATFORM           = 0 # Not bound to anything
126         TYPE_INSTANCE           = 1 # Bound to VkInstance
127         TYPE_DEVICE                     = 2 # Bound to VkDevice
128
129         def __init__ (self, name, returnType, arguments):
130                 self.name               = name
131                 self.returnType = returnType
132                 self.arguments  = arguments
133
134         def getType (self):
135                 if self.name in PLATFORM_FUNCTIONS:
136                         return Function.TYPE_PLATFORM
137                 elif self.name in INSTANCE_FUNCTIONS:
138                         return Function.TYPE_INSTANCE
139                 else:
140                         return Function.TYPE_DEVICE
141
142 class API:
143         def __init__ (self, definitions, handles, enums, bitfields, compositeTypes, functions):
144                 self.definitions        = definitions
145                 self.handles            = handles
146                 self.enums                      = enums
147                 self.bitfields          = bitfields
148                 self.compositeTypes     = compositeTypes
149                 self.functions          = functions
150
151 def readFile (filename):
152         with open(filename, 'rb') as f:
153                 return f.read()
154
155 IDENT_PTRN      = r'[a-zA-Z_][a-zA-Z0-9_]*'
156 TYPE_PTRN       = r'[a-zA-Z_][a-zA-Z0-9_ \t*]*'
157
158 def endswith (s, postfix):
159         return len(s) >= len(postfix) and s[len(s)-len(postfix):] == postfix
160
161 def fixupEnumValues (values):
162         fixed = []
163         for name, value in values:
164                 if endswith(name, "_BEGIN_RANGE") or endswith(name, "_END_RANGE"):
165                         continue
166                 fixed.append((name, value))
167         return fixed
168
169 def fixupType (type):
170         replacements = [
171                         ("uint8_t",             "deUint8"),
172                         ("uint16_t",    "deUint16"),
173                         ("uint32_t",    "deUint32"),
174                         ("uint64_t",    "deUint64"),
175                         ("int8_t",              "deInt8"),
176                         ("int16_t",             "deInt16"),
177                         ("int32_t",             "deInt32"),
178                         ("int64_t",             "deInt64"),
179                         ("bool32_t",    "deUint32"),
180                         ("size_t",              "deUintptr"),
181                 ]
182
183         for src, dst in replacements:
184                 type = type.replace(src, dst)
185
186         return type
187
188 def fixupFunction (function):
189         fixedArgs               = [Variable(fixupType(a.type), a.name, a.arraySize) for a in function.arguments]
190         fixedReturnType = fixupType(function.returnType)
191
192         return Function(function.name, fixedReturnType, fixedArgs)
193
194 def getInterfaceName (function):
195         assert function.name[:2] == "vk"
196         return function.name[2].lower() + function.name[3:]
197
198 def getFunctionTypeName (function):
199         assert function.name[:2] == "vk"
200         return function.name[2:] + "Func"
201
202 def endsWith (str, postfix):
203         return str[-len(postfix):] == postfix
204
205 def splitNameExtPostfix (name):
206         knownExtPostfixes = ["KHR", "EXT"]
207         for postfix in knownExtPostfixes:
208                 if endsWith(name, postfix):
209                         return (name[:-len(postfix)], postfix)
210         return (name, "")
211
212 def getBitEnumNameForBitfield (bitfieldName):
213         bitfieldName, postfix = splitNameExtPostfix(bitfieldName)
214
215         assert bitfieldName[-1] == "s"
216         return bitfieldName[:-1] + "Bits" + postfix
217
218 def getBitfieldNameForBitEnum (bitEnumName):
219         bitEnumName, postfix = splitNameExtPostfix(bitEnumName)
220
221         assert bitEnumName[-4:] == "Bits"
222         return bitEnumName[:-4] + "s" + postfix
223
224 def parsePreprocDefinedValue (src, name):
225         definition = re.search(r'#\s*define\s+' + name + r'\s+([^\n]+)\n', src)
226         if definition is None:
227                 raise Exception("No such definition: %s" % name)
228         value = definition.group(1).strip()
229
230         if value == "UINT32_MAX":
231                 value = "(~0u)"
232
233         return value
234
235 def parseEnum (name, src):
236         keyValuePtrn    = '(' + IDENT_PTRN + r')\s*=\s*([^\s,}]+)\s*[,}]'
237         matches                 = re.findall(keyValuePtrn, src)
238
239         return Enum(name, fixupEnumValues(matches))
240
241 # \note Parses raw enums, some are mapped to bitfields later
242 def parseEnums (src):
243         matches = re.findall(r'typedef enum(\s*' + IDENT_PTRN + r')?\s*{([^}]*)}\s*(' + IDENT_PTRN + r')\s*;', src)
244         enums   = []
245
246         for enumname, contents, typename in matches:
247                 enums.append(parseEnum(typename, contents))
248
249         return enums
250
251 def parseCompositeType (type, name, src):
252         # \todo [pyry] Array support is currently a hack (size coupled with name)
253         typeNamePtrn    = r'(' + TYPE_PTRN + ')(\s' + IDENT_PTRN + r'(\[[^\]]+\])*)\s*;'
254         matches                 = re.findall(typeNamePtrn, src)
255         members                 = [Variable(fixupType(t.strip()), n.strip()) for t, n, a in matches]
256
257         return CompositeType(type, name, members)
258
259 def parseCompositeTypes (src):
260         typeMap = { 'struct': CompositeType.CLASS_STRUCT, 'union': CompositeType.CLASS_UNION }
261         matches = re.findall(r'typedef (struct|union)(\s*' + IDENT_PTRN + r')?\s*{([^}]*)}\s*(' + IDENT_PTRN + r')\s*;', src)
262         types   = []
263
264         for type, structname, contents, typename in matches:
265                 if typename[-3:] == "KHR":
266                         continue # \todo [2016-01-05 pyry] Figure out how to handle platform-specific types
267
268                 types.append(parseCompositeType(typeMap[type], typename, contents))
269
270         return types
271
272 def parseHandles (src):
273         matches = re.findall(r'VK_DEFINE(_NON_DISPATCHABLE|)_HANDLE\((' + IDENT_PTRN + r')\)[ \t]*[\n\r]', src)
274         handles = []
275         typeMap = {'': Handle.TYPE_DISP, '_NON_DISPATCHABLE': Handle.TYPE_NONDISP}
276
277         for type, name in matches:
278                 handle = Handle(typeMap[type], name)
279                 handles.append(handle)
280
281         return handles
282
283 def parseArgList (src):
284         typeNamePtrn    = r'(' + TYPE_PTRN + ')(\s' + IDENT_PTRN + r')(\[[^\]]+\])?'
285         args                    = []
286
287         for rawArg in src.split(','):
288                 m = re.search(typeNamePtrn, rawArg)
289                 args.append(Variable(m.group(1).strip(), m.group(2).strip(), m.group(3)))
290
291         return args
292
293 def parseFunctions (src):
294         ptrn            = r'VKAPI_ATTR\s+(' + TYPE_PTRN + ')VKAPI_CALL\s+(' + IDENT_PTRN + r')\s*\(([^)]*)\)\s*;'
295         matches         = re.findall(ptrn, src)
296         functions       = []
297
298         for returnType, name, argList in matches:
299                 if name[-3:] == "KHR":
300                         continue # \todo [2015-11-16 pyry] Figure out how to handle platform-specific extension functions
301
302                 functions.append(Function(name.strip(), returnType.strip(), parseArgList(argList)))
303
304         return [fixupFunction(f) for f in functions]
305
306 def parseBitfieldNames (src):
307         ptrn            = r'typedef\s+VkFlags\s(' + IDENT_PTRN + r')\s*;'
308         matches         = re.findall(ptrn, src)
309
310         return matches
311
312 def parseAPI (src):
313         definitions             = [(name, parsePreprocDefinedValue(src, name)) for name in DEFINITIONS]
314         rawEnums                = parseEnums(src)
315         bitfieldNames   = parseBitfieldNames(src)
316         enums                   = []
317         bitfields               = []
318         bitfieldEnums   = set([getBitEnumNameForBitfield(n) for n in bitfieldNames])
319
320         for enum in rawEnums:
321                 if enum.name in bitfieldEnums:
322                         bitfields.append(Bitfield(getBitfieldNameForBitEnum(enum.name), enum.values))
323                 else:
324                         enums.append(enum)
325
326         for bitfieldName in bitfieldNames:
327                 if not bitfieldName in [bitfield.name for bitfield in bitfields]:
328                         # Add empty bitfield
329                         bitfields.append(Bitfield(bitfieldName, []))
330
331         return API(
332                 definitions             = definitions,
333                 handles                 = parseHandles(src),
334                 enums                   = enums,
335                 bitfields               = bitfields,
336                 compositeTypes  = parseCompositeTypes(src),
337                 functions               = parseFunctions(src))
338
339 def writeHandleType (api, filename):
340         def gen ():
341                 yield "enum HandleType"
342                 yield "{"
343                 yield "\t%s = 0," % api.handles[0].getHandleType()
344                 for handle in api.handles[1:]:
345                         yield "\t%s," % handle.getHandleType()
346                 yield "\tHANDLE_TYPE_LAST"
347                 yield "};"
348                 yield ""
349
350         writeInlFile(filename, INL_HEADER, gen())
351
352 def getEnumValuePrefix (enum):
353         prefix = enum.name[0]
354         for i in range(1, len(enum.name)):
355                 if enum.name[i].isupper():
356                         prefix += "_"
357                 prefix += enum.name[i].upper()
358         return prefix
359
360 def parseInt (value):
361         if value[:2] == "0x":
362                 return int(value, 16)
363         else:
364                 return int(value, 10)
365
366 def areEnumValuesLinear (enum):
367         curIndex = 0
368         for name, value in enum.values:
369                 if parseInt(value) != curIndex:
370                         return False
371                 curIndex += 1
372         return True
373
374 def genEnumSrc (enum):
375         yield "enum %s" % enum.name
376         yield "{"
377
378         for line in indentLines(["\t%s\t= %s," % v for v in enum.values]):
379                 yield line
380
381         if areEnumValuesLinear(enum):
382                 yield ""
383                 yield "\t%s_LAST" % getEnumValuePrefix(enum)
384
385         yield "};"
386
387 def genBitfieldSrc (bitfield):
388         if len(bitfield.values) > 0:
389                 yield "enum %s" % getBitEnumNameForBitfield(bitfield.name)
390                 yield "{"
391                 for line in indentLines(["\t%s\t= %s," % v for v in bitfield.values]):
392                         yield line
393                 yield "};"
394
395         yield "typedef deUint32 %s;" % bitfield.name
396
397 def genCompositeTypeSrc (type):
398         yield "%s %s" % (type.getClassName(), type.name)
399         yield "{"
400         for line in indentLines(["\t%s\t%s;" % (m.type, m.name) for m in type.members]):
401                 yield line
402         yield "};"
403
404 def genHandlesSrc (handles):
405         def genLines (handles):
406                 for handle in handles:
407                         if handle.type == Handle.TYPE_DISP:
408                                 yield "VK_DEFINE_HANDLE\t(%s,\t%s);" % (handle.name, handle.getHandleType())
409                         elif handle.type == Handle.TYPE_NONDISP:
410                                 yield "VK_DEFINE_NON_DISPATCHABLE_HANDLE\t(%s,\t%s);" % (handle.name, handle.getHandleType())
411
412         for line in indentLines(genLines(handles)):
413                 yield line
414
415 def writeBasicTypes (api, filename):
416         def gen ():
417                 for line in indentLines(["enum { %s\t= %s\t};" % define for define in api.definitions]):
418                         yield line
419                 yield ""
420                 for line in genHandlesSrc(api.handles):
421                         yield line
422                 yield ""
423                 for enum in api.enums:
424                         for line in genEnumSrc(enum):
425                                 yield line
426                         yield ""
427                 for bitfield in api.bitfields:
428                         for line in genBitfieldSrc(bitfield):
429                                 yield line
430                         yield ""
431
432         writeInlFile(filename, INL_HEADER, gen())
433
434 def writeCompositeTypes (api, filename):
435         def gen ():
436                 for type in api.compositeTypes:
437                         for line in genCompositeTypeSrc(type):
438                                 yield line
439                         yield ""
440
441         writeInlFile(filename, INL_HEADER, gen())
442
443 def argListToStr (args):
444         return ", ".join("%s %s%s" % (v.type, v.name, v.arraySize if v.arraySize != None else "") for v in args)
445
446 def writeInterfaceDecl (api, filename, functionTypes, concrete):
447         def genProtos ():
448                 postfix = "" if concrete else " = 0"
449                 for function in api.functions:
450                         if function.getType() in functionTypes:
451                                 yield "virtual %s\t%s\t(%s) const%s;" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments), postfix)
452
453         writeInlFile(filename, INL_HEADER, indentLines(genProtos()))
454
455 def writeFunctionPtrTypes (api, filename):
456         def genTypes ():
457                 for function in api.functions:
458                         yield "typedef VKAPI_ATTR %s\t(VKAPI_CALL* %s)\t(%s);" % (function.returnType, getFunctionTypeName(function), argListToStr(function.arguments))
459
460         writeInlFile(filename, INL_HEADER, indentLines(genTypes()))
461
462 def writeFunctionPointers (api, filename, functionTypes):
463         writeInlFile(filename, INL_HEADER, indentLines(["%s\t%s;" % (getFunctionTypeName(function), getInterfaceName(function)) for function in api.functions if function.getType() in functionTypes]))
464
465 def writeInitFunctionPointers (api, filename, functionTypes):
466         def makeInitFunctionPointers ():
467                 for function in api.functions:
468                         if function.getType() in functionTypes:
469                                 yield "m_vk.%s\t= (%s)\tGET_PROC_ADDR(\"%s\");" % (getInterfaceName(function), getFunctionTypeName(function), function.name)
470
471         writeInlFile(filename, INL_HEADER, indentLines(makeInitFunctionPointers()))
472
473 def writeFuncPtrInterfaceImpl (api, filename, functionTypes, className):
474         def makeFuncPtrInterfaceImpl ():
475                 for function in api.functions:
476                         if function.getType() in functionTypes:
477                                 yield ""
478                                 yield "%s %s::%s (%s) const" % (function.returnType, className, getInterfaceName(function), argListToStr(function.arguments))
479                                 yield "{"
480                                 yield " %sm_vk.%s(%s);" % ("return " if function.returnType != "void" else "", getInterfaceName(function), ", ".join(a.name for a in function.arguments))
481                                 yield "}"
482
483         writeInlFile(filename, INL_HEADER, makeFuncPtrInterfaceImpl())
484
485 def writeStrUtilProto (api, filename):
486         def makeStrUtilProto ():
487                 for line in indentLines(["const char*\tget%sName\t(%s value);" % (enum.name[2:], enum.name) for enum in api.enums]):
488                         yield line
489                 yield ""
490                 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]):
491                         yield line
492                 yield ""
493                 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]):
494                         yield line
495                 yield ""
496                 for line in indentLines(["tcu::Format::Bitfield<32>\tget%sStr\t(%s value);" % (bitfield.name[2:], bitfield.name) for bitfield in api.bitfields]):
497                         yield line
498                 yield ""
499                 for line in indentLines(["std::ostream&\toperator<<\t(std::ostream& s, const %s& value);" % (s.name) for s in api.compositeTypes]):
500                         yield line
501
502         writeInlFile(filename, INL_HEADER, makeStrUtilProto())
503
504 def writeStrUtilImpl (api, filename):
505         def makeStrUtilImpl ():
506                 for line in indentLines(["template<> const char*\tgetTypeName<%s>\t(void) { return \"%s\";\t}" % (handle.name, handle.name) for handle in api.handles]):
507                         yield line
508
509                 for enum in api.enums:
510                         yield ""
511                         yield "const char* get%sName (%s value)" % (enum.name[2:], enum.name)
512                         yield "{"
513                         yield "\tswitch (value)"
514                         yield "\t{"
515                         for line in indentLines(["\t\tcase %s:\treturn \"%s\";" % (n, n) for n, v in enum.values] + ["\t\tdefault:\treturn DE_NULL;"]):
516                                 yield line
517                         yield "\t}"
518                         yield "}"
519
520                 for bitfield in api.bitfields:
521                         yield ""
522                         yield "tcu::Format::Bitfield<32> get%sStr (%s value)" % (bitfield.name[2:], bitfield.name)
523                         yield "{"
524
525                         if len(bitfield.values) > 0:
526                                 yield "\tstatic const tcu::Format::BitDesc s_desc[] ="
527                                 yield "\t{"
528                                 for line in indentLines(["\t\ttcu::Format::BitDesc(%s,\t\"%s\")," % (n, n) for n, v in bitfield.values]):
529                                         yield line
530                                 yield "\t};"
531                                 yield "\treturn tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));"
532                         else:
533                                 yield "\treturn tcu::Format::Bitfield<32>(value, DE_NULL, DE_NULL);"
534
535                         yield "}"
536
537                 bitfieldTypeNames = set([bitfield.name for bitfield in api.bitfields])
538
539                 for type in api.compositeTypes:
540                         yield ""
541                         yield "std::ostream& operator<< (std::ostream& s, const %s& value)" % type.name
542                         yield "{"
543                         yield "\ts << \"%s = {\\n\";" % type.name
544                         for member in type.members:
545                                 memberName      = member.name
546                                 valFmt          = None
547                                 newLine         = ""
548                                 if member.type in bitfieldTypeNames:
549                                         valFmt = "get%sStr(value.%s)" % (member.type[2:], member.name)
550                                 elif member.type == "const char*" or member.type == "char*":
551                                         valFmt = "getCharPtrStr(value.%s)" % member.name
552                                 elif '[' in member.name:
553                                         baseName = member.name[:member.name.find('[')]
554                                         if baseName in ["extensionName", "deviceName", "layerName", "description"]:
555                                                 valFmt = "(const char*)value.%s" % baseName
556                                         elif member.type == 'char' or member.type == 'deUint8':
557                                                 newLine = "'\\n' << "
558                                                 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)
559                                         else:
560                                                 newLine = "'\\n' << "
561                                                 valFmt = "tcu::formatArray(DE_ARRAY_BEGIN(value.%s), DE_ARRAY_END(value.%s))" % (baseName, baseName)
562                                         memberName = baseName
563                                 else:
564                                         valFmt = "value.%s" % member.name
565                                 yield ("\ts << \"\\t%s = \" << " % memberName) + newLine + valFmt + " << '\\n';"
566                         yield "\ts << '}';"
567                         yield "\treturn s;"
568                         yield "}"
569
570
571         writeInlFile(filename, INL_HEADER, makeStrUtilImpl())
572
573 class ConstructorFunction:
574         def __init__ (self, type, name, objectType, iface, arguments):
575                 self.type               = type
576                 self.name               = name
577                 self.objectType = objectType
578                 self.iface              = iface
579                 self.arguments  = arguments
580
581 def getConstructorFunctions (api):
582         funcs = []
583         for function in api.functions:
584                 if (function.name[:8] == "vkCreate" or function.name == "vkAllocateMemory") and not "count" in [a.name for a in function.arguments]:
585                         # \todo [pyry] Rather hacky
586                         iface = None
587                         if function.getType() == Function.TYPE_PLATFORM:
588                                 iface = Variable("const PlatformInterface&", "vk")
589                         elif function.getType() == Function.TYPE_INSTANCE:
590                                 iface = Variable("const InstanceInterface&", "vk")
591                         else:
592                                 iface = Variable("const DeviceInterface&", "vk")
593
594                         assert function.arguments[-2].type == "const VkAllocationCallbacks*"
595
596                         objectType      = function.arguments[-1].type.replace("*", "").strip()
597                         arguments       = function.arguments[:-1]
598                         funcs.append(ConstructorFunction(function.getType(), getInterfaceName(function), objectType, iface, arguments))
599         return funcs
600
601 def writeRefUtilProto (api, filename):
602         functions       = getConstructorFunctions(api)
603
604         def makeRefUtilProto ():
605                 unindented = []
606                 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]):
607                         yield line
608
609         writeInlFile(filename, INL_HEADER, makeRefUtilProto())
610
611 def writeRefUtilImpl (api, filename):
612         functions = getConstructorFunctions(api)
613
614         def makeRefUtilImpl ():
615                 yield "namespace refdetails"
616                 yield "{"
617                 yield ""
618
619                 for function in api.functions:
620                         if function.getType() == Function.TYPE_DEVICE \
621                            and (function.name[:9] == "vkDestroy" or function.name == "vkFreeMemory") \
622                            and not function.name == "vkDestroyDevice":
623                                 objectType = function.arguments[-2].type
624                                 yield "template<>"
625                                 yield "void Deleter<%s>::operator() (%s obj) const" % (objectType, objectType)
626                                 yield "{"
627                                 yield "\tm_deviceIface->%s(m_device, obj, m_allocator);" % (getInterfaceName(function))
628                                 yield "}"
629                                 yield ""
630
631                 yield "} // refdetails"
632                 yield ""
633
634                 for function in functions:
635                         if function.type == Function.TYPE_DEVICE:
636                                 dtorObj = "device"
637                         elif function.type == Function.TYPE_INSTANCE:
638                                 if function.name == "createDevice":
639                                         dtorObj = "object"
640                                 else:
641                                         dtorObj = "instance"
642                         else:
643                                 dtorObj = "object"
644
645                         yield "Move<%s> %s (%s)" % (function.objectType, function.name, argListToStr([function.iface] + function.arguments))
646                         yield "{"
647                         yield "\t%s object = 0;" % function.objectType
648                         yield "\tVK_CHECK(vk.%s(%s));" % (function.name, ", ".join([a.name for a in function.arguments] + ["&object"]))
649                         yield "\treturn Move<%s>(check<%s>(object), Deleter<%s>(%s));" % (function.objectType, function.objectType, function.objectType, ", ".join(["vk", dtorObj, function.arguments[-1].name]))
650                         yield "}"
651                         yield ""
652
653         writeInlFile(filename, INL_HEADER, makeRefUtilImpl())
654
655 def writeNullDriverImpl (api, filename):
656         def genNullDriverImpl ():
657                 specialFuncNames        = [
658                                 "vkCreateGraphicsPipelines",
659                                 "vkCreateComputePipelines",
660                                 "vkGetInstanceProcAddr",
661                                 "vkGetDeviceProcAddr",
662                                 "vkEnumeratePhysicalDevices",
663                                 "vkGetPhysicalDeviceProperties",
664                                 "vkGetPhysicalDeviceQueueFamilyProperties",
665                                 "vkGetPhysicalDeviceMemoryProperties",
666                                 "vkGetPhysicalDeviceFormatProperties",
667                                 "vkGetBufferMemoryRequirements",
668                                 "vkGetImageMemoryRequirements",
669                                 "vkMapMemory",
670                                 "vkAllocateDescriptorSets",
671                                 "vkFreeDescriptorSets",
672                                 "vkResetDescriptorPool",
673                                 "vkAllocateCommandBuffers",
674                                 "vkFreeCommandBuffers"
675                         ]
676                 specialFuncs            = [f for f in api.functions if f.name in specialFuncNames]
677                 createFuncs                     = [f for f in api.functions if (f.name[:8] == "vkCreate" or f.name == "vkAllocateMemory") and not f in specialFuncs]
678                 destroyFuncs            = [f for f in api.functions if (f.name[:9] == "vkDestroy" or f.name == "vkFreeMemory") and not f in specialFuncs]
679                 dummyFuncs                      = [f for f in api.functions if f not in specialFuncs + createFuncs + destroyFuncs]
680
681                 def getHandle (name):
682                         for handle in api.handles:
683                                 if handle.name == name:
684                                         return handle
685                         raise Exception("No such handle: %s" % name)
686
687                 for function in createFuncs:
688                         objectType      = function.arguments[-1].type.replace("*", "").strip()
689                         argsStr         = ", ".join([a.name for a in function.arguments[:-1]])
690
691                         yield "VKAPI_ATTR %s VKAPI_CALL %s (%s)" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments))
692                         yield "{"
693                         yield "\tDE_UNREF(%s);" % function.arguments[-2].name
694
695                         if getHandle(objectType).type == Handle.TYPE_NONDISP:
696                                 yield "\tVK_NULL_RETURN((*%s = allocateNonDispHandle<%s, %s>(%s)));" % (function.arguments[-1].name, objectType[2:], objectType, argsStr)
697                         else:
698                                 yield "\tVK_NULL_RETURN((*%s = allocateHandle<%s, %s>(%s)));" % (function.arguments[-1].name, objectType[2:], objectType, argsStr)
699
700                         yield "}"
701                         yield ""
702
703                 for function in destroyFuncs:
704                         objectArg       = function.arguments[-2]
705
706                         yield "VKAPI_ATTR %s VKAPI_CALL %s (%s)" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments))
707                         yield "{"
708                         for arg in function.arguments[:-2]:
709                                 yield "\tDE_UNREF(%s);" % arg.name
710
711                         if getHandle(objectArg.type).type == Handle.TYPE_NONDISP:
712                                 yield "\tfreeNonDispHandle<%s, %s>(%s, %s);" % (objectArg.type[2:], objectArg.type, objectArg.name, function.arguments[-1].name)
713                         else:
714                                 yield "\tfreeHandle<%s, %s>(%s, %s);" % (objectArg.type[2:], objectArg.type, objectArg.name, function.arguments[-1].name)
715
716                         yield "}"
717                         yield ""
718
719                 for function in dummyFuncs:
720                         yield "VKAPI_ATTR %s VKAPI_CALL %s (%s)" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments))
721                         yield "{"
722                         for arg in function.arguments:
723                                 yield "\tDE_UNREF(%s);" % arg.name
724                         if function.returnType != "void":
725                                 yield "\treturn VK_SUCCESS;"
726                         yield "}"
727                         yield ""
728
729                 def genFuncEntryTable (type, name):
730                         funcs = [f for f in api.functions if f.getType() == type]
731
732                         yield "static const tcu::StaticFunctionLibrary::Entry %s[] =" % name
733                         yield "{"
734                         for line in indentLines(["\tVK_NULL_FUNC_ENTRY(%s,\t%s)," % (function.name, getInterfaceName(function)) for function in funcs]):
735                                 yield line
736                         yield "};"
737                         yield ""
738
739                 # Func tables
740                 for line in genFuncEntryTable(Function.TYPE_PLATFORM, "s_platformFunctions"):
741                         yield line
742
743                 for line in genFuncEntryTable(Function.TYPE_INSTANCE, "s_instanceFunctions"):
744                         yield line
745
746                 for line in genFuncEntryTable(Function.TYPE_DEVICE, "s_deviceFunctions"):
747                         yield line
748
749
750         writeInlFile(filename, INL_HEADER, genNullDriverImpl())
751
752 def writeTypeUtil (api, filename):
753         # Structs filled by API queries are not often used in test code
754         QUERY_RESULT_TYPES = set([
755                         "VkPhysicalDeviceFeatures",
756                         "VkPhysicalDeviceLimits",
757                         "VkFormatProperties",
758                         "VkImageFormatProperties",
759                         "VkPhysicalDeviceSparseProperties",
760                         "VkQueueFamilyProperties",
761                         "VkMemoryType",
762                         "VkMemoryHeap",
763                 ])
764         COMPOSITE_TYPES = set([t.name for t in api.compositeTypes])
765
766         def isSimpleStruct (type):
767                 def hasArrayMember (type):
768                         for member in type.members:
769                                 if "[" in member.name:
770                                         return True
771                         return False
772
773                 def hasCompositeMember (type):
774                         for member in type.members:
775                                 if member.type in COMPOSITE_TYPES:
776                                         return True
777                         return False
778
779                 return type.typeClass == CompositeType.CLASS_STRUCT and \
780                            type.members[0].type != "VkStructureType" and \
781                            not type.name in QUERY_RESULT_TYPES and \
782                            not hasArrayMember(type) and \
783                            not hasCompositeMember(type)
784
785         def gen ():
786                 for type in api.compositeTypes:
787                         if not isSimpleStruct(type):
788                                 continue
789
790                         yield ""
791                         yield "inline %s make%s (%s)" % (type.name, type.name[2:], argListToStr(type.members))
792                         yield "{"
793                         yield "\t%s res;" % type.name
794                         for line in indentLines(["\tres.%s\t= %s;" % (m.name, m.name) for m in type.members]):
795                                 yield line
796                         yield "\treturn res;"
797                         yield "}"
798
799         writeInlFile(filename, INL_HEADER, gen())
800
801 if __name__ == "__main__":
802         src                             = readFile(sys.argv[1])
803         api                             = parseAPI(src)
804         platformFuncs   = set([Function.TYPE_PLATFORM])
805         instanceFuncs   = set([Function.TYPE_INSTANCE])
806         deviceFuncs             = set([Function.TYPE_DEVICE])
807
808         writeHandleType                         (api, os.path.join(VULKAN_DIR, "vkHandleType.inl"))
809         writeBasicTypes                         (api, os.path.join(VULKAN_DIR, "vkBasicTypes.inl"))
810         writeCompositeTypes                     (api, os.path.join(VULKAN_DIR, "vkStructTypes.inl"))
811         writeInterfaceDecl                      (api, os.path.join(VULKAN_DIR, "vkVirtualPlatformInterface.inl"),               functionTypes = platformFuncs,  concrete = False)
812         writeInterfaceDecl                      (api, os.path.join(VULKAN_DIR, "vkVirtualInstanceInterface.inl"),               functionTypes = instanceFuncs,  concrete = False)
813         writeInterfaceDecl                      (api, os.path.join(VULKAN_DIR, "vkVirtualDeviceInterface.inl"),                 functionTypes = deviceFuncs,    concrete = False)
814         writeInterfaceDecl                      (api, os.path.join(VULKAN_DIR, "vkConcretePlatformInterface.inl"),              functionTypes = platformFuncs,  concrete = True)
815         writeInterfaceDecl                      (api, os.path.join(VULKAN_DIR, "vkConcreteInstanceInterface.inl"),              functionTypes = instanceFuncs,  concrete = True)
816         writeInterfaceDecl                      (api, os.path.join(VULKAN_DIR, "vkConcreteDeviceInterface.inl"),                functionTypes = deviceFuncs,    concrete = True)
817         writeFunctionPtrTypes           (api, os.path.join(VULKAN_DIR, "vkFunctionPointerTypes.inl"))
818         writeFunctionPointers           (api, os.path.join(VULKAN_DIR, "vkPlatformFunctionPointers.inl"),               functionTypes = platformFuncs)
819         writeFunctionPointers           (api, os.path.join(VULKAN_DIR, "vkInstanceFunctionPointers.inl"),               functionTypes = instanceFuncs)
820         writeFunctionPointers           (api, os.path.join(VULKAN_DIR, "vkDeviceFunctionPointers.inl"),                 functionTypes = deviceFuncs)
821         writeInitFunctionPointers       (api, os.path.join(VULKAN_DIR, "vkInitPlatformFunctionPointers.inl"),   functionTypes = platformFuncs)
822         writeInitFunctionPointers       (api, os.path.join(VULKAN_DIR, "vkInitInstanceFunctionPointers.inl"),   functionTypes = instanceFuncs)
823         writeInitFunctionPointers       (api, os.path.join(VULKAN_DIR, "vkInitDeviceFunctionPointers.inl"),             functionTypes = deviceFuncs)
824         writeFuncPtrInterfaceImpl       (api, os.path.join(VULKAN_DIR, "vkPlatformDriverImpl.inl"),                             functionTypes = platformFuncs,  className = "PlatformDriver")
825         writeFuncPtrInterfaceImpl       (api, os.path.join(VULKAN_DIR, "vkInstanceDriverImpl.inl"),                             functionTypes = instanceFuncs,  className = "InstanceDriver")
826         writeFuncPtrInterfaceImpl       (api, os.path.join(VULKAN_DIR, "vkDeviceDriverImpl.inl"),                               functionTypes = deviceFuncs,    className = "DeviceDriver")
827         writeStrUtilProto                       (api, os.path.join(VULKAN_DIR, "vkStrUtil.inl"))
828         writeStrUtilImpl                        (api, os.path.join(VULKAN_DIR, "vkStrUtilImpl.inl"))
829         writeRefUtilProto                       (api, os.path.join(VULKAN_DIR, "vkRefUtil.inl"))
830         writeRefUtilImpl                        (api, os.path.join(VULKAN_DIR, "vkRefUtilImpl.inl"))
831         writeNullDriverImpl                     (api, os.path.join(VULKAN_DIR, "vkNullDriverImpl.inl"))
832         writeTypeUtil                           (api, os.path.join(VULKAN_DIR, "vkTypeUtil.inl"))