blob: e50b5dbd0794d534e7b008bec30c746e8956dccf [file] [log] [blame]
# -*- 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
import glob
import json
import argparse
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, execute
from khr_util.format import indentLines, writeInlFile
VULKAN_HEADERS_INCLUDE_DIR = os.path.join(os.path.dirname(__file__), "..", "..", "vulkan-docs", "src", "include")
SCRIPTS_SRC_DIR = os.path.join(os.path.dirname(__file__), "src")
DEFAULT_OUTPUT_DIR = { "" : os.path.join(os.path.dirname(__file__), "..", "framework", "vulkan", "generated", "vulkan"),
"SC" : os.path.join(os.path.dirname(__file__), "..", "framework", "vulkan", "generated", "vulkansc") }
INL_HEADER = """\
/* WARNING: This is auto-generated file. Do not modify, since changes will
* be lost! Modify the generating script instead.
* This file was generated by /scripts/gen_framework.py
*/\
"""
DEFINITIONS = [
("VK_MAX_PHYSICAL_DEVICE_NAME_SIZE", "size_t"),
("VK_MAX_EXTENSION_NAME_SIZE", "size_t"),
("VK_MAX_DRIVER_NAME_SIZE", "size_t"),
("VK_MAX_DRIVER_INFO_SIZE", "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", "uint32_t"),
("VK_SUBPASS_EXTERNAL", "uint32_t"),
("VK_QUEUE_FAMILY_IGNORED", "uint32_t"),
("VK_QUEUE_FAMILY_EXTERNAL", "uint32_t"),
("VK_REMAINING_MIP_LEVELS", "uint32_t"),
("VK_REMAINING_ARRAY_LAYERS", "uint32_t"),
("VK_WHOLE_SIZE", "vk::VkDeviceSize"),
("VK_TRUE", "vk::VkBool32"),
("VK_FALSE", "vk::VkBool32"),
]
PLATFORM_TYPES = [
# VK_KHR_xlib_surface
(["Display","*"], ["XlibDisplayPtr"], "void*"),
(["Window"], ["XlibWindow"], "uintptr_t",),
(["VisualID"], ["XlibVisualID"], "uint32_t"),
# VK_KHR_xcb_surface
(["xcb_connection_t", "*"], ["XcbConnectionPtr"], "void*"),
(["xcb_window_t"], ["XcbWindow"], "uintptr_t"),
(["xcb_visualid_t"], ["XcbVisualid"], "uint32_t"),
# 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*"),
(["HMONITOR"], ["Win32MonitorHandle"], "void*"),
(["LPCWSTR"], ["Win32LPCWSTR"], "const void*"),
# VK_EXT_acquire_xlib_display
(["RROutput"], ["RROutput"], "void*"),
(["zx_handle_t"], ["zx_handle_t"], "uint32_t"),
(["GgpFrameToken"], ["GgpFrameToken"], "int32_t"),
(["GgpStreamDescriptor"], ["GgpStreamDescriptor"], "int32_t"),
(["CAMetalLayer"], ["CAMetalLayer"], "void*"),
]
PLATFORM_TYPE_NAMESPACE = "pt"
TYPE_SUBSTITUTIONS = [
# Platform-specific
("DWORD", "uint32_t"),
("HANDLE*", PLATFORM_TYPE_NAMESPACE + "::" + "Win32Handle*"),
]
EXTENSION_POSTFIXES = ["KHR", "EXT", "NV", "NVX", "KHX", "NN", "MVK", "FUCHSIA", "GGP", "AMD", "QNX"]
EXTENSION_POSTFIXES_STANDARD = ["KHR", "EXT"]
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_SHADER_FLOAT_16_INT_8_FEATURES", "PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES")
name = name.replace("PHYSICAL_DEVICE_RGBA_10_X_6_FORMATS_FEATURES_EXT", "PHYSICAL_DEVICE_RGBA10X6_FORMATS_FEATURES_EXT")
name = name.replace("_PCIBUS_", "_PCI_BUS_")
name = name.replace("ASTCD", "ASTC_D")
name = name.replace("AABBNV", "AABB_NV")
name = name.replace("IMAGE_PIPE", "IMAGEPIPE")
name = name.replace("SMBUILTINS", "SM_BUILTINS")
name = name.replace("ASTCHDRFEATURES", "ASTC_HDR_FEATURES")
name = name.replace("UINT_8", "UINT8")
name = name.replace("VULKAN_11_FEATURES", "VULKAN_1_1_FEATURES")
name = name.replace("VULKAN_11_PROPERTIES", "VULKAN_1_1_PROPERTIES")
name = name.replace("VULKAN_12_FEATURES", "VULKAN_1_2_FEATURES")
name = name.replace("VULKAN_12_PROPERTIES", "VULKAN_1_2_PROPERTIES")
name = name.replace("VULKAN_13_FEATURES", "VULKAN_1_3_FEATURES")
name = name.replace("VULKAN_13_PROPERTIES", "VULKAN_1_3_PROPERTIES")
name = name.replace("VULKAN_SC_10_FEATURES", "VULKAN_SC_1_0_FEATURES")
name = name.replace("VULKAN_SC_10_PROPERTIES", "VULKAN_SC_1_0_PROPERTIES")
name = name.replace("INT_8_", "INT8_")
name = name.replace("AABBNV", "AABB_NV")
name = name.replace("_H_264_", "_H264_")
name = name.replace("_H_265_", "_H265_")
name = name.replace("RDMAFEATURES", "RDMA_FEATURES")
name = name.replace("RGBA_10_X_6", "RGBA10X6")
name = name.replace("2_D", "2D_")
name = name.replace("3_D", "3D_")
name = name.replace("IMAGE_PIPE", "IMAGEPIPE")
return prefix + name
def getApiVariantIndexByName(variantName):
apiVariant = {
None : 0,
'' : 0,
'SC' : 1
}
return apiVariant[variantName]
def getApiVariantNameByIndex(variantIndex):
apiVariant = {
None : '',
0 : '',
1 : 'SC'
}
return apiVariant[variantIndex]
class Version:
def __init__ (self, versionTuple):
self.api = versionTuple[0]
self.major = versionTuple[1]
self.minor = versionTuple[2]
self.patch = versionTuple[3]
def getInHex (self):
if self.patch == 0:
return "VK%s_API_VERSION_%d_%d" % (getApiVariantNameByIndex(self.api), self.major, self.minor)
return '0x%Xu' % (hash(self))
def isStandardVersion (self):
if self.patch != 0:
return False
if self.major != 1:
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.api << 29) | (self.major << 22) | (self.minor << 12) | self.patch
def __eq__ (self, other):
return self.api == other.api and 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, arraySizeOrFieldWidth):
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
if len(arraySizeOrFieldWidth) > 0 and arraySizeOrFieldWidth[0] == ':':
self.arraySize = ''
self.fieldWidth = arraySizeOrFieldWidth
else:
self.arraySize = arraySizeOrFieldWidth
self.fieldWidth = ''
def contains(self, big, small):
for i in range(len(big)-len(small)+1):
for j in range(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%s' % (self.getType(), separator, self.name, self.arraySize, self.fieldWidth)
def getAsStringForArgumentList (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, apiVersion = None):
self.typeClass = typeClass
self.name = name
self.members = members
self.alias = None
self.isAlias = False
self.apiVersion = apiVersion
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, typedefs, 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.typedefs = typedefs
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, versions, definitions, handles, enums, bitfields, bitfields64, compositeTypes, functions, extensions, additionalExtensionData):
self.versions = versions
self.definitions = definitions
self.handles = handles
self.enums = enums
self.bitfields = bitfields
self.bitfields64 = bitfields64
self.compositeTypes = compositeTypes
self.functions = functions # \note contains extension functions as well
self.extensions = extensions
self.additionalExtensionData = additionalExtensionData # \note contains mandatory features and information about promotion
def readFile (filename):
with open(filename, 'rt') as f:
return f.read()
IDENT_PTRN = r'[a-zA-Z_][a-zA-Z0-9_]*'
WIDTH_PTRN = r'[:0-9]*'
TYPE_PTRN = r'[a-zA-Z_][a-zA-Z0-9_ \t*&]*'
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,\n}]+)\s*[,\n}]'
return Enum(name, re.findall(keyValuePtrn, src))
# \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*:\s*[0-9]+)*)\s*;'
matches = re.findall(typeNamePtrn, src)
members = [Variable(t.strip(), n.strip(), a.replace(' ', '')) 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 parseCompositeTypesByVersion (src, versionsData):
# find occurence of extension is a place where
# we cant assign apiVersion to found structures
extPtrn = r'#define\s+[A-Z0-9_]+_EXTENSION_NAME\s+"([^"]+)"'
versionEnd = re.search(extPtrn, src)
versions = [Version((v[2], v[3], v[4], 0)) for v in versionsData]
versions.append(None)
# construct list of locations where version definitions start, and add the end of the file to it
sectionLocations = [versionDef[1] for versionDef in versionsData]
sectionLocations.append(versionEnd.start())
sectionLocations.append(len(src))
# construct function declaration pattern
ptrn = r'typedef (struct|union)(\s*' + IDENT_PTRN + r')?\s*{([^}]*)}\s*(' + IDENT_PTRN + r')\s*;'
regPtrn = re.compile(ptrn)
types = []
typeMap = { 'struct': CompositeType.CLASS_STRUCT, 'union': CompositeType.CLASS_UNION }
# iterate over all versions and find all structure definitions
for index, v in enumerate(versions):
matches = regPtrn.findall(src, sectionLocations[index], sectionLocations[index+1])
for type, structname, contents, typename in matches:
compositeType = parseCompositeType(typeMap[type], typename, contents)
compositeType.apiVersion = v
types.append(compositeType)
return types
def parseVersions (src):
# returns list of tuples each with four items:
# 1. string with version token (without ' 1' at the end)
# 2. starting point off version specific definitions in vulkan.h.in
# 3. major version number
# 4. minor version number
return [(m.group()[:-2], m.start(), getApiVariantIndexByName(m.group(1)), int(m.group(2)), int(m.group(3))) for m in re.finditer('VK(SC)?_VERSION_([1-9])_([0-9]) 1', src)]
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 populateExtensionAliases(allObjects, extensionObjects):
for object in extensionObjects:
withoutPostfix = removeTypeExtPostfix(object.name)
if withoutPostfix != None and withoutPostfix in allObjects:
# max 1 alias is assumed by functions in this file
assert allObjects[withoutPostfix].alias == None
allObjects[withoutPostfix].alias = object
object.isAlias = True
for object in extensionObjects:
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, versions):
# construct list of locations where version definitions start, and add the end of the file to it
sectionLocations = [versionDef[1] for versionDef in versions]
sectionLocations.append(len(src))
# construct function declaration pattern
ptrn = r'VKAPI_ATTR\s+(' + TYPE_PTRN + ')\s+VKAPI_CALL\s+(' + IDENT_PTRN + r')\s*\(([^)]*)\)\s*;'
regPtrn = re.compile(ptrn)
functions = []
# iterate over all versions and find all function definitions
for index, v in enumerate(versions):
matches = regPtrn.findall(src, sectionLocations[index], sectionLocations[index+1])
for returnType, name, argList in matches:
functions.append(Function(name.strip(), returnType.strip(), parseArgList(argList), v[0]))
return functions
def splitByExtension (src):
ptrn = r'#define\s+[A-Z0-9_]+_EXTENSION_NAME\s+"([^"]+)"'
# Construct long pattern that will be used to split whole source by extensions
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, following tuples contain extension name and all its definitions
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
extNameUpper = extensionName.upper()
extNameUpper = extNameUpper.replace("VK_KHR_SYNCHRONIZATION2", "VK_KHR_SYNCHRONIZATION_2")
extNameUpper = extNameUpper.replace("VK_INTEL_SHADER_INTEGER_FUNCTIONS2", "VK_INTEL_SHADER_INTEGER_FUNCTIONS_2")
extNameUpper = extNameUpper.replace("VK_EXT_ROBUSTNESS2", "VK_EXT_ROBUSTNESS_2")
extNameUpper = extNameUpper.replace("VK_EXT_FRAGMENT_DENSITY_MAP2", "VK_EXT_FRAGMENT_DENSITY_MAP_2")
extNameUpper = extNameUpper.replace("VK_EXT_SHADER_ATOMIC_FLOAT2", "VK_EXT_SHADER_ATOMIC_FLOAT_2")
extNameUpper = extNameUpper.replace("VK_AMD_SHADER_CORE_PROPERTIES2", "VK_AMD_SHADER_CORE_PROPERTIES_2")
extNameUpper = extNameUpper.replace("VK_EXT_EXTENDED_DYNAMIC_STATE2", "VK_EXT_EXTENDED_DYNAMIC_STATE_2")
# SPEC_VERSION enums
if definition[0].startswith(extNameUpper) and definition[1].isdigit():
return False
if definition[0].startswith(extNameUpper):
return True
if definition[0].endswith("_H_"):
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 parseTypedefs (src):
ptrn = r'typedef\s+([^\s]+)\s+([^\r\n]+);'
matches = re.findall(ptrn, src)
return [Definition(None, match[0], match[1]) for match in matches]
def parseExtensions (src, versions, allFunctions, allCompositeTypes, allEnums, allBitfields, allHandles, allDefinitions, additionalExtensionData):
# note registeredExtensionDict is also executed for vulkan 1.0 source for which extension name is None
registeredExtensionDict = {None: None}
for extensionName, data in additionalExtensionData:
# make sure that this extension was registered
if 'register_extension' not in data.keys():
continue
# save array containing 'device' or 'instance' string followed by the optional vulkan version in which this extension is core;
# note that register_extension section is also required for partialy promoted extensions like VK_EXT_extended_dynamic_state2
# but those extensions should not fill 'core' tag
registeredExtensionDict[extensionName] = [ data['register_extension']['type'] ]
match = re.match("(\d).(\d).(\d).(\d)", data['register_extension']['core'])
if match != None:
registeredExtensionDict[extensionName].extend( [ int(match.group(1)), int(match.group(2)), int(match.group(3)), int(match.group(4)) ] )
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("uint32_t", v.getInHex(), parsePreprocDefinedValueOptional(extensionSrc, v.getInHex())) for v in versions]
definitions.extend([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 = parse32bitBitfieldNames(extensionSrc)
typedefs = parseTypedefs(extensionSrc)
enumBitfieldNames = [getBitEnumNameForBitfield(name) for name in bitfieldNames]
enums = [enum for enum in rawEnums if enum.name not in enumBitfieldNames]
extCoreVersion = None
extData = registeredExtensionDict.get(extensionName, None)
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]
if extData != None:
populateExtensionAliases(functionsByName, extFunctions)
populateExtensionAliases(handlesByName, extHandles)
populateExtensionAliases(enumsByName, extEnums)
populateExtensionAliases(bitfieldsByName, extBitfields)
populateExtensionAliases(compositeTypesByName, extCompositeTypes)
if len(extData) > 1:
extCoreVersion = extData
extensions.append(Extension(extensionName, extHandles, extEnums, extBitfields, extCompositeTypes, extFunctions, extDefinitions, additionalDefinitions, typedefs, extCoreVersion))
return extensions
def parse32bitBitfieldNames (src):
ptrn = r'typedef\s+VkFlags\s(' + IDENT_PTRN + r')\s*;'
matches = re.findall(ptrn, src)
return matches
def parse64bitBitfieldNames (src):
ptrn = r'typedef\s+VkFlags64\s(' + IDENT_PTRN + r')\s*;'
matches = re.findall(ptrn, src)
return matches
def parse64bitBitfieldValues (src, bitfieldNamesList):
bitfields64 = []
for bitfieldName in bitfieldNamesList:
ptrn = r'static const ' + bitfieldName + r'\s*(' + IDENT_PTRN + r')\s*=\s*([a-zA-Z0-9_]+)\s*;'
matches = re.findall(ptrn, src)
bitfields64.append(Bitfield(bitfieldName, matches))
return bitfields64
def parseAPI (src):
versionsData = parseVersions(src)
versions = [Version((v[2], v[3], v[4], 0)) for v in versionsData]
definitions = [Definition("uint32_t", v.getInHex(), parsePreprocDefinedValue(src, v.getInHex())) for v in versions] +\
[Definition(type, name, parsePreprocDefinedValue(src, name)) for name, type in DEFINITIONS]
handles = parseHandles(src)
rawEnums = parseEnums(src)
bitfieldNames = parse32bitBitfieldNames(src)
bitfieldEnums = set([getBitEnumNameForBitfield(n) for n in bitfieldNames if getBitEnumNameForBitfield(n) in [enum.name for enum in rawEnums]])
bitfield64Names = parse64bitBitfieldNames(src)
bitfields64 = parse64bitBitfieldValues(src, bitfield64Names)
enums = []
bitfields = []
compositeTypes = parseCompositeTypesByVersion(src, versionsData)
allFunctions = parseFunctionsByVersion(src, versionsData)
additionalExtensionData = {}
# read all files from extensions directory
for fileName in glob.glob(os.path.join(SCRIPTS_SRC_DIR, "extensions", "*.json")):
extensionName = os.path.basename(fileName)[:-5]
fileContent = readFile(fileName)
try:
additionalExtensionData[extensionName] = json.loads(fileContent)
except ValueError as err:
print("Error in %s: %s" % (os.path.basename(fileName), str(err)))
sys.exit(-1)
additionalExtensionData = sorted(additionalExtensionData.items(), key=lambda e: e[0])
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, []))
extensions = parseExtensions(src, versions, allFunctions, compositeTypes, enums, bitfields, handles, definitions, additionalExtensionData)
# Populate alias fields
populateAliasesWithTypedefs(compositeTypes, src)
populateAliasesWithTypedefs(enums, src)
populateAliasesWithTypedefs(bitfields, src)
populateAliasesWithTypedefs(bitfields64, src)
populateAliasesWithTypedefs(handles, src)
for enum in enums:
removeAliasedValues(enum)
# Make generator to create Deleter<VkAccelerationStructureNV>
for f in allFunctions:
if (f.name == 'vkDestroyAccelerationStructureNV'):
f.arguments[1].type[0] = 'VkAccelerationStructureNV'
# Dealias handles VkAccelerationStructureNV and VkAccelerationStructureKHR
for handle in handles:
if handle.name == 'VkAccelerationStructureKHR':
handle.alias = None
if handle.name == 'VkAccelerationStructureNV':
handle.isAlias = False
return API(
versions = versions,
definitions = definitions,
handles = handles,
enums = enums,
bitfields = bitfields,
bitfields64 = bitfields64,
compositeTypes = compositeTypes,
functions = allFunctions,
extensions = extensions,
additionalExtensionData = additionalExtensionData)
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
maxIntCount = 0
for name, value in enum.values:
if value[:2] != "VK":
intValue = parseInt(value)
if intValue != curIndex:
# enum is linear when all items are in order
if intValue != 0x7FFFFFFF:
return False
# count number of items with 0x7FFFFFFF value;
# enum containing single 0x7FFFFFFF item are also
# considered as linear (this is usualy *_MAX_ENUM item)
maxIntCount += 1
# enums containing more then one 0x7FFFFFFF value
# are not considered as linear (vulkan video enums)
if maxIntCount > 1:
return False
curIndex += 1
return True
def genEnumSrc (enum):
yield "enum %s" % enum.name
yield "{"
lines = []
if areEnumValuesLinear(enum):
hasMaxItem = parseInt(enum.values[-1][1]) == 0x7FFFFFFF
values = enum.values[:-1] if hasMaxItem else enum.values
lastItem = "\t%s_LAST," % getEnumValuePrefix(enum)
# linear values first, followed by *_LAST
lines += ["\t%s\t= %s," % v for v in values if v[1][:2] != "VK"]
lines.append(lastItem)
# equivalence enums and *_MAX_ENUM
lines += ["\t%s\t= %s," % v for v in values if v[1][:2] == "VK"]
if hasMaxItem:
lines.append("\t%s\t= %s," % enum.values[-1])
else:
lines += ["\t%s\t= %s," % v for v in enum.values]
for line in indentLines(lines):
yield line
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 uint32_t %s;" % bitfield.name
def genBitfield64Src (bitfield64):
yield "typedef uint64_t %s;" % bitfield64.name
if len(bitfield64.values) > 0:
ptrn = "static const " + bitfield64.name + " %s\t= %s;"
for line in indentLines([ptrn % v for v in bitfield64.values]):
yield line
yield ""
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 stripTrailingComment(str):
index = str.find("//")
if index == -1:
return str
return str[:index]
def genDefinitionsSrc (definitions):
for line in ["#define %s\t(static_cast<%s>\t(%s))" % (definition.name, definition.type, stripTrailingComment(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 genMaxFrameworkVersion (definitions):
maxApiVersionMajor = 1
maxApiVersionMinor = 0
for definition in definitions:
match = re.match("VK_API_VERSION_(\d+)_(\d+)", definition.name)
if match:
apiVersionMajor = int(match.group(1))
apiVersionMinor = int(match.group(2))
if apiVersionMajor > maxApiVersionMajor:
maxApiVersionMajor = apiVersionMajor
maxApiVersionMinor = apiVersionMinor
elif apiVersionMajor == maxApiVersionMajor and apiVersionMinor > maxApiVersionMinor:
maxApiVersionMinor = apiVersionMinor
yield "#define VK_API_MAX_FRAMEWORK_VERSION\tVK_API_VERSION_%d_%d" % (maxApiVersionMajor, maxApiVersionMinor)
def genMaxFrameworkVersionSC (definitions):
maxApiVersionMajor = 1
maxApiVersionMinor = 0
for definition in definitions:
match = re.match("VKSC_API_VERSION_(\d+)_(\d+)", definition.name)
if match:
apiVersionMajor = int(match.group(1))
apiVersionMinor = int(match.group(2))
if apiVersionMajor > maxApiVersionMajor:
maxApiVersionMajor = apiVersionMajor
maxApiVersionMinor = apiVersionMinor
elif apiVersionMajor == maxApiVersionMajor and apiVersionMinor > maxApiVersionMinor:
maxApiVersionMinor = apiVersionMinor
yield "#define VKSC_API_MAX_FRAMEWORK_VERSION\tVKSC_API_VERSION_%d_%d" % (maxApiVersionMajor, maxApiVersionMinor)
def writeBasicTypes (apiName, api, filename):
def gen ():
definitionsCore, definitionDuplicates = splitUniqueAndDuplicatedEntries(api.definitions)
if apiName == '':
for line in indentLines(chain(genDefinitionsSrc(definitionsCore), genMaxFrameworkVersion(definitionsCore), genDefinitionsAliasSrc(definitionDuplicates))):
yield line
yield ""
elif apiName == 'SC':
for line in indentLines(chain(genDefinitionsSrc(definitionsCore), genMaxFrameworkVersion(definitionsCore), genMaxFrameworkVersionSC(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
else:
for enum2 in api.enums:
if enum2.alias == enum:
yield "typedef %s %s;" % (enum2.name, enum.name)
yield ""
for bitfield in api.bitfields:
if not bitfield.isAlias:
for line in genBitfieldSrc(bitfield):
yield line
else:
for bitfield2 in api.bitfields:
if bitfield2.alias == bitfield:
yield "typedef %s %s;" % (bitfield2.name, bitfield.name)
yield ""
for bitfield in api.bitfields64:
if not bitfield.isAlias:
for line in genBitfield64Src(bitfield):
yield line
else:
for bitfield2 in api.bitfields64:
if bitfield2.alias == bitfield:
yield "typedef %s %s;" % (bitfield2.name, bitfield.name)
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
else:
for type2 in api.compositeTypes:
if type2.alias == type:
yield "typedef %s %s;" % (type2.name, type.name)
yield ""
writeInlFile(filename, INL_HEADER, gen())
def argListToStr (args):
return ", ".join(v.getAsStringForArgumentList(' ') 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 writeFuncPtrInterfaceSCImpl (api, filename, functionTypes, className):
normFuncs = {
"createGraphicsPipelines" : "\t\treturn createGraphicsPipelinesHandlerNorm(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);",
"createComputePipelines" : "\t\treturn createComputePipelinesHandlerNorm(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);",
"createSampler" : "\t\treturn createSamplerHandlerNorm(device, pCreateInfo, pAllocator, pSampler);",
"createSamplerYcbcrConversion" : "\t\treturn createSamplerYcbcrConversionHandlerNorm(device, pCreateInfo, pAllocator, pYcbcrConversion);",
"createDescriptorSetLayout" : "\t\treturn createDescriptorSetLayoutHandlerNorm(device, pCreateInfo, pAllocator, pSetLayout);",
"createPipelineLayout" : "\t\treturn createPipelineLayoutHandlerNorm(device, pCreateInfo, pAllocator, pPipelineLayout);",
"createRenderPass" : "\t\treturn createRenderPassHandlerNorm(device, pCreateInfo, pAllocator, pRenderPass);",
"createRenderPass2" : "\t\treturn createRenderPass2HandlerNorm(device, pCreateInfo, pAllocator, pRenderPass);",
"createCommandPool" : "\t\treturn createCommandPoolHandlerNorm(device, pCreateInfo, pAllocator, pCommandPool);",
"resetCommandPool" : "\t\treturn resetCommandPoolHandlerNorm(device, commandPool, flags);",
"createFramebuffer" : "\t\treturn createFramebufferHandlerNorm(device, pCreateInfo, pAllocator, pFramebuffer);",
}
statFuncs = {
"destroyDevice" : "\t\tdestroyDeviceHandler(device, pAllocator);",
"createDescriptorSetLayout" : "\t\tcreateDescriptorSetLayoutHandlerStat(device, pCreateInfo, pAllocator, pSetLayout);",
"destroyDescriptorSetLayout" : "\t\tdestroyDescriptorSetLayoutHandler(device, descriptorSetLayout, pAllocator);",
"createImageView" : "\t\tcreateImageViewHandler(device, pCreateInfo, pAllocator, pView);",
"destroyImageView" : "\t\tdestroyImageViewHandler(device, imageView, pAllocator);",
"createSemaphore" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_CREATE(semaphoreRequestCount,1);\n\t\t*pSemaphore = Handle<HANDLE_TYPE_SEMAPHORE>(m_resourceInterface->incResourceCounter());\n\t}",
"destroySemaphore" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_DESTROY_IF(semaphore,semaphoreRequestCount,1);\n\t}",
"createFence" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_CREATE(fenceRequestCount,1);\n\t\t*pFence = Handle<HANDLE_TYPE_FENCE>(m_resourceInterface->incResourceCounter());\n\t}",
"destroyFence" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_DESTROY_IF(fence,fenceRequestCount,1);\n\t}",
"allocateMemory" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_CREATE(deviceMemoryRequestCount,1);\n\t\t*pMemory = Handle<HANDLE_TYPE_DEVICE_MEMORY>(m_resourceInterface->incResourceCounter());\n\t}",
"createBuffer" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_CREATE(bufferRequestCount,1);\n\t\t*pBuffer = Handle<HANDLE_TYPE_BUFFER>(m_resourceInterface->incResourceCounter());\n\t}",
"destroyBuffer" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_DESTROY_IF(buffer,bufferRequestCount,1);\n\t}",
"createImage" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_CREATE(imageRequestCount,1);\n\t\t*pImage = Handle<HANDLE_TYPE_IMAGE>(m_resourceInterface->incResourceCounter());\n\t}",
"destroyImage" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_DESTROY_IF(image,imageRequestCount,1);\n\t}",
"createEvent" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_CREATE(eventRequestCount,1);\n\t\t*pEvent = Handle<HANDLE_TYPE_EVENT>(m_resourceInterface->incResourceCounter());\n\t}",
"destroyEvent" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_DESTROY_IF(event,eventRequestCount,1);\n\t}",
"createQueryPool" : "\t\tcreateQueryPoolHandler(device, pCreateInfo, pAllocator, pQueryPool);",
"createBufferView" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_CREATE(bufferViewRequestCount,1);\n\t\t*pView = Handle<HANDLE_TYPE_BUFFER_VIEW>(m_resourceInterface->incResourceCounter());\n\t}",
"destroyBufferView" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_DESTROY_IF(bufferView,bufferViewRequestCount,1);\n\t}",
"createPipelineLayout" : "\t\tcreatePipelineLayoutHandlerStat(device, pCreateInfo, pAllocator, pPipelineLayout);",
"destroyPipelineLayout" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_DESTROY_IF(pipelineLayout,pipelineLayoutRequestCount,1);\n\t}",
"createRenderPass" : "\t\tcreateRenderPassHandlerStat(device, pCreateInfo, pAllocator, pRenderPass);",
"createRenderPass2" : "\t\tcreateRenderPass2HandlerStat(device, pCreateInfo, pAllocator, pRenderPass);",
"destroyRenderPass" : "\t\tdestroyRenderPassHandler(device, renderPass, pAllocator);",
"createGraphicsPipelines" : "\t\tcreateGraphicsPipelinesHandlerStat(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);",
"createComputePipelines" : "\t\tcreateComputePipelinesHandlerStat(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);",
"destroyPipeline" : "\t\tdestroyPipelineHandler(device, pipeline, pAllocator);",
"createSampler" : "\t\tcreateSamplerHandlerStat(device, pCreateInfo, pAllocator, pSampler);",
"destroySampler" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_DESTROY_IF(sampler,samplerRequestCount,1);\n\t}",
"createDescriptorPool" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_CREATE(descriptorPoolRequestCount,1);\n\t\t*pDescriptorPool = Handle<HANDLE_TYPE_DESCRIPTOR_POOL>(m_resourceInterface->incResourceCounter());\n\t}",
"resetDescriptorPool" : "\t\tresetDescriptorPoolHandlerStat(device, descriptorPool, flags);",
"allocateDescriptorSets" : "\t\tallocateDescriptorSetsHandlerStat(device, pAllocateInfo, pDescriptorSets);",
"freeDescriptorSets" : "\t\tfreeDescriptorSetsHandlerStat(device, descriptorPool, descriptorSetCount, pDescriptorSets);",
"createFramebuffer" : "\t\tcreateFramebufferHandlerStat(device, pCreateInfo, pAllocator, pFramebuffer);",
"destroyFramebuffer" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_DESTROY_IF(framebuffer,framebufferRequestCount,1);\n\t}",
"createCommandPool" : "\t\tcreateCommandPoolHandlerStat(device, pCreateInfo, pAllocator, pCommandPool);",
"resetCommandPool" : "\t\tresetCommandPoolHandlerStat(device, commandPool, flags);",
"allocateCommandBuffers" : "\t\tallocateCommandBuffersHandler(device, pAllocateInfo, pCommandBuffers);",
"freeCommandBuffers" : "\t\tfreeCommandBuffersHandler(device, commandPool, commandBufferCount, pCommandBuffers);",
"createSamplerYcbcrConversion" : "\t\tcreateSamplerYcbcrConversionHandlerStat(device, pCreateInfo, pAllocator, pYcbcrConversion);",
"destroySamplerYcbcrConversion" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_DESTROY_IF(ycbcrConversion,samplerYcbcrConversionRequestCount,1);\n\t}",
"getDescriptorSetLayoutSupport" : "\t\tgetDescriptorSetLayoutSupportHandler(device, pCreateInfo, pSupport);",
# "" : "surfaceRequestCount",
# "" : "swapchainRequestCount",
# "" : "displayModeRequestCount"
"mapMemory" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tif(m_falseMemory.size() < (static_cast<std::size_t>(offset+size)))\n\t\t\tm_falseMemory.resize(static_cast<std::size_t>(offset+size));\n\t\t*ppData = (void*)m_falseMemory.data();\n\t}",
"getBufferMemoryRequirements" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tpMemoryRequirements->size = 1048576U;\n\t\tpMemoryRequirements->alignment = 1U;\n\t\tpMemoryRequirements->memoryTypeBits = ~0U;\n\t}",
"getImageMemoryRequirements" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tpMemoryRequirements->size = 1048576U;\n\t\tpMemoryRequirements->alignment = 1U;\n\t\tpMemoryRequirements->memoryTypeBits = ~0U;\n\t}",
"getBufferMemoryRequirements2" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tpMemoryRequirements->memoryRequirements.size = 1048576U;\n\t\tpMemoryRequirements->memoryRequirements.alignment = 1U;\n\t\tpMemoryRequirements->memoryRequirements.memoryTypeBits = ~0U;\n\t}",
"getImageMemoryRequirements2" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tpMemoryRequirements->memoryRequirements.size = 1048576U;\n\t\tpMemoryRequirements->memoryRequirements.alignment = 1U;\n\t\tpMemoryRequirements->memoryRequirements.memoryTypeBits = ~0U;\n\t}",
"getImageSubresourceLayout" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tpLayout->offset = 0U;\n\t\tpLayout->size = 1048576U;\n\t\tpLayout->rowPitch = 0U;\n\t\tpLayout->arrayPitch = 0U;\n\t\tpLayout->depthPitch = 0U;\n\t}",
"createPipelineCache" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_CREATE(pipelineCacheRequestCount,1);\n\t\t*pPipelineCache = Handle<HANDLE_TYPE_PIPELINE_CACHE>(m_resourceInterface->incResourceCounter());\n\t}",
"destroyPipelineCache" : "\t{\n\t\tDDSTAT_LOCK();\n\t\tDDSTAT_HANDLE_DESTROY_IF(pipelineCache,pipelineCacheRequestCount,1);\n\t}",
"cmdUpdateBuffer" : "\t\tincreaseCommandBufferSize(commandBuffer, dataSize);",
"getDeviceQueue" : "\t\tm_vk.getDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue);",
}
statReturns = {
"VkResult" : "return VK_SUCCESS;",
"VkDeviceAddress" : "return 0u;",
"uint64_t" : "return 0u;",
}
def makeFuncPtrInterfaceStatisticsImpl ():
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 ( getInterfaceName(function) in normFuncs ) or ( getInterfaceName(function) in statFuncs ):
yield "\tstd::lock_guard<std::mutex> lock(functionMutex);"
if getInterfaceName(function) != "getDeviceProcAddr" :
yield "\tif (m_normalMode)"
if getInterfaceName(function) in normFuncs :
yield "%s" % ( normFuncs[getInterfaceName(function)] )
else:
yield "\t\t%sm_vk.%s(%s);" % ("return " if function.returnType != "void" else "", getInterfaceName(function), ", ".join(a.name for a in function.arguments))
if getInterfaceName(function) in statFuncs :
yield "\telse"
yield "%s" % ( statFuncs[getInterfaceName(function)] )
elif getInterfaceName(function)[:3] == "cmd" :
yield "\telse"
yield "\t\tincreaseCommandBufferSize(commandBuffer, 0u);"
if function.returnType in statReturns:
yield "\t%s" % ( statReturns[function.returnType] )
yield "}"
writeInlFile(filename, INL_HEADER, makeFuncPtrInterfaceStatisticsImpl())
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 or bitfield.name=='VkBuildAccelerationStructureFlagsNV']):
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{"
enumValues = []
lastValue = 0x7FFFFFFF
for n, v in enum.values:
if (v[:2] != "VK") and (v != lastValue):
enumValues.append(f"\t\tcase {n}:\treturn \"{n}\";")
lastValue = v
enumValues.append("\t\tdefault:\treturn DE_NULL;")
for line in indentLines(enumValues):
yield line
yield "\t}"
yield "}"
for bitfield in api.bitfields:
if bitfield.isAlias:
if bitfield.name != 'VkBuildAccelerationStructureFlagsNV':
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.getType() == PLATFORM_TYPE_NAMESPACE + "::Win32LPCWSTR":
valFmt = "getWStr(value.%s)" % member.name
elif member.arraySize != '':
singleDimensional = not '][' in member.arraySize
if member.name in ["extensionName", "deviceName", "layerName", "description"]:
valFmt = "(const char*)value.%s" % member.name
elif singleDimensional and (member.getType() == 'char' or member.getType() == 'uint8_t'):
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())
def writeObjTypeImpl (api, filename):
def makeObjTypeImpl ():
yield "namespace vk"
yield "{"
yield "template<typename T> VkObjectType getObjectType (void);"
for line in indentLines(["template<> inline VkObjectType\tgetObjectType<%s>\t(void) { return %s;\t}" % (handle.name, prefixName("VK_OBJECT_TYPE_", handle.name)) for handle in api.handles if not handle.isAlias]):
yield line
yield "}"
writeInlFile(filename, INL_HEADER, makeObjTypeImpl())
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 and type.name != "VkBaseOutStructure" and type.name != "VkBaseInStructure":
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",
"vkCreateRayTracingPipelinesNV",
"vkCreateRayTracingPipelinesKHR",
"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",
"StdVideoH264SpsVuiFlags",
"StdVideoH264SpsFlags",
"StdVideoH264PpsFlags",
"StdVideoDecodeH264PictureInfoFlags",
"StdVideoDecodeH264ReferenceInfoFlags",
"StdVideoDecodeH264MvcElementFlags",
"StdVideoEncodeH264SliceHeaderFlags",
"StdVideoEncodeH264PictureInfoFlags",
"StdVideoEncodeH264RefMgmtFlags",
"StdVideoEncodeH264ReferenceInfoFlags",
"StdVideoH265HrdFlags",
"StdVideoH265VpsFlags",
"StdVideoH265SpsVuiFlags",
"StdVideoH265SpsFlags",
"StdVideoH265PpsFlags",
"StdVideoDecodeH265PictureInfoFlags",
"StdVideoDecodeH265ReferenceInfoFlags",
"StdVideoEncodeH265PictureInfoFlags",
"StdVideoEncodeH265SliceHeaderFlags",
"StdVideoEncodeH265ReferenceModificationFlags",
"StdVideoEncodeH265ReferenceInfoFlags",
"StdVideoEncodeH265SliceSegmentHeaderFlags",
])
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
name = type.name[2:] if type.name[:2].lower() == "vk" else type.name
yield ""
yield "inline %s make%s (%s)" % (type.name, name, 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 writeDriverIds(apiName, filename):
driverIdsString = []
driverIdsString.append("static const struct\n"
"{\n"
"\tstd::string driver;\n"
"\tuint32_t id;\n"
"} driverIds [] =\n"
"{")
vulkanHeaderFile = { "" : os.path.join(VULKAN_HEADERS_INCLUDE_DIR, "vulkan", "vulkan_core.h"),
"SC" : os.path.join(SCRIPTS_SRC_DIR, "vulkan_sc_core.h") }
vulkanCore = readFile(vulkanHeaderFile[apiName])
items = re.search(r'(?:typedef\s+enum\s+VkDriverId\s*{)((.*\n)*)(?:}\s*VkDriverId\s*;)', vulkanCore).group(1).split(',')
driverItems = dict()
for item in items:
item.strip()
splitted = item.split('=')
key = splitted[0].strip()
value_str = splitted[1].strip()
try: # is this previously defined value?
value = driverItems[value_str]
except:
value = value_str
value_str = ""
if value_str:
value_str = "\t// " + value_str
driverItems[key] = value
if not item == items[-1]:
driverIdsString.append("\t{\"" + key + "\"" + ", " + value + "}," + value_str)
else:
driverIdsString.append("\t{\"" + key + "\"" + ", " + value + "}" + value_str)
driverItems[key] = value
driverIdsString.append("};")
writeInlFile(filename, INL_HEADER, driverIdsString)
def writeSupportedExtensions(apiName, 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(" }")
if not map:
result.append(" DE_UNREF(coreVersion);")
return result
instanceMap = {}
deviceMap = {}
versionSet = set()
for ext in api.extensions:
if ext.versionInCore != None:
currVersion = Version(ext.versionInCore[1:])
# VulkanSC is based on Vulkan 1.2. Any Vulkan version greater than 1.2 should be excluded
if apiName=='SC' and currVersion.api==0 and currVersion.major==1 and currVersion.minor>2:
continue
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:]))
# add list of extensions missing in Vulkan SC specification
if apiName == 'SC':
for extensionName, data in api.additionalExtensionData:
# make sure that this extension was registered
if 'register_extension' not in data.keys():
continue
# save array containing 'device' or 'instance' string followed by the optional vulkan version in which this extension is core;
# note that register_extension section is also required for partialy promoted extensions like VK_EXT_extended_dynamic_state2
# but those extensions should not fill 'core' tag
match = re.match("(\d).(\d).(\d).(\d)", data['register_extension']['core'])
if match != None:
currVersion = Version([int(match.group(1)), int(match.group(2)), int(match.group(3)), int(match.group(4))])
ext = Extension(extensionName, 0, 0, 0, 0, 0, 0, 0, 0, 0)
if currVersion.api==0 and currVersion.major==1 and currVersion.minor>2:
continue
if data['register_extension']['type'] == 'instance':
list = instanceMap.get(currVersion)
instanceMap[currVersion] = list + [ext] if list else [ext]
else:
list = deviceMap.get(currVersion)
deviceMap[currVersion] = list + [ext] if list else [ext]
versionSet.add(currVersion)
lines = addVersionDefines(versionSet) + [
"",
"void getCoreDeviceExtensionsImpl (uint32_t coreVersion, ::std::vector<const char*>&%s)" % (" dst" if len(deviceMap) != 0 or apiName == 'SC' else ""),
"{"] + writeExtensionsForVersions(deviceMap) + [
"}",
"",
"void getCoreInstanceExtensionsImpl (uint32_t coreVersion, ::std::vector<const char*>&%s)" % (" dst" if len(instanceMap) != 0 or apiName == 'SC' 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
dg_list = [] # Device groups functions need special casing, as Vulkan 1.0 keeps them in VK_KHR_device_groups whereas 1.1 moved them into VK_KHR_swapchain
if functionType == Function.TYPE_INSTANCE:
yield 'void getInstanceExtensionFunctions (uint32_t apiVersion, ::std::string extName, ::std::vector<const char*>& functions)\n{'
dg_list = ["vkGetPhysicalDevicePresentRectanglesKHR"]
elif functionType == Function.TYPE_DEVICE:
yield 'void getDeviceExtensionFunctions (uint32_t apiVersion, ::std::string extName, ::std::vector<const char*>& functions)\n{'
dg_list = ["vkGetDeviceGroupPresentCapabilitiesKHR", "vkGetDeviceGroupSurfacePresentModesKHR", "vkAcquireNextImage2KHR"]
for ext in api.extensions:
funcNames = []
if ext.name:
for func in ext.functions:
if func.getType() == functionType:
# only add functions with same vendor as extension
# this is a workaroudn for entrypoints requiring more
# than one excetions and lack of the dependency in vulkan_core.h
vendor = ext.name.split('_')[1]
if func.name.endswith(vendor):
funcNames.append(func.name)
if ext.name:
yield '\tif (extName == "%s")' % ext.name
yield '\t{'
for funcName in funcNames:
if funcName in dg_list:
yield '\t\tif(apiVersion >= VK_API_VERSION_1_1) functions.push_back("%s");' % funcName
else:
yield '\t\tfunctions.push_back("%s");' % funcName
if ext.name == "VK_KHR_device_group":
for dg_func in dg_list:
yield '\t\tif(apiVersion < VK_API_VERSION_1_1) functions.push_back("%s");' % dg_func
yield '\t\treturn;'
yield '\t}'
isFirstWrite = False
if not isFirstWrite:
yield '\tDE_FATAL("Extension name not found");'
yield '}'
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(api.versions) + [
"",
'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<uint32_t, FunctionInfosList> ApisMap;",
"",
"void initApisMap (ApisMap& apis)",
"{",
" apis.clear();"] + [
" apis.insert(::std::pair<uint32_t, FunctionInfosList>(" + str(v) + ", FunctionInfosList()));" for v in api.versions] + [
""]
apiVersions = []
for index, v in enumerate(api.versions):
funcs = []
apiVersions.append("VK_VERSION_{0}_{1}".format(v.major, v.minor))
# iterate over all functions that are core in latest vulkan version
# note that first item in api.extension array are actually all definitions that are in vulkan.h.in before section with extensions
for fun in api.extensions[0].functions:
if fun.apiVersion in apiVersions:
funcs.append(' apis[' + str(v) + '].push_back(FunctionInfo("' + fun.name + '",\t' + functionOriginValues[fun.getType()] + '));')
lines = lines + [line for line in indentLines(funcs)] + [""]
lines = lines + ["}", ""] + removeVersionDefines(api.versions)
writeInlFile(filename, INL_HEADER, lines)
def camelToSnake(name):
name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
return re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()
def writeDeviceFeatures2(api, filename):
def structInAPI(name):
for c in api.compositeTypes:
if c.name == name:
return True
return False
# list of structures that should be tested with getPhysicalDeviceFeatures2
# this is not posible to determine from vulkan_core.h, if new feature structures
# are added they should be manualy added to this list
testedStructures = [
'VkPhysicalDevice4444FormatsFeaturesEXT',
'VkPhysicalDevice8BitStorageFeatures',
'VkPhysicalDevice16BitStorageFeatures',
'VkPhysicalDeviceAccelerationStructureFeaturesKHR',
'VkPhysicalDeviceASTCDecodeFeaturesEXT',
'VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT',
'VkPhysicalDeviceBufferDeviceAddressFeaturesEXT',
'VkPhysicalDeviceBufferDeviceAddressFeatures',
'VkPhysicalDeviceConditionalRenderingFeaturesEXT',
'VkPhysicalDeviceCustomBorderColorFeaturesEXT',
'VkPhysicalDeviceColorWriteEnableFeaturesEXT',
'VkPhysicalDeviceDescriptorIndexingFeatures',
'VkPhysicalDeviceDepthClipEnableFeaturesEXT',
'VkPhysicalDeviceDynamicRenderingFeatures',
'VkPhysicalDeviceExtendedDynamicStateFeaturesEXT',
'VkPhysicalDeviceExtendedDynamicState2FeaturesEXT',
'VkPhysicalDeviceFragmentDensityMapFeaturesEXT',
'VkPhysicalDeviceFragmentDensityMap2FeaturesEXT',
'VkPhysicalDeviceFragmentShadingRateFeaturesKHR',
'VkPhysicalDeviceGlobalPriorityQueryFeaturesKHR',
'VkPhysicalDeviceInlineUniformBlockFeatures',
'VkPhysicalDeviceIndexTypeUint8FeaturesEXT',
'VkPhysicalDeviceImagelessFramebufferFeatures',
'VkPhysicalDeviceImageRobustnessFeatures',
'VkPhysicalDeviceHostQueryResetFeatures',
'VkPhysicalDeviceLineRasterizationFeaturesEXT',
'VkPhysicalDeviceMaintenance4Features',
'VkPhysicalDeviceMultiviewFeatures',
'VkPhysicalDeviceMultiDrawFeaturesEXT',
'VkPhysicalDeviceMemoryPriorityFeaturesEXT',
'VkPhysicalDeviceDeviceMemoryReportFeaturesEXT',
'VkPhysicalDevicePerformanceQueryFeaturesKHR',
'VkPhysicalDevicePipelineCreationCacheControlFeatures',
'VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR',
'VkPhysicalDevicePresentIdFeaturesKHR',
'VkPhysicalDevicePresentWaitFeaturesKHR',
'VkPhysicalDeviceProtectedMemoryFeatures',
'VkPhysicalDeviceProvokingVertexFeaturesEXT',
'VkPhysicalDevicePrimitiveTopologyListRestartFeaturesEXT',
'VkPhysicalDevicePrivateDataFeatures',
'VkPhysicalDeviceRayTracingPipelineFeaturesKHR',
'VkPhysicalDeviceRayQueryFeaturesKHR',
'VkPhysicalDeviceRobustness2FeaturesEXT',
'VkPhysicalDeviceSamplerYcbcrConversionFeatures',
'VkPhysicalDeviceScalarBlockLayoutFeatures',
'VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures',
'VkPhysicalDeviceShaderAtomicInt64Features',
'VkPhysicalDeviceShaderAtomicFloatFeaturesEXT',
'VkPhysicalDeviceShaderAtomicFloat2FeaturesEXT',
'VkPhysicalDeviceShaderFloat16Int8Features',
'VkPhysicalDeviceShaderClockFeaturesKHR',
'VkPhysicalDeviceShaderDemoteToHelperInvocationFeatures',
'VkPhysicalDeviceShaderDrawParametersFeatures',
'VkPhysicalDeviceShaderIntegerDotProductFeatures',
'VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures',
'VkPhysicalDeviceShaderTerminateInvocationFeatures',
'VkPhysicalDeviceSubgroupSizeControlFeatures',
'VkPhysicalDeviceSynchronization2Features',
'VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT',
'VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT',
'VkPhysicalDeviceTextureCompressionASTCHDRFeatures',
'VkPhysicalDeviceTimelineSemaphoreFeatures',
'VkPhysicalDeviceTransformFeedbackFeaturesEXT',
'VkPhysicalDeviceUniformBufferStandardLayoutFeatures',
'VkPhysicalDeviceWorkgroupMemoryExplicitLayoutFeaturesKHR',
'VkPhysicalDeviceVariablePointersFeatures',
'VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT',
'VkPhysicalDeviceVertexInputDynamicStateFeaturesEXT',
'VkPhysicalDeviceVulkanMemoryModelFeaturesKHR',
'VkPhysicalDeviceYcbcrImageArraysFeaturesEXT',
'VkPhysicalDeviceYcbcr2Plane444FormatsFeaturesEXT',
'VkPhysicalDeviceZeroInitializeWorkgroupMemoryFeatures',
]
# helper class used to encapsulate all data needed during generation
class StructureDetail:
def __init__ (self, name):
nameResult = re.search('(.*)Features(.*)', name[len('VkPhysicalDevice'):])
nameSplitUp = ''
# generate structure type name from structure name
# note that sometimes digits are separated with '_':
# VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_2_FEATURES_EXT
# but mostly they are not:
# VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES
specialCaseDict = {
'FragmentDensityMap2' : ['FRAGMENT', 'DENSITY', 'MAP', '2'],
'Ycbcr2Plane444Formats' : ['YCBCR', '2', 'PLANE', '444', 'FORMATS'],
'ASTCDecode' : ['ASTC', 'DECODE'],
'4444Formats' : ['4444', 'FORMATS'],
'TextureCompressionASTCHDR' : ['TEXTURE', 'COMPRESSION', 'ASTC', 'HDR'],
'Synchronization2' : ['SYNCHRONIZATION', '2'],
'ShaderAtomicFloat2' : ['SHADER', 'ATOMIC', 'FLOAT', '2'],
'Robustness2' : ['ROBUSTNESS', '2'],
'Maintenance4' : ['MAINTENANCE', '4'],
'ExtendedDynamicState2' : ['EXTENDED', 'DYNAMIC', 'STATE', '2'],
}
nameSplitUp = specialCaseDict.get(nameResult.group(1))
if nameSplitUp == None:
nameSplit = re.findall(r'[1-9A-Z]+(?:[a-z1-9]+|[A-Z]*(?=[A-Z]|$))', nameResult.group(1))
nameSplitUp = map(str.upper, nameSplit)
nameSplitUp = list(nameSplitUp) + ['FEATURES']
# check if there is extension suffix
if (len(nameResult.group(2)) != 0):
nameSplitUp.append(nameResult.group(2))
self.name = name
self.sType = 'VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_' + '_'.join(nameSplitUp)
self.instanceName = 'd' + name[11:]
self.flagName = 'is' + name[16:]
self.extension = None
self.api = None
self.major = None
self.minor = None
self.members = []
# helper extension class used in algorith below
class StructureFoundContinueToNextOne(Exception):
pass
existingStructures = list(filter(structInAPI, testedStructures)) # remove features not found in API ( important for Vulkan SC )
testedStructureDetail = [StructureDetail(struct) for struct in existingStructures]
# iterate over all searched structures and find extensions that enable them
for structureDetail in testedStructureDetail:
try:
# iterate over all extensions
for extension in api.extensions[1:]:
# check composite types and typedefs in case extension is part of core
for structureList in [extension.compositeTypes, extension.typedefs]:
# iterate over all structures added by extension
for extensionStructure in structureList:
# compare checked structure name to name of structure from extension
if structureDetail.name == extensionStructure.name:
structureDetail.extension = extension.name
if extension.versionInCore is not None:
structureDetail.api = extension.versionInCore[1]
structureDetail.major = extension.versionInCore[2]
structureDetail.minor = extension.versionInCore[3]
raise StructureFoundContinueToNextOne
except StructureFoundContinueToNextOne:
continue
for structureDetail in testedStructureDetail:
for compositeType in api.compositeTypes:
if structureDetail.name != compositeType.name:
continue
structureMembers = compositeType.members[2:]
structureDetail.members = [m.name for m in structureMembers]
if structureDetail.major is not None:
break
# if structure was not added with extension then check if
# it was added directly with one of vulkan versions
apiVersion = compositeType.apiVersion
if apiVersion is None:
continue
structureDetail.api = apiVersion.api
structureDetail.major = apiVersion.major
structureDetail.minor = apiVersion.minor
break
# generate file content
structureDefinitions = []
featureEnabledFlags = []
clearStructures = []
structureChain = []
logStructures = []
verifyStructures = []
for index, structureDetail in enumerate(testedStructureDetail):
# create two instances of each structure
nameSpacing = '\t'
structureDefinitions.append(structureDetail.name + nameSpacing + structureDetail.instanceName + '[count];')
# create flags that check if proper extension or vulkan version is available
condition = ''
extension = structureDetail.extension
major = structureDetail.major
if extension is not None:
condition = ' checkExtension(properties, "' + extension + '")'
if major is not None:
if condition != '':
condition += ' || '
else:
condition += ' '
condition += 'context.contextSupports(vk::ApiVersion(' + str(structureDetail.api) + ', ' + str(major) + ', ' + str(structureDetail.minor) + ', 0))'
if condition == '':
condition = 'true'
condition += ';'
nameSpacing = '\t' * int((len(structureDetail.name) - 4) / 4)
featureEnabledFlags.append('const bool' + nameSpacing + structureDetail.flagName + ' =' + condition)
# clear memory of each structure
clearStructures.append('\tdeMemset(&' + structureDetail.instanceName + '[ndx], 0xFF * ndx, sizeof(' + structureDetail.name + '));')
# construct structure chain
nextInstanceName = 'DE_NULL';
if index < len(testedStructureDetail)-1:
nextInstanceName = '&' + testedStructureDetail[index+1].instanceName + '[ndx]'
structureChain.append([
'\t\t' + structureDetail.instanceName + '[ndx].sType = ' + structureDetail.flagName + ' ? ' + structureDetail.sType + ' : VK_STRUCTURE_TYPE_MAX_ENUM;',
'\t\t' + structureDetail.instanceName + '[ndx].pNext = DE_NULL;'])
# construct log section
logStructures.append([
'\tif (' + structureDetail.flagName + ')',
'\t\tlog << TestLog::Message << ' + structureDetail.instanceName + '[0] << TestLog::EndMessage;'
])
#construct verification section
verifyStructure = []
verifyStructure.append('\tif (' + structureDetail.flagName + ' &&')
for index, m in enumerate(structureDetail.members):
prefix = '\t\t(' if index == 0 else '\t\t '
postfix = '))' if index == len(structureDetail.members)-1 else ' ||'
verifyStructure.append(prefix + structureDetail.instanceName + '[0].' + m + ' != ' + structureDetail.instanceName + '[1].' + m + postfix)
if len(structureDetail.members) == 0:
verifyStructure.append('\t\tfalse)')
verifyStructure.append('\t{\n\t\tTCU_FAIL("Mismatch between ' + structureDetail.name + '");\n\t}')
verifyStructures.append(verifyStructure)
# construct file content
stream = []
# individual test functions
for n, x in enumerate(testedStructureDetail):
stream.append("tcu::TestStatus testPhysicalDeviceFeature" + x.instanceName[len('device'):]+" (Context& context)")
stream.append("""{
const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
const CustomInstance instance (createCustomInstanceWithExtension(context, "VK_KHR_get_physical_device_properties2"));
const InstanceDriver& vki (instance.getDriver());
const int count = 2u;
TestLog& log = context.getTestContext().getLog();
VkPhysicalDeviceFeatures2 extFeatures;
vector<VkExtensionProperties> properties = enumerateDeviceExtensionProperties(vki, physicalDevice, DE_NULL);
""")
stream.append("\t"+structureDefinitions[n])
stream.append("\t"+featureEnabledFlags[n])
stream.append('')
stream.append('\tfor (int ndx = 0; ndx < count; ++ndx)\n\t{')
stream.append("\t" + clearStructures[n])
stream.extend(structureChain[n])
stream.append('')
stream.append(
'\t\tdeMemset(&extFeatures.features, 0xcd, sizeof(extFeatures.features));\n'
'\t\textFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;\n'
'\t\textFeatures.pNext = &' + testedStructureDetail[n].instanceName + '[ndx];\n\n'
'\t\tvki.getPhysicalDeviceFeatures2(physicalDevice, &extFeatures);')
stream.append('\t}\n')
stream.extend(logStructures[n])
stream.append('')
stream.extend(verifyStructures[n])
stream.append('\treturn tcu::TestStatus::pass("Querying succeeded");')
stream.append("}\n")
# function to create tests
stream.append("""
void addSeparateFeatureTests (tcu::TestCaseGroup* testGroup)
{
""")
for x in testedStructureDetail:
stream.append('\taddFunctionCase(testGroup, "' + camelToSnake(x.instanceName[len('device'):]) + '", "' + x.name + '", testPhysicalDeviceFeature' + x.instanceName[len('device'):] + ');')
stream.append('}\n')
# write out
writeInlFile(filename, INL_HEADER, stream)
def generateDeviceFeaturesDefs(apiName, src):
# look for definitions
ptrnSType = r'VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_(\w+)_FEATURES(\w*)\s*='
matches = re.findall(ptrnSType, src, re.M)
matches = sorted(matches, key=lambda m: m[0])
# hardcoded list of core extensions having features and missing from Vulkan SC
missingVulkanSCExt = \
'#define VK_KHR_16BIT_STORAGE_EXTENSION_NAME \"VK_KHR_16bit_storage\"\n' \
'#define VK_KHR_8BIT_STORAGE_EXTENSION_NAME \"VK_KHR_8bit_storage\"\n' \
'#define VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME \"VK_KHR_buffer_device_address\"\n' \
'#define VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME \"VK_EXT_descriptor_indexing\"\n' \
'#define VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME \"VK_EXT_host_query_reset\"\n' \
'#define VK_KHR_IMAGELESS_FRAMEBUFFER_EXTENSION_NAME \"VK_KHR_imageless_framebuffer\"\n' \
'#define VK_KHR_MULTIVIEW_EXTENSION_NAME \"VK_KHR_multiview\"\n' \
'#define VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME \"VK_KHR_sampler_ycbcr_conversion\"\n' \
'#define VK_EXT_SCALAR_BLOCK_LAYOUT_EXTENSION_NAME \"VK_EXT_scalar_block_layout\"\n' \
'#define VK_KHR_SEPARATE_DEPTH_STENCIL_LAYOUTS_EXTENSION_NAME \"VK_KHR_separate_depth_stencil_layouts\"\n' \
'#define VK_KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME \"VK_KHR_shader_atomic_int64\"\n' \
'#define VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME \"VK_KHR_shader_draw_parameters\"\n' \
'#define VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME \"VK_KHR_shader_float16_int8\"\n' \
'#define VK_KHR_SHADER_SUBGROUP_EXTENDED_TYPES_EXTENSION_NAME \"VK_KHR_shader_subgroup_extended_types\"\n' \
'#define VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME \"VK_KHR_timeline_semaphore\"\n' \
'#define VK_KHR_UNIFORM_BUFFER_STANDARD_LAYOUT_EXTENSION_NAME \"VK_KHR_uniform_buffer_standard_layout\"\n' \
'#define VK_KHR_VARIABLE_POINTERS_EXTENSION_NAME \"VK_KHR_variable_pointers\"\n' \
'#define VK_KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME \"VK_KHR_vulkan_memory_model\"\n'
# construct final list
defs = []
for sType, sSuffix in matches:
structName = re.sub("[_0-9][a-z]", lambda match: match.group(0).upper(), sType.capitalize()).replace('_', '')
ptrnStructName = r'\s*typedef\s+struct\s+(VkPhysicalDevice' + structName + 'Features' + sSuffix.replace('_', '') + ')'
matchStructName = re.search(ptrnStructName, src, re.IGNORECASE)
if matchStructName:
# handle special cases
if sType == "EXCLUSIVE_SCISSOR":
sType = "SCISSOR_EXCLUSIVE"
elif sType == "ASTC_DECODE":
sType = "ASTC_DECODE_MODE"
elif sType == "MAINTENANCE_4":
sType = "MAINTENANCE4"
elif sType == "YCBCR_2_PLANE_444_FORMATS":
sType = "YCBCR_2PLANE_444_FORMATS"
elif sType in {'VULKAN_1_1', 'VULKAN_1_2', 'VULKAN_1_3'}:
continue
elif sType == 'RASTERIZATION_ORDER_ATTACHMENT_ACCESS':
# skip case that has const pNext pointer
continue
# skip cases that have const pNext pointer
if sType == 'RASTERIZATION_ORDER_ATTACHMENT_ACCESS':
continue
# skip cases that have const pNext pointer
if sType == 'RASTERIZATION_ORDER_ATTACHMENT_ACCESS':
continue
# end handling special cases
ptrnExtensionName = r'^\s*#define\s+(\w+' + sSuffix + '_' + sType + '_EXTENSION_NAME).+$'
matchExtensionName = re.search(ptrnExtensionName, src, re.M)
if matchExtensionName is None and apiName=='SC':
matchExtensionName = re.search(ptrnExtensionName, missingVulkanSCExt, re.M)
ptrnSpecVersion = r'^\s*#define\s+(\w+' + sSuffix + '_' + sType + '_SPEC_VERSION).+$'
matchSpecVersion = re.search(ptrnSpecVersion, src, re.M)
defs.append( (sType, '', sSuffix, matchStructName.group(1), \
matchExtensionName.group(0) if matchExtensionName else None,
matchExtensionName.group(1) if matchExtensionName else None,
matchSpecVersion.group(1) if matchSpecVersion else '0') )
return defs
def generateDevicePropertiesDefs(apiName, src):
# look for definitions
ptrnSType = r'VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_(\w+)_PROPERTIES(\w*)\s*='
matches = re.findall(ptrnSType, src, re.M)
matches = sorted(matches, key=lambda m: m[0])
# hardcoded list of core extensions having properties and missing from Vulkan SC
missingVulkanSCExt = \
'#define VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME \"VK_KHR_depth_stencil_resolve\"\n' \
'#define VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME \"VK_EXT_descriptor_indexing\"\n' \
'#define VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME \"VK_KHR_driver_properties\"\n' \
'#define VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME \"VK_KHR_shader_float_controls\"\n' \
'#define VK_KHR_MAINTENANCE3_EXTENSION_NAME \"VK_KHR_maintenance3\"\n' \
'#define VK_KHR_MULTIVIEW_EXTENSION_NAME \"VK_KHR_multiview\"\n' \
'#define VK_EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME \"VK_EXT_sampler_filter_minmax\"\n' \
'#define VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME \"VK_KHR_timeline_semaphore\"\n'
# construct final list
defs = []
for sType, sSuffix in matches:
# handle special cases
if sType in {'VULKAN_1_1', 'VULKAN_1_2', 'VULKAN_1_3', 'VULKAN_SC_1_0', 'GROUP', 'MEMORY_BUDGET', 'MEMORY', 'TOOL'}:
continue
# there are cases like VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_2_AMD
# where 2 is after PROPERTIES - to handle this we need to split suffix to two parts
sVerSuffix = ''
sExtSuffix = sSuffix
suffixStart = sSuffix.rfind('_')
if suffixStart > 0:
sVerSuffix = sSuffix[:suffixStart]
sExtSuffix = sSuffix[suffixStart:]
# handle special case
if sType == "ID":
structName = sType
else:
structName = re.sub("[_0-9][a-z]", lambda match: match.group(0).upper(), sType.capitalize()).replace('_', '')
ptrnStructName = r'\s*typedef\s+struct\s+(VkPhysicalDevice' + structName + 'Properties' + sSuffix.replace('_', '') + ')'
matchStructName = re.search(ptrnStructName, src, re.M)
if matchStructName:
extType = sType
if extType == "DISCARD_RECTANGLE":
extType = "DISCARD_RECTANGLES"
elif extType == "DRIVER":
extType = "DRIVER_PROPERTIES"
elif extType == "POINT_CLIPPING":
extType = "MAINTENANCE_2"
elif extType == "SHADER_CORE":
extType = "SHADER_CORE_PROPERTIES"
elif extType == "DRM":
extType = "PHYSICAL_DEVICE_DRM"
if apiName == 'SC':
if extType == "MAINTENANCE_3":
extType = "MAINTENANCE3"
elif extType == "MAINTENANCE_4":
extType = "MAINTENANCE4"
elif extType == "POINT_CLIPPING":
extType = "MAINTENANCE2"
# end handling special cases
ptrnExtensionName = r'^\s*#define\s+(\w+' + sExtSuffix + '_' + extType + sVerSuffix +'[_0-9]*_EXTENSION_NAME).+$'
matchExtensionName = re.search(ptrnExtensionName, src, re.M)
if matchExtensionName is None and apiName=='SC':
matchExtensionName = re.search(ptrnExtensionName, missingVulkanSCExt, re.M)
ptrnSpecVersion = r'^\s*#define\s+(\w+' + sExtSuffix + '_' + extType + sVerSuffix + '[_0-9]*_SPEC_VERSION).+$'
matchSpecVersion = re.search(ptrnSpecVersion, src, re.M)
defs.append( (sType, sVerSuffix, sExtSuffix, matchStructName.group(1), \
matchExtensionName.group(0) if matchExtensionName else None,
matchExtensionName.group(1) if matchExtensionName else None,
matchSpecVersion.group (1) if matchSpecVersion else '0') )
return defs
def writeDeviceFeatures(api, dfDefs, filename):
# find VkPhysicalDeviceVulkan[1-9][0-9]Features blob structurs
# and construct dictionary with all of their attributes
blobMembers = {}
blobStructs = {}
blobPattern = re.compile("^VkPhysicalDeviceVulkan([1-9][0-9])Features[0-9]*$")
for structureType in api.compositeTypes:
match = blobPattern.match(structureType.name)
if match:
allMembers = [member.name for member in structureType.members]
vkVersion = match.group(1)
blobMembers[vkVersion] = allMembers[2:]
blobStructs[vkVersion] = set()
initFromBlobDefinitions = []
emptyInitDefinitions = []
# iterate over all feature structures
allFeaturesPattern = re.compile("^VkPhysicalDevice\w+Features[1-9]*")
nonExtFeaturesPattern = re.compile("^VkPhysicalDevice\w+Features[1-9]*$")
for structureType in api.compositeTypes:
# skip structures that are not feature structures
if not allFeaturesPattern.match(structureType.name):
continue
# skip structures that were previously identified as blobs
if blobPattern.match(structureType.name):
continue
if structureType.isAlias:
continue
# skip sType and pNext and just grab third and next attributes
structureMembers = structureType.members[2:]
notPartOfBlob = True
if nonExtFeaturesPattern.match(structureType.name):
# check if this member is part of any of the blobs
for blobName, blobMemberList in blobMembers.items():
# if just one member is not part of this blob go to the next blob
# (we asume that all members are part of blob - no need to check all)
if structureMembers[0].name not in blobMemberList:
continue
# add another feature structure name to this blob
blobStructs[blobName].add(structureType)
# add specialization for this feature structure
memberCopying = ""
for member in structureMembers:
memberCopying += "\tfeatureType.{0} = allFeaturesBlobs.vk{1}.{0};\n".format(member.name, blobName)
wholeFunction = \
"template<> void initFeatureFromBlob<{0}>({0}& featureType, const AllFeaturesBlobs& allFeaturesBlobs)\n" \
"{{\n" \
"{1}" \
"}}".format(structureType.name, memberCopying)
initFromBlobDefinitions.append(wholeFunction)
notPartOfBlob = False
# assuming that all members are part of blob, goto next
break
# add empty template definition as on Fedora there are issue with
# linking using just generic template - all specializations are needed
if notPartOfBlob:
emptyFunction = "template<> void initFeatureFromBlob<{0}>({0}&, const AllFeaturesBlobs&) {{}}"
emptyInitDefinitions.append(emptyFunction.format(structureType.name))
extensionDefines = []
makeFeatureDescDefinitions = []
featureStructWrappers = []
for idx, (sType, sVerSuffix, sExtSuffix, extStruct, extLine, extName, specVer) in enumerate(dfDefs):
extensionNameDefinition = extName
if not extensionNameDefinition:
extensionNameDefinition = 'DECL{0}_{1}_EXTENSION_NAME'.format((sExtSuffix if sExtSuffix else ''), sType)
# construct defines with names
if extLine:
extensionDefines.append(extLine)
else:
extensionDefines.append('#define {0} "not_existent_feature"'.format(extensionNameDefinition))
# handle special cases
if sType == "SCISSOR_EXCLUSIVE":
sType = "EXCLUSIVE_SCISSOR"
elif sType == "ASTC_DECODE_MODE":
sType = "ASTC_DECODE"
elif sType == "MAINTENANCE4":
sType = "MAINTENANCE_4"
elif sType == "YCBCR_2PLANE_444_FORMATS":
sType = "YCBCR_2_PLANE_444_FORMATS"
# end handling special cases
# construct makeFeatureDesc template function definitions
sTypeName = "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_{0}_FEATURES{1}".format(sType, sVerSuffix + sExtSuffix)
makeFeatureDescDefinitions.append("template<> FeatureDesc makeFeatureDesc<{0}>(void) " \
"{{ return FeatureDesc{{{1}, {2}, {3}, {4}}}; }}".format(extStruct, sTypeName, extensionNameDefinition, specVer, len(dfDefs)-idx))
# construct CreateFeatureStruct wrapper block
featureStructWrappers.append("\t{{ createFeatureStructWrapper<{0}>, {1}, {2} }},".format(extStruct, extensionNameDefinition, specVer))
# construct function that will check for which vk version structure sType is part of blob
blobChecker = "deUint32 getBlobFeaturesVersion (VkStructureType sType)\n{\n" \
"\tconst std::map<VkStructureType, deUint32> sTypeBlobMap\n" \
"\t{\n"
# iterate over blobs with list of structures
for blobName in sorted(blobStructs.keys()):
blobChecker += "\t\t// Vulkan{0}\n".format(blobName)
# iterate over all feature structures in current blob
structuresList = list(blobStructs[blobName])
structuresList = sorted(structuresList, key=lambda s: s.name)
for structType in structuresList:
# find definition of this structure in dfDefs
structName = structType.name
# handle special cases
if structName == 'VkPhysicalDeviceShaderDrawParameterFeatures':
structName = 'VkPhysicalDeviceShaderDrawParametersFeatures'
# end handling special cases
structDef = [s for s in dfDefs if s[3] == structName][0]
sType = structDef[0]
sSuffix = structDef[1] + structDef[2]
# handle special cases
if sType == "SCISSOR_EXCLUSIVE":
sType = "EXCLUSIVE_SCISSOR"
elif sType == "MAINTENANCE4":
sType = "MAINTENANCE_4"
# end handling special cases
sTypeName = "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_{0}_FEATURES{1}".format(sType, sSuffix)
tabs = "\t" * int((88 - len(sTypeName)) / 4)
blobChecker += "\t\t{{ {0},{1}VK_API_VERSION_{2}_{3} }},\n".format(sTypeName, tabs, blobName[0], blobName[1])
blobChecker += "\t};\n\n" \
"\tauto it = sTypeBlobMap.find(sType);\n" \
"\tif(it == sTypeBlobMap.end())\n" \
"\t\treturn 0;\n" \
"\treturn it->second;\n" \
"}\n"
# combine all definition lists
stream = [
'#include "vkDeviceFeatures.hpp"\n',
'namespace vk\n{']
stream.extend(extensionDefines)
stream.append('\n')
stream.extend(initFromBlobDefinitions)
stream.append('\n// generic template is not enough for some compilers')
stream.extend(emptyInitDefinitions)
stream.append('\n')
stream.extend(makeFeatureDescDefinitions)
stream.append('\n')
stream.append('static const FeatureStructCreationData featureStructCreationArray[]\n{')
stream.extend(featureStructWrappers)
stream.append('};\n')
stream.append(blobChecker)
stream.append('} // vk\n')
writeInlFile(filename, INL_HEADER, stream)
def writeDeviceFeatureTest(apiName, api, filename):
coreFeaturesPattern = re.compile("^VkPhysicalDeviceVulkan([1-9][0-9])Features[0-9]*$")
featureItems = []
testFunctions = []
# iterate over all feature structures
allFeaturesPattern = re.compile("^VkPhysicalDevice\w+Features[1-9]*")
for structureType in api.compositeTypes:
# skip structures that are not feature structures
if not allFeaturesPattern.match(structureType.name):
continue
# skip alias structures
if structureType.isAlias:
continue
# skip sType and pNext and just grab third and next attributes
structureMembers = structureType.members[2:]
items = []
for member in structureMembers:
items.append(" FEATURE_ITEM ({0}, {1}),".format(structureType.name, member.name))
testBlock = """
tcu::TestStatus createDeviceWithUnsupportedFeaturesTest{4} (Context& context)
{{
const PlatformInterface& vkp = context.getPlatformInterface();
tcu::TestLog& log = context.getTestContext().getLog();
tcu::ResultCollector resultCollector (log);
const CustomInstance instance (createCustomInstanceWithExtensions(context, context.getInstanceExtensions(), DE_NULL, true));
const InstanceDriver& instanceDriver (instance.getDriver());
const VkPhysicalDevice physicalDevice = chooseDevice(instanceDriver, instance, context.getTestContext().getCommandLine());
const deUint32 queueFamilyIndex = 0;
const deUint32 queueCount = 1;
const float queuePriority = 1.0f;
const DeviceFeatures deviceFeaturesAll (context.getInstanceInterface(), context.getUsedApiVersion(), physicalDevice, context.getInstanceExtensions(), context.getDeviceExtensions(), DE_TRUE);
const VkPhysicalDeviceFeatures2 deviceFeatures2 = deviceFeaturesAll.getCoreFeatures2();
int numErrors = 0;
bool isSubProcess = context.getTestContext().getCommandLine().isSubProcess();
{6}
VkPhysicalDeviceFeatures emptyDeviceFeatures;
deMemset(&emptyDeviceFeatures, 0, sizeof(emptyDeviceFeatures));
// Only non-core extensions will be used when creating the device.
vector<const char*> coreExtensions;
getCoreDeviceExtensions(context.getUsedApiVersion(), coreExtensions);
vector<string> nonCoreExtensions(removeExtensions(context.getDeviceExtensions(), coreExtensions));
vector<const char*> extensionNames;
extensionNames.reserve(nonCoreExtensions.size());
for (const string& extension : nonCoreExtensions)
extensionNames.push_back(extension.c_str());
if (const void* featuresStruct = findStructureInChain(const_cast<const void*>(deviceFeatures2.pNext), getStructureType<{0}>()))
{{
static const Feature features[] =
{{
{1}
}};
auto* supportedFeatures = reinterpret_cast<const {0}*>(featuresStruct);
checkFeatures(vkp, instance, instanceDriver, physicalDevice, {2}, features, supportedFeatures, queueFamilyIndex, queueCount, queuePriority, numErrors, resultCollector, {3}, emptyDeviceFeatures, {5});
}}
if (numErrors > 0)
return tcu::TestStatus(resultCollector.getResult(), "Enabling unsupported features didn't return VK_ERROR_FEATURE_NOT_PRESENT.");
else
return tcu::TestStatus(resultCollector.getResult(), resultCollector.getMessage());
}}
"""
additionalParams = ( 'memReservationStatMax, isSubProcess' if apiName == 'SC' else 'isSubProcess' )
additionalDefs = ( ' VkDeviceObjectReservationCreateInfo memReservationStatMax = context.getResourceInterface()->getStatMax();' if apiName == 'SC' else '')
featureItems.append(testBlock.format(structureType.name, "\n".join(items), len(items), ("DE_NULL" if coreFeaturesPattern.match(structureType.name) else "&extensionNames"), structureType.name[len('VkPhysicalDevice'):], additionalParams, additionalDefs))
testFunctions.append("createDeviceWithUnsupportedFeaturesTest" + structureType.name[len('VkPhysicalDevice'):])
stream = ['']
stream.extend(featureItems)
stream.append("""
void addSeparateUnsupportedFeatureTests (tcu::TestCaseGroup* testGroup)
{
""")
for x in testFunctions:
stream.append('\taddFunctionCase(testGroup, "' + camelToSnake(x[len('createDeviceWithUnsupportedFeaturesTest'):]) + '", "' + x + '", ' + x + ');')
stream.append('}\n')
writeInlFile(filename, INL_HEADER, stream)
def writeDeviceProperties(api, dpDefs, filename):
# find VkPhysicalDeviceVulkan[1-9][0-9]Features blob structurs
# and construct dictionary with all of their attributes
blobMembers = {}
blobStructs = {}
blobPattern = re.compile("^VkPhysicalDeviceVulkan([1-9][0-9])Properties[0-9]*$")
for structureType in api.compositeTypes:
match = blobPattern.match(structureType.name)
if match:
allMembers = [member.name for member in structureType.members]
vkVersion = match.group(1)
blobMembers[vkVersion] = allMembers[2:]
blobStructs[vkVersion] = set()
initFromBlobDefinitions = []
emptyInitDefinitions = []
# iterate over all property structures
allPropertiesPattern = re.compile("^VkPhysicalDevice\w+Properties[1-9]*")
nonExtPropertiesPattern = re.compile("^VkPhysicalDevice\w+Properties[1-9]*$")
for structureType in api.compositeTypes:
# skip structures that are not property structures
if not allPropertiesPattern.match(structureType.name):
continue
# skip structures that were previously identified as blobs
if blobPattern.match(structureType.name):
continue
if structureType.isAlias:
continue
# skip sType and pNext and just grab third and next attributes
structureMembers = structureType.members[2:]
notPartOfBlob = True
if nonExtPropertiesPattern.match(structureType.name):
# check if this member is part of any of the blobs
for blobName, blobMemberList in blobMembers.items():
# if just one member is not part of this blob go to the next blob
# (we asume that all members are part of blob - no need to check all)
if structureMembers[0].name not in blobMemberList:
continue
# add another property structure name to this blob
blobStructs[blobName].add(structureType)
# add specialization for this property structure
memberCopying = ""
for member in structureMembers:
if not member.arraySize:
# handle special case
if structureType.name == "VkPhysicalDeviceSubgroupProperties" and "subgroup" not in member.name :
blobMemberName = "subgroup" + member.name[0].capitalize() + member.name[1:]
memberCopying += "\tpropertyType.{0} = allPropertiesBlobs.vk{1}.{2};\n".format(member.name, blobName, blobMemberName)
# end handling special case
else:
memberCopying += "\tpropertyType.{0} = allPropertiesBlobs.vk{1}.{0};\n".format(member.name, blobName)
else:
memberCopying += "\tmemcpy(propertyType.{0}, allPropertiesBlobs.vk{1}.{0}, sizeof({2}) * {3});\n".format(member.name, blobName, member.type[0], member.arraySize[1:-1])
wholeFunction = \
"template<> void initPropertyFromBlob<{0}>({0}& propertyType, const AllPropertiesBlobs& allPropertiesBlobs)\n" \
"{{\n" \
"{1}" \
"}}".format(structureType.name, memberCopying)
initFromBlobDefinitions.append(wholeFunction)
notPartOfBlob = False
# assuming that all members are part of blob, goto next
break
# add empty template definition as on Fedora there are issue with
# linking using just generic template - all specializations are needed
if notPartOfBlob:
emptyFunction = "template<> void initPropertyFromBlob<{0}>({0}&, const AllPropertiesBlobs&) {{}}"
emptyInitDefinitions.append(emptyFunction.format(structureType.name))
extensionDefines = []
makePropertyDescDefinitions = []
propertyStructWrappers = []
for idx, (sType, sVerSuffix, sExtSuffix, extStruct, extLine, extName, specVer) in enumerate(dpDefs):
extensionNameDefinition = extName
if not extensionNameDefinition:
extensionNameDefinition = 'DECL{0}_{1}_EXTENSION_NAME'.format((sExtSuffix if sExtSuffix else ''), sType)
# construct defines with names
if extLine:
extensionDefines.append(extLine)
else:
extensionDefines.append('#define {0} "core_property"'.format(extensionNameDefinition))
# construct makePropertyDesc template function definitions
sTypeName = "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_{0}_PROPERTIES{1}".format(sType, sVerSuffix + sExtSuffix)
makePropertyDescDefinitions.append("template<> PropertyDesc makePropertyDesc<{0}>(void) " \
"{{ return PropertyDesc{{{1}, {2}, {3}, {4}}}; }}".format(extStruct, sTypeName, extensionNameDefinition, specVer, len(dpDefs)-idx))
# construct CreateProperty struct wrapper block
propertyStructWrappers.append("\t{{ createPropertyStructWrapper<{0}>, {1}, {2} }},".format(extStruct, extensionNameDefinition, specVer))
# construct method that will check if structure sType is part of blob
blobChecker = "deUint32 getBlobPropertiesVersion (VkStructureType sType)\n{\n" \
"\tconst std::map<VkStructureType, deUint32> sTypeBlobMap\n" \
"\t{\n"
# iterate over blobs with list of structures
for blobName in sorted(blobStructs.keys()):
blobChecker += "\t\t// Vulkan{0}\n".format(blobName)
# iterate over all feature structures in current blob
structuresList = list(blobStructs[blobName])
structuresList = sorted(structuresList, key=lambda s: s.name)
for structType in structuresList:
# find definition of this structure in dpDefs
structName = structType.name
structDef = [s for s in dpDefs if s[3] == structName][0]
sType = structDef[0]
sSuffix = structDef[1] + structDef[2]
sTypeName = "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_{0}_PROPERTIES{1}".format(sType, sSuffix)
tabs = "\t" * int((76 - len(sTypeName)) / 4)
blobChecker += "\t\t{{ {0},{1}VK_API_VERSION_{2}_{3} }},\n".format(sTypeName, tabs, blobName[0], blobName[1])
blobChecker += "\t};\n\n" \
"\tauto it = sTypeBlobMap.find(sType);\n" \
"\tif(it == sTypeBlobMap.end())\n" \
"\t\treturn 0;\n" \
"\treturn it->second;\n" \
"}\n"
# combine all definition lists
stream = [
'#include "vkDeviceProperties.hpp"\n',
'namespace vk\n{']
stream.extend(extensionDefines)
stream.append('\n')
stream.extend(initFromBlobDefinitions)
stream.append('\n// generic template is not enough for some compilers')
stream.extend(emptyInitDefinitions)
stream.append('\n')
stream.extend(makePropertyDescDefinitions)
stream.append('\n')
stream.append('static const PropertyStructCreationData propertyStructCreationArray[] =\n{')
stream.extend(propertyStructWrappers)
stream.append('};\n')
stream.append(blobChecker)
stream.append('} // vk\n')
writeInlFile(filename, INL_HEADER, stream)
def genericDeviceFeaturesWriter(dfDefs, pattern, filename):
stream = []
for _, _, _, extStruct, _, _, _ in dfDefs:
nameSubStr = extStruct.replace("VkPhysicalDevice", "").replace("KHR", "").replace("NV", "")
stream.append(pattern.format(extStruct, nameSubStr))
writeInlFile(filename, INL_HEADER, indentLines(stream))
def writeDeviceFeaturesDefaultDeviceDefs(dfDefs, filename):
pattern = "const {0}&\tget{1}\t(void) const {{ return m_deviceFeatures.getFeatureType<{0}>();\t}}"
genericDeviceFeaturesWriter(dfDefs, pattern, filename)
def writeDeviceFeaturesContextDecl(dfDefs, filename):
pattern = "const vk::{0}&\tget{1}\t(void) const;"
genericDeviceFeaturesWriter(dfDefs, pattern, filename)
def writeDeviceFeaturesContextDefs(dfDefs, filename):
pattern = "const vk::{0}&\tContext::get{1}\t(void) const {{ return m_device->get{1}();\t}}"
genericDeviceFeaturesWriter(dfDefs, pattern, filename)
def genericDevicePropertiesWriter(dfDefs, pattern, filename):
stream = []
for _, _, _, extStruct, _, _, _ in dfDefs:
nameSubStr = extStruct.replace("VkPhysicalDevice", "").replace("KHR", "").replace("NV", "")
if extStruct == "VkPhysicalDeviceRayTracingPropertiesNV":
nameSubStr += "NV"
stream.append(pattern.format(extStruct, nameSubStr))
writeInlFile(filename, INL_HEADER, indentLines(stream))
def writeDevicePropertiesDefaultDeviceDefs(dfDefs, filename):
pattern = "const {0}&\tget{1}\t(void) const {{ return m_deviceProperties.getPropertyType<{0}>();\t}}"
genericDevicePropertiesWriter(dfDefs, pattern, filename)
def writeDevicePropertiesContextDecl(dfDefs, filename):
pattern = "const vk::{0}&\tget{1}\t(void) const;"
genericDevicePropertiesWriter(dfDefs, pattern, filename)
def writeDevicePropertiesContextDefs(dfDefs, filename):
pattern = "const vk::{0}&\tContext::get{1}\t(void) const {{ return m_device->get{1}();\t}}"
genericDevicePropertiesWriter(dfDefs, pattern, filename)
def writeMandatoryFeatures(api, filename):
def structInAPI(name):
for c in api.compositeTypes:
if c.name == name:
return True
return False
stream = []
dictStructs = {}
dictData = []
for _, data in api.additionalExtensionData:
if 'mandatory_features' not in data.keys():
continue
# sort to have same results for py2 and py3
listStructFeatures = sorted(data['mandatory_features'].items(), key=lambda tup: tup[0])
for structure, featuresList in listStructFeatures:
for featureData in featuresList:
# allow for featureless VKSC only extensions
if not 'features' in featureData.keys() or 'requirements' not in featureData.keys():
continue
requirements = featureData['requirements']
mandatory_variant = ''
try:
mandatory_variant = featureData['mandatory_variant']
except KeyError:
mandatory_variant = ''
dictData.append( [ structure, featureData['features'], requirements, mandatory_variant] )
if structure == 'VkPhysicalDeviceFeatures':
continue
# if structure is not in dict construct name of variable and add is as a first item
if (structure not in dictStructs):
dictStructs[structure] = ([structure[2:3].lower() + structure[3:]], mandatory_variant)
# add first requirement if it is unique
if requirements and (requirements[0] not in dictStructs[structure][0]):
dictStructs[structure][0].append(requirements[0])
stream.extend(['bool checkMandatoryFeatures(const vkt::Context& context)\n{',
'\tif (!context.isInstanceFunctionalitySupported("VK_KHR_get_physical_device_properties2"))',
'\t\tTCU_THROW(NotSupportedError, "Extension VK_KHR_get_physical_device_properties2 is not present");',
'',
'\tVkPhysicalDevice\t\t\t\t\tphysicalDevice\t\t= context.getPhysicalDevice();',
'\tconst InstanceInterface&\t\t\tvki\t\t\t\t\t= context.getInstanceInterface();',
'\tconst vector<VkExtensionProperties>\tdeviceExtensions\t= enumerateDeviceExtensionProperties(vki, physicalDevice, DE_NULL);',
'',
'\ttcu::TestLog& log = context.getTestContext().getLog();',
'\tvk::VkPhysicalDeviceFeatures2 coreFeatures;',
'\tdeMemset(&coreFeatures, 0, sizeof(coreFeatures));',
'\tcoreFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;',
'\tvoid** nextPtr = &coreFeatures.pNext;',
''])
listStruct = sorted(dictStructs.items(), key=lambda tup: tup[0]) # sort to have same results for py2 and py3
apiStruct = list( filter(lambda x : structInAPI(x[0]), listStruct)) # remove items not defined in current A
for k, v in apiStruct:
metaCondition = ''
if v[1] != '':
metaCondition = metaCondition + ' || defined(CTS_USES_' + v[1][0].upper() + ')'
stream.extend(['#if ' + metaCondition[4:]])
if (v[0][1].startswith("ApiVersion")):
cond = '\tif (context.contextSupports(vk::' + v[0][1] + '))'
else:
cond = '\tif (vk::isDeviceExtensionSupported(context.getUsedApiVersion(), context.getDeviceExtensions(), "' + v[0][1] + '"))'
stream.extend(['\tvk::' + k + ' ' + v[0][0]+ ';',
'\tdeMemset(&' + v[0][0] + ', 0, sizeof(' + v[0][0] + '));',
''])
reqs = v[0][1:]
if len(reqs) > 0 :
cond = 'if ( '
for i, req in enumerate(reqs) :
if (req.startswith("ApiVersion")):
cond = cond + 'context.contextSupports(vk::' + req + ')'
else:
cond = cond + 'isExtensionSupported(deviceExtensions, RequiredExtension("' + req + '"))'
if i+1 < len(reqs) :
cond = cond + ' || '
cond = cond + ' )'
stream.append('\t' + cond)
stream.extend(['\t{',
'\t\t' + v[0][0] + '.sType = getStructureType<' + k + '>();',
'\t\t*nextPtr = &' + v[0][0] + ';',
'\t\tnextPtr = &' + v[0][0] + '.pNext;',
'\t}'])
if metaCondition != '':
stream.extend(['#endif // ' + metaCondition[4:],
''])
else:
stream.extend([''])
stream.extend(['\tcontext.getInstanceInterface().getPhysicalDeviceFeatures2(context.getPhysicalDevice(), &coreFeatures);',
'\tbool result = true;',
''])
for v in dictData:
if not structInAPI(v[0]): # remove items not defined in current API ( important for Vulkan SC )
continue
structType = v[0];
structName = 'coreFeatures.features';
metaCondition = ''
if len(v) == 4 and v[3] != '':
# for x in v[3].split('_'):
metaCondition = metaCondition + ' || defined(CTS_USES_' + v[3][0].upper() + ')'
stream.extend(['#if ' + metaCondition[4:]])
if v[0] != 'VkPhysicalDeviceFeatures' :
structName = dictStructs[v[0]][0][0]
if len(v[2]) > 0 :
condition = 'if ( '
for i, req in enumerate(v[2]) :
if (req.startswith("ApiVersion")):
condition = condition + 'context.contextSupports(vk::' + req + ')'
elif '.' in req:
condition = condition + req
else:
condition = condition + 'isExtensionSupported(deviceExtensions, RequiredExtension("' + req + '"))'
if i+1 < len(v[2]) :
condition = condition + ' && '
condition = condition + ' )'
stream.append('\t' + condition)
stream.append('\t{')
# Don't need to support an AND case since that would just be another line in the .txt
if len(v[1]) == 1:
stream.append('\t\tif ( ' + structName + '.' + v[1][0] + ' == VK_FALSE )')
else:
condition = 'if ( '
for i, feature in enumerate(v[1]):
if i != 0:
condition = condition + ' && '
condition = condition + '( ' + structName + '.' + feature + ' == VK_FALSE )'
condition = condition + ' )'
stream.append('\t\t' + condition)
featureSet = " or ".join(v[1])
stream.extend(['\t\t{',
'\t\t\tlog << tcu::TestLog::Message << "Mandatory feature ' + featureSet + ' not supported" << tcu::TestLog::EndMessage;',
'\t\t\tresult = false;',
'\t\t}',
'\t}'])
if metaCondition != '':
stream.extend(['#endif // ' + metaCondition[4:],
''])
else:
stream.extend([''])
stream.append('\treturn result;')
stream.append('}\n')
writeInlFile(filename, INL_HEADER, stream)
def writeExtensionList(apiName, api, filename, extensionType):
extensionList = []
for extensionName, data in api.additionalExtensionData:
# make sure extension name starts with VK_KHR
if not extensionName.startswith('VK_KHR'):
continue
# make sure that this extension was registered
if 'register_extension' not in data.keys():
continue
# make sure extension is intended for the vulkan variant
is_sc_only = False
if apiName != 'SC':
if 'mandatory_features' in data.keys():
for structure, listStruct in data['mandatory_features'].items():
for featureData in listStruct:
mandatory_variant = ''
try:
mandatory_variant = featureData['mandatory_variant']
except KeyError:
mandatory_variant = ''
# VKSC only
if 'vulkansc' in mandatory_variant:
is_sc_only = True
if is_sc_only:
continue
# make sure extension has proper type
if extensionType == data['register_extension']['type']:
extensionList.append(extensionName)
extensionList.sort()
# write list of all found extensions
stream = []
stream.append('static const char* s_allowed{0}KhrExtensions[] =\n{{'.format(extensionType.title()))
for n in extensionList:
stream.append('\t"' + n + '",')
stream.append('};\n')
writeInlFile(filename, INL_HEADER, stream)
def parseCmdLineArgs():
parser = argparse.ArgumentParser(description = "Generate Vulkan INL files",
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument("-a",
"--api",
dest="api",
default="",
help="Choose between Vulkan and Vulkan SC")
parser.add_argument("-o",
"--outdir",
dest="outdir",
default="",
help="Choose output directory")
return parser.parse_args()
def preprocessTopInclude(src, dir):
pattern = r'#include\s+"([^\n]+)"'
while True:
inc = re.search(pattern, src)
if inc is None:
return src
incFileName = inc.string[inc.start(1):inc.end(1)]
patternIncNamed = r'#include\s+"' + incFileName + '"'
incBody = readFile(os.path.join(dir, incFileName)) if incFileName != 'vk_platform.h' else ''
incBodySanitized = re.sub(pattern, '', incBody)
bodyEndSanitized = re.sub(patternIncNamed, '', src[inc.end(0):])
src = src[0:inc.start(0)] + incBodySanitized + bodyEndSanitized
return src
if __name__ == "__main__":
args = parseCmdLineArgs()
outputPath = DEFAULT_OUTPUT_DIR[args.api]
# if argument was specified it is interpreted as a path to which .inl files will be written
if args.outdir != '':
outputPath = args.outdir
files = []
src = ""
if args.api == '':
# Generate vulkan headers from vk.xml
currentDir = os.getcwd()
pythonExecutable = sys.executable or "python"
os.chdir(os.path.join(VULKAN_HEADERS_INCLUDE_DIR, "..", "xml"))
vkTargets = [
"vulkan_android.h",
"vulkan_beta.h",
"vulkan_core.h",
"vulkan_fuchsia.h",
"vulkan_ggp.h",
"vulkan_ios.h",
"vulkan_macos.h",
"vulkan_metal.h",
"vulkan_vi.h",
"vulkan_wayland.h",
"vulkan_win32.h",
"vulkan_xcb.h",
"vulkan_xlib.h",
"vulkan_xlib_xrandr.h",
]
for target in vkTargets:
execute([pythonExecutable, "../scripts/genvk.py", "-o", "../include/vulkan", target])
videoDir = "../include/vk_video"
if (not os.path.isdir(videoDir)):
os.mkdir(videoDir)
videoTargets = [
'vulkan_video_codecs_common.h',
'vulkan_video_codec_h264std.h',
'vulkan_video_codec_h264std_decode.h',
'vulkan_video_codec_h264std_encode.h',
'vulkan_video_codec_h265std.h',
'vulkan_video_codec_h265std_decode.h',
'vulkan_video_codec_h265std_encode.h',
]
for target in videoTargets:
execute([pythonExecutable, "../scripts/genvk.py", "-registry", "video.xml", "-o", videoDir, target])
os.chdir(currentDir)
# Read all .h files and make sure vulkan_core.h is first out of vulkan files
vkTargets.remove("vulkan_core.h")
vkTargets.sort()
vkTargets.insert(0, "vulkan_core.h")
vkFilesWithCatalog = [os.path.join("vulkan", f) for f in vkTargets]
for file in vkFilesWithCatalog:
src += preprocessTopInclude(readFile(os.path.join(VULKAN_HEADERS_INCLUDE_DIR,file)), VULKAN_HEADERS_INCLUDE_DIR)
elif args.api=='SC':
# At the moment vulkan-docs does not have vulkan_sc_core.h. We will use a file from external/vulkancts/scripts/src
src = preprocessTopInclude(readFile(os.path.join(os.path.dirname(__file__), "src", "vulkan_sc_core.h" )), VULKAN_HEADERS_INCLUDE_DIR)
src = re.sub('\s*//[^\n]*', '', src)
src = re.sub('\n\n', '\n', src)
api = parseAPI(src)
platformFuncs = [Function.TYPE_PLATFORM]
instanceFuncs = [Function.TYPE_INSTANCE]
deviceFuncs = [Function.TYPE_DEVICE]
dfd = generateDeviceFeaturesDefs(args.api, src)
writeDeviceFeatures (api, dfd, os.path.join(outputPath, "vkDeviceFeatures.inl"))
writeDeviceFeaturesDefaultDeviceDefs (dfd, os.path.join(outputPath, "vkDeviceFeaturesForDefaultDeviceDefs.inl"))
writeDeviceFeaturesContextDecl (dfd, os.path.join(outputPath, "vkDeviceFeaturesForContextDecl.inl"))
writeDeviceFeaturesContextDefs (dfd, os.path.join(outputPath, "vkDeviceFeaturesForContextDefs.inl"))
writeDeviceFeatureTest (args.api, api, os.path.join(outputPath, "vkDeviceFeatureTest.inl"))
dpd = generateDevicePropertiesDefs(args.api, src)
writeDeviceProperties (api, dpd, os.path.join(outputPath, "vkDeviceProperties.inl"))
writeDevicePropertiesDefaultDeviceDefs (dpd, os.path.join(outputPath, "vkDevicePropertiesForDefaultDeviceDefs.inl"))
writeDevicePropertiesContextDecl (dpd, os.path.join(outputPath, "vkDevicePropertiesForContextDecl.inl"))
writeDevicePropertiesContextDefs (dpd, os.path.join(outputPath, "vkDevicePropertiesForContextDefs.inl"))
writeHandleType (api, os.path.join(outputPath, "vkHandleType.inl"))
writeBasicTypes (args.api, api, os.path.join(outputPath, "vkBasicTypes.inl"))
writeCompositeTypes (api, os.path.join(outputPath, "vkStructTypes.inl"))
writeInterfaceDecl (api, os.path.join(outputPath, "vkVirtualPlatformInterface.inl"), platformFuncs, False)
writeInterfaceDecl (api, os.path.join(outputPath, "vkVirtualInstanceInterface.inl"), instanceFuncs, False)
writeInterfaceDecl (api, os.path.join(outputPath, "vkVirtualDeviceInterface.inl"), deviceFuncs, False)
writeInterfaceDecl (api, os.path.join(outputPath, "vkConcretePlatformInterface.inl"), platformFuncs, True)
writeInterfaceDecl (api, os.path.join(outputPath, "vkConcreteInstanceInterface.inl"), instanceFuncs, True)
writeInterfaceDecl (api, os.path.join(outputPath, "vkConcreteDeviceInterface.inl"), deviceFuncs, True)
writeFunctionPtrTypes (api, os.path.join(outputPath, "vkFunctionPointerTypes.inl"))
writeFunctionPointers (api, os.path.join(outputPath, "vkPlatformFunctionPointers.inl"), platformFuncs)
writeFunctionPointers (api, os.path.join(outputPath, "vkInstanceFunctionPointers.inl"), instanceFuncs)
writeFunctionPointers (api, os.path.join(outputPath, "vkDeviceFunctionPointers.inl"), deviceFuncs)
writeInitFunctionPointers (api, os.path.join(outputPath, "vkInitPlatformFunctionPointers.inl"), platformFuncs, lambda f: f.name != "vkGetInstanceProcAddr")
writeInitFunctionPointers (api, os.path.join(outputPath, "vkInitInstanceFunctionPointers.inl"), instanceFuncs)
writeInitFunctionPointers (api, os.path.join(outputPath, "vkInitDeviceFunctionPointers.inl"), deviceFuncs)
writeFuncPtrInterfaceImpl (api, os.path.join(outputPath, "vkPlatformDriverImpl.inl"), platformFuncs, "PlatformDriver")
writeFuncPtrInterfaceImpl (api, os.path.join(outputPath, "vkInstanceDriverImpl.inl"), instanceFuncs, "InstanceDriver")
writeFuncPtrInterfaceImpl (api, os.path.join(outputPath, "vkDeviceDriverImpl.inl"), deviceFuncs, "DeviceDriver")
if args.api=='SC':
writeFuncPtrInterfaceSCImpl (api, os.path.join(outputPath, "vkDeviceDriverSCImpl.inl"), deviceFuncs, "DeviceDriverSC")
writeStrUtilProto (api, os.path.join(outputPath, "vkStrUtil.inl"))
writeStrUtilImpl (api, os.path.join(outputPath, "vkStrUtilImpl.inl"))
writeRefUtilProto (api, os.path.join(outputPath, "vkRefUtil.inl"))
writeRefUtilImpl (api, os.path.join(outputPath, "vkRefUtilImpl.inl"))
writeStructTraitsImpl (api, os.path.join(outputPath, "vkGetStructureTypeImpl.inl"))
writeNullDriverImpl (api, os.path.join(outputPath, "vkNullDriverImpl.inl"))
writeTypeUtil (api, os.path.join(outputPath, "vkTypeUtil.inl"))
writeSupportedExtensions (args.api, api, os.path.join(outputPath, "vkSupportedExtensions.inl"))
writeCoreFunctionalities (api, os.path.join(outputPath, "vkCoreFunctionalities.inl"))
writeExtensionFunctions (api, os.path.join(outputPath, "vkExtensionFunctions.inl"))
writeDeviceFeatures2 (api, os.path.join(outputPath, "vkDeviceFeatures2.inl"))
writeMandatoryFeatures (api, os.path.join(outputPath, "vkMandatoryFeatures.inl"))
writeExtensionList (args.api, api, os.path.join(outputPath, "vkInstanceExtensions.inl"), 'instance')
writeExtensionList (args.api, api, os.path.join(outputPath, "vkDeviceExtensions.inl"), 'device')
writeDriverIds (args.api, os.path.join(outputPath, "vkKnownDriverIds.inl"))
writeObjTypeImpl (api, os.path.join(outputPath, "vkObjTypeImpl.inl"))
# NOTE: when new files are generated then they should also be added to the
# vk-gl-cts\external\vulkancts\framework\vulkan\CMakeLists.txt outputs list