Update for Vulkan-Docs 1.4.230

This commit is contained in:
Jon Leech 2025-10-24 02:45:46 +01:00 committed by Jon Leech
parent 33d7f51258
commit ee3b5caaa7
25 changed files with 18311 additions and 13125 deletions

View file

@ -17,5 +17,7 @@ VulkanAPI = os.getenv('VULKAN_API', default=defaultAPI)
if VulkanAPI == 'vulkansc':
from vkconventions import VulkanSCConventions as APIConventions
elif VulkanAPI == 'vulkanbase':
from vkconventions import VulkanBaseConventions as APIConventions
else:
from vkconventions import VulkanConventions as APIConventions

View file

@ -9,7 +9,7 @@ import os
import tempfile
import copy
from vulkan_object import (VulkanObject,
Extension, Version, Deprecate, Handle, Param, CommandScope, Command,
Extension, Version, Legacy, Handle, Param, CommandScope, Command,
EnumField, Enum, Flag, Bitmask, ExternSync, Flags, Member, Struct,
Constant, FormatComponent, FormatPlane, Format, FeatureRequirement,
SyncSupport, SyncEquivalent, SyncStage, SyncAccess, SyncPipelineStage, SyncPipeline,
@ -377,12 +377,12 @@ class BaseGenerator(OutputGenerator):
if member.type in self.structAliasMap:
member.type = self.dealias(member.type, self.structAliasMap)
# Replace string with Version class now we have all version created
if command.deprecate and command.deprecate.version:
if command.deprecate.version not in self.vk.versions:
if command.legacy and command.legacy.version:
if command.legacy.version not in self.vk.versions:
# occurs if something like VK_VERSION_1_0, in which case we will always warn for deprecation
command.deprecate.version = None
command.legacy.version = None
else:
command.deprecate.version = self.vk.versions[command.deprecate.version]
command.legacy.version = self.vk.versions[command.legacy.version]
# Could build up a reverse lookup map, but since these are not too large of list, just do here
# (Need to be done after we have found all the aliases)
@ -688,9 +688,9 @@ class BaseGenerator(OutputGenerator):
cPrototype = decls[0]
cFunctionPointer = decls[1]
deprecate = None
legacy = None
if cmdinfo.deprecatedlink:
deprecate = Deprecate(cmdinfo.deprecatedlink,
legacy = Legacy(cmdinfo.deprecatedlink,
cmdinfo.deprecatedbyversion, # is just the string, will update to class later
cmdinfo.deprecatedbyextensions)
@ -708,7 +708,7 @@ class BaseGenerator(OutputGenerator):
returnType, params, instance, device,
tasks, queues, allowNoQueues, successcodes, errorcodes,
primary, secondary, renderpass, videocoding,
implicitExternSyncParams, deprecate, cPrototype, cFunctionPointer)
implicitExternSyncParams, legacy, cPrototype, cFunctionPointer)
#
# List the enum for the commands
@ -860,6 +860,12 @@ class BaseGenerator(OutputGenerator):
# Handle C bit field members
bitFieldWidth = int(cdecl.split(':')[1]) if ':' in cdecl else None
selector = member.get('selector') if not union else None
selection = member.get('selection') if union else None
selections = []
if selection:
selections = [s for s in selection.split(',')]
# if a pointer, this can be a something like:
# optional="true,false" for ppGeometries
# optional="false,true" for pPhysicalDeviceCount
@ -872,7 +878,7 @@ class BaseGenerator(OutputGenerator):
members.append(Member(name, type, fullType, noautovalidity, limittype,
const, length, nullTerminated, pointer, fixedSizeArray,
optional, optionalPointer,
externSync, cdecl, bitFieldWidth))
externSync, cdecl, bitFieldWidth, selector, selections))
self.vk.structs[typeName] = Struct(typeName, [], extension, self.currentVersion, protect, members,
union, returnedOnly, sType, allowDuplicate, extends, extendedBy)

View file

