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