summaryrefslogtreecommitdiff
path: root/codegen/vulkan/scripts/cereal/common/vulkantypes.py
diff options
context:
space:
mode:
Diffstat (limited to 'codegen/vulkan/scripts/cereal/common/vulkantypes.py')
-rw-r--r--codegen/vulkan/scripts/cereal/common/vulkantypes.py1216
1 files changed, 0 insertions, 1216 deletions
diff --git a/codegen/vulkan/scripts/cereal/common/vulkantypes.py b/codegen/vulkan/scripts/cereal/common/vulkantypes.py
deleted file mode 100644
index dc3a9072..00000000
--- a/codegen/vulkan/scripts/cereal/common/vulkantypes.py
+++ /dev/null
@@ -1,1216 +0,0 @@
-# Copyright (c) 2018 The Android Open Source Project
-# Copyright (c) 2018 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.
-from typing import Dict, Optional, List, Set, Union
-from xml.etree.ElementTree import Element
-
-from generator import noneStr
-
-from copy import copy
-from string import whitespace
-
-# Holds information about core Vulkan objects
-# and the API calls that are used to create/destroy each one.
-class HandleInfo(object):
- def __init__(self, name, createApis, destroyApis):
- self.name = name
- self.createApis = createApis
- self.destroyApis = destroyApis
-
- def isCreateApi(self, apiName):
- return apiName == self.createApis or (apiName in self.createApis)
-
- def isDestroyApi(self, apiName):
- if self.destroyApis is None:
- return False
- return apiName == self.destroyApis or (apiName in self.destroyApis)
-
-DISPATCHABLE_HANDLE_TYPES = [
- "VkInstance",
- "VkPhysicalDevice",
- "VkDevice",
- "VkQueue",
- "VkCommandBuffer",
-]
-
-NON_DISPATCHABLE_HANDLE_TYPES = [
- "VkDeviceMemory",
- "VkBuffer",
- "VkBufferView",
- "VkImage",
- "VkImageView",
- "VkShaderModule",
- "VkDescriptorPool",
- "VkDescriptorSetLayout",
- "VkDescriptorSet",
- "VkSampler",
- "VkPipeline",
- "VkPipelineLayout",
- "VkRenderPass",
- "VkFramebuffer",
- "VkPipelineCache",
- "VkCommandPool",
- "VkFence",
- "VkSemaphore",
- "VkEvent",
- "VkQueryPool",
- "VkSamplerYcbcrConversion",
- "VkSamplerYcbcrConversionKHR",
- "VkDescriptorUpdateTemplate",
- "VkSurfaceKHR",
- "VkSwapchainKHR",
- "VkDisplayKHR",
- "VkDisplayModeKHR",
- "VkObjectTableNVX",
- "VkIndirectCommandsLayoutNVX",
- "VkValidationCacheEXT",
- "VkDebugReportCallbackEXT",
- "VkDebugUtilsMessengerEXT",
- "VkAccelerationStructureNV",
- "VkIndirectCommandsLayoutNV",
- "VkAccelerationStructureKHR",
-]
-
-CUSTOM_HANDLE_CREATE_TYPES = [
- "VkPhysicalDevice",
- "VkQueue",
- "VkPipeline",
- "VkDeviceMemory",
- "VkDescriptorSet",
- "VkCommandBuffer",
- "VkRenderPass",
-]
-
-HANDLE_TYPES = list(sorted(list(set(DISPATCHABLE_HANDLE_TYPES +
- NON_DISPATCHABLE_HANDLE_TYPES + CUSTOM_HANDLE_CREATE_TYPES))))
-
-HANDLE_INFO = {}
-
-for h in HANDLE_TYPES:
- if h in CUSTOM_HANDLE_CREATE_TYPES:
- if h == "VkPhysicalDevice":
- HANDLE_INFO[h] = \
- HandleInfo(
- "VkPhysicalDevice",
- "vkEnumeratePhysicalDevices", None)
- if h == "VkQueue":
- HANDLE_INFO[h] = \
- HandleInfo(
- "VkQueue",
- ["vkGetDeviceQueue", "vkGetDeviceQueue2"],
- None)
- if h == "VkPipeline":
- HANDLE_INFO[h] = \
- HandleInfo(
- "VkPipeline",
- ["vkCreateGraphicsPipelines", "vkCreateComputePipelines"],
- "vkDestroyPipeline")
- if h == "VkDeviceMemory":
- HANDLE_INFO[h] = \
- HandleInfo("VkDeviceMemory",
- "vkAllocateMemory", ["vkFreeMemory", "vkFreeMemorySyncGOOGLE"])
- if h == "VkDescriptorSet":
- HANDLE_INFO[h] = \
- HandleInfo("VkDescriptorSet", "vkAllocateDescriptorSets",
- "vkFreeDescriptorSets")
- if h == "VkCommandBuffer":
- HANDLE_INFO[h] = \
- HandleInfo("VkCommandBuffer", "vkAllocateCommandBuffers",
- "vkFreeCommandBuffers")
- if h == "VkRenderPass":
- HANDLE_INFO[h] = \
- HandleInfo(
- "VkRenderPass",
- ["vkCreateRenderPass", "vkCreateRenderPass2", "vkCreateRenderPass2KHR"],
- "vkDestroyRenderPass")
- else:
- HANDLE_INFO[h] = \
- HandleInfo(h, "vkCreate" + h[2:], "vkDestroy" + h[2:])
-
-EXCLUDED_APIS = [
- "vkEnumeratePhysicalDeviceGroups",
-]
-
-EXPLICITLY_ABI_PORTABLE_TYPES = [
- "VkResult",
- "VkBool32",
- "VkSampleMask",
- "VkFlags",
- "VkDeviceSize",
-]
-
-EXPLICITLY_ABI_NON_PORTABLE_TYPES = [
- "size_t"
-]
-
-NON_ABI_PORTABLE_TYPE_CATEGORIES = [
- "handle",
- "funcpointer",
-]
-
-DEVICE_MEMORY_INFO_KEYS = [
- "devicememoryhandle",
- "devicememoryoffset",
- "devicememorysize",
- "devicememorytypeindex",
- "devicememorytypebits",
-]
-
-TRIVIAL_TRANSFORMED_TYPES = [
- "VkPhysicalDeviceExternalImageFormatInfo",
- "VkPhysicalDeviceExternalBufferInfo",
- "VkExternalMemoryImageCreateInfo",
- "VkExternalMemoryBufferCreateInfo",
- "VkExportMemoryAllocateInfo",
- "VkExternalImageFormatProperties",
- "VkExternalBufferProperties",
-]
-
-NON_TRIVIAL_TRANSFORMED_TYPES = [
- "VkExternalMemoryProperties",
- "VkImageCreateInfo",
-]
-
-TRANSFORMED_TYPES = TRIVIAL_TRANSFORMED_TYPES + NON_TRIVIAL_TRANSFORMED_TYPES
-
-# Holds information about a Vulkan type instance (i.e., not a type definition).
-# Type instances are used as struct field definitions or function parameters,
-# to be later fed to code generation.
-# VulkanType instances can be constructed in two ways:
-# 1. From an XML tag with <type> / <param> tags in vk.xml,
-# using makeVulkanTypeFromXMLTag
-# 2. User-defined instances with makeVulkanTypeSimple.
-class VulkanType(object):
-
- def __init__(self):
- self.parent: Optional[VulkanType] = None
- self.typeName: str = ""
-
- self.isTransformed = False
-
- self.paramName: Optional[str] = None
-
- self.lenExpr: Optional[str] = None # Value of the `len` attribute in the spec
- self.isOptional: bool = False
- self.optionalStr: Optional[str] = None # Value of the `optional` attribute in the spec
-
- self.isConst = False
-
- # "" means it's not a static array, otherwise this is the total size of
- # all elements. e.g. staticArrExpr of "x[3][2][8]" will be "((3)*(2)*(8))".
- self.staticArrExpr = ""
- # "" means it's not a static array, otherwise it's the raw expression
- # of static array size, which can be one-dimensional or multi-dimensional.
- self.rawStaticArrExpr = ""
-
- self.pointerIndirectionLevels = 0 # 0 means not pointer
- self.isPointerToConstPointer = False
-
- self.primitiveEncodingSize = None
-
- self.deviceMemoryInfoParameterIndices = None
-
- # Annotations
- # Environment annotation for binding current
- # variables to sub-structures
- self.binds = {}
-
- # Device memory annotations
-
- # self.deviceMemoryAttrib/Val stores
- # device memory info attributes from the XML.
- # devicememoryhandle
- # devicememoryoffset
- # devicememorysize
- # devicememorytypeindex
- # devicememorytypebits
- self.deviceMemoryAttrib = None
- self.deviceMemoryVal = None
-
- # Filter annotations
- self.filterVar = None
- self.filterVals = None
- self.filterFunc = None
- self.filterOtherwise = None
-
- # Stream feature
- self.streamFeature = None
-
- # All other annotations
- self.attribs = {}
-
- self.nonDispatchableHandleCreate = False
- self.nonDispatchableHandleDestroy = False
- self.dispatchHandle = False
- self.dispatchableHandleCreate = False
- self.dispatchableHandleDestroy = False
-
-
- def __str__(self,):
- return ("(vulkantype %s %s paramName %s len %s optional? %s "
- "staticArrExpr %s)") % (
- self.typeName + ("*" * self.pointerIndirectionLevels) +
- ("ptr2constptr" if self.isPointerToConstPointer else ""), "const"
- if self.isConst else "nonconst", self.paramName, self.lenExpr,
- self.isOptional, self.staticArrExpr)
-
- def isString(self):
- return self.pointerIndirectionLevels == 1 and (self.typeName == "char")
-
- def isArrayOfStrings(self):
- return self.isPointerToConstPointer and (self.typeName == "char")
-
- def primEncodingSize(self):
- return self.primitiveEncodingSize
-
- # Utility functions to make codegen life easier.
- # This method derives the correct "count" expression if possible.
- # Otherwise, returns None or "null-terminated" if a string.
- def getLengthExpression(self):
- if self.staticArrExpr != "":
- return self.staticArrExpr
- if self.lenExpr:
- return self.lenExpr
- return None
-
- # Can we just pass this to functions expecting T*
- def accessibleAsPointer(self):
- if self.staticArrExpr != "":
- return True
- if self.pointerIndirectionLevels > 0:
- return True
- return False
-
- # Rough attempt to infer where a type could be an output.
- # Good for inferring which things need to be marshaled in
- # versus marshaled out for Vulkan API calls
- def possiblyOutput(self,):
- return self.pointerIndirectionLevels > 0 and (not self.isConst)
-
- def isVoidWithNoSize(self,):
- return self.typeName == "void" and self.pointerIndirectionLevels == 0
-
- def getCopy(self,):
- return copy(self)
-
- def getTransformed(self, isConstChoice=None, ptrIndirectionChoice=None):
- res = self.getCopy()
-
- if isConstChoice is not None:
- res.isConst = isConstChoice
- if ptrIndirectionChoice is not None:
- res.pointerIndirectionLevels = ptrIndirectionChoice
-
- return res
-
- def getWithCustomName(self):
- return self.getTransformed(
- ptrIndirectionChoice=self.pointerIndirectionLevels + 1)
-
- def getForAddressAccess(self):
- return self.getTransformed(
- ptrIndirectionChoice=self.pointerIndirectionLevels + 1)
-
- def getForValueAccess(self):
- if self.typeName == "void" and self.pointerIndirectionLevels == 1:
- asUint8Type = self.getCopy()
- asUint8Type.typeName = "uint8_t"
- return asUint8Type.getForValueAccess()
- return self.getTransformed(
- ptrIndirectionChoice=self.pointerIndirectionLevels - 1)
-
- def getForNonConstAccess(self):
- return self.getTransformed(isConstChoice=False)
-
- def withModifiedName(self, newName):
- res = self.getCopy()
- res.paramName = newName
- return res
-
- def isNextPointer(self):
- return self.paramName == "pNext"
-
- def isSigned(self):
- return self.typeName in ["int", "int8_t", "int16_t", "int32_t", "int64_t"]
-
- def isEnum(self, typeInfo):
- return typeInfo.categoryOf(self.typeName) == "enum"
-
- def isBitmask(self, typeInfo):
- return typeInfo.categoryOf(self.typeName) == "enum"
-
- # Only deals with 'core' handle types here.
- def isDispatchableHandleType(self):
- return self.typeName in DISPATCHABLE_HANDLE_TYPES
-
- def isNonDispatchableHandleType(self):
- return self.typeName in NON_DISPATCHABLE_HANDLE_TYPES
-
- def isHandleType(self):
- return self.isDispatchableHandleType() or \
- self.isNonDispatchableHandleType()
-
- def isCreatedBy(self, api):
- if self.typeName in HANDLE_INFO.keys():
- nonKhrRes = HANDLE_INFO[self.typeName].isCreateApi(api.name)
- if nonKhrRes:
- return True
- if len(api.name) > 3 and "KHR" == api.name[-3:]:
- return HANDLE_INFO[self.typeName].isCreateApi(api.name[:-3])
-
- if self.typeName == "VkImage" and api.name == "vkCreateImageWithRequirementsGOOGLE":
- return True
-
- if self.typeName == "VkBuffer" and api.name == "vkCreateBufferWithRequirementsGOOGLE":
- return True
-
- return False
-
- def isDestroyedBy(self, api):
- if self.typeName in HANDLE_INFO.keys():
- nonKhrRes = HANDLE_INFO[self.typeName].isDestroyApi(api.name)
- if nonKhrRes:
- return True
- if len(api.name) > 3 and "KHR" == api.name[-3:]:
- return HANDLE_INFO[self.typeName].isDestroyApi(api.name[:-3])
-
- return False
-
- def isSimpleValueType(self, typeInfo):
- if typeInfo.isCompoundType(self.typeName):
- return False
- if self.isString() or self.isArrayOfStrings():
- return False
- if self.staticArrExpr or self.pointerIndirectionLevels > 0:
- return False
- return True
-
- def getStructEnumExpr(self,):
- return None
-
- def getPrintFormatSpecifier(self):
- kKnownTypePrintFormatSpecifiers = {
- 'float': '%f',
- 'int': '%d',
- 'int32_t': '%d',
- 'size_t': '%ld',
- 'uint16_t': '%d',
- 'uint32_t': '%d',
- 'uint64_t': '%ld',
- 'VkBool32': '%d',
- 'VkDeviceSize': '%ld',
- 'VkFormat': '%d',
- 'VkImageLayout': '%d',
- }
-
- if self.pointerIndirectionLevels > 0 or self.isHandleType():
- return '%p'
-
- if self.typeName in kKnownTypePrintFormatSpecifiers:
- return kKnownTypePrintFormatSpecifiers[self.typeName]
-
- if self.typeName.endswith('Flags'):
- # Based on `typedef uint32_t VkFlags;`
- return '%d'
-
- return None
- def isOptionalPointer(self) -> bool:
- return self.isOptional and \
- self.pointerIndirectionLevels > 0 and \
- (not self.isNextPointer())
-
-
-# Is an S-expression w/ the following spec:
-# From https://gist.github.com/pib/240957
-class Atom(object):
- def __init__(self, name):
- self.name = name
- def __repr__(self,):
- return self.name
-
-def parse_sexp(sexp):
- atom_end = set('()"\'') | set(whitespace)
- stack, i, length = [[]], 0, len(sexp)
- while i < length:
- c = sexp[i]
-
- reading = type(stack[-1])
- if reading == list:
- if c == '(': stack.append([])
- elif c == ')':
- stack[-2].append(stack.pop())
- if stack[-1][0] == ('quote',): stack[-2].append(stack.pop())
- elif c == '"': stack.append('')
- elif c == "'": stack.append([('quote',)])
- elif c in whitespace: pass
- else: stack.append(Atom(c))
- elif reading == str:
- if c == '"':
- stack[-2].append(stack.pop())
- if stack[-1][0] == ('quote',): stack[-2].append(stack.pop())
- elif c == '\\':
- i += 1
- stack[-1] += sexp[i]
- else: stack[-1] += c
- elif reading == Atom:
- if c in atom_end:
- atom = stack.pop()
- if atom.name[0].isdigit(): stack[-1].append(eval(atom.name))
- else: stack[-1].append(atom)
- if stack[-1][0] == ('quote',): stack[-2].append(stack.pop())
- continue
- else: stack[-1] = Atom(stack[-1].name + c)
- i += 1
-
- return stack.pop()
-
-class FuncExprVal(object):
- def __init__(self, val):
- self.val = val
- def __repr__(self,):
- return self.val.__repr__()
-
-class FuncExpr(object):
- def __init__(self, name, args):
- self.name = name
- self.args = args
- def __repr__(self,):
- if len(self.args) == 0:
- return "(%s)" % (self.name.__repr__())
- else:
- return "(%s %s)" % (self.name.__repr__(), " ".join(map(lambda x: x.__repr__(), self.args)))
-
-class FuncLambda(object):
- def __init__(self, vs, body):
- self.vs = vs
- self.body = body
- def __repr__(self,):
- return "(L (%s) %s)" % (" ".join(map(lambda x: x.__repr__(), self.vs)), self.body.__repr__())
-
-class FuncLambdaParam(object):
- def __init__(self, name, typ):
- self.name = name
- self.typ = typ
- def __repr__(self,):
- return "%s : %s" % (self.name, self.typ)
-
-def parse_func_expr(parsed_sexp):
- if len(parsed_sexp) != 1:
- print("Error: parsed # expressions != 1: %d" % (len(parsed_sexp)))
- raise
-
- e = parsed_sexp[0]
-
- def parse_lambda_param(e):
- return FuncLambdaParam(e[0].name, e[1].name)
-
- def parse_one(exp):
- if list == type(exp):
- if "lambda" == exp[0].__repr__():
- return FuncLambda(list(map(parse_lambda_param, exp[1])), parse_one(exp[2]))
- else:
- return FuncExpr(exp[0], list(map(parse_one, exp[1:])))
- else:
- return FuncExprVal(exp)
-
- return parse_one(e)
-
-def parseFilterFuncExpr(expr):
- res = parse_func_expr(parse_sexp(expr))
- print("parseFilterFuncExpr: parsed %s" % res)
- return res
-
-def parseLetBodyExpr(expr):
- res = parse_func_expr(parse_sexp(expr))
- print("parseLetBodyExpr: parsed %s" % res)
- return res
-
-
-def makeVulkanTypeFromXMLTag(typeInfo, tag: Element) -> VulkanType:
- res = VulkanType()
-
- # Process the length expression
-
- if tag.attrib.get("len") is not None:
- lengths = tag.attrib.get("len").split(",")
- res.lenExpr = lengths[0]
-
- # Calculate static array expression
-
- nametag = tag.find("name")
- enumtag = tag.find("enum")
-
- if enumtag is not None:
- res.staticArrExpr = enumtag.text
- elif nametag is not None:
- res.rawStaticArrExpr = noneStr(nametag.tail)
-
- dimensions = res.rawStaticArrExpr.count('[')
- if dimensions == 1:
- res.staticArrExpr = res.rawStaticArrExpr[1:-1]
- elif dimensions > 1:
- arraySizes = res.rawStaticArrExpr[1:-1].split('][')
- res.staticArrExpr = '(' + \
- '*'.join(f'({size})' for size in arraySizes) + ')'
-
- # Determine const
-
- beforeTypePart = noneStr(tag.text)
-
- if "const" in beforeTypePart:
- res.isConst = True
-
- # Calculate type and pointer info
- for elem in tag:
- if elem.tag == "name":
- res.paramName = elem.text
- if elem.tag == "type":
- duringTypePart = noneStr(elem.text)
- afterTypePart = noneStr(elem.tail)
- # Now we know enough to fill some stuff in
- res.typeName = duringTypePart
-
- if res.typeName in TRANSFORMED_TYPES:
- res.isTransformed = True
-
- # This only handles pointerIndirectionLevels == 2
- # along with optional constant pointer for the inner part.
- for c in afterTypePart:
- if c == "*":
- res.pointerIndirectionLevels += 1
- if "const" in afterTypePart and res.pointerIndirectionLevels == 2:
- res.isPointerToConstPointer = True
-
- # If void*, treat like it's not a pointer
- # if duringTypePart == "void":
- # res.pointerIndirectionLevels -= 1
-
- # Calculate optionality (based on validitygenerator.py)
- if tag.attrib.get("optional") is not None:
- res.isOptional = True
- res.optionalStr = tag.attrib.get("optional")
-
- # If no validity is being generated, it usually means that
- # validity is complex and not absolute, so let's say yes.
- if tag.attrib.get("noautovalidity") is not None:
- res.isOptional = True
-
- # If this is a structure extension, it is optional.
- if tag.attrib.get("structextends") is not None:
- res.isOptional = True
-
- # If this is a pNext pointer, it is optional.
- if res.paramName == "pNext":
- res.isOptional = True
-
- res.primitiveEncodingSize = typeInfo.getPrimitiveEncodingSize(res.typeName)
-
- # Annotations: Environment binds
- if tag.attrib.get("binds") is not None:
- bindPairs = map(lambda x: x.strip(), tag.attrib.get("binds").split(","))
- bindPairsSplit = map(lambda p: p.split(":"), bindPairs)
- res.binds = dict(map(lambda sp: (sp[0].strip(), sp[1].strip()), bindPairsSplit))
-
- # Annotations: Device memory
- for k in DEVICE_MEMORY_INFO_KEYS:
- if tag.attrib.get(k) is not None:
- res.deviceMemoryAttrib = k
- res.deviceMemoryVal = tag.attrib.get(k)
- break
-
- # Annotations: Filters
- if tag.attrib.get("filterVar") is not None:
- res.filterVar = tag.attrib.get("filterVar").strip()
-
- if tag.attrib.get("filterVals") is not None:
- res.filterVals = \
- list(map(lambda v: v.strip(),
- tag.attrib.get("filterVals").strip().split(",")))
- print("Filtervals: %s" % res.filterVals)
-
- if tag.attrib.get("filterFunc") is not None:
- res.filterFunc = parseFilterFuncExpr(tag.attrib.get("filterFunc"))
-
- if tag.attrib.get("filterOtherwise") is not None:
- res.Otherwise = tag.attrib.get("filterOtherwise")
-
- # store all other attribs here
- res.attribs = dict(tag.attrib)
-
- return res
-
-
-def makeVulkanTypeSimple(isConst,
- typeName,
- ptrIndirectionLevels,
- paramName=None):
- res = VulkanType()
-
- res.typeName = typeName
- res.isConst = isConst
- res.pointerIndirectionLevels = ptrIndirectionLevels
- res.isPointerToConstPointer = False
- res.paramName = paramName
- res.primitiveEncodingSize = None
-
- return res
-
-# A class for holding the parameter indices corresponding to various
-# attributes about a VkDeviceMemory, such as the handle, size, offset, etc.
-class DeviceMemoryInfoParameterIndices(object):
- def __init__(self, handle, offset, size, typeIndex, typeBits):
- self.handle = handle
- self.offset = offset
- self.size = size
- self.typeIndex = typeIndex
- self.typeBits = typeBits
-
-# initializes DeviceMemoryInfoParameterIndices for each
-# abstract VkDeviceMemory encountered over |parameters|
-def initDeviceMemoryInfoParameterIndices(parameters):
-
- use = False
- deviceMemoryInfoById = {}
-
- for (i, p) in enumerate(parameters):
- a = p.deviceMemoryAttrib
- if not a:
- continue
-
- if a in DEVICE_MEMORY_INFO_KEYS:
- use = True
- deviceMemoryInfoById[p.deviceMemoryVal] = DeviceMemoryInfoParameterIndices(
- None, None, None, None, None)
-
- for (i, p) in enumerate(parameters):
- a = p.deviceMemoryAttrib
- if not a:
- continue
-
- info = deviceMemoryInfoById[p.deviceMemoryVal]
-
- if a == "devicememoryhandle":
- info.handle = i
- if a == "devicememoryoffset":
- info.offset = i
- if a == "devicememorysize":
- info.size = i
- if a == "devicememorytypeindex":
- info.typeIndex = i
- if a == "devicememorytypebits":
- info.typeBits = i
-
- if not use:
- return None
-
- return deviceMemoryInfoById
-
-# Classes for describing aggregate types (unions, structs) and API calls.
-class VulkanCompoundType(object):
-
- def __init__(self, name: str, members: List[VulkanType], isUnion=False, structEnumExpr=None, structExtendsExpr=None, feature=None, initialEnv={}, optional=None):
- self.name: str = name
- self.typeName: str = name
- self.members: List[VulkanType] = members
- self.environment = initialEnv
- self.isUnion = isUnion
- self.structEnumExpr = structEnumExpr
- self.structExtendsExpr = structExtendsExpr
- self.feature = feature
- self.deviceMemoryInfoParameterIndices = initDeviceMemoryInfoParameterIndices(self.members)
- self.isTransformed = name in TRANSFORMED_TYPES
- self.copy = None
- self.optionalStr = optional
-
- def initCopies(self):
- self.copy = self
-
- for m in self.members:
- m.parent = self.copy
-
- def getMember(self, memberName) -> Optional[VulkanType]:
- for m in self.members:
- if m.paramName == memberName:
- return m
- return None
-
- def getStructEnumExpr(self,):
- return self.structEnumExpr
-
-class VulkanAPI(object):
-
- def __init__(self, name: str, retType: VulkanType, parameters, origName=None):
- self.name: str = name
- self.origName = name
- self.retType: VulkanType = retType
- self.parameters: List[VulkanType] = parameters
-
- self.deviceMemoryInfoParameterIndices = initDeviceMemoryInfoParameterIndices(self.parameters)
-
- self.copy = None
-
- self.isTransformed = name in TRANSFORMED_TYPES
-
- if origName:
- self.origName = origName
-
- def initCopies(self):
- self.copy = self
-
- for m in self.parameters:
- m.parent = self.copy
-
- def getCopy(self,):
- return copy(self)
-
- def getParameter(self, parameterName):
- for p in self.parameters:
- if p.paramName == parameterName:
- return p
- return None
-
- def withModifiedName(self, newName):
- res = VulkanAPI(newName, self.retType, self.parameters)
- return res
-
- def getRetVarExpr(self):
- if self.retType.typeName == "void":
- return None
- return "%s_%s_return" % (self.name, self.retType.typeName)
-
- def getRetTypeExpr(self):
- return self.retType.typeName
-
- def withCustomParameters(self, customParams):
- res = self.getCopy()
- res.parameters = customParams
- return res
-
- def withCustomReturnType(self, retType):
- res = self.getCopy()
- res.retType = retType
- return res
-
-# Whether or not special handling of virtual elements
-# such as VkDeviceMemory is needed.
-def vulkanTypeNeedsTransform(structOrApi):
- return structOrApi.deviceMemoryInfoParameterIndices != None
-
-def vulkanTypeGetNeededTransformTypes(structOrApi):
- res = []
- if structOrApi.deviceMemoryInfoParameterIndices != None:
- res.append("devicememory")
- return res
-
-def vulkanTypeforEachSubType(structOrApi, f):
- toLoop = None
- if type(structOrApi) == VulkanCompoundType:
- toLoop = structOrApi.members
- if type(structOrApi) == VulkanAPI:
- toLoop = structOrApi.parameters
-
- for (i, x) in enumerate(toLoop):
- f(i, x)
-
-# Parses everything about Vulkan types into a Python readable format.
-class VulkanTypeInfo(object):
-
- def __init__(self, generator):
- self.generator = generator
- self.categories: Set[str] = set([])
-
- # Tracks what Vulkan type is part of what category.
- self.typeCategories: Dict[str, str] = {}
-
- # Tracks the primitive encoding size for each type, if applicable.
- self.encodingSizes: Dict[str, Optional[int]] = {}
-
- self.structs: Dict[str, VulkanCompoundType] = {}
- self.apis: Dict[str, VulkanAPI] = {}
-
- # Maps bitmask types to the enum type used for the flags
- # E.g. "VkImageAspectFlags" -> "VkImageAspectFlagBits"
- self.bitmasks: Dict[str, str] = {}
-
- # Maps all enum names to their values.
- # For aliases, the value is the name of the canonical enum
- self.enumValues: Dict[str, Union[int, str]] = {}
-
- self.feature = None
-
- def initType(self, name: str, category: str):
- self.categories.add(category)
- self.typeCategories[name] = category
- self.encodingSizes[name] = self.setPrimitiveEncodingSize(name)
-
- def categoryOf(self, name):
- return self.typeCategories[name]
-
- def getPrimitiveEncodingSize(self, name):
- return self.encodingSizes[name]
-
- # Queries relating to categories of Vulkan types.
- def isHandleType(self, name):
- return self.typeCategories.get(name) == "handle"
-
- def isCompoundType(self, name: str):
- return self.typeCategories.get(name) in ["struct", "union"]
-
- # Gets the best size in bytes
- # for encoding/decoding a particular Vulkan type.
- # If not applicable, returns None.
- def setPrimitiveEncodingSize(self, name: str) -> Optional[int]:
- baseEncodingSizes = {
- "void": 8,
- "char": 1,
- "float": 4,
- "uint8_t": 1,
- "uint16_t": 2,
- "uint32_t": 4,
- "uint64_t": 8,
- "int": 4,
- "int8_t": 1,
- "int16_t": 2,
- "int32_t": 4,
- "int64_t": 8,
- "size_t": 8,
- "ssize_t": 8,
- "VkBool32": 4,
- }
-
- if name in baseEncodingSizes:
- return baseEncodingSizes[name]
-
- category = self.typeCategories[name]
-
- if category in [None, "api", "include", "define", "struct", "union"]:
- return None
-
- # Handles are pointers so they must be 8 bytes. Basetype includes VkDeviceSize which is 8 bytes.
- if category in ["handle", "basetype", "funcpointer"]:
- return 8
-
- if category in ["enum", "bitmask"]:
- return 4
-
- def isNonAbiPortableType(self, typeName):
- if typeName in EXPLICITLY_ABI_PORTABLE_TYPES:
- return False
-
- if typeName in EXPLICITLY_ABI_NON_PORTABLE_TYPES:
- return True
-
- category = self.typeCategories[typeName]
- return category in NON_ABI_PORTABLE_TYPE_CATEGORIES
-
- def onBeginFeature(self, featureName, featureType):
- self.feature = featureName
-
- def onEndFeature(self):
- self.feature = None
-
- def onGenType(self, typeinfo, name, alias):
- category = typeinfo.elem.get("category")
- self.initType(name, category)
-
- if category in ["struct", "union"]:
- self.onGenStruct(typeinfo, name, alias)
-
- if category == "bitmask":
- self.bitmasks[name] = typeinfo.elem.get("requires")
-
- def onGenStruct(self, typeinfo, typeName, alias):
- if not alias:
- members: List[VulkanType] = []
-
- structExtendsExpr = typeinfo.elem.get("structextends")
-
- structEnumExpr = None
-
- initialEnv = {}
- envStr = typeinfo.elem.get("exists")
- if envStr != None:
- comma_separated = envStr.split(",")
- name_type_pairs = map(lambda cs: tuple(map(lambda t: t.strip(), cs.split(":"))), comma_separated)
- for (name, typ) in name_type_pairs:
- initialEnv[name] = {
- "type" : typ,
- "binding" : None,
- "structmember" : False,
- "body" : None,
- }
-
- letenvStr = typeinfo.elem.get("let")
- if letenvStr != None:
- comma_separated = letenvStr.split(",")
- name_body_pairs = map(lambda cs: tuple(map(lambda t: t.strip(), cs.split(":"))), comma_separated)
- for (name, body) in name_body_pairs:
- initialEnv[name] = {
- "type" : "uint32_t",
- "binding" : name,
- "structmember" : False,
- "body" : parseLetBodyExpr(body)
- }
-
- for member in typeinfo.elem.findall(".//member"):
- vulkanType = makeVulkanTypeFromXMLTag(self, member)
- initialEnv[vulkanType.paramName] = {
- "type": vulkanType.typeName,
- "binding": vulkanType.paramName,
- "structmember": True,
- "body": None,
- }
- members.append(vulkanType)
- if vulkanType.typeName == "VkStructureType" and \
- member.get("values"):
- structEnumExpr = member.get("values")
-
- self.structs[typeName] = \
- VulkanCompoundType(
- typeName,
- members,
- isUnion = self.categoryOf(typeName) == "union",
- structEnumExpr = structEnumExpr,
- structExtendsExpr = structExtendsExpr,
- feature = self.feature,
- initialEnv = initialEnv,
- optional = typeinfo.elem.get("optional", None))
- self.structs[typeName].initCopies()
-
- def onGenGroup(self, groupinfo, groupName, _alias=None):
- self.initType(groupName, "enum")
- enums = groupinfo.elem.findall("enum")
- for enum in enums:
- intVal, strVal = self.generator.enumToValue(enum, True)
- self.enumValues[enum.get('name')] = intVal if intVal is not None else strVal
-
-
- def onGenEnum(self, enuminfo, name: str, alias):
- self.initType(name, "enum")
- value: str = enuminfo.elem.get("value")
- if value and value.isdigit():
- self.enumValues[name] = int(value)
- elif value and value[0] == '"' and value[-1] == '"':
- self.enumValues[name] = value[1:-1]
- elif alias is not None:
- self.enumValues[name] = alias
- else:
- # There's about a dozen cases of using the bitwise NOT operator (e.g.: `(~0U)`, `(~0ULL)`)
- # to concisely represent large values. Just ignore them for now.
- # In the future, we can add a lookup table to convert these to int
- return
-
- def onGenCmd(self, cmdinfo, name, _alias):
- self.initType(name, "api")
-
- proto = cmdinfo.elem.find("proto")
- params = cmdinfo.elem.findall("param")
-
- self.apis[name] = \
- VulkanAPI(
- name,
- makeVulkanTypeFromXMLTag(self, proto),
- list(map(lambda p: makeVulkanTypeFromXMLTag(self, p),
- params)))
- self.apis[name].initCopies()
-
- def onEnd(self):
- pass
-
-def hasNullOptionalStringFeature(forEachType):
- return (hasattr(forEachType, "onCheckWithNullOptionalStringFeature")) and \
- (hasattr(forEachType, "endCheckWithNullOptionalStringFeature")) and \
- (hasattr(forEachType, "finalCheckWithNullOptionalStringFeature"))
-
-
-# General function to iterate over a vulkan type and call code that processes
-# each of its sub-components, if any.
-def iterateVulkanType(typeInfo: VulkanTypeInfo, vulkanType: VulkanType, forEachType):
- if not vulkanType.isArrayOfStrings():
- if vulkanType.isPointerToConstPointer:
- return False
-
- forEachType.registerTypeInfo(typeInfo)
-
- needCheck = vulkanType.isOptionalPointer()
-
- if typeInfo.isCompoundType(vulkanType.typeName) and not vulkanType.isNextPointer():
-
- if needCheck:
- forEachType.onCheck(vulkanType)
-
- forEachType.onCompoundType(vulkanType)
-
- if needCheck:
- forEachType.endCheck(vulkanType)
-
- else:
- if vulkanType.isString():
- if needCheck and hasNullOptionalStringFeature(forEachType):
- forEachType.onCheckWithNullOptionalStringFeature(vulkanType)
- forEachType.onString(vulkanType)
- forEachType.endCheckWithNullOptionalStringFeature(vulkanType)
- forEachType.onString(vulkanType)
- forEachType.finalCheckWithNullOptionalStringFeature(vulkanType)
- elif needCheck:
- forEachType.onCheck(vulkanType)
- forEachType.onString(vulkanType)
- forEachType.endCheck(vulkanType)
- else:
- forEachType.onString(vulkanType)
-
- elif vulkanType.isArrayOfStrings():
- forEachType.onStringArray(vulkanType)
-
- elif vulkanType.staticArrExpr:
- forEachType.onStaticArr(vulkanType)
-
- elif vulkanType.isNextPointer():
- if needCheck:
- forEachType.onCheck(vulkanType)
- forEachType.onStructExtension(vulkanType)
- if needCheck:
- forEachType.endCheck(vulkanType)
-
- elif vulkanType.pointerIndirectionLevels > 0:
- if needCheck:
- forEachType.onCheck(vulkanType)
- forEachType.onPointer(vulkanType)
- if needCheck:
- forEachType.endCheck(vulkanType)
-
- else:
- forEachType.onValue(vulkanType)
-
- return True
-
-class VulkanTypeIterator(object):
- def __init__(self,):
- self.typeInfo = None
-
- def registerTypeInfo(self, typeInfo):
- self.typeInfo = typeInfo
-
-def vulkanTypeGetStructFieldLengthInfo(structInfo, vulkanType):
- def getSpecialCaseVulkanStructFieldLength(structInfo, vulkanType):
- cases = [
- {
- "structName": "VkShaderModuleCreateInfo",
- "field": "pCode",
- "lenExpr": "codeSize",
- "postprocess": lambda expr: "(%s / 4)" % expr
- },
- {
- "structName": "VkPipelineMultisampleStateCreateInfo",
- "field": "pSampleMask",
- "lenExpr": "rasterizationSamples",
- "postprocess": lambda expr: "(((%s) + 31) / 32)" % expr
- },
- ]
-
- for c in cases:
- if (structInfo.name, vulkanType.paramName) == (c["structName"], c["field"]):
- return c
-
- return None
-
- specialCaseAccess = getSpecialCaseVulkanStructFieldLength(structInfo, vulkanType)
-
- if specialCaseAccess is not None:
- return specialCaseAccess
-
- lenExpr = vulkanType.getLengthExpression()
-
- if lenExpr is None:
- return None
-
- return {
- "structName": structInfo.name,
- "field": vulkanType.typeName,
- "lenExpr": lenExpr,
- "postprocess": lambda expr: expr}
-
-
-class VulkanTypeProtobufInfo(object):
- def __init__(self, typeInfo, structInfo, vulkanType):
- self.needsMessage = typeInfo.isCompoundType(vulkanType.typeName)
- self.isRepeatedString = vulkanType.isArrayOfStrings()
- self.isString = vulkanType.isString() or (
- vulkanType.typeName == "char" and (vulkanType.staticArrExpr != ""))
-
- if structInfo is not None:
- self.lengthInfo = vulkanTypeGetStructFieldLengthInfo(
- structInfo, vulkanType)
- else:
- self.lengthInfo = vulkanType.getLengthExpression()
-
- self.protobufType = None
- self.origTypeCategory = typeInfo.categoryOf(vulkanType.typeName)
-
- self.isExtensionStruct = \
- vulkanType.typeName == "void" and \
- vulkanType.pointerIndirectionLevels > 0 and \
- vulkanType.paramName == "pNext"
-
- if self.needsMessage:
- return
-
- if typeInfo.categoryOf(vulkanType.typeName) in ["enum", "bitmask"]:
- self.protobufType = "uint32"
-
- if typeInfo.categoryOf(vulkanType.typeName) in ["funcpointer", "handle", "define"]:
- self.protobufType = "uint64"
-
- if typeInfo.categoryOf(vulkanType.typeName) in ["basetype"]:
- baseTypeMapping = {
- "VkFlags" : "uint32",
- "VkBool32" : "uint32",
- "VkDeviceSize" : "uint64",
- "VkSampleMask" : "uint32",
- }
- self.protobufType = baseTypeMapping[vulkanType.typeName]
-
- if typeInfo.categoryOf(vulkanType.typeName) == None:
-
- otherTypeMapping = {
- "void" : "uint64",
- "char" : "uint8",
- "size_t" : "uint64",
- "float" : "float",
- "uint8_t" : "uint32",
- "uint16_t" : "uint32",
- "int32_t" : "int32",
- "uint32_t" : "uint32",
- "uint64_t" : "uint64",
- "VkDeviceSize" : "uint64",
- "VkSampleMask" : "uint32",
- }
-
- if vulkanType.typeName in otherTypeMapping:
- self.protobufType = otherTypeMapping[vulkanType.typeName]
- else:
- self.protobufType = "uint64"
-
-
- protobufCTypeMapping = {
- "uint8" : "uint8_t",
- "uint32" : "uint32_t",
- "int32" : "int32_t",
- "uint64" : "uint64_t",
- "float" : "float",
- "string" : "const char*",
- }
-
- self.protobufCType = protobufCTypeMapping[self.protobufType]
-