Merge in code from gles32-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 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                 if typename[-3:] == "KHR":
265                         continue # \todo [2016-01-05 pyry] Figure out how to handle platform-specific types
266
267                 types.append(parseCompositeType(typeMap[type], typename, contents))
268
269         return types
270
271 def parseHandles (src):
272         matches = re.findall(r'VK_DEFINE(_NON_DISPATCHABLE|)_HANDLE\((' + IDENT_PTRN + r')\)[ \t]*[\n\r]', src)
273         handles = []
274         typeMap = {'': Handle.TYPE_DISP, '_NON_DISPATCHABLE': Handle.TYPE_NONDISP}
275
276         for type, name in matches:
277                 handle = Handle(typeMap[type], name)
278                 handles.append(handle)
279
280         return handles
281
282 def parseArgList (src):
283         typeNamePtrn    = r'(' + TYPE_PTRN + ')(\s' + IDENT_PTRN + r')(\[[^\]]+\])?'
284         args                    = []
285
286         for rawArg in src.split(','):
287                 m = re.search(typeNamePtrn, rawArg)
288                 args.append(Variable(m.group(1).strip(), m.group(2).strip(), m.group(3)))
289
290         return args
291
292 def parseFunctions (src):
293         ptrn            = r'VKAPI_ATTR\s+(' + TYPE_PTRN + ')VKAPI_CALL\s+(' + IDENT_PTRN + r')\s*\(([^)]*)\)\s*;'
294         matches         = re.findall(ptrn, src)
295         functions       = []
296
297         for returnType, name, argList in matches:
298                 if name[-3:] == "KHR":
299                         continue # \todo [2015-11-16 pyry] Figure out how to handle platform-specific extension functions
300
301                 functions.append(Function(name.strip(), returnType.strip(), parseArgList(argList)))
302
303         return [fixupFunction(f) for f in functions]
304
305 def parseBitfieldNames (src):
306         ptrn            = r'typedef\s+VkFlags\s(' + IDENT_PTRN + r')\s*;'
307         matches         = re.findall(ptrn, src)
308
309         return matches
310
311 def parseAPI (src):
312         definitions             = [(name, parsePreprocDefinedValue(src, name)) for name in DEFINITIONS]
313         rawEnums                = parseEnums(src)
314         bitfieldNames   = parseBitfieldNames(src)
315         enums                   = []
316         bitfields               = []
317         bitfieldEnums   = set([getBitEnumNameForBitfield(n) for n in bitfieldNames])
318
319         for enum in rawEnums:
320                 if enum.name in bitfieldEnums:
321                         bitfields.append(Bitfield(getBitfieldNameForBitEnum(enum.name), enum.values))
322                 else:
323                         enums.append(enum)
324
325         for bitfieldName in bitfieldNames:
326                 if not bitfieldName in [bitfield.name for bitfield in bitfields]:
327                         # Add empty bitfield
328                         bitfields.append(Bitfield(bitfieldName, []))
329
330         return API(
331                 definitions             = definitions,
332                 handles                 = parseHandles(src),
333                 enums                   = enums,
334                 bitfields               = bitfields,
335                 compositeTypes  = parseCompositeTypes(src),
336                 functions               = parseFunctions(src))
337
338 def writeHandleType (api, filename):
339         def gen ():
340                 yield "enum HandleType"
341                 yield "{"
342                 yield "\t%s = 0," % api.handles[0].getHandleType()
343                 for handle in api.handles[1:]:
344                         yield "\t%s," % handle.getHandleType()
345                 yield "\tHANDLE_TYPE_LAST"
346                 yield "};"
347                 yield ""
348
349         writeInlFile(filename, INL_HEADER, gen())
350
351 def getEnumValuePrefix (enum):
352         prefix = enum.name[0]
353         for i in range(1, len(enum.name)):
354                 if enum.name[i].isupper():
355                         prefix += "_"
356                 prefix += enum.name[i].upper()
357         return prefix
358
359 def parseInt (value):
360         if value[:2] == "0x":
361                 return int(value, 16)
362         else:
363                 return int(value, 10)
364
365 def areEnumValuesLinear (enum):
366         curIndex = 0
367         for name, value in enum.values:
368                 if parseInt(value) != curIndex:
369                         return False
370                 curIndex += 1
371         return True
372
373 def genEnumSrc (enum):
374         yield "enum %s" % enum.name
375         yield "{"
376
377         for line in indentLines(["\t%s\t= %s," % v for v in enum.values]):
378                 yield line
379
380         if areEnumValuesLinear(enum):
381                 yield ""
382                 yield "\t%s_LAST" % getEnumValuePrefix(enum)
383
384         yield "};"
385
386 def genBitfieldSrc (bitfield):
387         if len(bitfield.values) > 0:
388                 yield "enum %s" % getBitEnumNameForBitfield(bitfield.name)
389                 yield "{"
390                 for line in indentLines(["\t%s\t= %s," % v for v in bitfield.values]):
391                         yield line
392                 yield "};"
393
394         yield "typedef deUint32 %s;" % bitfield.name
395
396 def genCompositeTypeSrc (type):
397         yield "%s %s" % (type.getClassName(), type.name)
398         yield "{"
399         for line in indentLines(["\t%s\t%s;" % (m.type, m.name) for m in type.members]):
400                 yield line
401         yield "};"
402
403 def genHandlesSrc (handles):
404         def genLines (handles):
405                 for handle in handles:
406                         if handle.type == Handle.TYPE_DISP:
407                                 yield "VK_DEFINE_HANDLE\t(%s,\t%s);" % (handle.name, handle.getHandleType())
408                         elif handle.type == Handle.TYPE_NONDISP:
409                                 yield "VK_DEFINE_NON_DISPATCHABLE_HANDLE\t(%s,\t%s);" % (handle.name, handle.getHandleType())
410
411         for line in indentLines(genLines(handles)):
412                 yield line
413
414 def writeBasicTypes (api, filename):
415         def gen ():
416                 for line in indentLines(["enum { %s\t= %s\t};" % define for define in api.definitions]):
417                         yield line
418                 yield ""
419                 for line in genHandlesSrc(api.handles):
420                         yield line
421                 yield ""
422                 for enum in api.enums:
423                         for line in genEnumSrc(enum):
424                                 yield line
425                         yield ""
426                 for bitfield in api.bitfields:
427                         for line in genBitfieldSrc(bitfield):
428                                 yield line
429                         yield ""
430
431         writeInlFile(filename, INL_HEADER, gen())
432
433 def writeCompositeTypes (api, filename):
434         def gen ():
435                 for type in api.compositeTypes:
436                         for line in genCompositeTypeSrc(type):
437                                 yield line
438                         yield ""
439
440         writeInlFile(filename, INL_HEADER, gen())
441
442 def argListToStr (args):
443         return ", ".join("%s %s%s" % (v.type, v.name, v.arraySize if v.arraySize != None else "") for v in args)
444
445 def writeInterfaceDecl (api, filename, functionTypes, concrete):
446         def genProtos ():
447                 postfix = "" if concrete else " = 0"
448                 for function in api.functions:
449                         if function.getType() in functionTypes:
450                                 yield "virtual %s\t%s\t(%s) const%s;" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments), postfix)
451
452         writeInlFile(filename, INL_HEADER, indentLines(genProtos()))
453
454 def writeFunctionPtrTypes (api, filename):
455         def genTypes ():
456                 for function in api.functions:
457                         yield "typedef VKAPI_ATTR %s\t(VKAPI_CALL* %s)\t(%s);" % (function.returnType, getFunctionTypeName(function), argListToStr(function.arguments))
458
459         writeInlFile(filename, INL_HEADER, indentLines(genTypes()))
460
461 def writeFunctionPointers (api, filename, functionTypes):
462         writeInlFile(filename, INL_HEADER, indentLines(["%s\t%s;" % (getFunctionTypeName(function), getInterfaceName(function)) for function in api.functions if function.getType() in functionTypes]))
463
464 def writeInitFunctionPointers (api, filename, functionTypes):
465         def makeInitFunctionPointers ():
466                 for function in api.functions:
467                         if function.getType() in functionTypes:
468                                 yield "m_vk.%s\t= (%s)\tGET_PROC_ADDR(\"%s\");" % (getInterfaceName(function), getFunctionTypeName(function), function.name)
469
470         writeInlFile(filename, INL_HEADER, indentLines(makeInitFunctionPointers()))
471
472 def writeFuncPtrInterfaceImpl (api, filename, functionTypes, className):
473         def makeFuncPtrInterfaceImpl ():
474                 for function in api.functions:
475                         if function.getType() in functionTypes:
476                                 yield ""
477                                 yield "%s %s::%s (%s) const" % (function.returnType, className, getInterfaceName(function), argListToStr(function.arguments))
478                                 yield "{"
479                                 yield " %sm_vk.%s(%s);" % ("return " if function.returnType != "void" else "", getInterfaceName(function), ", ".join(a.name for a in function.arguments))
480                                 yield "}"
481
482         writeInlFile(filename, INL_HEADER, makeFuncPtrInterfaceImpl())
483
484 def writeStrUtilProto (api, filename):
485         def makeStrUtilProto ():
486                 for line in indentLines(["const char*\tget%sName\t(%s value);" % (enum.name[2:], enum.name) for enum in api.enums]):
487                         yield line
488                 yield ""
489                 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]):
490                         yield line
491                 yield ""
492                 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]):
493                         yield line
494                 yield ""
495                 for line in indentLines(["tcu::Format::Bitfield<32>\tget%sStr\t(%s value);" % (bitfield.name[2:], bitfield.name) for bitfield in api.bitfields]):
496                         yield line
497                 yield ""
498                 for line in indentLines(["std::ostream&\toperator<<\t(std::ostream& s, const %s& value);" % (s.name) for s in api.compositeTypes]):
499                         yield line
500
501         writeInlFile(filename, INL_HEADER, makeStrUtilProto())
502
503 def writeStrUtilImpl (api, filename):
504         def makeStrUtilImpl ():
505                 for line in indentLines(["template<> const char*\tgetTypeName<%s>\t(void) { return \"%s\";\t}" % (handle.name, handle.name) for handle in api.handles]):
506                         yield line
507
508                 for enum in api.enums:
509                         yield ""
510                         yield "const char* get%sName (%s value)" % (enum.name[2:], enum.name)
511                         yield "{"
512                         yield "\tswitch (value)"
513                         yield "\t{"
514                         for line in indentLines(["\t\tcase %s:\treturn \"%s\";" % (n, n) for n, v in enum.values] + ["\t\tdefault:\treturn DE_NULL;"]):
515                                 yield line
516                         yield "\t}"
517                         yield "}"
518
519                 for bitfield in api.bitfields:
520                         yield ""
521                         yield "tcu::Format::Bitfield<32> get%sStr (%s value)" % (bitfield.name[2:], bitfield.name)
522                         yield "{"
523
524                         if len(bitfield.values) > 0:
525                                 yield "\tstatic const tcu::Format::BitDesc s_desc[] ="
526                                 yield "\t{"
527                                 for line in indentLines(["\t\ttcu::Format::BitDesc(%s,\t\"%s\")," % (n, n) for n, v in bitfield.values]):
528                                         yield line
529                                 yield "\t};"
530                                 yield "\treturn tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));"
531                         else:
532                                 yield "\treturn tcu::Format::Bitfield<32>(value, DE_NULL, DE_NULL);"
533
534                         yield "}"
535
536                 bitfieldTypeNames = set([bitfield.name for bitfield in api.bitfields])
537
538                 for type in api.compositeTypes:
539                         yield ""
540                         yield "std::ostream& operator<< (std::ostream& s, const %s& value)" % type.name
541                         yield "{"
542                         yield "\ts << \"%s = {\\n\";" % type.name
543                         for member in type.members:
544                                 memberName      = member.name
545                                 valFmt          = None
546                                 newLine         = ""
547                                 if member.type in bitfieldTypeNames:
548                                         valFmt = "get%sStr(value.%s)" % (member.type[2:], member.name)
549                                 elif member.type == "const char*" or member.type == "char*":
550                                         valFmt = "getCharPtrStr(value.%s)" % member.name
551                                 elif '[' in member.name:
552                                         baseName = member.name[:member.name.find('[')]
553                                         if baseName in ["extensionName", "deviceName", "layerName", "description"]:
554                                                 valFmt = "(const char*)value.%s" % baseName
555                                         elif member.type == 'char' or member.type == 'deUint8':
556                                                 newLine = "'\\n' << "
557                                                 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)
558                                         else:
559                                                 newLine = "'\\n' << "
560                                                 valFmt = "tcu::formatArray(DE_ARRAY_BEGIN(value.%s), DE_ARRAY_END(value.%s))" % (baseName, baseName)
561                                         memberName = baseName
562                                 else:
563                                         valFmt = "value.%s" % member.name
564                                 yield ("\ts << \"\\t%s = \" << " % memberName) + newLine + valFmt + " << '\\n';"
565                         yield "\ts << '}';"
566                         yield "\treturn s;"
567                         yield "}"
568
569
570         writeInlFile(filename, INL_HEADER, makeStrUtilImpl())
571
572 class ConstructorFunction:
573         def __init__ (self, type, name, objectType, iface, arguments):
574                 self.type               = type
575                 self.name               = name
576                 self.objectType = objectType
577                 self.iface              = iface
578                 self.arguments  = arguments
579
580 def getConstructorFunctions (api):
581         funcs = []
582         for function in api.functions:
583                 if (function.name[:8] == "vkCreate" or function.name == "vkAllocateMemory") and not "count" in [a.name for a in function.arguments]:
584                         # \todo [pyry] Rather hacky
585                         iface = None
586                         if function.getType() == Function.TYPE_PLATFORM:
587                                 iface = Variable("const PlatformInterface&", "vk")
588                         elif function.getType() == Function.TYPE_INSTANCE:
589                                 iface = Variable("const InstanceInterface&", "vk")
590                         else:
591                                 iface = Variable("const DeviceInterface&", "vk")
592
593                         assert function.arguments[-2].type == "const VkAllocationCallbacks*"
594
595                         objectType      = function.arguments[-1].type.replace("*", "").strip()
596                         arguments       = function.arguments[:-1]
597                         funcs.append(ConstructorFunction(function.getType(), getInterfaceName(function), objectType, iface, arguments))
598         return funcs
599
600 def writeRefUtilProto (api, filename):
601         functions       = getConstructorFunctions(api)
602
603         def makeRefUtilProto ():
604                 unindented = []
605                 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]):
606                         yield line
607
608         writeInlFile(filename, INL_HEADER, makeRefUtilProto())
609
610 def writeRefUtilImpl (api, filename):
611         functions = getConstructorFunctions(api)
612
613         def makeRefUtilImpl ():
614                 yield "namespace refdetails"
615                 yield "{"
616                 yield ""
617
618                 for function in api.functions:
619                         if function.getType() == Function.TYPE_DEVICE \
620                            and (function.name[:9] == "vkDestroy" or function.name == "vkFreeMemory") \
621                            and not function.name == "vkDestroyDevice":
622                                 objectType = function.arguments[-2].type
623                                 yield "template<>"
624                                 yield "void Deleter<%s>::operator() (%s obj) const" % (objectType, objectType)
625                                 yield "{"
626                                 yield "\tm_deviceIface->%s(m_device, obj, m_allocator);" % (getInterfaceName(function))
627                                 yield "}"
628                                 yield ""
629
630                 yield "} // refdetails"
631                 yield ""
632
633                 for function in functions:
634                         dtorObj = "device" if function.type == Function.TYPE_DEVICE else "object"
635
636                         yield "Move<%s> %s (%s)" % (function.objectType, function.name, argListToStr([function.iface] + function.arguments))
637                         yield "{"
638                         yield "\t%s object = 0;" % function.objectType
639                         yield "\tVK_CHECK(vk.%s(%s));" % (function.name, ", ".join([a.name for a in function.arguments] + ["&object"]))
640                         yield "\treturn Move<%s>(check<%s>(object), Deleter<%s>(%s));" % (function.objectType, function.objectType, function.objectType, ", ".join(["vk", dtorObj, function.arguments[-1].name]))
641                         yield "}"
642                         yield ""
643
644         writeInlFile(filename, INL_HEADER, makeRefUtilImpl())
645
646 def writeNullDriverImpl (api, filename):
647         def genNullDriverImpl ():
648                 specialFuncNames        = [
649                                 "vkCreateGraphicsPipelines",
650                                 "vkCreateComputePipelines",
651                                 "vkGetInstanceProcAddr",
652                                 "vkGetDeviceProcAddr",
653                                 "vkEnumeratePhysicalDevices",
654                                 "vkGetPhysicalDeviceProperties",
655                                 "vkGetPhysicalDeviceQueueFamilyProperties",
656                                 "vkGetPhysicalDeviceMemoryProperties",
657                                 "vkGetPhysicalDeviceFormatProperties",
658                                 "vkGetBufferMemoryRequirements",
659                                 "vkGetImageMemoryRequirements",
660                                 "vkMapMemory",
661                                 "vkAllocateDescriptorSets",
662                                 "vkFreeDescriptorSets",
663                                 "vkResetDescriptorPool",
664                                 "vkAllocateCommandBuffers",
665                                 "vkFreeCommandBuffers"
666                         ]
667                 specialFuncs            = [f for f in api.functions if f.name in specialFuncNames]
668                 createFuncs                     = [f for f in api.functions if (f.name[:8] == "vkCreate" or f.name == "vkAllocateMemory") and not f in specialFuncs]
669                 destroyFuncs            = [f for f in api.functions if (f.name[:9] == "vkDestroy" or f.name == "vkFreeMemory") and not f in specialFuncs]
670                 dummyFuncs                      = [f for f in api.functions if f not in specialFuncs + createFuncs + destroyFuncs]
671
672                 def getHandle (name):
673                         for handle in api.handles:
674                                 if handle.name == name:
675                                         return handle
676                         raise Exception("No such handle: %s" % name)
677
678                 for function in createFuncs:
679                         objectType      = function.arguments[-1].type.replace("*", "").strip()
680                         argsStr         = ", ".join([a.name for a in function.arguments[:-1]])
681
682                         yield "VKAPI_ATTR %s VKAPI_CALL %s (%s)" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments))
683                         yield "{"
684                         yield "\tDE_UNREF(%s);" % function.arguments[-2].name
685
686                         if getHandle(objectType).type == Handle.TYPE_NONDISP:
687                                 yield "\tVK_NULL_RETURN((*%s = allocateNonDispHandle<%s, %s>(%s)));" % (function.arguments[-1].name, objectType[2:], objectType, argsStr)
688                         else:
689                                 yield "\tVK_NULL_RETURN((*%s = allocateHandle<%s, %s>(%s)));" % (function.arguments[-1].name, objectType[2:], objectType, argsStr)
690
691                         yield "}"
692                         yield ""
693
694                 for function in destroyFuncs:
695                         objectArg       = function.arguments[-2]
696
697                         yield "VKAPI_ATTR %s VKAPI_CALL %s (%s)" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments))
698                         yield "{"
699                         for arg in function.arguments[:-2]:
700                                 yield "\tDE_UNREF(%s);" % arg.name
701
702                         if getHandle(objectArg.type).type == Handle.TYPE_NONDISP:
703                                 yield "\tfreeNonDispHandle<%s, %s>(%s, %s);" % (objectArg.type[2:], objectArg.type, objectArg.name, function.arguments[-1].name)
704                         else:
705                                 yield "\tfreeHandle<%s, %s>(%s, %s);" % (objectArg.type[2:], objectArg.type, objectArg.name, function.arguments[-1].name)
706
707                         yield "}"
708                         yield ""
709
710                 for function in dummyFuncs:
711                         yield "VKAPI_ATTR %s VKAPI_CALL %s (%s)" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments))
712                         yield "{"
713                         for arg in function.arguments:
714                                 yield "\tDE_UNREF(%s);" % arg.name
715                         if function.returnType != "void":
716                                 yield "\treturn VK_SUCCESS;"
717                         yield "}"
718                         yield ""
719
720                 def genFuncEntryTable (type, name):
721                         funcs = [f for f in api.functions if f.getType() == type]
722
723                         yield "static const tcu::StaticFunctionLibrary::Entry %s[] =" % name
724                         yield "{"
725                         for line in indentLines(["\tVK_NULL_FUNC_ENTRY(%s,\t%s)," % (function.name, getInterfaceName(function)) for function in funcs]):
726                                 yield line
727                         yield "};"
728                         yield ""
729
730                 # Func tables
731                 for line in genFuncEntryTable(Function.TYPE_PLATFORM, "s_platformFunctions"):
732                         yield line
733
734                 for line in genFuncEntryTable(Function.TYPE_INSTANCE, "s_instanceFunctions"):
735                         yield line
736
737                 for line in genFuncEntryTable(Function.TYPE_DEVICE, "s_deviceFunctions"):
738                         yield line
739
740
741         writeInlFile(filename, INL_HEADER, genNullDriverImpl())
742
743 def writeTypeUtil (api, filename):
744         # Structs filled by API queries are not often used in test code
745         QUERY_RESULT_TYPES = set([
746                         "VkPhysicalDeviceFeatures",
747                         "VkPhysicalDeviceLimits",
748                         "VkFormatProperties",
749                         "VkImageFormatProperties",
750                         "VkPhysicalDeviceSparseProperties",
751                         "VkQueueFamilyProperties",
752                         "VkMemoryType",
753                         "VkMemoryHeap",
754                 ])
755         COMPOSITE_TYPES = set([t.name for t in api.compositeTypes])
756
757         def isSimpleStruct (type):
758                 def hasArrayMember (type):
759                         for member in type.members:
760                                 if "[" in member.name:
761                                         return True
762                         return False
763
764                 def hasCompositeMember (type):
765                         for member in type.members:
766                                 if member.type in COMPOSITE_TYPES:
767                                         return True
768                         return False
769
770                 return type.typeClass == CompositeType.CLASS_STRUCT and \
771                            type.members[0].type != "VkStructureType" and \
772                            not type.name in QUERY_RESULT_TYPES and \
773                            not hasArrayMember(type) and \
774                            not hasCompositeMember(type)
775
776         def gen ():
777                 for type in api.compositeTypes:
778                         if not isSimpleStruct(type):
779                                 continue
780
781                         yield ""
782                         yield "inline %s make%s (%s)" % (type.name, type.name[2:], argListToStr(type.members))
783                         yield "{"
784                         yield "\t%s res;" % type.name
785                         for line in indentLines(["\tres.%s\t= %s;" % (m.name, m.name) for m in type.members]):
786                                 yield line
787                         yield "\treturn res;"
788                         yield "}"
789
790         writeInlFile(filename, INL_HEADER, gen())
791
792 if __name__ == "__main__":
793         src                             = readFile(sys.argv[1])
794         api                             = parseAPI(src)
795         platformFuncs   = set([Function.TYPE_PLATFORM])
796         instanceFuncs   = set([Function.TYPE_INSTANCE])
797         deviceFuncs             = set([Function.TYPE_DEVICE])
798
799         writeHandleType                         (api, os.path.join(VULKAN_DIR, "vkHandleType.inl"))
800         writeBasicTypes                         (api, os.path.join(VULKAN_DIR, "vkBasicTypes.inl"))
801         writeCompositeTypes                     (api, os.path.join(VULKAN_DIR, "vkStructTypes.inl"))
802         writeInterfaceDecl                      (api, os.path.join(VULKAN_DIR, "vkVirtualPlatformInterface.inl"),               functionTypes = platformFuncs,  concrete = False)
803         writeInterfaceDecl                      (api, os.path.join(VULKAN_DIR, "vkVirtualInstanceInterface.inl"),               functionTypes = instanceFuncs,  concrete = False)
804         writeInterfaceDecl                      (api, os.path.join(VULKAN_DIR, "vkVirtualDeviceInterface.inl"),                 functionTypes = deviceFuncs,    concrete = False)
805         writeInterfaceDecl                      (api, os.path.join(VULKAN_DIR, "vkConcretePlatformInterface.inl"),              functionTypes = platformFuncs,  concrete = True)
806         writeInterfaceDecl                      (api, os.path.join(VULKAN_DIR, "vkConcreteInstanceInterface.inl"),              functionTypes = instanceFuncs,  concrete = True)
807         writeInterfaceDecl                      (api, os.path.join(VULKAN_DIR, "vkConcreteDeviceInterface.inl"),                functionTypes = deviceFuncs,    concrete = True)
808         writeFunctionPtrTypes           (api, os.path.join(VULKAN_DIR, "vkFunctionPointerTypes.inl"))
809         writeFunctionPointers           (api, os.path.join(VULKAN_DIR, "vkPlatformFunctionPointers.inl"),               functionTypes = platformFuncs)
810         writeFunctionPointers           (api, os.path.join(VULKAN_DIR, "vkInstanceFunctionPointers.inl"),               functionTypes = instanceFuncs)
811         writeFunctionPointers           (api, os.path.join(VULKAN_DIR, "vkDeviceFunctionPointers.inl"),                 functionTypes = deviceFuncs)
812         writeInitFunctionPointers       (api, os.path.join(VULKAN_DIR, "vkInitPlatformFunctionPointers.inl"),   functionTypes = platformFuncs)
813         writeInitFunctionPointers       (api, os.path.join(VULKAN_DIR, "vkInitInstanceFunctionPointers.inl"),   functionTypes = instanceFuncs)
814         writeInitFunctionPointers       (api, os.path.join(VULKAN_DIR, "vkInitDeviceFunctionPointers.inl"),             functionTypes = deviceFuncs)
815         writeFuncPtrInterfaceImpl       (api, os.path.join(VULKAN_DIR, "vkPlatformDriverImpl.inl"),                             functionTypes = platformFuncs,  className = "PlatformDriver")
816         writeFuncPtrInterfaceImpl       (api, os.path.join(VULKAN_DIR, "vkInstanceDriverImpl.inl"),                             functionTypes = instanceFuncs,  className = "InstanceDriver")
817         writeFuncPtrInterfaceImpl       (api, os.path.join(VULKAN_DIR, "vkDeviceDriverImpl.inl"),                               functionTypes = deviceFuncs,    className = "DeviceDriver")
818         writeStrUtilProto                       (api, os.path.join(VULKAN_DIR, "vkStrUtil.inl"))
819         writeStrUtilImpl                        (api, os.path.join(VULKAN_DIR, "vkStrUtilImpl.inl"))
820         writeRefUtilProto                       (api, os.path.join(VULKAN_DIR, "vkRefUtil.inl"))
821         writeRefUtilImpl                        (api, os.path.join(VULKAN_DIR, "vkRefUtilImpl.inl"))
822         writeNullDriverImpl                     (api, os.path.join(VULKAN_DIR, "vkNullDriverImpl.inl"))
823         writeTypeUtil                           (api, os.path.join(VULKAN_DIR, "vkTypeUtil.inl"))