When a Vulkan application tries to access (load, store, or perform an atomic on) memory it doesn’t have access to, the implementation must react somehow. In the case where there is no robustness, it is undefined behavior and the implementation is even allowed to terminate the program. If robustness is enabled for the type of memory accessed, then the implementation must behave a certain way as defined by the spec.
The nature of some Vulkan applications requires the ability run shader code that cannot be guaranteed to avoid bad memory accesses. Robustness is needed for these applications.
Turning on robustness may incur a runtime performance cost. Application writers should carefully consider the implications of enabling robustness.
All Vulkan implementations are required to support the
robustBufferAccess feature. The spec describes what is considered out-of-bounds and also how it should be handled. Implementations are given some amount of flexibility for
robustBufferAccess. An example would be accessing a
vec4(x,y,z,w) where the
w value is out-of-bounds as the spec allows the implementation to decide if the
z are also considered out-of-bounds or not.
If dealing with the update after bind functionality found in
VK_EXT_descriptor_indexing (which is core as of Vulkan 1.2) it is important to be aware of the robustBufferAccessUpdateAfterBind which indicates if an implementation can support both
robustBufferAccess and the ability to update the descriptor after binding it.
robustBufferAccess feature has some limitations as it only covers buffers and not images. It also allows out-of-bounds writes and atomics to modify the data of the buffer being accessed. For applications looking for a stronger form of robustness, there is VK_EXT_robustness2.
When images are out-of-bounds core Vulkan provides the guarantee that stores and atomics have no effect on the memory being accessed.
The robustImageAccess feature in VK_EXT_image_robustness enables out-of-bounds checking against the dimensions of the image view being accessed. If there is an out-of-bounds access to any image it will return
(0, 0, 0, 0) or
(0, 0, 0, 1).
robustImageAccess feature provides no guarantees about the values returned for access to an invalid LOD, it is still undefined behavior.
Some applications, such as those being ported from other APIs such as D3D12, require stricter guarantees than
robustImageAccess provide. The VK_EXT_robustness2 extension adds this by exposing 3 new robustness features, described in the following sections. For some implementations these extra guarantees can come at a performance cost. Applications that don’t need the extra robustness are recommended to use
robustImageAccess instead where possible.
The robustBufferAccess2 feature can be seen as a superset of
With the feature enabled, it prevents all out-of-bounds writes and atomic from modifying any memory backing buffers. The
robustBufferAccess2 feature also enforces the values that must be returned for the various types of buffers when accessed out-of-bounds as described in the spec.
It is important to query the
robustStorageBufferAccessSizeAlignment from VkPhysicalDeviceRobustness2PropertiesEXT as the alignment of where buffers are bound-checked is different between implementations.
The robustImageAccess2 feature can be seen as a superset of
robustImageAccess. It builds on the out-of-bounds checking against the dimensions of the image view being accessed, adding stricter requirements on which values may be returned.
robustImageAccess2 an out-of-bounds access to an R, RG, or RGB format will return
(0, 0, 0, 1). For an RGBA format, such as
VK_FORMAT_R8G8B8A8_UNORM, it will return
(0, 0, 0, 0).
For the case of accessing an image LOD outside the supported range, with
robustImageAccess2 enabled, it will be considered out of bounds.
Without the nullDescriptor feature enabled, when updating a
VkDescriptorSet, all the resources backing it must be non-null, even if the descriptor is statically not used by the shader. This feature allows descriptors to be backed by null resources or views. Loads from a null descriptor return zero values and stores and atomics to a null descriptor are discarded.
nullDescriptor feature also allows accesses to vertex input bindings where
vkCmdBindVertexBuffers::pBuffers is null.
Because robustness can come at a performance cost for some implementations, the VK_EXT_pipeline_robustness extension was added to allow developers to request robustness only where needed.
VkPipeline creation time one or more
VkPipelineRobustnessCreateInfoEXT structures can be passed to specify the desired robustness behavior of accesses to buffer, image, and vertex input resources, either for the pipeline as a whole or on a per-pipeline-stage basis.
This extension also provides
VkPhysicalDevicePipelineRobustnessPropertiesEXT which queries the implementation for what behavior it provides as default when no robustness features are enabled.