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