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