blob: a3469272f8b9d92909f68f6fa000e986ae788b22 [file] [log] [blame]
// Copyright 2015-2021 The Khronos Group Inc.
//
// SPDX-License-Identifier: CC-BY-4.0
[[writing]]
= Writing Style
[[writing-misc]]
== Miscellaneous Grammar, Spelling, and Punctuation Issues
=== Use the Oxford Comma (Serial Comma)
When writing a sentence listing a series of items, include a comma before
the "`and`" separating the last item.
*Correct:* The red, green, blue, and alpha components.
*Incorrect:* The red, green, blue and alpha components.
Also see this
link:https://blog.oxforddictionaries.com/2015/01/21/video-oxford-comma/[video
discussion of the Oxford comma] provided by the Oxford Dictionary.
=== Date Format
Whenever possible, write dates in the <<iso-8601,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 ambigious formats such as "`09/12/16`".
[source,asciidoc]
.Example Markup
----
* 2016-09-12
* September 12, 2016
----
[[writing-misc-a-an]]
=== A/An and Markup Macros
Use "`a`" and "`an`"
link:https://www.grammar.com/a-vs-an-when-to-use/[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,markup macros>>.
For example, if you wanted to say:
A ename:VK_ERROR_DEVICE_LOST error
the correct way to mark this up in asciidoctor would be:
[source,asciidoc]
----
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{cl}`".
That starts with a vowel, so the temptation is to say
[source,asciidoc]
----
An ename:VK_ERROR_DEVICE_LOST error may occur.
----
What matters here is how the *output* document is formatted.
=== 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.`"
=== Use American Spelling Conventions
In case of conflict, use American rather than British spelling conventions,
except for noted exceptions in the table below.
.Spelling
[width="60%",options="header"]
|====
| Use Spelling | Instead Of | Comments
| color | colour |
| signaled | signalled |
| tessellation | tesselation | Historical exception
|====
[[writing-inclusivity]]
=== Use Inclusive Language
The Vulkan Working Group has begun to apply the
link:https://www.khronos.org/about/inclusive-language[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.
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.
[[writing-pointers-instances]]
=== 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
dname:VK_NULL_HANDLE.
"`Optional pointer/handle`" are not well-defined terms in the Specification.
[source,asciidoc]
.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.
----
[[writing-arrays]]
=== 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:
[source,asciidoc]
.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:
[source,asciidoc]
.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`".
[[writing-compound-words]]
=== Compound Words and Preferred Orthography
Unless there is longstanding precedent in computer science literature, or
the word is a noted exception in the table below, do not arbitrarily cram
terms together.
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 pname:colorSpace member
of a structure as a "`color space`" value.
.Spelling
[width="70%",options="header",cols="20%,20%,60%"]
|====
| Use Spelling | Instead Of | Comments
| bit plane | bitplane |
| compile time | compile-time | Per Wikipedia "`compile time`"
| color space | colorspace |
| cube map | cubemap |
| double-buffer | doublebuffer |
| entry point | entry-point +
entrypoint
| Except if needed to disambiguate from surrounding terms
| flat shading | flatshading |
| GitHub | Github | Site's preferred spelling
| LOD | lod +
level of detail +
level-of-detail| Acronym for "`Level of Detail`"
| mip level +
mip layer +
mip size +
mip tail
| miplevel +
miplayer +
mipsize +
miptail | "`mipmap *term*`" may be used in time
| render pass | renderpass |
| reuse | re-use |
| side effect | side-effect |
3+h| Exceptions
| mipmap | mip map | Exception for historical reasons
| pname:pNext chain
| pname:pNext-chain +
pname:pNext extension chain
|
| general-purpose
| general purpose| When used as an adjective
| implementation-dependent
| implementation dependent
| When used as an adjective
| swapchain | swap chain | Exception due to heavy use in WSI extensions
| happen-before +
happen-after | happen before +
happen after | As used in concurrent languages such as
C++11, Java and OpenCL C.
|====
==== Words With "Pre-" Prefixes
// also: premultiply preorder prerotation predefined
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.
[[writing-references]]
=== References
When citing external references, use the appropriate <<acm-references,
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-spec, Vulkan Specification>> citation in this document for
an example.
[[writing-undefined]]
== 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{cl} 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 {cl}.
This is enforced by internal CI tests.
The undefined{cl} 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{cl} not create circumstances that
would lead to such behavior.
Such statements should be written as valid usage statements, if possible.
[[writing-describing]]
== Describing Commands and Parameters
The <<vulkan-spec,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 or 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-spec,Vulkan API Specification>>.
Do not vary from them without compelling need.
Normative parts of the <<vulkan-spec,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 dname: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 fname:vkCreateCommandPool`"
rather than
"`You/The application/The user can create a command pool by calling
fname: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-spec,Vulkan API Specification>> using
<<markup-informative-notes,informative notes>>.
[[writing-describing-errors]]
=== Commands which Return Error Codes
Commands which return elink: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 ename: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-spec,Vulkan API
Specification>> for additional information.
[[writing-describing-layers]]
== 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, <<extensions-documenting-extensions,
protected by asciidoctor conditionals>> for the new extension.
[NOTE]
.Guideline
====
Specification language should be structured, whenever possible, so it fits
into a single open block defining a <<writing-refpages, reference page>>.
====
[[writing-math]]
== 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.
=== Asciidoc Math Markup
Where possible, math is marked up using straight asciidoctor features.
For commonality with LaTeX math (see below), some common LaTeX operators and
names are defined as asciidoctor attributes using the same names, expanding
to the corresponding Unicode entities.
The complete set of these attributes is found in `config/attribs.txt`.
.Spelling
[width="100%",options="header",cols="20%,20%,60%"]
|====
| Feature | Result | Sample Markup
| Subscripts
| [eq]#a~x~#
| +++[eq]#a~x~#+++
| Superscripts
| [eq]#-2^(b-1)^#
| +++[eq]#-2^(b-1)^#+++
| Struct/parameter names as variables
| [eq]#2^pname:bits^#
| +++[eq]#2^pname:bits^#+++
| Greek Letters (selected)
| [eq]#{alpha}, {beta}, {gamma}, {delta}, {DeltaUpper}, {epsilon}, {lambda},
{rho}, {tau}#
| +++[eq]#{alpha}, {beta}, {gamma}, {delta}, {DeltaUpper}, {epsilon}, {lambda},
{rho}, {tau}#+++
| Fractions
| [eq]#{onequarter} {plus} {onehalf}#
| +++[eq]#{onequarter} {plus} {onehalf}#+++
| Closed Ranges
| [eq]#[0,1]#
| +++[eq]#[0,1]#+++
| Open Ranges
| [eq]#[0,1)#
| +++[eq]#[0,1)#+++
| Arithmetic and Relational Operators
| [eq]#a {times} b#, [eq]#a {leq} b#, [eq]#a {neq} b#, [eq]#a {geq} b#, [eq]#{vert}x{vert}#
| +++[eq]#a {times} b#+++, +++[eq]#a {leq} b#+++, +++[eq]#a {neq} b#+++, +++[eq]#a {geq} b#+++, +++[eq]#{vert}x{vert}#+++
| Floor
| [eq]#{lfloor}w - {onehalf}{rfloor}#
| +++[eq]#{lfloor}w - {onehalf}{rfloor}#+++
| Ceiling
| [eq]#{lceil}log~2~(max(pname:width, pname:height)){rceil} {plus} 1#
| +++[eq]#{lceil}log~2~(max(pname:width, pname:height)){rceil} {plus} 1#+++
| Logical and Set Operators
| [eq]#{land} {lnot} {lor} {oplus} {elem}#
| +++[eq]#{land} {lnot} {lor} {oplus} {elem}#+++
| Partial Derivatives
| [eq]#{partial}r~x~ / {partial}x = 0#
| +++[eq]#{partial}r~x~ / {partial}x = 0#+++
| Matrix/Vector Parameter Names
| [eq]#**P** = t **P**~1~ {plus} (1-t) **P**~2~#
| +++[eq]#**P** = t **P**~1~ {plus} (1-t) **P**~2~#+++
|====
[[writing-math-latexmath]]
=== LaTeX Math Markup
Math markup more complex than easily supported in straight asciidoctor
markup (examples found in the Vulkan Specification include matrices,
tensors, summation notation, conditional assignments, and division of
complex expressions) are 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]
.Note
====
There are font and style differences between LaTeX and asciidoctor 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{cl} macro.
For example:
* latexmath:[[0,1\]]
* latexmath:[\frac{1 - \frac{x}{2}}{x - 1}]
* latexmath:[\mathbf{c} = t \mathbf{c}_1 + (1-t) \mathbf{c}_2.]
[source,asciidoc]
.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 asciidoctor macro parsing.
_Block math_ is used for more complex equations.
This example uses the `aligned` environment to delimit the expression.
[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}
+++++++++++++++++++
[source,asciidoc]
.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]
.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've had to make are:
.LaTeX math replacements for KaTeX compatibility
[width="70%",options="header",cols="20%,20%,60%"]
|====
| Replace | With | Comments
| `\begin{equation}` | _nothing_ | Unnecessary in blocks. Should not be used for inline.
| `\end{equation}` | _nothing_ | Unnecessary in blocks. Should not be used for inline.
| `\begin{align*}` | `\begin{aligned}` |
| `\end{align*}` | `\end{aligned}` |
| `\operatorname{foo}` | `\mathbin{foo}` |
| `{\rm A}` | `\mathrm{A}` |
| `\text{for }` | `\text{for}\ ` | Text ending in spaces is unpredictable - favour escaped spaces after text
|====
The KaTeX repository provides a
link:https://github.com/Khan/KaTeX/wiki/Function-Support-in-KaTeX[list of
currently supported LaTeX functionality].
You can also use the link:https://khan.github.io/KaTeX/[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 April 2021, we are using v0.11.1.
See the mtex2MML repository for a
link:https://github.com/gjtorikian/mtex2MML/blob/master/SUPPORTED.md[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:
[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}
+++++++++++++++++++
[source,asciidoc]
.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}
+++++++++++++++++++
----
[[writing-latexmath-in-table-cells]]
=== LaTeX Math in Table Cells
To use `[latexmath]` or `latexmath{cl}` constructs inside table cells, the
cell separator must be `a|` instead of just `|`:
[source,asciidoc]
.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}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|====
----
[[writing-pNext-chain]]
== Describing Extending Structure Chains
When describing an extending structure which is passed to an existing
command by including it in the pname:pNext chain of a structure parameter of
that command, introduce the structure description in this fashion:
[source,asciidoc]
----
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 pname:pNext chain,
refer to that structure as "`included in the pname:pNext chain`" rather than
`"present in`" or other similar terms, in this fashion:
[source,asciidoc]
----
If the pname:pNext chain includes a slink:VkPhysicalDeviceFeatures2
structure, then pname:pEnabledFeatures must: be `NULL`
----
[[writing-example]]
== Example Command, Structure, and Enumerant Descriptions
The <<sample-command,next section>> is a sample based on the
<<vulkan-spec,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.
[[sample-command]]
== Sample Command Description: Creating Command Pools
[open,refpage='vkCreateCommandPool',desc='Create a new command pool object',type='protos']
--
To create a command pool, call:
include::{generated}/api/protos/vkCreateCommandPool.txt[]
[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
<<writing-refpages, automatic extraction into a reference page>>.
Use a short, active sentence when describing what commands do, instead of
more passive phrasing like "`A command pool is created by calling:`" or
"`The application may create a command pool by calling:`".
After the description, include the autogenerated prototype for the command
from the `\{generated}/api/protos/` directory:
// The 'subs=attributes+' and '{blank}--' are one way to allow the inner
// [source] block to show the correct two dashes. See
// http://discuss.asciidoctor.org/Another-markup-escaping-question-td5665.html
[source,asciidoc,subs=attributes+]
~~~~
[open,refpage='vkCreateCommandPool',desc='Create a new command pool object',type='protos']
{blank}--
To create a command pool, call:
\include::\{generated}/api/protos/vkCreateCommandPool.txt[]
~~~~
Note that each autogenerated command, enumeration, flag, or structure
definition include file also defines a corresponding asciidoctor anchor
which is the base name of the file.
In this case, the anchor is named `vkCreateCommandPool`.
====
* pname:device is the logical device that the command pool is created on.
* pname:pCreateInfo is a pointer to a slink:VkCommandPoolCreateInfo
structure specifying the state of the command pool object.
* pname:pAllocator controls host memory allocation as described in the
<<memory-allocation, Memory Allocation>> chapter.
* pname:pCommandPool is a pointer to a slink: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{cl} macro.
Strive for compact notation, and in particular always try to use the
phrasing "`pname{cl}param _is_`" rather than wordier forms such as
"`pname{cl}param _specifies_`" or "`The pname{cl}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{cl}device is the logical
device`" rather than "`pname{cl}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]]
pname:pCreateInfo->queueFamilyIndex must: be the index of a queue family
available in the logical device pname:device
****
include::{generated}/validity/protos/vkCreateCommandPool.txt[]
--
[NOTE]
.Guideline
====
If there is a general description of the command, add it following the
parameter descriptions:
[source,asciidoc,subs=attributes+]
~~~~
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:
[source,asciidoc,subs=attributes+]
~~~~
.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
<<sample-writing-explicit-vu, 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.
[source,asciidoc,subs=attributes+]
~~~~
\include::\{generated}/validity/protos/vkCreateCommandPool.txt[]
{blank}--
~~~~
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 asciidoctor 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.
====
[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.txt[]
[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
<<writing-refpages, automatic extraction into a reference page>>.
Use a short, active paragraph to introduce the structure, usually just "`The
sname:VkStructureName structure is defined as:`".
After the description, include the autogenerated definition for the
structure from the `\{generated}/api/structs/` directory:
[source,asciidoc,subs=attributes+]
~~~~
[open,refpage='VkCommandPoolCreateInfo',desc='Structure specifying parameters of a newly created command pool',type='structs']
{blank}--
The sname:VkCommandPoolCreateInfo structure is defined as:
\include::\{generated}/api/structs/VkCommandPoolCreateInfo.txt[]
~~~~
====
* pname:sType is the type of 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.
[NOTE]
.Guideline
====
Each structure member is described in a separate bullet list item.
For structures with pname:sType and pname:pNext members, there is standard
boilerplate for their descriptions.
Descriptions of other members of the structure follow.
[source,asciidoc,subs=attributes+]
~~~~
* pname:sType is the type of this structure.
* pname:pNext is `NULL` or a pointer to a structure extending this
structure.
+
{blank}--
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.
{blank}--
* 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 asciidoctor xrefs.
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 asciidoctor parser.
It is usually best to append a continuation block following the first
paragraph of such a list item, as shown for pname:pNext above.
Add general descriptions of the structure, if any, following the member
descriptions.
No general description is shown in this example.
====
.Valid Usage
****
ifdef::VK_VERSION_1_1[]
* [[VUID-VkCommandPoolCreateInfo-flags-02860]]
If the protected memory feature is not enabled, the
ename:VK_COMMAND_POOL_CREATE_PROTECTED_BIT bit of pname:flags must: not
be set
endif::VK_VERSION_1_1[]
****
include::{generated}/validity/structs/VkCommandPoolCreateInfo.txt[]
--
[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.
[source,asciidoc,subs=attributes+]
~~~~
.Valid Usage
****
ifdef::VK_VERSION_1_1[]
* [[VUID-VkCommandPoolCreateInfo-flags-02860]]
If the protected memory feature is not enabled, the
ename:VK_COMMAND_POOL_CREATE_PROTECTED_BIT bit of pname:flags must: not
be set
endif::VK_VERSION_1_1[]
****
\include::\{generated}/validity/structs/VkCommandPoolCreateInfo.txt[]
{blank}--
~~~~
====
[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.txt[]
[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.
[source,asciidoc,subs=attributes+]
~~~~
[open,refpage='VkCommandPoolCreateFlagBits',desc='Bitmask specifying usage behavior for a command pool',type='enums']
{blank}--
Bits which can: be set in slink:VkCommandPoolCreateInfo::pname:flags to
specify usage behavior for a command pool are:
\include::\{generated}/api/enums/VkCommandPoolCreateFlagBits.txt[]
~~~~
====
* 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[]
--
[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 asciidoctor conditionals.
Close the open block after all enumerants are described.
[source,asciidoc,subs=attributes+]
~~~~
* 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[]
{blank}--
~~~~
====
[[sample-writing-explicit-vu]]
== 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 {times} 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.
Do not use nested bullet lists or other writing structure where valid usage
statements are not self-contained.
This would make it impossible to extract semantically meaningful
descriptions for each assigned <<appendix-vuid, Valid Usage ID Tag>>.
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 valid usage statements apply only when specific extensions and/or core
API versions are enabled at runtime, surround those statements in their
entirety with appropriate asciidoctor conditionals.
Never use asciidoctor conditionals _inside_ a valid usage statement.
Explicit valid usage statements must be assigned Valid Usage ID tags before
publication.
This process is described in the <<appendix-vuid, 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
flink:vkCreateCommandPool::pname:queueFamilyIndex valid usage statement
shown above, the tag
[source,asciidoc,subs=attributes+]
----
[[VUID-vkCreateCommandPool-queueFamilyIndex-01937]]
----
was inserted by a script, not the original author.
[NOTE]
.Guideline
====
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.txt`), and
then the file can be included in the relevant API features using standard
include syntax:
[source,asciidoc,subs=attributes+]
~~~~
.Valid Usage
****
\include::\{chapters}/commonvalidity/draw_common.txt[]
\include::\{chapters}/commonvalidity/draw_vertex_binding.txt[]
* [[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:
[source,asciidoc]
~~~~
// 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.
[source,asciidoc]
~~~~
[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.
====
[[writing-empty-enumerations]]
== 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 asciidoctor
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
ename:VkDescriptorSetLayoutCreateFlagBits description, whose only value is
defined by an extension, will look like this:
[source,asciidoc,subs=attributes+]
----
\include::\{generated}/api/enums/VkDescriptorSetLayoutCreateFlagBits.txt[]
\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]
.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[]
----
[[writing-refpages]]
== 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
asciidoctor `open` block surrounding markup describing that page, with
attributes used to specify properties of the reference page.
Additional heuristics and non-asciidoctor tags, described below, are used to
identify subsections of a reference page in some cases.
In general the open block introduction will look like:
[source,asciidoc]
----
[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 comma-separated names of other API entities which this
refpage also describes. This is used when an API is promoted and the
refpage block describes both the old and promoted APIs.
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`, but 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 asciidoctor 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 asciidoctor markup to have an
empty line in the bullet list section, add a `// refBody` comment
immediately following the bullet list and preceding this section:
+
[source,asciidoc]
----
// refBody
----
+
There are no examples of this usage in the Vulkan 1.2.192 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 asciidoctor delimiter closing the open block:
+
[source,asciidoc]
----
--
----
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:
[source,asciidoc,subs=attributes+]
----
\ifdef::isrefpage[]
=== Refpage-Only Section
*This section will appear only when generating an extension refpage,
but not in the specification extensions appendix.*
\endif::isrefpage[]
----