Author: Jon Leech, Tobias Hector

# Vulkan® Documentation and Extensions: Procedures and Conventions

Jon Leech, Tobias Hector
version 1.4.350, 2026-05-14 02:53:14Z
from git branch: makepkg commit: 81b1d516cbf42f04a3c7f781977c499945b5e5dc

Loading… please wait.

Copyright 2014-2026 The Khronos Group Inc.

SPDX-License-Identifier: CC-BY-4.0

## 1. Introduction

This document contains required procedures and conventions when writing documentation for new Vulkan APIs, extensions and layers, or related Khronos® documentation such as proposals. These are collectively referred to as Vulkan Documentation or just documentation below. The primary focus is the API Specification and API extensions, although most of this document is equally applicable to other documentation.

Note | The custom asciidoctor macros described in the Markup Macros and Normative Terminology section are only available in the actual Vulkan Specification, not in proposals and other documents. For those documents only pure asciidoc markup may be used, in order that they be renderable in the web view provided by GitHub and Gitlab.

The primary purpose is to achieve consistency across the API, as well as across all of our source and output documents. Consistency makes it easier for developers, editors, reviewers, and users of our documentation to understand and modify it.

This document is now formally voted on and approved by the Vulkan Working Group. This means that unless explicitly stated otherwise, the procedures and conventions must be followed. If you have a strong desire to modify the procedures and conventions, such changes must be made through the normal Vulkan Working Group processes.

### 1.1. Terminology

The key words must, required, should, recommend, may, and optional in this document are to be interpreted as described in RFC 2119 and by the Vulkan Specification in the “Terminology” section.

### 1.2. Document Structure

The style guide is broken into four sections:

- API Naming Conventions - the required rules for choosing names of Vulkan identifiers of all types.

- Extensions and Layers - the required procedures for creating formal Vulkan extensions and layers.

- Markup Style - the required and recommended markup style for writing asciidoc and XML source that follows consistent formatting and layout guidelines, tags special terms and phrases for proper processing by the specification generation tools, etc.

- Writing Style - the required and recommended writing style for overall and fine-grained structure and conventions, normative language use, API naming conventions, common words and phrases to use and to avoid, linking and cross-referencing, etc.

### 1.3. Asciidoc Markup

Vulkan Documentation is primarily written in Asciidoc, a text markup language. We process asciidoc using the command-line `asciidoctor` application, as well as with `asciidoctor.js` when building the integrated Vulkan documentation site.

