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