Theme

alex/volcanic

Automated vulkan bindings

BRANCH main
main
SNAPSHOT Improved loading api and made ready for publish
DOWNLOAD
Download file

root / spec / registry.rnc

# Copyright 2013-2026 The Khronos Group Inc.
# SPDX-License-Identifier: Apache-2.0

# Relax NG schema for Khronos API Registry XML
#
# This definition is subject to change (mostly in the form of additions)

namespace xsd = "http://www.w3.org/2001/XMLSchema-datatypes"

# Toplevel is a <registry> tag.
# May be led by an optional <comment> tag containing e.g. copyrights.
start =
    element registry {
        (CommentElt?
         | Platforms*
         | Tags*
         | Types*
         | Enums*
         | Commands*
         | Feature*
         | Extensions*
         | Formats*
         | Sync*
         | VideoCodecs*
         | SpirvExtensions*
         | SpirvCapabilities*)*
    }

# <platforms> defines a group of platform names
Platforms = element platforms { CommentAttr?, Platform* }

# <platform> defines a single platform name.
#   name - string name of the platform, used as part of extension names
#   protect - preprocessor symbol to include platform headers from <vulkan.h>
#   comment - platform description
Platform =
    element platform {
        attribute name {
            xsd:NCName { pattern = "[a-z0-9_]+" }
        },
        ProtectAttr,
        CommentAttr
    }

# <tags> defines a group of author tags
Tags = element tags { CommentAttr?, Tag* }

# <tag> defines a single author tag.
#   name - name of the tag
#   author - name of the author (usually a company or project name)
#   contact - contact responsible for the tag (name and contact information)
Tag =
    element tag {
        attribute name { VendorId_t },
        attribute author { text },
        attribute contact { text }
    }

# <types> defines a group of types
Types = element types { CommentAttr?, (Type | CommentElt)* }

# <type> defines a single type. It is usually a C typedef but
# may contain arbitrary C code.
# There are many possible valid attribute and tag body combinations, mostly
# determined by the "category" attribute.
# The rules below try to reflect the "category".
# Unfortunately, there is some apparently unavoidable redundancy because
# every category supports a "name" / "alias" combination to define a type
# alias, as well as a more detailed schema for defining a non-aliased type.
#
# The attributes are fully described in the registry schema document.


#
#   name - name of this type, if not present in the <name> tag
#   api - matches a <feature> api attribute, if present
#   alias - name of a type this type aliases
#   requires - name of another type definition required by this one
#   bitvalues - for a *Flags type, name of an enum definition that
#       defines the valid values for parameters of that type
#   category - if present, 'enum' indicates a matching <enums>
#       block to generate an enumerated type for, and 'struct'
#       causes special interpretation of the contents of the type
#       tag including ... TBD ...
#       Other allowed values are 'include', 'define', 'handle' and 'bitmask',
#       which do not change syntactic interpretation but allow organization
#       in the generated header.
#   deprecated - denotes that this type is marked as legacy, and why.
#       Valid values: 'aliased', 'true'.
#   parent - only applicable if category is 'handle'. Notes another type with
#       the 'handle' category that acts as a parent object for this type.
#   returnedonly - only applicable if category is 'struct'. Notes that this
#       struct is going to be filled in by the API, rather than an application
#       filling it out and passing it to the API.
#   structextends - only applicable if category is 'struct'. Lists parent
#       structures which this structure may extend via the pNext chain
#       of the parent.
#       When present it suppresses generation of automatic validity for the
#       pNext member of that structure, and instead the structure is added
#       to pNext chain validity for the parent structures it extends.
#   allowduplicate - only applicable if category is 'struct'. pNext can include
#       multiple structures of this type.
#   objtypeenum - name of VK_OBJECT_TYPE_* API enumerant which corresponds
#       to this type. Currently only specified for category="handle" types.
#   requiredlimittype - only applicable if category is 'struct'.
#       If 'true', member tags other than sType and pNext must have limittype
#       attributes.
#       Valid values: 'true', 'false'.
#   comment - descriptive text with no semantic meaning
# For types without a category, contents include
#   <name> - contains name of the type being defined
#   <type> - contains name of types used to define this type. There
#       may be multiple imbedded <type> tags
# For types with category 'enum', contents should be empty
# For types with category 'struct', contents should be one or more
#   <member> - like <param> for a struct or union member
#       len - if the member is an array, len may be one or more of the following
#           things, separated by commas (one for each array indirection):
#           (a) a latex equation (prefixed with 'latexmath:');
#           (b) the name of another member of the struct specifying the length
#           for corresponding indirection;
#           (c) 'null-terminated', indicating a pointer to a null-terminated
#           UTF-8 string
#           (d)'1' to indicate it is just a pointer (used for nested pointers);
#           (e) a C99 expression that refers to another member of the struct
#           indirectly specifying the length for corresponding indirection;
#           (f) or a custom expression that cannot be used directly by
#           code generation and needs manual handling.
#       altlen - if len has latexmath equations (a), this contains one or more
#           of (b), (c), (d), (e), or (f) above, separated by commas (one for
#           each array indirection).
#       stride - if the member is an array, stride specifies the name of
#           another member containing the byte stride between consecutive
#           elements in the array. The array is assumed to be tightly packed
#           if omitted.
#       deprecated - denotes that this member is marked as legacy, and why.
#           Valid values: 'unused', 'true'.
#           If the value is 'unused', the member must always be set to 0.
#       externsync - denotes that the member should be externally synchronized
#           when accessed by Vulkan
#       optional - whether this value can be omitted by providing NULL (for
#           pointers), VK_NULL_HANDLE (for handles) or 0 (for bitmasks/values)
#       selector - for a union member, identifies a separate enum member that
#           selects which of the union's members are valid
#       selection - for a member of a union, identifies one or more comma-separated
#           enum values indicating that member is valid
#       noautovalidity - tag stating that no automatic validity language should be generated
#       values - comma-separated list of legal values, usually used only for sType enums
#       limittype - only applicable for members of VkPhysicalDeviceProperties and
#           VkPhysicalDeviceProperties2, their substructures, and extensions.
#           Specifies the type of a device limit.
#           Valid values: 'min', 'max', 'not', 'pot', 'mul', 'bits', bitmask', 'range', 'struct', 'exact', 'noauto'
#       objecttype - only applicable for members representing a handle as
#           a uint64_t value. Specifies the name of another member which is
#           a VkObjectType or VkDebugReportObjectTypeEXT value specifying
#           the type of object the handle references.
#       featurelink - only applicable for members representing a Boolean API
#           feature. Specifies that the feature has a link in the
#           specification that does not match the name of the feature.
#           Typically for features in extensions that were later promoted but
#           with changes.
#   <comment> - containing arbitrary text (unused)
#

