01495026f0e7ebad5ed3b5351a50576dcdc4ed35
[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 Confidential Information as defined by the
21 # Khronos Membership Agreement until designated non-confidential by
22 # Khronos, at which point this condition clause shall be removed.
23 #
24 # THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
27 # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
28 # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
29 # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
30 # MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
31 #
32 #-------------------------------------------------------------------------
33
34 import os
35 import re
36 import sys
37
38 sys.path.append(os.path.join(os.path.dirname(__file__), "..", "..", "scripts"))
39
40 from build.common import DEQP_DIR
41 from khr_util.format import indentLines, writeInlFile
42
43 VULKAN_DIR = os.path.join(os.path.dirname(__file__), "framework", "vulkan")
44
45 INL_HEADER = """\
46 /* WARNING: This is auto-generated file. Do not modify, since changes will
47  * be lost! Modify the generating script instead.
48  */\
49 """
50
51 PLATFORM_FUNCTIONS      = [
52         "vkCreateInstance",
53         "vkGetInstanceProcAddr",
54         "vkEnumerateInstanceExtensionProperties",
55         "vkEnumerateInstanceLayerProperties",
56 ]
57 INSTANCE_FUNCTIONS      = [
58         "vkDestroyInstance",
59         "vkEnumeratePhysicalDevices",
60         "vkGetPhysicalDeviceFeatures",
61         "vkGetPhysicalDeviceFormatProperties",
62         "vkGetPhysicalDeviceImageFormatProperties",
63         "vkGetPhysicalDeviceLimits",
64         "vkGetPhysicalDeviceProperties",
65         "vkGetPhysicalDeviceQueueFamilyProperties",
66         "vkGetPhysicalDeviceMemoryProperties",
67         "vkEnumerateDeviceExtensionProperties",
68         "vkEnumerateDeviceLayerProperties",
69         "vkCreateDevice",
70         "vkGetDeviceProcAddr",
71 ]
72
73 DEFINITIONS                     = [
74         "VK_API_VERSION",
75         "VK_MAX_PHYSICAL_DEVICE_NAME_SIZE",
76         "VK_MAX_EXTENSION_NAME_SIZE",
77         "VK_UUID_SIZE",
78         "VK_MAX_MEMORY_TYPES",
79         "VK_MAX_MEMORY_HEAPS",
80         "VK_MAX_DESCRIPTION_SIZE",
81         "VK_ATTACHMENT_UNUSED",
82 ]
83
84 class Handle:
85         TYPE_DISP               = 0
86         TYPE_NONDISP    = 1
87
88         def __init__ (self, type, name):
89                 self.type       = type
90                 self.name       = name
91
92         def getHandleType (self):
93                 name = re.sub(r'([a-z])([A-Z])', r'\1_\2', self.name)
94                 return "HANDLE_TYPE_" + name[3:].upper()
95
96 class Enum:
97         def __init__ (self, name, values):
98                 self.name       = name
99                 self.values     = values
100
101 class Bitfield:
102         def __init__ (self, name, values):
103                 self.name       = name
104                 self.values     = values
105
106 class Variable:
107         def __init__ (self, type, name, arraySize = None):
108                 self.type               = type
109                 self.name               = name
110                 self.arraySize  = arraySize
111
112 class CompositeType:
113         CLASS_STRUCT    = 0
114         CLASS_UNION             = 1
115
116         def __init__ (self, typeClass, name, members):
117                 self.typeClass  = typeClass
118                 self.name               = name
119                 self.members    = members
120
121         def getClassName (self):
122                 names = {CompositeType.CLASS_STRUCT: 'struct', CompositeType.CLASS_UNION: 'union'}
123                 return names[self.typeClass]
124
125 class Function:
126         TYPE_PLATFORM           = 0 # Not bound to anything
127         TYPE_INSTANCE           = 1 # Bound to VkInstance
128         TYPE_DEVICE                     = 2 # Bound to VkDevice
129
130         def __init__ (self, name, returnType, arguments):
131                 self.name               = name
132                 self.returnType = returnType
133                 self.arguments  = arguments
134
135         def getType (self):
136                 if self.name in PLATFORM_FUNCTIONS:
137                         return Function.TYPE_PLATFORM
138                 elif self.name in INSTANCE_FUNCTIONS:
139                         return Function.TYPE_INSTANCE
140                 else:
141                         return Function.TYPE_DEVICE
142
143 class API:
144         def __init__ (self, definitions, handles, enums, bitfields, compositeTypes, functions):
145                 self.definitions        = definitions
146                 self.handles            = handles
147                 self.enums                      = enums
148                 self.bitfields          = bitfields
149                 self.compositeTypes     = compositeTypes
150                 self.functions          = functions
151
152 def readFile (filename):
153         with open(filename, 'rb') as f:
154                 return f.read()
155
156 IDENT_PTRN      = r'[a-zA-Z_][a-zA-Z0-9_]*'
157 TYPE_PTRN       = r'[a-zA-Z_][a-zA-Z0-9_ \t*]*'
158
159 def endswith (s, postfix):
160         return len(s) >= len(postfix) and s[len(s)-len(postfix):] == postfix
161
162 def fixupEnumValues (values):
163         fixed = []
164         for name, value in values:
165                 if endswith(name, "_BEGIN_RANGE") or endswith(name, "_END_RANGE"):
166                         continue
167                 fixed.append((name, value))
168         return fixed
169
170 def fixupType (type):
171         replacements = [
172                         ("uint8_t",             "deUint8"),
173                         ("uint16_t",    "deUint16"),
174                         ("uint32_t",    "deUint32"),
175                         ("uint64_t",    "deUint64"),
176                         ("int8_t",              "deInt8"),
177                         ("int16_t",             "deInt16"),
178                         ("int32_t",             "deInt32"),
179                         ("int64_t",             "deInt64"),
180                         ("bool32_t",    "deUint32"),
181                         ("size_t",              "deUintptr"),
182                 ]
183
184         for src, dst in replacements:
185                 type = type.replace(src, dst)
186
187         return type
188
189 def fixupFunction (function):
190         fixedArgs               = [Variable(fixupType(a.type), a.name, a.arraySize) for a in function.arguments]
191         fixedReturnType = fixupType(function.returnType)
192
193         return Function(function.name, fixedReturnType, fixedArgs)
194
195 def getInterfaceName (function):
196         assert function.name[:2] == "vk"
197         return function.name[2].lower() + function.name[3:]
198
199 def getFunctionTypeName (function):
200         assert function.name[:2] == "vk"
201         return function.name[2:] + "Func"
202
203 def getBitEnumNameForBitfield (bitfieldName):
204         if bitfieldName[-3:] == "KHR":
205                 postfix = "KHR"
206                 bitfieldName = bitfieldName[:-3]
207         else:
208                 postfix = ""
209
210         assert bitfieldName[-1] == "s"
211         return bitfieldName[:-1] + "Bits" + postfix
212
213 def getBitfieldNameForBitEnum (bitEnumName):
214         if bitEnumName[-3:] == "KHR":
215                 postfix = "KHR"
216                 bitEnumName = bitEnumName[:-3]
217         else:
218                 postfix = ""
219
220         assert bitEnumName[-4:] == "Bits"
221         return bitEnumName[:-4] + "s" + postfix
222
223 def parsePreprocDefinedValue (src, name):
224         definition = re.search(r'#\s*define\s+' + name + r'\s+([^\n]+)\n', src)
225         if definition is None:
226                 raise Exception("No such definition: %s" % name)
227         value = definition.group(1).strip()
228
229         if value == "UINT32_MAX":
230                 value = "(~0u)"
231
232         return value
233
234 def parseEnum (name, src):
235         keyValuePtrn    = '(' + IDENT_PTRN + r')\s*=\s*([^\s,}]+)\s*[,}]'
236         matches                 = re.findall(keyValuePtrn, src)
237
238         return Enum(name, fixupEnumValues(matches))
239
240 # \note Parses raw enums, some are mapped to bitfields later
241 def parseEnums (src):
242         matches = re.findall(r'typedef enum(\s*' + IDENT_PTRN + r')?\s*{([^}]*)}\s*(' + IDENT_PTRN + r')\s*;', src)
243         enums   = []
244
245         for enumname, contents, typename in matches:
246                 enums.append(parseEnum(typename, contents))
247
248         return enums
249
250 def parseCompositeType (type, name, src):
251         # \todo [pyry] Array support is currently a hack (size coupled with name)
252         typeNamePtrn    = r'(' + TYPE_PTRN + ')(\s' + IDENT_PTRN + r'(\[[^\]]+\])*)\s*;'
253         matches                 = re.findall(typeNamePtrn, src)
254         members                 = [Variable(fixupType(t.strip()), n.strip()) for t, n, a in matches]
255
256         return CompositeType(type, name, members)
257
258 def parseCompositeTypes (src):
259         typeMap = { 'struct': CompositeType.CLASS_STRUCT, 'union': CompositeType.CLASS_UNION }
260         matches = re.findall(r'typedef (struct|union)(\s*' + IDENT_PTRN + r')?\s*{([^}]*)}\s*(' + IDENT_PTRN + r')\s*;', src)
261         types   = []
262
263         for type, structname, contents, typename in matches:
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 ["extName", "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[:-2]
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);" % (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, DE_NULL);" % (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] + ["DE_NULL", "&object"]))
637                         yield "\treturn Move<%s>(check<%s>(object), Deleter<%s>(vk, %s));" % (function.objectType, function.objectType, function.objectType, dtorObj)
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                                 "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[:-2]])
677
678                         yield "%s %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 = %s((deUint64)(deUintptr)new %s(%s)));" % (function.arguments[-1].name, objectType, objectType[2:], argsStr)
684                         else:
685                                 yield "\tVK_NULL_RETURN(*%s = reinterpret_cast<%s>(new %s(%s)));" % (function.arguments[-1].name, objectType, objectType[2:], argsStr)
686
687                         yield "}"
688                         yield ""
689
690                 for function in destroyFuncs:
691                         objectArg       = function.arguments[-2]
692
693                         yield "%s %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                         yield "\tDE_UNREF(%s);" % function.arguments[-1].name
698
699                         if getHandle(objectArg.type).type == Handle.TYPE_NONDISP:
700                                 yield "\tdelete reinterpret_cast<%s*>((deUintptr)%s.getInternal());" % (objectArg.type[2:], objectArg.name)
701                         else:
702                                 yield "\tdelete reinterpret_cast<%s*>(%s);" % (objectArg.type[2:], objectArg.name)
703
704                         yield "}"
705                         yield ""
706
707                 for function in dummyFuncs:
708                         yield "%s %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"))