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