Vulkan Validation Overview

The purpose of this section is to give a full overview of how Vulkan deals with valid usage of the API.

Valid Usage (VU)

A VU is explicitly defined in the Vulkan Spec as:

set of conditions that must be met in order to achieve well-defined run-time behavior in an application.

One of the main advantages of Vulkan, as an explicit API, is that the implementation (driver) doesn’t waste time checking for valid input. In OpenGL, the implementation would have to always check for valid usage which added noticeable overhead. There is no glGetError equivalent in Vulkan.

The valid usages will be listed in the spec after every function and structure. For example, if a VUID checks for an invalid VkImage at VkBindImageMemory then the valid usage in the spec is found under VkBindImageMemory. This is because the Validation Layers will only know about all the information at VkBindImageMemory during the execution of the application.

Undefined Behavior

When an application supplies invalid input, according to the valid usages in the spec, the result is undefined behavior. In this state, Vulkan makes no guarantees as anything is possible with undefined behavior.

VERY IMPORTANT: While undefined behavior might seem to work on one implementation, there is a good chance it will fail on another.

Undefined Value

There are few spots that will be undefined value. These are situation where it is not invalid to do something, but the value returned from the hardware might be garbage. Imagine the following code

int x;
print(x)

It will never crash, but the value can be anything and relying on the undefined value to be something like 0 is dangerous.

Valid Usage ID (VUID)

A VUID is an unique ID given to each valid usage. This allows a way to point to a valid usage in the spec easily.

Using VUID-vkBindImageMemory-memoryOffset-01046 as an example, it is as simple as adding the VUID to an anchor in the HTML version of the spec (vkspec.html#VUID-vkBindImageMemory-memoryOffset-01046) and it will jump right to the VUID.

Implicit vs Explicit

Implicit Validation is the validation that is generated from the vk.xml. It will be the "obvious" things such as "`device` must be a valid VkDevice handle".

Explicit Validation are the handwritten VUs found everywhere else

Simple way to detect which is which is by looking for a number in the VUID

  • VUID-vkBindImageMemory-image-01044 is explicit

  • VUID-vkBindImageMemory-memory-parameter is implicit

Khronos Validation Layer

Since Vulkan doesn’t do any error checking, it is very important, when developing, to enable the Validation Layers right away to help catch invalid behavior. Applications should also never ship the Validation Layers with their application as they noticeably reduce performance and are designed for the development phase.

The Khronos Validation Layer used to consist of multiple layers but now has been unified to a single VK_LAYER_KHRONOS_validation layer. More details explained in LunarG’s whitepaper.

Getting Validation Layers

The Validation Layers are constantly being updated and improved so it is always possible to grab the source and build it yourself. In case you want a prebuilt version there are various options for all supported platforms:

  • Android - Binaries are released on GitHub with most up to date version. The NDK will also comes with the Validation Layers built and information on how to use them.

  • Linux - The Vulkan SDK comes with the Validation Layers built and instructions on how to use them on Linux.

  • MacOS - The Vulkan SDK comes with the Validation Layers built and instructions on how to use them on MacOS.

  • Windows - The Vulkan SDK comes with the Validation Layers built and instructions on how to use them on Windows.

Breaking Down a Validation Error Message

This information can be found in the Validation Layers documentation.

Special Usage Tags

The Best Practices layer will produce warnings when an application tries to use any extension with special usage tags. An example of such an extension is VK_EXT_transform_feedback which is only designed for emulation layers. If an application’s intended usage corresponds to one of the special use cases, the following approach will allow you to ignore the warnings.

Ignoring Special Usage Warnings with VK_EXT_debug_report

VkBool32 DebugReportCallbackEXT(/* ... */ const char* pMessage /* ... */)
{
    // If pMessage contains "specialuse-extension", then exit
    if(strstr(pMessage, "specialuse-extension") != NULL) {
        return VK_FALSE;
    }

    // Handle remaining validation messages
}

Ignoring Special Usage Warnings with VK_EXT_debug_utils

VkBool32 DebugUtilsMessengerCallbackEXT(/* ... */ const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData /* ... */)
{
    // If pMessageIdName contains "specialuse-extension", then exit
    if(strstr(pCallbackData->pMessageIdName, "specialuse-extension") != NULL) {
        return VK_FALSE;
    }

    // Handle remaining validation messages
}