@ -153,6 +153,7 @@ class GeneratorOptions:
genpath=None,
apiname=None,
mergeApiNames=None,
mergeInternalApis=True,
profile=None,
versions='.*',
emitversions='.*',
@ -179,6 +180,7 @@ class GeneratorOptions:
- apiname - string matching `<api>` 'apiname' attribute, e.g. 'gl'.
- mergeApiNames - If not None, a comma separated list of API names
to merge into the API specified by 'apiname'
- mergeInternalApis - whether to merge internal APIs into public APIs
- profile - string specifying API profile , e.g. 'core', or None.
- versions - regex matching API versions to process interfaces for.
Normally `'.*'` or `'[0-9][.][0-9]'` to match all defined versions.
@ -240,6 +242,9 @@ class GeneratorOptions:
self.mergeApiNames = mergeApiNames
"comma separated list of API names to merge into the API specified by 'apiname'"
self.mergeInternalApis = mergeInternalApis
"whether to merge internal APIs into public APIs"
self.profile = profile
"string specifying API profile , e.g. 'core', or None."
@ -587,14 +592,14 @@ class OutputGenerator:
name = elem.get('name')
if reason == 'aliased':
return f'{padding}// {name} is a deprecated alias\n'
return f'{padding}// {name} is a legacy alias\n'
elif reason == 'ignored':
return f'{padding}// {name} is deprecated and should not be used\n'
return f'{padding}// {name} is legacy and should not be used\n'
elif reason == 'true':
return f'{padding}// {name} is deprecated, but no reason was given in the API XML\n'
return f'{padding}// {name} is legacy, but no reason was given in the API XML\n'
else:
# This can be caught by schema validation
self.logMsg('error', f"{name} has an unknown deprecation attribute value '{reason}'")
self.logMsg('error', f"{name} has an unknown legacy attribute value '{reason}'")
exit(1)
def buildEnumCDecl(self, expand, groupinfo, groupName):

View file

