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