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