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