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