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