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