Note: This is written for the 1.4.309 SDK and afterwards, the older versions of the Validation Layers will be slightly different
When an error message is found, the Validation Layers use the “debug callback” mechanism (PFN_vkDebugUtilsMessengerCallbackEXT) to report the error message.
There are 2 options
By default, the Validation Layers will format the VkDebugUtilsMessengerCallbackDataEXT struct for you and print to the following to the OS-dependent standard output (stdout, logcat, OutputDebugString, etc):
Validation Error: [ VUID-vkCmdSetScissor-firstScissor-00593 ] | MessageID = 0x603fac6b
vkCmdSetScissor(): firstScissor is 1 but the multiViewport feature was not enabled.
The Vulkan spec states: If the multiViewport feature is not enabled, firstScissor must be 0 (https://docs.vulkan.org/spec/latest/chapters/fragops.html#VUID-vkCmdSetScissor-firstScissor-00593)
Objects: 1 [0] VkCommandBuffer 0x5c11921d2d10
(new line)
Here we see a few things, listed in the order they appear
For those who want to handle the callback to format the message the way they want, here is how the VkDebugUtilsMessengerCallbackDataEXT is laid out
// VkDebugUtilsMessengerCallbackDataEXT const char* pMessageIdName; // VUID int32_t messageIdNumber; // Hash of the VUID const char* pMessage; // The "main message" (includes the spec text on seperate line) // Debug Objects that Validaiton will print for you in a default callback uint32_t queueLabelCount; const VkDebugUtilsLabelEXT* pQueueLabels; uint32_t cmdBufLabelCount; const VkDebugUtilsLabelEXT* pCmdBufLabels; uint32_t objectCount; const VkDebugUtilsObjectNameInfoEXT* pObjects;
The following is an example of how one could do their custom callback
VkBool32 DebugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT message_severity, VkDebugUtilsMessageTypeFlagsEXT message_type, const VkDebugUtilsMessengerCallbackDataEXT *callback_data) { // Other layers might also be trying to report via the callback, so can filter using the type bool is_validation = messageType & VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT; // Only report Errors and Warnings bool is_error = messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; bool is_warning = messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT; if (is_error || is_warning) { std::cout << "Validation " << (is_error ? "Error:" : "Warning:"); std::cout << " [ " << pCallbackData->pMessageIdName << " ]\n"; std::cout << pCallbackData->pMessage; for (uint32_t i = 0; i < pCallbackData->objectCount; i++) { std::cout << '\n'; if (pCallbackData->pObjects[i].objectHandle) { std::cout << " Object Handle [" << i << "] = " << " 0x" << std::hex << pCallbackData->pObjects[i].objectHandle; } if (pCallbackData->pObjects[i].pObjectName) { std::cout << "[" << pCallbackData->pObjects[i].pObjectName << "]"; } } } std::cout << '\n'; // Return false to move on and still call the function to the driver return VK_FALSE; // Return true to have validation skip passing down the call to the driver return VK_TRUE; };
For those who want something more machine readable, or don't want to deal with regex parsing, there is an option to output the error in JSON.
The string returned in VkDebugUtilsMessengerCallbackDataEXT::pMessage will be a valid JSON object.
The JSON schema:
All fields are always printed, an empty string will be given if no value is provided
{ "Severity" : "string", "VUID" : "string", "Objects" : [ {"type" : "string", "handle" : "string", "name" : "string"}, ... ], "MessageID" : "string", "Function" : "string", "Location" : "string", "MainMessage" : "string", // Newline '\n' will be inlined here "DebugRegion" : "string", "SpecText" : "string", "SpecUrl" : "string" }
Here is an example of what it looks like
{ "Severity" : "Error", "VUID" : "VUID-vkCmdSetScissor-x-00595", "Objects" : [ {"type" : "VkCommandBuffer", "handle" : "0x618497491590", "name" : "command_buffer_name"}, ], "MessageID" : "0xa54a6ff8", "Function" : "vkCmdSetScissor", "Location" : "pScissors[0].offset.x", "MainMessage" : "(-1) is negative.", "DebugRegion" : "", "SpecText" : "The x and y members of offset member of any element of pScissors must be greater than or equal to 0", "SpecUrl" : "https://docs.vulkan.org/spec/latest/chapters/fragops.html#VUID-vkCmdSetScissor-x-00595" }
On Android, we will print it all in a single line to work better with
logcat.
To try it out, use vkconfig or set with
# Windows set VK_VALIDATION_MESSAGE_FORMAT_JSON=1 # Linux export VK_VALIDATION_MESSAGE_FORMAT_JSON=1 # Android adb shell setprop debug.vulkan.khronos_validation.message_format_json=1
By default the validation layers will try to print the error message out to OutputDebugString on Windows, logcat on Android, and stdout for Linux/MacOS.
You have the option to have the files write out to a file as well.
To try it out, use vkconfig or set with
# Windows set VK_LAYER_DEBUG_ACTION=VK_DBG_LAYER_ACTION_LOG_MSG set VK_LAYER_LOG_FILENAME=C:\vvl_errors.txt # Linux export VK_LAYER_DEBUG_ACTION=VK_DBG_LAYER_ACTION_LOG_MSG export VK_LAYER_LOG_FILENAME=/tmp/vvl_errors.txt # Android adb shell setprop debug.vulkan.khronos_validation.debug_action=VK_DBG_LAYER_ACTION_LOG_MSG adb shell setprop debug.vulkan.khronos_validation.log_filename=/data/local/tmp/vvl_errors.txt
Synchronization validation detects memory hazards and has custom error conventions. Additional information about SyncVal errors can be found in the Synchronization Validation Messages document.