# Attributes shared by (almost all) type tags
CommonTypeAttributes =
    ApiAttr?,
    CommentAttr?,
    attribute requires { text }?,
    attribute deprecated { "unused" | "true" }?

# Type declarations with some minimal structure - a single <name> tag
# preceded and followed by any amount of text mixed with <type> tags.
TypeBody =
        mixed {
          element type { TypeName_t }
        }*,
        mixed {
         element name { attribute alias { text }?, TypeName_t }?
        }?,
        mixed {
          ( element type { TypeName_t }
            | CommentElt
          )
        }*

# Type declarations for fixed-size arrays - like TypeBody above but also
# allows <enum> tags following the type name, which accommodates all the
# uses in the Vulkan XML.
TypeBodyWithEnum =
        mixed {
          element type { TypeName_t }
        }*,
        mixed {
          element name { attribute alias { text }?, TypeName_t }?
        }?,
        mixed {
          ( element type { TypeName_t }
            | element enum { VkDefineOrEnumName_t }
            | CommentElt
          )
        }*

Type =
    element type {
        TypeBasetype
      | TypeBitmask
      | TypeDefine
      | TypeEnum
      | TypeFuncpointer
      | TypeHandle
      | TypeInclude
      | TypeRequires
      | TypeStruct
    }

TypeBasetype =
    CommonTypeAttributes,
    attribute category { "basetype" },
    TypeBody

TypeBitmask =
    CommonTypeAttributes,
    attribute category { "bitmask" },
    (
       ( NameAttr,
         attribute alias { text }
       )
     | ( NameAttr?,
         attribute bitvalues { text }?,
         TypeBody
       )
    )

TypeDefine =
    CommonTypeAttributes,
    attribute category { "define" },
    NameAttr?,
    TypeBody

TypeEnum =
    CommonTypeAttributes,
    attribute category { "enum" },
    NameAttr,
    attribute alias { text }?

# funcpointers do not support "alias" attributes yet
TypeFuncpointer =
    CommonTypeAttributes,
    attribute category { "funcpointer" },
    element proto {
        mixed {
            element type { TypeName_t }?,
            element name { text }
        }
    },
    element param {
        ApiAttr?,
        attribute len { text }?,
        attribute altlen { text }?,
        attribute stride { text }?,
        attribute externsync { text }?,
        OptionalAttr?,
        attribute selector { text }?,
        NoAutoValidityAttr?,
        attribute objecttype { text }?,
        attribute validstructs { VkTypeNameListRef_t }?,
        mixed {
            element type { TypeName_t }?,
            element name { text }?
        }
    }*

TypeHandle =
    CommonTypeAttributes,
    attribute category { "handle" },
    (
       ( NameAttr,
         attribute alias { text }
       )
     | ( attribute parent { TypeName_t }?,
         attribute objtypeenum { text },
         TypeBody
       )
    )

TypeInclude =
    CommonTypeAttributes,
    attribute category { "include" },
    attribute name { text },
    text

# Cannot use CommonTypeAttributes because "requires" is not optional for
# this pattern.
TypeRequires =
    ApiAttr?,
    CommentAttr?,
    attribute deprecated { "unused" | "true" }?,
    attribute name { TypeName_t },
    attribute requires { text }

