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