Vulkan is a layered API. The lowest layer is the core Vulkan layer, as defined by this Specification. The application can use additional layers above the core for debugging, validation, and other purposes.
One of the core principles of Vulkan is that building and submitting command buffers should be highly efficient. Thus error checking and validation of state in the core layer is minimal, although more rigorous validation can be enabled through the use of layers.
The core layer assumes applications are using the API correctly. Except as
documented elsewhere in the Specification, the behavior of the core layer to
an application using the API incorrectly is undefined, and may include
program termination.
However, implementations must ensure that incorrect usage by an
application does not affect the integrity of the operating system,
the Vulkan implementation, or other Vulkan client applications
in the system, and does not allow one application to access data
belonging to another application. Applications can request stronger
robustness guarantees by enabling the robustBufferAccess
feature
as described in Chapter 31, Features, Limits, and Formats.
Validation of correct API usage is left to validation layers. Applications should be developed with validation layers enabled, to help catch and eliminate errors. Once validated, released applications should not enable validation layers by default.
Valid usage defines a set of conditions which must be met in order to achieve well-defined run-time behavior in an application. These conditions depend only on Vulkan state, and the parameters or objects whose usage is constrained by the condition.
Some valid usage conditions have dependencies on run-time limits or feature availability. It is possible to validate these conditions against Vulkan’s minimum supported values for these limits and features, or some subset of other known values.
Valid usage conditions do not cover conditions where well-defined behavior (including returning an error code) exists.
Valid usage conditions should apply to the command or structure where complete information about the condition would be known during execution of an application. This is such that a validation layer or linter can be written directly against these statements at the point they are specified.
![]() | Note |
---|---|
This does lead to some non-obvious places for valid usage statements. For instance, the valid values for a structure might depend on a separate value in the calling command. In this case, the structure itself will not reference this valid usage as it is impossible to determine validity from the structure that it is invalid - instead this valid usage would be attached to the calling command. Another example is draw state - the state setters are independent, and can cause a legitimately invalid state configuration between draw calls; so the valid usage statements are attached to the place where all state needs to be valid - at the draw command. |
Certain usage rules apply to all commands in the API unless explicitly denoted differently for a command. These rules are as follows.
Any input parameter to a command that is an object handle must be a valid object handle, unless otherwise specified. An object handle is valid if:
The reserved handle VK_NULL_HANDLE
can be passed in place of valid
object handles when explicitly called out in the specification. Any
command that creates an object successfully must not return
VK_NULL_HANDLE
. It is valid to pass VK_NULL_HANDLE
to any
vkDestroy*
or vkFree*
command, which will silently ignore these
values.
Any parameter that is a pointer must be a valid pointer. A pointer is valid if it points at memory containing values of the number and type(s) expected by the command, and all fundamental types accessed through the pointer (e.g. as elements of an array or as members of a structure) satisfy the alignment requirements of the host processor.
Any parameter of an enumerated type must be a valid enumerant for that type. A enumerant is valid if:
_BEGIN_RANGE
,
_END_RANGE
, _RANGE_SIZE
or _MAX_ENUM
.
A collection of flags is represented by a bitmask using the type
VkFlags
:
typedef uint32_t VkFlags;
Bitmasks are passed to many commands and structures to compactly represent
options, but VkFlags
is not used directly in the API. Instead, a
Vk*Flags
type which is an alias of VkFlags
, and whose name
matches the corresponding Vk*FlagBits
that are valid for that type, is
used. These aliases are described in the Flag Types
appendix of the Specification.
Any Vk*Flags
member or parameter used in the API must be a valid combination of bit
flags. A valid combination is either zero or the bitwise OR of valid bit
flags. A bit flag is valid if:
Vk*FlagBits
type, where the bits type is
obtained by taking the flag type and replacing the trailing Flags
with FlagBits
. For example, a flag value of type
VkColorComponentFlags
must contain only bit flags defined by
VkColorComponentFlagBits
.
Any parameter that is a structure containing a
sType
member must have a value of sType
which is a
valid VkStructureType
value matching the type of the structure.
As a general rule, the name of this value is obtained by taking the
structure name, stripping the leading Vk
, prefixing each capital
letter with _
, converting the entire resulting string to upper case,
and prefixing it with VK_STRUCTURE_TYPE_
. For example, structures of
type VkImageCreateInfo
must have a sType
value of
VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO
.
The values VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO
and
VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO
are reserved for internal
use by the loader, and do not have corresponding Vulkan structures in this
specification.
The list of supported structure types is defined in an appendix.
Any parameter that is a structure containing a void
* pNext
member must have a value of pNext
that is either NULL
, or points to
a valid structure defined by an extension, containing sType
and
pNext
members as described in the Vulkan Documentation and Extensions document in the section “Extension
Interactions”. If that extension is supported by the
implementation, then it must be enabled. Any component of the
implementation (the loader, any enabled layers, and drivers) must skip
over, without processing (other than reading the sType
and pNext
members) any chained structures with sType
values not defined by
extensions supported by that component.
Extension structures are not described in the base Vulkan specification, but either in layered specifications incorporating those extensions, or in separate vendor-provided documents.
While the core Vulkan API is not designed to capture incorrect usage, some circumstances still require return codes. Commands in Vulkan return their status via return codes that are in one of two categories:
All return codes in Vulkan are reported via VkResult
return
values. The possible codes are:
typedef enum VkResult { VK_SUCCESS = 0, VK_NOT_READY = 1, VK_TIMEOUT = 2, VK_EVENT_SET = 3, VK_EVENT_RESET = 4, VK_INCOMPLETE = 5, VK_ERROR_OUT_OF_HOST_MEMORY = -1, VK_ERROR_OUT_OF_DEVICE_MEMORY = -2, VK_ERROR_INITIALIZATION_FAILED = -3, VK_ERROR_DEVICE_LOST = -4, VK_ERROR_MEMORY_MAP_FAILED = -5, VK_ERROR_LAYER_NOT_PRESENT = -6, VK_ERROR_EXTENSION_NOT_PRESENT = -7, VK_ERROR_FEATURE_NOT_PRESENT = -8, VK_ERROR_INCOMPATIBLE_DRIVER = -9, VK_ERROR_TOO_MANY_OBJECTS = -10, VK_ERROR_FORMAT_NOT_SUPPORTED = -11, VK_ERROR_FRAGMENTED_POOL = -12, VK_ERROR_SURFACE_LOST_KHR = -1000000000, VK_ERROR_NATIVE_WINDOW_IN_USE_KHR = -1000000001, VK_SUBOPTIMAL_KHR = 1000001003, VK_ERROR_OUT_OF_DATE_KHR = -1000001004, VK_ERROR_INCOMPATIBLE_DISPLAY_KHR = -1000003001, } VkResult;
Success codes
VK_SUCCESS
Command successfully completed
VK_NOT_READY
A fence or query has not yet completed
VK_TIMEOUT
A wait operation has not completed in the specified time
VK_EVENT_SET
An event is signaled
VK_EVENT_RESET
An event is unsignaled
VK_INCOMPLETE
A return array was too small for the result
VK_SUBOPTIMAL_KHR
A swapchain no longer matches the surface properties exactly, but can
still be used to present to the surface successfully.
Error codes
VK_ERROR_OUT_OF_HOST_MEMORY
A host memory allocation has failed.
VK_ERROR_OUT_OF_DEVICE_MEMORY
A device memory allocation has failed.
VK_ERROR_INITIALIZATION_FAILED
Initialization of an object could not be completed for
implementation-specific reasons.
VK_ERROR_DEVICE_LOST
The logical or physical device has been lost. See
Lost Device
VK_ERROR_MEMORY_MAP_FAILED
Mapping of a memory object has failed.
VK_ERROR_LAYER_NOT_PRESENT
A requested layer is not present or could not be loaded.
VK_ERROR_EXTENSION_NOT_PRESENT
A requested extension is not supported.
VK_ERROR_FEATURE_NOT_PRESENT
A requested feature is not supported.
VK_ERROR_INCOMPATIBLE_DRIVER
The requested version of Vulkan is not supported by the driver or
is otherwise incompatible for implementation-specific reasons.
VK_ERROR_TOO_MANY_OBJECTS
Too many objects of the type have already been created.
VK_ERROR_FORMAT_NOT_SUPPORTED
A requested format is not supported on this device.
VK_ERROR_FRAGMENTED_POOL
A requested pool allocation has failed due to fragmentation of the
pool’s memory.
VK_ERROR_SURFACE_LOST_KHR
A surface is no longer available.
VK_ERROR_NATIVE_WINDOW_IN_USE_KHR
The requested window is already connected to a VkSurfaceKHR, or
to some other non-Vulkan API.
VK_ERROR_OUT_OF_DATE_KHR
A surface has changed in such a way that it is no longer compatible with
the swapchain, and further presentation requests using the swapchain
will fail. Applications must query the new surface properties and
recreate their swapchain if they wish to continue presenting to the
surface.
VK_ERROR_INCOMPATIBLE_DISPLAY_KHR
The display used by a swapchain does not use the same presentable image
layout, or is incompatible in a way that prevents sharing an image.
If a command returns a run time error, it will leave any result pointers unmodified, unless other behavior is explicitly defined in the specification.
Out of memory errors do not damage any currently existing Vulkan objects. Objects that have already been successfully created can still be used by the application.
Performance-critical commands generally do not have return codes. If a run
time error occurs in such commands, the implementation will defer reporting
the error until a specified point. For commands that record into
command buffers (vkCmd*
) run time errors are reported by
vkEndCommandBuffer
.