TypeStruct =
    CommonTypeAttributes,
    attribute category { "struct" | "union" },
    (
       ( NameAttr,
         attribute alias { text }
       )
     | ( attribute name { TypeName_t },
         attribute returnedonly { "true" }?,
         attribute structextends { StringList_t }?,
         attribute allowduplicate { "true" | "false" }?,
         attribute requiredlimittype { "true" }?,
         (
           element member {
               ApiAttr?,
               attribute len { text }?,
               attribute altlen { text }?,
               attribute stride { text }?,
               attribute externsync { text }?,
               OptionalAttr?,
               attribute selector { text }?,
               attribute selection { VkEnumNameList_t }?,
               NoAutoValidityAttr?,
               attribute values { VkEnumNameList_t }?,
               attribute limittype { text }?,
               attribute objecttype { text }?,
               attribute deprecated { text }?,
               attribute featurelink { text }?,
               attribute flagsextend { VkTypeNameRef_t }?,
               attribute flagsextendmember { TypeName_t }?,
               TypeBodyWithEnum
           }
           | CommentElt
         )*
       )
    )

# <enums> defines a group of enumerants
#   name - identifies a type name associated with this group. Should
#       match a <type> name to trigger generation of the type.
#   type - 'bitmask', 'constants' or 'enum'.
#   bitwidth - bit width of the enum value type.
#   comment - descriptive text with no semantic meaning
Enums =
    element enums {
        attribute name { text }?,
        attribute type { text },
        attribute bitwidth { "32" | "64" } ?,
        CommentAttr?,
        (Enum | Unused | CommentElt)*
    }

# <enum> defines or references a single enumerant. There are two places it
# can be used: in an <enums> block, providing a global definition which
# may later be required by a feature or extension; or in a feature or
# extension, defining an enumerant specific to that feature. The second
# form has more possible attributes. Some combinations of attributes are
# nonsensical in on or the other place, but these are not detected by the
# validator.
#
# Ways to specify the enumerant value:
#   value - integer (including hex) value of the enumerant
#   bitpos - integer bit position of the enumerant in a bitmask
#   [extnumber], offset, [dir] - integer extension number specifying a
#       base block value (inherited from surrounding <extension> if
#       not specified); integer offset in that block; and direction
#       of offset ('-' for negative, positive if not specified).
#   alias - name of another enum this is an alias of
#
# value and bitpos allow, and extnumber/offset/dir require:
#   extends - type name of the enumerant being extended
#
# Other attributes:
#   api - matches a <feature> api attribute, if present
#   type - 'uint8_t', 'uint32_t', 'uint64_t', or 'float', if present.
#       There are certain conditions under which the tag must be present,
#       or absent, but they are context-dependent and difficult to express
#       in the RNC syntax.
#   name - enumerant name
#   alias - another enumerant this is semantically identical to
#   protect - additional #ifdef symbol to place around the enum
#   comment - descriptive text with no semantic meaning
#   deprecated - denotes that this enum is marked as legacy, and why.
#       Valid values: 'aliased', 'unused', 'true'.
Enum =
    element enum {
        ((attribute value { text }
          & # needs to be split to handle the string defines as well as ints
            attribute extends { TypeName_t }?)
         | (attribute bitpos { xsd:long }
            & attribute extends { VkTypeNameRef_t }?)
         | (attribute extnumber { xsd:long }?
            & attribute offset { xsd:long }
            & attribute dir { "-" }?
            & attribute extends { VkTypeNameRef_t })
         | (attribute extends { VkTypeNameRef_t }?
            & attribute alias {
                  VkTypeNameRef_t | VkDefineOrEnumName_t
              })
         | (attribute value { text }
            & attribute extends { VkTypeNameRef_t }?
            & attribute alias {
                  VkTypeNameRef_t | VkDefineOrEnumName_t
              })
         | (attribute bitpos { xsd:long }
            & attribute extends { VkTypeNameRef_t }?
            & attribute alias {
                  VkTypeNameRef_t | VkDefineOrEnumName_t
              }))?
        & ProtectAttr?
        & ApiAttr?
        & attribute type { "uint8_t" | "uint32_t" | "uint64_t" | "float" }?
        & attribute name { VkDefineOrEnumName_t }
        & attribute deprecated { "aliased" | "unused" | "true" }?
        & CommentAttr?
    }

# <unused> defines a range of enumerants not currently being used
#   start, end - beginning and end of an unused numeric range
#   vendor - unused
#   comment - descriptive text with no semantic meaning
Unused =
    element unused {
        attribute start { IntegerOrHex_t },
        attribute end { IntegerOrHex_t }?,
        VendorAttr?,
        CommentAttr?
    }

# <commands> defines a group of commands
Commands = element commands { CommentAttr?, Command* }