Asciidoctor is implemented in Ruby (https://www.ruby-lang.org/), which is available for Linux, MacOS, and Microsoft Windows. Asciidoctor.js is a Javascript implementation transpiled from asciidoctor.

Note | Additional implementations of asciidoc exist including `AsciidoctorJ` and the builtin GitHub and GitLab preview renderers. Live preview extensions exist for Chrome and Firefox. However, because of the use of custom macros in the Vulkan Specification toolchain, and the high complexity of the documents and toolchain used to generate it, these web tools cannot currently render the Specification from source. Instead, we generate HTML and PDF versions of the Specification and publish them on the Khronos website. The Asciidoctor toolchain and build process are not addressed by this document, which concentrates solely on source documents.

### 1.4. Normative References

Normative references are references to external documents or resources to which documentation authors must comply.

Association for Computing Machinery. Citation Style and Reference Formats. Retrieved July 27, 2019. https://www.acm.org/publications/authors/reference-formatting .

International Organization for Standardization. Data elements and interchange formats — Information interchange — Representation of dates and times (2004-12-01). https://www.iso.org/standard/40874.html . Also see https://www.w3.org/QA/Tips/iso-date for colloquial examples.

Khronos Vulkan Working Group. `KhronosGroup/Vulkan-Docs` project on GitHub (July 5, 2016). https://github.com/KhronosGroup/Vulkan-Docs .

Jon Leech. The Khronos Vulkan API Registry (December 2, 2024). https://registry.khronos.org/vulkan/specs/latest/registry.html .

Khronos Vulkan Working Group. Vulkan 1.4 - A Specification. https://registry.khronos.org/vulkan/ .

Version 1.4.303 (December 2, 2024) is the latest patch release of the Vulkan API Specification as of the time this reference was last updated, but the Specification is frequently updated with minor bugfixes and clarifications. When a more recent patch release is made, it becomes the normative reference for the API.

## 2. API Naming Conventions

Identifiers in the Vulkan API (e.g. types, parameters, constants, etc.) all follow a set of naming rules, providing a consistent scheme for developers.

The Vulkan C API uses prefixes as an implicit namespace control mechanism. Bindings to other languages can choose not to use these prefixes if the language provides an explicit namespace mechanism.

### 2.1. General Naming Rules

Names of identifiers should generally be written with full words, as a concise description of what that identifier is. For example, the type of a structure containing information about how to create an instance is `VkInstanceCreateInfo`.

Abbreviations and prefixes are sometimes used in the API when they do not impede clarity. All abbreviations and prefixes used in the API must be approved by the Vulkan working group, and be added to the Common Abbreviations and Standard Prefixes sections, respectively. Whenever an approved abbreviation exists for a particular word, it should be used in place of the full word unless there is good reason not to.

When a number is part of an identifier, it is treated as a word if it is a standalone number, such as the extension name token VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME for the `VK_KHR_get_memory_requirements2` extension. For uses where the number is part of a common abbreviation such as `2D` or `R8B8``, the entire abbreviation is treated as a word.

Note | editing-note Unfortunately, there is an internal inconsistency here between extension name strings, such as VK_KHR_get_memory_requirements2, and tokens encoding those names, such as VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME.

### 2.2. Preprocessor Defines

Preprocessor definitions include an underscore `_` as a delimiter between words, with every character in upper case.

Each definition is prefixed with `VK_`, followed by the name.

This rule applies to most declarations with the C Preprocessor’s `#define` token, including macros and constants. There are however a few exceptions:

- The header guard for each header includes an additional underscore `_` at the end of the identifier.

  - Example: `VULKAN_H_`

- Definitions that denote the presence of an extension follow the extension name string convention.

  - Example: `VK_KHR_sampler_mirror_clamp_to_edge`

- Three `VKAPI_*` definitions are defined by the platform header to alias certain platform-specific identifiers related to calling conventions.

  - Examples: `VKAPI_ATTR`, `VKAPI_CALL` and `VKAPI_PTR`

- Preprocessor defines are occasionally used to create aliases between other Vulkan identifiers, which usually happens when something was originally misnamed. In these cases, the fixed name is added to the API, and the old name is made into an alias of that. In these cases, the name will be whatever the original misnamed identifier was.

Example

    // VK_VERSION_MAJOR (Macro)
    #define VK_VERSION_MAJOR(version) ((uint32_t)(version) >> 22)

    // VK_HEADER_VERSION (Base type)
    #define VK_HEADER_VERSION 10

### 2.3. Type Names

Type names are declared with no separator between words. Each word starts with a capital letter, and every other character in each word is lower case.

Type names are prefixed with `Vk`, except for external type names used when integrating with platform APIs and window systems.

Type names must not match the names of the command parameter or structure member they apply to.

Example

    // Disallowed, type name identical to member name
    typedef struct VkExample {
        ubm_device  ubm_device;
    } VkExample;

    // Allowed
    typedef struct VkExample {
        ubm_device  device;
    } VkExample;

This rule applies to all type definitions except function pointer types, including struct and union types, handles, base typedefs, and enumerant types.

Example

    // VkImage (Handle)
    VK_NONDISP_HANDLE(VkImage)

    // VkFlags (Base type)
    typedef uint32_t VkFlags;

    // VkResult (Enum type)
    typedef enum VkResult {
        ...
    };

    // VkApplicationInfo (Struct)
    typedef struct VkApplicationInfo {
        ...
    } VkApplicationInfo;

    // VkClearColorValue (Union)
    typedef union VkClearColorValue {
        ...
    } VkClearColorValue;

#### 2.3.1. Extending Structure Names

Structures which extend a base structure through its `pNext` chain should reflect the name of the base structure. Currently there are two examples of such naming schemes.

New structures which add extended object creation parameters to a base structure should use this naming scheme:

Table 1. Extended Object Information Structures
Base Structure Name | Extending Structure Name
--- | ---
`VkObjectCreateInfo` | `VkObjectNameCreateInfoAuthor`

`Object` is the name of the object being created. `Name` is a short name for the extension or the new information added by that extension. `Author` is the author ID of the extension.

New structures which extend API queries, such as the `vkGetPhysicalDeviceFeatures2KHR` and `vkGetPhysicalDeviceProperties2KHR` commands defined by the `VK_KHR_get_physical_device_properties2` extension, should use this naming scheme:

Table 2. Extended Query Structures
Base Structure Name | Extending Structure Name
--- | ---
`vkGetPhysicalDeviceFeatures2KHR` | `VkPhysicalDeviceNameFeaturesAuthor`
`vkGetPhysicalDeviceProperties2KHR` | `VkPhysicalDeviceNamePropertiesAuthor`

`Name` is a short name for the extension, or for the new feature or property being queried, such as `Multiview` or `DiscardRectangle`. `Author` is the author ID of the extension.

### 2.4. Enumerant Names

Enumerants include an underscore `_` as a delimiter between words, with every character in upper case.

Each enumerant name is prefixed with `VK_`.

Enumerants are prefixed with the exact name of the type it belongs to, converted to the correct case (e.g. `VkStructureType` → `VK_STRUCTURE_TYPE_*`).

This rule applies to all enumerants, with one exception.

- The `VkResult` enumerants are split into two sub types: error and success codes.

  - Success codes are not prefixed with anything other than `VK_`.

  - Error codes are prefixed with `VK_ERROR_`.

Example

    // VK_FORMAT_UNDEFINED, VK_FORMAT_R4G4_UNORM_PACK8 (Enumerants)
    typedef enum VkFormat {
        VK_FORMAT_UNDEFINED = 0,
        VK_FORMAT_R4G4_UNORM_PACK8 = 1,
        ...
    };

    // VkResult codes (Exception)
    typedef enum VkResult {
        VK_SUCCESS = 0,
        ...
        VK_ERROR_OUT_OF_HOST_MEMORY = -1,
        ...
    } VkResult;

### 2.5. Bitflag Names

The names of bitflag enumerants (those that belong to a `FlagBits` type) must end with `_BIT` (followed by the author ID for enumerants defined by extensions).

The only exception to this rule is where a name ending in `_NONE`, such as `VK_CULL_MODE_NONE` or `VK_VIDEO_CODEC_OPERATION_NONE_KHR`, is used as an alias for the value `0`.

These names represent not a bitflag, but the absence of any bitflags.

### 2.6. Command Names

Command names are declared with no separator between words. Each word starts with a capital letter, and every other character in each word is lower case.

The structure of a command name should be as follows:

`prefix Verb Object Property`

`prefix`

  This is usually “vk”, but will be “vkCmd” if it is a command used to record into a command buffer, or “vkQueue” if it directly affects a queue.

`Verb`

  The verb describing the action being performed. A list of most verbs used in Vulkan is available here.

`Object`

  The name of the object being acted upon by the command.

`Property`

  The property of the object which is being acted upon by the command, and is omitted in cases where the whole object is being acted upon (e.g. creation commands).

These rules apply to all command declarations.

Example

    // Creation command
    VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance( ... );

    // Command buffer recording command
    VKAPI_ATTR VkResult VKAPI_CALL vkCmdBindPipeline( ... );

    // Get command
    VKAPI_ATTR VkResult VKAPI_CALL vkGetQueryPoolResults( ... );

Note | There are three exceptions to the above rule in the core Vulkan API: vkDeviceWaitIdle vkCmdNextSubpass vkCmdPipelineBarrier These names are left as-is to maintain compatibility. There are additionally a number of exceptions in a few existing extensions.

#### 2.6.1. Query Commands

A number of commands in the API are used to determine the properties of some object in the implementation.

The queried properties may either be invariant, or they may change based on application behavior. If the results are not invariant, the lifetime of the results should be clearly described in the command description. See Lifetime of Retrieved Results in the specification for more information.

These commands fall into two categories from a naming perspective:

Capability Queries

  These are commands which query capabilities of objects that an implementation can provide. Such commands use the verb “Enumerate” to identify themselves.

  e.g. `vkEnumeratePhysicalDeviceProperties`

  Whilst these commands describe properties of the named object, they do not accept a parameter of that object type - though they usually have a parameter for the parent type.

Object State Queries

  These commands are used to query the current properties of an object that has been created. Such commands use the verb “Get” to identify themselves.

  e.g. `vkGetPhysicalDeviceQueueFamilyProperties`

  These commands always have a parameter of the object type.

#### 2.6.2. Command Verbs

Below is a list of many of the verbs currently in use in core Vulkan and KHR extensions, along with their meanings. The list is not guaranteed to be up to date, but covers all core and KHR verbs at the time of writing.

Verb | Meaning
--- | ---
Acquire | Acquire ownership of an object from an external source
Allocate | Allocates memory in a pool or memory heap and creates object - paired with “Free”
Begin | Start of a range of command buffer commands with different behavior than those outside the range - “End” marks the end of the range
Bind | Binds an object to another object
Blit | Performs a filtered and scaled copy of pixels from one image to another
Clear | Sets all pixels in an image to the same value
Copy | A raw copy of data from one object to another with no transformation of the data
Create | Creates an object - paired with “Destroy”
Destroy | Destroys an object - paired with “Create”
Dispatch | Kicks off a set of compute tasks
Draw | Kicks off a set of rasterization tasks
End | End of a range of command buffer commands with different behavior than those outside the range - “Begin” marks the start of the range
Enumerate | Queries the capabilities of objects that could be created, before creating them
Execute | Executes commands recorded in another command buffer
Fill | Sets all data units in a buffer to the same value
Flush | Flushes data from the host to the device
Free | Destroys an object and then frees memory back to a pool or memory heap - paired with “Allocate”
Get | Queries the state of an existing object
Import | Imports the payload from an external object into a Vulkan object
Invalidate | Invalidates data on the host, forcing newer data on the device to be read
Map | Maps an allocation into host memory - paired with “Unmap”
Merge | Merges two objects
Present | Presents an image to a surface
Push | Pushes data to the device as part of a command stream
Release | Releases ownership of an object to an external source
Reset | Resets the state of an object to an initial state
Resolve | Resolves multiple samples in a multisampled image to an image with one sample per pixel
Set | Sets the state of an object
Submit | Submits a set of commands to a queue
Unmap | Unmaps an allocation from host memory - paired with “Map”
Update | Updates entries in a descriptor set
Wait | Waits for some signal
Write | Writes values to an object

#### 2.6.3. Function Pointer Type Names

Function pointer names are declared exactly as the equivalent statically declared command would be declared, but prefixed with `PFN_`, standing for "Pointer to FunctioN".

Example

    // PFN_vkCreateInstance (Function Pointer)
    typedef VkResult (VKAPI_PTR *PFN_vkCreateInstance)( ... );

### 2.7. Function Parameter and Struct/Union Member Names

Function parameter names are declared with no separator between words. Each new word, except for the first, starts with a capital letter. All other characters in the parameter name are in lower case.

Members/parameters of a type that is not a base type should generally be named in a similar way to the type itself, with additional context added for clarity when necessary.

Pointer members/parameters are prefixed with a number of `p` characters, with one `p` for each level of indirection.

Function pointer members/parameters are prefixed with `pfn`.

Any member describing the size of a memory allocation should be suffixed with `Size`. If the context is self-evident from the structure name, then it may simply be named `size`.

Any member describing the number of something, such as an array length or number of internal allocations, should be suffixed with `Count`. The `size` rule overrides this rule, though it is possible to have multiple sizes (e.g. `sizeCount`). If the member is an array length, then the name of length should correspond to the name of the array member, usually `XYZCount` for an array named `pXYZs`. If a structure in a `pNext` chain is an array whose length must match the length of an array of the base structure, then that extending structure should include an array length member with the same name as the length in the base structure.

These rules apply to all function parameters and struct/union members, with a single exception:

- The `sType` member of structures is abbreviated as it is used in almost every structure.

  - The slightly odd naming prevents it clashing with any future variables.

  - The `s` stands for “structure”, referring to its enumerant type.

Example

    // Function parameters, including a twice indirected pointer.
    VKAPI_ATTR VkResult VKAPI_CALL vkMapMemory(
        VkDevice                                    device,
        VkDeviceMemory                              memory,
        VkDeviceSize                                offset,
        VkDeviceSize                                size,
        VkMemoryMapFlags                            flags,
        void**                                      ppData);

    // Structure members, including the sType exception and a single indirected
    // pointer.
    typedef struct VkMemoryBarrier {
        VkStructureType    sType;
        const void*        pNext;
        VkAccessFlags      srcAccessMask;
        VkAccessFlags      dstAccessMask;
    } VkMemoryBarrier;

    // Function pointer members
    typedef struct VkAllocationCallbacks {
        void*                                   pUserData;
        PFN_vkAllocationFunction                pfnAllocation;
        PFN_vkReallocationFunction              pfnReallocation;
        PFN_vkFreeFunction                      pfnFree;
        PFN_vkInternalAllocationNotification    pfnInternalAllocation;
        PFN_vkInternalFreeNotification          pfnInternalFree;
    } VkAllocationCallbacks;

    // Size member (pCode is not a specific array of anything, it is just a
    // pointer to memory)
    typedef struct VkShaderModuleCreateInfo {
        VkStructureType              sType;
        const void*                  pNext;
        VkShaderModuleCreateFlags    flags;
        size_t                       codeSize;
        const uint32_t*              pCode;
    } VkShaderModuleCreateInfo;

    // Count member
    typedef struct VkSparseImageMemoryBindInfo {
        VkImage                           image;
        uint32_t                          bindCount;
        const VkSparseImageMemoryBind*    pBinds;
    } VkSparseImageMemoryBindInfo;

### 2.8. Extension Identifier Naming Conventions

Identifiers defined by an extension are modified by appending the extension’s author ID to the end of the identifier, as described below. Author IDs are obtained as described in the Extension and Layer Naming Conventions section.

If an extension becomes part of core, a new version of the extension’s identifiers should be created, that do not contain the author ID at the end of the identifier. The original identifiers should be kept in order to maintain source-level compatibility with existing applications making use of the earlier extension’s identifiers.

#### 2.8.1. Extension Type Names

Types defined by extensions have the author ID appended to the end of the type name.

Example

    // VkSurfaceFormatKHR (structure type with KHR appended)
    typedef struct VkSurfaceFormatKHR {
        VkFormat           format;
        VkColorSpaceKHR    colorSpace;
    } VkSurfaceFormatKHR;

#### 2.8.2. Extension Enumerant Names

Enumerants defined by extensions have the author ID appended to the end of the enumerant name, separated by an underscore. This includes the begin, end, range, and max values added to enumeranted type definitions by the generator scripts.

Note | There is one exception to this rule in the `VK_KHR_sampler_mirror_clamp_to_edge` extension. This functionality was included in the original specification, but quickly separated out at release. Due to this late change, the single enum exposed has retained its original identifier to avoid compatibility issues: VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE

Example

    // VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR (enumerant with _KHR appended)
    typedef enum VkCompositeAlphaFlagBitsKHR {
        VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR = 0x00000001,
        ...
    } VkCompositeAlphaFlagBitsKHR;

#### 2.8.3. Extension Function Names

Function and function pointer type names defined by extensions have the author ID appended to the end of the name.

Example

    // vkDestroySurfaceKHR (function with KHR appended)
    VKAPI_ATTR void VKAPI_CALL vkDestroySurfaceKHR(
        VkInstance                                  instance,
        VkSurfaceKHR                                surface,
        const VkAllocationCallbacks*                pAllocator);

    typedef void (VKAPI_PTR *PFN_vkDestroySurfaceKHR)(
        VkInstance                                  instance,
        VkSurfaceKHR                                surface,
        const VkAllocationCallbacks*                pAllocator);

### 2.9. Common Abbreviations

Abbreviations and acronyms are sometimes used in the Vulkan API Specification and the Vulkan API where they are considered clear and commonplace. They are now described fully in the “Common Abbreviations” section of the “Lexicon” appendix of the Specification and are not reproduced here, with the following exception:

Mip

  Related to a mipmap. Use “mipmap” in full only when it is a standalone term. If referred to some associating with a mipmap, such as levels, sampling mode, size, tail images, etc., use “mip” as a standalone prefix word, e.g. `maxMipLevels`, `VK_MIP_MODE`, etc. This is analogous to the spelling conventions for mip-related terms

Note | The names `mipmapMode`, `mipmapPrecisionBits`, `VkSamplerMipmapMode`, and VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT are exceptions to this general usage guideline, for historical reasons.

### 2.10. Standard Prefixes

Prefixes are used in the API to denote specific semantic meaning of Vulkan names, or as a label to avoid name clashes. They are now described fully in the “Prefixes” section of the “Lexicon” appendix of the Specification and are not reproduced here.

### 2.11. Format Types

Formats naming conventions

Numeric Format

  Describes the suffix found on formats ex. SFLOAT, SINT, SNORM, SRGB, UINT, USCALED, etc

Numeric Type

  describes float, signed int, or unsigned int

SPIR-V Type

  The combination of the type (ex OpTypeInt), width, and signedness

## 3. API Versions, Extensions, and Layers

This chapter describes required and recommended processes for writing specification language for different core API versions, extensions, and API layers. It is concerned with processes and registration, while fine-grained naming conventions are included in the API Naming Conventions chapter.

Note | The mechanism and process of specifying extensions is subject to change, as we receive feedback from authors and further requirements of documentation tooling. This document will be updated as changes are made.

### 3.1. Introduction

The Khronos extension registries and extension naming conventions serve several purposes:

- Avoiding naming collisions between extensions developed by mutually unaware parties, both in the extension names themselves, as well as their token, command, and type names.

- Allocating enumerant values for tokens added by extensions

- Creating a defined order between extensions. Extensions with higher numbers may have dependencies upon extensions with lower numbers, and must define any relevant interactions with lower-numbered extensions.

- Provides a central repository for documentation and header changes associated with extensions

### 3.2. Proposing New Extensions

The first step in the process should be to fill out a proposal document, and iterate on that before committing to writing specification language.

The main reasons to do this are to ensure that everyone understands the nature of the problem being addressed, to be clear why a particular solution was chosen in lieu of others, and to allow for design changes before committing to specification text. If a potential implementor has concerns with any of the design choices, it is much easier to change details in a proposal document than it is to rewrite specification text.

In the top level `proposals` folder there is a template (`template.adoc`) for writing design proposals, including guidance on how it should be used.

For some simpler extensions it may not be necessary to write a proposal document if both the problem is well understood and the solution well bounded, so this is not a required piece of documentation. However it may still be useful to write this in a proposal document.

Once a proposal is written, the Vulkan Working Group and other interested parties should be asked to review and provide feedback before specification work begins.

### 3.3. General Rules/Guidelines

Some general rules to simplify the specific rules below:

- API versions, extensions and layers must each have a globally unique name.

- All commands and tokens must have a globally unique name.

- API versions and extensions can expose new commands, types, and/or tokens, but layers must not.

  - However, layers can expose their own extensions, which in turn are allowed to expose new commands and tokens.

- All extensions must be registered with Khronos.

- Extensions in general are strictly additive and backwards-compatible with each other and with the core API. However, as described in more detail the Fundamentals chapter of the Vulkan API Specification, explicit incompatibilities may exist, and must be documented.

### 3.4. Version, Extension, and Layer Naming Conventions

Versions, extensions, and layers have formal names. These names are used in a variety of places:

- When specifying extensions and layers to enable in the API.

- As a preprocessor symbol in the `vulkan_*.h` header files indicating that an extension interface is defined at compile time.

- To control building the Vulkan Specification from asciidoc source containing multiple versions and extensions, by explicitly enabling their inclusion.

Note | Published extensions are documented as part of the default branch (`main`) of the KhronosGroup/Vulkan-Docs project. They can optionally be included or excluded when generating specifications.

There is a rigid syntax for these names:

- Versions are named with the syntax `VK_VERSION_<major>_<minor>`.

- Extensions are named with the syntax `VK_<author>_<name>`.

- Layers are named with the syntax `VK_LAYER_<author>_<name>` or `VK_LAYER_<fqdn>_<name>`.

All these names include a `VK_` prefix, as described in the Preprocessor Defines section above. In addition, layers add a `LAYER_` prefix.

All these names must be valid C language identifiers.

#### 3.4.1. Version, Extension, and Layer Name Strings

The `<name>` portion of version, extension, and layer names is a concise name describing its purpose or functionality. The underscore (`_`) character is used as a delimiter between words. Every alphabetic character of the name must be in lower case.

#### 3.4.2. Author IDs for Extensions and Layers

Extension and layer names also contain an author ID, indicated by `<author>` above, identifying the author of the extension/layer. This ID is a short, capitalized string identifying an author, such as a Khronos member developing Vulkan implementations for their devices, or a non-Khronos developer creating Vulkan layers. Author IDs must be registered with Khronos.

Some authors have platform communities they wish to distinguish between, and can register additional author IDs for that purpose. For example, Google has separate Android and Chrome communities with separate author IDs. This is represented in the API registry as:

    <tag name="ANDROID"  author="Google LLC" contact="contactperson @githubusername"/>
    <tag name="CHROMIUM" author="Google LLC" contact="contactperson @githubusername"/>

In the above example, `Google LLC` is the author for two author IDs (`ANDROID` and `CHROMIUM`).

Details on how to register an author ID are provided below. Layer authors not wishing to register an author ID with Khronos can instead use a fully-qualified domain name (FQDN, indicated by `<fqdn>` above) as the ID. The FQDN should be a domain name owned by the author. FQDNs cannot be used for extensions, only for layers.

Vendor extensions are used for functionality that is, at least initially, specific to a single registered author or platform (e.g. Android). These extensions are not ratified by Khronos. Typically, they are only implemented by the registered author or by implementations that support the target platform.

Khronos has registered some author IDs for specific uses:

- KHR is used for Khronos-ratified extensions.

- EXT is used for multi-vendor extensions. These are extensions intended to be exposed by implementations from multiple vendors. Historically these extensions were not ratified, but Khronos has begun retroactively ratifying selected `EXT` extensions.

Note | The `KHX` author ID was used for experimental extensions, as described in the “Layers & Extensions” appendix of the Vulkan API Specification. As of the initial Vulkan 1.1 public release, all `KHX` extensions have been promoted to `KHR` status, and this mechanism is no longer used.

The following author IDs are reserved and must not be used:

- `VK` - To avoid confusion with the top-level `VK_` prefix.

- `VULKAN` - To avoid confusion with the name of the Vulkan API.

- `LAYER` - To avoid confusion with the higher-level “LAYER” prefix.

- `KHRONOS` - To avoid confusion with the Khronos organization.

The following is a summary of extension and layer names, demonstrating the cases described above:

- Extension names all use the base prefix `VK_`.

- Khronos-ratified extensions add the reserved author ID `KHR` and use the prefix `VK_KHR_`.

- Multi-vendor extensions add the special author ID `EXT` to the base prefix, and will use the prefix `VK_EXT_`.

- Vendor extensions add the author ID to the base prefix. For example, NVIDIA will use the prefix `VK_NV_`, and Valve will use the prefix `VK_VALVE_`.

- Layer names follow the same conventions as extensions, but use the base prefix `VK_LAYER_`.

- Because layers need not be registered with Khronos, an alternative mechanism is needed to allow creating unique layer names without registering an author ID. Layer authors that prefer not to register an author ID can instead use a fully-qualified domain name (FQDN) in reverse-order as an author ID, replacing `.` (period) with `_` (underscore) characters. The restriction that layer names must be valid C identifiers means that some FQDNs cannot be used as part of layer names.

Example

    // Core API version name for Vulkan 1.1
    VK_VERSION_1_1

    // Khronos ratified extension name
    VK_KHR_mirror_clamp_to_edge

    // Multi-vendor extension name
    VK_EXT_debug_marker

    // Vendor extension name using author ID NV
    VK_NV_glsl_shader

    // Vendor layer name using author ID LUNARG
    VK_LAYER_LUNARG_vktrace

    // Layer name using the FQDN www.3dxcl.invalid instead of an author ID
    VK_LAYER_invalid_3dxcl_www

Note | To avoid linking to a nonexistent domain, the reserved TLD `.invalid` is used in the example above.

### 3.5. Extension Command, Type, and Token Naming Conventions

Extensions may add new commands, types, and tokens, or collectively “objects”, to the Vulkan API. These objects are given globally unique names by appending the author ID defined above for the extension name as described in the Extension Identifier Naming Conventions section above.

### 3.6. The Vulkan API Registry

The canonical definition of the Vulkan APIs is kept in an XML file known as the Vulkan API Registry. The registry is kept in `xml/vk.xml` in the default branch (`main`) of the KhronosGroup/Vulkan-Docs project, containing the most recently released Vulkan API specification. The registry contains reserved author IDs, core and extension interface definitions, definitions of individual commands and structures, and other information which must be agreed on by all implementations. The registry is used to maintain a single, consistent global namespace for the registered entities, to generate the Khronos-supplied Vulkan header files, and to create a variety of related documentation used in generating the API specification and reference pages. Other uses of the registry outside Khronos include the LunarG Loader and Validation Layers, and a variety of language bindings.

### 3.7. Registering an Author ID With Khronos

Previous Khronos APIs could only officially be modified by Khronos members. In an effort to build a more flexible platform, Vulkan allows non-Khronos developers to extend and modify the API via layers and extensions in the same manner as Khronos members. However, extensions must still be registered with Khronos. A mechanism for non-members to register layers and extensions is provided.

Extension authors will be able to create an account on GitHub and register an author ID with Khronos through the KhronosGroup/Vulkan-Docs project. The author ID must be used for any extensions that author registers. The same mechanism will be used to request registration of extensions or layers with Khronos, as described below.

To reserve an author ID, propose a merge request against `vk.xml` in the default branch. The merge must add a `<tag>` XML tag and fill in the `name`, `author` and `contact` attributes with the requested author ID, the author’s formal name (e.g. company or project name), and contact email address, respectively. The author ID will only be reserved once this merge request is accepted.

Please do not try to reserve author IDs which clearly belong to another existing company or project which may wish to develop Vulkan extensions or layers in the future, as a matter of courtesy and respect. Khronos may decline to register author IDs that are not requested in good faith.

### 3.8. Registering a Vendor ID With Khronos

Vulkan implementors must report a valid vendor ID for their implementation when queried by `vkGetPhysicalDeviceProperties`, as described in the “Devices and Queues” section of the Vulkan API Specification. If there is no valid PCI vendor ID defined for the physical device, implementations must obtain a Khronos vendor ID.

Khronos vendor IDs are reserved in a similar fashion to author IDs. While vendor IDs are not directly related to API extensions, the reservation process is similar, and so is described in this section.

To reserve a Khronos vendor ID, you must first have a Khronos author ID. Propose a merge request against `vk.xml` in the default branch. The merge must define a new enumerant by adding an `<enum>` tag to the `VkVendorId` `<enums>` tag, following the existing examples. The `value` attribute of the `<enum>` must be the next available unused value, and is the reserved vendor ID. The `name` attribute must be `VK_VENDOR_ID_<author>`, where `<author>` is the author tag. The vendor ID will be reserved only once this merge request has been accepted.

Please do not try to reserve vendor IDs unless you are making a good faith effort to develop an implementation of a Khronos API and require one for that purpose.

Note | Other Khronos APIs such as OpenCL also utilize vendor IDs and share the Khronos vendor ID space. To obtain a vendor ID for these APIs, first reserve it in Vulkan’s `vk.xml` and once that is done, utilize it in the other API. To avoid collisions, we are currently utilizing `vk.xml` as the central Khronos vendor ID registry.

### 3.9. Registering Extensions and Layers

Extensions must be registered with Khronos. Layers should be registered, but registration is not required. Registration means:

- Receiving an extension number.

- Adding the extension or layer name to the list in `vk.xml` and appearing on the Khronos registry website, which will link to associated documentation hosted on Khronos.

- For extensions which add to the Vulkan API, including definitions of those additions to `vk.xml`.

Registration for Khronos members is handled by filing a merge request in the internal gitlab repository modifying `vk.xml` in the default branch, containing the core specification against which the extension or layer will be written. Registration is not complete until the registry maintainer has validated and accepted the merge.

A similar mechanism is used to register extensions not authored by Khronos members. Implementors who are not Khronos members and who need to create extensions must register with Khronos by creating a GitHub account, and registering their author ID and/or FQDNs to that account. They can then submit new extension registration requests by proposing merges to `vk.xml`. On acceptance of the merge, the extension will be registered, though its specification need not be checked into the Khronos GitHub repository at that point.

The registration process can be split into several steps to accommodate extension number assignment prior to extension publication:

- Acquire an extension number. This is done by proposing a merge request against `vk.xml` similarly to how author IDs are reserved. The merge should add a new `<extension>` tag at the end of the file with attributes specifying the proposed extension `name`, the next unused sequential extension `number`, the `author` and `contact` information (if different than that already specified for the author ID used in the extension name), and finally, specifying `supported="disabled"`. The extension number will be reserved only once this merge request is accepted into the default branch.

- Develop and test the extension using the registered extension number.

- Publish the extension to Khronos using the previously registered extension number, by submitting merge requests to the default branch defining the changes specific to the extension. Changes to both the specification source, and to `vk.xml` will be needed.

  - Extension changes to the specification source must be protected by asciidoc conditionals as described in the Documenting Extensions section.

  - Changes to `vk.xml` must define the extension interfaces in the `<extension>` block, and must also change the `supported` attribute value of the `<extension>` to `supported="vulkan"`.

  - When publishing an extension, mark it as enabled by proposing a merge to the default branch changing the `supported` attribute value of the `<extension>` to `supported="vulkan"`.

  - Once the merge request defining an extension has been accepted into the default branch, publication is complete - although it may not be visible on GitHub until the next regular core Specification update is pushed out.

  - Publishing on the Khronos public GitHub repository is preferred when possible. Khronos members may instead create branches on Khronos' internal gitlab server, but those branches will eventually be mirrored to GitHub.

- It is still possible to publish a separate branch of the repository with appropriate changes relative to the core Vulkan API branch instead, but this approach is deprecated and discouraged. If this is done, all changes to `vk.xml` must still be made in the default branch.

### 3.10. Documenting API Versions and Extensions

API versions and extensions are documented as modifications to the Vulkan specification. Changes specific to a version or extension are protected by asciidoc conditionals. The changes are only visible in generated documentation when the Specification is built with an asciidoc attribute of that name defined. Khronos publishes three forms of the Vulkan Specification: the core API (e.g. versions 1.x) only; core API with all registered `KHR` and `EXT` extensions; and core API with all registered extensions.

#### 3.10.1. Changes for New Extensions

If a new extension, or a related group of them is of sufficient scope to require a new chapter of the specification, localize such changes into a new asciidoc file. Include the new chapter file at a relevant point in `vkspec.adoc` so it is incorporated in the specification build, with appropriate asciidoc conditional protections so it is only included when needed for the specification being built. An example can be found in `chapters/videocoding.adoc`.

Most extensions are not entirely self-contained, and also require changes in existing parts of the specification to document new interactions. Such changes should be inlined in existing chapters.

Extensions may also require small additions to `vk.xml`, in addition to defining the extension interfaces themselves, for purposes such as introducing new return codes or extending structures to existing APIs.

Note | We do not yet fully document an example of including a new version or extension. New versions are authored only by Khronos and examples will be available at such time that we publish a new version. Extension authors should refer to the default branch and search for the names of existing extensions, such as `VK_KHR_surface`, for markup examples. Some aspects of the changes for this example extension are described below.

Changes for extensions include (but may not be limited to) the following:

- All extensions must add an appendix to the Vulkan specification. The appendix can be modeled after the `VK_KHR_shader_float_controls` extension in `appendices/VK_KHR_shader_float_controls.adoc`. It contains metainformation about the extension as well as code examples, and revision history. Other useful references are the `VK_KHR_shader_draw_parameters` appendix, which includes a variety of external dependencies and interactions, and the `VK_EXT_debug_marker` appendix, which is a simpler, standalone example.

  - The extension appendices are also incorporated in separate per-extension reference pages, and must rigidly follow the structure of the model appendices (although individual subsections can be added or removed as required).

  - When creating references to the extension appendix from elsewhere in the Specification, use the custom macro `apiext:`, instead of an explicit asciidoc link: macro. This allows more easily checking for invalid extensions, and changing the link target for generated reference pages and other alternate output forms.

    Example Markup

        A link to the `apiext:VK_KHR_shader_float_controls` extension.

        Do not use this (old) form: `<<VK_KHR_shader_float_controls>>`.

    Note | If you are converting an old branch with extension references in it to use the `apiext:` macro, you can use this shell script:
        sed -i -E 's/`?<<(VK_[A-Za-z0-9_]*)>>`?/`apiext:\1`/g' chapters/{*.adoc,*/*.adoc} appendices/*.adoc

- In the preamble to the appendix, start with an asciidoc `include` of the automatically generated meta information. This information includes the extension name string, type, number, revision, and contact information from `vk.xml`.

- Following the `include`, add an Other Extension Metadata subsection containing as many of the following items as are meaningful:

  - Status - Complete, Draft, or other. When an extension is published in the default branch, it is normally assumed to be complete; the Status field should be removed at this time, unless it contains additional information.

  - Last Modified Date - if wanted, although git log queries can provide equivalent information.

  - IP Status - Such as No known IP claims, or more specific information if there are known IP claims and the extension has, or has not been ratified by the Khronos Board of Promoters.

  - Interactions and External Dependencies - may include requirements or interactions with optional Vulkan features, SPIR-V (`SPV`) and OpenGL extensions, and interactions (other than strictly requiring) with other Vulkan extensions.

  - Contributors - Names and corporate affiliations of people who have made significant direct contributions to this extension.

- Following these items, add whitespace followed by a Description section. The first paragraph of this section should be a compact, standalone description of the extension’s functionality and purpose, suitable for use in summaries of new functionality such as press releases or the Vulkan change log. Additional paragraphs expanding on the description may be added at the author’s discretion.

- If the extension has been deprecated or promoted, add Deprecation and/or Promotion sections describing these actions. There is standard boilerplate Promotion language used when promoting to a Vulkan core version. For example, see `appendices/VK_EXT_descriptor_indexing.adoc for language used when promoting to Vulkan core, with some features made optional in the promoted version.

- Next, add an asciidoc `include` of the automatically generated interface information. This information includes API entities defined by the extension in `vk.xml`, such as new commands, structures, enumerants, and so on.

- Following the `include`, add subsections describing interface information for SPIR-V shading capabilities not captured in `vk.xml`, such as:

  - New SPIR-V Capabilities (include xrefs to the appropriate new section of the List of SPIR-V Capabilities in `appendices/spirvenv.adoc`).

  - New or Modified Built-In Variables (include xrefs to the appropriate new section of the Interfaces chapter).

  - New Variable Decorations (include xrefs to the appropriate new section of the Interfaces chapter).

- Finally, add subsections describing other information about the extension, such as:

  - Issues (in itemized list style, describing each significant issue raised during development of the extension, and its resolution).

  - Version History (in itemized list style, describing significant functional changes to the extension during its development).

- Each extension’s appendix file is automatically included from `appendices/extensions.adoc` via code generated from `vk.xml`. It is not necessary to explicitly include the appendices.

- Extensions usually make significant additions and changes to the Vulkan specification. They often add an entirely new chapter, or a new section of an existing chapter, defining the new commands, structures, and enumerants. For example, `VK_EXT_debug_marker` adds a new section of the “Debugging” chapter in `chapters/debugging.adoc`. in that file:

  Example Markup

      ifdef::VK_EXT_debug_marker[]
      [[debugging-debug-markers]]
      == Debug Markers

      ...
      endif::VK_EXT_debug_marker[]

- In every other place where the extension alters the behavior of the core Specification, make such changes and protect the modifications with the same asciidoc conditionals. For example, `VK_KHR_surface` adds a new valid usage statement to `vkEndCommandBuffer` in `chapters/cmdbuffers.adoc`, which is protected as follows:

  Example Markup

      ... previously defined valid usage statements
      ifdef::VK_EXT_debug_marker[]
        * [[VUID-vkEndCommandBuffer-commandBuffer-00062]]
          If pname:commandBuffer is a secondary command buffer, there must: not be
          an outstanding flink:vkCmdDebugMarkerBeginEXT command recorded to
          pname:commandBuffer that has not previously been ended by a call to
          flink:vkCmdDebugMarkerEndEXT
      endif::VK_EXT_debug_marker[]

- If two extensions interact, the asciidoc conditionals must be carefully structured so as to properly document the interactions if the specification is built with both extensions. Asciidoc conditionals allow AND and OR constructs.

  Example Markup

      ifdef::VK_KHR_foo[]
      ... discussion of VK_KHR_foo ...
      endif::VK_KHR_foo[]
      ifdef::VK_KHR_foo+VK_KHR_fum[]
      ... discussion of interactions between VK_KHR_foo and VK_KHR_fum when both
      are defined ...
      endif::VK_KHR_foo+VK_KHR_fum[]

- In cases where a new extension (A) modifies both core and an existing extension (B), if the new extension (A) becomes part of the core at a future release (i.e. is no longer an extension), the portion of the new extension that modified the existing extension (B) effectively becomes part of that existing extension. Thus, at the new core release, enabling the pre-existing extension (B) also enables the functionality that was previously enabled by enabling the previously-new extension (A).

- For vendor extensions, changes made to existing core Specification source files and to `vk.xml` normally fall under the Contributor License Agreement, which assigns copyright to Khronos. Entirely new files added by vendors can use their own copyright attribution. Vendors may add their own copyright attribution when they make changes to existing markup files, although this is discouraged. In all cases, the copyright license terms must be the same as the rest of the Specification repository.

- In most cases, there will be no new files added to the Specification, only changes. When a new chapter and/or appendix is added, there will be new files `extensions/extension_name.adoc` and/or `chapters/extension_name.adoc`.

- Valid usage statements referring to interactions between structures in a `pNext` chain must be described in the parent structure’s language, as specified in more detail below.

- Valid usage statements should be written including all relevant version and extension information embedded in the text, and surrounded by preprocessor directives as necessary, rather than simply relying on an `ifdef` to take care of it. For example, instead of:

  Example Markup

      ifndef::VK_VERSION_1_3[]
        * At least one of the following must: be true:
      ifdef::VK_EXT_extended_dynamic_state[]
        ** the <<features-extendedDynamicState, pname:extendedDynamicState>>
           feature is enabled
      endif::VK_EXT_extended_dynamic_state[]
      ifdef::VK_EXT_shader_object[]
        ** the <<features-shaderObject, pname:shaderObject>>
           feature is enabled
      endif::VK_EXT_shader_object[]
      endif::VK_VERSION_1_3[]

  where the version overrides the need for the features, add a condition for the version too:

  Example Markup

        * At least one of the following must: be true:
      ifdef::VK_EXT_extended_dynamic_state[]
        ** the <<features-extendedDynamicState, pname:extendedDynamicState>>
           feature is enabled
      endif::VK_EXT_extended_dynamic_state[]
      ifdef::VK_EXT_shader_object[]
        ** the <<features-shaderObject, pname:shaderObject>>
           feature is enabled
      endif::VK_EXT_shader_object[]
      ifdef::VK_VERSION_1_3[]
        ** the value of slink:VkApplicationInfo::pname:apiVersion used to create
           the slink:VkInstance parent of pname:commandBuffer is greater than or
           equal to Version 1.3
      endif::VK_VERSION_1_3[]

When writing language dependent on the interaction of multiple extensions, asciidoc conditional syntax is very restricted and only supports a single level of logical AND (`+`) or OR (`,`) operators. For example, if a section of text only applies when one extensions is enabled and another is not, the following markup will not work:

Example Markup (Does Not Work)

    ifdef::VK_KHR_shader_float16_int8+!VK_KHR_8bit_storage[]
    This should only appear if VK_KHR_shader_float16_int8 is defined and
    VK_KHR_8bit_storage is not defined.
    endif::VK_KHR_shader_float16_int8+!VK_KHR_8bit_storage[]

Instead, expand the complex conditional into nested simpler ones:

Example Markup (Does Work)

    ifdef::VK_KHR_shader_float16_int8[]
    ifndef::VK_KHR_8bit_storage[]
    This should only appear if VK_KHR_shader_float16_int8 is defined and
    VK_KHR_8bit_storage is not defined.
    endif::VK_KHR_8bit_storage[]
    \endif::VK_KHR_shader_float16_int8

#### 3.10.2. Changes for New API Versions

When creating a new version of the core API, such as Vulkan 1.1, changes are done similarly to extensions, with the following differences:

Note | This list is being developed in conjunction with the Vulkan 1.1 Specification, is probably incomplete, and is subject to change. Items marked TBD are still being discussed within the Vulkan Working Group.

- New API versions will be more tightly integrated into the specification sources than extensions, although it is still helpful to partition changes into new files when they are sufficiently self-contained.

- New API versions must add an appendix to the Vulkan specification. Unlike the extension appendices, this appendix simply summarizes release information (dates of Ratification by the Khronos Board of Promoters, and of public release), the contributor list, and high-level descriptions of new features in this version (including the names of any extensions promoted to core status in this version).

  - TBD - we might choose to include a new API summary with links into the specification body for new features, as well.

- TBD - how to name and where to include this appendix file.

- Changes to the Specification for new versions will range from small changes to existing language, to new commands and structures, to adding entire new chapters. New chapters must be defined in separate files under the `chapters/` directory, and included at an appropriate point in `vkspec.adoc` or other specification source files. Other changes and additions are included inline in existing chapters.

- All changes that are specific to the new version must be protected by the asciidoc conditional (e.g. the version name). For example, in the case of Vulkan 1.1:

  Example Markup

      Add a new chapter:

      ifdef::VK_VERSION_1_1[]
      include::{chapters}/newchapter11.adoc[]
      endif::VK_VERSION_1_1[]

      Add a new feature:

      ifdef::VK_VERSION_1_1[]
      ... language describing the new command, structure, or enumeration
      endif::VK_VERSION_1_1[]

- The specification must continue to be a valid document when the new version is not defined, so that (for example) the Vulkan 1.1 branch specification can continue to be updated.

- TBD - how to deprecate extensions which have been promoted to core status in the new version, while continuing to have those extensions appear then older versions of the specification are being built.

- The same constraints described above for Valid Usage statements modified by extensions apply for new versions.

### 3.11. Assigning Extension Token Values

Extensions can define their own enumeration types and assign any values to their enumerants that they like. Each enumeration has a private namespace, so collisions are not a problem. However, when extending existing enumeration objects with new values, care must be taken to preserve global uniqueness of values. Enumerations which define new bits in a bitmask are treated specially as described in Reserving Bitmask Values below.

Each extension is assigned a range of values that can be used to create globally-unique enum values. Most values will be negative numbers, but positive numbers are also reserved. The ability to create both positive and negative extension values is necessary to enable extending enumerations such as `VkResult` that assign special meaning to negative and positive values. Therefore, 1000 positive and 1000 negative values are reserved for each extension. Extensions must not define enum values outside their reserved range without explicit permission from the owner of those values (e.g. from the author of another extension whose range is infringed on, or from the Khronos Registrar if the values do not belong to any extension’s range).

Note | Typically, extensions use a unique offset for each enumeration constant they add, yielding 1000 distinct token values per extension. Since each enumeration object has its own namespace, if an extension needs to add many enumeration constant values, it can reuse offsets on a per-type basis.

The information needed to add new values to the XML are as follows:

- The extension name (e.g. `VK_KHR_swapchain`) that is adding the new enumeration constant.

- The existing enumeration type being extended (e.g. `VkStructureType`).

- The name of the new enumeration token being added (e.g. `VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR`).

- The offset, which is an integer between 0 and 999 relative to the base being used for the extension.

- The direction may be specified to indicate a negative value (`dir="-"`) when needed for negative `VkResult` values indicating errors, like `VK_ERROR_SURFACE_LOST_KHR`. The default direction is positive, if not specified.

- The extension number is usually implicit and taken from metadata of the extension being defined. It is used to create a range of unused values specific to that extension.

Individual enumerant values are calculated as offsets in the range defined by the extension number, as follows:

- base_value = 1000000000

- range_size = 1000

- enum_offset(extension_number, offset) = base_value + (extension_number - 1) × range_size + offset

- Positive values: enum_offset(extension_number, offset})

- Negative values: enum_offset(extension_number, offset})

The exact syntax for specifying extension enumerant values is defined in the Vulkan API Registry schema documentation. Extension authors should also refer to existing extensions for examples.

If an extension is promoted to another extension or to a core API version, the enumerant values should remain the same as they were in the original extension, in order to maintain binary compatibility with existing applications. In this case, the extension number will need to be specified explicitly to keep the promoted enumerant value unchanged.

#### 3.11.1. Reserving Bitmask Values

Enumerants which define bitmask values are a special case, since there are only a small number of unused bits available for extensions. For core Vulkan API and KHR extension bitmask types, reservations must be approved by a vote of the Vulkan Working Group. For EXT and vendor extension bitmask types, reservations must be approved by the listed contact of the extension. Bits are reserved in the same fashion as extension numbers, by creating a placeholder reservation for each bit in the disabled XML `<extension>` block for that extension in the default branch. Once the extension is ready to be merged into the default branch, the `<extension>` block is updated with the actual name. An example reservation for a disabled extension is:

    <extension name="VK_AMD_extension_24" number="24" author="AMD" supported="disabled">
      <require>
        <enum bitpos="6" extends="VkQueueFlagBits" name="VK_QUEUE_RESERVED_6_BIT_KHR"/>

Bit position 31 may not be used, due to inconsistent behavior by C compilers. This is enforced by the generator scripts.

Note | Because of the way in which extension bitmask values are assigned inside the XML `<extension>` tag, it is not always obvious what the next free bit in a bitmask type is, or when a collision occurs. The script `scripts/nextfreebits.py` can be used to determine which bits are not yet used or reserved in the XML. When run with a specific `Vk*FlagBits*` name, it will report only on that type. Otherwise it will report on all bitmask types in the XML. It is also possible, but more difficult to determine the next free bit for a given bitmask type by manually searching the XML. Just looking at the generated headers is not sufficient, because bits reserved in disabled extension are not included in the headers. When generating the headers, the script will raise warnings about “Two enums found with the same value” that will help identify this problem.

When a 32-bit flags type is close to running out of bits, a corresponding 64-bit flag type may be created for use with new interfaces, such as the VkAccessFlags and VkAccessFlags2KHR types. These flag types have corresponding 32- and 64-bit bitmask types (VkAccessFlagBits and VkAccessFlagBits2KHR). When reserving remaining bits at bit positions 0 through 30, a similarly named bit should be reserved in both bitmask types (VK_ACCESS_MEMORY_READ_BIT and VK_ACCESS_2_MEMORY_READ_BIT), to avoid having the same bit used for different purposes in two otherwise very similar interfaces. If that usage is not actually supported by one or the other bitmask type, the bit should still be reserved, but commented out in the XML.

### 3.12. New Flags and Bitmask Types

When an extension introduces a new flags (`*Flags`) type, it should also introduce a corresponding new bitmask (`*FlagBits`) type. The flags type contains zero or more bits from the bitmask, and is used to specify sets of bits for commands or structures.

In some cases, a new flags type will be defined with no individual bits yet specified. This usage occurs when the flags are intended for future expansion. In this case, even though the corresponding bitmask type is not yet useful, the (empty) bitmask type should be defined in `vk.xml`. The empty bitmask type and corresponding flags type should be given boilerplate definitions in the specification.

### 3.13. Required Extension Tokens

In addition to any tokens specific to the functionality of an extension, all extensions must define two additional tokens.

- `VK_EXTNAME_SPEC_VERSION` is an integer constant which is the revision of the extension named `VK_extname` (`EXTNAME` is all upper-case, while extname is the capitalization of the actual extension name). This value begins at 1 when an extension specification is first published (pre-release versions may use an internal numbering scheme that is reset at release time), and is incremented when changes are made. Note that the revision of an extension defined in the Vulkan header files and the revision supported by the Vulkan implementation (the `specVersion` field of the `VkExtensionProperties` structure corresponding to the extension and returned by one of the extension queries) may differ. The revision value indicates a patch version of the extension specification, and differences in this version number maintain full compatibility, as defined in the “Compatibility Guarantees” section of the Vulkan API Specification.

Note | Any changes requiring the addition or removal of a type or command should be done by creating a new extension. The resulting extension should take care to include the appropriate dependency information on the original extension.

Note | When the Debug Report extension (VK_EXT_debug_report) was recently updated to include the enum values of VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_KHR_EXT and VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT, we violated this policy. That change was done prior to this revision policy clarification. We intend to follow this policy in the future, although in exceptional circumstances an exception may be made.

- `VK_EXTNAME_EXTENSION_NAME` is a string constant which is the name of the extension.

For example, for the WSI extension `VK_KHR_surface`, at the time of writing the following definitions were in effect:

    #define VK_KHR_SURFACE_SPEC_VERSION 24
    #define VK_KHR_SURFACE_EXTENSION_NAME "VK_KHR_surface"

### 3.14. Extension Handles, Objects, Enums, and Typedefs

Expanding on previous discussion, extensions can add values to existing enums; and can add their own commands, enums, typedefs, etc. This is done by adding to `vk.xml`. All such additions will be included in the Vulkan header files supplied by Khronos.

If the extension adds a new handle to Vulkan, a corresponding value must be added to VkObjectType (as defined in the “Debugging” section of the Vulkan API Specification) in order to allow components to identify and track objects of the new type.

The new enumeration value must conform to the naming defined in the Extension Enumerant Names section. In this case, the type’s `Vk` prefix is replaced with the enum prefix `VK_OBJECT_TYPE_`, and the rest of the handle name is converted as described in that section.

Table 3. Conversion of Handle to `VkObjectType` Examples:
Handle | `VkObjectType` token
--- | ---
VkSurfaceKHR | VK_OBJECT_TYPE_SURFACE_KHR
VkDescriptorUpdateTemplateKHR | VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_KHR

### 3.15. Extension Function Prototypes

Function pointer declarations and function prototypes for all core Vulkan API commands are included in the Vulkan header files. These come from the official XML specification of the Vulkan API hosted by Khronos.

Function pointer declarations are also included in the Vulkan header for all commands defined by registered extensions. Function prototypes for extensions may be included in the headers. Extension commands that are part of the Vulkan ABI must be flagged in the XML. Function prototypes will be included in the headers for all extension commands that are part of the Vulkan ABI.

An extension can be considered platform specific, in which case its interfaces in the header files are protected by #ifdefs. This is orthogonal to whether an extension command is considered to be part of the Vulkan ABI.

The initial set of WSI extension commands (i.e. for `VK_KHR_surface`, `VK_KHR_swapchain`, and `VK_KHR_*_surface`) are considered to be part of the Vulkan ABI. Function prototypes for these WSI commands are included in platform-specific files such as `vulkan_android.h`. See the “Window System-Specific Header Control (Informative)” section of the Vulkan Specification for more details.

Note | Based on feedback from implementors, Khronos expects the Android, Linux, and Windows Vulkan SDKs to include our header files, and export the supported WSI functions for those platforms from their loader libraries. Other implementations can make different choices for their headers and loader libraries, but are encouraged to be consistent with these implementations.

### 3.16. Accessing Extension Functions From Programs

`vkGetInstanceProcAddr` and `vkGetDeviceProcAddr` can be used in order to obtain function pointer addresses for core and extension commands (per the description in the “Command Function Pointers” section of the Vulkan API Specification). Different Vulkan API loaders can choose to statically export functions for some or all of the core Vulkan API commands, and can statically export functions for some or all extension commands. If a loader statically exports a function, an application can link against that function without needing to call one of the `vkGet*ProcAddr` commands.

Note | The Vulkan API loader for Android, Linux, and Windows exports functions for all core Vulkan API commands, and for a set of WSI extension commands that are applicable to those operating systems (see Vulkan loader documentation for the relevant platform/OS for details). The WSI functions are considered special, because they are required for many applications.

### 3.17. Extending Structures

Extending structures modify the behavior of existing commands or structures by providing additional parameters, using the `pNext` field of an existing structure to point to a chain of additional structures. This mechanism is described in more detail in the “Valid Usage for Structure Pointer Chains” section of the Vulkan API Specification.

Multiple extending structures affecting the same structure, defined by multiple core versions or extensions, can be chained together in this fashion. Any structure which can be chained in this fashion must begin with the following two members:

    VkStructureType        sType;
    const void*            pNext;

It is in principle possible for extensions to provide additional parameters through alternate means, such as passing a handle parameter to a structure with a `sType` value defined by the extension. This approach is strongly discouraged.

When chaining multiple extending structures together, the implementation will process the chain starting with the base structure and proceeding through each successive extending structure in turn. Extending structures should behave in the same fashion no matter the order of chaining, and must define their interactions with other extensions such that the results are deterministic.

If an extending structure must be present in a `pNext` chain in specific ordering relative to other structures in the chain in order to provide deterministic results, it must define that ordering and expected behavior as part of its specification and valid usage statements.

Note | Specific ordering requirements in a `pNext` chain are strongly discouraged.

Validation of structure types in `pNext` chains is automatically generated from the registry, based on the description of `structextends` in the registry document.

### 3.18. Valid Usage and `pNext` Chains

When there is a Valid Usage interaction between a parent structure and an extending structure appearing in the `pNext` chain of the parent, that interaction must be described in the explicit Valid Usage section of the parent structure, rather than the extending structure, and must be protected by appropriate extension-specific `ifdef` constructs.

For example, a constraint added to the `VkImageCreateInfo` structure by the presence of structures defined by two extensions which cannot interact is described as:

Example Markup

    // CORRECT: define interaction with children in parent VkImageCreateInfo
    // structure
    ifdef::VK_NV_external_memory+VK_KHR_external_memory[]
      * If the pname:pNext chain includes a
        slink:VkExternalMemoryImageCreateInfoNV structure, it must: not include
        a slink:VkExternalMemoryImageCreateInfoKHR structure.
    endif::VK_NV_external_memory+VK_KHR_external_memory[]

However, a constraint added to `VkBufferCreateInfo` by an extending structure in the `VK_NV_dedicated_allocation` extension must not be described as part of the extending structure’s valid usage:

Example Markup

    // WRONG! Do not define interaction with parent in child
    // VkDedicatedAllocationBufferCreateInfoNV structure
      * If pname:dedicatedAllocation is ename:VK_TRUE,
        sname:VkBufferCreateInfo::pname:flags must: not include
        ename:VK_BUFFER_CREATE_SPARSE_BINDING_BIT,
        ename:VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT, or
        ename:VK_BUFFER_CREATE_SPARSE_ALIASED_BIT

Instead, define the constraint as part of the parent `VkBufferCreateInfo` structure’s valid usage:

Example Markup

    // REWRITTEN CORRECTLY: Define interaction with child in
    // parent VkBufferCreateInfo structure
    ifdef::VK_NV_dedicated_allocation[]
      * If the pname:pNext chain includes a
        slink:VkDedicatedAllocationBufferCreateInfoNV structure, and the
        pname:dedicatedAllocation member of the chained structure is
        ename:VK_TRUE, then pname:flags must: not include
        ename:VK_BUFFER_CREATE_SPARSE_BINDING_BIT,
        ename:VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT, or
        ename:VK_BUFFER_CREATE_SPARSE_ALIASED_BIT
    endif::VK_NV_dedicated_allocation[]

### 3.19. Feature Structures

A feature structure is a structure that extends `VkPhysicalDeviceFeatures2` and `VkDeviceCreateInfo`, and which provides VkBool32 members to indicate implementation support for individual features.

    typedef struct VkPhysicalDeviceImageRobustnessFeaturesEXT {
        VkStructureType    sType;
        void*              pNext;
        VkBool32           robustImageAccess;
    } VkPhysicalDeviceImageRobustnessFeaturesEXT;

Every device or physical-device extension that adds or modifies device-level commands, or adds new structures or enum values used in device-level commands, must define a feature structure.

If an extension requires a feature structure, then any mandatory features must be described in the Feature Requirements section. New extensions must mandate that implementations support at least one feature of an extension.

Example Markup

    ifdef::VK_EXT_image_robustness[]
      * <<features-robustImageAccess, pname:robustImageAccess>>, if the
        `apiext:VK_EXT_image_robustness` extension is supported.
    endif::VK_EXT_image_robustness[]

For WSI extensions, it is often necessary to extend `VkSurfaceCapabilities2KHR` in order to enable compatibility between a `VkSurface` and a `VkPhysicalDevice` to be queried. Every device or physical-device extension that relies upon support from the window system should implement this query.

The presence of a structure extending `VkSurfaceCapabilities2KHR` does not remove the requirement for a feature structure if any device-level functionality is introduced by an extension.

## 4. Markup Style

This chapter demonstrates asciidoc and Specification structure, including text layout and markup style.

### 4.1. Directory Structure and File Names

All asciidoc markup files in the Specification must have a filename ending in `.adoc`.

Specification markup files must go in one of the top-level directories `appendices` or `chapters`.

When a file defining a new chapters or appendix is added, it must be included from the top-level `vkspec.adoc` file, appropriately protected by asciidoc conditionals if the file is specific to an extension or core version. The file must also be included from the Antora navigation file `antora/spec/modules/ROOT/nav.adoc`, but without any asciidoc conditionals, since the Antora build always includes all extensions and core versions.

### 4.2. Copyrights and Licenses

The asciidoc source for the Vulkan Specification and related documents is under an open source license.

When creating a new file, add the following copyright and license statement at the top:

Example Markup

    // Copyright YEAR AUTHOR
    // SPDX-License-Identifier: CC-BY-4.0

`YEAR` should be replaced by the year in which the file was created.

`AUTHOR` is normally “The Khronos Group Inc.”. If a new file is created by a member company or outside contributor, use that entity’s legal name as the author.

`SPDX-License-Identifier` gives the license used for the file, following the SPDX standard for short identifiers in source files. `CC-BY-4.0` is the short identifier for the Creative Commons Attribution 4.0 International license.

No matter who holds the copyright on a source file for the Specification, it must be placed under the `CC-BY-4.0` license. When contributing to the Specification, contributors are required to execute a Contributor License Agreement to this effect.

When updating an existing file, modify the following copyright and license statement to include the year(s) of modification. For example:

Example Markup

    // Copyright 2018-2026 The Khronos Group Inc.
    // SPDX-License-Identifier: CC-BY-4.0

indicates a file which has been modified in 2018, 2019, and 2020 inclusive.

Files which are not actual specification source but are “code-like”, such as scripts and Makefiles, are normally placed under the Apache 2.0 license. Use `Apache-2.0` as the license identifier for such files.

### 4.3. Document Structure

Chapters and sections follow a rigid template consisting of an optional anchor (if other parts of the document cross-reference the section) followed by a one line title and a blank line. The anchor is typically the base name of the file containing the chapter, with a lowercased version of the section name following, with spaces replaced by dashes.

Always use the one-line title form, with one to four `=` signs preceding the chapter/section title. The two-line title form cannot be easily searched for, and often looks like other types of asciidoc delimiters. Using a mix of one-line and two-line titles causes compatibility issues, and using the two-line title form may implicitly set a backwards-compatibility syntax mode we do not want.

Always precede the anchor by two blank lines (except at the beginning of a file), and follow the title by a blank line, to set off sections visibly.

Example Markup

    [[markup]]
    = Markup Style

    [[markup-sample-section]]
    == Sample Section

#### 4.3.1. Include File Paths

When using the asciidoc `include::` directive anywhere other than the top-level file of the document, always use a full (absolute) path to the file being included. To make this easier, the specification build process defines several attributes which refer to different paths in the document tree:

- `{chapters}` - path to the `chapters/` directory containing most of the specification.

- `{appendices}` - path to the `appendices/` directory containing appendices.

- `{generated}` - path to the temporary directory containing generated files such as API includes.

- `{config}` - path to configuration files used in the specification toolchain.

Numerous examples of using these attributes are given in the Writing Style and API Versions, Extensions, and Layers chapters.

### 4.4. Sample Section

This is a sample section structurally similar to the Vulkan API Specification, nested one level inside a chapter. Sections can be nested up to level 5, although not all levels are included in the Table of Contents.

### 4.5. Asciidoc Markup and Text Layout

Asciidoc source should be text filled to 76 columns with hard line breaks. Each sentence in a paragraph ends with a newline to minimize git diff conflicts. Except when necessary for lists or other markup, text should begin at the first column of each line (leading spaces are often semantically meaningful in asciidoc markup).

UTF-8 characters outside the ASCII subset should be used sparingly, only when needed for non-English names. Instead use asciidoc markup for special characters, if required. For example, two hyphens produces an em-dash:

Note | Example Markup `An -- em-dash` → An — em-dash

As an exception, multiplication should be marked with the unicode multiplication symbol “×” (and not an asterisk) when used in plain text. You may also use the `{times}` asciidoc attribute for this symbol. In math sections, the same symbol should be referred to as `\times`. In code sections, a conventional asterisk (`*`) should be used instead.

The trailing `+` character causes a hard break in asciidoc markup, and should not be used except for this purpose. Markup addition with the {plus} asciidoc attribute, except in LaTeX math and source blocks.

See the asciidoc supported special characters, as well as use of entity references.

Quotation marks should use the 66/99 convention. That is, double asymmetric quotation marks, indicated by a quotation mark then a backtick as opening marks, and a backtick then quotation mark as closing marks ("`like this`"), which renders “like this”.

Never use hard tabs or trailing blanks.

- In some cases, limitations of asciidoc markup may result in lines that are longer than 76 characters and cannot easily be shortened without compromising the output documents.

#### 4.5.1. Minimize Indentation

Indentation (leading whitespace) for markup should not be used, except for bullet lists as described below. Leading whitespace can affect asciidoc processing.

When presenting unformatted text, use asciidoc source blocks as described in the next section. Source blocks do allow leading whitespace, for example when including sample code in C.

#### 4.5.2. Blocks

There are a variety of asciidoc block constructs. With the exception of tables and of open blocks used to group markup together, blocks should be delimited by exactly four repeated characters indicating the block type, for consistency. The block types and delimiters are shown in the following table.

Table 4. Asciidoc Block Delimiters
Table Type | Delimiter | Comments
--- | --- | ---
Open | `--` | For continuation blocks and reference pages
Open (alt.) | `----` | For continuation blocks inside reference pages. Must be preceded by `[open]`
Example | `====` | For Notes
Passthrough | `++++` | For some kinds of math markup
Comment | `////` |
Listing | `----` | For source code listings
Sidebar | `****` | For implementor’s notes
Table | `|====` | For tables
Quote | `____` |
Literal | `....` |

##### Open Blocks Nested in Open Blocks

If you need to include an `open` block that would normally use `--` delimiters inside an open block delimiting a reference page, such as a continuation block, use the markup:

Example Markup

    [open]
    ----
    Open block contents
    ----

This replaces prior use of `~~~~` delimiters and is enabled by a custom asciidoctor extension. The `[open]` block type is required in this case, to distinguish the block from a regular listing block using the same delimiter.

#### 4.5.3. Footnotes

Use manually marked-up footnotes (the asciidoc footnote construct is OK for PDF outputs, but does not work well with long HTML documents since it places all footnotes at the end of the document).

Refer to footnotes with asciidoc superscript notation1, and mark up the footnotes below, but near the references as labeled lists. Manually assigned footnote numbers will inevitably be reused, which is OK as long as the colliding numbers are not in the same section.

1

  Like this example footnote.

Note | Example Markup
    See reference^2^

    2::
        Reference 2.
→ See reference2 2 Reference 2.

#### 4.5.4. Lists

##### Bullet Lists and Continuation Blocks

- Bullet lists are the preferred form of list, aside from glossary definitions.

- Lists should have text indented by 4 spaces and the list item delimiter (e.g. one or more asterisks, for bullet lists) indented by two spaces.

  Note that continuation blocks for list items longer than one paragraph cannot be indented, only the first paragraph.

  In general, successive list items should not be separated by white space. However, list continuation blocks should be followed by a `+` on a line by itself, or by a blank line, due to limitations of the asciidoc parser.

- Indent bullet lists two spaces (to the bullet), 4 spaces (to the text, if it extends over multiple lines). This lets us visually distinguish lists from other kinds of markup.

  - Nested lists should align the leftmost list item delimiter (bullet, etc.) with the parent delimiter.

Example Markup

      * This is the first item in a bullet list.
      * The second item is described with two paragraphs.
        The second paragraph is in a continuation block:
    +
    This is a continuation block containing the second paragraph,
    +
      ** This is a nested list item for the second item.
         Since it follows a continuation block, it must be separated by a blank
         line or `+` from that block.

- This is the first item in a bullet list.

- The second item is described with two paragraphs. The second paragraph is in a continuation block:

  This is a continuation block containing the second paragraph,

  - This is a nested list item for the second item. Since it follows a continuation block, it must be separated by a blank line or `+` from that block.

- It is possible to continue a paragraph of the first bullet after a list of sub-bullets if so desired by using continuations in a similar fashion:

Example Markup

      * This an item in a bullet list.
    +
      ** This is a nested list item for the second item.
         Since it follows a continuation block, it must be separated by a blank
         line or `+` from that block.
    +
    This is a continuation of the first bullet

- This an item in a bullet list.

  - This is a nested list item for the second item. Since it follows a continuation block, it must be separated by a blank line or `+` from that block.

    This is a continuation of the first bullet

##### Labeled Lists

Labeled lists may be used in some cases such as footnotes; glossary entries; and long lists of information about similar names, such as the “Features, Limits, and Formats” chapter of the Vulkan Specification. Whenever labeled lists are used the label and its terminating double colon must be alone on a line, followed by the contents of that list entry.

For consistency do not use labels ending in three or four colons, or two semicolons, even though these forms are allowed in asciidoc markup.

Example Markup

    Glossary Entry::
        This is a glossary entry.

    Last Modified Date::
        2016-02-16

##### Numbered Lists

Numbered lists may be used if strictly necessary to place an ordering on list items. Always use implicit numbering, with the bullet point being a single period.

1. Explicit numbering with a number preceding the period is prone to accumulating errors as edits are made.

2. In addition, the markup is harder to recognize for scripts and tools (other than asciidoctor itself) operating on the document source.

Example Markup

    . First list item.
    . Second list item.
    . Etc.

#### 4.5.5. Anchors and Cross-references

Chapters, sections, and tables should always have anchors, following the naming convention discussed above. Anchors to other parts of the document may be inserted as needed. In addition, the autogenerated include files defining commands, structures, enumerations, and flags all include anchors whose name is the name of the command or type being defined, so it is easy to link to a (for example) a command name such as vkCreateCommandPool. However, using the markup macros described below is preferred when linking to anchors corresponding to API names, such as vkCreateCommandPool.

If you want a cross-reference to an anchor to appear as something other than the raw anchor name, always make sure to include that text as part of the cross-reference. There are several different toolchains used for various forms of asciidoctor output, and not all of them treat anchors without alt-text the same way.

Example Markup

    Chapters, sections, and tables should always have anchors, following the
    naming convention <<markup,discussed above>>.
    ...
    command or type being defined, so it is easy to link to a (for example) a
    command name such as <<vkCreateCommandPool,vkCreateCommandPool>>.
    However, using the <<markup-macros,markup macros>> described below is
    preferred when linking to anchors corresponding to API names, such as
    flink:vkCreateCommandPool.

#### 4.5.6. Feature Cross-References

When creating a cross-reference to an API feature (see the “Features, Limits, and Formats” chapter of the Vulkan Specification), use the following markup convention:

Example Markup

    The <<features-someFeatureName, pname:someFeatureName>> feature ...

Always use the API feature name as the cross-reference text.

#### 4.5.7. Tables

Asciidoc tables should use the block prefix `|====`. Where feasible, align the `|` separating cells across rows. This will sometimes result in very wide tables in the source document, but makes it easier to see which cells belong to which column. Alternatively, long cells can be broken onto a separate line with the `|` separator appearing first, except for the first row of the table, which must all appear on a single line.

Tables should always be given an anchor, following the convention in the Document Structure section for section anchors, but appending “-table” to the anchor name.

Tables should be preceded with a short title. If a longer

Example Markup

    [[markup-normative-terminology-macros-table]]
    .Normative Terminology Macros
    [width="100%",options="header"]
    |====
    | Macro Name     | Output
    | can{cl}        | can:
    | cannot{cl}     | cannot:
    |====

#### 4.5.8. Figures

All figures (images) must be marked up as follows, to ensure there is an anchor and that the figure is given a caption which shows the figure number and is added to the list of figures.

Example Markup

    [[markup-caption-figure]]
    image::{images}/imagename.svg[align="center",title="Figure caption",opts="{imageopts}"]

There must be SVG versions of each figure checked into the `images/` directory, to support generating both HTML and PDF outputs. This directory is referred to as `{images}` so that there is a consistent path no matter what directory the file including the images is in. The PDF generation pipeline is now able to use SVG images, so PDF versions of each image are no longer required. The `opts=` attribute defaults to `inline`, which decreases output image size in the generated HTML. However, the `inline` option interferes with generating HTML diffs between two specifications with the script we currently use. By using the `{imageopts}` asciidoc attribute, this behavior can be controlled.

#### 4.5.9. Longer Captions

Asciidoc restricts captions in figures and tables to be a single line in the source document, rendered as a single paragraph. If a longer or more complexly formatted caption is required, follow the figure or table markup with a sidebar block including the full caption, preceded by a link to the figure or table.

Example Markup

    .Caption
    ****
    In the <<markup-caption-figure, Figure caption>> diagram, the diagram
    represents
    ... long caption text here.
    ****

#### 4.5.10. Indentation of Equations

Asciidoc separates structural markup in asciidoc source from formatting, in HTML CSS stylesheets and invoked via asciidoc “role” attributes on blocks. However, the flexibility of CSS stylesheets is not available in PDF layout using the existing PDF toolchain and YML stylesheets.

Explicit indentation should be used sparingly in the specification, but one place it is useful is with equations. Using asciidoc math markup, the easiest way to produce indentation is with a list where the leading bullet or descriptive text is suppressed

Example Markup

    [none]
      * A {plus} B

    or

      {empty}:: A {plus} B

→

- A + B

or

  A + B

#### 4.5.11. Italicized Enumerant Names

When writing a “wildcard” enumerant name containing an italicized term within it, it is difficult to directly combine constrained formatting markup (double underscores) and the single underscores that separate words in the enumerant. Instead, use attribute substitution as suggested in the “Escape unconstrained formatting marks” section of the AsciiDoc Language Documentation. To help when this is required, an attribute `{ibit}` expanding to `_i_` is defined in `config/attribs.adoc`, and the same technique can be used for similar markup in other cases if `i` is not the desired italicized term:

Example Markup

    `VK_IMAGE_ASPECT_PLANE__{ibit}__BIT`

→

`VK_IMAGE_ASPECT_PLANE_i_BIT`

Note | This technique cannot be used with the markup macros that are normally used to semantically tag API names. Because there are so few places it is needed, conventional backquote formatting markup is used instead.

### 4.6. Markup Macros and Normative Terminology

This section discusses macros used in the document. In addition to the macros defined by asciidoctor itself, additional macros are defined by the Vulkan API Specification and Reference Page configuration files.

#### 4.6.1. API Markup Macros

These macros must be used to tag command, structure, enumeration, enumerant, and other Vulkan-specific names so they can be rendered in a distinctive fashion, link to definitions of those names, and be easily searched for in the source documents. The validation scripts (`make allchecks` output) also rely on these macros being used consistently and correctly. The API markup macros, with examples of their use, are in the following table (note that these examples will not actually successfully link into corresponding specification or reference pages, since they are in an unrelated document).

Table 5. API Markup Macros
Macro Name | Usage and Meaning
--- | ---
reflink: | Generates a cross-reference or link to an unknown type of API entity. This is only used in generated content in the reference pages which refers to other reference pages which are not actually part of the API. Example: reflink:WSIheaders → WSIheaders.
`apiext:` | Generates a cross-reference or link to the description of an extension. Example: `apiext:VK_KHR_ray_tracing_pipeline` → `VK_KHR_ray_tracing_pipeline`.
flink: | Generates a cross-reference or link to the definition of the command name in the macro argument. Example: flink:vkCreateCommandPool → vkCreateCommandPool.
fname: | Formats the macro argument like flink:. Does not generate a cross-reference. Example: fname:vkCreateCommandPool → `vkCreateCommandPool`. Only use this macro when necessary.
ftext: | Formats the macro argument like fname:. May contain asterisks for wildcards. Not validated. Example: ftext:vkCmd* → `vkCmd*`. Only use this macro when necessary.
slink: | Generates a cross-reference or link to the definition of the structure or handle in the macro argument. Example: slink:VkMemoryHeap → VkMemoryHeap.
sname: | Formats the macro argument like slink:. Does not generate a cross-reference. May also be an abstract structure or handle name. Example: sname:VkCommandPoolCreateInfo → `VkCommandPoolCreateInfo`. Only use this macro when necessary.
stext: | Formats the macro argument like sname:. May contain asterisks for wildcards. Not validated. Example: stext:Vk*CreateInfo → `Vk*CreateInfo`. Only use this macro when necessary.
elink: | Formats the macro argument as a Vulkan enumerated type name and links to the definition of that enumeration type. Example: elink:VkResult → VkResult.
ename: | Formats the macro argument as a Vulkan enumerant name. Example: ename:VK_EVENT_SET → VK_EVENT_SET. Note that this is not related to elink:, unlike the other macro link:/text: pairings.
etext: | Formats the macro argument like ename:. Not validated. Examples: etext:_RANGE_SIZE → `_RANGE_SIZE`, etext:VK_IMAGE_CREATE_SPARSE_* → `VK_IMAGE_CREATE_SPARSE_*` Only use this macro when necessary.
pname: | Formats the macro argument as a Vulkan parameter or structure member name. Example: pname:device → `device`.
ptext: | Formats the macro argument like pname:. May contain asterisks for wildcards. Not validated. Example: ptext:sparseResidency* → `sparseResidency*`. Only use this macro when necessary.
tlink: | Generates a cross-reference or link to the definition of the Vulkan type in the macro argument. Example: tlink:PFN_vkAllocationFunction → PFN_vkAllocationFunction. This is only used for function pointer and `Vk*Flags` types at present, although it is a potentially a catch-all for other types not covered by a more specific macro.
tname: | Formats the macro argument like tlink:. Does not generate a cross-reference. Example: tname:PFN_vkAllocationFunction → `PFN_vkAllocationFunction`. Only use this macro when necessary.
dlink: | Generates a cross-reference or link to the definition of the Vulkan C macro in the macro argument. Example: dlink:VK_NULL_HANDLE → VK_NULL_HANDLE. There are only a few macros in the Vulkan API, described in the “API Boilerplate” appendix of the Vulkan API Specification
dname: | Formats the macro argument like dlink:. Does not generate a cross-reference. Only use this macro when necessary.
basetype: | Formats the macro argument like a basic scalar type, handle name, or type defined by an external API, with a definition in the Vulkan Specification. Examples: basetype:VkBool32 → VkBool32, basetype:AHardwareBuffer → AHardwareBuffer, basetype:VkDeviceSize → VkDeviceSize. The `Std*` types used in the Vulkan video APIs intentionally have no definition in the Vulkan Specification. Use the code: macro for these types.
code: | Formats the macro argument as a code sample. Used for SPIR-V keywords, builtin C types, and names belonging to other APIs such as Linux or Windows system calls. Examples: code:uint32_t → `uint32_t`, code:ClipDistance → `ClipDistance`. code:OpImage*Gather → `OpImage*Gather`, code:StdVideoDecodeH264PictureInfo → `StdVideoDecodeH264PictureInfo`. This macro allows imbedded field member (`.`) and wildcard (`*`) text separating words, ending with an optional wildcard.

When referring to a compound name (function-parameter, or structure-member), combine the macros separated by two colons, resulting in vkCmdBindIndexBuffer::`indexType` and VkMemoryHeap::`flags`. This is often done when referring to a particular parameter or member in a part of the document other than the description of the corresponding function or structure. When a nested member within the compound name is referred to, use normal C markup:

Example Markup

    flink:vkCmdBindIndexBuffer::pname:indexType
    sname:VkExternalImageFormatProperties::pname:externalMemoryProperties.externalMemoryFeatures
    pname:pAllocateInfo->memoryTypeIndex

Note | In the macros, “`->`” is correct markup for the C arrow operator. But in any other context (including a “```” delimited inline literal) it would be subject to asciidoc character replacement substitutions, resulting in a unicode arrow: →.

##### When to Use *name: Macros

Only use the fname:, sname:, tname:, and dname: macros if no definition of the target type with a corresponding anchor exists in the document. Anchors are automatically defined when including the generated API interface definitions under `{generated}/api/*/*adoc`. If an anchor does exist, use the corresponding *link: macro.

Note | There are many legacy uses of the *name: macros that will be replaced over time. These uses date from before anchors were added to the generated API definitions.

##### When to Use *text: Macros

Only use the ftext:, stext:, etext:, and ptext: macros when describing something that should be rendered like a command, structure, enumerant, or parameter name, respectively, but is not actually one. Typically these macros are used for wildcards describing multiple API names with common prefixes or suffixes, or common subsets of API names.

##### Prime Symbols

Occasionally we want to use mathematical prime symbols as markup in regular text, outside of LaTeX math markup. While it is easy to write the single quote character for this, since that is what LaTeX uses, asciidoc will turn this into a curved quote character whenever it is followed by an alphabetic character. For example, when writing the Y′CBCR term widely used to describe a color encoding, the obvious markup does not look quite right:

Table 6. Prime Attributes (Incorrect, With Curved Prime Symbol)
Markup | Output
--- | ---
`Y'C~b~C~r~` | Y’CbCr

Using a backslash to escape the apostrophe works in body text, but not places such as section titles, captions, and link text. When prime symbols are needed, use the Unicode ``prime'' symbol. Several predefined asciidoc attributes are available to help with this, including symbols for Y′CBCR and R′G′B′ because they are frequently used in the specification.

Table 7. Prime Attributes (correct)
Markup | Output
--- | ---
`{prime}` | ′
`{YCbCr}` | Y′CBCR
`{RGBprime}` | R′G′B′

##### Other Markup

Uses of standard Asciidoc markup are less common. Occasional asterisk markup is used for emphasis. Underscores are used for glossary terms. Backtick markup is used for the C `NULL` macro.

Example Markup

    *emphasis*
    `NULL`

##### Glossary Terms

Glossary terms are currently marked up using underscore markup where they are defined in the documents, as well as being added to the formal Glossary appendix in the Vulkan API Specification. However, we will probably change to using custom macros soon, to enable linkage between the glossary and definitions in the specification body.

Example Markup

    _Glossary terms_

#### 4.6.2. Normative Terminology

Normative terminology is precisely defined in section 1.3 of the Vulkan API Specification, and is used to visually tag terms which express mandatory and optional behavior of Vulkan implementations, and of applications using Vulkan.

Whenever one of these terms appears in the Vulkan API Specification outside of an informative section, it must be tagged using the macros, to indicate that its use has been carefully considered and is consistent with the definitions in section 1.3. This is extremely important for determining IP that is in and out of Scope during Ratification reviews. The normative terminology macros are defined in the following table:

Table 8. Normative Terminology Macros
Macro Name | Output
--- | ---
can: | can
cannot: | cannot
may: | may
may: not | may not
must: | must
must: not | must not
optional: | optional
optionally: | optionally
required: | required
should: | should
should: not | should not

Note that the macros are lower-case only, so language should be written such that these terms do not appear at the beginning of a sentence (if really necessary, additional capitalized macros could be added).

##### Optional Behavior

If a described behavior of the implementation is not necessary for conformance, use the terms may:, optional:, or optionally: to describe it.

If a described usage pattern by the application is allowed but not necessary, use the term can: to describe it.

If language flows more logically using the term “may not”, use the term may: not to describe it.

##### Optional Functionality

If functionality (rather than behavior) is optional, it should be described as

Example Markup

    not required:

Implementations are not mandated to support functionality which is not required, but if they do, they must behave as described by the Vulkan API Specification. The term functionality includes API features, extensions, and layers.

### 4.7. Informative, Editing, and Implementor’s Notes

There are several possible types of notes. Depending on the type of output, they are rendered in different styles, but always include a note title, and are usually set off in a box or with an icon. While asciidoc supports a wide set of admonition paragraphs such as TIP, IMPORTANT, WARNING, and CAUTION, we always use the NOTE form, augmented by a note title. Each type of note is discussed below.

#### 4.7.1. Informative Sections and Notes

If an entire chapter or section is considered informative, its title should be suffixed with “(Informative)”. Additionally, the chapter or section text may begin with the sentence:

Example Markup

    == Explanatory Section (Informative)

    This chapter/section is Informative.

Informative notes always appear as part of the document, but are considered non-normative. They usually describe usage advice for applications, and are always given the title Note, as in the following example:

Note | As of July 2024, we no longer use the `.Note` title on NOTE blocks.

Example Markup

    [NOTE]
    ====
    As of July 2024, we no longer use the `.Note` title on NOTE blocks.
    ====

It is not necessary to include the text “Informative” in the body of the note.

#### 4.7.2. Editing Notes

Note | Editing Notes are now rarely used in the Specification markup. Instead, file a gitlab or GitHub issue.

Editing notes usually only appear in internal (non-published) versions of documents, via asciidoc conditionals. If they are internal issues that should not be visible in public, file a gitlab issue instead. They usually tag places where an outstanding gitlab or GitHub issue is being worked, and are always given the title editing-note, as in the following example:

Note | editing-note This is an editing note, marked up as follows:

Example Markup

    ifdef::editing-notes[]
    [NOTE]
    .editing-note
    ====
    Contents of an editing note go here.
    It is good practice to include a gitlab or GitHub issue number, or link to
    the issue, in the editing note.
    ====
    endif::editing-notes[]

#### 4.7.3. Implementor’s Notes

Implementor’s notes may or may not appear in published versions of documents, via asciidoc conditionals. They describe suggested approaches or guidelines for people writing Vulkan implementations, and are rare because the hardware being targeted varies so widely. They are always given the title Implementor’s Note, as in the following example:

Example 1. Implementor’s Note

This is an implementor’s note, marked up as follows:

Example Markup

    ifdef::implementation-guide[]
    .Implementor's Note
    ====
    Contents of an implementor's note go here.
    ====
    endif::implementation-guide[]

### 4.8. Word Choices

There are a variety of common terms that have several equivalent word choices. Always use the words or phrases in the first column instead of the alternate terms, unless an exception described in the comments applies, or referring to a concept from an external API which is specifically named using an alternate term.

This list is not comprehensive; when in doubt, be guided by the existing Vulkan API Specification.

Table 9. Word Choices
Use This | Instead Of | Comments
--- | --- | ---
allocate | create | When describing objects or memory resulting from `vkAllocate*` commands.
application | client / user | Except when describing one of: Callback “user data” “client APIs” Input from, output to, or display to an actual user Shader “user-defined variables” Window system clients as described for Wayland, Xlib, and other external software
begins / begun | starts / started | For `vkBegin*` - also see “finish”
finishes / finished | ends / ended | For `vkEnd*` - also see “begins”
bitmask | bit field | Technically correct. Vulkan bitmasks are just integers and are not logically addressable at the bit level.
bound | currently bound | Appears primarily in valid usage statements, which are always referring to the current state of the objects they are validating. Rare exceptions may be justified in other cases.
called in a command buffer | called on a command buffer | Technically correct.
command | entry point, function | Except when talking about shader entry points, or function pointers returned by `vkGet*ProcAddr` commands.
component | channel | Specifically this refers to color channels/components
create | allocate | When describing objects resulting from `vkCreate*` commands.
depth/stencil | packed (interleaved, combined, other prefix) depth/stencil, depth-stencil, DepthStencil, etc. | Combined format implicit in the name.
device | GPU / processor / accelerator | The Vulkan specification is functional and could be implemented in many different ways.
dispatching command, drawing command | dispatch command, draw command | Glossary usage
display used to optimize the content | mastering display |
executable memory, executable state, pipeline executable | executable | Disambiguation
host | CPU |
host endianness | platform endianness |
image subresource | subresource | Except when referring to host-accessible subresources
implementation | system / hardware / software | For consistency, and avoids implied requirements.
indices | indexes | More common
regardless of | indifferent of |
handle is not dlink:VK_NULL_HANDLE | handle is a valid structure |
member | field |
`enumerant` specifies | `enumerant` indicates (denotes) | When giving a brief description of enums in an enumerated type. It is often appropriate to use “enumerant is” when describing the behavior or meaning of enumerants in other places.
verb on the device | verb in the device | Such as “enabled on” or “executed on”
`parameter` are/is | `parameter` specifies (denotes, indicates) | In cases when are or is are not grammatically appropriate, specifies may be used instead.
`parameter` is | the value of `parameter` is | In rare cases, the value of is appropriate. See the existing specification language for examples.
`parameter` is a typename containing / controlling / defining / describing / specifying / etc. | `parameter` is a typename that/which contains (controls, defines, describes, specifies, etc.) | Commonly used for more nuanced descriptions of parameters or structure members
If the featureName feature is enabled / is not enabled | If featureName is enabled / is not enabled / is disabled | For consistency, and to make clear that the internal link to a feature description does in fact refer to a feature name, which is not obvious otherwise.
used | referenced | When describing attachments specified in a subpass description.
statically used | referenced | When describing resources or push constants accessed by shader code
nothing | or the equivalent | When describing promoted or aliased APIs. Similar phrasing is now generated by scripts.
a more specific term | referenced | For all other situations.

Note | The “begin/start” and “end/finish” distinction is still being sorted out. See gitlab issue #61. Some word choices which are always used in the Specification are captured in the `config/CI/codespell-vulkan` custom dictionary used in the `check-spelling` build target. Terms in the list above cannot be tested by that target because their use is context-dependent, or they are multiword terms which are not testable by the spell-checking tool. Some terms above are instead checked by the `check-writing` build target.

#### 4.8.1. Avoid Abbreviations and Contractions

Abbreviations and contractions make the specification sound less formal. Avoid using them in specification text. The following lists provides some guidance, but are not complete.

Table 10. Word Choices (Contractions)
Use This | Instead Of
--- | ---
are not | aren’t
cannot: | can’t
does not | doesn’t
do not | don’t
has not | hasn’t
is not | isn’t
it is | it’s
should not | shouldn’t
that is | that’s
there is | there’s
we are | we’re
we will | we’ll
we would | we’d
what is | what’s
will not | won’t
would not | wouldn’t

Table 11. Word Choices (Abbreviations)
Use This | Instead Of
--- | ---
information | info
specification | spec

Note | Avoid using abbreviations in specification text describing the API, even though there are certain approved abbreviations used in the names of API entities such as commands, structures, and enumerants.

#### 4.8.2. Terms to Use With Caution

The term subset is sometimes used to refer to a strict subset, and sometimes used to refer to a subset which may be equal to the entire set. This is particularly likely to come up when describing bitmasks. Make sure to use either subset or strict subset as appropriate.

#### 4.8.3. Terms to Avoid

Do not describe anything in the documentation using vague or wishy-washy terms. Our goal is to precisely describe behavior of implementations.

The normative terms may:, optional:, and should: are available when implementations may make choices of behavior, but when such choices are allowed, each choice still must have well-defined behavior.

Table 12. Terms to Avoid
Bad Term | Comments
--- | ---
expect | And variants such as expected
likely | And variants such as will likely
allowed, could, generally, might, probably, perhaps | And all other such terms of choice. Use may: or can: depending on the context.
may: or may: not | Just use may:.

## 5. Writing Style

New specification language should, whenever possible, closely follow related examples in the existing specification documents.

Whenever possible follow existing API design patterns. Some specific patterns to follow (this list is very incomplete) include:

- Behavior of queries which return arrays of unknown length (see e.g. `vkEnumeratePhysicalDevices`).

- Behavior of creation commands which create multiple objects at once (see e.g. `vkCreateGraphicsPipelines`).

### 5.1. Miscellaneous Grammar, Spelling, and Punctuation Issues

#### 5.1.1. Use the Oxford Comma (Serial Comma)

When writing a sentence listing a series of items, include a comma before the “and” or “or” separating the last item.

Correct: The red, green, blue, and alpha components.

Incorrect: The red, green, blue and alpha components.

#### 5.1.2. Use AP Title Case for Chapter and Section Titles

Here is a summary of the rules:

- Capitalize the first word and the last word of the title.

- Capitalize the principal words.

- Capitalize “to” in infinitives.

- Capitalize all words of four letters or more.

- Do not capitalize articles, conjunctions, and prepositions of three letters or fewer.

Note | The actual AP style guide is behind a paywall. The summary here is from a commercial website.

#### 5.1.3. Use the Active Voice

The passive voice is often imprecise.

There are too many examples to exhaustively list them. Some that have come up include:

- “Applications should” instead of “It is recommended that”

- “To create a command buffer, call” instead of “A command buffer is created by calling” or “The application may create a command pool by calling”

#### 5.1.4. Date Format

Whenever possible, write dates in the ISO 8601 format: YYYY-MM-DD.

If needed for consistency with existing dates, e.g. in appendix changelogs, you can also write “Month DD, YYYY” where “Month” is the English name of the month.

Never use ambiguous formats such as “09/12/16”.

Example Markup

      * 2016-09-12
      * September 12, 2016

#### 5.1.5. A/An and Markup Macros

Use “a” and “an” correctly, based on the sound of the letter beginning the following word.

It is easy to get this wrong when talking about Vulkan API names tagged with the markup macros. For example, if you wanted to say:

A VK_ERROR_DEVICE_LOST error

the correct way to mark this up in asciidoc would be:

    A ename:VK_ERROR_DEVICE_LOST error

However, on first glance at this it appears wrong, because the “word” following “a” is the macro name, “ename:”. That starts with a vowel, so the temptation is to say

    An ename:VK_ERROR_DEVICE_LOST error may occur.

What matters here is how the output document is formatted.

#### 5.1.6. Numbers in Text

When describing the need for a small number of objects, smaller than ten, spell the number out (e.g. “one”). If you are describing a literal value that is a small number, you may use a numeric value (e.g. “1”).

For example, instead of writing that a bitmask “contains 1 or more bits”, write that it “contains one or more bits”. A counter example is that it is okay to write “For non-stereoscopic-3D applications, this value is 1.”

#### 5.1.7. Use American Spelling Conventions

In case of conflict, use American rather than British spelling conventions, except for noted exceptions in the table below.

Table 13. Spelling
Use Spelling | Instead Of | Comments
--- | --- | ---
tessellation | tesselation | Historical exception

Note | American spelling is enforced in CI and the `check-spelling` Makefile target by the `codespell` builtin dictionary `en-GB_to_en-US`. If any exceptions to the dictionary are needed, they can be added in `config/CI/codespell-allowed`. If specific files need to be excluded, they can be added to the `skip` entry in `config/CI/codespellrc`. There are a few exceptions to `color` in the Vulkan Video extensions, such as `VK_VIDEO_ENCODE_H264_CAPABILITY_SEPARATE_COLOUR_PLANE_BIT_EXT`. This is because those extensions refer to externally defined video compression standards and headers using that spelling.

#### 5.1.8. Use Inclusive Language

The Vulkan Working Group has begun to apply the Khronos Inclusive Language list to our specifications and other documents. The Khronos Inclusive Language list contains terms to avoid due to their use in discriminatory contexts that make people uncomfortable, or cause division.

We are working through the Vulkan Specification repository to make appropriate changes, and enhancing the repository continuous integration scripts to report questionable terminology usage. This process will take some time.

If use of a term on the list is absolutely unavoidable the CI script check can be bypassed by inserting a “word joiner” character into the markup of that term. Rendered HTML output will show this term as a single word and can be searched as such.

Asciidoctor predefines the attribute `⁠` for this purpose:

Example Markup

    The external DRM API supported by the VK_EXT_acquire_drm_display
    extension uses the term "`DRM mast{wj}er` permissions".

Some files in the repository are incorporated unmodified from external projects we do not control, and which may not comply with the Inclusive Language list. We will ask those projects to update their terminology usage, but cannot control their choices.

#### 5.1.9. Avoid Use of “set to” Where Possible

When describing a parameter or member that is required to be, or not to be a specific value, avoid extraneous use of “set to”. In particular, when constraining a value passed or returned to the API write “`value` must be zero” (or other simple scalar value) instead of “`value` must be set to zero”.

However, in more complicated sentences with multiple clauses and values described, “set to” sometimes makes language flow more naturally.

#### 5.1.10. Describing Pointers, Handles, Structures, and Arrays

When describing pointer parameters or members, use “is a pointer to” rather than more informal phrasing such as “points to”.

When describing individual structures, use “VkStructname structure” rather than longer phrasing such as “instance of the VkStructname structure” or “structure of type VkStructname”.

When describing array parameters or members, use “is a pointer to an array of” rather than “is an array of” unless it is a structure member that is a fixed-size array. Reference the dynamic size of the array that is pointed to (usually another structure member), or the static size for fixed-size arrays, in the description.

When describing pointers which may be `NULL`, use “is `NULL` or a pointer to” rather than “is an optional pointer”. The same principle applies when describing a handle which may be `VK_NULL_HANDLE`. “Optional pointer/handle” are not well-defined terms in the Specification.

Example Markup

      * pname:pInfo is a pointer to a slink:VkDebugUtilsLabelEXT structure
        specifying the parameters of the label to insert.
      * pname:pBindInfos is a pointer to an array of pname:bindInfoCount
        slink:VkBindBufferMemoryInfo structures describing buffers and memory to
        bind.
      * pname:pStrides is `NULL` or a pointer to an array
        of buffer strides.
      * pname:image is dlink:VK_NULL_HANDLE or a handle of an image which this
        memory will be bound to.

#### 5.1.11. Describing Properties of Array Elements

Many Vulkan parameters are arrays, or pointers to arrays. When describing array elements, use the terminology “each element” when the description applies uniformly and independently to every element of the array. For example:

Example Markup

      * Each element of the pname:pCommandBuffers member of each element of
        pname:pSubmits must: be in the <<commandbuffers-lifecycle, pending or
        executable state>>.

Use the terminology “any element” when the description is of zero or more elements of the array sharing a property. For example:

Example Markup

      * If any element of the pname:pCommandBuffers member of any element
        of pname:pSubmits was not recorded with the
        ename:VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, it must: not be in
        the <<commandbuffers-lifecycle, pending state>>.

Never use the redundant terminology “any given element”.

#### 5.1.12. Compound Words and Preferred Orthography

Unless there is longstanding precedent in computer science literature, or the word is a noted exception, do not arbitrarily combine terms together with hyphens, or as a single compound word without hyphens.

This does not apply to parameter names in the API, where capitalization is used to distinguish words. For example, it is proper to refer to the use of a `colorSpace` member of a structure as a “color space” value.

Table 14. Spelling
Use Spelling | Instead Of | Comments
--- | --- | ---
bit plane | bit⁠plane |
compile time | compile-⁠time | Per Wikipedia “compile time”
closest hit | closest-⁠hit |
color space | color⁠space | Not currently checked due to API naming conventions
cube map | cube⁠map |
double-buffer | double⁠buffer |
entry point | entry-⁠point, entry⁠point | Except if needed to disambiguate from surrounding terms
flat shading | flat⁠shading |
GitHub | Git⁠hub | Site’s preferred spelling
indirect (drawing/dispatching) command | indirect command (draw/dispatch) | Even though related commands are named `vk*Draw*Indirect`
LOD | lo⁠d, level of detail, level-⁠of-detail | Acronym for “Level of Detail”
mip level mip layer mip size mip tail | mip⁠level mip⁠layer mip⁠size mip⁠tail | “mipmap term” may be used in time mip⁠level is not currently checked due to API naming conventions
ray tracing | ray⁠tracing |
render pass | render⁠pass | Not currently checked due to API naming conventions
reuse | re-⁠use |
runtime | run time, run-⁠time | Arbitrary choice for consistency
side effect | side-⁠effect |
use case | use-⁠case |

Table 15. Spelling Exceptions
Use Spelling | Instead Of | Comments
--- | --- | ---
floating-point | floating point |
general-purpose | general purpose | When used as an adjective
happen-before happen-after | happen before happen after | As used in concurrent languages such as C++11, Java, and OpenCL C.
implementation-dependent | implementation dependent | When used as an adjective
mipmap | mip map | Exception for historical reasons
`pNext` chain | `pNext`-chain, `pNext` extension chain |
swapchain | swap chain | Exception due to heavy use in WSI extensions

Note | These examples are not complete, and will be added to over time when there is reason to. Different sources and individuals can and do reasonably disagree with regard to some of the examples.

##### Words With "Pre-" Prefixes

When using the prefix “pre” to indicate “prior to”, such as in the words “preinitialized”, “preprocess”, and “pretransform”, do not separate the prefix from the word with a hyphen. This list is not intended to be complete.

#### 5.1.13. References

When citing external references, use the appropriate Association for Computing Machinery Citation Style. Most citations in our specifications should follow the For an online document/WWW resource style, using the actual date on the document being referenced rather than the document retrieval date. See the Vulkan API Specification citation in this document for an example.

### 5.2. Describing Undefined Behavior

When describing undefined behavior that results only in the values of specified variables, or the contents of specified memory, becoming undefined or implementation-defined, use the undefined: macro to indicate that each use of the term “undefined” has been carefully considered and accurately represents the degree of undefined behavior allowed.

The word “undefined” should not be used without the trailing :. This is enforced by internal CI tests.

The undefined: macro does not result in visible markup in the output document, and is not itself a normative term. The macro is simply markup to help ensure that use of the word has been consciously chosen.

When describing more general types of undefined behavior (up to and including termination of the application), do not use the term “undefined”. Instead, specify that the application must: not create circumstances that would lead to such behavior. Such statements should be written as valid usage statements, if possible.

### 5.3. Describing Commands and Parameters

The Vulkan API Specification describes API commands followed by descriptions of their parameters, which are usually simple scalar types; handles or pointers to Vulkan objects or arrays of objects; enumerated types specifying values; bitmasks which affect the operation of a command; or structures containing combinations of scalar types and objects. The templates and examples shown and annotated here are based on the Vulkan API Specification. Do not vary from them without compelling need.

Normative parts of the Vulkan API Specification should describe what something does, rather than how or why an application would want to use it.

When explicitly allowed by the Specification, the reserved value `NULL` may be used for pointer parameters and members and dispatchable object handles, and the reserved value `VK_NULL_HANDLE` may be used for non-dispatchable Vulkan object handle parameters and members. Otherwise, pointers and handles must refer to valid memory and valid Vulkan objects, respectively.

Note | Guideline As a simple example, say “To create a command pool, call `vkCreateCommandPool`” rather than “You/The application can create a command pool by calling `vkCreateCommandPool`”.

Explanations of why and how should largely be confined to reference documentation, sample code, tutorials, and other such documents. Occasional non-normative explanations can be included in the Vulkan API Specification using informative notes.

#### 5.3.1. Commands Which Return Error Codes

Commands which return VkResult values must list all possible error codes for the command in the `errorcodes` XML attribute for the command. Almost all such commands may return the VK_ERROR_OUT_OF_HOST_MEMORY error code. Any exceptions to this rule should be carefully considered by the specification author, and a rationale for this anomalous behavior may be provided in a NOTE or in the Issues section of the extension appendix corresponding to the new command.

See the “Return Codes” section of the Vulkan API Specification for additional information.

### 5.4. Extensions and Grouping Related Language

Language specifying behavior of a command or structure that does not originate in an extension should be placed in a single contiguous region of the specification.

When defining a new command or structure from an extension that introduces additional behavior or options, do not insert such new language in a way that “orphans” part of an existing description by splitting up the existing language.

This constraint does not apply to enumerated types. Language for new enumerants defined by extensions should be added to the existing enumerant definition, protected by asciidoc conditionals for the new extension.

Note | Guideline Specification language should be structured, whenever possible, so it fits into a single open block defining a reference page.

### 5.5. Math Markup

There is a considerable amount of math in the documentation, ranging from simple arithmetic expressions to complicated conditionals. There are two ways of marking up math expressions, described below.

#### 5.5.1. Asciidoc Math Markup

Where possible, math is marked up using straight asciidoc features. For commonality with LaTeX math (see below), some common LaTeX operators and names are defined as asciidoc attributes using the same names, expanding to the corresponding Unicode entities. The complete set of these attributes is found in `config/attribs.adoc`.

Table 16. Spelling
Feature | Result | Sample Markup
--- | --- | ---
Subscripts | ax | [eq]#a~x~#
Superscripts | -2(b-1) | [eq]#-2^(b-1)^#
Struct/parameter names as variables | 2`bits` | [eq]#2^pname:bits^#
Greek Letters (selected) | α, β, γ, δ, Δ, ε, λ, ρ, τ | [eq]#{alpha}, {beta}, {gamma}, {delta}, {DeltaUpper}, {epsilon}, {lambda}, {rho}, {tau}#
Fractions | ¼ + ½ | [eq]#{onequarter} {plus} {onehalf}#
Closed Ranges | [0,1] | [eq]#[0,1]#
Open Ranges | [0,1) | [eq]#[0,1)#
Arithmetic and Relational Operators | a × b, a ≤ b, a ≠ b, a ≥ b, |x| | [eq]#a {times} b#, [eq]#a {leq} b#, [eq]#a {neq} b#, [eq]#a {geq} b#, [eq]#{vert}x{vert}#
Floor | ⌊w - ½⌋ | [eq]#{lfloor}w - {onehalf}{rfloor}#
Ceiling | ⌈log2(max(`width`, `height`))⌉ + 1 | [eq]#{lceil}log~2~(max(pname:width, pname:height)){rceil} {plus} 1#
Logical and Set Operators | ∧ ¬ ∨ ⊕ ∈ | [eq]#{land} {lnot} {lor} {oplus} {elem}#
Partial Derivatives | ∂rx / ∂x = 0 | [eq]#{partial}r~x~ / {partial}x = 0#
Matrix/Vector Parameter Names | P = t P1 + (1-t) P2 | [eq]#**P** = t **P**~1~ {plus} (1-t) **P**~2~#

#### 5.5.2. LaTeX Math Markup

Math markup more complex than easily supported in straight asciidoc markup (examples found in the Vulkan Specification include matrices, tensors, summation notation, conditional assignments, and division of complex expressions) is marked up using LaTeX math notation, which is either passed through to the KaTeX in-browser rendering script for HTML outputs, or passed through asciidoctor-mathematical for PDF outputs.

Note | There are font and style differences between LaTeX and asciidoc math markup which lead to minor visual inconsistencies. We will try to make this better over time, but it is not significant enough to be a big priority.

While LaTeX math macros, including the amsmath package, are supported, general LaTeX constructs are not.

Inline math is encoded using the latexmath: macro. For example:

- [0, 1]

- x−1 1−2 x​​

- c=tc 1​+(1−t)c 2​.

Example Markup

      * latexmath:[[0,1\]]
      * latexmath:[\frac{1 - \frac{x}{2}}{x - 1}]
      * latexmath:[\mathbf{c} = t \mathbf{c}_1 + (1-t) \mathbf{c}_2. ]

Note the escaped bracket in markup for the first expression, which is necessary to work around asciidoc macro parsing.

Block math is used for more complex equations. This example uses the `aligned` environment to delimit the expression.

c RGB​​={12.92 c s RGB​​(1.055 c s RGB​+0.055​)2.4​for c s RGB​≤0.04045 for c s RGB​>0.04045​​
Example Markup

    [latexmath]
    ++++
    \begin{aligned}
    c_{RGB} & =
      \begin{cases}
        \frac{c_{sRGB}}{12.92}                              & \text{for}\  c_{sRGB} \leq 0.04045 \\
        \left ( \frac{c_{sRGB}+0.055}{1.055} \right )^{2.4} & \text{for}\  c_{sRGB} > 0.04045
      \end{cases}
    \end{aligned}
    ++++

Note | The KaTeX processor used to render LaTeX math inside HTML documents does not support all features of LaTeX math. Similarly, the asciidoctor-mathematical processor does not support everything, though does have some support for AMSMath. Some workarounds we use are:
Table 17. LaTeX Math Replacements for KaTeX Compatibility
Replace | With | Comments
--- | --- | ---
`\begin{equation}`, `\end{equation}` | nothing | Unnecessary in blocks. Should not be used for inline.
`\operatorname{foo}` | `\mathbin{foo}` |
`{\rm A}` | `\mathrm{A}` |
`\text{for }` | `\text{for}\ ` | Text ending in spaces is unpredictable - favor escaped spaces after text
The KaTeX repository provides a list of currently supported LaTeX functionality. You can also use the live katex preview tool on the KaTeX website to double check support, without building the whole specification. Note that we use a locally-cached copy of KaTeX which may lag the latest published version on the website. As of July 2024, we are using KaTeX v0.16.10. See the mtex2MML repository for a list of supported operations in the PDF build. In particular, `\mathop` is not supported properly, but most other standard functionality is included. It is necessary to cross reference these two to make sure that support exists before using anything, but almost all standard functionality is supported for both.

This example is among the most complex expressions in the Vulkan specification:

V=⎩
⎨
⎧​(−1)S×0.0,(−1)S×2−14×2 10 M​,(−1)S×2 E−15×(1+2 10 M​),(−1)S×I n f, N a N,​E=0, M=0 E=0, M=0 0<E<31 E=31, M=0 E=31, M=0​
Example Markup

    [latexmath]
    ++++
    V =
      \begin{cases}
        (-1)^S \times 0.0,                      & E = 0, M = 0     \\
        (-1)^S \times 2^{-14} \times { M \over 2^{10} },
                                                & E = 0,  M \neq 0 \\
        (-1)^S \times 2^{E-15} \times { \left( 1 + { M \over 2^{10} } \right) },
                                                & 0 < E < 31       \\
        (-1)^S \times Inf,             & E = 31, M = 0             \\
        NaN,                           & E = 31, M \neq 0
      \end{cases}
    ++++

#### 5.5.3. LaTeX Math in Table Cells

To use `[latexmath]` or `latexmath:` constructs inside table cells, the cell separator must be `a|` instead of just `|`:

Example Markup

    .Advanced Blend Overlap Modes
    [width="80%",options="header"]
    |====
    | Overlap Mode                              | Weighting Equations
    | ename:VK_BLEND_OVERLAP_UNCORRELATED_EXT  a|
    [latexmath]
    ++++
                                                  \begin{aligned}
                                                    p_0(A_s,A_d) & = A_sA_d \\
                                                    p_1(A_s,A_d) & = A_s(1-A_d) \\
                                                    p_2(A_s,A_d) & = A_d(1-A_s) \\
                                                  \end{aligned}
    ++++
    |====

### 5.6. Describing Extending Structure Chains

When describing an extending structure which is passed to an existing command by including it in the `pNext` chain of a structure parameter of that command, introduce the structure description in this fashion:

    When *performing an operation described by the extending structure*, add
    a slink:VkExtensionStructNameID structure to the pname:pNext chain of the
    slink:VkBaseExtensionStructName structure passed to the
    flink:vkBaseFunctionName command *saying what the extending structure
    does*.

When describing properties of a structure included in a `pNext` chain, refer to that structure as “included in the `pNext` chain” rather than “present in” or other similar terms, in this fashion:

    If the pname:pNext chain includes a slink:VkPhysicalDeviceFeatures2
    structure, then pname:pEnabledFeatures must: be `NULL`

### 5.7. Example Command, Structure, and Enumerant Descriptions

The next section is a sample based on the Vulkan API Specification, and describes a command and related structures and enumerated types in enough detail to see the different usage patterns and layout / markup used. Informative notes discussing markup and guidelines are interspersed with the example description to explain how and why it looks as it does.

### 5.8. Sample Command Description: Creating Command Pools

To create a command pool, call:

    // Provided by VK_VERSION_1_0
    VkResult vkCreateCommandPool(
        VkDevice                                    device,
        const VkCommandPoolCreateInfo*              pCreateInfo,
        const VkAllocationCallbacks*                pAllocator,
        VkCommandPool*                              pCommandPool);

Note | Guideline Begin the command description with an open block delimiting the contents as a reference page. The open block contains several required attribute values, as described for automatic extraction into a reference page. Use a short introductory sentence written in the active voice when describing commands, and follow similar existing examples. After the description, include the autogenerated prototype for the command from the `{generated}/api/protos/` directory:
    [open,refpage='vkCreateCommandPool',desc='Create a new command pool object',type='protos']
    --
    To create a command pool, call:

    include::{generated}/api/protos/vkCreateCommandPool.adoc[]
Note that each autogenerated command, enumeration, flag, or structure definition include file also defines a corresponding asciidoc anchor which is the base name of the file. In this case, the anchor is named `vkCreateCommandPool`.

- `device` is the logical device that the command pool is created on.

- `pCreateInfo` is a pointer to a VkCommandPoolCreateInfo structure specifying the state of the command pool object.

- `pAllocator` controls host memory allocation as described in the Memory Allocation chapter.

- `pCommandPool` is a pointer to a VkCommandPool handle in which the created pool is returned.

Note | Guideline Describe each command parameter in a separate bullet list item. in the same order that parameters appear in the command. Each description must begin with the parameter name. This aids in extracting short descriptions of parameters for inclusion in annotated headers and similar documentation. Make sure to tag each parameter with the pname: macro. Strive for compact notation, and in particular always try to use the phrasing “pname:param is” rather than wordier forms such as “pname:param specifies” or “The pname:param parameter specifies”. In general there is no need to describe a parameter which is a Vulkan object handle as a handle; for example, say “pname:device is the logical device” rather than “pname:device is a handle to the logical device”. An exception is object creation functions, where a pointer to a handle of the proper type is used to return the newly created object.

This is a general description of creating a command pool.

Valid Usage

- VUID-vkCreateCommandPool-queueFamilyIndex-01937
  `pCreateInfo->queueFamilyIndex` must be the index of a queue family available in the logical device `device`

Valid Usage (Implicit)

- VUID-vkCreateCommandPool-device-parameter
  `device` must be a valid VkDevice handle

- VUID-vkCreateCommandPool-pCreateInfo-parameter
  `pCreateInfo` must be a valid pointer to a valid VkCommandPoolCreateInfo structure

- VUID-vkCreateCommandPool-pAllocator-parameter
  If `pAllocator` is not `NULL`, `pAllocator` must be a valid pointer to a valid VkAllocationCallbacks structure

- VUID-vkCreateCommandPool-pCommandPool-parameter
  `pCommandPool` must be a valid pointer to a VkCommandPool handle

- VUID-vkCreateCommandPool-device-queuecount
  The device must have been created with at least `1` queue

Return Codes

Success

  - VK_SUCCESS

Failure

  - VK_ERROR_OUT_OF_DEVICE_MEMORY

  - VK_ERROR_OUT_OF_HOST_MEMORY

  - VK_ERROR_UNKNOWN

  - VK_ERROR_VALIDATION_FAILED

Note | Guideline If there is a general description of the command, add it following the parameter descriptions:
    This is a general description of creating a command pool.
If there are explicit valid usage statements for the command, add them in their own valid usage block:
    .Valid Usage
    ****
      * [[VUID-vkCreateCommandPool-queueFamilyIndex-01937]]
        pname:pCreateInfo->queueFamilyIndex must: be the index of a queue family
        available in the logical device pname:device
    ****
Although a valid usage ID is shown in the rendered example above, do not specify the ID when initially writing the statement, as described below. VUIDs are normally assigned immediately prior to publication. Some parameter and member validation language for commands and structures is implicit (autogenerated from `vk.xml`), and included from the `{generated}/validity/` directories. All Vulkan command and structure language should include the autogenerated file at the end of their descriptions. It is harmless to include a nonexistent file, in the rare cases where no implicit validity language exists.
    include::{generated}/validity/protos/vkCreateCommandPool.adoc[]
    --
Close the open block surrounding the command description after the implicit validity include. All content within the block will be extracted for the corresponding reference page. Open blocks delimiting reference page content should not themselves contain section headers, as asciidoc cannot render such nested content correctly. Reference pages should in general be relatively short, so this limitation is not severe. Structures and enumerations first introduced as parameters of a command are described next.

The `VkCommandPoolCreateInfo` structure is defined as:

    // Provided by VK_VERSION_1_0
    typedef struct VkCommandPoolCreateInfo {
        VkStructureType             sType;
        const void*                 pNext;
        VkCommandPoolCreateFlags    flags;
        uint32_t                    queueFamilyIndex;
    } VkCommandPoolCreateInfo;

Note | Guideline Begin the structure description with an open block delimiting the contents as a reference page, in the same fashion as described above for commands. The open block contains several required attribute values, as described for automatic extraction into a reference page. Use a short, active paragraph to introduce the structure, usually just “The `VkStructureName` structure is defined as:”. After the description, include the autogenerated definition for the structure from the `{generated}/api/structs/` directory:
    [open,refpage='VkCommandPoolCreateInfo',desc='Structure specifying parameters of a newly created command pool',type='structs']
    --

    The sname:VkCommandPoolCreateInfo structure is defined as:

    include::{generated}/api/structs/VkCommandPoolCreateInfo.adoc[]

- `sType` is a VkStructureType value identifying this structure.

- `pNext` is `NULL` or a pointer to a structure extending this structure.

This demonstrates how to create a continuation paragraph in a member description. This paragraph is not present in the actual specification the example is based on.

- `flags` is a bitmask of VkCommandPoolCreateFlagBits indicating usage behavior for the pool and command buffers allocated from it.

- `queueFamilyIndex` designates a queue family as described in section Queue Family Properties. All command buffers allocated from this command pool must be submitted on queues from the same queue family.

Note | Guideline Each structure member is described in a separate bullet list item. For structures with `sType` and `pNext` members, there is standard boilerplate for their descriptions. Descriptions of other members of the structure follow.
      * pname:sType is a elink:VkStructureType value identifying this structure.
      * pname:pNext is `NULL` or a pointer to a structure extending this
        structure.
    +
    --
    This demonstrates how to create a continuation paragraph in a member
    description.
    This paragraph is not present in the actual specification the example is
    based on.
    --
      * pname:flags is a bitmask of elink:VkCommandPoolCreateFlagBits indicating
        usage behavior for the pool and command buffers allocated from it.
      * pname:queueFamilyIndex designates a queue family as described in section
        <<devsandqueues-queueprops,Queue Family Properties>>.
        All command buffers allocated from this command pool must: be submitted
        on queues from the same queue family.
These entries should be short and functional, without describing details of e.g. new enumerant values, function of individual parameter settings, etc. They can refer to other types using the appropriate *link: macros or to related sections of the specification using asciidoc `xref` macros. In rare cases, a member description will cover multiple paragraphs. In these cases the normal list nesting and indentation guidelines cannot be applied due to limitations of the asciidoc parser. It is usually best to append a continuation block following the first paragraph of such a list item, as shown for `pNext` above. Add general descriptions of the structure, if any, following the member descriptions. No general description is shown in this example.

Valid Usage

- VUID-VkCommandPoolCreateInfo-flags-02860
  If the `protectedMemory` feature is not enabled, the VK_COMMAND_POOL_CREATE_PROTECTED_BIT bit of `flags` must not be set

Valid Usage (Implicit)

- VUID-VkCommandPoolCreateInfo-sType-sType
  `sType` must be VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO

- VUID-VkCommandPoolCreateInfo-pNext-pNext
  `pNext` must be `NULL` or a pointer to a valid instance of VkDataGraphProcessingEngineCreateInfoARM

- VUID-VkCommandPoolCreateInfo-sType-unique
  The `sType` value of each structure in the `pNext` chain must be unique

- VUID-VkCommandPoolCreateInfo-flags-parameter
  `flags` must be a valid combination of VkCommandPoolCreateFlagBits values

Note | Guideline Add explicit valid usage statements (if any) and the implicit autovalidity include in the same fashion as described for commands above, then close the open block.
    .Valid Usage
    ****
      * [[VUID-VkCommandPoolCreateInfo-flags-02860]]
        If the <<features-protectedMemory, pname:protectedMemory>> feature is
        not enabled, the ename:VK_COMMAND_POOL_CREATE_PROTECTED_BIT bit of
        pname:flags must: not be set
    ****

    include::{generated}/validity/structs/VkCommandPoolCreateInfo.adoc[]
    --

Bits which can be set in VkCommandPoolCreateInfo::`flags` to specify usage behavior for a command pool are:

    // Provided by VK_VERSION_1_0
    typedef enum VkCommandPoolCreateFlagBits {
        VK_COMMAND_POOL_CREATE_TRANSIENT_BIT = 0x00000001,
        VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT = 0x00000002,
      // Provided by VK_VERSION_1_1
        VK_COMMAND_POOL_CREATE_PROTECTED_BIT = 0x00000004,
    } VkCommandPoolCreateFlagBits;

Note | Guideline Begin an enumerated type description with an open block delimiting the contents as a reference page, in the same fashion as described above for commands and structures. Use boilerplate language similar to that above to introduce the type.
    [open,refpage='VkCommandPoolCreateFlagBits',desc='Bitmask specifying usage behavior for a command pool',type='enums']
    --
    Bits which can: be set in slink:VkCommandPoolCreateInfo::pname:flags to
    specify usage behavior for a command pool are:

    include::{generated}/api/enums/VkCommandPoolCreateFlagBits.adoc[]

- VK_COMMAND_POOL_CREATE_TRANSIENT_BIT specifies that command buffers allocated from the pool will be short-lived, meaning that they will be reset or freed in a relatively short timeframe. This flag may be used by the implementation to control memory allocation behavior within the pool.

- VK_COMMAND_POOL_CREATE_PROTECTED_BIT specifies that command buffers allocated from the pool are protected command buffers.

Note | Guideline Each enumerant in the enumerated type is described in a separate bullet list item. Make sure to protect enumerants added to the type by extensions or future core versions with asciidoc conditionals. Close the open block after all enumerants are described.
      * ename:VK_COMMAND_POOL_CREATE_TRANSIENT_BIT specifies that command
        buffers allocated from the pool will be short-lived, meaning that they
        will be reset or freed in a relatively short timeframe.
        This flag may: be used by the implementation to control memory
        allocation behavior within the pool.
    ifdef::VK_VERSION_1_1[]
      * ename:VK_COMMAND_POOL_CREATE_PROTECTED_BIT specifies that command
        buffers allocated from the pool are protected command buffers.
    endif::VK_VERSION_1_1[]
    --

### 5.9. Writing Explicit Valid Usage Statements

Explicit valid usage statements must be written at a point that all information needed to evaluate them is known. In particular, if validity of structure parameters depends on other parameters of a command that structure is passed to, such valid usage statements must be written for the command, rather than the structure.

Each explicit valid usage statement should be a single, self-contained assertion, possibly involving multiple subexpressions or parameters. For example, instead of writing “width, height, and depth must all be greater than zero”, write each condition as a separate statement. In contrast, “width × height must be less than 1024” is a single assertion involving multiple parameters.

Do not use “unless” to call out exceptions - always write valid usage statements of the form “if A then B”. This may result in harder to read statements in a few cases, but maintains consistency. In many cases, it may lead to a simpler VU statement, or splitting one large VU into multiple new ones.

Be clear on the distinction between a “valid pointer” and a “pointer to a valid object” when writing valid usage statements. See the “Valid Usage” section of the Vulkan Specification, and particularly the “Valid Usage for Pointers” section.

When a valid usage statement must apply independently to every element of an array parameter or member, write it starting with “For each element” instead of “For any element”.

A valid usage statement may used nested bullet lists or other asciidoc markup.

When clauses in valid usage statements apply only when specific extensions and/or core API versions are enabled at runtime, use appropriate asciidoc conditionals around such clauses.

Note | Prior to specification update 1.3.255, there were stronger restrictions on placement of asciidoc conditionals that have been relaxed, allowing writing such valid usage statements in a more natural manner and with less duplication of language.

Explicit valid usage statements must be assigned Valid Usage ID tags before publication. This process is described in the Valid Usage ID Tags appendix, but is normally performed only when preparing to integrate functionality into the Vulkan Specification prior to publication. It is something authors of new functionality should be aware of, but are not themselves responsible for. For example, when writing the explicit vkCreateCommandPool::`queueFamilyIndex` valid usage statement shown above, the tag

    [[VUID-vkCreateCommandPool-queueFamilyIndex-01937]]

was inserted by a script, not the original author.

### 5.10. Writing Common Explicit Valid Usage Statements

If the same set of valid usage statements are going to be common to multiple commands or structures, these should be extracted into a separate file under `chapters/commonvalidity/`. The file name should be short but to the point (e.g. `draw_common.adoc`), and then the file can be included in the relevant API features using standard include syntax:

    .Valid Usage
    ****
    include::{chapters}/commonvalidity/draw_common.adoc[]
    include::{chapters}/commonvalidity/draw_vertex_binding.adoc[]
      * [[VUID-vkCmdDrawIndirectByteCountEXT-transformFeedback-02287]]
        sname:VkPhysicalDeviceTransformFeedbackFeaturesEXT::pname:transformFeedback
        must: be enabled
    ****

Common VU includes should appear before individual VUs for consistency.

The file itself should be structured with the comment `// Common Valid Usage` used as a delimiter at the start and end of the file, with a comment describing in more detail where these are included, and then the valid usage statement bullets outside of a valid usage block. For example:

    // Common Valid Usage
    // Common to drawing commands that consume vertex binding state
      * All vertex input bindings accessed via vertex input variables declared
        in the vertex shader entry point's interface must: have valid buffers
        bound
      * For a given vertex buffer binding, any attribute data fetched must: be
        entirely contained within the corresponding vertex buffer binding, as
        described in <<fxvertex-input>>
    // Common Valid Usage

Finally, the original feature section needs to define the `:refpage:` attribute to match the name of the feature, as this is used to correctly generate links to expanded common valid usage statements in the built specification.

    [open,refpage='vkCmdDrawIndirectByteCountEXT',desc='Draw primitives where the vertex count is derived from the counter byte value in the counter buffer',type='protos']
    --
    :refpage: vkCmdDrawIndirectByteCountEXT

In general, this methodology should be preferred over any other method of consolidation - e.g. calling out a block of common valid usage statements, or referencing the valid usage statements of another command. However, for cases where the boilerplate of setting this up creates more text than a simple copy paste (e.g. only two commands consume a single valid usage statement), the original VUs can be left intact.

### 5.11. Markup for Empty Enumerated Types

Sometimes an enumerated type has all values defined by extensions, and each enumerated value defined by the type will be surrounded by an asciidoc conditional for the corresponding extension. When a specification is built without any of those extensions enabled, the type should still be included, even though it is empty. In this case, the enumerated value descriptions must be followed by one additional conditional section which is only included when none of the relevant extensions are enabled.

For example, the relevant part of the VkDescriptorSetLayoutCreateFlagBits description, whose only value is defined by an extension, will look like this:

    include::{generated}/api/enums/VkDescriptorSetLayoutCreateFlagBits.adoc[]

    ifdef::VK_KHR_push_descriptor[]
      * ename:VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR specifies
        that descriptor sets must: not be allocated using this layout, and
        descriptors are instead pushed by flink:vkCmdPushDescriptorSetKHR.
    endif::VK_KHR_push_descriptor[]

    ifndef::VK_KHR_push_descriptor[]
    [NOTE]
    ====
    All bits for this type are defined by extensions, and none of those
    extensions are enabled in this build of the specification.
    ====
    endif::VK_KHR_push_descriptor[]

### 5.12. Markup for Automatic Reference Page Extraction

The Vulkan reference pages are (mostly) extracted from corresponding sections of the API Specification. This requires that the markup and writing conventions described above be adhered to rigidly.

The extraction scripts for a given page rely on the existence of an asciidoc `open` block surrounding markup describing that page, with attributes used to specify properties of the reference page. Additional heuristics and non-asciidoc tags, described below, are used to identify subsections of a reference page in some cases.

In general the open block introduction will look like:

    [open,refpage='name',desc='short description',type='pagetype',alias='alias',anchor='anchor',xrefs='xrefs']
    --

Attributes which can be set on the block are:

- refpage - the name of the reference page, e.g. the Vulkan interface (command, structure, enumerant, handle, etc.) name. This attribute is required.

- desc - short description / summary of the page, used in the page title. This attribute is required.

- type - type of the interface, which must match the directory name following `api/` in the interface `include::` line within the block, and must be one of `basetypes`, `defines`, `enums`, `flags`, `funcpointers`, `handles`, `protos`, or `structs`; or the non-API block types `feature`, `freeform`. or `spirv`. This attribute is required.

- alias - list of whitespace-separated names of other pages which this page also describes. Used to generate redirections so that multiple names can refer to the same page. This is rarely used, and only for non-API pages. API aliases are also redirected, but are derived from the XML during reference page generation. This attribute is optional.

- anchor - anchor name at which this reference page is fully described in the API specification document. This attribute is optional except for the non-API block types, which do not correspond to Vulkan APIs.

- xrefs - list of whitespace-separated names of other reference pages which should be added to the `See Also` section of this page. Most cross-references are automatically generated based on the immediate dependency information in `vk.xml`. In some cases, such as referring between `*FlagBits` and `*Flags` types, this additional tagging is useful. This attribute is optional.

Attributes of the open block must be written in this format, using single quotes as delimiters (even though asciidoc markup also allows double quotes), and escape single quotes in e.g. the desc attribute value with backquotes.

After the open block is started, the following markup should be provided:

- A single paragraph of text describing the definition of the interface. This paragraph is optional, but strongly recommended.

- The `include` line for the interface, which must be consistent with the page name and type in the open block attributes. This paragraph is required.

- A bullet list describing function parameters, structure members, enumerants in an enumerated type, etc. This list should contain no empty lines, as the extraction script classifies the uninterrupted block of text following the `include` directive as the `Parameters` or `Members` section of the ref page. This list is required, unless the interface has nothing to describe, such as an empty structure or enumeration, or a function with no parameters.

- Paragraphs of text making up the `Description` section of the ref page. This section is optional. If it is necessary due to constraints of asciidoc markup to have an empty line in the bullet list section, add a `// refBody` comment immediately following the bullet list and preceding this section:

      // refBody

  There are no examples of this usage in the current Vulkan Specification, but it has been needed in the past and may again in the future.

- An explicit valid usage block. This block is required if the interface has such valid usage constraints.

- The `include` line for the implicit valid usage block. This line is required for commands and structures, but not for interfaces such as enumerated types, which do not have implicit valid usage blocks.

- Finally, a two-dash asciidoc delimiter closing the open block:

      --

All elements specifying an interface name (open block `refpage` attributes, interface `include` lines, and validity `include` lines) must use the same interface name, if present. Otherwise the extraction script is either unable to extract that page, or will extract the wrong text - and the language will be structurally incorrect, as well. The extraction process is somewhat fragile, so care should be taken and the results of reference page extraction verified after making changes to that portion of the specification source.

Content that should only appear in reference pages, such as developer-oriented guidelines for reference pages describing extensions, may be conditionally included in the specification as follows:

    ifdef::isrefpage[]

    === Refpage-Only Section

    *This section will appear only when generating an extension refpage,
    but not in the specification extensions appendix.*

    endif::isrefpage[]

## 6. Image Authoring, Formats, and Style

Images used in the Vulkan documents must be kept in the directory `images/` in SVG format.

Images should be authored in the open-source `Inkscape` tool, downloadable from its website or packaged as an optional install for most Linux distributions. This allows other people to easily edit your images in the future. Also, while SVG is in principle a portable image format, some proprietary image editors have been observed to produce images incompatible with the PDF image pipeline used by the Specification.

Images must be authored at their actual image size in the HTML and PDF output documents, and must not be scaled with asciidoc options. In most cases, images are included as standalone figures and should occupy the full width of the document - do not leave unnecessary whitespace on either side of the image.

The PDF output has an available width of just over 660px (at the default 96dpi), and a height somewhere around 1000px (which diagrams should really go nowhere near anyway). The html output is wider (800 pixels) and with practically unlimited height. As the PDF dimensions are more restrictive, images should not exceed these limits.

Note | According to the documentation available, the PDF output should have dimensions of roughly 184mm x 271mm - or equivalently 697px x 1026px (A4 size [asciidoc default] with a 0.5in margin [prawn-pdf default] on each side). However for reasons currently unknown, at least the available width before images are scaled down lies is about 30-something pixels lower than that; the height where this happens has not been measured, but is likely to similarly be lower than it should be for reasons currently unknown.

Dimensions of elements in the SVG file should be authored in pixels (`px`) such that lines/strokes are not unnecessarily anti-aliased (e.g. usually stick to integer pixel widths for lines). In many cases it is useful to also set the background grid to px, but it not necessary; Inkscape has reliable conversions between px and mm using a default dpi of 96 (which matches the PDF output), so the output dimension is mostly irrelevant.

Text in images should usually appear at 12 point type so as to match that in the body of the specification, though 10 point text can be used sparingly where necessary (however this is often indicative of the diagram being too cramped, so authors should consider scaling or reworking the diagram instead). Text should use the built-in generic sans serif font so as to ensure the font in the output document matches whatever sans serif font is used for that document. Note that the character set is currently restricted to Windows-1252.

The font and color scheme used for existing images (black, red, and 50% gray) should be used for changes and new images whenever reasonable to do so, to preserve a consistent look and feel. Whilst a white background is typically assumed, explicitly adding white as a color should be avoided - instead leave elements transparent so the diagrams can be used in other documents.

Many other elements are consistent throughout the set of diagrams which should be maintained in new diagrams where possible. Examples include:

- Lines are usually either fully solid, or use a consistent, and relatively spacious, dash style.

- Lines are capped with a consistent arrow shape where relevant.

- Small solid circles representing points are a consistently sized circle.

Whenever reasonable, it is advised to copy an existing similar diagram and edit it rather than creating one from scratch in order to reuse elements and maintain consistency.

### 6.1. Character Sets in SVG Files

At the moment, the PDF conversion path only supports the Windows-1252 character set, as we are currently using the standard fonts built into every PDF viewer - such that we do not have to embed a different font. Unfortunately these only support Windows-1252, which is a highly limited character set.

As such, characters not in that set will not display properly when present in an SVG, and will generate a warning when building the PDF. Luckily, Inkscape has an “Object to path” function built in, which will convert text to a raw path, allowing these characters to be supported.

Please ensure that you build the PDF before submitting any new images, particularly with non-standard characters, in order to catch such errors.

Note | editing-note Other Stuff Which May Be Described In This Chapter Eventually Something about Image formats Something about validation scripts Glossary lists New param/enum macros

## Appendix A: Valid Usage ID Tags

Valid usage statements in the published Vulkan Specification must all be given Valid Usage ID or VUID tags. These tags are asciidoc anchors, intended for use by the validation layer to provide unique names for each validation condition, and a way to link from validation layer reports into the corresponding parts of the Specification.

### A.1. Format of VUID Tags

For implicit valid usage statements, the tags are formatted like this:

    [[VUID-blockname-paramname-category]]

blockname is the name of the function or structure for which a valid usage statement is being generated.

paramname is the name of the parameter being validated. In some cases, the statement does not validate a single parameter and this portion of the tag is absent.

category is the type of statement being generated. There are over one dozen types referring to distinct conditions such as valid objects, required bitmasks, required array lengths, constraints on parent objects, and so on.

For explicit valid usage statements, the tags are formatted like this:

    [[VUID-blockname-paramname-number]]

blockname is the name of the function or structure for which a valid usage statement is being generated.

paramname is the name of the parameter being validated. In some cases, the statement does not validate a single parameter and this portion of the tag is replaced by `-None-`

number is a unique five digit, zero-filled number used to disambiguate similar tag names.

Note | The blockname, paramname, and category portions of a VUID tag name must each be composed only of the alphanumeric characters A-Z, a-z, and 0-9, and the ':' character. In general only the alphabetic subset of these characters is used, but there are a few exceptions.

### A.2. Creating VUID Tags

For implicit valid usage statements generated automatically from `vk.xml`, VUID tags are created automatically by the generator scripts.

For explicit valid usage statements, VUID tags are generated by passing appropriate options to the script `reflow.py`.

Since these tags are of use only to the published validation layer, they are needed only in the published Specification sources and outputs. Therefore, authors of extensions, or other branches adding valid usage statements, are not themselves responsible for adding tags in their branches. The specification editors will take care of this as part of the process of publishing updates. For reference purposes, this process is described below:

First, after integrating all new specification language into the internal gitlab default branch (currently `main`) containing the canonical Specification source, invoke the following command:

    python3 scripts/reflow.py -overwrite -noflow -tagvu chapters/*.adoc chapters/*/*.adoc

This will add VUID tags to all statements in valid usage blocks which do not already have them. Some diagnostics will be reported, but these are do not in general require any action.

After updating all files, the script will update the file `scripts/vuidCounts.py` containing reserved ranges of VUIDs for the default branch and certain other development branches.

Commit the updated source files and `vuidCounts.py` together. The next time the script is run, VUID tags will be assigned numbers starting from the next free value in the range available to default branch.

In-development Vulkan extensions are kept in their own branches, with the branch name the same as the name of the extension being developed. VUID tags may be assigned in these branches in the same fashion as in default branch. To enable this, each development branch must be assigned its own independent VUID range in the default branch copy of `vuidCounts.py`, to prevent collisions. In the event that default branch or any development branch exhausts the available VUID range, `reflow.py` will report this and stop assigning VUIDs. At that point, a new range must be assigned to the branch in the default branch copy of `vuidCounts.py`, as well as in the per-branch copy.

### A.3. Updating VUID Tags When Valid Usage Statements Change

Valid usage statements have corresponding tests in the Vulkan Validation Layer. The tests must be changed in response to semantic changes in the VU statements, whether for bug-fixing, adding extension interactions, or otherwise. The rule used when updating explicit VU statements is that the merge request or pull request responsible for making the change must remove the existing VUID tag, so that a new one can be assigned, except in the following cases:

- The changes are non-semantic, such as using consistent phrasing or markup.

- The changes consist of removing or changing extension suffixes when promoting an extension to `EXT`, `KHR`, or core status.

- The valid usage statement has not yet been implemented in the validation layers.

Note | This section may need further modification in response to guidelines agreed to by the Vulkan Working Group.

## Appendix B: Revision History

- 2026-02-18 - Disallow type names matching command parameter or structure member names (public issue 2679).

- 2026-02-03 - Expand the Tables section to require an explicit anchor (public issue 2670).

- 2026-01-05 - Recommend use of the `nextfreebits.py` script when reserving new bitmask values.

- 2025-12-09 - Update the API Versions, Extensions, and Layers section to discourage adding new markup files other than entirely new chapters or appendices (internal MR 7893).

- 2025-11-13 - Require use of “for each element” when writing explicit valid usage statements to be evaluated independent for elements of an array (internal issue 4534).

- 2025-11-06 - Add “regardless of” to the preferred Word Choices (internal MR 7799).

- 2025-11-05 - Avoid use of “or the equivalent” when describing promoted or aliased APIs in the Word Choices section, since this is now generated by scripts (internal MR 7779).

- 2025-11-05 - Update description of the reference page open block `alias` attribute in the Markup for Automatic Reference Page Extraction section, since it is no longer needed for API aliases.

- 2025-05-27 - Add a new Bitflag Names section (internal issue 4276).

- 2024-11-13 - Add a new Use the Active Voice section (internal issue 4085).

- 2024-10-28 - Add preferred phrasing for describing links to feature descriptions in the Word Choices section (internal issue 4056).

- 2024-10-14 - Add Avoid Use of “set to” Where Possible section (internal issue 3966).

- 2024-07-03 - remove `\begin{align*}` from the list of <<writing-math-latexmath, LaTeX markup that is not supported, after updating to KaTeX 0.16.10.

- 2024-07-02 - Remove redundant Common Abbreviations and Standard Prefixes content from this document, since it is now in an appendix of the API Specification.

- 2024-06-19 - Add the Directory Structure and File Names section. Use `asciidoc` consistently when referring to the markup language, and `asciidoctor` when referring to the asciidoc processing tool.

- 2024-06-12 - Specify where “client” and “user” terminology is allowed in the Word Choices section (internal issue 3898).

- 2024-06-04 - Add preferred way to write “command” instead of “entry point” (except for shaders).

- 2024-04-10 - Update the Use American Spelling Conventions section to describe how the `codespell` tool is used to enforce these guidelines (internal issue 3848).

- 2024-03-28 - Move the Writing Common Explicit Valid Usage Statements language into its own subsection, rather than as a NOTE.

- 2024-02-27 - Add a NOTE to the introduction to clarify that the custom asciidoctor macros are only available in the Specification, not related documentation (internal issue 3808).

- 2023-11-30 - Update introduction of the Writing Style chapter to recommend following existing language and API design patterms when creating new specification language (internal issue 3707).

- 2023-10-22 - Update description of `EXT` extensions, since some are now being ratified.

- 2023-10-11 - Add rules for writing chapter and section titles.

- 2023-10-05 - Mention that bit position 31 may not be used for enumerated type bitmasks, due to portability concerns.

- 2023-07-07 - Remove style guide requirement to not use nested bullet points or other complex markup in a valid usage statement, which is now allowed due to toolchain improvements.

- 2023-07-07 - Add “use case” as preferred orthography (internal merge request 5991).

- 2023-07-05 - Change the boilerplate language for `sType` to refer to `VkStructureType` (internal issue 3493).

- 2023-06-21 - Remove the style guide advice to keep valid usage statements “atomic” with respect to preprocessor directives, as a recent script and validation layer change has enabled preprocessor directives within VUs. In its place, add new advice about making sure all version and extension information is included in the text of the valid usage statement rather than relying on preprocessor directives.

- 2023-05-03 - Add preferred way to write “called in a command buffer” (internal issue 3480).

- 2023-04-30 - Update Blocks to remove tilde markup for source blocks inside refpages, and use `[open]`-tagged listing blocks for continuation blocks inside refpages instead.

- 2023-02-26 - update description of computing numeric enumerant values, and reference the normative references section for the registry schema document (public issue 2069).

- 2022-11-29 - Add a NOTE to the Use American Spelling Conventions section to explain why there are a few uses of British spelling in the Vulkan Video extensions (internal issue 3254).

- 2022-11-16 - Update `basetype` markup macro description to exclude types without definitions in the Vulkan Specification, such as the Video `Std*` types (internal issue 2703).

- 2022-11-11 - Add preferred way to write “_handle_ is not dlink:VK_NULL_HANDLE”

- 2022-10-12 - Add preferred way to write “_verb_ on the device”, and re-order part of that table (internal merge request 5475).

- 2022-09-05 - Refactor markup to separate Introduction chapter from `styleguide.adoc` and make anchor naming scheme consistent. Convert Revision History from a chapter to an appendix and add an anchor.

- 2022-07-14 - Add Feature Cross-References section specifying how to mark up API feature links.

- 2021-11-21 - Add preferred uses of “indirect (drawing/dispatching) command” to the Compound Words and Preferred Orthography section.

- 2021-11-15 - Add Include File Paths section requiring using full paths to included markup files.

- 2021-11-04 - Remove backquote markup around recommended use of the `apiext:` macro, since that macro now styles the extension name argument itself.

- 2021-10-29 - add "`render pass" to the Compound Words and Preferred Orthography section.

- 2021-10-04 - Update the Changes for New Extensions section to require use of the `apiext:` macro for links to extension names (internal issue 2831).

- 2021-09-12 - Add a new subsection with more details on using tilde-delimited source blocks inside reference page open blocks, and rewrite the Sample Command Description section to follow current phrasing and markup patterns (internal issue 2040).

- 2021-09-09 - Add the Italicized Enumerant Names section to clarify how to write wildcard enumerant names with imbedded italicized text.

- 2021-09-06 - Add the Use Inclusive Language section based on the Khronos Inclusive Language list (internal issue 2293).

- 2021-09-06 - add “cube map” to the Compound Words and Preferred Orthography section (internal merge request 4794).

- 2021-07-20 - Add additional contraction examples to the table in the Avoid Abbreviations and Contractions section.

- 2021-05-31 - Add “implementation-dependent” as an exception in the Compound Words and Preferred Orthography section (internal merge request 4611).

- 2021-05-24 - Add escapes to prevent expansion of attribute names in a few places where markup examples are given.

- 2021-05-22 - Expand the markup rules to include avoiding abbreviations, as well as contractions.

- 2021-05-07 - Add preferred way to write "`drawing/dispatching command".

- 2021-04-28 - Add disambiguations for “executable”.

- 2021-04-28 - Add usage for pointers and handles which may be `NULL` or `VK_NULL_HANDLE`, respectively (internal issue 2662).

- 2021-04-14 - Add “side effect” and “reuse” as preferred orthography (public issue 1484).

- 2021-03-31 - Update description of the code: macro in the API Markup Macros section to match current behavior.

- 2021-03-21 - Note that the [extensions-reserving-bitmask-values same bit should be reserved] for the same purpose in comparable 32- and 64-bit bitmask types (internal issue 2565).

- 2020-09-14 - Change Informative Sections and Notes section to track actual usage and update the description of the undefined: macro to further clarify its purpose and uses (internal issue 2195).

- 2020-08-16 - Add “reference monitor” to the preferred Word Choices (internal issue 2291).

- 2020-08-10 - Add a Commands which Return Error Codes section to guide authors of new commands (internal issue 2290).

- 2020-07-28 - Add a Copyrights and Licenses section describing how to properly attribute this information.

- 2020-06-23 - Update the Changes for New Extensions section to recommend placing most extension language inline in existing specification source files, rather than in separate files, and to base extension revision numbers at `1` starting with initial public release (public issue 1263).

- 2020-04-29 - Expand use of `basetype` macros to include external API types.

- 2020-03-16 - Add documentation of writing links to extension appendices in the Changes for New Extensions section and document the `apiext:` and `reflink:` macros in the API Markup Macros section. Improve documentation of writing Markup For Automatic Reference Page Extraction including how to mark up content in the Specification source so it only appears in generated reference pages; however, this section is still out of date (internal issue 1999).

- 2020-03-11 - Specify in the Sample Command Description section that a valid usage statement must be defined at the place (command or structure specification) that all information need to evaluate the statement is known. Update the description of Creating VUID tags to match the current scripts. Use the term “asciidoctor” instead of “asciidoc” everywhere. Note in the Asciidoctor Markup section that the Specification can only be built using the command-line asciidoctor application.

- 2020-02-22 - Document that it is no longer needed to escape C arrows in macros.

- 2019-12-15 - Add a markup section on Prime Symbols (internal issue 1110).

- 2019-11-27 - Expand the Describing Extension Structure Chains section and make all specification language consistent with it (internal issue 1814).

- 2019-09-09 - Define markup for nested structure members in the API Markup Macros section (internal issue 1765).

- 2019-09-08 - Add language to the end of the Changes for New Extensions section describing how to mark up asciidoctor conditionals (internal issue 1808).

- 2019-08-25 - Add the Indentation of Equations section (internal issue 1793).

- 2019-08-25 - Add the Extensions and Grouping Related Language section (internal issue 979) and the Minimize Indentation section (internal issue 747). Disallow use of standalone `+` except in latexmath and source blocks, in the Asciidoc Markup And Text Layout section (internal issue 736).

- 2019-08-19 - Add the Describing Pointers and Instances section (internal issue 1553).

- 2019-08-13 - Add a NOTE to the Format of VUID Tags appendix specifying allowed characters in VUID tags (based on discussion for internal merge request 3239).

- 2019-07-27 - Add the References section and rewrite external references accordingly.

- 2019-05-09 - Specify rules for defining new flags and bitmask types (internal issue 1649).

- 2019-01-06 - Add details on Reserving Bitmask Values (internal issue 1411).

- 2018-11-19 - Add details to the Changes for New Extensions section including the new “Description” section, and other standard parts of extension appendices.

- 2018-08-13 - Add %inline directive to the Figures section (public pull request 734).

- 2018-07-30 - Added a section on Describing Undefined Behavior (as part of the fixes for public issue 379), and describing why the undefined: macro should always be used.

- 2018-07-08 - Remove requirement to explicitly include extension appendices in the Changes for New Extensions section.

- 2018-06-25 - Modify the process for Registering a Vendor ID with Khronos to define vendor ID values as part of an enumerated type.

- 2018-03-07 - Updated for Vulkan 1.1 release.

- 2018-01-10 - Move details of mandated extension compatibility from the General Rules/Guidelines section into the Fundamentals section of the API Specification, where they are changed slightly to allow explicit incompatibilities (public issue 638).

- 2017-10-27 - Add language about proper use of “valid pointer” and “pointer to valid object” for valid usage statements, in the Sample Command Description section (related to public pull request 547).

- 2017-10-15 - Describe how to write LaTeX Math in Table Cells (internal issue 908).

- 2017-10-15 - Add more details of `KHX` extensions (public issues 536, 580).

- 2017-09-10 - Add descriptions of how to use `each` and `any` to refer to properties of elements of arrays (internal issue 884).

- 2017-09-10 - Add Valid Usage and Extension `pNext` Chains language specifying where to describe interactions of structures in a `pNext` chain (internal issue 715).

- 2017-09-10 - Add example of marking up an enumerated type all of whose values are defined by extensions (internal issue 864).

- 2017-08-25 - Add language to the API Versions, Extensions, and Layers chapter describing how to write new API versions (internal issue 892).

- 2017-06-12 - Add sections describing when to use the *name: and *text: markup macros instead of the *link: macros, and clarify that slink: should be used for handle as well as structure names (internal issue 886).

- 2017-05-08 - Add appendix describing Valid Usage ID Tags and how they are generated.

- 2017-03-19 - Add naming rule for Extension Structure Names.

- 2017-02-11 - Finish transitioning to asciidoctor markup.

- 2016-09-28 - Add asciidoc math markup guidelines.

- 2016-09-16 - Make style guide markup more consistent with its own recommendations. Simplify some tables of preferred terms. Add sections on block and table markup.

- 2016-09-12 - Describe writing and markup style for labeled lists. Require use of the ISO 8601 date format except in rare legacy cases. Expand the description of Line Lengths and add a description of markup for Footnotes.

- 2016-09-08 - Add a writing section about proper use of “a” and “an” (internal issue 432).

- 2016-08-30 - Remove mustnot: and shouldnot: macro definitions, which are no longer used in the Specification (internal issue 407).

- 2016-08-29 - Add spelling and compound word rules (public issue 352).

- 2016-08-23 - Modify description of specifying extensions in the Layers and Extensions chapter to refer to the new single-branch model for extensions (internal issue 397).

- 2016-07-26 - Add section describing markup for automatic reference page extraction.

- 2016-07-18 - Add examples of function-parameter and structure-member markup (based on public issue 286).

- 2016-07-11 - Change the document title.

- 2016-07-07 - Rename document, change license to CC BY, clarify required and recommended actions, and reserve use of “normative” for the Specifications.

- 2016-06-26 - Move Layers and Extensions chapter from Appendix C of the Vulkan API Specification and merge content with the naming guide. Put extension and naming chapters into their own source files.

- 2016-06-20 - Add API naming guide.

- 2016-05-22 - Add markup and image creation rules, after fixing missing figure captions for public issue 219.

- 2016-05-01 - Include feedback from public issues 120 and 190. Use consistent conventions for defining structures. Use American rather than British spelling conventions.

- 2016-03-12 - Recommend against “the value of”.

- 2016-02-26 - Replace use of the “maynot:” macro with “may: not”.

- 2016-02-16 - Place asciidoc conversion post-release.

- 2016-02-09 - Added quotation mark convention.

- 2016-02-01 - Add the Oxford Comma section and issue resolution.

- 2016-01-26 - Add bullet-list style description of command parameters.

- 2016-01-11 - Add “Numbers in Text” section from WSI work.

- 2015-12-16 - Make “begin / end” preferred terms to “start / finish”.

- 2015-12-15 - Make “implementation” preferred term instead of “system”.

- 2015-12-13 - Add tlink:/tname: macros for function pointer types.

- 2015-12-10 - Initial release for feedback.