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