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