# <command> defines a single command
#
# There are two forms of the tag.
# The attributes are more fully described in the registry schema document.
# The "prefix" and "suffix" attributes are currently present only in the
# OpenCL XML registry, where they are currently unused.
#
# Either form may have these attributes:
#   api - matches a <feature> api attribute, if present
#   export - comma-separated list of names exporting this command.
#       An arbitrary string, but usually corresponding to static
#       entry points in a library like the Vulkan Loader.
#
# The first form only has 'name' and 'alias' attributes, and no contents.
# It defines a command alias.
#
# The second form fully defines a command, and has the following structure:
#
#   <proto> is the C function prototype, including the return type
#   <param> are function parameters, in order
#     len - if the member is an array, len may be one or more of the following
#         things, separated by commas (one for each array indirection):
#         (a) a latex equation (prefixed with 'latexmath:');
#         (b) the name of another parameter of the command specifying the
#         length for corresponding indirection;
#         (c) 'null-terminated', indicating a pointer to a null-terminated
#         UTF-8 string
#         (d)'1' to indicate it is just a pointer (used for nested pointers);
#         (e) a C99 expression that refers to another parameter of the command
#         indirectly specifying the length for corresponding indirection;
#         (f) or a custom expression that cannot be used directly by
#         code generation and needs manual handling.
#     altlen - if len has latexmath equations (a), this contains one or more
#         of (b), (c), (d), (e), or (f) above, separated by commas (one for
#         each array indirection).
#     stride - if the member is an array, stride specifies the name of
#         another parameter containing the byte stride between consecutive
#         elements in the array. The array is assumed to be tightly packed
#         if omitted.
#     externsync - denotes that the member should be externally synchronized
#         when accessed by Vulkan
#     optional - whether this value can be omitted by providing NULL (for
#         pointers), VK_NULL_HANDLE (for handles) or 0 (for bitmasks/values)
#     selector - for a union parameter, identifies a separate enum parameter that
#         selects which of the union's members are valid
#     noautovalidity - tag stating that no automatic validity language should be
#         generated
#     objecttype - only applicable for parameters representing a handle as
#         a uint64_t value. Specifies the name of another parameter which is
#         a VkObjectType or VkDebugReportObjectTypeEXT value specifying
#         the type of object the handle references.
#     validstructs - only applicable for parameters which are pointers to
#         VkBaseInStructure or VkBaseOutStructure types, used as abstract
#         placeholders. Specifies a comma-separated list of structures which
#         may be passed in place of the parameter, or anywhere in the pNext
#         chain of the parameter.
#     <type> is a <type> name, if present
#     <name> is the function / parameter name, if present (normally should
#         be, except for void parameters).
# The textual contents of <proto> and <param> should be legal C
# for those parts of a function declaration.
#   <alias> - denotes function aliasing, if present
#     name - name of aliased function
#   <description> - unused text
#   <implicitexternsyncparams> are spec-language descriptions of
#       objects that are not parameters of the command, but
#       are related to them and also require external synchronization.
Command =
    element command {
        (attribute name { VkFuncName_t },
         attribute alias { VkFuncName_t },
         ApiAttr?)
        | (attribute tasks { StringList_t }?,
           attribute queues { StringList_t }?,
           attribute successcodes { VkEnumNameList_t }?,
           attribute errorcodes { VkEnumNameList_t }?,
           attribute renderpass { "inside" | "outside" | "both" }?,
           attribute videocoding { "inside" | "outside" | "both" }?,
           attribute conditionalrendering { "true" | "false" }?,
           attribute cmdbufferlevel { CmdbufferList_t }?,
           attribute allownoqueues { StringBool_t } ? ,
           attribute prefix { text }?,
           attribute suffix { text }?,
           attribute export { StringList_t }?,
           ApiAttr?,
           CommentAttr?,
           element proto {
               mixed {
                   element type { TypeName_t }?,
                   element name { text }
               }
           },
           element param {
               ApiAttr?,
               attribute len { text }?,
               attribute altlen { text }?,
               attribute stride { text }?,
               attribute externsync { text }?,
               OptionalAttr?,
               attribute selector { text }?,
               NoAutoValidityAttr?,
               attribute objecttype { text }?,
               attribute validstructs { VkTypeNameListRef_t }?,
               mixed {
                   element type { TypeName_t }?,
                   element name { text }?
               }
           }*,
           (element alias { NameAttr }?
            & element description { text }?
            & element implicitexternsyncparams {
                  element param { text }*
              }?))
    }

