| # -*- coding: utf-8 -*- |
| |
| #------------------------------------------------------------------------- |
| # Vulkan CTS |
| # ---------- |
| # |
| # Copyright (c) 2015 Google Inc. |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| # |
| #------------------------------------------------------------------------- |
| |
| import os |
| import re |
| import sys |
| import copy |
| from itertools import chain |
| from collections import OrderedDict |
| |
| sys.path.append(os.path.join(os.path.dirname(__file__), "..", "..", "..", "scripts")) |
| |
| from build.common import DEQP_DIR |
| from khr_util.format import indentLines, writeInlFile |
| |
| VULKAN_H = os.path.join(os.path.dirname(__file__), "src", "vulkan.h.in") |
| VULKAN_DIR = os.path.join(os.path.dirname(__file__), "..", "framework", "vulkan") |
| |
| INL_HEADER = """\ |
| /* WARNING: This is auto-generated file. Do not modify, since changes will |
| * be lost! Modify the generating script instead. |
| */\ |
| """ |
| |
| DEFINITIONS = [ |
| ("VK_API_VERSION_1_0", "deUint32"), |
| ("VK_API_VERSION_1_1", "deUint32"), |
| ("VK_MAX_PHYSICAL_DEVICE_NAME_SIZE", "size_t"), |
| ("VK_MAX_EXTENSION_NAME_SIZE", "size_t"), |
| ("VK_MAX_DRIVER_NAME_SIZE_KHR", "size_t"), |
| ("VK_MAX_DRIVER_INFO_SIZE_KHR", "size_t"), |
| ("VK_UUID_SIZE", "size_t"), |
| ("VK_LUID_SIZE", "size_t"), |
| ("VK_MAX_MEMORY_TYPES", "size_t"), |
| ("VK_MAX_MEMORY_HEAPS", "size_t"), |
| ("VK_MAX_DESCRIPTION_SIZE", "size_t"), |
| ("VK_MAX_DEVICE_GROUP_SIZE", "size_t"), |
| ("VK_ATTACHMENT_UNUSED", "deUint32"), |
| ("VK_SUBPASS_EXTERNAL", "deUint32"), |
| ("VK_QUEUE_FAMILY_IGNORED", "deUint32"), |
| ("VK_QUEUE_FAMILY_EXTERNAL", "deUint32"), |
| ("VK_REMAINING_MIP_LEVELS", "deUint32"), |
| ("VK_REMAINING_ARRAY_LAYERS", "deUint32"), |
| ("VK_WHOLE_SIZE", "vk::VkDeviceSize"), |
| ("VK_TRUE", "vk::VkBool32"), |
| ("VK_FALSE", "vk::VkBool32"), |
| ] |
| |
| PLATFORM_TYPES = [ |
| # VK_KHR_xlib_surface |
| (["Display","*"], ["XlibDisplayPtr"], "void*"), |
| (["Window"], ["XlibWindow"], "deUintptr",), |
| (["VisualID"], ["XlibVisualID"], "deUint32"), |
| |
| # VK_KHR_xcb_surface |
| (["xcb_connection_t", "*"], ["XcbConnectionPtr"], "void*"), |
| (["xcb_window_t"], ["XcbWindow"], "deUintptr"), |
| (["xcb_visualid_t"], ["XcbVisualid"], "deUint32"), |
| |
| # VK_KHR_wayland_surface |
| (["struct", "wl_display","*"], ["WaylandDisplayPtr"], "void*"), |
| (["struct", "wl_surface", "*"], ["WaylandSurfacePtr"], "void*"), |
| |
| # VK_KHR_mir_surface |
| (["MirConnection", "*"], ["MirConnectionPtr"], "void*"), |
| (["MirSurface", "*"], ["MirSurfacePtr"], "void*"), |
| |
| # VK_KHR_android_surface |
| (["ANativeWindow", "*"], ["AndroidNativeWindowPtr"], "void*"), |
| |
| # VK_KHR_win32_surface |
| (["HINSTANCE"], ["Win32InstanceHandle"], "void*"), |
| (["HWND"], ["Win32WindowHandle"], "void*"), |
| (["HANDLE"], ["Win32Handle"], "void*"), |
| (["const", "SECURITY_ATTRIBUTES", "*"], ["Win32SecurityAttributesPtr"], "const void*"), |
| (["AHardwareBuffer", "*"], ["AndroidHardwareBufferPtr"], "void*"), |
| |
| # VK_EXT_acquire_xlib_display |
| (["RROutput"], ["RROutput"], "void*") |
| ] |
| |
| PLATFORM_TYPE_NAMESPACE = "pt" |
| |
| TYPE_SUBSTITUTIONS = [ |
| ("uint8_t", "deUint8"), |
| ("uint16_t", "deUint16"), |
| ("uint32_t", "deUint32"), |
| ("uint64_t", "deUint64"), |
| ("int8_t", "deInt8"), |
| ("int16_t", "deInt16"), |
| ("int32_t", "deInt32"), |
| ("int64_t", "deInt64"), |
| ("bool32_t", "deUint32"), |
| ("size_t", "deUintptr"), |
| |
| # Platform-specific |
| ("DWORD", "deUint32"), |
| ("HANDLE*", PLATFORM_TYPE_NAMESPACE + "::" + "Win32Handle*"), |
| ("LPCWSTR", "char*"), |
| ] |
| |
| EXTENSION_POSTFIXES = ["KHR", "EXT", "NV", "NVX", "KHX", "NN", "MVK"] |
| EXTENSION_POSTFIXES_STANDARD = ["KHR"] |
| |
| def prefixName (prefix, name): |
| name = re.sub(r'([a-z0-9])([A-Z])', r'\1_\2', name[2:]) |
| name = re.sub(r'([a-zA-Z])([0-9])', r'\1_\2', name) |
| name = name.upper() |
| |
| name = name.replace("YCB_CR_", "YCBCR_") |
| name = name.replace("WIN_32_", "WIN32_") |
| name = name.replace("8_BIT_", "8BIT_") |
| name = name.replace("16_BIT_", "16BIT_") |
| name = name.replace("INT_64_", "INT64_") |
| name = name.replace("D_3_D_12_", "D3D12_") |
| name = name.replace("IOSSURFACE_", "IOS_SURFACE_") |
| name = name.replace("MAC_OS", "MACOS_") |
| name = name.replace("TEXTURE_LOD", "TEXTURE_LOD_") |
| name = name.replace("VIEWPORT_W", "VIEWPORT_W_") |
| name = name.replace("_IDPROPERTIES", "_ID_PROPERTIES") |
| name = name.replace("PHYSICAL_DEVICE_FLOAT_16_INT_8_FEATURES", "PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES") |
| |
| return prefix + name |
| |
| class Version: |
| def __init__ (self, versionTuple): |
| self.major = versionTuple[0] |
| self.minor = versionTuple[1] |
| self.patch = versionTuple[2] |
| |
| def getInHex (self): |
| if self.major == 1 and self.minor == 0 and self.patch == 0: |
| return "VK_API_VERSION_1_0" |
| elif self.major == 1 and self.minor == 1 and self.patch == 0: |
| return "VK_API_VERSION_1_1" |
| else: |
| hex = (self.major << 22) | (self.minor << 12) | self.patch |
| return '0x%Xu' % (hex) |
| |
| def isStandardVersion (self): |
| if self.patch != 0: |
| return False |
| if self.major != 1: |
| return False |
| if self.minor != 1 and self.minor != 0: |
| return False |
| return True |
| |
| def getBestRepresentation (self): |
| if self.isStandardVersion(): |
| return self.getInHex() |
| return self.getDefineName() |
| |
| def getDefineName (self): |
| return 'VERSION_%d_%d_%d' % (self.major, self.minor, self.patch) |
| |
| def __hash__ (self): |
| return (self.major << 22) | (self.minor << 12) | self.patch |
| |
| def __eq__ (self, other): |
| return self.major == other.major and self.minor == other.minor and self.patch == other.patch |
| |
| def __str__ (self): |
| return self.getBestRepresentation() |
| |
| |
| class Handle: |
| TYPE_DISP = 0 |
| TYPE_NONDISP = 1 |
| |
| def __init__ (self, type, name): |
| self.type = type |
| self.name = name |
| self.alias = None |
| self.isAlias = False |
| |
| def getHandleType (self): |
| return prefixName("HANDLE_TYPE_", self.name) |
| |
| def checkAliasValidity (self): |
| pass |
| |
| def __repr__ (self): |
| return '%s (%s, %s)' % (self.name, self.alias, self.isAlias) |
| |
| class Definition: |
| def __init__ (self, type, name, value): |
| self.type = type |
| self.name = name |
| self.value = value |
| self.alias = None |
| self.isAlias = False |
| |
| def __repr__ (self): |
| return '%s = %s (%s)' % (self.name, self.value, self.type) |
| |
| class Enum: |
| def __init__ (self, name, values): |
| self.name = name |
| self.values = values |
| self.alias = None |
| self.isAlias = False |
| |
| def checkAliasValidity (self): |
| if self.alias != None: |
| if len(self.values) != len(self.alias.values): |
| raise Exception("%s has different number of flags than its alias %s." % (self.name, self.alias.name)) |
| for index, value in enumerate(self.values): |
| aliasVal = self.alias.values[index] |
| if value[1] != aliasVal[1] or not (value[0].startswith(aliasVal[0]) or aliasVal[0].startswith(value[0])): |
| raise Exception("Flag %s of %s has different value than %s of %s." % (self.alias.values[index], self.alias.name, value, self.name)) |
| |
| def __repr__ (self): |
| return '%s (%s) %s' % (self.name, self.alias, self.values) |
| |
| class Bitfield: |
| def __init__ (self, name, values): |
| self.name = name |
| self.values = values |
| self.alias = None |
| self.isAlias = False |
| |
| def checkAliasValidity (self): |
| if self.alias != None: |
| if len(self.values) != len(self.alias.values): |
| raise Exception("%s has different number of flags than its alias %s." % (self.name, self.alias.name)) |
| for index, value in enumerate(self.values): |
| aliasVal = self.alias.values[index] |
| if value[1] != aliasVal[1] or not (value[0].startswith(aliasVal[0]) or aliasVal[0].startswith(value[0])): |
| raise Exception("Flag %s of %s has different value than %s of %s." % (self.alias.values[index], self.alias.name, value, self.name)) |
| |
| def __repr__ (self): |
| return '%s (%s)' % (self.name, self.alias) |
| |
| class Variable: |
| def __init__ (self, type, name, arraySize): |
| type = type.replace('*',' *').replace('&',' &') |
| for src, dst in TYPE_SUBSTITUTIONS: |
| type = type.replace(src, dst) |
| self.type = type.split(' ') |
| for platformType, substitute, compat in PLATFORM_TYPES: |
| range = self.contains(self.type, platformType) |
| if range != None: |
| self.type = self.type[:range[0]]+[PLATFORM_TYPE_NAMESPACE + '::' + substitute[0]] + substitute[1:] + self.type[range[1]:] |
| break |
| self.name = name |
| self.arraySize = arraySize |
| |
| def contains(self, big, small): |
| for i in xrange(len(big)-len(small)+1): |
| for j in xrange(len(small)): |
| if big[i+j] != small[j]: |
| break |
| else: |
| return i, i+len(small) |
| return None |
| |
| def getType (self): |
| return ' '.join(self.type).replace(' *','*').replace(' &','&') |
| |
| def getAsString (self, separator): |
| return '%s%s%s%s' % (self.getType(), separator, self.name, self.arraySize) |
| |
| def __repr__ (self): |
| return '<%s> <%s> <%s>' % (self.type, self.name, self.arraySize) |
| |
| def __eq__ (self, other): |
| if len(self.type) != len(other.type): |
| return False |
| for index, type in enumerate(self.type): |
| if "*" == type or "&" == type or "const" == type or "volatile" == type: |
| if type != other.type[index]: |
| return False |
| elif type != other.type[index] and \ |
| type not in map(lambda ext: other.type[index] + ext, EXTENSION_POSTFIXES_STANDARD) and \ |
| other.type[index] not in map(lambda ext: type + ext, EXTENSION_POSTFIXES_STANDARD): |
| return False |
| return self.arraySize == other.arraySize |
| |
| def __ne__ (self, other): |
| return not self == other |
| |
| class CompositeType: |
| CLASS_STRUCT = 0 |
| CLASS_UNION = 1 |
| |
| def __init__ (self, typeClass, name, members): |
| self.typeClass = typeClass |
| self.name = name |
| self.members = members |
| self.alias = None |
| self.isAlias = False |
| |
| def getClassName (self): |
| names = {CompositeType.CLASS_STRUCT: 'struct', CompositeType.CLASS_UNION: 'union'} |
| return names[self.typeClass] |
| |
| def checkAliasValidity (self): |
| if self.alias != None: |
| if len(self.members) != len(self.alias.members): |
| raise Exception("%s has different number of members than its alias %s." % (self.name, self.alias.name)) |
| for index, member in enumerate(self.members ): |
| break |
| #if member != self.alias.members[index]: |
| #raise Exception("Member %s of %s is different than core member %s in %s." % (self.alias.members[index], self.alias.name, member, self.name)) |
| #raise Exception("Member ",str(self.alias.members[index])," of ", str(self.alias.name)," is different than core member ", str(member)," in ", str(self.name),".") |
| def __repr__ (self): |
| return '%s (%s)' % (self.name, self.alias) |
| |
| class Function: |
| TYPE_PLATFORM = 0 # Not bound to anything |
| TYPE_INSTANCE = 1 # Bound to VkInstance |
| TYPE_DEVICE = 2 # Bound to VkDevice |
| |
| def __init__ (self, name, returnType, arguments, apiVersion = None): |
| self.name = name |
| self.returnType = returnType |
| self.arguments = arguments |
| self.alias = None |
| self.isAlias = False |
| self.apiVersion = apiVersion |
| |
| def getType (self): |
| # Special functions |
| if self.name == "vkGetInstanceProcAddr": |
| return Function.TYPE_PLATFORM |
| assert len(self.arguments) > 0 |
| firstArgType = self.arguments[0].getType() |
| if firstArgType in ["VkInstance", "VkPhysicalDevice"]: |
| return Function.TYPE_INSTANCE |
| elif firstArgType in ["VkDevice", "VkCommandBuffer", "VkQueue"]: |
| return Function.TYPE_DEVICE |
| else: |
| return Function.TYPE_PLATFORM |
| |
| def checkAliasValidity (self): |
| if self.alias != None: |
| if len(self.arguments) != len(self.alias.arguments): |
| raise Exception("%s has different number of arguments than its alias %s." % (self.name, self.alias.name)) |
| if self.returnType != self.alias.returnType or not (self.returnType.startswith(self.alias.returnType) or self.alias.returnType.startswith(self.returnType)): |
| raise Exception("%s has different return value's type than its alias %s." % (self.name, self.alias.name)) |
| for index, argument in enumerate(self.arguments): |
| if argument != self.alias.arguments[index]: |
| 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)) |
| |
| def __repr__ (self): |
| return '%s (%s)' % (self.name, self.alias) |
| |
| class Extension: |
| def __init__ (self, name, handles, enums, bitfields, compositeTypes, functions, definitions, additionalDefinitions, versionInCore): |
| self.name = name |
| self.definitions = definitions |
| self.additionalDefs = additionalDefinitions |
| self.handles = handles |
| self.enums = enums |
| self.bitfields = bitfields |
| self.compositeTypes = compositeTypes |
| self.functions = functions |
| self.versionInCore = versionInCore |
| |
| def __repr__ (self): |
| 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) |
| |
| class API: |
| def __init__ (self, definitions, handles, enums, bitfields, compositeTypes, functions, extensions): |
| self.definitions = definitions |
| self.handles = handles |
| self.enums = enums |
| self.bitfields = bitfields |
| self.compositeTypes = compositeTypes |
| self.functions = functions # \note contains extension functions as well |
| self.extensions = extensions |
| |
| def readFile (filename): |
| with open(filename, 'rb') as f: |
| return f.read() |
| |
| IDENT_PTRN = r'[a-zA-Z_][a-zA-Z0-9_]*' |
| TYPE_PTRN = r'[a-zA-Z_][a-zA-Z0-9_ \t*&]*' |
| |
| def fixupEnumValues (values): |
| fixed = [] |
| for name, value in values: |
| if "_BEGIN_RANGE" in name or "_END_RANGE" in name: |
| continue |
| fixed.append((name, value)) |
| return fixed |
| |
| def getInterfaceName (function): |
| assert function.name[:2] == "vk" |
| return function.name[2].lower() + function.name[3:] |
| |
| def getFunctionTypeName (function): |
| assert function.name[:2] == "vk" |
| return function.name[2:] + "Func" |
| |
| def endsWith (str, postfix): |
| return str[-len(postfix):] == postfix |
| |
| def splitNameExtPostfix (name): |
| knownExtPostfixes = EXTENSION_POSTFIXES |
| for postfix in knownExtPostfixes: |
| if endsWith(name, postfix): |
| return (name[:-len(postfix)], postfix) |
| return (name, "") |
| |
| def getBitEnumNameForBitfield (bitfieldName): |
| bitfieldName, postfix = splitNameExtPostfix(bitfieldName) |
| assert bitfieldName[-1] == "s" |
| return bitfieldName[:-1] + "Bits" + postfix |
| |
| def getBitfieldNameForBitEnum (bitEnumName): |
| bitEnumName, postfix = splitNameExtPostfix(bitEnumName) |
| assert bitEnumName[-4:] == "Bits" |
| return bitEnumName[:-4] + "s" + postfix |
| |
| def parsePreprocDefinedValue (src, name): |
| value = parsePreprocDefinedValueOptional(src, name) |
| if value is None: |
| |
| raise Exception("No such definition: %s" % name) |
| return value |
| |
| def parsePreprocDefinedValueOptional (src, name): |
| definition = re.search(r'#\s*define\s+' + name + r'\s+([^\n]+)\n', src) |
| if definition is None: |
| return None |
| value = definition.group(1).strip() |
| if value == "UINT32_MAX": |
| value = "(~0u)" |
| return value |
| |
| def parseEnum (name, src): |
| keyValuePtrn = '(' + IDENT_PTRN + r')\s*=\s*([^\s,}]+)\s*[,}]' |
| matches = re.findall(keyValuePtrn, src) |
| |
| return Enum(name, fixupEnumValues(matches)) |
| |
| # \note Parses raw enums, some are mapped to bitfields later |
| def parseEnums (src): |
| matches = re.findall(r'typedef enum(\s*' + IDENT_PTRN + r')?\s*{([^}]*)}\s*(' + IDENT_PTRN + r')\s*;', src) |
| enums = [] |
| for enumname, contents, typename in matches: |
| enums.append(parseEnum(typename, contents)) |
| return enums |
| |
| |
| |
| def parseCompositeType (type, name, src): |
| typeNamePtrn = r'(' + TYPE_PTRN + r')(\s+' + IDENT_PTRN + r')((\[[^\]]+\])*)\s*;' |
| matches = re.findall(typeNamePtrn, src) |
| members = [Variable(t.strip(), n.strip(), a.strip()) for t, n, a, _ in matches] |
| return CompositeType(type, name, members) |
| |
| def parseCompositeTypes (src): |
| typeMap = { 'struct': CompositeType.CLASS_STRUCT, 'union': CompositeType.CLASS_UNION } |
| matches = re.findall(r'typedef (struct|union)(\s*' + IDENT_PTRN + r')?\s*{([^}]*)}\s*(' + IDENT_PTRN + r')\s*;', src) |
| types = [] |
| for type, structname, contents, typename in matches: |
| types.append(parseCompositeType(typeMap[type], typename, contents)) |
| return types |
| |
| def parseHandles (src): |
| matches = re.findall(r'VK_DEFINE(_NON_DISPATCHABLE|)_HANDLE\((' + IDENT_PTRN + r')\)[ \t]*[\n\r]', src) |
| handles = [] |
| typeMap = {'': Handle.TYPE_DISP, '_NON_DISPATCHABLE': Handle.TYPE_NONDISP} |
| for type, name in matches: |
| handle = Handle(typeMap[type], name) |
| handles.append(handle) |
| return handles |
| |
| def parseArgList (src): |
| typeNamePtrn = r'(' + TYPE_PTRN + r')(\s+' + IDENT_PTRN + r')((\[[^\]]+\])*)\s*' |
| args = [] |
| for rawArg in src.split(','): |
| m = re.search(typeNamePtrn, rawArg) |
| args.append(Variable(m.group(1).strip(), m.group(2).strip(), m.group(3))) |
| return args |
| |
| def removeTypeExtPostfix (name): |
| for extPostfix in EXTENSION_POSTFIXES_STANDARD: |
| if endsWith(name, extPostfix): |
| return name[0:-len(extPostfix)] |
| return None |
| |
| def populateAliases (objects): |
| objectsByName = {} |
| for object in objects: |
| objectsByName[object.name] = object |
| for object in objects: |
| withoutPostfix = removeTypeExtPostfix(object.name) |
| if withoutPostfix != None and withoutPostfix in objectsByName: |
| objectsByName[withoutPostfix].alias = object |
| object.isAlias = True |
| for object in objects: |
| object.checkAliasValidity() |
| |
| def populateAliasesWithTypedefs (objects, src): |
| objectsByName = {} |
| for object in objects: |
| objectsByName[object.name] = object |
| ptrn = r'\s*typedef\s+' + object.name + r'\s+([^;]+)' |
| stash = re.findall(ptrn, src) |
| if len(stash) == 1: |
| objExt = copy.deepcopy(object) |
| objExt.name = stash[0] |
| object.alias = objExt |
| objExt.isAlias = True |
| objects.append(objExt) |
| |
| |
| def removeAliasedValues (enum): |
| valueByName = {} |
| for name, value in enum.values: |
| valueByName[name] = value |
| |
| def removeDefExtPostfix (name): |
| for extPostfix in EXTENSION_POSTFIXES: |
| if endsWith(name, "_" + extPostfix): |
| return name[0:-(len(extPostfix)+1)] |
| return None |
| |
| newValues = [] |
| for name, value in enum.values: |
| withoutPostfix = removeDefExtPostfix(name) |
| if withoutPostfix != None and withoutPostfix in valueByName and valueByName[withoutPostfix] == value: |
| continue |
| newValues.append((name, value)) |
| enum.values = newValues |
| |
| def parseFunctions (src): |
| ptrn = r'VKAPI_ATTR\s+(' + TYPE_PTRN + ')\s+VKAPI_CALL\s+(' + IDENT_PTRN + r')\s*\(([^)]*)\)\s*;' |
| matches = re.findall(ptrn, src) |
| functions = [] |
| for returnType, name, argList in matches: |
| functions.append(Function(name.strip(), returnType.strip(), parseArgList(argList))) |
| return functions |
| |
| def parseFunctionsByVersion (src): |
| ptrnVer10 = 'VK_VERSION_1_0 1' |
| ptrnVer11 = 'VK_VERSION_1_1 1' |
| matchVer10 = re.search(ptrnVer10, src) |
| matchVer11 = re.search(ptrnVer11, src) |
| ptrn = r'VKAPI_ATTR\s+(' + TYPE_PTRN + ')\s+VKAPI_CALL\s+(' + IDENT_PTRN + r')\s*\(([^)]*)\)\s*;' |
| regPtrn = re.compile(ptrn) |
| matches = regPtrn.findall(src, matchVer10.start(), matchVer11.start()) |
| functions = [] |
| for returnType, name, argList in matches: |
| functions.append(Function(name.strip(), returnType.strip(), parseArgList(argList), 'VK_VERSION_1_0')) |
| matches = regPtrn.findall(src, matchVer11.start()) |
| for returnType, name, argList in matches: |
| functions.append(Function(name.strip(), returnType.strip(), parseArgList(argList), 'VK_VERSION_1_1')) |
| return functions |
| |
| def splitByExtension (src): |
| ptrn = r'#define\s+[A-Z0-9_]+_EXTENSION_NAME\s+"([^"]+)"' |
| match = "#define\s+(" |
| for part in re.finditer(ptrn, src): |
| match += part.group(1)+"|" |
| match = match[:-1] + ")\s+1" |
| parts = re.split(match, src) |
| # First part is core |
| byExtension = [(None, parts[0])] |
| for ndx in range(1, len(parts), 2): |
| byExtension.append((parts[ndx], parts[ndx+1])) |
| return byExtension |
| |
| def parseDefinitions (extensionName, src): |
| |
| def skipDefinition (extensionName, definition): |
| if extensionName == None: |
| return True |
| # SPEC_VERSION enums |
| if definition[0].startswith(extensionName.upper()) and definition[1].isdigit(): |
| return False |
| if definition[0].startswith(extensionName.upper()): |
| return True |
| if definition[1].isdigit(): |
| return True |
| return False |
| |
| ptrn = r'#define\s+([^\s]+)\s+([^\r\n]+)' |
| matches = re.findall(ptrn, src) |
| |
| return [Definition(None, match[0], match[1]) for match in matches if not skipDefinition(extensionName, match)] |
| |
| def parseExtensions (src, allFunctions, allCompositeTypes, allEnums, allBitfields, allHandles, allDefinitions): |
| |
| def getCoreVersion (extensionTuple): |
| if not extensionTuple[0]: |
| return None |
| ptrn = r'\/\/\s*' + extensionTuple[0] + r'\s+(DEVICE|INSTANCE)\s+([0-9_]+)' |
| coreVersion = re.search(ptrn, extensionTuple[1], re.I) |
| if coreVersion != None: |
| return [coreVersion.group(1)] + [int(number) for number in coreVersion.group(2).split('_')[:3]] |
| return None |
| |
| splitSrc = splitByExtension(src) |
| extensions = [] |
| functionsByName = {function.name: function for function in allFunctions} |
| compositeTypesByName = {compType.name: compType for compType in allCompositeTypes} |
| enumsByName = {enum.name: enum for enum in allEnums} |
| bitfieldsByName = {bitfield.name: bitfield for bitfield in allBitfields} |
| handlesByName = {handle.name: handle for handle in allHandles} |
| definitionsByName = {definition.name: definition for definition in allDefinitions} |
| |
| for extensionName, extensionSrc in splitSrc: |
| definitions = [Definition(type, name, parsePreprocDefinedValueOptional(extensionSrc, name)) for name, type in DEFINITIONS] |
| definitions = [definition for definition in definitions if definition.value != None] |
| additionalDefinitions = parseDefinitions(extensionName, extensionSrc) |
| handles = parseHandles(extensionSrc) |
| functions = parseFunctions(extensionSrc) |
| compositeTypes = parseCompositeTypes(extensionSrc) |
| rawEnums = parseEnums(extensionSrc) |
| bitfieldNames = parseBitfieldNames(extensionSrc) |
| enumBitfieldNames = [getBitEnumNameForBitfield(name) for name in bitfieldNames] |
| enums = [enum for enum in rawEnums if enum.name not in enumBitfieldNames] |
| |
| extCoreVersion = getCoreVersion((extensionName, extensionSrc)) |
| extFunctions = [functionsByName[function.name] for function in functions] |
| extCompositeTypes = [compositeTypesByName[compositeType.name] for compositeType in compositeTypes] |
| extEnums = [enumsByName[enum.name] for enum in enums] |
| extBitfields = [bitfieldsByName[bitfieldName] for bitfieldName in bitfieldNames] |
| extHandles = [handlesByName[handle.name] for handle in handles] |
| extDefinitions = [definitionsByName[definition.name] for definition in definitions] |
| |
| extensions.append(Extension(extensionName, extHandles, extEnums, extBitfields, extCompositeTypes, extFunctions, extDefinitions, additionalDefinitions, extCoreVersion)) |
| return extensions |
| |
| def parseBitfieldNames (src): |
| ptrn = r'typedef\s+VkFlags\s(' + IDENT_PTRN + r')\s*;' |
| matches = re.findall(ptrn, src) |
| |
| return matches |
| |
| def parseAPI (src): |
| definitions = [Definition(type, name, parsePreprocDefinedValue(src, name)) for name, type in DEFINITIONS] |
| handles = parseHandles(src) |
| rawEnums = parseEnums(src) |
| bitfieldNames = parseBitfieldNames(src) |
| enums = [] |
| bitfields = [] |
| bitfieldEnums = set([getBitEnumNameForBitfield(n) for n in bitfieldNames if getBitEnumNameForBitfield(n) in [enum.name for enum in rawEnums]]) |
| compositeTypes = parseCompositeTypes(src) |
| allFunctions = parseFunctionsByVersion(src) |
| |
| for enum in rawEnums: |
| if enum.name in bitfieldEnums: |
| bitfields.append(Bitfield(getBitfieldNameForBitEnum(enum.name), enum.values)) |
| else: |
| enums.append(enum) |
| |
| for bitfieldName in bitfieldNames: |
| if not bitfieldName in [bitfield.name for bitfield in bitfields]: |
| # Add empty bitfield |
| bitfields.append(Bitfield(bitfieldName, [])) |
| |
| # Populate alias fields |
| populateAliasesWithTypedefs(compositeTypes, src) |
| populateAliasesWithTypedefs(enums, src) |
| populateAliasesWithTypedefs(bitfields, src) |
| populateAliases(allFunctions) |
| populateAliases(handles) |
| populateAliases(enums) |
| populateAliases(bitfields) |
| populateAliases(compositeTypes) |
| |
| |
| for enum in enums: |
| removeAliasedValues(enum) |
| |
| extensions = parseExtensions(src, allFunctions, compositeTypes, enums, bitfields, handles, definitions) |
| |
| return API( |
| definitions = definitions, |
| handles = handles, |
| enums = enums, |
| bitfields = bitfields, |
| compositeTypes = compositeTypes, |
| functions = allFunctions, |
| extensions = extensions) |
| |
| def splitUniqueAndDuplicatedEntries (handles): |
| listOfUniqueHandles = [] |
| duplicates = OrderedDict() |
| for handle in handles: |
| if handle.alias != None: |
| duplicates[handle.alias] = handle |
| if not handle.isAlias: |
| listOfUniqueHandles.append(handle) |
| return listOfUniqueHandles, duplicates |
| |
| def writeHandleType (api, filename): |
| uniqeHandles, duplicatedHandles = splitUniqueAndDuplicatedEntries(api.handles) |
| |
| def genHandles (): |
| yield "\t%s\t= 0," % uniqeHandles[0].getHandleType() |
| for handle in uniqeHandles[1:]: |
| yield "\t%s," % handle.getHandleType() |
| for duplicate in duplicatedHandles: |
| yield "\t%s\t= %s," % (duplicate.getHandleType(), duplicatedHandles[duplicate].getHandleType()) |
| yield "\tHANDLE_TYPE_LAST\t= %s + 1" % (uniqeHandles[-1].getHandleType()) |
| |
| def genHandlesBlock (): |
| yield "enum HandleType" |
| yield "{" |
| |
| for line in indentLines(genHandles()): |
| yield line |
| |
| yield "};" |
| yield "" |
| |
| writeInlFile(filename, INL_HEADER, genHandlesBlock()) |
| |
| def getEnumValuePrefix (enum): |
| prefix = enum.name[0] |
| for i in range(1, len(enum.name)): |
| if enum.name[i].isupper() and not enum.name[i-1].isupper(): |
| prefix += "_" |
| prefix += enum.name[i].upper() |
| return prefix |
| |
| def parseInt (value): |
| if value[:2] == "0x": |
| return int(value, 16) |
| else: |
| return int(value, 10) |
| |
| def areEnumValuesLinear (enum): |
| curIndex = 0 |
| for name, value in enum.values: |
| if parseInt(value) != curIndex: |
| return False |
| curIndex += 1 |
| return True |
| |
| def genEnumSrc (enum): |
| yield "enum %s" % enum.name |
| yield "{" |
| |
| for line in indentLines(["\t%s\t= %s," % v for v in enum.values]): |
| yield line |
| |
| if areEnumValuesLinear(enum): |
| yield "" |
| yield "\t%s_LAST" % getEnumValuePrefix(enum) |
| |
| yield "};" |
| |
| def genBitfieldSrc (bitfield): |
| if len(bitfield.values) > 0: |
| yield "enum %s" % getBitEnumNameForBitfield(bitfield.name) |
| yield "{" |
| for line in indentLines(["\t%s\t= %s," % v for v in bitfield.values]): |
| yield line |
| yield "};" |
| yield "typedef deUint32 %s;" % bitfield.name |
| |
| def genCompositeTypeSrc (type): |
| yield "%s %s" % (type.getClassName(), type.name) |
| yield "{" |
| for line in indentLines(['\t'+m.getAsString('\t')+';' for m in type.members]): |
| yield line |
| yield "};" |
| |
| def genHandlesSrc (handles): |
| uniqeHandles, duplicatedHandles = splitUniqueAndDuplicatedEntries(handles) |
| |
| def genLines (handles): |
| for handle in uniqeHandles: |
| if handle.type == Handle.TYPE_DISP: |
| yield "VK_DEFINE_HANDLE\t(%s,\t%s);" % (handle.name, handle.getHandleType()) |
| elif handle.type == Handle.TYPE_NONDISP: |
| yield "VK_DEFINE_NON_DISPATCHABLE_HANDLE\t(%s,\t%s);" % (handle.name, handle.getHandleType()) |
| |
| for duplicate in duplicatedHandles: |
| if duplicate.type == Handle.TYPE_DISP: |
| yield "VK_DEFINE_HANDLE\t(%s,\t%s);" % (duplicate.name, duplicatedHandles[duplicate].getHandleType()) |
| elif duplicate.type == Handle.TYPE_NONDISP: |
| yield "VK_DEFINE_NON_DISPATCHABLE_HANDLE\t(%s,\t%s);" % (duplicate.name, duplicatedHandles[duplicate].getHandleType()) |
| |
| for line in indentLines(genLines(handles)): |
| yield line |
| |
| def genDefinitionsSrc (definitions): |
| for line in ["#define %s\t(static_cast<%s>\t(%s))" % (definition.name, definition.type, definition.value) for definition in definitions]: |
| yield line |
| |
| def genDefinitionsAliasSrc (definitions): |
| for line in ["#define %s\t%s" % (definition.name, definitions[definition].name) for definition in definitions]: |
| if definition.value != definitions[definition].value and definition.value != definitions[definition].name: |
| raise Exception("Value of %s (%s) is different than core definition value %s (%s)." % (definition.name, definition.value, definitions[definition].name, definitions[definition].value)) |
| yield line |
| |
| def writeBasicTypes (api, filename): |
| |
| def gen (): |
| definitionsCore, definitionDuplicates = splitUniqueAndDuplicatedEntries(api.definitions) |
| |
| for line in indentLines(chain(genDefinitionsSrc(definitionsCore), genDefinitionsAliasSrc(definitionDuplicates))): |
| yield line |
| yield "" |
| |
| for line in genHandlesSrc(api.handles): |
| yield line |
| yield "" |
| |
| for enum in api.enums: |
| if not enum.isAlias: |
| for line in genEnumSrc(enum): |
| yield line |
| yield "" |
| |
| for bitfield in api.bitfields: |
| if not bitfield.isAlias: |
| for line in genBitfieldSrc(bitfield): |
| yield line |
| yield "" |
| for line in indentLines(["VK_DEFINE_PLATFORM_TYPE(%s,\t%s);" % (s[0], c) for n, s, c in PLATFORM_TYPES]): |
| yield line |
| |
| for ext in api.extensions: |
| if ext.additionalDefs != None: |
| for definition in ext.additionalDefs: |
| yield "#define " + definition.name + " " + definition.value |
| writeInlFile(filename, INL_HEADER, gen()) |
| |
| def writeCompositeTypes (api, filename): |
| def gen (): |
| for type in api.compositeTypes: |
| type.checkAliasValidity() |
| |
| if not type.isAlias: |
| for line in genCompositeTypeSrc(type): |
| yield line |
| yield "" |
| |
| writeInlFile(filename, INL_HEADER, gen()) |
| |
| def argListToStr (args): |
| return ", ".join(v.getAsString(' ') for v in args) |
| |
| def writeInterfaceDecl (api, filename, functionTypes, concrete): |
| def genProtos (): |
| postfix = "" if concrete else " = 0" |
| for function in api.functions: |
| if not function.getType() in functionTypes: |
| continue |
| if not function.isAlias: |
| yield "virtual %s\t%s\t(%s) const%s;" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments), postfix) |
| |
| writeInlFile(filename, INL_HEADER, indentLines(genProtos())) |
| |
| def writeFunctionPtrTypes (api, filename): |
| def genTypes (): |
| for function in api.functions: |
| yield "typedef VKAPI_ATTR %s\t(VKAPI_CALL* %s)\t(%s);" % (function.returnType, getFunctionTypeName(function), argListToStr(function.arguments)) |
| |
| writeInlFile(filename, INL_HEADER, indentLines(genTypes())) |
| |
| def writeFunctionPointers (api, filename, functionTypes): |
| def FunctionsYielder (): |
| for function in api.functions: |
| if function.getType() in functionTypes: |
| if function.isAlias: |
| if function.getType() == Function.TYPE_INSTANCE and function.arguments[0].getType() == "VkPhysicalDevice": |
| yield "%s\t%s;" % (getFunctionTypeName(function), getInterfaceName(function)) |
| else: |
| yield "%s\t%s;" % (getFunctionTypeName(function), getInterfaceName(function)) |
| |
| writeInlFile(filename, INL_HEADER, indentLines(FunctionsYielder())) |
| |
| def writeInitFunctionPointers (api, filename, functionTypes, cond = None): |
| def makeInitFunctionPointers (): |
| for function in api.functions: |
| if function.getType() in functionTypes and (cond == None or cond(function)): |
| interfaceName = getInterfaceName(function) |
| if function.isAlias: |
| if function.getType() == Function.TYPE_INSTANCE and function.arguments[0].getType() == "VkPhysicalDevice": |
| yield "m_vk.%s\t= (%s)\tGET_PROC_ADDR(\"%s\");" % (getInterfaceName(function), getFunctionTypeName(function), function.name) |
| else: |
| yield "m_vk.%s\t= (%s)\tGET_PROC_ADDR(\"%s\");" % (getInterfaceName(function), getFunctionTypeName(function), function.name) |
| if function.alias != None: |
| yield "if (!m_vk.%s)" % (getInterfaceName(function)) |
| yield " m_vk.%s\t= (%s)\tGET_PROC_ADDR(\"%s\");" % (getInterfaceName(function), getFunctionTypeName(function), function.alias.name) |
| lines = [line.replace(' ', '\t') for line in indentLines(makeInitFunctionPointers())] |
| writeInlFile(filename, INL_HEADER, lines) |
| |
| def writeFuncPtrInterfaceImpl (api, filename, functionTypes, className): |
| def makeFuncPtrInterfaceImpl (): |
| for function in api.functions: |
| if function.getType() in functionTypes and not function.isAlias: |
| yield "" |
| yield "%s %s::%s (%s) const" % (function.returnType, className, getInterfaceName(function), argListToStr(function.arguments)) |
| yield "{" |
| if function.name == "vkEnumerateInstanceVersion": |
| yield " if (m_vk.enumerateInstanceVersion)" |
| yield " return m_vk.enumerateInstanceVersion(pApiVersion);" |
| yield "" |
| yield " *pApiVersion = VK_API_VERSION_1_0;" |
| yield " return VK_SUCCESS;" |
| elif function.getType() == Function.TYPE_INSTANCE and function.arguments[0].getType() == "VkPhysicalDevice" and function.alias != None: |
| yield " vk::VkPhysicalDeviceProperties props;" |
| yield " m_vk.getPhysicalDeviceProperties(physicalDevice, &props);" |
| yield " if (props.apiVersion >= VK_API_VERSION_1_1)" |
| yield " %sm_vk.%s(%s);" % ("return " if function.returnType != "void" else "", getInterfaceName(function), ", ".join(a.name for a in function.arguments)) |
| yield " else" |
| yield " %sm_vk.%s(%s);" % ("return " if function.returnType != "void" else "", getInterfaceName(function.alias), ", ".join(a.name for a in function.arguments)) |
| else: |
| yield " %sm_vk.%s(%s);" % ("return " if function.returnType != "void" else "", getInterfaceName(function), ", ".join(a.name for a in function.arguments)) |
| yield "}" |
| |
| writeInlFile(filename, INL_HEADER, makeFuncPtrInterfaceImpl()) |
| |
| def writeStrUtilProto (api, filename): |
| def makeStrUtilProto (): |
| 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]): |
| yield line |
| yield "" |
| 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]): |
| yield line |
| yield "" |
| 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]): |
| yield line |
| yield "" |
| 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]): |
| yield line |
| yield "" |
| 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]): |
| yield line |
| |
| writeInlFile(filename, INL_HEADER, makeStrUtilProto()) |
| |
| def writeStrUtilImpl (api, filename): |
| def makeStrUtilImpl (): |
| 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]): |
| yield line |
| |
| yield "" |
| yield "namespace %s" % PLATFORM_TYPE_NAMESPACE |
| yield "{" |
| |
| 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): |
| yield line |
| |
| yield "}" |
| |
| for enum in api.enums: |
| if enum.isAlias: |
| continue |
| yield "" |
| yield "const char* get%sName (%s value)" % (enum.name[2:], enum.name) |
| yield "{" |
| yield "\tswitch (value)" |
| yield "\t{" |
| for line in indentLines(["\t\tcase %s:\treturn \"%s\";" % (n, n) for n, v in enum.values] + ["\t\tdefault:\treturn DE_NULL;"]): |
| yield line |
| yield "\t}" |
| yield "}" |
| |
| for bitfield in api.bitfields: |
| if bitfield.isAlias: |
| continue |
| yield "" |
| yield "tcu::Format::Bitfield<32> get%sStr (%s value)" % (bitfield.name[2:], bitfield.name) |
| yield "{" |
| |
| if len(bitfield.values) > 0: |
| yield "\tstatic const tcu::Format::BitDesc s_desc[] =" |
| yield "\t{" |
| for line in indentLines(["\t\ttcu::Format::BitDesc(%s,\t\"%s\")," % (n, n) for n, v in bitfield.values]): |
| yield line |
| yield "\t};" |
| yield "\treturn tcu::Format::Bitfield<32>(value, DE_ARRAY_BEGIN(s_desc), DE_ARRAY_END(s_desc));" |
| else: |
| yield "\treturn tcu::Format::Bitfield<32>(value, DE_NULL, DE_NULL);" |
| yield "}" |
| |
| bitfieldTypeNames = set([bitfield.name for bitfield in api.bitfields]) |
| |
| for type in api.compositeTypes: |
| if not type.isAlias: |
| yield "" |
| yield "std::ostream& operator<< (std::ostream& s, const %s& value)" % type.name |
| yield "{" |
| yield "\ts << \"%s = {\\n\";" % type.name |
| for member in type.members: |
| memberName = member.name |
| valFmt = None |
| newLine = "" |
| if member.getType() in bitfieldTypeNames: |
| valFmt = "get%sStr(value.%s)" % (member.getType()[2:], member.name) |
| elif member.getType() == "const char*" or member.getType() == "char*": |
| valFmt = "getCharPtrStr(value.%s)" % member.name |
| elif member.arraySize != '': |
| if member.name in ["extensionName", "deviceName", "layerName", "description"]: |
| valFmt = "(const char*)value.%s" % member.name |
| elif member.getType() == 'char' or member.getType() == 'deUint8': |
| newLine = "'\\n' << " |
| 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) |
| else: |
| if member.name == "memoryTypes" or member.name == "memoryHeaps": |
| endIter = "DE_ARRAY_BEGIN(value.%s) + value.%sCount" % (member.name, member.name[:-1]) |
| else: |
| endIter = "DE_ARRAY_END(value.%s)" % member.name |
| newLine = "'\\n' << " |
| valFmt = "tcu::formatArray(DE_ARRAY_BEGIN(value.%s), %s)" % (member.name, endIter) |
| memberName = member.name |
| else: |
| valFmt = "value.%s" % member.name |
| yield ("\ts << \"\\t%s = \" << " % memberName) + newLine + valFmt + " << '\\n';" |
| yield "\ts << '}';" |
| yield "\treturn s;" |
| yield "}" |
| writeInlFile(filename, INL_HEADER, makeStrUtilImpl()) |
| |
| class ConstructorFunction: |
| def __init__ (self, type, name, objectType, ifaceArgs, arguments): |
| self.type = type |
| self.name = name |
| self.objectType = objectType |
| self.ifaceArgs = ifaceArgs |
| self.arguments = arguments |
| |
| def getConstructorFunctions (api): |
| funcs = [] |
| ifacesDict = { |
| Function.TYPE_PLATFORM: [Variable("const PlatformInterface&", "vk", "")], |
| Function.TYPE_INSTANCE: [Variable("const InstanceInterface&", "vk", "")], |
| Function.TYPE_DEVICE: [Variable("const DeviceInterface&", "vk", "")] |
| } |
| for function in api.functions: |
| if function.isAlias: |
| continue |
| if (function.name[:8] == "vkCreate" or function.name == "vkAllocateMemory") and not "createInfoCount" in [a.name for a in function.arguments]: |
| if function.name == "vkCreateDisplayModeKHR": |
| continue # No way to delete display modes (bug?) |
| |
| # \todo [pyry] Rather hacky |
| ifaceArgs = ifacesDict[function.getType()] |
| if function.name == "vkCreateDevice": |
| ifaceArgs = [Variable("const PlatformInterface&", "vkp", ""), Variable("VkInstance", "instance", "")] + ifaceArgs |
| |
| assert (function.arguments[-2].type == ["const", "VkAllocationCallbacks", "*"]) |
| |
| objectType = function.arguments[-1].type[0] #not getType() but type[0] on purpose |
| arguments = function.arguments[:-1] |
| funcs.append(ConstructorFunction(function.getType(), getInterfaceName(function), objectType, ifaceArgs, arguments)) |
| return funcs |
| |
| def addVersionDefines(versionSpectrum): |
| output = ["#define " + ver.getDefineName() + " " + ver.getInHex() for ver in versionSpectrum if not ver.isStandardVersion()] |
| return output |
| |
| def removeVersionDefines(versionSpectrum): |
| output = ["#undef " + ver.getDefineName() for ver in versionSpectrum if not ver.isStandardVersion()] |
| return output |
| |
| def writeRefUtilProto (api, filename): |
| functions = getConstructorFunctions(api) |
| |
| def makeRefUtilProto (): |
| unindented = [] |
| 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]): |
| yield line |
| |
| writeInlFile(filename, INL_HEADER, makeRefUtilProto()) |
| |
| def writeRefUtilImpl (api, filename): |
| functions = getConstructorFunctions(api) |
| |
| def makeRefUtilImpl (): |
| yield "namespace refdetails" |
| yield "{" |
| yield "" |
| |
| for function in api.functions: |
| if function.getType() == Function.TYPE_DEVICE \ |
| and (function.name[:9] == "vkDestroy" or function.name == "vkFreeMemory") \ |
| and not function.name == "vkDestroyDevice" \ |
| and not function.isAlias: |
| objectType = function.arguments[-2].getType() |
| yield "template<>" |
| yield "void Deleter<%s>::operator() (%s obj) const" % (objectType, objectType) |
| yield "{" |
| yield "\tm_deviceIface->%s(m_device, obj, m_allocator);" % (getInterfaceName(function)) |
| yield "}" |
| yield "" |
| |
| yield "} // refdetails" |
| yield "" |
| |
| dtorDict = { |
| Function.TYPE_PLATFORM: "object", |
| Function.TYPE_INSTANCE: "instance", |
| Function.TYPE_DEVICE: "device" |
| } |
| |
| for function in functions: |
| deleterArgsString = '' |
| if function.name == "createDevice": |
| # createDevice requires two additional parameters to setup VkDevice deleter |
| deleterArgsString = "vkp, instance, object, " + function.arguments[-1].name |
| else: |
| deleterArgsString = "vk, %s, %s" % (dtorDict[function.type], function.arguments[-1].name) |
| |
| yield "Move<%s> %s (%s)" % (function.objectType, function.name, argListToStr(function.ifaceArgs + function.arguments)) |
| yield "{" |
| yield "\t%s object = 0;" % function.objectType |
| yield "\tVK_CHECK(vk.%s(%s));" % (function.name, ", ".join([a.name for a in function.arguments] + ["&object"])) |
| yield "\treturn Move<%s>(check<%s>(object), Deleter<%s>(%s));" % (function.objectType, function.objectType, function.objectType, deleterArgsString) |
| yield "}" |
| yield "" |
| |
| writeInlFile(filename, INL_HEADER, makeRefUtilImpl()) |
| |
| def writeStructTraitsImpl (api, filename): |
| def gen (): |
| for type in api.compositeTypes: |
| if type.getClassName() == "struct" and type.members[0].name == "sType" and not type.isAlias: |
| yield "template<> VkStructureType getStructureType<%s> (void)" % type.name |
| yield "{" |
| yield "\treturn %s;" % prefixName("VK_STRUCTURE_TYPE_", type.name) |
| yield "}" |
| yield "" |
| |
| writeInlFile(filename, INL_HEADER, gen()) |
| |
| def writeNullDriverImpl (api, filename): |
| def genNullDriverImpl (): |
| specialFuncNames = [ |
| "vkCreateGraphicsPipelines", |
| "vkCreateComputePipelines", |
| "vkGetInstanceProcAddr", |
| "vkGetDeviceProcAddr", |
| "vkEnumeratePhysicalDevices", |
| "vkEnumerateInstanceExtensionProperties", |
| "vkEnumerateDeviceExtensionProperties", |
| "vkGetPhysicalDeviceFeatures", |
| "vkGetPhysicalDeviceFeatures2KHR", |
| "vkGetPhysicalDeviceProperties", |
| "vkGetPhysicalDeviceProperties2KHR", |
| "vkGetPhysicalDeviceQueueFamilyProperties", |
| "vkGetPhysicalDeviceMemoryProperties", |
| "vkGetPhysicalDeviceFormatProperties", |
| "vkGetPhysicalDeviceImageFormatProperties", |
| "vkGetDeviceQueue", |
| "vkGetBufferMemoryRequirements", |
| "vkGetBufferMemoryRequirements2KHR", |
| "vkGetImageMemoryRequirements", |
| "vkGetImageMemoryRequirements2KHR", |
| "vkAllocateMemory", |
| "vkMapMemory", |
| "vkUnmapMemory", |
| "vkAllocateDescriptorSets", |
| "vkFreeDescriptorSets", |
| "vkResetDescriptorPool", |
| "vkAllocateCommandBuffers", |
| "vkFreeCommandBuffers", |
| "vkCreateDisplayModeKHR", |
| "vkCreateSharedSwapchainsKHR", |
| "vkGetPhysicalDeviceExternalBufferPropertiesKHR", |
| "vkGetPhysicalDeviceImageFormatProperties2KHR", |
| "vkGetMemoryAndroidHardwareBufferANDROID", |
| ] |
| |
| coreFunctions = [f for f in api.functions if not f.isAlias] |
| specialFuncs = [f for f in coreFunctions if f.name in specialFuncNames] |
| createFuncs = [f for f in coreFunctions if (f.name[:8] == "vkCreate" or f.name == "vkAllocateMemory") and not f in specialFuncs] |
| destroyFuncs = [f for f in coreFunctions if (f.name[:9] == "vkDestroy" or f.name == "vkFreeMemory") and not f in specialFuncs] |
| dummyFuncs = [f for f in coreFunctions if f not in specialFuncs + createFuncs + destroyFuncs] |
| |
| def getHandle (name): |
| for handle in api.handles: |
| if handle.name == name[0]: |
| return handle |
| raise Exception("No such handle: %s" % name) |
| |
| for function in createFuncs: |
| objectType = function.arguments[-1].type[:-1] |
| argsStr = ", ".join([a.name for a in function.arguments[:-1]]) |
| |
| yield "VKAPI_ATTR %s VKAPI_CALL %s (%s)" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments)) |
| yield "{" |
| yield "\tDE_UNREF(%s);" % function.arguments[-2].name |
| |
| if getHandle(objectType).type == Handle.TYPE_NONDISP: |
| yield "\tVK_NULL_RETURN((*%s = allocateNonDispHandle<%s, %s>(%s)));" % (function.arguments[-1].name, objectType[0][2:], objectType[0], argsStr) |
| else: |
| yield "\tVK_NULL_RETURN((*%s = allocateHandle<%s, %s>(%s)));" % (function.arguments[-1].name, objectType[0][2:], objectType[0], argsStr) |
| yield "}" |
| yield "" |
| |
| for function in destroyFuncs: |
| objectArg = function.arguments[-2] |
| |
| yield "VKAPI_ATTR %s VKAPI_CALL %s (%s)" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments)) |
| yield "{" |
| for arg in function.arguments[:-2]: |
| yield "\tDE_UNREF(%s);" % arg.name |
| |
| if getHandle(objectArg.type).type == Handle.TYPE_NONDISP: |
| yield "\tfreeNonDispHandle<%s, %s>(%s, %s);" % (objectArg.getType()[2:], objectArg.getType(), objectArg.name, function.arguments[-1].name) |
| else: |
| yield "\tfreeHandle<%s, %s>(%s, %s);" % (objectArg.getType()[2:], objectArg.getType(), objectArg.name, function.arguments[-1].name) |
| |
| yield "}" |
| yield "" |
| |
| for function in dummyFuncs: |
| yield "VKAPI_ATTR %s VKAPI_CALL %s (%s)" % (function.returnType, getInterfaceName(function), argListToStr(function.arguments)) |
| yield "{" |
| for arg in function.arguments: |
| yield "\tDE_UNREF(%s);" % arg.name |
| if function.returnType != "void": |
| yield "\treturn VK_SUCCESS;" |
| yield "}" |
| yield "" |
| |
| def genFuncEntryTable (type, name): |
| funcs = [f for f in api.functions if f.getType() == type] |
| refFuncs = {} |
| for f in api.functions: |
| if f.alias != None: |
| refFuncs[f.alias] = f |
| |
| yield "static const tcu::StaticFunctionLibrary::Entry %s[] =" % name |
| yield "{" |
| 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]): |
| yield line |
| yield "};" |
| yield "" |
| |
| # Func tables |
| for line in genFuncEntryTable(Function.TYPE_PLATFORM, "s_platformFunctions"): |
| yield line |
| |
| for line in genFuncEntryTable(Function.TYPE_INSTANCE, "s_instanceFunctions"): |
| yield line |
| |
| for line in genFuncEntryTable(Function.TYPE_DEVICE, "s_deviceFunctions"): |
| yield line |
| |
| writeInlFile(filename, INL_HEADER, genNullDriverImpl()) |
| |
| def writeTypeUtil (api, filename): |
| # Structs filled by API queries are not often used in test code |
| QUERY_RESULT_TYPES = set([ |
| "VkPhysicalDeviceFeatures", |
| "VkPhysicalDeviceLimits", |
| "VkFormatProperties", |
| "VkImageFormatProperties", |
| "VkPhysicalDeviceSparseProperties", |
| "VkQueueFamilyProperties", |
| "VkMemoryType", |
| "VkMemoryHeap", |
| ]) |
| COMPOSITE_TYPES = set([t.name for t in api.compositeTypes if not t.isAlias]) |
| |
| def isSimpleStruct (type): |
| def hasArrayMember (type): |
| for member in type.members: |
| if member.arraySize != '': |
| return True |
| return False |
| |
| def hasCompositeMember (type): |
| for member in type.members: |
| if member.getType() in COMPOSITE_TYPES: |
| return True |
| return False |
| |
| return type.typeClass == CompositeType.CLASS_STRUCT and \ |
| type.members[0].getType() != "VkStructureType" and \ |
| not type.name in QUERY_RESULT_TYPES and \ |
| not hasArrayMember(type) and \ |
| not hasCompositeMember(type) |
| |
| def gen (): |
| for type in api.compositeTypes: |
| if not isSimpleStruct(type) or type.isAlias: |
| continue |
| |
| yield "" |
| yield "inline %s make%s (%s)" % (type.name, type.name[2:], argListToStr(type.members)) |
| yield "{" |
| yield "\t%s res;" % type.name |
| for line in indentLines(["\tres.%s\t= %s;" % (m.name, m.name) for m in type.members]): |
| yield line |
| yield "\treturn res;" |
| yield "}" |
| |
| writeInlFile(filename, INL_HEADER, gen()) |
| |
| def writeSupportedExtenions(api, filename): |
| |
| def writeExtensionsForVersions(map): |
| result = [] |
| for version in map: |
| result.append(" if (coreVersion >= " + str(version) + ")") |
| result.append(" {") |
| for extension in map[version]: |
| result.append(' dst.push_back("' + extension.name + '");') |
| result.append(" }") |
| |
| return result |
| |
| instanceMap = {} |
| deviceMap = {} |
| versionSet = set() |
| |
| for ext in api.extensions: |
| if ext.versionInCore != None: |
| if ext.versionInCore[0] == 'INSTANCE': |
| list = instanceMap.get(Version(ext.versionInCore[1:])) |
| instanceMap[Version(ext.versionInCore[1:])] = list + [ext] if list else [ext] |
| else: |
| list = deviceMap.get(Version(ext.versionInCore[1:])) |
| deviceMap[Version(ext.versionInCore[1:])] = list + [ext] if list else [ext] |
| versionSet.add(Version(ext.versionInCore[1:])) |
| |
| lines = addVersionDefines(versionSet) + [ |
| "", |
| "void getCoreDeviceExtensionsImpl (deUint32 coreVersion, ::std::vector<const char*>&%s)" % (" dst" if len(deviceMap) != 0 else ""), |
| "{"] + writeExtensionsForVersions(deviceMap) + [ |
| "}", |
| "", |
| "void getCoreInstanceExtensionsImpl (deUint32 coreVersion, ::std::vector<const char*>&%s)" % (" dst" if len(instanceMap) != 0 else ""), |
| "{"] + writeExtensionsForVersions(instanceMap) + [ |
| "}", |
| ""] + removeVersionDefines(versionSet) |
| writeInlFile(filename, INL_HEADER, lines) |
| |
| def writeExtensionFunctions (api, filename): |
| |
| def isInstanceExtension (ext): |
| if ext.name and ext.functions: |
| if ext.functions[0].getType() == Function.TYPE_INSTANCE: |
| return True |
| else: |
| return False |
| |
| def isDeviceExtension (ext): |
| if ext.name and ext.functions: |
| if ext.functions[0].getType() == Function.TYPE_DEVICE: |
| return True |
| else: |
| return False |
| |
| def writeExtensionNameArrays (): |
| instanceExtensionNames = [] |
| deviceExtensionNames = [] |
| for ext in api.extensions: |
| if ext.name and isInstanceExtension(ext): |
| instanceExtensionNames += [ext.name] |
| elif ext.name and isDeviceExtension(ext): |
| deviceExtensionNames += [ext.name] |
| yield '::std::string instanceExtensionNames[] =\n{' |
| for instanceExtName in instanceExtensionNames: |
| if (instanceExtName == instanceExtensionNames[len(instanceExtensionNames) - 1]): |
| yield '\t"%s"' % instanceExtName |
| else: |
| yield '\t"%s",' % instanceExtName |
| yield '};\n' |
| yield '::std::string deviceExtensionNames[] =\n{' |
| for deviceExtName in deviceExtensionNames: |
| if (deviceExtName == deviceExtensionNames[len(deviceExtensionNames) - 1]): |
| yield '\t"%s"' % deviceExtName |
| else: |
| yield '\t"%s",' % deviceExtName |
| yield '};' |
| |
| def writeExtensionFunctions (functionType): |
| isFirstWrite = True |
| if functionType == Function.TYPE_INSTANCE: |
| yield 'void getInstanceExtensionFunctions (::std::string extName, ::std::vector<const char*>& functions)\n{' |
| elif functionType == Function.TYPE_DEVICE: |
| yield 'void getDeviceExtensionFunctions (::std::string extName, ::std::vector<const char*>& functions)\n{' |
| for ext in api.extensions: |
| funcNames = [] |
| if ext.name: |
| for func in ext.functions: |
| if func.getType() == functionType: |
| funcNames.append(func.name) |
| if (funcNames): |
| yield ('\tif (extName == "%s")' % ext.name) if isFirstWrite else ('\telse if (extName == "%s")' % ext.name) |
| if (len(funcNames) > 1): |
| yield "\t{" |
| for funcName in funcNames: |
| yield '\t\tfunctions.push_back("%s");' % funcName |
| if (len(funcNames) > 1): |
| yield '\t}' |
| isFirstWrite = False |
| if not isFirstWrite: |
| yield '\telse' |
| yield '\t\tDE_ASSERT("Extension name not found");\n}' |
| |
| lines = [''] |
| for line in writeExtensionFunctions(Function.TYPE_INSTANCE): |
| lines += [line] |
| lines += [''] |
| for line in writeExtensionFunctions(Function.TYPE_DEVICE): |
| lines += [line] |
| lines += [''] |
| for line in writeExtensionNameArrays(): |
| lines += [line] |
| |
| writeInlFile(filename, INL_HEADER, lines) |
| |
| def writeCoreFunctionalities(api, filename): |
| functionOriginValues = ["FUNCTIONORIGIN_PLATFORM", "FUNCTIONORIGIN_INSTANCE", "FUNCTIONORIGIN_DEVICE"] |
| |
| lines = addVersionDefines([Version((1, 0, 0)), Version((1, 1, 0))]) + [ |
| "", |
| 'enum FunctionOrigin', '{'] + [line for line in indentLines([ |
| '\t' + functionOriginValues[0] + '\t= 0,', |
| '\t' + functionOriginValues[1] + ',', |
| '\t' + functionOriginValues[2]])] + [ |
| "};", |
| "", |
| "typedef ::std::pair<const char*, FunctionOrigin> FunctionInfo;", |
| "typedef ::std::vector<FunctionInfo> FunctionInfosList;", |
| "typedef ::std::map<deUint32, FunctionInfosList> ApisMap;", |
| "", |
| "void initApisMap (ApisMap& apis)", |
| "{", |
| " apis.clear();", |
| " apis.insert(::std::pair<deUint32, FunctionInfosList>(" + str(Version((1, 0, 0))) + ", FunctionInfosList()));", |
| " apis.insert(::std::pair<deUint32, FunctionInfosList>(" + str(Version((1, 1, 0))) + ", FunctionInfosList()));", |
| ""] |
| |
| def list10Funcs (): |
| for fun in api.functions: |
| if fun.apiVersion == 'VK_VERSION_1_0': |
| insert = ' apis[' + str(Version((1, 0, 0))) + '].push_back(FunctionInfo("' + fun.name + '",\t' + functionOriginValues[fun.getType()] + '));' |
| yield insert |
| |
| def listAllFuncs (): |
| for fun in api.extensions[0].functions: |
| insert = ' apis[' + str(Version((1, 1, 0))) + '].push_back(FunctionInfo("' + fun.name + '",\t' + functionOriginValues[fun.getType()] + '));' |
| yield insert |
| |
| lines = lines + [line for line in indentLines(list10Funcs())] |
| lines.append("") |
| lines = lines + [line for line in indentLines(listAllFuncs())] |
| |
| lines.append("}") |
| lines.append("") |
| lines = lines + removeVersionDefines([Version((1, 0, 0)), Version((1, 1, 0))]) |
| |
| writeInlFile(filename, INL_HEADER, lines) |
| |
| if __name__ == "__main__": |
| src = readFile(VULKAN_H) |
| api = parseAPI(src) |
| |
| platformFuncs = [Function.TYPE_PLATFORM] |
| instanceFuncs = [Function.TYPE_INSTANCE] |
| deviceFuncs = [Function.TYPE_DEVICE] |
| |
| writeHandleType (api, os.path.join(VULKAN_DIR, "vkHandleType.inl")) |
| writeBasicTypes (api, os.path.join(VULKAN_DIR, "vkBasicTypes.inl")) |
| writeCompositeTypes (api, os.path.join(VULKAN_DIR, "vkStructTypes.inl")) |
| writeInterfaceDecl (api, os.path.join(VULKAN_DIR, "vkVirtualPlatformInterface.inl"), platformFuncs, False) |
| writeInterfaceDecl (api, os.path.join(VULKAN_DIR, "vkVirtualInstanceInterface.inl"), instanceFuncs, False) |
| writeInterfaceDecl (api, os.path.join(VULKAN_DIR, "vkVirtualDeviceInterface.inl"), deviceFuncs, False) |
| writeInterfaceDecl (api, os.path.join(VULKAN_DIR, "vkConcretePlatformInterface.inl"), platformFuncs, True) |
| writeInterfaceDecl (api, os.path.join(VULKAN_DIR, "vkConcreteInstanceInterface.inl"), instanceFuncs, True) |
| writeInterfaceDecl (api, os.path.join(VULKAN_DIR, "vkConcreteDeviceInterface.inl"), deviceFuncs, True) |
| writeFunctionPtrTypes (api, os.path.join(VULKAN_DIR, "vkFunctionPointerTypes.inl")) |
| writeFunctionPointers (api, os.path.join(VULKAN_DIR, "vkPlatformFunctionPointers.inl"), platformFuncs) |
| writeFunctionPointers (api, os.path.join(VULKAN_DIR, "vkInstanceFunctionPointers.inl"), instanceFuncs) |
| writeFunctionPointers (api, os.path.join(VULKAN_DIR, "vkDeviceFunctionPointers.inl"), deviceFuncs) |
| writeInitFunctionPointers (api, os.path.join(VULKAN_DIR, "vkInitPlatformFunctionPointers.inl"), platformFuncs, lambda f: f.name != "vkGetInstanceProcAddr") |
| writeInitFunctionPointers (api, os.path.join(VULKAN_DIR, "vkInitInstanceFunctionPointers.inl"), instanceFuncs) |
| writeInitFunctionPointers (api, os.path.join(VULKAN_DIR, "vkInitDeviceFunctionPointers.inl"), deviceFuncs) |
| writeFuncPtrInterfaceImpl (api, os.path.join(VULKAN_DIR, "vkPlatformDriverImpl.inl"), platformFuncs, "PlatformDriver") |
| writeFuncPtrInterfaceImpl (api, os.path.join(VULKAN_DIR, "vkInstanceDriverImpl.inl"), instanceFuncs, "InstanceDriver") |
| writeFuncPtrInterfaceImpl (api, os.path.join(VULKAN_DIR, "vkDeviceDriverImpl.inl"), deviceFuncs, "DeviceDriver") |
| writeStrUtilProto (api, os.path.join(VULKAN_DIR, "vkStrUtil.inl")) |
| writeStrUtilImpl (api, os.path.join(VULKAN_DIR, "vkStrUtilImpl.inl")) |
| writeRefUtilProto (api, os.path.join(VULKAN_DIR, "vkRefUtil.inl")) |
| writeRefUtilImpl (api, os.path.join(VULKAN_DIR, "vkRefUtilImpl.inl")) |
| writeStructTraitsImpl (api, os.path.join(VULKAN_DIR, "vkGetStructureTypeImpl.inl")) |
| writeNullDriverImpl (api, os.path.join(VULKAN_DIR, "vkNullDriverImpl.inl")) |
| writeTypeUtil (api, os.path.join(VULKAN_DIR, "vkTypeUtil.inl")) |
| writeSupportedExtenions (api, os.path.join(VULKAN_DIR, "vkSupportedExtensions.inl")) |
| writeCoreFunctionalities (api, os.path.join(VULKAN_DIR, "vkCoreFunctionalities.inl")) |
| writeExtensionFunctions (api, os.path.join(VULKAN_DIR, "vkExtensionFunctions.inl")) |