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