# Each <feature> defines the interface of an API version (e.g. OpenGL 1.2)
#   api - API tag (e.g. 'gl', 'gles2', etc. - used internally, not
#     necessarily an actual API name
#   apitype - whether the API block should be exposed publicly (default) or
#     if it is for internal usage. Valid values are 'internal', 'public' or
#     not specified (default), which is equivalent to 'public'.
#   name - version name (C preprocessor name, e.g. GL_VERSION_4_2)
#   number - version number, e.g. 4.2 (deprecated)
#   depends - boolean expression of API and/or extension names
#       upon which this feature depends.
#   protect - additional #ifdef symbol to place around the feature
#   sortorder - order relative to other features, default 0
#   <require> / <remove> / <deprecate> contains features to require, remove,
#                        or mark legacy in this version
#     depends - as a require tag the depends tag may additionally
#               include named feature booleans in C-style as
#               "VkStructName::featureBooleanName"
#     profile - only require/remove when generated profile matches
#     comment - descriptive text with no semantic meaning
Feature =
    element feature {
        attribute api { SupportedList_t },
        attribute apitype { "internal" | "public" }?,
        NameAttr,
        attribute number { xsd:float }?,
        DependsAttr?,
        ProtectAttr?,
        attribute sortorder { xsd:integer }?,
        CommentAttr?,
        (element require {
             ProfileNameAttr?,
             DependsAttr?,
             CommentAttr?,
             (InterfaceElement | CommentElt)*
         }
         | element deprecate {
               ProfileNameAttr?,
               CommentAttr?,
               attribute explanationlink { text } ,
               (DeprecateElement | CommentElt)*
         }
         | element remove {
               ProfileNameAttr?,
               CommentAttr?,
               attribute reasonlink { text }?,
               (InterfaceElement | CommentElt)*
           })*
    }

Extensions = element extensions { CommentAttr?, Extension* }

# Each <extension> defines the interface of an API <extension>.
# Like a <feature> tag, but with slightly different attributes:
#   api - regexp pattern matching one or more API tags, indicating
#     which APIs the extension is known to work with. The only
#     syntax supported is <name>{|<name>}* and each name must
#     exactly match an API being generated (implicit ^$ surrounding).
#   name - extension name string
#   number - extension number (positive integer, should be unique)
#   sortorder - order relative to other extensions, default 0
#   protect - C preprocessor symbol to conditionally define the interface
#   platform - should be one of the platform names defined in the
#     <platform> tag. Currently unused.
#   author - name of the author (usually a company or project name)
#   contact - contact responsible for the tag (name and contact information)
#   type - 'device' or 'instance', if present
#   depends - boolean expression of API and/or extension names
#       upon which this extension depends.
#   supported - comma-separated list of API name(s) supporting this extension,
#       e.g. 'vulkan', or 'disabled' to never generate output.
#   ratified - comma-separated list of API name(s) for which this extension
#       has been ratified by Khronos. Defaults to "" if not specified.
#   promotedto - API version or a name of an extension that this
#       extension was promoted to; e.g. 'VK_VERSION_1_1', or
#       'VK_KHR_draw_indirect_county'
#   deprecatedby - API version or a name of an extension that deprecates
#       this extension. It may be an empty string.
#       e.g. 'VK_VERSION_1_1', or 'VK_EXT_debug_utils', or ''
#   obsoletedby - Vulkan version or a name of an extension that obsoletes
#       this extension. It may be an empty string.
#       e.g. 'VK_VERSION_1_1', or 'VK_EXT_debug_utils', or ''
#   provisional - 'true' if this extension is released provisionally
#   specialuse - contains one or more tokens separated by commas, indicating
#       a special purpose of the extension. Tokens may include 'cadsupport',
#       'd3demulation', 'devtools', 'debugging', and 'glemulation'. Others
#       may be added in the future.
#   nofeatures - contains "true" if this extension has no <feature> tags
#       or "false" if it does have them. Defaults to "false".
# In addition, <require> / <remove> tags also support an api attribute:
#     api - only require/remove these features for the matching API.
#       Not a regular expression.
Extension =
    element extension {
        attribute name { VkExtName_t },
        attribute number { IntegerOrHex_t },
        attribute sortorder { xsd:integer }?,
        ProtectAttr?,
        attribute platform { text }?,
        attribute author { text }?,
        attribute contact { text }?,
        attribute type { "instance" | "device" }?,
        DependsAttr?,
        attribute supported { SupportedList_t | "disabled" }?,
        attribute ratified { SupportedList_t }?,
        attribute promotedto { VkVersion_t | VkExtName_t }?,
        attribute deprecatedby { "" | VkVersion_t | VkExtName_t }?,
        attribute obsoletedby { VkVersion_t | VkExtName_t }?,
        attribute provisional { "true" }?,
        attribute specialuse { StringList_t }?,
        attribute nofeatures { StringBool_t }?,
        CommentAttr?,
        (element require {
             ApiAttr?,
             ProfileNameAttr?,
             DependsAttr?,
             CommentAttr?,
             (InterfaceElement | CommentElt)*
         }
         | element deprecate {
               ApiAttr?,
            attribute explanationlink { text } ,
               ProfileNameAttr?,
               CommentAttr?,
               (DeprecateElement | CommentElt)*
         }
         | element remove {
               ApiAttr?,
               ProfileNameAttr?,
               CommentAttr?,
               (InterfaceElement | CommentElt)*
           })*
    }

# Each <format> define information about a VkFormat in a machine readable format
Formats = element formats { Format* }

