• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2017-2022 The Khronos Group Inc.
2//
3// SPDX-License-Identifier: CC-BY-4.0
4
5include::{generated}/meta/{refprefix}VK_EXT_debug_utils.adoc[]
6
7=== Other Extension Metadata
8
9*Last Modified Date*::
10    2020-04-03
11*Revision*::
12    2
13*IP Status*::
14    No known IP claims.
15*Dependencies*::
16  - This extension is written against version 1.0 of the Vulkan API.
17  - Requires elink:VkObjectType
18*Contributors*::
19  - Mark Young, LunarG
20  - Baldur Karlsson
21  - Ian Elliott, Google
22  - Courtney Goeltzenleuchter, Google
23  - Karl Schultz, LunarG
24  - Mark Lobodzinski, LunarG
25  - Mike Schuchardt, LunarG
26  - Jaakko Konttinen, AMD
27  - Dan Ginsburg, Valve Software
28  - Rolando Olivares, Epic Games
29  - Dan Baker, Oxide Games
30  - Kyle Spagnoli, NVIDIA
31  - Jon Ashburn, LunarG
32  - Piers Daniell, NVIDIA
33
34=== Description
35
36Due to the nature of the Vulkan interface, there is very little error
37information available to the developer and application.
38By using the `VK_EXT_debug_utils` extension, developers can: obtain more
39information.
40When combined with validation layers, even more detailed feedback on the
41application's use of Vulkan will be provided.
42
43This extension provides the following capabilities:
44
45  - The ability to create a debug messenger which will pass along debug
46    messages to an application supplied callback.
47  - The ability to identify specific Vulkan objects using a name or tag to
48    improve tracking.
49  - The ability to identify specific sections within a sname:VkQueue or
50    sname:VkCommandBuffer using labels to aid organization and offline
51    analysis in external tools.
52
53The main difference between this extension and `apiext:VK_EXT_debug_report`
54and `apiext:VK_EXT_debug_marker` is that those extensions use
55elink:VkDebugReportObjectTypeEXT to identify objects.
56This extension uses the core elink:VkObjectType in place of
57elink:VkDebugReportObjectTypeEXT.
58The primary reason for this move is that no future object type handle
59enumeration values will be added to elink:VkDebugReportObjectTypeEXT since
60the creation of elink:VkObjectType.
61
62In addition, this extension combines the functionality of both
63`apiext:VK_EXT_debug_report` and `apiext:VK_EXT_debug_marker` by allowing
64object name and debug markers (now called labels) to be returned to the
65application's callback function.
66This should assist in clarifying the details of a debug message including:
67what objects are involved and potentially which location within a
68slink:VkQueue or slink:VkCommandBuffer the message occurred.
69
70include::{generated}/interfaces/VK_EXT_debug_utils.adoc[]
71
72=== Examples
73
74*Example 1*
75
76`VK_EXT_debug_utils` allows an application to register multiple callbacks
77with any Vulkan component wishing to report debug information.
78Some callbacks may log the information to a file, others may cause a debug
79break point or other application defined behavior.
80An application can: register callbacks even when no validation layers are
81enabled, but they will only be called for loader and, if implemented, driver
82events.
83
84To capture events that occur while creating or destroying an instance an
85application can: link a slink:VkDebugUtilsMessengerCreateInfoEXT structure
86to the pname:pNext element of the slink:VkInstanceCreateInfo structure given
87to flink:vkCreateInstance.
88
89Example uses: Create three callback objects.
90One will log errors and warnings to the debug console using Windows
91code:OutputDebugString.
92The second will cause the debugger to break at that callback when an error
93happens and the third will log warnings to stdout.
94[source,c++]
95------------------------------------------------------------------------------
96    extern VkInstance instance;
97    VkResult res;
98    VkDebugUtilsMessengerEXT cb1, cb2, cb3;
99
100    // Must call extension functions through a function pointer:
101    PFN_vkCreateDebugUtilsMessengerEXT pfnCreateDebugUtilsMessengerEXT = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT");
102    PFN_vkDestroyDebugUtilsMessengerEXT pfnDestroyDebugUtilsMessengerEXT = (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT");
103
104    VkDebugUtilsMessengerCreateInfoEXT callback1 = {
105            VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,  // sType
106            NULL,                                                     // pNext
107            0,                                                        // flags
108            VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT |           // messageSeverity
109            VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT,
110            VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |             // messageType
111            VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT,
112            myOutputDebugString,                                      // pfnUserCallback
113            NULL                                                      // pUserData
114    };
115    res = pfnCreateDebugUtilsMessengerEXT(instance, &callback1, NULL, &cb1);
116    if (res != VK_SUCCESS) {
117       // Do error handling for VK_ERROR_OUT_OF_MEMORY
118    }
119
120    callback1.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
121    callback1.pfnUserCallback = myDebugBreak;
122    callback1.pUserData = NULL;
123    res = pfnCreateDebugUtilsMessengerEXT(instance, &callback1, NULL, &cb2);
124    if (res != VK_SUCCESS) {
125       // Do error handling for VK_ERROR_OUT_OF_MEMORY
126    }
127
128    VkDebugUtilsMessengerCreateInfoEXT callback3 = {
129            VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,  // sType
130            NULL,                                                     // pNext
131            0,                                                        // flags
132            VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT,          // messageSeverity
133            VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |             // messageType
134            VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT,
135            mystdOutLogger,                                           // pfnUserCallback
136            NULL                                                      // pUserData
137    };
138    res = pfnCreateDebugUtilsMessengerEXT(instance, &callback3, NULL, &cb3);
139    if (res != VK_SUCCESS) {
140       // Do error handling for VK_ERROR_OUT_OF_MEMORY
141    }
142
143    ...
144
145    // Remove callbacks when cleaning up
146    pfnDestroyDebugUtilsMessengerEXT(instance, cb1, NULL);
147    pfnDestroyDebugUtilsMessengerEXT(instance, cb2, NULL);
148    pfnDestroyDebugUtilsMessengerEXT(instance, cb3, NULL);
149------------------------------------------------------------------------------
150
151*Example 2*
152
153Associate a name with an image, for easier debugging in external tools or
154with validation layers that can print a friendly name when referring to
155objects in error messages.
156
157[source,c++]
158----------------------------------------
159    extern VkInstance instance;
160    extern VkDevice device;
161    extern VkImage image;
162
163    // Must call extension functions through a function pointer:
164    PFN_vkSetDebugUtilsObjectNameEXT pfnSetDebugUtilsObjectNameEXT = (PFN_vkSetDebugUtilsObjectNameEXT)vkGetInstanceProcAddr(instance, "vkSetDebugUtilsObjectNameEXT");
165
166    // Set a name on the image
167    const VkDebugUtilsObjectNameInfoEXT imageNameInfo =
168    {
169        VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, // sType
170        NULL,                                               // pNext
171        VK_OBJECT_TYPE_IMAGE,                               // objectType
172        (uint64_t)image,                                    // objectHandle
173        "Brick Diffuse Texture",                            // pObjectName
174    };
175
176    pfnSetDebugUtilsObjectNameEXT(device, &imageNameInfo);
177
178    // A subsequent error might print:
179    //   Image 'Brick Diffuse Texture' (0xc0dec0dedeadbeef) is used in a
180    //   command buffer with no memory bound to it.
181----------------------------------------
182
183*Example 3*
184
185Annotating regions of a workload with naming information so that offline
186analysis tools can display a more usable visualization of the commands
187submitted.
188
189[source,c++]
190----------------------------------------
191    extern VkInstance instance;
192    extern VkCommandBuffer commandBuffer;
193
194    // Must call extension functions through a function pointer:
195    PFN_vkQueueBeginDebugUtilsLabelEXT pfnQueueBeginDebugUtilsLabelEXT = (PFN_vkQueueBeginDebugUtilsLabelEXT)vkGetInstanceProcAddr(instance, "vkQueueBeginDebugUtilsLabelEXT");
196    PFN_vkQueueEndDebugUtilsLabelEXT pfnQueueEndDebugUtilsLabelEXT = (PFN_vkQueueEndDebugUtilsLabelEXT)vkGetInstanceProcAddr(instance, "vkQueueEndDebugUtilsLabelEXT");
197    PFN_vkCmdBeginDebugUtilsLabelEXT pfnCmdBeginDebugUtilsLabelEXT = (PFN_vkCmdBeginDebugUtilsLabelEXT)vkGetInstanceProcAddr(instance, "vkCmdBeginDebugUtilsLabelEXT");
198    PFN_vkCmdEndDebugUtilsLabelEXT pfnCmdEndDebugUtilsLabelEXT = (PFN_vkCmdEndDebugUtilsLabelEXT)vkGetInstanceProcAddr(instance, "vkCmdEndDebugUtilsLabelEXT");
199    PFN_vkCmdInsertDebugUtilsLabelEXT pfnCmdInsertDebugUtilsLabelEXT = (PFN_vkCmdInsertDebugUtilsLabelEXT)vkGetInstanceProcAddr(instance, "vkCmdInsertDebugUtilsLabelEXT");
200
201    // Describe the area being rendered
202    const VkDebugUtilsLabelEXT houseLabel =
203    {
204        VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT, // sType
205        NULL,                                    // pNext
206        "Brick House",                           // pLabelName
207        { 1.0f, 0.0f, 0.0f, 1.0f },              // color
208    };
209
210    // Start an annotated group of calls under the 'Brick House' name
211    pfnCmdBeginDebugUtilsLabelEXT(commandBuffer, &houseLabel);
212    {
213        // A mutable structure for each part being rendered
214        VkDebugUtilsLabelEXT housePartLabel =
215        {
216            VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT, // sType
217            NULL,                                    // pNext
218            NULL,                                    // pLabelName
219            { 0.0f, 0.0f, 0.0f, 0.0f },              // color
220        };
221
222        // Set the name and insert the marker
223        housePartLabel.pLabelName = "Walls";
224        pfnCmdInsertDebugUtilsLabelEXT(commandBuffer, &housePartLabel);
225
226        // Insert the drawcall for the walls
227        vkCmdDrawIndexed(commandBuffer, 1000, 1, 0, 0, 0);
228
229        // Insert a recursive region for two sets of windows
230        housePartLabel.pLabelName = "Windows";
231        pfnCmdBeginDebugUtilsLabelEXT(commandBuffer, &housePartLabel);
232        {
233            vkCmdDrawIndexed(commandBuffer, 75, 6, 1000, 0, 0);
234            vkCmdDrawIndexed(commandBuffer, 100, 2, 1450, 0, 0);
235        }
236        pfnCmdEndDebugUtilsLabelEXT(commandBuffer);
237
238        housePartLabel.pLabelName = "Front Door";
239        pfnCmdInsertDebugUtilsLabelEXT(commandBuffer, &housePartLabel);
240
241        vkCmdDrawIndexed(commandBuffer, 350, 1, 1650, 0, 0);
242
243        housePartLabel.pLabelName = "Roof";
244        pfnCmdInsertDebugUtilsLabelEXT(commandBuffer, &housePartLabel);
245
246        vkCmdDrawIndexed(commandBuffer, 500, 1, 2000, 0, 0);
247    }
248    // End the house annotation started above
249    pfnCmdEndDebugUtilsLabelEXT(commandBuffer);
250
251    // Do other work
252
253    vkEndCommandBuffer(commandBuffer);
254
255    // Describe the queue being used
256    const VkDebugUtilsLabelEXT queueLabel =
257    {
258        VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT, // sType
259        NULL,                                    // pNext
260        "Main Render Work",                      // pLabelName
261        { 0.0f, 1.0f, 0.0f, 1.0f },              // color
262    };
263
264    // Identify the queue label region
265    pfnQueueBeginDebugUtilsLabelEXT(queue, &queueLabel);
266
267    // Submit the work for the main render thread
268    const VkCommandBuffer cmd_bufs[] = {commandBuffer};
269    VkSubmitInfo submit_info = {.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
270                                .pNext = NULL,
271                                .waitSemaphoreCount = 0,
272                                .pWaitSemaphores = NULL,
273                                .pWaitDstStageMask = NULL,
274                                .commandBufferCount = 1,
275                                .pCommandBuffers = cmd_bufs,
276                                .signalSemaphoreCount = 0,
277                                .pSignalSemaphores = NULL};
278    vkQueueSubmit(queue, 1, &submit_info, fence);
279
280    // End the queue label region
281    pfnQueueEndDebugUtilsLabelEXT(queue);
282
283----------------------------------------
284
285=== Issues
286
2871) Should we just name this extension `VK_EXT_debug_report2`
288
289*RESOLVED*: No.
290There is enough additional changes to the structures to break backwards
291compatibility.
292So, a new name was decided that would not indicate any interaction with the
293previous extension.
294
2952) Will validation layers immediately support all the new features.
296
297*RESOLVED*: Not immediately.
298As one can imagine, there is a lot of work involved with converting the
299validation layer logging over to the new functionality.
300Basic logging, as seen in the origin `apiext:VK_EXT_debug_report` extension
301will be made available immediately.
302However, adding the labels and object names will take time.
303Since the priority for Khronos at this time is to continue focusing on Valid
304Usage statements, it may take a while before the new functionality is fully
305exposed.
306
3073) If the validation layers will not expose the new functionality
308immediately, then what is the point of this extension?
309
310*RESOLVED*: We needed a replacement for `apiext:VK_EXT_debug_report` because
311the elink:VkDebugReportObjectTypeEXT enumeration will no longer be updated
312and any new objects will need to be debugged using the new functionality
313provided by this extension.
314
3154) Should this extension be split into two separate parts (1 extension that
316is an instance extension providing the callback functionality, and another
317device extension providing the general debug marker and annotation
318functionality)?
319
320*RESOLVED*: No, the functionality for this extension is too closely related.
321If we did split up the extension, where would the structures and enums live,
322and how would you define that the device behavior in the instance extension
323is really only valid if the device extension is enabled, and the
324functionality is passed in.
325It is cleaner to just define this all as an instance extension, plus it
326allows the application to enable all debug functionality provided with one
327enable string during flink:vkCreateInstance.
328
329=== Version History
330
331  * Revision 1, 2017-09-14 (Mark Young and all listed Contributors)
332  ** Initial draft, based on `apiext:VK_EXT_debug_report` and
333     `apiext:VK_EXT_debug_marker` in addition to previous feedback supplied
334     from various companies including Valve, Epic, and Oxide games.
335  * Revision 2, 2020-04-03 (Mark Young and Piers Daniell)
336  ** Updated to allow either `NULL` or an empty string to be passed in for
337     pname:pObjectName in sname:VkDebugUtilsObjectNameInfoEXT, because the
338     loader and various drivers support `NULL` already.
339