// Copyright (c) 2015-2016 The Khronos Group Inc. // Copyright notice at https://www.khronos.org/registry/speccopyright.html [[extensions]] = Layers & Extensions This chapter describes required and recommended processes for writing formal extensions and layers for the Vulkan API. It is concerned with processes and registration, while fine-grained naming conventions are included in the <>. Prior to revision 1.0.19 of the <>, most of the content in this chapter existed as part of Appendix C of that document. [NOTE] .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. ==== == 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 Vulkan's design and general software development trends introduces two new paradigms that require rethinking the existing mechanisms: * Layers, and with them a focus on a more open ecosystem where non-Khronos members are expected to extend a Khronos API using the Layer mechanism. * Namespaced constants (enumerations) that do not necessarily draw from a single global set of token values. == General Rules/Guidelines Some general rules to simplify the specific rules below: * Extensions and layers must each have a globally unique name. * All commands and tokens must have a globally unique name. * 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 must be strictly additive and backwards-compatible. That is, extensions must not remove existing functionality, or change existing default behaviors. A Vulkan implementation may support any combination of extensions, but applications written using only the core API, or a subset of the supported extensions, must continue to work in such an implementation without changes in behavior. [[extensions-naming-conventions]] == Extension and Layer Naming Conventions 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 file indicating that an extension interface is defined at compile time. * As part of the name of Github repository branches containing specifications for an extension. There is a rigid syntax for these names: * Extensions are named with the syntax: +VK_AUTHOR_+. * Layers are named with the syntax: +VK_LAYER_{AUTHOR|FQDN}_+. Both extensions and layer names include a +VK_+ prefix, as described in the <> section above. In addition, layers add a +LAYER_+ prefix. Extension and layer names must both be valid C language identifiers. [[extensions-naming-conventions-name-strings]] === Extension and Layer Name Strings The ++ portion of extension and layer names is a concise name describing the purpose or functionality of the extension or layer. The underscore (`_`) character is used as a delimiter between words. Every character of the name must be in lower case. === Author IDs 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. 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) as the ID. The FQDN should be a domain name owned by the author. FQDNs cannot be used for extensions, only for layers. * The following are examples of extension and layer names, demonstrating the above syntax: ** Extension names all use the base prefix +VK_+. ** Khronos-ratified extensions add the reserved author ID +KHR+, and will use the prefix +VK_KHR_+. ** 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. ** Multi-author extensions that have not been ratified by Khronos (those developed via cooperation between, and intended to be supported by two or more registered authors) add the special author ID +EXT+ to the base prefix, and will use the prefix +VK_EXT_+. ** Traditional author-specific extensions developed by one author (or one author in cooperation with non-authors) 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_+. Some authors can have additional registered author IDs for special purposes. For example, an Android extension developed by Google - but part of an Android open-source community project, and so not a proprietary Google extension - will use the author ID +ANDROID+. ** 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. [source, c] .Example ---- // Khronos extension name VK_KHR_mirror_clamp_to_edge // Multivendor 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] .Note ==== To avoid linking to a nonexistent domain, the reserved TLD +.invalid+ is used in the example above. ==== [[extensions-naming]] == 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 <> section above. [[extensions-api-registry]] == The Vulkan Registry The canonical definition of the Vulkan APIs is kept in an XML file known as the *Vulkan registry*. The registry is kept in +src/spec/vk.xml+ in the branch of the vulkan project containing the most recently released core 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.h+, and to create a variety of related documentation used in generating the API specification and reference pages. [[extensions-author-ID]] == 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 +<>+ 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 <> in the +1.0+ branch. The merge must add a ++ 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 software 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. [[extensions-vendor-id]] == Registering a Vendor ID with Khronos Vulkan implementers must report a valid vendor ID for their implementation when queried by fname:vkGetPhysicalDeviceProperties, as described in the ``Devices and Queues'' section of the <>. 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 <>. While vendor IDs are not directly related to API extensions, the reservation process is very similar and so is described in this section. To reserve an Khronos vendor ID, you must first have a Khronos author ID. Propose a merge request against <> in the +1.0+ branch. The merge must add a ++ tag and fill in the +name+ and +id+ attributes. The +name+ attribute must be set to the author ID. The +id+ attribute must be the first sequentially available ID in the list of ++ tags. 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 a Vulkan implementation and require one for that purpose. == Registering Extensions and Layers Extensions must be registered with Khronos. Layers may be registered, and registration is strongly recommended. 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 against the branch containing the core specification against which the extension or layer will be written. The merge must modify +vk.xml+ to define extension names, API interfaces, and related information. Registration is not complete until the registry maintainer has validated and accepted the merge. Since this process could in principle be completely automated, this suggests a scalable mechanism for accepting registration of non-Khronos extensions. Non-Khronos members who want 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 <>. The merge should add a new ++ 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 +1.0+ branch. * Develop and test the extension using the registered extension number. * Publish the extension to Khronos using the previously registered extension number, by creating a branch of the repository with appropriate changes relative to the core Vulkan API branch. ** Publishing on the <> is preferred whenever possible. Khronos members may instead create branches on Khronos' internal gitlab server, but those branches will eventually be mirrored to github. * Mark the extension as enabled, by proposing a merge to the +1.0+ branch changing the +supported+ attribute value of the ++ to +supported="vulkan"+. This should be completely automated and under the control of the publishers, to allow them to align publication on Khronos with product releases. However, complete automation might be difficult, since steps such as regenerating and validating +vulkan.h+ are involved. Once the merge is accepted and the corresponding updated header with the new extension interface is committed to the +1.0+ branch, publication is complete. The automated process does not exist yet, and would require significant investment in infrastructure to support the process on the Khronos servers. ifdef::editing-notes[] [NOTE] .editing-note ==== TODO: This section is subject to change and not complete yet, but in broad is how we expect extension registration and specifications to work. The process will be refined as members and outside authors define further extensions. ==== endif::editing-notes[] == Documenting Extensions Extensions are documented as modifications to the Vulkan specification. These modifications will be on Git branches that are named with the following syntax: +-+ For example, the VK_KHR_surface extension will be documented relative to version 1.0 of the <>. As such, the branch name will be: +1.0-VK_KHR_surface+ in the Github +<>+ project. If the extension modifies an existing section of the Vulkan specification, those modifications are made in-place. Since the changes are on a branch, the core-only specification can be easily produced. A specification with an extension is created by merging in the extension's branch contents. Extensions should be merged according to their registered extension number. If two extensions both modify the same portion of the specification, the higher-numbered extension should take care to deal with any conflicts. The WSI extensions were used to help prototype what should be done for extensions. This includes the following: * All extensions should add an appendix to the Vulkan specification. This should be modeled after what was done for the +VK_KHR_surface+ extension (in the +1.0-VK_KHR_surface+ Github branch), which contains some high-level information about the extension (as well as code examples, and revision history) in the +appendices/vk_khr_surface.txt+ file. * Each extension's appendix file is included by adding an +include+ statement to the +doc/specs/vulkan/vkspec.txt+ file. Since most extensions will all put their +include+ line at the same place in this file, they should add this statement on the +1.0+ branch, even though the file will not actually exist on the +1.0+ branch. This helps avoid merge conflicts when multiple extensions' branches are merged in order to create the ``full'' branch specification. * If there are any other places where 2 or more extensions will extend the Vulkan specification, it is best to put that content in a file, and use an +include+ statement to put that content into the spec. Again, this +include+ line should be put on the +1.0+ branch in order to avoid merge conflicts. * If an extension is more of an addition to the Vulkan specification, the extension should add a chapter to the Vulkan specification. [NOTE] .Note ==== As of June 2016, we have found that the ``extension branch'' model poses some challenges. It works fine for individual extensions, but trying to merge extensions into combined branches, such as the +1.0-wsi_extensions+ branch containing all Khronos WSI family extensions, invariably produces a number of merge conflicts which must be manually resolved. We are likely to continue using the extension branch model, and hope to simplify the merge process over time, but authors should be aware that it is not as completely transparent as we had hoped initially. ==== == 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 <> 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 etext: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] .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. stext:VkStructureType). * The name of the new enumeration **token** being added (e.g. etext: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 etext:VkResult values indicating errors, like etext:VK_ERROR_SURFACE_LOST_KHR. The default direction is positive, if not specified. Implicit is the registered number of an extension, which is used to create a range of unused values offset against a global extension base value. Individual enumerant values are calculated as offsets in that range. Values are calculated 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 +readme.pdf+ specifying the format of +vk.xml+, and extension authors can also refer to existing extensions for examples. [[extensions-reserving-bitmask-values]] === 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 not reserved, and must not be used in a published implementation or specification until the reservation is merged into <> by the registry maintainer. [NOTE] .Note ==== In reality the approving authority for EXT and vendor extension bitmask additions will probably be the owner of the github branch containing the specification of that extension; however, until the github process is fully defined and locked down, it is safest to refer to the listed contact. ==== == 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) in +vulkan.h+. This value begins at 1 with the initial version of an extension specification, and is incremented when significant changes (bugfixes or added functionality) are made. Note that the revision of an extension defined in +vulkan.h+ and the revision supported by the Vulkan implementation (the pname:specVersion field of the slink:VkExtensionProperties structure corresponding to the extension and returned by one of the <>) may differ. In such cases, only the functionality and behavior of the lowest-numbered revision can be used. * 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: [source,c] --------------------------------------------------- #define VK_KHR_SURFACE_SPEC_VERSION 24 #define VK_KHR_SURFACE_EXTENSION_NAME "VK_KHR_surface" --------------------------------------------------- == Extension 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 <>. All such additions will be included in the +vulkan.h+ header supplied by Khronos. [NOTE] .Note ==== Application developers are encouraged to be careful when using +switch+ statements with Vulkan API enums. This is because extensions can add new values to existing enums. The use of a +default:+ statement, within a +switch+, may avoid future compilation issues. ==== [[extension-function_prototypes]] == Extension Function Prototypes Function pointer declarations and function prototypes for all core Vulkan API commands are included in the +vulkan.h+ file. These come from the official XML specification of the Vulkan API hosted by Khronos. Function pointer declarations are also included in the +vulkan.h+ file for all commands defined by registered extensions. Function prototypes for extensions may be included in +vulkan.h+. Extension commands that are part of the Vulkan ABI must be flagged in the XML. Function prototypes will be included in +vulkan.h+ for all extension commands that are part of the Vulkan ABI. An extension can be considered platform specific, in which case its interfaces in +vulkan.h+ 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 the +vulkan.h+ provided by Khronos, though the platform-specific portions of +vulkan.h+ are protected by #ifdefs. [NOTE] .Note ==== Based on feedback from implementers, Khronos expects that the Android, Linux, and Windows Vulkan SDKs will include our +vulkan.h+ 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. ==== == Accessing Extension Functions from Programs flink:vkGetInstanceProcAddr and flink: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 <>). 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 ftext:vkGet*ProcAddr commands. [NOTE] .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. ==== [[extensions-interactions]] == Extension Interactions Extensions modifying the behavior of existing commands should provide additional parameters by using the pname:pNext field of an existing structure, pointing to a new structure defined by the extension, as described in the ``Valid Usage'' section of the <>. Extension structures defined by multiple extensions affecting the same structure can be chained together in this fashion. Any structure which can be chained in this fashion must begin with the following two members: ["source","{basebackend@docbook:c++:cpp}",title=""] ------------------------------------------------------------------------------ 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 pname:sType defined by the extension, but this approach is discouraged and should not be used. When chaining multiple extensions to a structure, the implementation will process the chain starting with the base parameter and proceeding through each successive chained structure in turn. Extensions should be defined to accept any order of chaining, and must define their interactions with other extensions such that the results are deterministic. If an extension needs a specific ordering of its extension structure with respect to other extensions in a chain to provide deterministic results, it must define the required ordering and expected behavior as part of its specification.