early-access version 2323
This commit is contained in:
11
externals/Vulkan-Headers/registry/apiconventions.py
vendored
Executable file
11
externals/Vulkan-Headers/registry/apiconventions.py
vendored
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/python3 -i
|
||||
#
|
||||
# Copyright 2021 The Khronos Group Inc.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# Generic alias for working group-specific API conventions interface.
|
||||
|
||||
# This import should be changed at the repository / working group level to
|
||||
# specify the correct API's conventions.
|
||||
|
||||
from vkconventions import VulkanConventions as APIConventions
|
@@ -188,7 +188,7 @@ class COutputGenerator(OutputGenerator):
|
||||
OutputGenerator.beginFeature(self, interface, emit)
|
||||
# C-specific
|
||||
# Accumulate includes, defines, types, enums, function pointer typedefs,
|
||||
# end function prototypes separately for this feature. They're only
|
||||
# end function prototypes separately for this feature. They are only
|
||||
# printed in endFeature().
|
||||
self.sections = {section: [] for section in self.ALL_SECTIONS}
|
||||
self.feature_not_empty = False
|
||||
@@ -267,7 +267,7 @@ class COutputGenerator(OutputGenerator):
|
||||
else:
|
||||
# Replace <apientry /> tags with an APIENTRY-style string
|
||||
# (from self.genOpts). Copy other text through unchanged.
|
||||
# If the resulting text is an empty string, don't emit it.
|
||||
# If the resulting text is an empty string, do not emit it.
|
||||
body = noneStr(typeElem.text)
|
||||
for elem in typeElem:
|
||||
if elem.tag == 'apientry':
|
||||
@@ -306,8 +306,8 @@ class COutputGenerator(OutputGenerator):
|
||||
|
||||
def typeMayAlias(self, typeName):
|
||||
if not self.may_alias:
|
||||
# First time we've asked if a type may alias.
|
||||
# So, let's populate the set of all names of types that may.
|
||||
# First time we have asked if a type may alias.
|
||||
# So, populate the set of all names of types that may.
|
||||
|
||||
# Everyone with an explicit mayalias="true"
|
||||
self.may_alias = set(typeName
|
||||
|
@@ -139,9 +139,9 @@ class ConventionsBase:
|
||||
Optionally adds a quantifier (like 'any') before a list of 2 or more,
|
||||
if specified by fmt.
|
||||
|
||||
Don't edit these defaults, override self.makeProseList().
|
||||
Do not edit these defaults, override self.makeProseList().
|
||||
"""
|
||||
assert(serial_comma) # didn't implement what we didn't need
|
||||
assert(serial_comma) # did not implement what we did not need
|
||||
if isinstance(fmt, str):
|
||||
fmt = ProseListFormats.from_string(fmt)
|
||||
|
||||
|
69
externals/Vulkan-Headers/registry/generator.py
vendored
69
externals/Vulkan-Headers/registry/generator.py
vendored
@@ -43,7 +43,10 @@ def enquote(s):
|
||||
"""Return string argument with surrounding quotes,
|
||||
for serialization into Python code."""
|
||||
if s:
|
||||
return "'{}'".format(s)
|
||||
if isinstance(s, str):
|
||||
return "'{}'".format(s)
|
||||
else:
|
||||
return s
|
||||
return None
|
||||
|
||||
|
||||
@@ -119,8 +122,11 @@ class GeneratorOptions:
|
||||
removeExtensions=None,
|
||||
emitExtensions=None,
|
||||
emitSpirv=None,
|
||||
emitFormats=None,
|
||||
reparentEnums=True,
|
||||
sortProcedure=regSortFeatures):
|
||||
sortProcedure=regSortFeatures,
|
||||
requireCommandAliases=False,
|
||||
):
|
||||
"""Constructor.
|
||||
|
||||
Arguments:
|
||||
@@ -152,6 +158,8 @@ class GeneratorOptions:
|
||||
to None.
|
||||
- emitSpirv - regex matching names of extensions and capabilities
|
||||
to actually emit interfaces for.
|
||||
- emitFormats - regex matching names of formats to actually emit
|
||||
interfaces for.
|
||||
- reparentEnums - move <enum> elements which extend an enumerated
|
||||
type from <feature> or <extension> elements to the target <enums>
|
||||
element. This is required for almost all purposes, but the
|
||||
@@ -217,6 +225,10 @@ class GeneratorOptions:
|
||||
"""regex matching names of extensions and capabilities
|
||||
to actually emit interfaces for."""
|
||||
|
||||
self.emitFormats = self.emptyRegex(emitFormats)
|
||||
"""regex matching names of formats
|
||||
to actually emit interfaces for."""
|
||||
|
||||
self.reparentEnums = reparentEnums
|
||||
"""boolean specifying whether to remove <enum> elements from
|
||||
<feature> or <extension> when extending an <enums> type."""
|
||||
@@ -230,6 +242,10 @@ class GeneratorOptions:
|
||||
self.codeGenerator = False
|
||||
"""True if this generator makes compilable code"""
|
||||
|
||||
self.requireCommandAliases = requireCommandAliases
|
||||
"""True if alias= attributes of <command> tags are transitively
|
||||
required."""
|
||||
|
||||
def emptyRegex(self, pat):
|
||||
"""Substitute a regular expression which matches no version
|
||||
or extension names for None or the empty string."""
|
||||
@@ -257,6 +273,17 @@ class OutputGenerator:
|
||||
'basetype': 'basetypes',
|
||||
}
|
||||
|
||||
def breakName(self, name, msg):
|
||||
"""Break into debugger if this is a special name"""
|
||||
|
||||
# List of string names to break on
|
||||
bad = (
|
||||
)
|
||||
|
||||
if name in bad and True:
|
||||
print('breakName {}: {}'.format(name, msg))
|
||||
pdb.set_trace()
|
||||
|
||||
def __init__(self, errFile=sys.stderr, warnFile=sys.stderr, diagFile=sys.stdout):
|
||||
"""Constructor
|
||||
|
||||
@@ -337,7 +364,7 @@ class OutputGenerator:
|
||||
# print('About to translate value =', value, 'type =', type(value))
|
||||
if needsNum:
|
||||
numVal = int(value, 0)
|
||||
# If there's a non-integer, numeric 'type' attribute (e.g. 'u' or
|
||||
# If there is a non-integer, numeric 'type' attribute (e.g. 'u' or
|
||||
# 'ull'), append it to the string value.
|
||||
# t = enuminfo.elem.get('type')
|
||||
# if t is not None and t != '' and t != 'i' and t != 's':
|
||||
@@ -418,7 +445,7 @@ class OutputGenerator:
|
||||
+ ') found with different values:' + strVal
|
||||
+ ' and ' + strVal2)
|
||||
|
||||
# Don't add the duplicate to the returned list
|
||||
# Do not add the duplicate to the returned list
|
||||
continue
|
||||
elif numVal in valueMap:
|
||||
# Duplicate value found (such as an alias); report it, but
|
||||
@@ -519,7 +546,7 @@ class OutputGenerator:
|
||||
|
||||
# Accumulate non-numeric enumerant values separately and append
|
||||
# them following the numeric values, to allow for aliases.
|
||||
# NOTE: this doesn't do a topological sort yet, so aliases of
|
||||
# NOTE: this does not do a topological sort yet, so aliases of
|
||||
# aliases can still get in the wrong order.
|
||||
aliasText = ''
|
||||
|
||||
@@ -553,7 +580,7 @@ class OutputGenerator:
|
||||
# Work around this by chasing the aliases to get the actual value.
|
||||
while numVal is None:
|
||||
alias = self.registry.tree.find("enums/enum[@name='" + strVal + "']")
|
||||
(numVal, strVal) = self.enumToValue(alias, True)
|
||||
(numVal, strVal) = self.enumToValue(alias, True, bitwidth, True)
|
||||
decl += "static const {} {} = {};\n".format(flagTypeName, name, strVal)
|
||||
|
||||
if numVal is not None:
|
||||
@@ -612,7 +639,7 @@ class OutputGenerator:
|
||||
|
||||
# Accumulate non-numeric enumerant values separately and append
|
||||
# them following the numeric values, to allow for aliases.
|
||||
# NOTE: this doesn't do a topological sort yet, so aliases of
|
||||
# NOTE: this does not do a topological sort yet, so aliases of
|
||||
# aliases can still get in the wrong order.
|
||||
aliasText = []
|
||||
|
||||
@@ -651,7 +678,7 @@ class OutputGenerator:
|
||||
self.logMsg('error', 'Allowable range for C enum types is [', minValidValue, ',', maxValidValue, '], but', name, 'has a value outside of this (', strVal, ')\n')
|
||||
exit(1)
|
||||
|
||||
# Don't track min/max for non-numbers (numVal is None)
|
||||
# Do not track min/max for non-numbers (numVal is None)
|
||||
if isEnum and numVal is not None and elem.get('extends') is None:
|
||||
if minName is None:
|
||||
minName = maxName = name
|
||||
@@ -674,7 +701,7 @@ class OutputGenerator:
|
||||
" {}_RANGE_SIZE{} = ({} - {} + 1),".format(expandPrefix, expandSuffix, maxName, minName)))
|
||||
|
||||
# Generate a range-padding value to ensure the enum is 32 bits, but
|
||||
# only in code generators, so it doesn't appear in documentation
|
||||
# only in code generators, so it does not appear in documentation
|
||||
if (self.genOpts.codeGenerator or
|
||||
self.conventions.generate_max_enum_in_docs):
|
||||
body.append(" {}_MAX_ENUM{} = 0x7FFFFFFF".format(
|
||||
@@ -747,7 +774,7 @@ class OutputGenerator:
|
||||
def beginFile(self, genOpts):
|
||||
"""Start a new interface file
|
||||
|
||||
- genOpts - GeneratorOptions controlling what's generated and how"""
|
||||
- genOpts - GeneratorOptions controlling what is generated and how"""
|
||||
self.genOpts = genOpts
|
||||
self.should_insert_may_alias_macro = \
|
||||
self.genOpts.conventions.should_insert_may_alias_macro(self.genOpts)
|
||||
@@ -778,7 +805,6 @@ class OutputGenerator:
|
||||
self.warnFile.flush()
|
||||
if self.diagFile:
|
||||
self.diagFile.flush()
|
||||
self.outFile.flush()
|
||||
if self.outFile != sys.stdout and self.outFile != sys.stderr:
|
||||
self.outFile.close()
|
||||
|
||||
@@ -800,7 +826,7 @@ class OutputGenerator:
|
||||
- emit - actually write to the header only when True"""
|
||||
self.emit = emit
|
||||
self.featureName = interface.get('name')
|
||||
# If there's an additional 'protect' attribute in the feature, save it
|
||||
# If there is an additional 'protect' attribute in the feature, save it
|
||||
self.featureExtraProtect = interface.get('protect')
|
||||
|
||||
def endFeature(self):
|
||||
@@ -812,7 +838,7 @@ class OutputGenerator:
|
||||
|
||||
def genRequirements(self, name, mustBeFound = True):
|
||||
"""Generate text showing what core versions and extensions introduce
|
||||
an API. This exists in the base Generator class because it's used by
|
||||
an API. This exists in the base Generator class because it is used by
|
||||
the shared enumerant-generating interfaces (buildEnumCDecl, etc.).
|
||||
Here it returns an empty string for most generators, but can be
|
||||
overridden by e.g. DocGenerator.
|
||||
@@ -825,7 +851,7 @@ class OutputGenerator:
|
||||
return ''
|
||||
|
||||
def validateFeature(self, featureType, featureName):
|
||||
"""Validate we're generating something only inside a `<feature>` tag"""
|
||||
"""Validate we are generating something only inside a `<feature>` tag"""
|
||||
if self.featureName is None:
|
||||
raise UserWarning('Attempt to generate', featureType,
|
||||
featureName, 'when not in feature')
|
||||
@@ -887,6 +913,14 @@ class OutputGenerator:
|
||||
Extend to generate as desired in your derived class."""
|
||||
return
|
||||
|
||||
def genFormat(self, format, formatinfo, alias):
|
||||
"""Generate interface for a format element.
|
||||
|
||||
- formatinfo - FormatInfo
|
||||
|
||||
Extend to generate as desired in your derived class."""
|
||||
return
|
||||
|
||||
def makeProtoName(self, name, tail):
|
||||
"""Turn a `<proto>` `<name>` into C-language prototype
|
||||
and typedef declarations for that name.
|
||||
@@ -939,6 +973,9 @@ class OutputGenerator:
|
||||
|
||||
# Clear prefix for subsequent iterations
|
||||
prefix = ''
|
||||
|
||||
paramdecl = paramdecl + prefix
|
||||
|
||||
if aligncol == 0:
|
||||
# Squeeze out multiple spaces other than the indentation
|
||||
paramdecl = indent + ' '.join(paramdecl.split())
|
||||
@@ -1013,7 +1050,7 @@ class OutputGenerator:
|
||||
return None
|
||||
|
||||
def isStructAlwaysValid(self, structname):
|
||||
"""Try to do check if a structure is always considered valid (i.e. there's no rules to its acceptance)."""
|
||||
"""Try to do check if a structure is always considered valid (i.e. there is no rules to its acceptance)."""
|
||||
# A conventions object is required for this call.
|
||||
if not self.conventions:
|
||||
raise RuntimeError("To use isStructAlwaysValid, be sure your options include a Conventions object.")
|
||||
@@ -1109,7 +1146,7 @@ class OutputGenerator:
|
||||
# Leading text
|
||||
pdecl += noneStr(proto.text)
|
||||
tdecl += noneStr(proto.text)
|
||||
# For each child element, if it's a <name> wrap in appropriate
|
||||
# For each child element, if it is a <name> wrap in appropriate
|
||||
# declaration. Otherwise append its contents and tail contents.
|
||||
for elem in proto:
|
||||
text = noneStr(elem.text)
|
||||
|
119
externals/Vulkan-Headers/registry/genvk.py
vendored
119
externals/Vulkan-Headers/registry/genvk.py
vendored
@@ -19,11 +19,13 @@ from interfacedocgenerator import InterfaceDocGenerator
|
||||
from generator import write
|
||||
from spirvcapgenerator import SpirvCapabilityOutputGenerator
|
||||
from hostsyncgenerator import HostSynchronizationOutputGenerator
|
||||
from formatsgenerator import FormatsOutputGenerator
|
||||
from pygenerator import PyOutputGenerator
|
||||
from rubygenerator import RubyOutputGenerator
|
||||
from reflib import logDiag, logWarn, setLogFile
|
||||
from reg import Registry
|
||||
from validitygenerator import ValidityOutputGenerator
|
||||
from vkconventions import VulkanConventions
|
||||
from apiconventions import APIConventions
|
||||
|
||||
|
||||
# Simple timer functions
|
||||
@@ -77,6 +79,9 @@ def makeGenOpts(args):
|
||||
# SPIR-V capabilities / features to emit (list of extensions & capabilities)
|
||||
emitSpirv = args.emitSpirv
|
||||
|
||||
# Vulkan Formats to emit
|
||||
emitFormats = args.emitFormats
|
||||
|
||||
# Features to include (list of features)
|
||||
features = args.feature
|
||||
|
||||
@@ -97,13 +102,14 @@ def makeGenOpts(args):
|
||||
|
||||
# Descriptive names for various regexp patterns used to select
|
||||
# versions and extensions
|
||||
allSpirv = allFeatures = allExtensions = r'.*'
|
||||
allFormats = allSpirv = allFeatures = allExtensions = r'.*'
|
||||
|
||||
# Turn lists of names/patterns into matching regular expressions
|
||||
addExtensionsPat = makeREstring(extensions, None)
|
||||
removeExtensionsPat = makeREstring(removeExtensions, None)
|
||||
emitExtensionsPat = makeREstring(emitExtensions, allExtensions)
|
||||
emitSpirvPat = makeREstring(emitSpirv, allSpirv)
|
||||
emitFormatsPat = makeREstring(emitFormats, allFormats)
|
||||
featuresPat = makeREstring(features, allFeatures)
|
||||
|
||||
# Copyright text prefixing all headers (list of strings).
|
||||
@@ -130,7 +136,9 @@ def makeGenOpts(args):
|
||||
protectFile = protect
|
||||
|
||||
# An API style conventions object
|
||||
conventions = VulkanConventions()
|
||||
conventions = APIConventions()
|
||||
|
||||
defaultAPIName = conventions.xml_api_name
|
||||
|
||||
# API include files for spec and ref pages
|
||||
# Overwrites include subdirectories in spec source tree
|
||||
@@ -146,7 +154,7 @@ def makeGenOpts(args):
|
||||
filename = 'timeMarker',
|
||||
directory = directory,
|
||||
genpath = genpath,
|
||||
apiname = 'vulkan',
|
||||
apiname = defaultAPIName,
|
||||
profile = None,
|
||||
versions = featuresPat,
|
||||
emitversions = featuresPat,
|
||||
@@ -162,8 +170,8 @@ def makeGenOpts(args):
|
||||
expandEnumerants = False)
|
||||
]
|
||||
|
||||
# Python representation of API information, used by scripts that
|
||||
# don't need to load the full XML.
|
||||
# Python and Ruby representations of API information, used by scripts
|
||||
# that do not need to load the full XML.
|
||||
genOpts['api.py'] = [
|
||||
PyOutputGenerator,
|
||||
DocGeneratorOptions(
|
||||
@@ -171,7 +179,7 @@ def makeGenOpts(args):
|
||||
filename = 'api.py',
|
||||
directory = directory,
|
||||
genpath = None,
|
||||
apiname = 'vulkan',
|
||||
apiname = defaultAPIName,
|
||||
profile = None,
|
||||
versions = featuresPat,
|
||||
emitversions = featuresPat,
|
||||
@@ -182,7 +190,30 @@ def makeGenOpts(args):
|
||||
reparentEnums = False)
|
||||
]
|
||||
|
||||
genOpts['api.rb'] = [
|
||||
RubyOutputGenerator,
|
||||
DocGeneratorOptions(
|
||||
conventions = conventions,
|
||||
filename = 'api.rb',
|
||||
directory = directory,
|
||||
genpath = None,
|
||||
apiname = defaultAPIName,
|
||||
profile = None,
|
||||
versions = featuresPat,
|
||||
emitversions = featuresPat,
|
||||
defaultExtensions = None,
|
||||
addExtensions = addExtensionsPat,
|
||||
removeExtensions = removeExtensionsPat,
|
||||
emitExtensions = emitExtensionsPat,
|
||||
reparentEnums = False)
|
||||
]
|
||||
|
||||
|
||||
# API validity files for spec
|
||||
#
|
||||
# requireCommandAliases is set to True because we need validity files
|
||||
# for the command something is promoted to even when the promoted-to
|
||||
# feature is not included. This avoids wordy includes of validity files.
|
||||
genOpts['validinc'] = [
|
||||
ValidityOutputGenerator,
|
||||
DocGeneratorOptions(
|
||||
@@ -190,14 +221,16 @@ def makeGenOpts(args):
|
||||
filename = 'timeMarker',
|
||||
directory = directory,
|
||||
genpath = None,
|
||||
apiname = 'vulkan',
|
||||
apiname = defaultAPIName,
|
||||
profile = None,
|
||||
versions = featuresPat,
|
||||
emitversions = featuresPat,
|
||||
defaultExtensions = None,
|
||||
addExtensions = addExtensionsPat,
|
||||
removeExtensions = removeExtensionsPat,
|
||||
emitExtensions = emitExtensionsPat)
|
||||
emitExtensions = emitExtensionsPat,
|
||||
requireCommandAliases = True,
|
||||
)
|
||||
]
|
||||
|
||||
# API host sync table files for spec
|
||||
@@ -208,7 +241,7 @@ def makeGenOpts(args):
|
||||
filename = 'timeMarker',
|
||||
directory = directory,
|
||||
genpath = None,
|
||||
apiname = 'vulkan',
|
||||
apiname = defaultAPIName,
|
||||
profile = None,
|
||||
versions = featuresPat,
|
||||
emitversions = featuresPat,
|
||||
@@ -230,7 +263,7 @@ def makeGenOpts(args):
|
||||
filename = 'timeMarker',
|
||||
directory = directory,
|
||||
genpath = None,
|
||||
apiname = 'vulkan',
|
||||
apiname = defaultAPIName,
|
||||
profile = None,
|
||||
versions = featuresPat,
|
||||
emitversions = None,
|
||||
@@ -249,7 +282,7 @@ def makeGenOpts(args):
|
||||
filename = 'timeMarker',
|
||||
directory = directory,
|
||||
genpath = None,
|
||||
apiname = 'vulkan',
|
||||
apiname = defaultAPIName,
|
||||
profile = None,
|
||||
versions = featuresPat,
|
||||
emitversions = featuresPat,
|
||||
@@ -267,7 +300,7 @@ def makeGenOpts(args):
|
||||
filename = 'timeMarker',
|
||||
directory = directory,
|
||||
genpath = None,
|
||||
apiname = 'vulkan',
|
||||
apiname = defaultAPIName,
|
||||
profile = None,
|
||||
versions = featuresPat,
|
||||
emitversions = featuresPat,
|
||||
@@ -279,6 +312,26 @@ def makeGenOpts(args):
|
||||
reparentEnums = False)
|
||||
]
|
||||
|
||||
# Used to generate various format chapter tables
|
||||
genOpts['formatsinc'] = [
|
||||
FormatsOutputGenerator,
|
||||
DocGeneratorOptions(
|
||||
conventions = conventions,
|
||||
filename = 'timeMarker',
|
||||
directory = directory,
|
||||
genpath = None,
|
||||
apiname = defaultAPIName,
|
||||
profile = None,
|
||||
versions = featuresPat,
|
||||
emitversions = featuresPat,
|
||||
defaultExtensions = None,
|
||||
addExtensions = addExtensionsPat,
|
||||
removeExtensions = removeExtensionsPat,
|
||||
emitExtensions = emitExtensionsPat,
|
||||
emitFormats = emitFormatsPat,
|
||||
reparentEnums = False)
|
||||
]
|
||||
|
||||
# Platform extensions, in their own header files
|
||||
# Each element of the platforms[] array defines information for
|
||||
# generating a single platform:
|
||||
@@ -307,6 +360,7 @@ def makeGenOpts(args):
|
||||
'VK_EXT_video_decode_h264',
|
||||
'VK_EXT_video_decode_h265',
|
||||
'VK_EXT_video_encode_h264',
|
||||
'VK_EXT_video_encode_h265',
|
||||
]
|
||||
|
||||
betaSuppressExtensions = []
|
||||
@@ -314,10 +368,13 @@ def makeGenOpts(args):
|
||||
platforms = [
|
||||
[ 'vulkan_android.h', [ 'VK_KHR_android_surface',
|
||||
'VK_ANDROID_external_memory_android_hardware_buffer'
|
||||
], commonSuppressExtensions ],
|
||||
], commonSuppressExtensions +
|
||||
[ 'VK_KHR_format_feature_flags2',
|
||||
] ],
|
||||
[ 'vulkan_fuchsia.h', [ 'VK_FUCHSIA_imagepipe_surface',
|
||||
'VK_FUCHSIA_external_memory',
|
||||
'VK_FUCHSIA_external_semaphore' ], commonSuppressExtensions ],
|
||||
'VK_FUCHSIA_external_semaphore',
|
||||
'VK_FUCHSIA_buffer_collection' ], commonSuppressExtensions ],
|
||||
[ 'vulkan_ggp.h', [ 'VK_GGP_stream_descriptor_surface',
|
||||
'VK_GGP_frame_token' ], commonSuppressExtensions ],
|
||||
[ 'vulkan_ios.h', [ 'VK_MVK_ios_surface' ], commonSuppressExtensions ],
|
||||
@@ -357,7 +414,7 @@ def makeGenOpts(args):
|
||||
filename = headername,
|
||||
directory = directory,
|
||||
genpath = None,
|
||||
apiname = 'vulkan',
|
||||
apiname = defaultAPIName,
|
||||
profile = None,
|
||||
versions = featuresPat,
|
||||
emitversions = None,
|
||||
@@ -398,7 +455,7 @@ def makeGenOpts(args):
|
||||
filename = 'vulkan_core.h',
|
||||
directory = directory,
|
||||
genpath = None,
|
||||
apiname = 'vulkan',
|
||||
apiname = defaultAPIName,
|
||||
profile = None,
|
||||
versions = featuresPat,
|
||||
emitversions = featuresPat,
|
||||
@@ -432,7 +489,7 @@ def makeGenOpts(args):
|
||||
filename = 'vulkan10.h',
|
||||
directory = directory,
|
||||
genpath = None,
|
||||
apiname = 'vulkan',
|
||||
apiname = defaultAPIName,
|
||||
profile = None,
|
||||
versions = 'VK_VERSION_1_0',
|
||||
emitversions = 'VK_VERSION_1_0',
|
||||
@@ -466,7 +523,7 @@ def makeGenOpts(args):
|
||||
filename = 'vulkan11.h',
|
||||
directory = directory,
|
||||
genpath = None,
|
||||
apiname = 'vulkan',
|
||||
apiname = defaultAPIName,
|
||||
profile = None,
|
||||
versions = '^VK_VERSION_1_[01]$',
|
||||
emitversions = '^VK_VERSION_1_[01]$',
|
||||
@@ -495,7 +552,7 @@ def makeGenOpts(args):
|
||||
filename = 'alias.h',
|
||||
directory = directory,
|
||||
genpath = None,
|
||||
apiname = 'vulkan',
|
||||
apiname = defaultAPIName,
|
||||
profile = None,
|
||||
versions = featuresPat,
|
||||
emitversions = featuresPat,
|
||||
@@ -546,6 +603,8 @@ def genTarget(args):
|
||||
logDiag('* options.addExtensions =', options.addExtensions)
|
||||
logDiag('* options.removeExtensions =', options.removeExtensions)
|
||||
logDiag('* options.emitExtensions =', options.emitExtensions)
|
||||
logDiag('* options.emitSpirv =', options.emitSpirv)
|
||||
logDiag('* options.emitFormats =', options.emitFormats)
|
||||
|
||||
gen = createGenerator(errFile=errWarn,
|
||||
warnFile=errWarn,
|
||||
@@ -564,7 +623,7 @@ if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser()
|
||||
|
||||
parser.add_argument('-defaultExtensions', action='store',
|
||||
default='vulkan',
|
||||
default=APIConventions().xml_api_name,
|
||||
help='Specify a single class of extensions to add to targets')
|
||||
parser.add_argument('-extension', action='append',
|
||||
default=[],
|
||||
@@ -578,6 +637,9 @@ if __name__ == '__main__':
|
||||
parser.add_argument('-emitSpirv', action='append',
|
||||
default=[],
|
||||
help='Specify a SPIR-V extension or capability to emit in targets')
|
||||
parser.add_argument('-emitFormats', action='append',
|
||||
default=[],
|
||||
help='Specify Vulkan Formats to emit in targets')
|
||||
parser.add_argument('-feature', action='append',
|
||||
default=[],
|
||||
help='Specify a core API feature name or names to add to targets')
|
||||
@@ -601,7 +663,7 @@ if __name__ == '__main__':
|
||||
parser.add_argument('-time', action='store_true',
|
||||
help='Enable timing')
|
||||
parser.add_argument('-validate', action='store_true',
|
||||
help='Enable XML group validation')
|
||||
help='Validate the registry properties and exit')
|
||||
parser.add_argument('-genpath', action='store', default='gen',
|
||||
help='Path to generated files')
|
||||
parser.add_argument('-o', action='store', dest='directory',
|
||||
@@ -635,8 +697,14 @@ if __name__ == '__main__':
|
||||
else:
|
||||
diag = None
|
||||
|
||||
# Create the API generator & generator options
|
||||
(gen, options) = genTarget(args)
|
||||
if args.time:
|
||||
# Log diagnostics and warnings
|
||||
setLogFile(setDiag = True, setWarn = True, filename = '-')
|
||||
|
||||
(gen, options) = (None, None)
|
||||
if not args.validate:
|
||||
# Create the API generator & generator options
|
||||
(gen, options) = genTarget(args)
|
||||
|
||||
# Create the registry object with the specified generator and generator
|
||||
# options. The options are set before XML loading as they may affect it.
|
||||
@@ -653,7 +721,8 @@ if __name__ == '__main__':
|
||||
endTimer(args.time, '* Time to parse ElementTree =')
|
||||
|
||||
if args.validate:
|
||||
reg.validateGroups()
|
||||
success = reg.validateRegistry()
|
||||
sys.exit(0 if success else 1)
|
||||
|
||||
if args.dump:
|
||||
logDiag('* Dumping registry to regdump.txt')
|
||||
|
333
externals/Vulkan-Headers/registry/reg.py
vendored
333
externals/Vulkan-Headers/registry/reg.py
vendored
@@ -10,19 +10,24 @@ import copy
|
||||
import re
|
||||
import sys
|
||||
import xml.etree.ElementTree as etree
|
||||
from collections import defaultdict, namedtuple
|
||||
from collections import defaultdict, deque, namedtuple
|
||||
from generator import OutputGenerator, GeneratorOptions, write
|
||||
import pdb
|
||||
from apiconventions import APIConventions
|
||||
|
||||
def apiNameMatch(str, supported):
|
||||
"""Return whether a required api name matches a pattern specified for an
|
||||
XML <feature> 'api' attribute or <extension> 'supported' attribute.
|
||||
|
||||
- str - api name such as 'vulkan' or 'openxr'
|
||||
- supported - comma-separated list of XML API names"""
|
||||
- str - API name such as 'vulkan' or 'openxr'. May be None, in which
|
||||
case it never matches (this should not happen).
|
||||
- supported - comma-separated list of XML API names. May be None, in
|
||||
which case str always matches (this is the usual case)."""
|
||||
|
||||
return (str is not None and str in supported.split(','))
|
||||
if str is not None:
|
||||
return supported is None or str in supported.split(',')
|
||||
|
||||
# Fallthrough case - either str is None or the test failed
|
||||
return False
|
||||
|
||||
def matchAPIProfile(api, profile, elem):
|
||||
"""Return whether an API and profile
|
||||
@@ -52,7 +57,7 @@ def matchAPIProfile(api, profile, elem):
|
||||
--------- --------
|
||||
None None Always matches
|
||||
'string' None Always matches
|
||||
None 'string' Does not match. Can't generate multiple APIs
|
||||
None 'string' Does not match. Cannot generate multiple APIs
|
||||
or profiles, so if an API/profile constraint
|
||||
is present, it must be asked for explicitly.
|
||||
'string' 'string' Strings must match
|
||||
@@ -60,7 +65,7 @@ def matchAPIProfile(api, profile, elem):
|
||||
|
||||
** In the future, we will allow regexes for the attributes,
|
||||
not just strings, so that `api="^(gl|gles2)"` will match. Even
|
||||
this isn't really quite enough, we might prefer something
|
||||
this is not really quite enough, we might prefer something
|
||||
like `"gl(core)|gles1(common-lite)"`."""
|
||||
# Match 'api', if present
|
||||
elem_api = elem.get('api')
|
||||
@@ -69,7 +74,7 @@ def matchAPIProfile(api, profile, elem):
|
||||
raise UserWarning("No API requested, but 'api' attribute is present with value '"
|
||||
+ elem_api + "'")
|
||||
elif api != elem_api:
|
||||
# Requested API doesn't match attribute
|
||||
# Requested API does not match attribute
|
||||
return False
|
||||
elem_profile = elem.get('profile')
|
||||
if elem_profile:
|
||||
@@ -77,11 +82,37 @@ def matchAPIProfile(api, profile, elem):
|
||||
raise UserWarning("No profile requested, but 'profile' attribute is present with value '"
|
||||
+ elem_profile + "'")
|
||||
elif profile != elem_profile:
|
||||
# Requested profile doesn't match attribute
|
||||
# Requested profile does not match attribute
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def stripNonmatchingAPIs(tree, apiName, actuallyDelete = True):
|
||||
"""Remove tree Elements with 'api' attributes matching apiName.
|
||||
|
||||
tree - Element at the root of the hierarchy to strip. Only its
|
||||
children can actually be removed, not the tree itself.
|
||||
apiName - string which much match a command-separated component of
|
||||
the 'api' attribute.
|
||||
actuallyDelete - only delete matching elements if True."""
|
||||
|
||||
stack = deque()
|
||||
stack.append(tree)
|
||||
|
||||
while len(stack) > 0:
|
||||
parent = stack.pop()
|
||||
|
||||
for child in parent.findall('*'):
|
||||
api = child.get('api')
|
||||
if api:
|
||||
if not apiNameMatch(apiName, api):
|
||||
if actuallyDelete:
|
||||
parent.remove(child)
|
||||
else:
|
||||
# Add child to the queue
|
||||
stack.append(child)
|
||||
|
||||
|
||||
class BaseInfo:
|
||||
"""Base class for information about a registry feature
|
||||
(type/group/enum/command/API/extension).
|
||||
@@ -128,12 +159,12 @@ class BaseInfo:
|
||||
if (self.compareKeys(info, 'value', required = True) or
|
||||
self.compareKeys(info, 'bitpos', required = True)):
|
||||
# If both specify the same value or bit position,
|
||||
# they're equal
|
||||
# they are equal
|
||||
return True
|
||||
elif (self.compareKeys(info, 'extnumber') and
|
||||
self.compareKeys(info, 'offset') and
|
||||
self.compareKeys(info, 'dir')):
|
||||
# If both specify the same relative offset, they're equal
|
||||
# If both specify the same relative offset, they are equal
|
||||
return True
|
||||
elif (self.compareKeys(info, 'alias')):
|
||||
# If both are aliases of the same value
|
||||
@@ -141,7 +172,7 @@ class BaseInfo:
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
# The same enum can't extend two different types
|
||||
# The same enum cannot extend two different types
|
||||
return False
|
||||
else:
|
||||
# Non-<enum>s should never be redefined
|
||||
@@ -248,7 +279,7 @@ class FeatureInfo(BaseInfo):
|
||||
enumerant offsets. <feature> features do not have extension
|
||||
numbers and are assigned number 0."""
|
||||
|
||||
# If there's no 'number' attribute, use 0, so sorting works
|
||||
# If there is no 'number' attribute, use 0, so sorting works
|
||||
if self.number is None:
|
||||
self.number = 0
|
||||
self.supported = elem.get('supported')
|
||||
@@ -260,6 +291,12 @@ class SpirvInfo(BaseInfo):
|
||||
def __init__(self, elem):
|
||||
BaseInfo.__init__(self, elem)
|
||||
|
||||
class FormatInfo(BaseInfo):
|
||||
"""Registry information about an API <format>."""
|
||||
|
||||
def __init__(self, elem):
|
||||
BaseInfo.__init__(self, elem)
|
||||
|
||||
class Registry:
|
||||
"""Object representing an API registry, loaded from an XML file."""
|
||||
|
||||
@@ -272,7 +309,9 @@ class Registry:
|
||||
"Output generator used to write headers / messages"
|
||||
|
||||
if genOpts is None:
|
||||
self.genOpts = GeneratorOptions()
|
||||
# If no generator is provided, we may still need the XML API name
|
||||
# (for example, in genRef.py).
|
||||
self.genOpts = GeneratorOptions(apiname = APIConventions().xml_api_name)
|
||||
else:
|
||||
self.genOpts = genOpts
|
||||
"Options controlling features to write and how to format them"
|
||||
@@ -311,6 +350,9 @@ class Registry:
|
||||
self.spirvcapdict = {}
|
||||
"dictionary of FeatureInfo objects for `<spirvcapability>` elements keyed by spirv capability name"
|
||||
|
||||
self.formatsdict = {}
|
||||
"dictionary of FeatureInfo objects for `<format>` elements keyed by VkFormat name"
|
||||
|
||||
self.emitFeatures = False
|
||||
"""True to actually emit features for a version / extension,
|
||||
or False to just treat them as emitted"""
|
||||
@@ -356,10 +398,10 @@ class Registry:
|
||||
|
||||
Intended for internal use only.
|
||||
|
||||
- elem - `<type>`/`<enums>`/`<enum>`/`<command>`/`<feature>`/`<extension>`/`<spirvextension>`/`<spirvcapability>` Element
|
||||
- elem - `<type>`/`<enums>`/`<enum>`/`<command>`/`<feature>`/`<extension>`/`<spirvextension>`/`<spirvcapability>`/`<format>` Element
|
||||
- info - corresponding {Type|Group|Enum|Cmd|Feature|Spirv}Info object
|
||||
- infoName - 'type' / 'group' / 'enum' / 'command' / 'feature' / 'extension' / 'spirvextension' / 'spirvcapability'
|
||||
- dictionary - self.{type|group|enum|cmd|api|ext|spirvext|spirvcap}dict
|
||||
- infoName - 'type' / 'group' / 'enum' / 'command' / 'feature' / 'extension' / 'spirvextension' / 'spirvcapability' / 'format'
|
||||
- dictionary - self.{type|group|enum|cmd|api|ext|format|spirvext|spirvcap}dict
|
||||
|
||||
If the Element has an 'api' attribute, the dictionary key is the
|
||||
tuple (name,api). If not, the key is the name. 'name' is an
|
||||
@@ -408,15 +450,26 @@ class Registry:
|
||||
# This must be the Element for the root <registry>
|
||||
self.reg = self.tree.getroot()
|
||||
|
||||
# Preprocess the tree by removing all elements with non-matching
|
||||
# 'api' attributes by breadth-first tree traversal.
|
||||
# This is a blunt hammer, but eliminates the need to track and test
|
||||
# the apis deeper in processing to select the correct elements and
|
||||
# avoid duplicates.
|
||||
# Schema validation should prevent duplicate elements with
|
||||
# overlapping api attributes, or where one element has an api
|
||||
# attribute and the other does not.
|
||||
|
||||
stripNonmatchingAPIs(self.reg, self.genOpts.apiname)
|
||||
|
||||
# Create dictionary of registry types from toplevel <types> tags
|
||||
# and add 'name' attribute to each <type> tag (where missing)
|
||||
# based on its <name> element.
|
||||
#
|
||||
# There's usually one <types> block; more are OK
|
||||
# There is usually one <types> block; more are OK
|
||||
# Required <type> attributes: 'name' or nested <name> tag contents
|
||||
self.typedict = {}
|
||||
for type_elem in self.reg.findall('types/type'):
|
||||
# If the <type> doesn't already have a 'name' attribute, set
|
||||
# If the <type> does not already have a 'name' attribute, set
|
||||
# it from contents of its <name> tag.
|
||||
if type_elem.get('name') is None:
|
||||
type_elem.set('name', type_elem.find('name').text)
|
||||
@@ -425,8 +478,8 @@ class Registry:
|
||||
# Create dictionary of registry enum groups from <enums> tags.
|
||||
#
|
||||
# Required <enums> attributes: 'name'. If no name is given, one is
|
||||
# generated, but that group can't be identified and turned into an
|
||||
# enum type definition - it's just a container for <enum> tags.
|
||||
# generated, but that group cannot be identified and turned into an
|
||||
# enum type definition - it is just a container for <enum> tags.
|
||||
self.groupdict = {}
|
||||
for group in self.reg.findall('enums'):
|
||||
self.addElementInfo(group, GroupInfo(group), 'group', self.groupdict)
|
||||
@@ -452,7 +505,7 @@ class Registry:
|
||||
# and add 'name' attribute to each <command> tag (where missing)
|
||||
# based on its <proto><name> element.
|
||||
#
|
||||
# There's usually only one <commands> block; more are OK.
|
||||
# There is usually only one <commands> block; more are OK.
|
||||
# Required <command> attributes: 'name' or <proto><name> tag contents
|
||||
self.cmddict = {}
|
||||
# List of commands which alias others. Contains
|
||||
@@ -460,7 +513,7 @@ class Registry:
|
||||
# for each alias
|
||||
cmdAlias = []
|
||||
for cmd in self.reg.findall('commands/command'):
|
||||
# If the <command> doesn't already have a 'name' attribute, set
|
||||
# If the <command> does not already have a 'name' attribute, set
|
||||
# it from contents of its <proto><name> tag.
|
||||
name = cmd.get('name')
|
||||
if name is None:
|
||||
@@ -507,11 +560,11 @@ class Registry:
|
||||
# Instead, generateRequiredInterface ignores <enum> elements
|
||||
# that extend enumerated types.
|
||||
#
|
||||
# For <enum> tags which are actually just constants, if there's
|
||||
# For <enum> tags which are actually just constants, if there is
|
||||
# no 'extends' tag but there is a 'value' or 'bitpos' tag, just
|
||||
# add an EnumInfo record to the dictionary. That works because
|
||||
# output generation of constants is purely dependency-based, and
|
||||
# doesn't need to iterate through the XML tags.
|
||||
# does not need to iterate through the XML tags.
|
||||
for elem in feature.findall('require'):
|
||||
for enum in elem.findall('enum'):
|
||||
addEnumInfo = False
|
||||
@@ -599,7 +652,7 @@ class Registry:
|
||||
for parent in parentStructs.split(','):
|
||||
# self.gen.logMsg('diag', type.get('name'), 'extends', parent)
|
||||
self.validextensionstructs[parent].append(type_elem.get('name'))
|
||||
# Sort the lists so they don't depend on the XML order
|
||||
# Sort the lists so they do not depend on the XML order
|
||||
for parent in self.validextensionstructs:
|
||||
self.validextensionstructs[parent].sort()
|
||||
|
||||
@@ -612,6 +665,10 @@ class Registry:
|
||||
spirvInfo = SpirvInfo(spirv)
|
||||
self.addElementInfo(spirv, spirvInfo, 'spirvcapability', self.spirvcapdict)
|
||||
|
||||
for format in self.reg.findall('formats/format'):
|
||||
formatInfo = FormatInfo(format)
|
||||
self.addElementInfo(format, formatInfo, 'format', self.formatsdict)
|
||||
|
||||
def dumpReg(self, maxlen=120, filehandle=sys.stdout):
|
||||
"""Dump all the dictionaries constructed from the Registry object.
|
||||
|
||||
@@ -651,6 +708,10 @@ class Registry:
|
||||
for key in self.spirvcapdict:
|
||||
write(' SPIR-V Capability', key, '->',
|
||||
etree.tostring(self.spirvcapdict[key].elem)[0:maxlen], file=filehandle)
|
||||
write('// VkFormat', file=filehandle)
|
||||
for key in self.formatsdict:
|
||||
write(' VkFormat', key, '->',
|
||||
etree.tostring(self.formatsdict[key].elem)[0:maxlen], file=filehandle)
|
||||
|
||||
def markTypeRequired(self, typename, required):
|
||||
"""Require (along with its dependencies) or remove (but not its dependencies) a type.
|
||||
@@ -671,7 +732,7 @@ class Registry:
|
||||
if depname:
|
||||
self.gen.logMsg('diag', 'Generating dependent type',
|
||||
depname, 'for', attrib_name, 'type', typename)
|
||||
# Don't recurse on self-referential structures.
|
||||
# Do not recurse on self-referential structures.
|
||||
if typename != depname:
|
||||
self.markTypeRequired(depname, required)
|
||||
else:
|
||||
@@ -718,10 +779,10 @@ class Registry:
|
||||
if enum is not None:
|
||||
# If the enum is part of a group, and is being removed, then
|
||||
# look it up in that <group> tag and remove it there, so that it
|
||||
# isn't visible to generators (which traverse the <group> tag
|
||||
# is not visible to generators (which traverse the <group> tag
|
||||
# elements themselves).
|
||||
# This isn't the most robust way of doing this, since a removed
|
||||
# enum that's later required again will no longer have a group
|
||||
# This is not the most robust way of doing this, since a removed
|
||||
# enum that is later required again will no longer have a group
|
||||
# element, but it makes the change non-intrusive on generator
|
||||
# code.
|
||||
if required is False:
|
||||
@@ -762,12 +823,23 @@ class Registry:
|
||||
cmd = self.lookupElementInfo(cmdname, self.cmddict)
|
||||
if cmd is not None:
|
||||
cmd.required = required
|
||||
|
||||
# Tag command dependencies in 'alias' attribute as required
|
||||
depname = cmd.elem.get('alias')
|
||||
if depname:
|
||||
self.gen.logMsg('diag', 'Generating dependent command',
|
||||
depname, 'for alias', cmdname)
|
||||
self.markCmdRequired(depname, required)
|
||||
#
|
||||
# This is usually not done, because command 'aliases' are not
|
||||
# actual C language aliases like type and enum aliases. Instead
|
||||
# they are just duplicates of the function signature of the
|
||||
# alias. This means that there is no dependency of a command
|
||||
# alias on what it aliases. One exception is validity includes,
|
||||
# where the spec markup needs the promoted-to validity include
|
||||
# even if only the promoted-from command is being built.
|
||||
if self.genOpts.requireCommandAliases:
|
||||
depname = cmd.elem.get('alias')
|
||||
if depname:
|
||||
self.gen.logMsg('diag', 'Generating dependent command',
|
||||
depname, 'for alias', cmdname)
|
||||
self.markCmdRequired(depname, required)
|
||||
|
||||
# Tag all parameter types of this command as required.
|
||||
# This DOES NOT remove types of commands in a <remove>
|
||||
# tag, because many other commands may use the same type.
|
||||
@@ -792,7 +864,7 @@ class Registry:
|
||||
|
||||
# Loop over types, enums, and commands in the tag
|
||||
# @@ It would be possible to respect 'api' and 'profile' attributes
|
||||
# in individual features, but that's not done yet.
|
||||
# in individual features, but that is not done yet.
|
||||
for typeElem in feature.findall('type'):
|
||||
self.markTypeRequired(typeElem.get('name'), required)
|
||||
for enumElem in feature.findall('enum'):
|
||||
@@ -842,8 +914,13 @@ class Registry:
|
||||
- require - `<require>` block from the registry
|
||||
- tag - tag to look for in the require block"""
|
||||
|
||||
if alias and require.findall(tag + "[@name='" + alias + "']"):
|
||||
return True
|
||||
# For the time being, the code below is bypassed. It has the effect
|
||||
# of excluding "spelling aliases" created to comply with the style
|
||||
# guide, but this leaves references out of the specification and
|
||||
# causes broken internal links.
|
||||
#
|
||||
# if alias and require.findall(tag + "[@name='" + alias + "']"):
|
||||
# return True
|
||||
|
||||
return False
|
||||
|
||||
@@ -887,7 +964,7 @@ class Registry:
|
||||
typeinfo = self.lookupElementInfo(typename, self.typedict)
|
||||
|
||||
if typeinfo:
|
||||
# Remove aliases in the same extension/feature; these are always added as a correction. Don't need the original to be visible.
|
||||
# Remove aliases in the same extension/feature; these are always added as a correction. Do not need the original to be visible.
|
||||
alias = self.getAlias(typeElem, self.typedict)
|
||||
if not self.checkForCorrectionAliases(alias, require, 'type'):
|
||||
# Resolve the type info to the actual type, so we get an accurate read for 'structextends'
|
||||
@@ -902,12 +979,15 @@ class Registry:
|
||||
if not typeextends in self.gen.featureDictionary[featurename][typecat][required_key]:
|
||||
self.gen.featureDictionary[featurename][typecat][required_key][typeextends] = []
|
||||
self.gen.featureDictionary[featurename][typecat][required_key][typeextends].append(typename)
|
||||
else:
|
||||
self.gen.logMsg('warn', 'fillFeatureDictionary: NOT filling for {}'.format(typename))
|
||||
|
||||
|
||||
for enumElem in require.findall('enum'):
|
||||
enumname = enumElem.get('name')
|
||||
typeinfo = self.lookupElementInfo(enumname, self.enumdict)
|
||||
|
||||
# Remove aliases in the same extension/feature; these are always added as a correction. Don't need the original to be visible.
|
||||
# Remove aliases in the same extension/feature; these are always added as a correction. Do not need the original to be visible.
|
||||
alias = self.getAlias(enumElem, self.enumdict)
|
||||
if not self.checkForCorrectionAliases(alias, require, 'enum'):
|
||||
enumextends = enumElem.get('extends')
|
||||
@@ -916,16 +996,18 @@ class Registry:
|
||||
if not enumextends in self.gen.featureDictionary[featurename]['enumconstant'][required_key]:
|
||||
self.gen.featureDictionary[featurename]['enumconstant'][required_key][enumextends] = []
|
||||
self.gen.featureDictionary[featurename]['enumconstant'][required_key][enumextends].append(enumname)
|
||||
else:
|
||||
self.gen.logMsg('warn', 'fillFeatureDictionary: NOT filling for {}'.format(typename))
|
||||
|
||||
for cmdElem in require.findall('command'):
|
||||
|
||||
# Remove aliases in the same extension/feature; these are always added as a correction. Don't need the original to be visible.
|
||||
# Remove aliases in the same extension/feature; these are always added as a correction. Do not need the original to be visible.
|
||||
alias = self.getAlias(cmdElem, self.cmddict)
|
||||
if not self.checkForCorrectionAliases(alias, require, 'command'):
|
||||
if not required_key in self.gen.featureDictionary[featurename]['command']:
|
||||
self.gen.featureDictionary[featurename]['command'][required_key] = []
|
||||
self.gen.featureDictionary[featurename]['command'][required_key].append(cmdElem.get('name'))
|
||||
|
||||
else:
|
||||
self.gen.logMsg('warn', 'fillFeatureDictionary: NOT filling for {}'.format(typename))
|
||||
|
||||
def requireAndRemoveFeatures(self, interface, featurename, api, profile):
|
||||
"""Process `<require>` and `<remove>` tags for a `<version>` or `<extension>`.
|
||||
@@ -935,10 +1017,12 @@ class Registry:
|
||||
- featurename - name of the feature
|
||||
- api - string specifying API name being generated
|
||||
- profile - string specifying API profile being generated"""
|
||||
|
||||
# <require> marks things that are required by this version/profile
|
||||
for feature in interface.findall('require'):
|
||||
if matchAPIProfile(api, profile, feature):
|
||||
self.markRequired(featurename, feature, True)
|
||||
|
||||
# <remove> marks things that are removed by this version/profile
|
||||
for feature in interface.findall('remove'):
|
||||
if matchAPIProfile(api, profile, feature):
|
||||
@@ -979,7 +1063,7 @@ class Registry:
|
||||
'returning!')
|
||||
return
|
||||
|
||||
# If feature isn't required, or has already been declared, return
|
||||
# If feature is not required, or has already been declared, return
|
||||
if not f.required:
|
||||
self.gen.logMsg('diag', 'Skipping', ftype, fname, '(not required)')
|
||||
return
|
||||
@@ -1056,7 +1140,7 @@ class Registry:
|
||||
# @ The enum group is not ready for generation. At this
|
||||
# @ point, it contains all <enum> tags injected by
|
||||
# @ <extension> tags without any verification of whether
|
||||
# @ they're required or not. It may also contain
|
||||
# @ they are required or not. It may also contain
|
||||
# @ duplicates injected by multiple consistent
|
||||
# @ definitions of an <enum>.
|
||||
|
||||
@@ -1094,7 +1178,7 @@ class Registry:
|
||||
if required:
|
||||
# Mark this element as required (in the element, not the EnumInfo)
|
||||
elem.set('required', 'true')
|
||||
# If it's an alias, track that for later use
|
||||
# If it is an alias, track that for later use
|
||||
enumAlias = elem.get('alias')
|
||||
if enumAlias:
|
||||
enumAliases.append(enumAlias)
|
||||
@@ -1145,7 +1229,7 @@ class Registry:
|
||||
for t in features.findall('type'):
|
||||
self.generateFeature(t.get('name'), 'type', self.typedict)
|
||||
for e in features.findall('enum'):
|
||||
# If this is an enum extending an enumerated type, don't
|
||||
# If this is an enum extending an enumerated type, do not
|
||||
# generate it - this has already been done in reg.parseTree,
|
||||
# by copying this element into the enumerated type.
|
||||
enumextends = e.get('extends')
|
||||
@@ -1167,6 +1251,45 @@ class Registry:
|
||||
genProc = self.gen.genSpirv
|
||||
genProc(spirv, name, alias)
|
||||
|
||||
def stripUnsupportedAPIs(self, dictionary, attribute, supportedDictionary):
|
||||
"""Strip unsupported APIs from attributes of APIs.
|
||||
dictionary - *Info dictionary of APIs to be updated
|
||||
attribute - attribute name to look for in each API
|
||||
supportedDictionary - dictionary in which to look for supported
|
||||
API elements in the attribute"""
|
||||
|
||||
for key in dictionary:
|
||||
eleminfo = dictionary[key]
|
||||
attribstring = eleminfo.elem.get(attribute)
|
||||
if attribstring is not None:
|
||||
apis = []
|
||||
stripped = False
|
||||
for api in attribstring.split(','):
|
||||
##print('Checking API {} referenced by {}'.format(api, key))
|
||||
if supportedDictionary[api].required:
|
||||
apis.append(api)
|
||||
else:
|
||||
stripped = True
|
||||
##print('\t**STRIPPING API {} from {}'.format(api, key))
|
||||
|
||||
# Update the attribute after stripping stuff.
|
||||
# Could sort apis before joining, but it is not a clear win
|
||||
if stripped:
|
||||
eleminfo.elem.set(attribute, ','.join(apis))
|
||||
|
||||
def generateFormat(self, format, dictionary):
|
||||
if format is None:
|
||||
self.gen.logMsg('diag', 'No entry found for format element',
|
||||
'returning!')
|
||||
return
|
||||
|
||||
name = format.elem.get('name')
|
||||
# No known alias for VkFormat elements
|
||||
alias = None
|
||||
if format.emit:
|
||||
genProc = self.gen.genFormat
|
||||
genProc(format, name, alias)
|
||||
|
||||
def apiGen(self):
|
||||
"""Generate interface for specified versions using the current
|
||||
generator and generator options"""
|
||||
@@ -1177,8 +1300,13 @@ class Registry:
|
||||
'profile:', self.genOpts.profile)
|
||||
self.gen.logMsg('diag', '*******************************************')
|
||||
|
||||
# Reset required/declared flags for all features
|
||||
self.apiReset()
|
||||
# Could reset required/declared flags for all features here.
|
||||
# This has been removed as never used. The initial motivation was
|
||||
# the idea of calling apiGen() repeatedly for different targets, but
|
||||
# this has never been done. The 20% or so build-time speedup that
|
||||
# might result is not worth the effort to make it actually work.
|
||||
#
|
||||
# self.apiReset()
|
||||
|
||||
# Compile regexps used to select versions & extensions
|
||||
regVersions = re.compile(self.genOpts.versions)
|
||||
@@ -1187,6 +1315,7 @@ class Registry:
|
||||
regRemoveExtensions = re.compile(self.genOpts.removeExtensions)
|
||||
regEmitExtensions = re.compile(self.genOpts.emitExtensions)
|
||||
regEmitSpirv = re.compile(self.genOpts.emitSpirv)
|
||||
regEmitFormats = re.compile(self.genOpts.emitFormats)
|
||||
|
||||
# Get all matching API feature names & add to list of FeatureInfo
|
||||
# Note we used to select on feature version attributes, not names.
|
||||
@@ -1242,7 +1371,7 @@ class Registry:
|
||||
|
||||
# Include additional extensions if the extension name matches
|
||||
# the regexp specified in the generator options. This allows
|
||||
# forcing extensions into an interface even if they're not
|
||||
# forcing extensions into an interface even if they are not
|
||||
# tagged appropriately in the registry.
|
||||
# However we still respect the 'supported' attribute.
|
||||
if regAddExtensions.match(extName) is not None:
|
||||
@@ -1256,7 +1385,7 @@ class Registry:
|
||||
include = True
|
||||
# Remove extensions if the name matches the regexp specified
|
||||
# in generator options. This allows forcing removal of
|
||||
# extensions from an interface even if they're tagged that
|
||||
# extensions from an interface even if they are tagged that
|
||||
# way in the registry.
|
||||
if regRemoveExtensions.match(extName) is not None:
|
||||
self.gen.logMsg('diag', 'Removing extension',
|
||||
@@ -1274,8 +1403,8 @@ class Registry:
|
||||
'for emission (does not match emitextensions pattern)')
|
||||
|
||||
# Hack - can be removed when validity generator goes away
|
||||
# (Jon) I'm not sure what this does, or if it should respect
|
||||
# the ei.emit flag above.
|
||||
# (Jon) I am not sure what this does, or if it should
|
||||
# respect the ei.emit flag above.
|
||||
self.requiredextensions.append(extName)
|
||||
else:
|
||||
self.gen.logMsg('diag', 'NOT including extension',
|
||||
@@ -1295,6 +1424,12 @@ class Registry:
|
||||
si.emit = (regEmitSpirv.match(key) is not None)
|
||||
spirvcaps.append(si)
|
||||
|
||||
formats = []
|
||||
for key in self.formatsdict:
|
||||
si = self.formatsdict[key]
|
||||
si.emit = (regEmitFormats.match(key) is not None)
|
||||
formats.append(si)
|
||||
|
||||
# Sort the features list, if a sort procedure is defined
|
||||
if self.genOpts.sortProcedure:
|
||||
self.genOpts.sortProcedure(features)
|
||||
@@ -1316,8 +1451,23 @@ class Registry:
|
||||
self.requireAndRemoveFeatures(f.elem, f.name, self.genOpts.apiname, self.genOpts.profile)
|
||||
self.assignAdditionalValidity(f.elem, self.genOpts.apiname, self.genOpts.profile)
|
||||
|
||||
# Now, strip references to APIs that are not required.
|
||||
# At present such references may occur in:
|
||||
# Structs in <type category="struct"> 'structextends' attributes
|
||||
# Enums in <command> 'successcodes' and 'errorcodes' attributes
|
||||
self.stripUnsupportedAPIs(self.typedict, 'structextends', self.typedict)
|
||||
self.stripUnsupportedAPIs(self.cmddict, 'successcodes', self.enumdict)
|
||||
self.stripUnsupportedAPIs(self.cmddict, 'errorcodes', self.enumdict)
|
||||
|
||||
# @@May need to strip <spirvcapability> / <spirvextension> <enable>
|
||||
# tags of these forms:
|
||||
# <enable version="VK_API_VERSION_1_0"/>
|
||||
# <enable struct="VkPhysicalDeviceFeatures" feature="geometryShader" requires="VK_VERSION_1_0"/>
|
||||
# <enable extension="VK_KHR_shader_draw_parameters"/>
|
||||
# <enable property="VkPhysicalDeviceVulkan12Properties" member="shaderDenormPreserveFloat16" value="VK_TRUE" requires="VK_VERSION_1_2,VK_KHR_shader_float_controls"/>
|
||||
|
||||
# Pass 2: loop over specified API versions and extensions printing
|
||||
# declarations for required things which haven't already been
|
||||
# declarations for required things which have not already been
|
||||
# generated.
|
||||
self.gen.logMsg('diag', 'PASS 2: GENERATE INTERFACES FOR FEATURES')
|
||||
self.gen.beginFile(self.genOpts)
|
||||
@@ -1329,7 +1479,7 @@ class Registry:
|
||||
self.gen.logMsg('diag', 'PASS 2: NOT declaring feature',
|
||||
f.elem.get('name'), 'because it is not tagged for emission')
|
||||
# Generate the interface (or just tag its elements as having been
|
||||
# emitted, if they haven't been).
|
||||
# emitted, if they have not been).
|
||||
self.gen.beginFeature(f.elem, emit)
|
||||
self.generateRequiredInterface(f.elem)
|
||||
self.gen.endFeature()
|
||||
@@ -1338,6 +1488,8 @@ class Registry:
|
||||
self.generateSpirv(s, self.spirvextdict)
|
||||
for s in spirvcaps:
|
||||
self.generateSpirv(s, self.spirvcapdict)
|
||||
for s in formats:
|
||||
self.generateFormat(s, self.formatsdict)
|
||||
self.gen.endFile()
|
||||
|
||||
def apiReset(self):
|
||||
@@ -1353,39 +1505,44 @@ class Registry:
|
||||
for cmd in self.apidict:
|
||||
self.apidict[cmd].resetState()
|
||||
|
||||
def validateGroups(self):
|
||||
"""Validate `group=` attributes on `<param>` and `<proto>` tags.
|
||||
def __validateStructLimittypes(self, struct):
|
||||
"""Validate 'limittype' attributes for a single struct."""
|
||||
limittypeDiags = namedtuple('limittypeDiags', ['missing', 'invalid'])
|
||||
badFields = defaultdict(lambda : limittypeDiags(missing=[], invalid=[]))
|
||||
validLimittypes = { 'min', 'max', 'bitmask', 'range', 'struct', 'noauto' }
|
||||
for member in struct.getMembers():
|
||||
memberName = member.findtext('name')
|
||||
if memberName in ['sType', 'pNext']:
|
||||
continue
|
||||
limittype = member.get('limittype')
|
||||
if not limittype:
|
||||
badFields[struct.elem.get('name')].missing.append(memberName)
|
||||
elif limittype == 'struct':
|
||||
typeName = member.findtext('type')
|
||||
memberType = self.typedict[typeName]
|
||||
badFields.update(self.__validateStructLimittypes(memberType))
|
||||
elif limittype not in validLimittypes:
|
||||
badFields[struct.elem.get('name')].invalid.append(memberName)
|
||||
return badFields
|
||||
|
||||
Check that `group=` attributes match actual groups"""
|
||||
# Keep track of group names not in <group> tags
|
||||
badGroup = {}
|
||||
self.gen.logMsg('diag', 'VALIDATING GROUP ATTRIBUTES')
|
||||
for cmd in self.reg.findall('commands/command'):
|
||||
proto = cmd.find('proto')
|
||||
# funcname = cmd.find('proto/name').text
|
||||
group = proto.get('group')
|
||||
if group is not None and group not in self.groupdict:
|
||||
# self.gen.logMsg('diag', '*** Command ', funcname, ' has UNKNOWN return group ', group)
|
||||
if group not in badGroup:
|
||||
badGroup[group] = 1
|
||||
else:
|
||||
badGroup[group] = badGroup[group] + 1
|
||||
def __validateLimittype(self):
|
||||
"""Validate 'limittype' attributes."""
|
||||
badFields = self.__validateStructLimittypes(self.typedict['VkPhysicalDeviceProperties2'])
|
||||
for featStructName in self.validextensionstructs['VkPhysicalDeviceProperties2']:
|
||||
featStruct = self.typedict[featStructName]
|
||||
badFields.update(self.__validateStructLimittypes(featStruct))
|
||||
|
||||
for param in cmd.findall('param'):
|
||||
pname = param.find('name')
|
||||
if pname is not None:
|
||||
pname = pname.text
|
||||
else:
|
||||
pname = param.get('name')
|
||||
group = param.get('group')
|
||||
if group is not None and group not in self.groupdict:
|
||||
# self.gen.logMsg('diag', '*** Command ', funcname, ' param ', pname, ' has UNKNOWN group ', group)
|
||||
if group not in badGroup:
|
||||
badGroup[group] = 1
|
||||
else:
|
||||
badGroup[group] = badGroup[group] + 1
|
||||
if badFields:
|
||||
self.gen.logMsg('diag', 'SUMMARY OF FIELDS WITH INCORRECT LIMITTYPES')
|
||||
for key in sorted(badFields.keys()):
|
||||
diags = badFields[key]
|
||||
if diags.missing:
|
||||
self.gen.logMsg('diag', ' ', key, 'missing limittype:', ', '.join(badFields[key].missing))
|
||||
if diags.invalid:
|
||||
self.gen.logMsg('diag', ' ', key, 'invalid limittype:', ', '.join(badFields[key].invalid))
|
||||
return False
|
||||
return True
|
||||
|
||||
if badGroup:
|
||||
self.gen.logMsg('diag', 'SUMMARY OF UNRECOGNIZED GROUPS')
|
||||
for key in sorted(badGroup.keys()):
|
||||
self.gen.logMsg('diag', ' ', key, ' occurred ', badGroup[key], ' times')
|
||||
def validateRegistry(self):
|
||||
"""Validate properties of the registry."""
|
||||
return self.__validateLimittype()
|
||||
|
8648
externals/Vulkan-Headers/registry/validusage.json
vendored
8648
externals/Vulkan-Headers/registry/validusage.json
vendored
File diff suppressed because one or more lines are too long
4047
externals/Vulkan-Headers/registry/vk.xml
vendored
4047
externals/Vulkan-Headers/registry/vk.xml
vendored
File diff suppressed because it is too large
Load Diff
@@ -31,6 +31,7 @@ SPECIAL_WORDS = set((
|
||||
'Int64', # VkPhysicalDeviceShaderAtomicInt64FeaturesKHR
|
||||
'Int8', # VkPhysicalDeviceShaderFloat16Int8FeaturesKHR
|
||||
'MacOS', # VkMacOSSurfaceCreateInfoMVK
|
||||
'RGBA10X6', # VkPhysicalDeviceRGBA10X6FormatsFeaturesEXT
|
||||
'Uint8', # VkPhysicalDeviceIndexTypeUint8FeaturesEXT
|
||||
'Win32', # VkWin32SurfaceCreateInfoKHR
|
||||
))
|
||||
@@ -168,7 +169,7 @@ class VulkanConventions(ConventionsBase):
|
||||
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 aren't to ref pages can link into it
|
||||
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.
|
||||
"""
|
||||
@@ -208,7 +209,7 @@ class VulkanConventions(ConventionsBase):
|
||||
@property
|
||||
def unified_flag_refpages(self):
|
||||
"""Return True if Flags/FlagBits refpages are unified, False if
|
||||
they're separate.
|
||||
they are separate.
|
||||
"""
|
||||
return False
|
||||
|
||||
@@ -231,7 +232,8 @@ class VulkanConventions(ConventionsBase):
|
||||
def category_requires_validation(self, category):
|
||||
"""Return True if the given type 'category' always requires validation.
|
||||
|
||||
Overridden because Vulkan doesn't require "valid" text for basetype in the spec right now."""
|
||||
Overridden because Vulkan does not require "valid" text for basetype
|
||||
in the spec right now."""
|
||||
return category in CATEGORIES_REQUIRING_VALIDATION
|
||||
|
||||
@property
|
||||
|
Reference in New Issue
Block a user