Update for Vulkan-Docs 1.4.319
This commit is contained in:
parent
b39ab380a4
commit
10739e8e00
38 changed files with 184363 additions and 135674 deletions
|
|
@ -9,7 +9,7 @@ import os
|
|||
import tempfile
|
||||
from vulkan_object import (VulkanObject,
|
||||
Extension, Version, Deprecate, Handle, Param, Queues, CommandScope, Command,
|
||||
EnumField, Enum, Flag, Bitmask, Flags, Member, Struct,
|
||||
EnumField, Enum, Flag, Bitmask, ExternSync, Flags, Member, Struct,
|
||||
FormatComponent, FormatPlane, Format,
|
||||
SyncSupport, SyncEquivalent, SyncStage, SyncAccess, SyncPipelineStage, SyncPipeline,
|
||||
SpirvEnables, Spirv)
|
||||
|
|
@ -35,6 +35,30 @@ def intIfGet(elem, name):
|
|||
def boolGet(elem, name) -> bool:
|
||||
return elem.get(name) is not None and elem.get(name) == "true"
|
||||
|
||||
def externSyncGet(elem):
|
||||
value = elem.get('externsync')
|
||||
if value is None:
|
||||
return (ExternSync.NONE, None)
|
||||
if value == 'true':
|
||||
return (ExternSync.ALWAYS, None)
|
||||
if value == 'maybe':
|
||||
return (ExternSync.MAYBE, None)
|
||||
|
||||
# There are no cases where multiple members of the param are marked as
|
||||
# externsync. Supporting that with maybe: requires more than
|
||||
# ExternSync.SUBTYPE_MAYBE (which is only one bit of information), which is
|
||||
# not currently done as there are no users.
|
||||
#
|
||||
# If this assert is hit, please consider simplifying the design such that
|
||||
# externsync can move to the struct itself and so external synchronization
|
||||
# requirements do not depend on the context.
|
||||
assert ',' not in value
|
||||
|
||||
if value.startswith('maybe:'):
|
||||
return (ExternSync.SUBTYPE_MAYBE, value.removeprefix('maybe:'))
|
||||
return (ExternSync.SUBTYPE, value)
|
||||
|
||||
|
||||
def getQueues(elem) -> Queues:
|
||||
queues = 0
|
||||
queues_list = splitIfGet(elem, 'queues')
|
||||
|
|
@ -139,6 +163,10 @@ class BaseGenerator(OutputGenerator):
|
|||
self.currentExtension = None
|
||||
self.currentVersion = None
|
||||
|
||||
# We need to flag extensions that we ignore because they are disabled or not
|
||||
# supported in the target API(s)
|
||||
self.unsupportedExtension = False
|
||||
|
||||
# Will map alias to promoted name
|
||||
# ex. ['VK_FILTER_CUBIC_IMG' : 'VK_FILTER_CUBIC_EXT']
|
||||
# When generating any code, there is no reason so use the old name
|
||||
|
|
@ -437,6 +465,17 @@ class BaseGenerator(OutputGenerator):
|
|||
name = interface.get('name')
|
||||
|
||||
if interface.tag == 'extension':
|
||||
# Generator scripts built on BaseGenerator do not handle the `supported` attribute of extensions
|
||||
# therefore historically the `generate_source.py` in individual ecosystem components hacked the
|
||||
# registry by removing non-applicable or disabled extensions from the loaded XML already before
|
||||
# reg.py parsed it. That broke the general behavior of reg.py for certain use cases so we now
|
||||
# filter extensions here instead (after parsing) in order to no longer need the filtering hack
|
||||
# in downstream `generate_source.py` scripts.
|
||||
enabledApiList = [ globalApiName ] + ([] if mergedApiNames is None else mergedApiNames.split(','))
|
||||
if (sup := interface.get('supported')) is not None and all(api not in sup.split(',') for api in enabledApiList):
|
||||
self.unsupportedExtension = True
|
||||
return
|
||||
|
||||
instance = interface.get('type') == 'instance'
|
||||
device = not instance
|
||||
depends = interface.get('depends')
|
||||
|
|
@ -468,12 +507,17 @@ class BaseGenerator(OutputGenerator):
|
|||
OutputGenerator.endFeature(self)
|
||||
self.currentExtension = None
|
||||
self.currentVersion = None
|
||||
self.unsupportedExtension = False
|
||||
|
||||
#
|
||||
# All <command> from XML
|
||||
def genCmd(self, cmdinfo, name, alias):
|
||||
OutputGenerator.genCmd(self, cmdinfo, name, alias)
|
||||
|
||||
# Do not include APIs from unsupported extensions
|
||||
if self.unsupportedExtension:
|
||||
return
|
||||
|
||||
params = []
|
||||
for param in cmdinfo.elem.findall('param'):
|
||||
paramName = param.find('name').text
|
||||
|
|
@ -505,12 +549,8 @@ class BaseGenerator(OutputGenerator):
|
|||
optional = optionalValues is not None and optionalValues[0].lower() == "true"
|
||||
optionalPointer = optionalValues is not None and len(optionalValues) > 1 and optionalValues[1].lower() == "true"
|
||||
|
||||
# externsync will be 'true' or expression
|
||||
# if expression, it should be same as 'true'
|
||||
externSync = boolGet(param, 'externsync')
|
||||
externSyncPointer = None if externSync else splitIfGet(param, 'externsync')
|
||||
if not externSync and externSyncPointer is not None:
|
||||
externSync = True
|
||||
# externsync will be 'true', 'maybe', '<expression>' or 'maybe:<expression>'
|
||||
(externSync, externSyncPointer) = externSyncGet(param)
|
||||
|
||||
params.append(Param(paramName, paramAlias, paramType, paramFullType, paramNoautovalidity,
|
||||
paramConst, length, nullTerminated, pointer, fixedSizeArray,
|
||||
|
|
@ -566,6 +606,10 @@ class BaseGenerator(OutputGenerator):
|
|||
# List the enum for the commands
|
||||
# TODO - Seems empty groups like `VkDeviceDeviceMemoryReportCreateInfoEXT` do not show up in here
|
||||
def genGroup(self, groupinfo, groupName, alias):
|
||||
# Do not include APIs from unsupported extensions
|
||||
if self.unsupportedExtension:
|
||||
return
|
||||
|
||||
# There can be case where the Enum/Bitmask is in a protect, but the individual
|
||||
# fields also have their own protect
|
||||
groupProtect = self.currentExtension.protect if hasattr(self.currentExtension, 'protect') and self.currentExtension.protect is not None else None
|
||||
|
|
@ -580,6 +624,15 @@ class BaseGenerator(OutputGenerator):
|
|||
for elem in enumElem.findall('enum'):
|
||||
fieldName = elem.get('name')
|
||||
|
||||
# Do not include non-required enum constants
|
||||
# reg.py emits the enum constants of the entire type, even constants that are part of unsupported
|
||||
# extensions or those that are removed by <remove> elements in a given API. reg.py correctly tracks
|
||||
# down these and also alias dependencies and marks the enum constants that are actually required
|
||||
# with the 'required' attribute. Therefore we also have to verify that here to make sure we only
|
||||
# include enum constants that are actually required in the target API(s).
|
||||
if elem.get('required') is None:
|
||||
continue
|
||||
|
||||
if elem.get('alias') is not None:
|
||||
self.enumFieldAliasMap[fieldName] = elem.get('alias')
|
||||
continue
|
||||
|
|
@ -604,6 +657,15 @@ class BaseGenerator(OutputGenerator):
|
|||
for elem in enumElem.findall('enum'):
|
||||
flagName = elem.get('name')
|
||||
|
||||
# Do not include non-required enum constants
|
||||
# reg.py emits the enum constants of the entire type, even constants that are part of unsupported
|
||||
# extensions or those that are removed by <remove> elements in a given API. reg.py correctly tracks
|
||||
# down these and also alias dependencies and marks the enum constants that are actually required
|
||||
# with the 'required' attribute. Therefore we also have to verify that here to make sure we only
|
||||
# include enum constants that are actually required in the target API(s).
|
||||
if elem.get('required') is None:
|
||||
continue
|
||||
|
||||
if elem.get('alias') is not None:
|
||||
self.flagAliasMap[flagName] = elem.get('alias')
|
||||
continue
|
||||
|
|
@ -628,6 +690,11 @@ class BaseGenerator(OutputGenerator):
|
|||
|
||||
def genType(self, typeInfo, typeName, alias):
|
||||
OutputGenerator.genType(self, typeInfo, typeName, alias)
|
||||
|
||||
# Do not include APIs from unsupported extensions
|
||||
if self.unsupportedExtension:
|
||||
return
|
||||
|
||||
typeElem = typeInfo.elem
|
||||
protect = self.currentExtension.protect if hasattr(self.currentExtension, 'protect') and self.currentExtension.protect is not None else None
|
||||
extension = [self.currentExtension] if self.currentExtension is not None else []
|
||||
|
|
@ -656,10 +723,13 @@ class BaseGenerator(OutputGenerator):
|
|||
name = textIfFind(member, 'name')
|
||||
type = textIfFind(member, 'type')
|
||||
sType = member.get('values') if member.get('values') is not None else sType
|
||||
externSync = boolGet(member, 'externsync')
|
||||
noautovalidity = boolGet(member, 'noautovalidity')
|
||||
limittype = member.get('limittype')
|
||||
|
||||
(externSync, externSyncPointer) = externSyncGet(member)
|
||||
# No cases currently where a subtype of a struct is marked as externally synchronized.
|
||||
assert externSyncPointer is None
|
||||
|
||||
nullTerminated = False
|
||||
length = member.get('altlen') if member.get('altlen') is not None else member.get('len')
|
||||
if length:
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@ class CGeneratorOptions(GeneratorOptions):
|
|||
protectProtoStr=None,
|
||||
protectExtensionProto=None,
|
||||
protectExtensionProtoStr=None,
|
||||
protectExportName=None,
|
||||
protectExportProtoStr=None,
|
||||
apicall='',
|
||||
apientry='',
|
||||
apientryp='',
|
||||
|
|
@ -66,6 +68,12 @@ class CGeneratorOptions(GeneratorOptions):
|
|||
set to None
|
||||
- protectExtensionProtoStr - #ifdef/#ifndef symbol to use around
|
||||
extension prototype declarations, if protectExtensionProto is set
|
||||
- protectExportName - name used to determine if a command is
|
||||
exported matching an entry in the XML 'export' attribute.
|
||||
Set to None if no matching should be done.
|
||||
- protectExportProtoStr - #ifndef symbol to use around prototypes
|
||||
for commands that are not exported.
|
||||
Set to None if no protection is wanted.
|
||||
- apicall - string to use for the function declaration prefix,
|
||||
such as APICALL on Windows
|
||||
- apientry - string to use for the calling convention macro,
|
||||
|
|
@ -115,6 +123,12 @@ class CGeneratorOptions(GeneratorOptions):
|
|||
self.protectExtensionProtoStr = protectExtensionProtoStr
|
||||
"""#ifdef/#ifndef symbol to use around extension prototype declarations, if protectExtensionProto is set"""
|
||||
|
||||
self.protectExportName = protectExportName
|
||||
"""Export name for commands which are exported"""
|
||||
|
||||
self.protectExportProtoStr = protectExportProtoStr
|
||||
"""#ifndef symbol to use around prototypes for commands which are not exported"""
|
||||
|
||||
self.apicall = apicall
|
||||
"""string to use for the function declaration prefix, such as APICALL on Windows."""
|
||||
|
||||
|
|
@ -507,6 +521,23 @@ class COutputGenerator(OutputGenerator):
|
|||
|
||||
prefix = ''
|
||||
decls = self.makeCDecls(cmdinfo.elem)
|
||||
|
||||
# If the 'export' attribute is not set for this command, or does not
|
||||
# match the export name selected during generation, wrap the command
|
||||
# prototype in a C conditional which can be enabled to make the
|
||||
# prototype not appear at compile time.
|
||||
|
||||
export = cmdinfo.elem.get('export','')
|
||||
protect_prefix = protect_suffix = ''
|
||||
if export is None or self.genOpts.protectExportName not in export.split(','):
|
||||
if self.genOpts.protectExportProtoStr is not None:
|
||||
# Command is not exported, so should not be visible if
|
||||
# suppressed by this symbol
|
||||
protect_prefix = f'#ifndef {self.genOpts.protectExportProtoStr}\n'
|
||||
protect_suffix = '\n#endif'
|
||||
|
||||
decls[0] = protect_prefix + decls[0] + protect_suffix
|
||||
|
||||
self.appendSection('command', f"{prefix + decls[0]}\n")
|
||||
if self.genOpts.genFuncPointers:
|
||||
self.appendSection('commandPointer', decls[1])
|
||||
|
|
|
|||
|
|
@ -1413,6 +1413,7 @@ class OutputGenerator:
|
|||
else:
|
||||
paramdecl += 'void'
|
||||
paramdecl += ");"
|
||||
|
||||
return [pdecl + indentdecl, tdecl + paramdecl]
|
||||
|
||||
def newline(self):
|
||||
|
|
|
|||
|
|
@ -210,7 +210,7 @@ class BaseInfo:
|
|||
|
||||
self.elem = elem
|
||||
"etree Element for this feature"
|
||||
|
||||
|
||||
self.deprecatedbyversion = None
|
||||
self.deprecatedbyextensions = []
|
||||
self.deprecatedlink = None
|
||||
|
|
@ -353,7 +353,7 @@ class FeatureInfo(BaseInfo):
|
|||
|
||||
self.number = 0
|
||||
self.supported = None
|
||||
|
||||
|
||||
self.deprecates = elem.findall('deprecate')
|
||||
else:
|
||||
# Extract vendor portion of <APIprefix>_<vendor>_<name>
|
||||
|
|
@ -688,6 +688,9 @@ class Registry:
|
|||
# Now loop over aliases, injecting a copy of the aliased command's
|
||||
# Element with the aliased prototype name replaced with the command
|
||||
# name - if it exists.
|
||||
# Copy the 'export' sttribute (whether it exists or not) from the
|
||||
# original, aliased command, since that can be different for a
|
||||
# command and its alias.
|
||||
for (name, alias, cmd) in cmdAlias:
|
||||
if alias in self.cmddict:
|
||||
aliasInfo = self.cmddict[alias]
|
||||
|
|
@ -695,6 +698,14 @@ class Registry:
|
|||
cmdElem.find('proto/name').text = name
|
||||
cmdElem.set('name', name)
|
||||
cmdElem.set('alias', alias)
|
||||
export = cmd.get('export')
|
||||
if export is not None:
|
||||
# Replicate the command's 'export' attribute
|
||||
cmdElem.set('export', export)
|
||||
elif cmdElem.get('export') is not None:
|
||||
# Remove the 'export' attribute, if the alias has one but
|
||||
# the command does not.
|
||||
del cmdElem.attrib['export']
|
||||
ci = CmdInfo(cmdElem)
|
||||
# Replace the dictionary entry for the CmdInfo element
|
||||
self.cmddict[name] = ci
|
||||
|
|
@ -1264,7 +1275,7 @@ class Registry:
|
|||
- featurename - name of the feature
|
||||
- api - string specifying API name being generated
|
||||
- profile - string specifying API profile being generated"""
|
||||
|
||||
|
||||
versionmatch = APIConventions().is_api_version_name(featurename)
|
||||
|
||||
# <deprecate> marks things that are deprecated by this version/profile
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
888
registry/vk.xml
888
registry/vk.xml
File diff suppressed because it is too large
Load diff
|
|
@ -81,6 +81,13 @@ class Handle:
|
|||
def __lt__(self, other):
|
||||
return self.name < other.name
|
||||
|
||||
class ExternSync(Enum):
|
||||
NONE = auto() # no externsync attribute
|
||||
ALWAYS = auto() # externsync="true"
|
||||
MAYBE = auto() # externsync="maybe"
|
||||
SUBTYPE = auto() # externsync="param->member"
|
||||
SUBTYPE_MAYBE = auto() # externsync="maybe:param->member"
|
||||
|
||||
@dataclass
|
||||
class Param:
|
||||
"""<command/param>"""
|
||||
|
|
@ -110,8 +117,9 @@ class Param:
|
|||
optional: bool
|
||||
optionalPointer: bool # if type contains a pointer, is the pointer value optional
|
||||
|
||||
externSync: bool
|
||||
externSyncPointer: list[str] # if type contains a pointer, might only specific members modified
|
||||
externSync: ExternSync
|
||||
externSyncPointer: (str | None) # if type contains a pointer (externSync is SUBTYPE*),
|
||||
# only a specific member is externally synchronized.
|
||||
|
||||
# C string of member, example:
|
||||
# - const void* pNext
|
||||
|
|
@ -217,7 +225,7 @@ class Member:
|
|||
optional: bool
|
||||
optionalPointer: bool # if type contains a pointer, is the pointer value optional
|
||||
|
||||
externSync: bool
|
||||
externSync: ExternSync
|
||||
|
||||
# C string of member, example:
|
||||
# - const void* pNext
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue