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