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