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 23import os 24import re 25import sys 26import copy 27from itertools import chain 28from collections import OrderedDict 29 30sys.path.append(os.path.join(os.path.dirname(__file__), "..", "..", "..", "scripts")) 31 32from build.common import DEQP_DIR 33from khr_util.format import indentLines, writeInlFile 34 35VULKAN_H = os.path.join(os.path.dirname(__file__), "src", "vulkan.h.in") 36VULKAN_DIR = os.path.join(os.path.dirname(__file__), "..", "framework", "vulkan") 37 38INL_HEADER = """\ 39/* WARNING: This is auto-generated file. Do not modify, since changes will 40 * be lost! Modify the generating script instead. 41 */\ 42""" 43 44DEFINITIONS = [ 45 ("VK_API_VERSION_1_0", "deUint32"), 46 ("VK_API_VERSION_1_1", "deUint32"), 47 ("VK_MAX_PHYSICAL_DEVICE_NAME_SIZE", "size_t"), 48 ("VK_MAX_EXTENSION_NAME_SIZE", "size_t"), 49 ("VK_UUID_SIZE", "size_t"), 50 ("VK_LUID_SIZE", "size_t"), 51 ("VK_MAX_MEMORY_TYPES", "size_t"), 52 ("VK_MAX_MEMORY_HEAPS", "size_t"), 53 ("VK_MAX_DESCRIPTION_SIZE", "size_t"), 54 ("VK_MAX_DEVICE_GROUP_SIZE", "size_t"), 55 ("VK_ATTACHMENT_UNUSED", "deUint32"), 56 ("VK_SUBPASS_EXTERNAL", "deUint32"), 57 ("VK_QUEUE_FAMILY_IGNORED", "deUint32"), 58 ("VK_QUEUE_FAMILY_EXTERNAL", "deUint32"), 59 ("VK_REMAINING_MIP_LEVELS", "deUint32"), 60 ("VK_REMAINING_ARRAY_LAYERS", "deUint32"), 61 ("VK_WHOLE_SIZE", "vk::VkDeviceSize"), 62 ("VK_TRUE", "vk::VkBool32"), 63 ("VK_FALSE", "vk::VkBool32"), 64] 65 66PLATFORM_TYPES = [ 67 # VK_KHR_xlib_surface 68 (["Display","*"], ["XlibDisplayPtr"], "void*"), 69 (["Window"], ["XlibWindow"], "deUintptr",), 70 (["VisualID"], ["XlibVisualID"], "deUint32"), 71 72 # VK_KHR_xcb_surface 73 (["xcb_connection_t", "*"], ["XcbConnectionPtr"], "void*"), 74 (["xcb_window_t"], ["XcbWindow"], "deUintptr"), 75 (["xcb_visualid_t"], ["XcbVisualid"], "deUint32"), 76 77 # VK_KHR_wayland_surface 78 (["struct", "wl_display","*"], ["WaylandDisplayPtr"], "void*"), 79 (["struct", "wl_surface", "*"], ["WaylandSurfacePtr"], "void*"), 80 81 # VK_KHR_mir_surface 82 (["MirConnection", "*"], ["MirConnectionPtr"], "void*"), 83 (["MirSurface", "*"], ["MirSurfacePtr"], "void*"), 84 85 # VK_KHR_android_surface 86 (["ANativeWindow", "*"], ["AndroidNativeWindowPtr"], "void*"), 87 88 # VK_KHR_win32_surface 89 (["HINSTANCE"], ["Win32InstanceHandle"], "void*"), 90 (["HWND"], ["Win32WindowHandle"], "void*"), 91 (["HANDLE"], ["Win32Handle"], "void*"), 92 (["const", "SECURITY_ATTRIBUTES", "*"], ["Win32SecurityAttributesPtr"], "const void*"), 93 (["AHardwareBuffer", "*"], ["AndroidHardwareBufferPtr"], "void*"), 94 95 # VK_EXT_acquire_xlib_display 96 (["RROutput"], ["RROutput"], "void*") 97] 98 99PLATFORM_TYPE_NAMESPACE = "pt" 100 101TYPE_SUBSTITUTIONS = [ 102 ("uint8_t", "deUint8"), 103 ("uint16_t", "deUint16"), 104 ("uint32_t", "deUint32"), 105 ("uint64_t", "deUint64"), 106 ("int8_t", "deInt8"), 107 ("int16_t", "deInt16"), 108 ("int32_t", "deInt32"), 109 ("int64_t", "deInt64"), 110 ("bool32_t", "deUint32"), 111 ("size_t", "deUintptr"), 112 113 # Platform-specific 114 ("DWORD", "deUint32"), 115 ("HANDLE*", PLATFORM_TYPE_NAMESPACE + "::" + "Win32Handle*"), 116 ("LPCWSTR", "char*"), 117] 118 119EXTENSION_POSTFIXES = ["KHR", "EXT", "NV", "NVX", "KHX", "NN", "MVK"] 120EXTENSION_POSTFIXES_STANDARD = ["KHR"] 121 122def prefixName (prefix, name): 123 name = re.sub(r'([a-z0-9])([A-Z])', r'\1_\2', name[2:]) 124 name = re.sub(r'([a-zA-Z])([0-9])', r'\1_\2', name) 125 name = name.upper() 126 127 name = name.replace("YCB_CR_", "YCBCR_") 128 name = name.replace("WIN_32_", "WIN32_") 129 name = name.replace("16_BIT_", "16BIT_") 130 name = name.replace("D_3_D_12_", "D3D12_") 131 name = name.replace("IOSSURFACE_", "IOS_SURFACE_") 132 name = name.replace("MAC_OS", "MACOS_") 133 name = name.replace("TEXTURE_LOD", "TEXTURE_LOD_") 134 name = name.replace("VIEWPORT_W", "VIEWPORT_W_") 135 name = name.replace("_IDPROPERTIES", "_ID_PROPERTIES") 136 137 return prefix + name 138 139class Version: 140 def __init__ (self, versionTuple): 141 self.major = versionTuple[0] 142 self.minor = versionTuple[1] 143 self.patch = versionTuple[2] 144 145 def getInHex (self): 146 if self.major == 1 and self.minor == 0 and self.patch == 0: 147 return "VK_API_VERSION_1_0" 148 elif self.major == 1 and self.minor == 1 and self.patch == 0: 149 return "VK_API_VERSION_1_1" 150 else: 151 hex = (self.major << 22) | (self.minor << 12) | self.patch 152 return '0x%Xu' % (hex) 153 154 def isStandardVersion (self): 155 if self.patch != 0: 156 return False 157 if self.major != 1: 158 return False 159 if self.minor != 1 and self.minor != 0: 160 return False 161 return True 162 163 def getBestRepresentation (self): 164 if self.isStandardVersion(): 165 return self.getInHex() 166 return self.getDefineName() 167 168 def getDefineName (self): 169 return 'VERSION_%d_%d_%d' % (self.major, self.minor, self.patch) 170 171 def __hash__ (self): 172 return (self.major << 22) | (self.minor << 12) | self.patch 173 174 def __eq__ (self, other): 175 return self.major == other.major and self.minor == other.minor and self.patch == other.patch 176 177 def __str__ (self): 178 return self.getBestRepresentation() 179 180 181class Handle: 182 TYPE_DISP = 0 183 TYPE_NONDISP = 1 184 185 def __init__ (self, type, name): 186 self.type = type 187 self.name = name 188 self.alias = None 189 self.isAlias = False 190 191 def getHandleType (self): 192 return prefixName("HANDLE_TYPE_", self.name) 193 194 def checkAliasValidity (self): 195 pass 196 197 def __repr__ (self): 198 return '%s (%s, %s)' % (self.name, self.alias, self.isAlias) 199 200class Definition: 201 def __init__ (self, type, name, value): 202 self.type = type 203 self.name = name 204 self.value = value 205 self.alias = None 206 self.isAlias = False 207 208 def __repr__ (self): 209 return '%s = %s (%s)' % (self.name, self.value, self.type) 210 211class Enum: 212 def __init__ (self, name, values): 213 self.name = name 214 self.values = values 215 self.alias = None 216 self.isAlias = False 217 218 def checkAliasValidity (self): 219 if self.alias != None: 220 if len(self.values) != len(self.alias.values): 221 raise Exception("%s has different number of flags than its alias %s." % (self.name, self.alias.name)) 222 for index, value in enumerate(self.values): 223 aliasVal = self.alias.values[index] 224 if value[1] != aliasVal[1] or not (value[0].startswith(aliasVal[0]) or aliasVal[0].startswith(value[0])): 225 raise Exception("Flag %s of %s has different value than %s of %s." % (self.alias.values[index], self.alias.name, value, self.name)) 226 227 def __repr__ (self): 228 return '%s (%s) %s' % (self.name, self.alias, self.values) 229 230class Bitfield: 231 def __init__ (self, name, values): 232 self.name = name 233 self.values = values 234 self.alias = None 235 self.isAlias = False 236 237 def checkAliasValidity (self): 238 if self.alias != None: 239 if len(self.values) != len(self.alias.values): 240 raise Exception("%s has different number of flags than its alias %s." % (self.name, self.alias.name)) 241 for index, value in enumerate(self.values): 242 aliasVal = self.alias.values[index] 243 if value[1] != aliasVal[1] or not (value[0].startswith(aliasVal[0]) or aliasVal[0].startswith(value[0])): 244 raise Exception("Flag %s of %s has different value than %s of %s." % (self.alias.values[index], self.alias.name, value, self.name)) 245 246 def __repr__ (self): 247 return '%s (%s)' % (self.name, self.alias) 248 249class Variable: 250 def __init__ (self, type, name, arraySize): 251 type = type.replace('*',' *').replace('&',' &') 252 for src, dst in TYPE_SUBSTITUTIONS: 253 type = type.replace(src, dst) 254 self.type = type.split(' ') 255 for platformType, substitute, compat in PLATFORM_TYPES: 256 range = self.contains(self.type, platformType) 257 if range != None: 258 self.type = self.type[:range[0]]+[PLATFORM_TYPE_NAMESPACE + '::' + substitute[0]] + substitute[1:] + self.type[range[1]:] 259 break 260 self.name = name 261 self.arraySize = arraySize 262 263 def contains(self, big, small): 264 for i in xrange(len(big)-len(small)+1): 265 for j in xrange(len(small)): 266 if big[i+j] != small[j]: 267 break 268 else: 269 return i, i+len(small) 270 return None 271 272 def getType (self): 273 return ' '.join(self.type).replace(' *','*').replace(' &','&') 274 275 def getAsString (self, separator): 276 return '%s%s%s%s' % (self.getType(), separator, self.name, self.arraySize) 277 278 def __repr__ (self): 279 return '<%s> <%s> <%s>' % (self.type, self.name, self.arraySize) 280 281 def __eq__ (self, other): 282 if len(self.type) != len(other.type): 283 return False 284 for index, type in enumerate(self.type): 285 if "*" == type or "&" == type or "const" == type or "volatile" == type: 286 if type != other.type[index]: 287 return False 288 elif type != other.type[index] and \ 289 type not in map(lambda ext: other.type[index] + ext, EXTENSION_POSTFIXES_STANDARD) and \ 290 other.type[index] not in map(lambda ext: type + ext, EXTENSION_POSTFIXES_STANDARD): 291 return False 292 return self.arraySize == other.arraySize 293 294 def __ne__ (self, other): 295 return not self == other 296 297class CompositeType: 298 CLASS_STRUCT = 0 299 CLASS_UNION = 1 300 301 def __init__ (self, typeClass, name, members): 302 self.typeClass = typeClass 303 self.name = name 304 self.members = members 305 self.alias = None 306 self.isAlias = False 307 308 def getClassName (self): 309 names = {CompositeType.CLASS_STRUCT: 'struct', CompositeType.CLASS_UNION: 'union'} 310 return names[self.typeClass] 311 312 def checkAliasValidity (self): 313 if self.alias != None: 314 if len(self.members) != len(self.alias.members): 315 raise Exception("%s has different number of members than its alias %s." % (self.name, self.alias.name)) 316 for index, member in enumerate(self.members ): 317 break 318 #if member != self.alias.members[index]: 319 #raise Exception("Member %s of %s is different than core member %s in %s." % (self.alias.members[index], self.alias.name, member, self.name)) 320 #raise Exception("Member ",str(self.alias.members[index])," of ", str(self.alias.name)," is different than core member ", str(member)," in ", str(self.name),".") 321 def __repr__ (self): 322 return '%s (%s)' % (self.name, self.alias) 323 324class Function: 325 TYPE_PLATFORM = 0 # Not bound to anything 326 TYPE_INSTANCE = 1 # Bound to VkInstance 327 TYPE_DEVICE = 2 # Bound to VkDevice 328 329 def __init__ (self, name, returnType, arguments, apiVersion = None): 330 self.name = name 331 self.returnType = returnType 332 self.arguments = arguments 333 self.alias = None 334 self.isAlias = False 335 self.apiVersion = apiVersion 336 337 def getType (self): 338 # Special functions 339 if self.name == "vkGetInstanceProcAddr": 340 return Function.TYPE_PLATFORM 341 elif self.name == "vkGetDeviceProcAddr": 342 return Function.TYPE_INSTANCE 343 assert len(self.arguments) > 0 344 firstArgType = self.arguments[0].getType() 345 if firstArgType in ["VkInstance", "VkPhysicalDevice"]: 346 return Function.TYPE_INSTANCE 347 elif firstArgType in ["VkDevice", "VkCommandBuffer", "VkQueue"]: 348 return Function.TYPE_DEVICE 349 else: 350 return Function.TYPE_PLATFORM 351 352 def checkAliasValidity (self): 353 if self.alias != None: 354 if len(self.arguments) != len(self.alias.arguments): 355 raise Exception("%s has different number of arguments than its alias %s." % (self.name, self.alias.name)) 356 if self.returnType != self.alias.returnType or not (self.returnType.startswith(self.alias.returnType) or self.alias.returnType.startswith(self.returnType)): 357 raise Exception("%s has different return value's type than its alias %s." % (self.name, self.alias.name)) 358 for index, argument in enumerate(self.arguments): 359 if argument != self.alias.arguments[index]: 360 raise Exception("argument %s: \"%s\" of %s is different than \"%s\" of %s." % (index, self.alias.arguments[index].getAsString(' '), self.alias.name, argument.getAsString(' '), self.name)) 361 362 def __repr__ (self): 363 return '%s (%s)' % (self.name, self.alias) 364 365class Extension: 366 def __init__ (self, name, handles, enums, bitfields, compositeTypes, functions, definitions, additionalDefinitions, versionInCore): 367 self.name = name 368 self.definitions = definitions 369 self.additionalDefs = additionalDefinitions 370 self.handles = handles 371 self.enums = enums 372 self.bitfields = bitfields 373 self.compositeTypes = compositeTypes 374 self.functions = functions 375 self.versionInCore = versionInCore 376 377 def __repr__ (self): 378 return 'EXT:\n%s ->\nENUMS:\n%s\nCOMPOS:\n%s\nFUNCS:\n%s\nBITF:\n%s\nHAND:\n%s\nDEFS:\n%s\n' % (self.name, self.enums, self.compositeTypes, self.functions, self.bitfields, self.handles, self.definitions, self.versionInCore) 379 380class API: 381 def __init__ (self, definitions, handles, enums, bitfields, compositeTypes, functions, extensions): 382 self.definitions = definitions 383 self.handles = handles 384 self.enums = enums 385 self.bitfields = bitfields 386 self.compositeTypes = compositeTypes 387 self.functions = functions # \note contains extension functions as well 388 self.extensions = extensions 389 390def readFile (filename): 391 with open(filename, 'rb') as f: 392 return f.read() 393 394IDENT_PTRN = r'[a-zA-Z_][a-zA-Z0-9_]*' 395TYPE_PTRN = r'[a-zA-Z_][a-zA-Z0-9_ \t*&]*' 396 397def fixupEnumValues (values): 398 fixed = [] 399 for name, value in values: 400 if "_BEGIN_RANGE" in name or "_END_RANGE" in name: 401 continue 402 fixed.append((name, value)) 403 return fixed 404 405def getInterfaceName (function): 406 assert function.name[:2] == "vk" 407 return function.name[2].lower() + function.name[3:] 408 409def getFunctionTypeName (function): 410 assert function.name[:2] == "vk" 411 return function.name[2:] + "Func" 412 413def endsWith (str, postfix): 414 return str[-len(postfix):] == postfix 415 416def splitNameExtPostfix (name): 417 knownExtPostfixes = EXTENSION_POSTFIXES 418 for postfix in knownExtPostfixes: 419 if endsWith(name, postfix): 420 return (name[:-len(postfix)], postfix) 421 return (name, "") 422 423def getBitEnumNameForBitfield (bitfieldName): 424 bitfieldName, postfix = splitNameExtPostfix(bitfieldName) 425 assert bitfieldName[-1] == "s" 426 return bitfieldName[:-1] + "Bits" + postfix 427 428def getBitfieldNameForBitEnum (bitEnumName): 429 bitEnumName, postfix = splitNameExtPostfix(bitEnumName) 430 assert bitEnumName[-4:] == "Bits" 431 return bitEnumName[:-4] + "s" + postfix 432 433def parsePreprocDefinedValue (src, name): 434 value = parsePreprocDefinedValueOptional(src, name) 435 if value is None: 436 437 raise Exception("No such definition: %s" % name) 438 return value 439 440def parsePreprocDefinedValueOptional (src, name): 441 definition = re.search(r'#\s*define\s+' + name + r'\s+([^\n]+)\n', src) 442 if definition is None: 443 return None 444 value = definition.group(1).strip() 445 if value == "UINT32_MAX": 446 value = "(~0u)" 447 return value 448 449def parseEnum (name, src): 450 keyValuePtrn = '(' + IDENT_PTRN + r')\s*=\s*([^\s,}]+)\s*[,}]' 451 matches = re.findall(keyValuePtrn, src) 452 453 return Enum(name, fixupEnumValues(matches)) 454 455# \note Parses raw enums, some are mapped to bitfields later 456def parseEnums (src): 457 matches = re.findall(r'typedef enum(\s*' + IDENT_PTRN + r')?\s*{([^}]*)}\s*(' + IDENT_PTRN + r')\s*;', src) 458 enums = [] 459 for enumname, contents, typename in matches: 460 enums.append(parseEnum(typename, contents)) 461 return enums 462 463 464 465def parseCompositeType (type, name, src): 466 typeNamePtrn = r'(' + TYPE_PTRN + r')(\s+' + IDENT_PTRN + r')((\[[^\]]+\])*)\s*;' 467 matches = re.findall(typeNamePtrn, src) 468 members = [Variable(t.strip(), n.strip(), a.strip()) for t, n, a, _ in matches] 469 return CompositeType(type, name, members) 470 471def parseCompositeTypes (src): 472 typeMap = { 'struct': CompositeType.CLASS_STRUCT, 'union': CompositeType.CLASS_UNION } 473 matches = re.findall(r'typedef (struct|union)(\s*' + IDENT_PTRN + r')?\s*{([^}]*)}\s*(' + IDENT_PTRN + r')\s*;', src) 474 types = [] 475 for type, structname, contents, typename in matches: 476 types.append(parseCompositeType(typeMap[type], typename, contents)) 477 return types 478 479def parseHandles (src): 480 matches = re.findall(r'VK_DEFINE(_NON_DISPATCHABLE|)_HANDLE\((' + IDENT_PTRN + r')\)[ \t]*[\n\r]', src) 481 handles = [] 482 typeMap = {'': Handle.TYPE_DISP, '_NON_DISPATCHABLE': Handle.TYPE_NONDISP} 483 for type, name in matches: 484 handle = Handle(typeMap[type], name) 485 handles.append(handle) 486 return handles 487 488def parseArgList (src): 489 typeNamePtrn = r'(' + TYPE_PTRN + r')(\s+' + IDENT_PTRN + r')((\[[^\]]+\])*)\s*' 490 args = [] 491 for rawArg in src.split(','): 492 m = re.search(typeNamePtrn, rawArg) 493 args.append(Variable(m.group(1).strip(), m.group(2).strip(), m.group(3))) 494 return args 495 496def removeTypeExtPostfix (name): 497 for extPostfix in EXTENSION_POSTFIXES_STANDARD: 498 if endsWith(name, extPostfix): 499 return name[0:-len(extPostfix)] 500 return None 501 502def populateAliases (objects): 503 objectsByName = {} 504 for object in objects: 505 objectsByName[object.name] = object 506 for object in objects: 507 withoutPostfix = removeTypeExtPostfix(object.name) 508 if withoutPostfix != None and withoutPostfix in objectsByName: 509 objectsByName[withoutPostfix].alias = object 510 object.isAlias = True 511 for object in objects: 512 object.checkAliasValidity() 513 514def populateAliasesWithTypedefs (objects, src): 515 objectsByName = {} 516 for object in objects: 517 objectsByName[object.name] = object 518 ptrn = r'\s*typedef\s+' + object.name + r'\s+([^;]+)' 519 stash = re.findall(ptrn, src) 520 if len(stash) == 1: 521 objExt = copy.deepcopy(object) 522 objExt.name = stash[0] 523 object.alias = objExt 524 objExt.isAlias = True 525 objects.append(objExt) 526 527 528def removeAliasedValues (enum): 529 valueByName = {} 530 for name, value in enum.values: 531 valueByName[name] = value 532 533 def removeDefExtPostfix (name): 534 for extPostfix in EXTENSION_POSTFIXES: 535 if endsWith(name, "_" + extPostfix): 536 return name[0:-(len(extPostfix)+1)] 537 return None 538 539 newValues = [] 540 for name, value in enum.values: 541 withoutPostfix = removeDefExtPostfix(name) 542 if withoutPostfix != None and withoutPostfix in valueByName and valueByName[withoutPostfix] == value: 543 continue 544 newValues.append((name, value)) 545 enum.values = newValues 546 547def parseFunctions (src): 548 ptrn = r'VKAPI_ATTR\s+(' + TYPE_PTRN + ')\s+VKAPI_CALL\s+(' + IDENT_PTRN + r')\s*\(([^)]*)\)\s*;' 549 matches = re.findall(ptrn, src) 550 functions = [] 551 for returnType, name, argList in matches: 552 functions.append(Function(name.strip(), returnType.strip(), parseArgList(argList))) 553 return functions 554 555def parseFunctionsByVersion (src): 556 ptrnVer10 = 'VK_VERSION_1_0 1' 557 ptrnVer11 = 'VK_VERSION_1_1 1' 558 matchVer10 = re.search(ptrnVer10, src) 559 matchVer11 = re.search(ptrnVer11, src) 560 ptrn = r'VKAPI_ATTR\s+(' + TYPE_PTRN + ')\s+VKAPI_CALL\s+(' + IDENT_PTRN + r')\s*\(([^)]*)\)\s*;' 561 regPtrn = re.compile(ptrn) 562 matches = regPtrn.findall(src, matchVer10.start(), matchVer11.start()) 563 functions = [] 564 for returnType, name, argList in matches: 565 functions.append(Function(name.strip(), returnType.strip(), parseArgList(argList), 'VK_VERSION_1_0')) 566 matches = regPtrn.findall(src, matchVer11.start()) 567 for returnType, name, argList in matches: 568 functions.append(Function(name.strip(), returnType.strip(), parseArgList(argList), 'VK_VERSION_1_1')) 569 return functions 570 571def splitByExtension (src): 572 ptrn = r'#define\s+[A-Z0-9_]+_EXTENSION_NAME\s+"([^"]+)"' 573 match = "#define\s+(" 574 for part in re.finditer(ptrn, src): 575 match += part.group(1)+"|" 576 match = match[:-1] + ")\s+1" 577 parts = re.split(match, src) 578 # First part is core 579 byExtension = [(None, parts[0])] 580 for ndx in range(1, len(parts), 2): 581 byExtension.append((parts[ndx], parts[ndx+1])) 582 return byExtension 583 584def parseDefinitions (extensionName, src): 585 586 def skipDefinition (extensionName, definition): 587 if extensionName == None: 588 return True 589 if definition[0].startswith(extensionName.upper()): 590 return True 591 if definition[1].isdigit(): 592 return True 593 return False 594 595 ptrn = r'#define\s+([^\s]+)\s+([^\r\n]+)' 596 matches = re.findall(ptrn, src) 597 598 return [Definition(None, match[0], match[1]) for match in matches if not skipDefinition(extensionName, match)] 599 600def parseExtensions (src, allFunctions, allCompositeTypes, allEnums, allBitfields, allHandles, allDefinitions): 601 602 def getCoreVersion (extensionTuple): 603 if not extensionTuple[0]: 604 return None 605 ptrn = r'\/\/\s*' + extensionTuple[0] + r'\s+(DEVICE|INSTANCE)\s+([0-9_]+)' 606 coreVersion = re.search(ptrn, extensionTuple[1], re.I) 607 if coreVersion != None: 608 return [coreVersion.group(1)] + [int(number) for number in coreVersion.group(2).split('_')[:3]] 609 return None 610 611 splitSrc = splitByExtension(src) 612 extensions = [] 613 functionsByName = {function.name: function for function in allFunctions} 614 compositeTypesByName = {compType.name: compType for compType in allCompositeTypes} 615 enumsByName = {enum.name: enum for enum in allEnums} 616 bitfieldsByName = {bitfield.name: bitfield for bitfield in allBitfields} 617 handlesByName = {handle.name: handle for handle in allHandles} 618 definitionsByName = {definition.name: definition for definition in allDefinitions} 619 620 for extensionName, extensionSrc in splitSrc: 621 definitions = [Definition(type, name, parsePreprocDefinedValueOptional(extensionSrc, name)) for name, type in DEFINITIONS] 622 definitions = [definition for definition in definitions if definition.value != None] 623 additionalDefinitions = parseDefinitions(extensionName, extensionSrc) 624 handles = parseHandles(extensionSrc) 625 functions = parseFunctions(extensionSrc) 626 compositeTypes = parseCompositeTypes(extensionSrc) 627 rawEnums = parseEnums(extensionSrc) 628 bitfieldNames = parseBitfieldNames(extensionSrc) 629 enumBitfieldNames = [getBitEnumNameForBitfield(name) for name in bitfieldNames] 630 enums = [enum for enum in rawEnums if enum.name not in enumBitfieldNames] 631 632 extCoreVersion = getCoreVersion((extensionName, extensionSrc)) 633 extFunctions = [functionsByName[function.name] for function in functions] 634 extCompositeTypes = [compositeTypesByName[compositeType.name] for compositeType in compositeTypes] 635 extEnums = [enumsByName[enum.name] for enum in enums] 636 extBitfields = [bitfieldsByName[bitfieldName] for bitfieldName in bitfieldNames] 637 extHandles = [handlesByName[handle.name] for handle in handles] 638 extDefinitions = [definitionsByName[definition.name] for definition in definitions] 639 640 extensions.append(Extension(extensionName, extHandles, extEnums, extBitfields, extCompositeTypes, extFunctions, extDefinitions, additionalDefinitions, extCoreVersion)) 641 return extensions 642 643def parseBitfieldNames (src): 644 ptrn = r'typedef\s+VkFlags\s(' + IDENT_PTRN + r')\s*;' 645 matches = re.findall(ptrn, src) 646 647 return matches 648 649def parseAPI (src): 650 definitions = [Definition(type, name, parsePreprocDefinedValue(src, name)) for name, type in DEFINITIONS] 651 handles = parseHandles(src) 652 rawEnums = parseEnums(src) 653 bitfieldNames = parseBitfieldNames(src) 654 enums = [] 655 bitfields = [] 656 bitfieldEnums = set([getBitEnumNameForBitfield(n) for n in bitfieldNames if getBitEnumNameForBitfield(n) in [enum.name for enum in rawEnums]]) 657 compositeTypes = parseCompositeTypes(src) 658 allFunctions = parseFunctionsByVersion(src) 659 660 for enum in rawEnums: 661 if enum.name in bitfieldEnums: 662 bitfields.append(Bitfield(getBitfieldNameForBitEnum(enum.name), enum.values)) 663 else: 664 enums.append(enum) 665 666 for bitfieldName in bitfieldNames: 667 if not bitfieldName in [bitfield.name for bitfield in bitfields]: 668 # Add empty bitfield 669 bitfields.append(Bitfield(bitfieldName, [])) 670 671 # Populate alias fields 672 populateAliasesWithTypedefs(compositeTypes, src) 673 populateAliasesWithTypedefs(enums, src) 674 populateAliasesWithTypedefs(bitfields, src) 675 populateAliases(allFunctions) 676 populateAliases(handles) 677 populateAliases(enums) 678 populateAliases(bitfields) 679 populateAliases(compositeTypes) 680 681 682 for enum in enums: 683 removeAliasedValues(enum) 684 685 extensions = parseExtensions(src, allFunctions, compositeTypes, enums, bitfields, handles, definitions) 686 687 return API( 688 definitions = definitions, 689 handles = handles, 690 enums = enums, 691 bitfields = bitfields, 692 compositeTypes = compositeTypes, 693 functions = allFunctions, 694 extensions = extensions) 695 696def splitUniqueAndDuplicatedEntries (handles): 697 listOfUniqueHandles = [] 698 duplicates = OrderedDict() 699 for handle in handles: 700 if handle.alias != None: 701 duplicates[handle.alias] = handle 702 if not handle.isAlias: 703 listOfUniqueHandles.append(handle) 704 return listOfUniqueHandles, duplicates 705 706def writeHandleType (api, filename): 707 uniqeHandles, duplicatedHandles = splitUniqueAndDuplicatedEntries(api.handles) 708 709 def genHandles (): 710 yield "\t%s\t= 0," % uniqeHandles[0].getHandleType() 711 for handle in uniqeHandles[1:]: 712 yield "\t%s," % handle.getHandleType() 713 for duplicate in duplicatedHandles: 714 yield "\t%s\t= %s," % (duplicate.getHandleType(), duplicatedHandles[duplicate].getHandleType()) 715 yield "\tHANDLE_TYPE_LAST\t= %s + 1" % (uniqeHandles[-1].getHandleType()) 716 717 def genHandlesBlock (): 718 yield "enum HandleType" 719 yield "{" 720 721 for line in indentLines(genHandles()): 722 yield line 723 724 yield "};" 725 yield "" 726 727 writeInlFile(filename, INL_HEADER, genHandlesBlock()) 728 729def getEnumValuePrefix (enum): 730 prefix = enum.name[0] 731 for i in range(1, len(enum.name)): 732 if enum.name[i].isupper() and not enum.name[i-1].isupper(): 733 prefix += "_" 734 prefix += enum.name[i].upper() 735 return prefix 736 737def parseInt (value): 738 if value[:2] == "0x": 739 return int(value, 16) 740 else: 741 return int(value, 10) 742 743def areEnumValuesLinear (enum): 744 curIndex = 0 745 for name, value in enum.values: 746 if parseInt(value) != curIndex: 747 return False 748 curIndex += 1 749 return True 750 751def genEnumSrc (enum): 752 yield "enum %s" % enum.name 753 yield "{" 754 755 for line in indentLines(["\t%s\t= %s," % v for v in enum.values]): 756 yield line 757 758 if areEnumValuesLinear(enum): 759 yield "" 760 yield "\t%s_LAST" % getEnumValuePrefix(enum) 761 762 yield "};" 763 764def genBitfieldSrc (bitfield): 765 if len(bitfield.values) > 0: 766 yield "enum %s" % getBitEnumNameForBitfield(bitfield.name) 767 yield "{" 768 for line in indentLines(["\t%s\t= %s," % v for v in bitfield.values]): 769 yield line 770 yield "};" 771 yield "typedef deUint32 %s;" % bitfield.name 772 773def genCompositeTypeSrc (type): 774 yield "%s %s" % (type.getClassName(), type.name) 775 yield "{" 776 for line in indentLines(['\t'+m.getAsString('\t')+';' for m in type.members]): 777 yield line 778 yield "};" 779 780def genHandlesSrc (handles): 781 uniqeHandles, duplicatedHandles = splitUniqueAndDuplicatedEntries(handles) 782 783 def genLines (handles): 784 for handle in uniqeHandles: 785 if handle.type == Handle.TYPE_DISP: 786 yield "VK_DEFINE_HANDLE\t(%s,\t%s);" % (handle.name, handle.getHandleType()) 787 elif handle.type == Handle.TYPE_NONDISP: 788 yield "VK_DEFINE_NON_DISPATCHABLE_HANDLE\t(%s,\t%s);" % (handle.name, handle.getHandleType()) 789 790 for duplicate in duplicatedHandles: 791 if duplicate.type == Handle.TYPE_DISP: 792 yield "VK_DEFINE_HANDLE\t(%s,\t%s);" % (duplicate.name, duplicatedHandles[duplicate].getHandleType()) 793 elif duplicate.type == Handle.TYPE_NONDISP: 794 yield "VK_DEFINE_NON_DISPATCHABLE_HANDLE\t(%s,\t%s);" % (duplicate.name, duplicatedHandles[duplicate].getHandleType()) 795 796 for line in indentLines(genLines(handles)): 797 yield line 798 799def genDefinitionsSrc (definitions): 800 for line in ["#define %s\t(static_cast<%s>\t(%s))" % (definition.name, definition.type, definition.value) for definition in definitions]: 801 yield line 802 803def genDefinitionsAliasSrc (definitions): 804 for line in ["#define %s\t%s" % (definition.name, definitions[definition].name) for definition in definitions]: 805 if definition.value != definitions[definition].value and definition.value != definitions[definition].name: 806 raise Exception("Value of %s (%s) is different than core definition value %s (%s)." % (definition.name, definition.value, definitions[definition].name, definitions[definition].value)) 807 yield line 808 809def writeBasicTypes (api, filename): 810 811 def gen (): 812 definitionsCore, definitionDuplicates = splitUniqueAndDuplicatedEntries(api.definitions) 813 814 for line in indentLines(chain(genDefinitionsSrc(definitionsCore), genDefinitionsAliasSrc(definitionDuplicates))): 815 yield line 816 yield "" 817 818 for line in genHandlesSrc(api.handles): 819 yield line 820 yield "" 821 822 for enum in api.enums: 823 if not enum.isAlias: 824 for line in genEnumSrc(enum): 825 yield line 826 yield "" 827 828 for bitfield in api.bitfields: 829 if not bitfield.isAlias: 830 for line in genBitfieldSrc(bitfield): 831 yield line 832 yield "" 833 for line in indentLines(["VK_DEFINE_PLATFORM_TYPE(%s,\t%s);" % (s[0], c) for n, s, c in PLATFORM_TYPES]): 834 yield line 835 836 for ext in api.extensions: 837 if ext.additionalDefs != None: 838 for definition in ext.additionalDefs: 839 yield "#define " + definition.name + " " + definition.value 840 writeInlFile(filename, INL_HEADER, gen()) 841 842def writeCompositeTypes (api, filename): 843 def gen (): 844 for type in api.compositeTypes: 845 type.checkAliasValidity() 846 847 if not type.isAlias: 848 for line in genCompositeTypeSrc(type): 849 yield line 850 yield "" 851 852 writeInlFile(filename, INL_HEADER, gen()) 853 854def argListToStr (args): 855 return ", ".join(v.getAsString(' ') for v in args) 856 857def writeInterfaceDecl (api, filename, functionTypes, concrete): 858 def genProtos (): 859 postfix = "" if concrete else " = 0" 860 for function in api.functions: 861 if not function.getType() in functionTypes: 862 continue 863 if not function.isAlias: 864 yield "virtual %s\t%s\t(%s) const%s;" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments), postfix) 865 866 writeInlFile(filename, INL_HEADER, indentLines(genProtos())) 867 868def writeFunctionPtrTypes (api, filename): 869 def genTypes (): 870 for function in api.functions: 871 yield "typedef VKAPI_ATTR %s\t(VKAPI_CALL* %s)\t(%s);" % (function.returnType, getFunctionTypeName(function), argListToStr(function.arguments)) 872 873 writeInlFile(filename, INL_HEADER, indentLines(genTypes())) 874 875def writeFunctionPointers (api, filename, functionTypes): 876 def FunctionsYielder (): 877 for function in api.functions: 878 if function.getType() in functionTypes: 879 if function.isAlias: 880 if function.getType() == Function.TYPE_INSTANCE and function.arguments[0].getType() == "VkPhysicalDevice": 881 yield "%s\t%s;" % (getFunctionTypeName(function), getInterfaceName(function)) 882 else: 883 yield "%s\t%s;" % (getFunctionTypeName(function), getInterfaceName(function)) 884 885 writeInlFile(filename, INL_HEADER, indentLines(FunctionsYielder())) 886 887def writeInitFunctionPointers (api, filename, functionTypes, cond = None): 888 def makeInitFunctionPointers (): 889 for function in api.functions: 890 if function.getType() in functionTypes and (cond == None or cond(function)): 891 interfaceName = getInterfaceName(function) 892 if function.isAlias: 893 if function.getType() == Function.TYPE_INSTANCE and function.arguments[0].getType() == "VkPhysicalDevice": 894 yield "m_vk.%s\t= (%s)\tGET_PROC_ADDR(\"%s\");" % (getInterfaceName(function), getFunctionTypeName(function), function.name) 895 else: 896 yield "m_vk.%s\t= (%s)\tGET_PROC_ADDR(\"%s\");" % (getInterfaceName(function), getFunctionTypeName(function), function.name) 897 if function.alias != None: 898 yield "if (!m_vk.%s)" % (getInterfaceName(function)) 899 yield " m_vk.%s\t= (%s)\tGET_PROC_ADDR(\"%s\");" % (getInterfaceName(function), getFunctionTypeName(function), function.alias.name) 900 lines = [line.replace(' ', '\t') for line in indentLines(makeInitFunctionPointers())] 901 writeInlFile(filename, INL_HEADER, lines) 902 903def writeFuncPtrInterfaceImpl (api, filename, functionTypes, className): 904 def makeFuncPtrInterfaceImpl (): 905 for function in api.functions: 906 if function.getType() in functionTypes and not function.isAlias: 907 yield "" 908 yield "%s %s::%s (%s) const" % (function.returnType, className, getInterfaceName(function), argListToStr(function.arguments)) 909 yield "{" 910 if function.name == "vkEnumerateInstanceVersion": 911 yield " if (m_vk.enumerateInstanceVersion)" 912 yield " return m_vk.enumerateInstanceVersion(pApiVersion);" 913 yield "" 914 yield " *pApiVersion = VK_API_VERSION_1_0;" 915 yield " return VK_SUCCESS;" 916 elif function.getType() == Function.TYPE_INSTANCE and function.arguments[0].getType() == "VkPhysicalDevice" and function.alias != None: 917 yield " vk::VkPhysicalDeviceProperties props;" 918 yield " m_vk.getPhysicalDeviceProperties(physicalDevice, &props);" 919 yield " if (props.apiVersion >= VK_API_VERSION_1_1)" 920 yield " %sm_vk.%s(%s);" % ("return " if function.returnType != "void" else "", getInterfaceName(function), ", ".join(a.name for a in function.arguments)) 921 yield " else" 922 yield " %sm_vk.%s(%s);" % ("return " if function.returnType != "void" else "", getInterfaceName(function.alias), ", ".join(a.name for a in function.arguments)) 923 else: 924 yield " %sm_vk.%s(%s);" % ("return " if function.returnType != "void" else "", getInterfaceName(function), ", ".join(a.name for a in function.arguments)) 925 yield "}" 926 927 writeInlFile(filename, INL_HEADER, makeFuncPtrInterfaceImpl()) 928 929def writeStrUtilProto (api, filename): 930 def makeStrUtilProto (): 931 for line in indentLines(["const char*\tget%sName\t(%s value);" % (enum.name[2:], enum.name) for enum in api.enums if not enum.isAlias]): 932 yield line 933 yield "" 934 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 if not e.isAlias]): 935 yield line 936 yield "" 937 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 if not e.isAlias]): 938 yield line 939 yield "" 940 for line in indentLines(["tcu::Format::Bitfield<32>\tget%sStr\t(%s value);" % (bitfield.name[2:], bitfield.name) for bitfield in api.bitfields if not bitfield.isAlias]): 941 yield line 942 yield "" 943 for line in indentLines(["std::ostream&\toperator<<\t(std::ostream& s, const %s& value);" % (s.name) for s in api.compositeTypes if not s.isAlias]): 944 yield line 945 946 writeInlFile(filename, INL_HEADER, makeStrUtilProto()) 947 948def writeStrUtilImpl (api, filename): 949 def makeStrUtilImpl (): 950 for line in indentLines(["template<> const char*\tgetTypeName<%s>\t(void) { return \"%s\";\t}" % (handle.name, handle.name) for handle in api.handles if not handle.isAlias]): 951 yield line 952 953 yield "" 954 yield "namespace %s" % PLATFORM_TYPE_NAMESPACE 955 yield "{" 956 957 for line in indentLines("std::ostream& operator<< (std::ostream& s, %s\tv) { return s << tcu::toHex(v.internal); }" % ''.join(s) for n, s, c in PLATFORM_TYPES): 958 yield line 959 960 yield "}" 961 962 for enum in api.enums: 963 if enum.isAlias: 964 continue 965 yield "" 966 yield "const char* get%sName (%s value)" % (enum.name[2:], enum.name) 967 yield "{" 968 yield "\tswitch (value)" 969 yield "\t{" 970 for line in indentLines(["\t\tcase %s:\treturn \"%s\";" % (n, n) for n, v in enum.values] + ["\t\tdefault:\treturn DE_NULL;"]): 971 yield line 972 yield "\t}" 973 yield "}" 974 975 for bitfield in api.bitfields: 976 if bitfield.isAlias: 977 continue 978 yield "" 979 yield "tcu::Format::Bitfield<32> get%sStr (%s value)" % (bitfield.name[2:], bitfield.name) 980 yield "{" 981 982 if len(bitfield.values) > 0: 983 yield "\tstatic const tcu::Format::BitDesc s_desc[] =" 984 yield "\t{" 985 for line in indentLines(["\t\ttcu::Format::BitDesc(%s,\t\"%s\")," % (n, n) for n, v in bitfield.values]): 986 yield line 987 yield "\t};" 988 yield "\treturn tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));" 989 else: 990 yield "\treturn tcu::Format::Bitfield<32>(value, DE_NULL, DE_NULL);" 991 yield "}" 992 993 bitfieldTypeNames = set([bitfield.name for bitfield in api.bitfields]) 994 995 for type in api.compositeTypes: 996 if not type.isAlias: 997 yield "" 998 yield "std::ostream& operator<< (std::ostream& s, const %s& value)" % type.name 999 yield "{" 1000 yield "\ts << \"%s = {\\n\";" % type.name 1001 for member in type.members: 1002 memberName = member.name 1003 valFmt = None 1004 newLine = "" 1005 if member.getType() in bitfieldTypeNames: 1006 valFmt = "get%sStr(value.%s)" % (member.getType()[2:], member.name) 1007 elif member.getType() == "const char*" or member.getType() == "char*": 1008 valFmt = "getCharPtrStr(value.%s)" % member.name 1009 elif member.arraySize != '': 1010 if member.name in ["extensionName", "deviceName", "layerName", "description"]: 1011 valFmt = "(const char*)value.%s" % member.name 1012 elif member.getType() == 'char' or member.getType() == 'deUint8': 1013 newLine = "'\\n' << " 1014 valFmt = "tcu::formatArray(tcu::Format::HexIterator<%s>(DE_ARRAY_BEGIN(value.%s)), tcu::Format::HexIterator<%s>(DE_ARRAY_END(value.%s)))" % (member.getType(), member.name, member.getType(), member.name) 1015 else: 1016 if member.name == "memoryTypes" or member.name == "memoryHeaps": 1017 endIter = "DE_ARRAY_BEGIN(value.%s) + value.%sCount" % (member.name, member.name[:-1]) 1018 else: 1019 endIter = "DE_ARRAY_END(value.%s)" % member.name 1020 newLine = "'\\n' << " 1021 valFmt = "tcu::formatArray(DE_ARRAY_BEGIN(value.%s), %s)" % (member.name, endIter) 1022 memberName = member.name 1023 else: 1024 valFmt = "value.%s" % member.name 1025 yield ("\ts << \"\\t%s = \" << " % memberName) + newLine + valFmt + " << '\\n';" 1026 yield "\ts << '}';" 1027 yield "\treturn s;" 1028 yield "}" 1029 writeInlFile(filename, INL_HEADER, makeStrUtilImpl()) 1030 1031class ConstructorFunction: 1032 def __init__ (self, type, name, objectType, iface, arguments): 1033 self.type = type 1034 self.name = name 1035 self.objectType = objectType 1036 self.iface = iface 1037 self.arguments = arguments 1038 1039def getConstructorFunctions (api): 1040 funcs = [] 1041 for function in api.functions: 1042 if function.isAlias: 1043 continue 1044 if (function.name[:8] == "vkCreate" or function.name == "vkAllocateMemory") and not "createInfoCount" in [a.name for a in function.arguments]: 1045 if function.name == "vkCreateDisplayModeKHR": 1046 continue # No way to delete display modes (bug?) 1047 1048 # \todo [pyry] Rather hacky 1049 iface = None 1050 if function.getType() == Function.TYPE_PLATFORM: 1051 iface = Variable("const PlatformInterface&", "vk", "") 1052 elif function.getType() == Function.TYPE_INSTANCE: 1053 iface = Variable("const InstanceInterface&", "vk", "") 1054 else: 1055 iface = Variable("const DeviceInterface&", "vk", "") 1056 1057 assert (function.arguments[-2].type == ["const", "VkAllocationCallbacks", "*"]) 1058 1059 objectType = function.arguments[-1].type[0] #not getType() but type[0] on purpose 1060 arguments = function.arguments[:-1] 1061 funcs.append(ConstructorFunction(function.getType(), getInterfaceName(function), objectType, iface, arguments)) 1062 return funcs 1063 1064def addVersionDefines(versionSpectrum): 1065 output = ["#define " + ver.getDefineName() + " " + ver.getInHex() for ver in versionSpectrum if not ver.isStandardVersion()] 1066 return output 1067 1068def removeVersionDefines(versionSpectrum): 1069 output = ["#undef " + ver.getDefineName() for ver in versionSpectrum if not ver.isStandardVersion()] 1070 return output 1071 1072def writeRefUtilProto (api, filename): 1073 functions = getConstructorFunctions(api) 1074 1075 def makeRefUtilProto (): 1076 unindented = [] 1077 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]): 1078 yield line 1079 1080 writeInlFile(filename, INL_HEADER, makeRefUtilProto()) 1081 1082def writeRefUtilImpl (api, filename): 1083 functions = getConstructorFunctions(api) 1084 1085 def makeRefUtilImpl (): 1086 yield "namespace refdetails" 1087 yield "{" 1088 yield "" 1089 1090 for function in api.functions: 1091 if function.getType() == Function.TYPE_DEVICE \ 1092 and (function.name[:9] == "vkDestroy" or function.name == "vkFreeMemory") \ 1093 and not function.name == "vkDestroyDevice" \ 1094 and not function.isAlias: 1095 objectType = function.arguments[-2].getType() 1096 yield "template<>" 1097 yield "void Deleter<%s>::operator() (%s obj) const" % (objectType, objectType) 1098 yield "{" 1099 yield "\tm_deviceIface->%s(m_device, obj, m_allocator);" % (getInterfaceName(function)) 1100 yield "}" 1101 yield "" 1102 1103 yield "} // refdetails" 1104 yield "" 1105 1106 for function in functions: 1107 if function.type == Function.TYPE_DEVICE: 1108 dtorObj = "device" 1109 elif function.type == Function.TYPE_INSTANCE: 1110 if function.name == "createDevice": 1111 dtorObj = "object" 1112 else: 1113 dtorObj = "instance" 1114 else: 1115 dtorObj = "object" 1116 1117 yield "Move<%s> %s (%s)" % (function.objectType, function.name, argListToStr([function.iface] + function.arguments)) 1118 yield "{" 1119 yield "\t%s object = 0;" % function.objectType 1120 yield "\tVK_CHECK(vk.%s(%s));" % (function.name, ", ".join([a.name for a in function.arguments] + ["&object"])) 1121 yield "\treturn Move<%s>(check<%s>(object), Deleter<%s>(%s));" % (function.objectType, function.objectType, function.objectType, ", ".join(["vk", dtorObj, function.arguments[-1].name])) 1122 yield "}" 1123 yield "" 1124 1125 writeInlFile(filename, INL_HEADER, makeRefUtilImpl()) 1126 1127def writeStructTraitsImpl (api, filename): 1128 def gen (): 1129 for type in api.compositeTypes: 1130 if type.getClassName() == "struct" and type.members[0].name == "sType" and not type.isAlias: 1131 yield "template<> VkStructureType getStructureType<%s> (void)" % type.name 1132 yield "{" 1133 yield "\treturn %s;" % prefixName("VK_STRUCTURE_TYPE_", type.name) 1134 yield "}" 1135 yield "" 1136 1137 writeInlFile(filename, INL_HEADER, gen()) 1138 1139def writeNullDriverImpl (api, filename): 1140 def genNullDriverImpl (): 1141 specialFuncNames = [ 1142 "vkCreateGraphicsPipelines", 1143 "vkCreateComputePipelines", 1144 "vkGetInstanceProcAddr", 1145 "vkGetDeviceProcAddr", 1146 "vkEnumeratePhysicalDevices", 1147 "vkEnumerateInstanceExtensionProperties", 1148 "vkEnumerateDeviceExtensionProperties", 1149 "vkGetPhysicalDeviceFeatures", 1150 "vkGetPhysicalDeviceFeatures2KHR", 1151 "vkGetPhysicalDeviceProperties", 1152 "vkGetPhysicalDeviceProperties2KHR", 1153 "vkGetPhysicalDeviceQueueFamilyProperties", 1154 "vkGetPhysicalDeviceMemoryProperties", 1155 "vkGetPhysicalDeviceFormatProperties", 1156 "vkGetPhysicalDeviceImageFormatProperties", 1157 "vkGetDeviceQueue", 1158 "vkGetBufferMemoryRequirements", 1159 "vkGetBufferMemoryRequirements2KHR", 1160 "vkGetImageMemoryRequirements", 1161 "vkGetImageMemoryRequirements2KHR", 1162 "vkAllocateMemory", 1163 "vkMapMemory", 1164 "vkUnmapMemory", 1165 "vkAllocateDescriptorSets", 1166 "vkFreeDescriptorSets", 1167 "vkResetDescriptorPool", 1168 "vkAllocateCommandBuffers", 1169 "vkFreeCommandBuffers", 1170 "vkCreateDisplayModeKHR", 1171 "vkCreateSharedSwapchainsKHR", 1172 "vkGetPhysicalDeviceExternalBufferPropertiesKHR", 1173 "vkGetPhysicalDeviceImageFormatProperties2KHR", 1174 "vkGetMemoryAndroidHardwareBufferANDROID", 1175 ] 1176 1177 coreFunctions = [f for f in api.functions if not f.isAlias] 1178 specialFuncs = [f for f in coreFunctions if f.name in specialFuncNames] 1179 createFuncs = [f for f in coreFunctions if (f.name[:8] == "vkCreate" or f.name == "vkAllocateMemory") and not f in specialFuncs] 1180 destroyFuncs = [f for f in coreFunctions if (f.name[:9] == "vkDestroy" or f.name == "vkFreeMemory") and not f in specialFuncs] 1181 dummyFuncs = [f for f in coreFunctions if f not in specialFuncs + createFuncs + destroyFuncs] 1182 1183 def getHandle (name): 1184 for handle in api.handles: 1185 if handle.name == name[0]: 1186 return handle 1187 raise Exception("No such handle: %s" % name) 1188 1189 for function in createFuncs: 1190 objectType = function.arguments[-1].type[:-1] 1191 argsStr = ", ".join([a.name for a in function.arguments[:-1]]) 1192 1193 yield "VKAPI_ATTR %s VKAPI_CALL %s (%s)" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments)) 1194 yield "{" 1195 yield "\tDE_UNREF(%s);" % function.arguments[-2].name 1196 1197 if getHandle(objectType).type == Handle.TYPE_NONDISP: 1198 yield "\tVK_NULL_RETURN((*%s = allocateNonDispHandle<%s, %s>(%s)));" % (function.arguments[-1].name, objectType[0][2:], objectType[0], argsStr) 1199 else: 1200 yield "\tVK_NULL_RETURN((*%s = allocateHandle<%s, %s>(%s)));" % (function.arguments[-1].name, objectType[0][2:], objectType[0], argsStr) 1201 yield "}" 1202 yield "" 1203 1204 for function in destroyFuncs: 1205 objectArg = function.arguments[-2] 1206 1207 yield "VKAPI_ATTR %s VKAPI_CALL %s (%s)" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments)) 1208 yield "{" 1209 for arg in function.arguments[:-2]: 1210 yield "\tDE_UNREF(%s);" % arg.name 1211 1212 if getHandle(objectArg.type).type == Handle.TYPE_NONDISP: 1213 yield "\tfreeNonDispHandle<%s, %s>(%s, %s);" % (objectArg.getType()[2:], objectArg.getType(), objectArg.name, function.arguments[-1].name) 1214 else: 1215 yield "\tfreeHandle<%s, %s>(%s, %s);" % (objectArg.getType()[2:], objectArg.getType(), objectArg.name, function.arguments[-1].name) 1216 1217 yield "}" 1218 yield "" 1219 1220 for function in dummyFuncs: 1221 yield "VKAPI_ATTR %s VKAPI_CALL %s (%s)" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments)) 1222 yield "{" 1223 for arg in function.arguments: 1224 yield "\tDE_UNREF(%s);" % arg.name 1225 if function.returnType != "void": 1226 yield "\treturn VK_SUCCESS;" 1227 yield "}" 1228 yield "" 1229 1230 def genFuncEntryTable (type, name): 1231 funcs = [f for f in api.functions if f.getType() == type] 1232 refFuncs = {} 1233 for f in api.functions: 1234 if f.alias != None: 1235 refFuncs[f.alias] = f 1236 1237 yield "static const tcu::StaticFunctionLibrary::Entry %s[] =" % name 1238 yield "{" 1239 for line in indentLines(["\tVK_NULL_FUNC_ENTRY(%s,\t%s)," % (function.name, getInterfaceName(function if not function.isAlias else refFuncs[function])) for function in funcs]): 1240 yield line 1241 yield "};" 1242 yield "" 1243 1244 # Func tables 1245 for line in genFuncEntryTable(Function.TYPE_PLATFORM, "s_platformFunctions"): 1246 yield line 1247 1248 for line in genFuncEntryTable(Function.TYPE_INSTANCE, "s_instanceFunctions"): 1249 yield line 1250 1251 for line in genFuncEntryTable(Function.TYPE_DEVICE, "s_deviceFunctions"): 1252 yield line 1253 1254 writeInlFile(filename, INL_HEADER, genNullDriverImpl()) 1255 1256def writeTypeUtil (api, filename): 1257 # Structs filled by API queries are not often used in test code 1258 QUERY_RESULT_TYPES = set([ 1259 "VkPhysicalDeviceFeatures", 1260 "VkPhysicalDeviceLimits", 1261 "VkFormatProperties", 1262 "VkImageFormatProperties", 1263 "VkPhysicalDeviceSparseProperties", 1264 "VkQueueFamilyProperties", 1265 "VkMemoryType", 1266 "VkMemoryHeap", 1267 ]) 1268 COMPOSITE_TYPES = set([t.name for t in api.compositeTypes if not t.isAlias]) 1269 1270 def isSimpleStruct (type): 1271 def hasArrayMember (type): 1272 for member in type.members: 1273 if member.arraySize != '': 1274 return True 1275 return False 1276 1277 def hasCompositeMember (type): 1278 for member in type.members: 1279 if member.getType() in COMPOSITE_TYPES: 1280 return True 1281 return False 1282 1283 return type.typeClass == CompositeType.CLASS_STRUCT and \ 1284 type.members[0].getType() != "VkStructureType" and \ 1285 not type.name in QUERY_RESULT_TYPES and \ 1286 not hasArrayMember(type) and \ 1287 not hasCompositeMember(type) 1288 1289 def gen (): 1290 for type in api.compositeTypes: 1291 if not isSimpleStruct(type) or type.isAlias: 1292 continue 1293 1294 yield "" 1295 yield "inline %s make%s (%s)" % (type.name, type.name[2:], argListToStr(type.members)) 1296 yield "{" 1297 yield "\t%s res;" % type.name 1298 for line in indentLines(["\tres.%s\t= %s;" % (m.name, m.name) for m in type.members]): 1299 yield line 1300 yield "\treturn res;" 1301 yield "}" 1302 1303 writeInlFile(filename, INL_HEADER, gen()) 1304 1305def writeSupportedExtenions(api, filename): 1306 1307 def writeExtensionsForVersions(map): 1308 result = [] 1309 for version in map: 1310 result.append(" if (coreVersion >= " + str(version) + ")") 1311 result.append(" {") 1312 for extension in map[version]: 1313 result.append(' dst.push_back("' + extension.name + '");') 1314 result.append(" }") 1315 1316 return result 1317 1318 instanceMap = {} 1319 deviceMap = {} 1320 versionSet = set() 1321 1322 for ext in api.extensions: 1323 if ext.versionInCore != None: 1324 if ext.versionInCore[0] == 'INSTANCE': 1325 list = instanceMap.get(Version(ext.versionInCore[1:])) 1326 instanceMap[Version(ext.versionInCore[1:])] = list + [ext] if list else [ext] 1327 else: 1328 list = deviceMap.get(Version(ext.versionInCore[1:])) 1329 deviceMap[Version(ext.versionInCore[1:])] = list + [ext] if list else [ext] 1330 versionSet.add(Version(ext.versionInCore[1:])) 1331 1332 lines = addVersionDefines(versionSet) + [ 1333 "", 1334 "void getCoreDeviceExtensionsImpl (deUint32 coreVersion, ::std::vector<const char*>&%s)" % (" dst" if len(deviceMap) != 0 else ""), 1335 "{"] + writeExtensionsForVersions(deviceMap) + [ 1336 "}", 1337 "", 1338 "void getCoreInstanceExtensionsImpl (deUint32 coreVersion, ::std::vector<const char*>&%s)" % (" dst" if len(instanceMap) != 0 else ""), 1339 "{"] + writeExtensionsForVersions(instanceMap) + [ 1340 "}", 1341 ""] + removeVersionDefines(versionSet) 1342 writeInlFile(filename, INL_HEADER, lines) 1343 1344def writeCoreFunctionalities(api, filename): 1345 functionOriginValues = ["FUNCTIONORIGIN_PLATFORM", "FUNCTIONORIGIN_INSTANCE", "FUNCTIONORIGIN_DEVICE"] 1346 1347 lines = addVersionDefines([Version((1, 0, 0)), Version((1, 1, 0))]) + [ 1348 "", 1349 'enum FunctionOrigin', '{'] + [line for line in indentLines([ 1350 '\t' + functionOriginValues[0] + '\t= 0,', 1351 '\t' + functionOriginValues[1] + ',', 1352 '\t' + functionOriginValues[2]])] + [ 1353 "};", 1354 "", 1355 "typedef ::std::pair<const char*, FunctionOrigin> FunctionInfo;", 1356 "typedef ::std::vector<FunctionInfo> FunctionInfosList;", 1357 "typedef ::std::map<deUint32, FunctionInfosList> ApisMap;", 1358 "", 1359 "void initApisMap (ApisMap& apis)", 1360 "{", 1361 " apis.clear();", 1362 " apis.insert(::std::pair<deUint32, FunctionInfosList>(" + str(Version((1, 0, 0))) + ", FunctionInfosList()));", 1363 " apis.insert(::std::pair<deUint32, FunctionInfosList>(" + str(Version((1, 1, 0))) + ", FunctionInfosList()));", 1364 ""] 1365 1366 def list10Funcs (): 1367 for fun in api.functions: 1368 if fun.apiVersion == 'VK_VERSION_1_0': 1369 insert = ' apis[' + str(Version((1, 0, 0))) + '].push_back(FunctionInfo("' + fun.name + '",\t' + functionOriginValues[fun.getType()] + '));' 1370 yield insert 1371 1372 def listAllFuncs (): 1373 for fun in api.extensions[0].functions: 1374 insert = ' apis[' + str(Version((1, 1, 0))) + '].push_back(FunctionInfo("' + fun.name + '",\t' + functionOriginValues[fun.getType()] + '));' 1375 yield insert 1376 1377 lines = lines + [line for line in indentLines(list10Funcs())] 1378 lines.append("") 1379 lines = lines + [line for line in indentLines(listAllFuncs())] 1380 1381 lines.append("}") 1382 lines.append("") 1383 lines = lines + removeVersionDefines([Version((1, 0, 0)), Version((1, 1, 0))]) 1384 1385 writeInlFile(filename, INL_HEADER, lines) 1386 1387if __name__ == "__main__": 1388 src = readFile(VULKAN_H) 1389 api = parseAPI(src) 1390 1391 platformFuncs = [Function.TYPE_PLATFORM] 1392 instanceFuncs = [Function.TYPE_INSTANCE] 1393 deviceFuncs = [Function.TYPE_DEVICE] 1394 1395 writeHandleType (api, os.path.join(VULKAN_DIR, "vkHandleType.inl")) 1396 writeBasicTypes (api, os.path.join(VULKAN_DIR, "vkBasicTypes.inl")) 1397 writeCompositeTypes (api, os.path.join(VULKAN_DIR, "vkStructTypes.inl")) 1398 writeInterfaceDecl (api, os.path.join(VULKAN_DIR, "vkVirtualPlatformInterface.inl"), platformFuncs, False) 1399 writeInterfaceDecl (api, os.path.join(VULKAN_DIR, "vkVirtualInstanceInterface.inl"), instanceFuncs, False) 1400 writeInterfaceDecl (api, os.path.join(VULKAN_DIR, "vkVirtualDeviceInterface.inl"), deviceFuncs, False) 1401 writeInterfaceDecl (api, os.path.join(VULKAN_DIR, "vkConcretePlatformInterface.inl"), platformFuncs, True) 1402 writeInterfaceDecl (api, os.path.join(VULKAN_DIR, "vkConcreteInstanceInterface.inl"), instanceFuncs, True) 1403 writeInterfaceDecl (api, os.path.join(VULKAN_DIR, "vkConcreteDeviceInterface.inl"), deviceFuncs, True) 1404 writeFunctionPtrTypes (api, os.path.join(VULKAN_DIR, "vkFunctionPointerTypes.inl")) 1405 writeFunctionPointers (api, os.path.join(VULKAN_DIR, "vkPlatformFunctionPointers.inl"), platformFuncs) 1406 writeFunctionPointers (api, os.path.join(VULKAN_DIR, "vkInstanceFunctionPointers.inl"), instanceFuncs) 1407 writeFunctionPointers (api, os.path.join(VULKAN_DIR, "vkDeviceFunctionPointers.inl"), deviceFuncs) 1408 writeInitFunctionPointers (api, os.path.join(VULKAN_DIR, "vkInitPlatformFunctionPointers.inl"), platformFuncs, lambda f: f.name != "vkGetInstanceProcAddr") 1409 writeInitFunctionPointers (api, os.path.join(VULKAN_DIR, "vkInitInstanceFunctionPointers.inl"), instanceFuncs) 1410 writeInitFunctionPointers (api, os.path.join(VULKAN_DIR, "vkInitDeviceFunctionPointers.inl"), deviceFuncs) 1411 writeFuncPtrInterfaceImpl (api, os.path.join(VULKAN_DIR, "vkPlatformDriverImpl.inl"), platformFuncs, "PlatformDriver") 1412 writeFuncPtrInterfaceImpl (api, os.path.join(VULKAN_DIR, "vkInstanceDriverImpl.inl"), instanceFuncs, "InstanceDriver") 1413 writeFuncPtrInterfaceImpl (api, os.path.join(VULKAN_DIR, "vkDeviceDriverImpl.inl"), deviceFuncs, "DeviceDriver") 1414 writeStrUtilProto (api, os.path.join(VULKAN_DIR, "vkStrUtil.inl")) 1415 writeStrUtilImpl (api, os.path.join(VULKAN_DIR, "vkStrUtilImpl.inl")) 1416 writeRefUtilProto (api, os.path.join(VULKAN_DIR, "vkRefUtil.inl")) 1417 writeRefUtilImpl (api, os.path.join(VULKAN_DIR, "vkRefUtilImpl.inl")) 1418 writeStructTraitsImpl (api, os.path.join(VULKAN_DIR, "vkGetStructureTypeImpl.inl")) 1419 writeNullDriverImpl (api, os.path.join(VULKAN_DIR, "vkNullDriverImpl.inl")) 1420 writeTypeUtil (api, os.path.join(VULKAN_DIR, "vkTypeUtil.inl")) 1421 writeSupportedExtenions (api, os.path.join(VULKAN_DIR, "vkSupportedExtensions.inl")) 1422 writeCoreFunctionalities (api, os.path.join(VULKAN_DIR, "vkCoreFunctionalities.inl")) 1423