# name - Format name, matching a VkFormat enum name
# class - Used for 'Compatible Formats' table
# blockSize - Used for 'Compatible Formats' table
# texelsPerBlock - Used for 'Compatible Formats' table
# blockExtent - 3D extent, no attribute is same as blockExtent=1,1,1
# packed - number of bits data type
# compressed - compression format class
# planes - number of planes, no attribute is same as planes=1
# chroma - can be one of [420, 422, 444] and used to mark if YCbCr Sampler are required by default
Format =
    element format {
        NameAttr,
        attribute class { text },
        attribute blockSize { xsd:integer },
        attribute texelsPerBlock { xsd:integer },
        attribute blockExtent { StringList_t }?,
        attribute packed { xsd:integer }?,
        attribute compressed { text }?,
        attribute chroma { "420" | "422" | "444" }?,
        Component+,
        Plane*,
        SpirvImageFormat*
    }

# bits - size of component or "compressed" if part of block-compression format
# numericFormat - as per Interpretation of Numeric Format table
#     some formats (depth/stencil) will have different numeric per component
# planeIndex - For multi-planar formats to map to the plane element
Component =
    element component {
        NameAttr,
        attribute bits { xsd:integer | "compressed" },
        attribute numericFormat { "SFIXED5" | "SFLOAT" | "SINT" | "SNORM" | "SRGB" | "SSCALED" | "UFLOAT" | "UINT" | "UNORM" | "USCALED" | "BOOL" },
        attribute planeIndex { xsd:integer }?
    }

# For multi-planar formats
Plane =
    element plane {
        attribute index { xsd:integer },
        attribute widthDivisor { xsd:integer },
        attribute heightDivisor { xsd:integer },
        attribute compatible { text }
    }

# labels a SPIR-V Image Format
SpirvImageFormat = element spirvimageformat { NameAttr }

# <sync> is a set of all sync objects
Sync =
    element sync {
        CommentAttr?,
        SyncStage*,
        SyncAccess*,
        SyncPipeline*
    }

SyncSupport =
    element syncsupport {
        attribute queues { StringList_t }?,
        attribute stage { StringList_t }?
    }

SyncEquivalent =
    element syncequivalent {
        attribute stage { StringList_t }?,
        attribute access { StringList_t }?
    }

# describes all Pipeline Stages
SyncStage =
    element syncstage {
        NameAttr,
        attribute alias { text }?,
        SyncSupport?,
        SyncEquivalent?
    }

# describes all Access Flags
SyncAccess =
    element syncaccess {
        element comment { text }?,
        NameAttr,
        attribute alias { text }?,
        SyncSupport?,
        SyncEquivalent?
    }

# describes pipelines
# VkExtNameExpression_t is too broad - just a list of extension dependencies
SyncPipeline =
    element syncpipeline {
        attribute name { text },
        attribute depends { VkExtNameExpression_t }?,
        SyncPipelineStage*
    }

SyncPipelineStage =
    element syncpipelinestage {
        attribute order { text }?,
        attribute before { text }?,
        attribute after { text }?,
        text
    }

# Each <videocodec> element defines either a video codec category or a
# specific video codec that can be used in the API.
# Video codec categories are defined with a <videocodec> element with a
# single name attribute specifying the video codec category (such as decode
# or encode).
# Specific video codecs are defined with a <videocodec> element with the
# following attributes:
#   name - descriptive name of the specific video codec
#   extend - descriptive name of the video codec category it specializes
#   value - the VkVideoCodecOperationFlagBitsKHR value identifying the codec
#
# Each <videocapabilities> element defines a video capability structure that
# is supported by the video codec and has a single struct attribute
# identifying the video capability structure.
#
# Each <videoformat> element defines a video format category that is
# supported by the video codec. If this is a new video format category
# (typically defined in video codec categories), the following attributes
# are required:
#   name - descriptive name of the video format category
#   usage - image usage flags expected to be specified in
#       VkPhysicalDeviceVideoFormatInfoKHR::imageUsage to query the format
#       properties for the video format category ("," and "+" can be used to
#       express disjunction and conjunction, respectively)
# In case a specific video codec extends the video format category with
# additional codec-specific information, the descriptive name of the
# extended video format category is specified through a single extend
# attribute.
# Video format properties supported by the video format category are
# defined with <videoformatproperties> elements with a single struct
# attribute identifying the video format properties structure.
# If the video format category is dependent on some capability, then
# <videorequirecapabilities> elements can be included in them with the
# following attributes:
#   struct - name of the capability structure used to determine the
#       precondition
#   member - name of the capability structure member used to determine the
#       precondition
#   value - the value the member should have to meet the precondition
#       ("," and "+" can be used to express disjunction and conjunction,
#       respectively)
# If more <videorequirecapabilities> elements are specified, then the
# overall precondition is the conjunction of the individual preconditions.
#
# Specific video profiles supported by a video codec are declared by a
# <videoprofiles> element with a single struct attribute identifying the
# codec-specific video profile structure. For each member of the specified
# profile structure, a <videoprofilemember> element is expected to be
# included with the name attribute specifying the name of the video profile
# structure member.
# Each <profile> element defined in a <member> element has the following
# attributes:
#   name - descriptive name of the profile
#   value - value of the member in case of this profile
# Some codec-specific video profile structures have multiple members. In
# such cases the complete definition and name of specific video profiles
# is constructed by combinations of the <profile> elements of each member.
VideoCodecs = element videocodecs { CommentAttr?, VideoCodec* }