@ -166,6 +166,109 @@ def mergeAPIs(tree, fromApiNames, toApiName):
variant.set('api', toApiName)
def mergeInternalFeatures(tree, apiName):
"""Merge internal API features (apitype='internal') into their public dependents.
This processes the tree to find features marked with apitype='internal' and merges
their <require>, <deprecate>, and <remove> blocks into the first public feature
that depends on them. After merging, the internal features are removed from the tree.
tree - Element at the root of the hierarchy (typically <registry>)
apiName - the API name to process (e.g., 'vulkan', 'vulkansc')
"""
import copy
# Find all features in the tree
features = tree.findall('feature')
# Separate internal and public features
internal_features = []
public_features = []
for feature in features:
api = feature.get('api', '')
apitype = feature.get('apitype', '')
# Only process features matching the target API
if apiName not in api.split(','):
continue
if apitype == 'internal':
internal_features.append(feature)
else:
public_features.append(feature)
# Build a simple dependency map from the 'depends' attributes
def get_dependencies(feature):
"""Extract all dependencies from a feature's depends attribute."""
depends = feature.get('depends', '')
if not depends:
return set()
# Parse the depends expression - for simplicity, extract feature names
# Dependencies can be like "VK_VERSION_1_0" or "VK_VERSION_1_0+VK_KHR_feature"
deps = set()
# Split on + and , to get individual dependencies
for dep in depends.replace('+', ',').split(','):
dep = dep.strip()
if dep:
deps.add(dep)
return deps
def has_dependency(feature, target_name, all_features_map, visited=None):
"""Check if feature depends on target_name (directly or transitively)."""
if visited is None:
visited = set()
feature_name = feature.get('name')
if feature_name in visited:
return False
visited.add(feature_name)
deps = get_dependencies(feature)
if target_name in deps:
return True
# Check transitive dependencies
for dep_name in deps:
if dep_name in all_features_map:
if has_dependency(all_features_map[dep_name], target_name, all_features_map, visited):
return True
return False
# Create a map of all features for dependency lookups
all_features_map = {f.get('name'): f for f in public_features + internal_features}
# For each internal feature, find its first public dependent and merge
for internal_feature in internal_features:
internal_name = internal_feature.get('name')
target_feature = None
# Find the first public feature that depends on this internal feature
for public_feature in public_features:
if has_dependency(public_feature, internal_name, all_features_map):
target_feature = public_feature
break
if target_feature is not None:
# Merge require blocks
for require in internal_feature.findall('require'):
require_copy = copy.deepcopy(require)
target_feature.append(require_copy)
# Merge deprecate blocks
for deprecate in internal_feature.findall('deprecate'):
deprecate_copy = copy.deepcopy(deprecate)
target_feature.append(deprecate_copy)
# Merge remove blocks
for remove in internal_feature.findall('remove'):
remove_copy = copy.deepcopy(remove)
target_feature.append(remove_copy)
# Remove the internal feature from the tree
tree.remove(internal_feature)
def stripNonmatchingAPIs(tree, apiName, actuallyDelete = True):
"""Remove tree Elements with 'api' attributes matching apiName.
@ -429,6 +532,9 @@ class Registry:
self.gen.genOpts = self.genOpts
self.gen.genOpts.registry = self
# Store mergeInternalApis in self to avoid repeated lookups
self.mergeInternalApis = getattr(self.genOpts, 'mergeInternalApis', True)
self.tree = None
"ElementTree containing the root `<registry>`"
@ -601,6 +707,11 @@ class Registry:
else:
stripNonmatchingAPIs(self.reg, self.genOpts.apiname, actuallyDelete = True)
# Merge internal features (apitype="internal") into their public dependents
# This happens after API merging/stripping so we work with the correct API
if self.mergeInternalApis:
mergeInternalFeatures(self.reg, self.genOpts.apiname)
self.aliasdict = {}
self.enumvaluedict = {}

View file

@ -37,7 +37,8 @@ EXT_NAME_DECOMPOSE_RE = re.compile(r'(?P<prefix>[A-Za-z]+)_(?P<vendor>[A-Za-z]+)
# Match an API version name.
# Match object includes API prefix, major, and minor version numbers.
# This could be refined further for specific APIs.
API_VERSION_NAME_RE = re.compile(r'(?P<apivariant>[A-Za-z]+)_VERSION_(?P<major>[0-9]+)_(?P<minor>[0-9]+)')
# Handles both simple versions (VK_VERSION_1_0) and component-specific versions (VK_BASE_VERSION_1_0)
API_VERSION_NAME_RE = re.compile(r'(?P<apivariant>[A-Za-z]+)(?:_(?:BASE|COMPUTE|GRAPHICS))?_VERSION_(?P<major>[0-9]+)_(?P<minor>[0-9]+)')
class ProseListFormats(Enum):
"""A connective, possibly with a quantifier."""

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

View file

@ -312,3 +312,19 @@ class VulkanSCConventions(VulkanConventions):
"""Return the name used in the default API XML registry for the default API"""
return 'vulkansc'
class VulkanBaseConventions(VulkanConventions):
def specURL(self, spectype='api'):
"""Return public registry URL which ref pages should link to for the
current all-extensions HTML specification, so xrefs in the
asciidoc source that are not to ref pages can link into it
instead. N.b. this may need to change on a per-refpage basis if
there are multiple documents involved.
"""
return 'https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html'
@property
def xml_api_name(self):
"""Return the name used in the default API XML registry for the default API"""
return 'vulkanbase'

View file

@ -65,9 +65,11 @@ class Version:
featureRequirement: list[FeatureRequirement]
@dataclass
class Deprecate:
"""<deprecate>"""
link: (str | None) # Spec URL Anchor - ex) deprecation-dynamicrendering
class Legacy:
"""<deprecate>
For historical reasons, the XML tag is "deprecate" but we decided in the WG to not use that as the public facing name
"""
link: (str | None) # Spec URL Anchor - ex) legacy-dynamicrendering
version: (Version | None)
extensions: list[str]
@ -181,7 +183,7 @@ class Command:
implicitExternSyncParams: list[str]
deprecate: (Deprecate | None)
legacy: (Legacy | None)
# C prototype string - ex:
# VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(
@ -237,6 +239,11 @@ class Member:
bitFieldWidth: (int | None) # bit width (only for bit field struct members)
# Selector for the union, this type determines the used data type in the union
selector: (str | None)
# Valid selections for the union member
selection: list[str]
def __lt__(self, other):
return self.name < other.name