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