Class EXTDebugUtils

  • public class EXTDebugUtils
    extends java.lang.Object
    Due to the nature of the Vulkan interface, there is very little error information available to the developer and application. By using the VK_EXT_debug_utils extension, developers can obtain more information. When combined with validation layers, even more detailed feedback on the application's use of Vulkan will be provided.

    This extension provides the following capabilities:

    • The ability to create a debug messenger which will pass along debug messages to an application supplied callback.
    • The ability to identify specific Vulkan objects using a name or tag to improve tracking.
    • The ability to identify specific sections within a VkQueue or VkCommandBuffer using labels to aid organization and offline analysis in external tools.

    The main difference between this extension and VK_EXT_debug_report and VK_EXT_debug_marker is that those extensions use VkDebugReportObjectTypeEXT to identify objects. This extension uses the core VkObjectType in place of VkDebugReportObjectTypeEXT. The primary reason for this move is that no future object type handle enumeration values will be added to VkDebugReportObjectTypeEXT since the creation of VkObjectType.

    In addition, this extension combines the functionality of both VK_EXT_debug_report and VK_EXT_debug_marker by allowing object name and debug markers (now called labels) to be returned to the application's callback function. This should assist in clarifying the details of a debug message including: what objects are involved and potentially which location within a VkQueue or VkCommandBuffer the message occurred.


    Example 1

    VK_EXT_debug_utils allows an application to register multiple callbacks with any Vulkan component wishing to report debug information. Some callbacks may log the information to a file, others may cause a debug break point or other application defined behavior. An application can register callbacks even when no validation layers are enabled, but they will only be called for loader and, if implemented, driver events.

    To capture events that occur while creating or destroying an instance an application can link a VkDebugUtilsMessengerCreateInfoEXT structure to the pNext element of the VkInstanceCreateInfo structure given to CreateInstance. This callback is only valid for the duration of the CreateInstance and the DestroyInstance call. Use CreateDebugUtilsMessengerEXT to create persistent callback objects.

    Example uses: Create three callback objects. One will log errors and warnings to the debug console using Windows OutputDebugString. The second will cause the debugger to break at that callback when an error happens and the third will log warnings to stdout.

         extern VkInstance instance;
         VkResult res;
         VkDebugUtilsMessengerEXT cb1, cb2, cb3;
         // Must call extension functions through a function pointer:
         PFN_vkCreateDebugUtilsMessengerEXT pfnCreateDebugUtilsMessengerEXT = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetDeviceProcAddr(device, "vkCreateDebugUtilsMessengerEXT");
         PFN_vkDestroyDebugUtilsMessengerEXT pfnDestroyDebugUtilsMessengerEXT = (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetDeviceProcAddr(device, "vkDestroyDebugUtilsMessengerEXT");
         VkDebugUtilsMessengeCreateInfoEXT callback1 = {
                 NULL,                                                     // pNext
                 0,                                                        // flags
                 VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT |           // messageSeverity
                 VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |             // messageType
                 myOutputDebugString,                                      // pfnUserCallback
                 NULL                                                      // pUserData
         res = pfnCreateDebugUtilsMessengerEXT(instance, &callback1, NULL, &cb1);
         if (res != VK_SUCCESS) {
            // Do error handling for VK_ERROR_OUT_OF_MEMORY
         callback1.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
         callback1.pfnCallback = myDebugBreak;
         callback1.pUserData = NULL;
         res = pfnCreateDebugUtilsMessengerEXT(instance, &callback1, NULL, &cb2);
         if (res != VK_SUCCESS) {
            // Do error handling for VK_ERROR_OUT_OF_MEMORY
         VkDebugUtilsMessengerCreateInfoEXT callback3 = {
                 NULL,                                                     // pNext
                 0,                                                        // flags
                 VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT,          // messageSeverity
                 VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |             // messageType
                 mystdOutLogger,                                           // pfnUserCallback
                 NULL                                                      // pUserData
         res = pfnCreateDebugUtilsMessengerEXT(instance, &callback3, NULL, &cb3);
         if (res != VK_SUCCESS) {
            // Do error handling for VK_ERROR_OUT_OF_MEMORY
         // Remove callbacks when cleaning up
         pfnDestroyDebugUtilsMessengerEXT(instance, cb1, NULL);
         pfnDestroyDebugUtilsMessengerEXT(instance, cb2, NULL);
         pfnDestroyDebugUtilsMessengerEXT(instance, cb3, NULL);

    Example 2

    Associate a name with an image, for easier debugging in external tools or with validation layers that can print a friendly name when referring to objects in error messages.

         extern VkDevice device;
         extern VkImage image;
         // Must call extension functions through a function pointer:
         PFN_vkSetDebugUtilsObjectNameEXT pfnSetDebugUtilsObjectNameEXT = (PFN_vkSetDebugUtilsObjectNameEXT)vkGetDeviceProcAddr(device, "vkSetDebugUtilsObjectNameEXT");
         // Set a name on the image
         const VkDebugUtilsObjectNameInfoEXT imageNameInfo =
             NULL,                                               // pNext
             VK_OBJECT_TYPE_IMAGE,                               // objectType
             (uint64_t)image,                                    // object
             "Brick Diffuse Texture",                            // pObjectName
         pfnSetDebugUtilsObjectNameEXT(device, &imageNameInfo);
         // A subsequent error might print:
         //   Image 'Brick Diffuse Texture' (0xc0dec0dedeadbeef) is used in a
         //   command buffer with no memory bound to it.

    Example 3

    Annotating regions of a workload with naming information so that offline analysis tools can display a more usable visualization of the commands submitted.

         extern VkDevice device;
         extern VkCommandBuffer commandBuffer;
         // Must call extension functions through a function pointer:
         PFN_vkQueueBeginDebugUtilsLabelEXT pfnQueueBeginDebugUtilsLabelEXT = (PFN_vkQueueBeginDebugUtilsLabelEXT)vkGetDeviceProcAddr(device, "vkQueueBeginDebugUtilsLabelEXT");
         PFN_vkQueueEndDebugUtilsLabelEXT pfnQueueEndDebugUtilsLabelEXT = (PFN_vkQueueEndDebugUtilsLabelEXT)vkGetDeviceProcAddr(device, "vkQueueEndDebugUtilsLabelEXT");
         PFN_vkCmdBeginDebugUtilsLabelEXT pfnCmdBeginDebugUtilsLabelEXT = (PFN_vkCmdBeginDebugUtilsLabelEXT)vkGetDeviceProcAddr(device, "vkCmdBeginDebugUtilsLabelEXT");
         PFN_vkCmdEndDebugUtilsLabelEXT pfnCmdEndDebugUtilsLabelEXT = (PFN_vkCmdEndDebugUtilsLabelEXT)vkGetDeviceProcAddr(device, "vkCmdEndDebugUtilsLabelEXT");
         PFN_vkCmdInsertDebugUtilsLabelEXT pfnCmdInsertDebugUtilsLabelEXT = (PFN_vkCmdInsertDebugUtilsLabelEXT)vkGetDeviceProcAddr(device, "vkCmdInsertDebugUtilsLabelEXT");
         // Describe the area being rendered
         const VkDebugUtilsLabelEXT houseLabel =
             NULL,                                    // pNext
             "Brick House",                           // pLabelName
             { 1.0f, 0.0f, 0.0f, 1.0f },              // color
         // Start an annotated group of calls under the 'Brick House' name
         pfnCmdBeginDebugUtilsLabelEXT(commandBuffer, &houseLabel);
             // A mutable structure for each part being rendered
             VkDebugUtilsLabelEXT housePartLabel =
                 NULL,                                    // pNext
                 NULL,                                    // pLabelName
                 { 0.0f, 0.0f, 0.0f, 0.0f },              // color
             // Set the name and insert the marker
             housePartLabel.pLabelName = "Walls";
             pfnCmdInsertDebugUtilsLabelEXT(commandBuffer, &housePartLabel);
             // Insert the drawcall for the walls
             vkCmdDrawIndexed(commandBuffer, 1000, 1, 0, 0, 0);
             // Insert a recursive region for two sets of windows
             housePartLabel.pLabelName = "Windows";
             pfnCmdBeginDebugUtilsLabelEXT(commandBuffer, &housePartLabel);
                 vkCmdDrawIndexed(commandBuffer, 75, 6, 1000, 0, 0);
                 vkCmdDrawIndexed(commandBuffer, 100, 2, 1450, 0, 0);
             housePartLabel.pLabelName = "Front Door";
             pfnCmdInsertDebugUtilsLabelEXT(commandBuffer, &housePartLabel);
             vkCmdDrawIndexed(commandBuffer, 350, 1, 1650, 0, 0);
             housePartLabel.pLabelName = "Roof";
             pfnCmdInsertDebugUtilsLabelEXT(commandBuffer, &housePartLabel);
             vkCmdDrawIndexed(commandBuffer, 500, 1, 2000, 0, 0);
         // End the house annotation started above
         // Do other work
         // Describe the queue being used
         const VkDebugUtilsLabelEXT queueLabel =
             NULL,                                    // pNext
             "Main Render Work",                      // pLabelName
             { 0.0f, 1.0f, 0.0f, 1.0f },              // color
         // Identify the queue label region
         pfnQueueBeginDebugUtilsLabelEXT(queue, &queueLabel);
         // Submit the work for the main render thread
         const VkCommandBuffer cmd_bufs[] = {commandBuffer};
         VkSubmitInfo submit_info = {.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
                                     .pNext = NULL,
                                     .waitSemaphoreCount = 0,
                                     .pWaitSemaphores = NULL,
                                     .pWaitDstStageMask = NULL,
                                     .commandBufferCount = 1,
                                     .pCommandBuffers = cmd_bufs,
                                     .signalSemaphoreCount = 0,
                                     .pSignalSemaphores = NULL};
         vkQueueSubmit(queue, 1, &submit_info, fence);
         // End the queue label region
    Name String
    Extension Type
    Instance extension
    Registered Extension Number
    Extension and Version Dependencies
    • Requires Vulkan 1.0
    Last Modified Date
    IP Status
    No known IP claims.
    • This extension is written against version 1.0 of the Vulkan API.
    • Requires VkObjectType
    • Mark Young, LunarG
    • Baldur Karlsson
    • Ian Elliott, Google
    • Courtney Goeltzenleuchter, Google
    • Karl Schultz, LunarG
    • Mark Lobodzinski, LunarG
    • Mike Schuchardt, LunarG
    • Jaakko Konttinen, AMD
    • Dan Ginsburg, Valve Software
    • Rolando Olivares, Epic Games
    • Dan Baker, Oxide Games
    • Kyle Spagnoli, NVIDIA
    • Jon Ashburn, LunarG