VideoCodec =
    element videocodec {
        CommentAttr?,
        attribute name { text },
        attribute extend { text }?,
        attribute value { text }?,
        VideoProfiles*,
        VideoCapabilities*,
        VideoFormat*
    }

VideoProfiles =
    element videoprofiles {
        CommentAttr?,
        attribute struct { text },
        VideoProfileMember+
    }

VideoProfileMember =
    element videoprofilemember {
        CommentAttr?,
        attribute name { text },
        VideoProfile+
    }

VideoProfile =
    element videoprofile {
        CommentAttr?,
        attribute name { text },
        attribute value { text }
    }

VideoCapabilities =
    element videocapabilities {
        CommentAttr?,
        attribute struct { text }
    }

VideoFormat =
    element videoformat {
        CommentAttr?,
        attribute name { text }?,
        attribute usage { text }?,
        attribute extend { text }?,
        VideoRequireCapabilities*,
        VideoFormatProperties*
    }

VideoFormatProperties =
    element videoformatproperties {
        CommentAttr?,
        attribute struct { text }
    }

VideoRequireCapabilities =
    element videorequirecapabilities {
        CommentAttr?,
        attribute struct { text },
        attribute member { text },
        attribute value { text }
    }

# Each <spirvextension> define a SPIR-V extension that can be used in the API.
# Each <spirvcapability> define a SPIR-V capability that can be used in the API.
# Contains information to both generate table in spec as well as validating
# what needs to be enabled or supported to be used in Vulkan
SpirvExtensions =
    element spirvextensions { CommentAttr?, SpirvExtension* }
SpirvExtension = element spirvextension { NameAttr, Enable+ }
SpirvCapabilities =
    element spirvcapabilities { CommentAttr?, SpirvCapability* }
SpirvCapability = element spirvcapability { NameAttr, Enable+ }

# <enable> defines a way to enable the parent element in the API.
# If anyone of the <enable> elements are valid then the parent element
# can be used.
#
# There are four forms of the tag.
#
# The first only has the minimal version of Vulkan of the application
#
# The second only has a single Vulkan extension that must be enabled
#
# The third has a single Vulkan feature with the struct where it is from
#
# The fourth has a property struct, the member field in it, and the value
# that must be present
#
# To make scripting easier, each <enable> has a require attribute to map
# to the asciidoctor conditional logic in the spec. For version and
# extension attribute variations, there is no need for the require attribute
# since it is a redundant 1:1 mapping.
#
# The 'alias' attribute is used in cases where the anchor link cannot be
# properly resolved and needs a manual name to link to
Enable =
    element enable {
        attribute version { VkVersion_t }
        | attribute extension { VkExtName_t }
        | (attribute struct { text },
           attribute feature { text },
           attribute requires { text },
           attribute alias { text }?)
        | (attribute property { text },
           attribute member { text },
           attribute value { text },
           attribute requires { text }?)
    }

# Contents of a <require> / <remove> tag, defining a group
# of features to require or remove.
#   <type> / <enum> / <command> / <feature> all have attributes
#     name - feature name which must match
# The NameAttr of a feature element may be a comma-separated list to indicate
# that any one of the named features must be supported
InterfaceElement =
    element type {
# The 'name' can be an arbitrary string, such as a C #include path, in which case this fails
#        attribute name { xsd:NCName },
        attribute name { text },
        CommentAttr?
    }
    | Enum
    | element command {
          attribute name { VkFuncName_t },
          CommentAttr?
      }
    | element feature {
          attribute name { text },
          attribute struct { text },
          CommentAttr?
      }

# Contents of a <deprecate> tag, defining a group of features to deprecate.
#   <type> / <enum> / <command> all have attributes
#     name - feature name which must match
#   <feature> marks a feature struct member (as named in a <require> block
#     elsewhere in the registry) as deprecated
#     name - member name
#     struct - name of the struct containing the member
# The NameAttr of a feature element may be a comma-separated list to indicate
# that any one of the named features must be supported
DeprecateElement =
    element type {
# The 'name' can be an arbitrary string, such as a C #include path, in which case this fails
#        attribute name { xsd:NCName },
        attribute name { text },
        attribute supersededby { text }?,
        CommentAttr?
    }
    | element enum {
        attribute name { VkDefineOrEnumName_t },
        attribute supersededby { VkDefineOrEnumName_t }?,
        CommentAttr?
    }
    | element command {
          attribute name { VkFuncName_t },
          attribute supersededby { VkFuncName_t }?,
          CommentAttr?
      }
    | element feature {
          attribute name { text },
          attribute struct { text },
          attribute supersededby { text }?,
          CommentAttr?
      }

# Data types - all end in _t
MemberOrParamName_t =
    xsd:NCName { pattern = "[a-z]([a-z0-9]*)([A-Z][a-z0-9]*)*" }
VendorId_t = xsd:ID { pattern = "[A-Z]+" }
VendorIdRef_t = xsd:IDREF { pattern = "[A-Z]+" }
HexValue_t = xsd:token { pattern = "0[xX][0-9a-fA-F]+" }
IntegerOrHex_t = xsd:long | HexValue_t
# Many attributes accept comma-separated lists in strings
StringList_t = xsd:token { pattern = "[A-Za-z0-9_]+(,[A-Za-z0-9_]+)*" }
VkUpperSnakeCase_t =
    xsd:NCName { pattern = "(VK|VKSC)_[A-Z0-9]+(_[A-Z0-9]+)*" }

# Adds the ability to recognize things like 5x5
# Pattern allows Vulkan Video enums, which are not part of the API
VkDefineOrEnumName_t =
    VkUpperSnakeCase_t
    | xsd:NCName { pattern = "(VK|VKSC|STD)_[A-Z0-9]+(_[A-Z0-9x]+)*" }
VkEnumNameList_t =
    xsd:token {
        pattern =
            "(VK|VKSC)_[A-Z0-9]+(_[A-Z0-9x]+)*(,(VK|VKSC)_[A-Z0-9]+(_[A-Z0-9x]+)*)*"
    }
VkFuncName_t = xsd:NCName { pattern = "vk([A-Z]+[a-z0-9]*)+" }
VkPFNName_t = xsd:NCName { pattern = "PFN_vk([A-Z]+[a-z0-9]*)+" }

VkTypeName_t = xsd:NCName { pattern = "Vk([A-Z]+[a-z0-9]*)+" }
VkTypeNameRef_t = xsd:NCName { pattern = "Vk([A-Z]+[a-z0-9]*)+" }
VkTypeNameListRef_t =
    xsd:token {
        pattern = "Vk([A-Z]+[a-z0-9]*)+(,Vk([A-Z]+[a-z0-9]*)+)*"
    }

VkVersion_t = xsd:token { pattern = "VK_VERSION_1_[0-9]" }
VkExtName_t = xsd:NCName { pattern = "(VK_[A-Z]+|vulkan_video_codec(|s))(_[A-Za-z0-9]+)+" }
VkExtNameExpression_t =
    xsd:token {
        pattern =
            "VK_[A-Z]+(_[A-Za-z0-9]+)+([+,]VK_[A-Z]+(_[A-Za-z0-9]+)+)*"
    }

# TypeName_t is an argument/return value C type name
TypeName_t = text

Api_t = xsd:token { pattern = "(vulkan|vulkansc|vulkanbase)(,(vulkan|vulkansc|vulkanbase))*" }
SupportedList_t = xsd:token { pattern = "(vulkan|vulkansc|vulkanbase)(,(vulkan|vulkansc|vulkanbase))*" }

# StringBool_t is "true" or "false"
StringBool_t = "true" | "false"

ReturnCodes_t =
    xsd:token {
        pattern = "VK_([A-Z]+)(_[A-Z]+)*(,VK_([A-Z]+)(_[A-Z]+)*)*"
    }
ExtensionNameDefineVal_t =
    xsd:token {
        # For the name define
        pattern = '"(VK|VKSC)_[A-Z]+((_([A-Z0-9]+|[a-z0-9]+))*)"'
    }
VkEntityName_t =
    VkUpperSnakeCase_t | VkFuncName_t | VkPFNName_t | VkTypeName_t

# Repeatedly used attributes
ApiAttr = attribute api { Api_t }
ProfileNameAttr = attribute profile { text }

# Boolean expression of core version and extension names using (),+ operators
DependsAttr =
    attribute depends {
        xsd:token { pattern = "[(),+_A-Za-z0-9:]+" }
    }
CmdbufferList_t = xsd:token { pattern = "(primary(,secondary)?)|(secondary(,primary)?)" }
ExtensionNameAttr = attribute extension { VkExtName_t }
VendorAttr = attribute vendor { VendorIdRef_t }
CommentAttr = attribute comment { text }
NameAttr = attribute name { xsd:NCName }
# ProtectAttr supports boolean expressions like depends (using +, operators and parentheses)
ProtectAttr =
    attribute protect {
        xsd:token { pattern = "[!(),+_A-Z0-9]+" }
    }

# Optional attributes that must be true if present.
NoAutoValidityAttr = attribute noautovalidity { "true" }
ReturnedOnlyAttr = attribute returnedonly { "true" }
MayAliasAttr = attribute mayalias { "true" }
OptionalAttr =
    attribute optional {
        "true" | "false,true" | "true,true" | "true,false"
    }
# Repeatedly used elements
TypeRefElt = element type { xsd:NCName }
ParamOrMemberNameElt = element name { MemberOrParamName_t }
CommentElt = element comment { text }