blob: 90ebabd6196fac1e3a405c446cd74dcb5f931eae [file] [log] [blame]
Mark Young6ba8abe2017-11-09 10:37:04 -07001/* Copyright (c) 2015-2017 The Khronos Group Inc.
2 * Copyright (c) 2015-2017 Valve Corporation
3 * Copyright (c) 2015-2017 LunarG, Inc.
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -06004 *
Jon Ashburn3ebf1252016-04-19 11:30:31 -06005 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -06008 *
Jon Ashburn3ebf1252016-04-19 11:30:31 -06009 * http://www.apache.org/licenses/LICENSE-2.0
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060010 *
Jon Ashburn3ebf1252016-04-19 11:30:31 -060011 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060016 *
Courtney Goeltzenleuchter05559522015-10-30 11:14:30 -060017 * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
18 * Author: Tobin Ehlis <tobin@lunarg.com>
Mark Young6ba8abe2017-11-09 10:37:04 -070019 * Author: Mark Young <marky@lunarg.com>
Courtney Goeltzenleuchter05559522015-10-30 11:14:30 -060020 *
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060021 */
22
23#ifndef LAYER_LOGGING_H
24#define LAYER_LOGGING_H
25
Mark Lobodzinskib87f9022016-05-24 16:04:56 -060026#include "vk_loader_layer.h"
Tobin Ehlis2d9deec2016-04-21 14:19:26 -060027#include "vk_layer_config.h"
Tobin Ehlisa0cb02e2015-07-03 10:15:26 -060028#include "vk_layer_data.h"
29#include "vk_layer_table.h"
Tobin Ehlis2d9deec2016-04-21 14:19:26 -060030#include "vk_loader_platform.h"
31#include "vulkan/vk_layer.h"
Mark Young6ba8abe2017-11-09 10:37:04 -070032#include "vk_object_types.h"
Mark Lobodzinskic9d81652017-08-10 11:01:17 -060033#include <signal.h>
Karl Schultzd7f37542016-05-10 11:36:08 -060034#include <cinttypes>
Tobin Ehlis2d9deec2016-04-21 14:19:26 -060035#include <stdarg.h>
36#include <stdbool.h>
37#include <stdio.h>
38#include <unordered_map>
Mark Lobodzinski97c4d512016-05-19 15:27:18 -060039#include <vector>
Mark Young6ba8abe2017-11-09 10:37:04 -070040#include <sstream>
41#include <string>
42
43// TODO: Could be autogenerated for the specific handles for extra type safety...
44template <typename HANDLE_T>
45static inline uint64_t HandleToUint64(HANDLE_T *h) {
46 return reinterpret_cast<uint64_t>(h);
47}
48
49static inline uint64_t HandleToUint64(uint64_t h) { return h; }
50
51// Data we store per label for logging
52typedef struct _LoggingLabelData {
53 std::string name;
54 float color[4];
55} LoggingLabelData;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060056
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -060057typedef struct _debug_report_data {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -060058 VkLayerDbgFunctionNode *debug_callback_list;
59 VkLayerDbgFunctionNode *default_debug_callback_list;
Mark Young6ba8abe2017-11-09 10:37:04 -070060 VkDebugUtilsMessageSeverityFlagsEXT active_severities;
61 VkDebugUtilsMessageTypeFlagsEXT active_types;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060062 bool g_DEBUG_REPORT;
Mark Young6ba8abe2017-11-09 10:37:04 -070063 bool g_DEBUG_UTILS;
Tony Barbour3431dac2017-06-19 16:50:37 -060064 std::unordered_map<uint64_t, std::string> *debugObjectNameMap;
Mark Young6ba8abe2017-11-09 10:37:04 -070065 std::unordered_map<uint64_t, std::string> *debugUtilsObjectNameMap;
66 std::unordered_map<VkQueue, std::vector<LoggingLabelData>> *debugUtilsQueueLabels;
67 bool queueLabelHasInsert;
68 std::unordered_map<VkCommandBuffer, std::vector<LoggingLabelData>> *debugUtilsCmdBufLabels;
69 bool cmdBufLabelHasInsert;
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -060070} debug_report_data;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060071
Tobin Ehlis8d6acde2017-02-08 07:40:40 -070072template debug_report_data *GetLayerDataPtr<debug_report_data>(void *data_key,
Jon Ashburn5484e0c2016-03-08 17:48:44 -070073 std::unordered_map<void *, debug_report_data *> &data_map);
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060074
Mark Young6ba8abe2017-11-09 10:37:04 -070075static inline void DebugReportFlagsToAnnotFlags(VkDebugReportFlagsEXT dr_flags, bool default_flag_is_spec,
76 VkDebugUtilsMessageSeverityFlagsEXT *da_severity,
77 VkDebugUtilsMessageTypeFlagsEXT *da_type) {
78 // All layer warnings are spec warnings currently. At least as far as anything not specifically
79 // called out. In the future, we'll label things using the new split severity and type values.
80 *da_type = VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;
81 *da_severity = 0;
82 if ((dr_flags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) != 0) {
83 *da_severity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT;
84 *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT;
85 }
86 if ((dr_flags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) != 0) {
87 *da_severity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
88 *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT;
89 }
90 if ((dr_flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) != 0) {
91 *da_severity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
92 *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
93 }
94 if ((dr_flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) != 0) {
95 *da_severity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
96 }
97 if ((dr_flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) != 0) {
98 *da_severity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
99 }
100}
101
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600102// Forward Declarations
Mark Young6ba8abe2017-11-09 10:37:04 -0700103static inline bool debug_log_msg(const debug_report_data *debug_data, VkFlags msg_flags, VkDebugReportObjectTypeEXT object_type,
104 uint64_t src_object, size_t location, int32_t msg_code, const char *layer_prefix,
105 const char *message);
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600106
107// Add a debug message callback node structure to the specified callback linked list
Mark Young6ba8abe2017-11-09 10:37:04 -0700108static inline void AddDebugCallbackNode(debug_report_data *debug_data, VkLayerDbgFunctionNode **list_head,
109 VkLayerDbgFunctionNode *new_node) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600110 new_node->pNext = *list_head;
111 *list_head = new_node;
112}
113
Mark Young6ba8abe2017-11-09 10:37:04 -0700114// Remove specified debug messenger node structure from the specified linked list
115static inline void RemoveDebugUtilsMessenger(debug_report_data *debug_data, VkLayerDbgFunctionNode **list_head,
116 VkDebugUtilsMessengerEXT messenger) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600117 VkLayerDbgFunctionNode *cur_callback = *list_head;
118 VkLayerDbgFunctionNode *prev_callback = cur_callback;
119 bool matched = false;
Mark Young6ba8abe2017-11-09 10:37:04 -0700120 VkFlags local_severities = 0;
121 VkFlags local_types = 0;
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600122
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600123 while (cur_callback) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700124 if (cur_callback->is_messenger && cur_callback->messenger.messenger == messenger) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600125 matched = true;
126 prev_callback->pNext = cur_callback->pNext;
127 if (*list_head == cur_callback) {
128 *list_head = cur_callback->pNext;
129 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700130 debug_log_msg(debug_data, VK_DEBUG_REPORT_DEBUG_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT,
131 reinterpret_cast<uint64_t &>(cur_callback->messenger.messenger), 0, 0, "DebugUtilsMessenger",
132 "Destroyed messenger\n");
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600133 } else {
134 matched = false;
Mark Young6ba8abe2017-11-09 10:37:04 -0700135 local_severities |= cur_callback->messenger.messageSeverity;
136 local_types |= cur_callback->messenger.messageType;
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600137 }
138 prev_callback = cur_callback;
139 cur_callback = cur_callback->pNext;
140 if (matched) {
141 free(prev_callback);
142 }
143 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700144 debug_data->active_severities = local_severities;
145 debug_data->active_types = local_types;
146}
147
148// Remove specified debug message callback node structure from the specified callback linked list
149static inline void RemoveDebugUtilsMessageCallback(debug_report_data *debug_data, VkLayerDbgFunctionNode **list_head,
150 VkDebugReportCallbackEXT callback) {
151 VkLayerDbgFunctionNode *cur_callback = *list_head;
152 VkLayerDbgFunctionNode *prev_callback = cur_callback;
153 bool matched = false;
154 VkFlags local_severities = 0;
155 VkFlags local_types = 0;
156
157 while (cur_callback) {
158 if (!cur_callback->is_messenger && cur_callback->report.msgCallback == callback) {
159 matched = true;
160 prev_callback->pNext = cur_callback->pNext;
161 if (*list_head == cur_callback) {
162 *list_head = cur_callback->pNext;
163 }
164 debug_log_msg(debug_data, VK_DEBUG_REPORT_DEBUG_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT,
165 reinterpret_cast<uint64_t &>(cur_callback->report.msgCallback), 0, 0, "DebugReport",
166 "Destroyed callback\n");
167 } else {
168 matched = false;
169 VkFlags this_severities = 0;
170 VkFlags this_types = 0;
171 DebugReportFlagsToAnnotFlags(cur_callback->report.msgFlags, true, &this_severities, &this_types);
172 local_severities |= this_severities;
173 local_types |= this_types;
174 }
175 prev_callback = cur_callback;
176 cur_callback = cur_callback->pNext;
177 if (matched) {
178 free(prev_callback);
179 }
180 }
181 debug_data->active_severities = local_severities;
182 debug_data->active_types = local_types;
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600183}
184
185// Removes all debug callback function nodes from the specified callback linked lists and frees their resources
186static inline void RemoveAllMessageCallbacks(debug_report_data *debug_data, VkLayerDbgFunctionNode **list_head) {
187 VkLayerDbgFunctionNode *current_callback = *list_head;
188 VkLayerDbgFunctionNode *prev_callback = current_callback;
189
190 while (current_callback) {
191 prev_callback = current_callback->pNext;
Mark Young6ba8abe2017-11-09 10:37:04 -0700192 if (!current_callback->is_messenger) {
193 debug_log_msg(debug_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT,
194 (uint64_t)current_callback->report.msgCallback, 0, 0, "DebugReport",
195 "Debug Report callbacks not removed before DestroyInstance");
196 } else {
197 debug_log_msg(debug_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT,
198 (uint64_t)current_callback->messenger.messenger, 0, 0, "Messenger",
199 "Debug messengers not removed before DestroyInstance");
200 }
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600201 free(current_callback);
202 current_callback = prev_callback;
203 }
204 *list_head = NULL;
205}
206
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600207// Utility function to handle reporting
Mark Young6ba8abe2017-11-09 10:37:04 -0700208static inline bool debug_log_msg(const debug_report_data *debug_data, VkFlags msg_flags, VkDebugReportObjectTypeEXT object_type,
209 uint64_t src_object, size_t location, int32_t msg_code, const char *layer_prefix,
210 const char *message) {
Dustin Graves8f1eab92016-04-05 09:41:17 -0600211 bool bail = false;
Mark Young6ba8abe2017-11-09 10:37:04 -0700212 VkLayerDbgFunctionNode *layer_dbg_node = NULL;
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600213
Mark Lobodzinski55a197f2016-06-21 15:54:57 -0600214 if (debug_data->debug_callback_list != NULL) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700215 layer_dbg_node = debug_data->debug_callback_list;
Mark Lobodzinski55a197f2016-06-21 15:54:57 -0600216 } else {
Mark Young6ba8abe2017-11-09 10:37:04 -0700217 layer_dbg_node = debug_data->default_debug_callback_list;
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600218 }
219
Mark Young6ba8abe2017-11-09 10:37:04 -0700220 VkDebugUtilsMessageSeverityFlagsEXT severity;
221 VkDebugUtilsMessageTypeFlagsEXT types;
222 VkDebugUtilsMessengerCallbackDataEXT callback_data;
223 VkDebugUtilsObjectNameInfoEXT object_name_info;
224
225 // Convert the info to the VK_EXT_debug_utils form in case we need it.
226 DebugReportFlagsToAnnotFlags(msg_flags, true, &severity, &types);
227 object_name_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
228 object_name_info.pNext = NULL;
229 object_name_info.objectType = convertDebugReportObjectToCoreObject(object_type);
230 object_name_info.objectHandle = (uint64_t)(uintptr_t)src_object;
231 object_name_info.pObjectName = NULL;
232
233 callback_data.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT;
234 callback_data.pNext = NULL;
235 callback_data.flags = 0;
236 callback_data.pMessageIdName = layer_prefix;
237 callback_data.messageIdNumber = msg_code;
238 callback_data.pMessage = message;
239 callback_data.queueLabelCount = 0;
240 callback_data.pQueueLabels = NULL;
241 callback_data.cmdBufLabelCount = 0;
242 callback_data.pCmdBufLabels = NULL;
243 callback_data.objectCount = 1;
244 callback_data.pObjects = &object_name_info;
245
246 VkDebugUtilsLabelEXT *queue_labels = nullptr;
247 VkDebugUtilsLabelEXT *cmd_buf_labels = nullptr;
248 std::string new_debug_report_message = "";
249 std::ostringstream oss;
Mark Young6ba8abe2017-11-09 10:37:04 -0700250
251 if (0 != src_object) {
Mark Young8504ba62018-03-21 13:35:34 -0600252 oss << "Object: 0x" << std::hex << src_object;
Mark Young6ba8abe2017-11-09 10:37:04 -0700253 // If this is a queue, add any queue labels to the callback data.
254 if (VK_OBJECT_TYPE_QUEUE == object_name_info.objectType) {
255 auto label_iter = debug_data->debugUtilsQueueLabels->find(reinterpret_cast<VkQueue>(src_object));
256 if (label_iter != debug_data->debugUtilsQueueLabels->end()) {
257 queue_labels = new VkDebugUtilsLabelEXT[label_iter->second.size()];
258 if (nullptr != queue_labels) {
259 // Record the labels, but record them in reverse order since we want the
260 // most recent at the top.
261 uint32_t label_size = static_cast<uint32_t>(label_iter->second.size());
262 uint32_t last_index = label_size - 1;
263 for (uint32_t label = 0; label < label_size; ++label) {
264 queue_labels[last_index - label].sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
265 queue_labels[last_index - label].pNext = nullptr;
266 queue_labels[last_index - label].pLabelName = label_iter->second[label].name.c_str();
267 queue_labels[last_index - label].color[0] = label_iter->second[label].color[0];
268 queue_labels[last_index - label].color[1] = label_iter->second[label].color[1];
269 queue_labels[last_index - label].color[2] = label_iter->second[label].color[2];
270 queue_labels[last_index - label].color[3] = label_iter->second[label].color[3];
271 }
272 callback_data.queueLabelCount = label_size;
273 callback_data.pQueueLabels = queue_labels;
274 }
275 }
276 // If this is a command buffer, add any command buffer labels to the callback data.
277 } else if (VK_OBJECT_TYPE_COMMAND_BUFFER == object_name_info.objectType) {
278 auto label_iter = debug_data->debugUtilsCmdBufLabels->find(reinterpret_cast<VkCommandBuffer>(src_object));
279 if (label_iter != debug_data->debugUtilsCmdBufLabels->end()) {
280 cmd_buf_labels = new VkDebugUtilsLabelEXT[label_iter->second.size()];
281 if (nullptr != cmd_buf_labels) {
282 // Record the labels, but record them in reverse order since we want the
283 // most recent at the top.
284 uint32_t label_size = static_cast<uint32_t>(label_iter->second.size());
285 uint32_t last_index = label_size - 1;
286 for (uint32_t label = 0; label < label_size; ++label) {
287 cmd_buf_labels[last_index - label].sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
288 cmd_buf_labels[last_index - label].pNext = nullptr;
289 cmd_buf_labels[last_index - label].pLabelName = label_iter->second[label].name.c_str();
290 cmd_buf_labels[last_index - label].color[0] = label_iter->second[label].color[0];
291 cmd_buf_labels[last_index - label].color[1] = label_iter->second[label].color[1];
292 cmd_buf_labels[last_index - label].color[2] = label_iter->second[label].color[2];
293 cmd_buf_labels[last_index - label].color[3] = label_iter->second[label].color[3];
294 }
295 callback_data.cmdBufLabelCount = label_size;
296 callback_data.pCmdBufLabels = cmd_buf_labels;
297 }
298 }
299 }
300 // Look for any debug utils or marker names to use for this object
301 callback_data.pObjects[0].pObjectName = NULL;
302 auto utils_name_iter = debug_data->debugUtilsObjectNameMap->find(src_object);
303 if (utils_name_iter != debug_data->debugUtilsObjectNameMap->end()) {
304 callback_data.pObjects[0].pObjectName = utils_name_iter->second.c_str();
305 } else {
306 auto marker_name_iter = debug_data->debugObjectNameMap->find(src_object);
307 if (marker_name_iter != debug_data->debugObjectNameMap->end()) {
308 callback_data.pObjects[0].pObjectName = marker_name_iter->second.c_str();
309 }
310 }
311 if (NULL != callback_data.pObjects[0].pObjectName) {
Mark Young8504ba62018-03-21 13:35:34 -0600312 oss << " (Name = " << callback_data.pObjects[0].pObjectName << " : Type = ";
313 } else {
314 oss << " (Type = ";
Mark Young6ba8abe2017-11-09 10:37:04 -0700315 }
Mark Young8504ba62018-03-21 13:35:34 -0600316 oss << std::to_string(object_type) << ")";
317 } else {
318 oss << "Object: VK_NULL_HANDLE (Type = " << std::to_string(object_type) << ")";
Mark Young6ba8abe2017-11-09 10:37:04 -0700319 }
320 new_debug_report_message += oss.str();
321 new_debug_report_message += " | ";
322 new_debug_report_message += message;
323
324 while (layer_dbg_node) {
Mark Young8504ba62018-03-21 13:35:34 -0600325 // If the app uses the VK_EXT_debug_report extension, call all of those registered callbacks.
Mark Young6ba8abe2017-11-09 10:37:04 -0700326 if (!layer_dbg_node->is_messenger && (layer_dbg_node->report.msgFlags & msg_flags) &&
327 layer_dbg_node->report.pfnMsgCallback(msg_flags, object_type, src_object, location, msg_code, layer_prefix,
328 new_debug_report_message.c_str(), layer_dbg_node->pUserData)) {
329 bail = true;
Mark Young8504ba62018-03-21 13:35:34 -0600330 // If the app uses the VK_EXT_debug_utils extension, call all of those registered callbacks.
Mark Young6ba8abe2017-11-09 10:37:04 -0700331 } else if (layer_dbg_node->is_messenger && (layer_dbg_node->messenger.messageSeverity & severity) &&
332 (layer_dbg_node->messenger.messageType & types) &&
333 layer_dbg_node->messenger.pfnUserCallback(static_cast<VkDebugUtilsMessageSeverityFlagBitsEXT>(severity), types,
334 &callback_data, layer_dbg_node->pUserData)) {
335 bail = true;
336 }
337 layer_dbg_node = layer_dbg_node->pNext;
338 }
339
340 if (nullptr != queue_labels) {
341 delete[] queue_labels;
342 }
343 if (nullptr != cmd_buf_labels) {
344 delete[] cmd_buf_labels;
345 }
346
347 return bail;
348}
349
350static inline void DebugAnnotFlagsToReportFlags(VkDebugUtilsMessageSeverityFlagBitsEXT da_severity,
351 VkDebugUtilsMessageTypeFlagsEXT da_type, VkDebugReportFlagsEXT *dr_flags) {
352 *dr_flags = 0;
353
354 if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) != 0) {
355 *dr_flags |= VK_DEBUG_REPORT_ERROR_BIT_EXT;
356 } else if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) != 0) {
357 if ((da_type & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT) != 0) {
358 *dr_flags |= VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
359 } else {
360 *dr_flags |= VK_DEBUG_REPORT_WARNING_BIT_EXT;
361 }
362 } else if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) != 0) {
363 *dr_flags |= VK_DEBUG_REPORT_INFORMATION_BIT_EXT;
364 } else if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) != 0) {
365 *dr_flags |= VK_DEBUG_REPORT_DEBUG_BIT_EXT;
366 }
367}
368
369static inline bool debug_messenger_log_msg(const debug_report_data *debug_data,
370 VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
371 VkDebugUtilsMessageTypeFlagsEXT message_type,
372 VkDebugUtilsMessengerCallbackDataEXT *callback_data) {
373 bool bail = false;
374 VkLayerDbgFunctionNode *layer_dbg_node = NULL;
375
376 if (debug_data->debug_callback_list != NULL) {
377 layer_dbg_node = debug_data->debug_callback_list;
378 } else {
379 layer_dbg_node = debug_data->default_debug_callback_list;
380 }
381
382 VkDebugReportFlagsEXT object_flags = 0;
383
384 DebugAnnotFlagsToReportFlags(message_severity, message_type, &object_flags);
385
386 while (layer_dbg_node) {
387 if (layer_dbg_node->is_messenger && (layer_dbg_node->messenger.messageSeverity & message_severity) &&
388 (layer_dbg_node->messenger.messageType & message_type)) {
389 // Loop through each object and give it the proper name if it was set.
390 for (uint32_t obj = 0; obj < callback_data->objectCount; obj++) {
391 auto it = debug_data->debugUtilsObjectNameMap->find(callback_data->pObjects[obj].objectHandle);
392 if (it == debug_data->debugUtilsObjectNameMap->end()) {
393 continue;
394 }
395 callback_data->pObjects[obj].pObjectName = it->second.c_str();
396 }
397 if (layer_dbg_node->messenger.pfnUserCallback(message_severity, message_type, callback_data,
398 layer_dbg_node->pUserData)) {
399 bail = true;
400 }
401 } else if (!layer_dbg_node->is_messenger && layer_dbg_node->report.msgFlags & object_flags) {
402 auto it = debug_data->debugObjectNameMap->find(callback_data->pObjects[0].objectHandle);
403 VkDebugReportObjectTypeEXT object_type = get_debug_report_enum[callback_data->pObjects[0].objectType];
Tony Barbour3431dac2017-06-19 16:50:37 -0600404 if (it == debug_data->debugObjectNameMap->end()) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700405 if (layer_dbg_node->report.pfnMsgCallback(object_flags, object_type, callback_data->pObjects[0].objectHandle, 0,
406 callback_data->messageIdNumber, callback_data->pMessageIdName,
407 callback_data->pMessage, layer_dbg_node->pUserData)) {
Tony Barbour3431dac2017-06-19 16:50:37 -0600408 bail = true;
409 }
410 } else {
411 std::string newMsg = "SrcObject name = ";
412 newMsg.append(it->second.c_str());
413 newMsg.append(" ");
Mark Young6ba8abe2017-11-09 10:37:04 -0700414 newMsg.append(callback_data->pMessage);
415 if (layer_dbg_node->report.pfnMsgCallback(object_flags, object_type, callback_data->pObjects[0].objectHandle, 0,
416 callback_data->messageIdNumber, callback_data->pMessageIdName,
417 newMsg.c_str(), layer_dbg_node->pUserData)) {
Tony Barbour3431dac2017-06-19 16:50:37 -0600418 bail = true;
419 }
Courtney Goeltzenleuchter06640832015-09-04 13:52:24 -0600420 }
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600421 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700422 layer_dbg_node = layer_dbg_node->pNext;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600423 }
Courtney Goeltzenleuchter06640832015-09-04 13:52:24 -0600424
425 return bail;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600426}
427
Mark Young6ba8abe2017-11-09 10:37:04 -0700428static inline debug_report_data *debug_utils_create_instance(
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700429 VkLayerInstanceDispatchTable *table, VkInstance inst, uint32_t extension_count,
Mark Young6ba8abe2017-11-09 10:37:04 -0700430 const char *const *enabled_extensions) // layer or extension name to be enabled
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600431{
Mark Youngaa1aa3a2016-07-05 16:41:50 -0600432 debug_report_data *debug_data = (debug_report_data *)malloc(sizeof(debug_report_data));
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700433 if (!debug_data) return NULL;
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600434
435 memset(debug_data, 0, sizeof(debug_report_data));
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600436 for (uint32_t i = 0; i < extension_count; i++) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600437 // TODO: Check other property fields
Mark Young6ba8abe2017-11-09 10:37:04 -0700438 if (strcmp(enabled_extensions[i], VK_EXT_DEBUG_REPORT_EXTENSION_NAME) == 0) {
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600439 debug_data->g_DEBUG_REPORT = true;
Mark Young6ba8abe2017-11-09 10:37:04 -0700440 } else if (strcmp(enabled_extensions[i], VK_EXT_DEBUG_UTILS_EXTENSION_NAME) == 0) {
441 debug_data->g_DEBUG_UTILS = true;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600442 }
443 }
Tony Barbour3431dac2017-06-19 16:50:37 -0600444 debug_data->debugObjectNameMap = new std::unordered_map<uint64_t, std::string>;
Mark Young6ba8abe2017-11-09 10:37:04 -0700445 debug_data->debugUtilsObjectNameMap = new std::unordered_map<uint64_t, std::string>;
446 debug_data->debugUtilsQueueLabels = new std::unordered_map<VkQueue, std::vector<LoggingLabelData>>;
447 debug_data->debugUtilsCmdBufLabels = new std::unordered_map<VkCommandBuffer, std::vector<LoggingLabelData>>;
448 debug_data->queueLabelHasInsert = false;
449 debug_data->cmdBufLabelHasInsert = false;
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600450 return debug_data;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600451}
452
Mark Young6ba8abe2017-11-09 10:37:04 -0700453static inline void layer_debug_utils_destroy_instance(debug_report_data *debug_data) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600454 if (debug_data) {
455 RemoveAllMessageCallbacks(debug_data, &debug_data->default_debug_callback_list);
456 RemoveAllMessageCallbacks(debug_data, &debug_data->debug_callback_list);
Tony Barbour3431dac2017-06-19 16:50:37 -0600457 delete debug_data->debugObjectNameMap;
Mark Young6ba8abe2017-11-09 10:37:04 -0700458 delete debug_data->debugUtilsObjectNameMap;
459 delete debug_data->debugUtilsQueueLabels;
460 delete debug_data->debugUtilsCmdBufLabels;
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600461 free(debug_data);
Courtney Goeltzenleuchteree4027d2015-06-28 13:01:17 -0600462 }
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600463}
464
Mark Young6ba8abe2017-11-09 10:37:04 -0700465static inline debug_report_data *layer_debug_utils_create_device(debug_report_data *instance_debug_data, VkDevice device) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600466 // DEBUG_REPORT shares data between Instance and Device,
467 // so just return instance's data pointer
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600468 return instance_debug_data;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600469}
470
Mark Young6ba8abe2017-11-09 10:37:04 -0700471static inline void layer_debug_utils_destroy_device(VkDevice device) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600472 // Nothing to do since we're using instance data record
473}
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600474
Mark Young6ba8abe2017-11-09 10:37:04 -0700475static inline void layer_destroy_messenger_callback(debug_report_data *debug_data, VkDebugUtilsMessengerEXT messenger,
476 const VkAllocationCallbacks *allocator) {
477 RemoveDebugUtilsMessenger(debug_data, &debug_data->debug_callback_list, messenger);
478 RemoveDebugUtilsMessenger(debug_data, &debug_data->default_debug_callback_list, messenger);
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600479}
480
Mark Young6ba8abe2017-11-09 10:37:04 -0700481static inline VkResult layer_create_messenger_callback(debug_report_data *debug_data, bool default_callback,
482 const VkDebugUtilsMessengerCreateInfoEXT *create_info,
483 const VkAllocationCallbacks *allocator,
484 VkDebugUtilsMessengerEXT *messenger) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700485 VkLayerDbgFunctionNode *pNewDbgFuncNode = (VkLayerDbgFunctionNode *)malloc(sizeof(VkLayerDbgFunctionNode));
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700486 if (!pNewDbgFuncNode) return VK_ERROR_OUT_OF_HOST_MEMORY;
Mark Young6ba8abe2017-11-09 10:37:04 -0700487 memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode));
488 pNewDbgFuncNode->is_messenger = true;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600489
Tobin Ehliseb7715d2015-09-21 09:36:47 -0600490 // Handle of 0 is logging_callback so use allocated Node address as unique handle
Mark Young6ba8abe2017-11-09 10:37:04 -0700491 if (!(*messenger)) *messenger = (VkDebugUtilsMessengerEXT)pNewDbgFuncNode;
492 pNewDbgFuncNode->messenger.messenger = *messenger;
493 pNewDbgFuncNode->messenger.pfnUserCallback = create_info->pfnUserCallback;
494 pNewDbgFuncNode->messenger.messageSeverity = create_info->messageSeverity;
495 pNewDbgFuncNode->messenger.messageType = create_info->messageType;
496 pNewDbgFuncNode->pUserData = create_info->pUserData;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600497
Mark Young6ba8abe2017-11-09 10:37:04 -0700498 debug_data->active_severities |= create_info->messageSeverity;
499 debug_data->active_types |= create_info->messageType;
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600500 if (default_callback) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700501 AddDebugCallbackNode(debug_data, &debug_data->default_debug_callback_list, pNewDbgFuncNode);
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600502 } else {
Mark Young6ba8abe2017-11-09 10:37:04 -0700503 AddDebugCallbackNode(debug_data, &debug_data->debug_callback_list, pNewDbgFuncNode);
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600504 }
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600505
Mark Young6ba8abe2017-11-09 10:37:04 -0700506 VkDebugUtilsMessengerCallbackDataEXT callback_data = {};
507 VkDebugUtilsObjectNameInfoEXT blank_object = {};
508 callback_data.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT;
509 callback_data.pNext = NULL;
510 callback_data.flags = 0;
511 callback_data.pMessageIdName = "Layer Internal Message";
512 callback_data.messageIdNumber = 0;
513 callback_data.pMessage = "Added messenger";
514 callback_data.queueLabelCount = 0;
515 callback_data.pQueueLabels = NULL;
516 callback_data.cmdBufLabelCount = 0;
517 callback_data.pCmdBufLabels = NULL;
518 callback_data.objectCount = 1;
519 callback_data.pObjects = &blank_object;
520 blank_object.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
521 blank_object.pNext = NULL;
522 blank_object.objectType = VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT;
523 blank_object.objectHandle = HandleToUint64(*messenger);
524 blank_object.pObjectName = NULL;
525 debug_messenger_log_msg(debug_data, VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT,
526 VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT, &callback_data);
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600527 return VK_SUCCESS;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600528}
529
Mark Young6ba8abe2017-11-09 10:37:04 -0700530static inline void layer_destroy_report_callback(debug_report_data *debug_data, VkDebugReportCallbackEXT callback,
531 const VkAllocationCallbacks *allocator) {
532 RemoveDebugUtilsMessageCallback(debug_data, &debug_data->debug_callback_list, callback);
533 RemoveDebugUtilsMessageCallback(debug_data, &debug_data->default_debug_callback_list, callback);
534}
535
536static inline VkResult layer_create_report_callback(debug_report_data *debug_data, bool default_callback,
537 const VkDebugReportCallbackCreateInfoEXT *create_info,
538 const VkAllocationCallbacks *allocator, VkDebugReportCallbackEXT *callback) {
539 VkLayerDbgFunctionNode *pNewDbgFuncNode = (VkLayerDbgFunctionNode *)malloc(sizeof(VkLayerDbgFunctionNode));
540 if (!pNewDbgFuncNode) {
541 return VK_ERROR_OUT_OF_HOST_MEMORY;
542 }
543 memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode));
544 pNewDbgFuncNode->is_messenger = false;
545
546 // Handle of 0 is logging_callback so use allocated Node address as unique handle
547 if (!(*callback)) *callback = (VkDebugReportCallbackEXT)pNewDbgFuncNode;
548 pNewDbgFuncNode->report.msgCallback = *callback;
549 pNewDbgFuncNode->report.pfnMsgCallback = create_info->pfnCallback;
550 pNewDbgFuncNode->report.msgFlags = create_info->flags;
551 pNewDbgFuncNode->pUserData = create_info->pUserData;
552
553 VkFlags local_severity = 0;
554 VkFlags local_type = 0;
555 DebugReportFlagsToAnnotFlags(create_info->flags, true, &local_severity, &local_type);
556 debug_data->active_severities |= local_severity;
557 debug_data->active_types |= local_type;
558 if (default_callback) {
559 AddDebugCallbackNode(debug_data, &debug_data->default_debug_callback_list, pNewDbgFuncNode);
560 } else {
561 AddDebugCallbackNode(debug_data, &debug_data->debug_callback_list, pNewDbgFuncNode);
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600562 }
563
Mark Young6ba8abe2017-11-09 10:37:04 -0700564 debug_log_msg(debug_data, VK_DEBUG_REPORT_DEBUG_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT, (uint64_t)*callback, 0,
565 0, "DebugReport", "Added callback");
566 return VK_SUCCESS;
567}
568
569static inline PFN_vkVoidFunction debug_utils_get_instance_proc_addr(debug_report_data *debug_data, const char *func_name) {
570 if (!debug_data) {
571 return NULL;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600572 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700573 if (debug_data->g_DEBUG_REPORT) {
574 if (!strcmp(func_name, "vkCreateDebugReportCallbackEXT")) {
575 return (PFN_vkVoidFunction)vkCreateDebugReportCallbackEXT;
576 }
577 if (!strcmp(func_name, "vkDestroyDebugReportCallbackEXT")) {
578 return (PFN_vkVoidFunction)vkDestroyDebugReportCallbackEXT;
579 }
580 if (!strcmp(func_name, "vkDebugReportMessageEXT")) {
581 return (PFN_vkVoidFunction)vkDebugReportMessageEXT;
582 }
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600583 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700584 if (debug_data->g_DEBUG_UTILS) {
585 if (!strcmp(func_name, "vkCreateDebugUtilsMessengerEXT")) {
586 return (PFN_vkVoidFunction)vkCreateDebugUtilsMessengerEXT;
587 }
588 if (!strcmp(func_name, "vkDestroyDebugUtilsMessengerEXT")) {
589 return (PFN_vkVoidFunction)vkDestroyDebugUtilsMessengerEXT;
590 }
591 if (!strcmp(func_name, "vkSubmitDebugUtilsMessageEXT")) {
592 return (PFN_vkVoidFunction)vkSubmitDebugUtilsMessageEXT;
593 }
Courtney Goeltzenleuchter822e8d72015-11-30 15:28:25 -0700594 }
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600595 return NULL;
596}
597
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600598// This utility (called at vkCreateInstance() time), looks at a pNext chain.
599// It counts any VkDebugReportCallbackCreateInfoEXT structs that it finds. It
600// then allocates an array that can hold that many structs, as well as that
601// many VkDebugReportCallbackEXT handles. It then copies each
602// VkDebugReportCallbackCreateInfoEXT, and initializes each handle.
Mark Young6ba8abe2017-11-09 10:37:04 -0700603static inline VkResult layer_copy_tmp_report_callbacks(const void *pChain, uint32_t *num_callbacks,
604 VkDebugReportCallbackCreateInfoEXT **infos,
605 VkDebugReportCallbackEXT **callbacks) {
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600606 uint32_t n = *num_callbacks = 0;
607
608 const void *pNext = pChain;
609 while (pNext) {
610 // 1st, count the number VkDebugReportCallbackCreateInfoEXT:
611 if (((VkDebugReportCallbackCreateInfoEXT *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT) {
612 n++;
613 }
614 pNext = (void *)((VkDebugReportCallbackCreateInfoEXT *)pNext)->pNext;
615 }
616 if (n == 0) {
617 return VK_SUCCESS;
618 }
619
620 // 2nd, allocate memory for each VkDebugReportCallbackCreateInfoEXT:
621 VkDebugReportCallbackCreateInfoEXT *pInfos = *infos =
622 ((VkDebugReportCallbackCreateInfoEXT *)malloc(n * sizeof(VkDebugReportCallbackCreateInfoEXT)));
623 if (!pInfos) {
624 return VK_ERROR_OUT_OF_HOST_MEMORY;
625 }
626 // 3rd, allocate memory for a unique handle for each callback:
627 VkDebugReportCallbackEXT *pCallbacks = *callbacks = ((VkDebugReportCallbackEXT *)malloc(n * sizeof(VkDebugReportCallbackEXT)));
628 if (!pCallbacks) {
629 free(pInfos);
630 return VK_ERROR_OUT_OF_HOST_MEMORY;
631 }
632 // 4th, copy each VkDebugReportCallbackCreateInfoEXT for use by
633 // vkDestroyInstance, and assign a unique handle to each callback (just
634 // use the address of the copied VkDebugReportCallbackCreateInfoEXT):
635 pNext = pChain;
636 while (pNext) {
637 if (((VkInstanceCreateInfo *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT) {
638 memcpy(pInfos, pNext, sizeof(VkDebugReportCallbackCreateInfoEXT));
639 *pCallbacks++ = (VkDebugReportCallbackEXT)pInfos++;
640 }
641 pNext = (void *)((VkInstanceCreateInfo *)pNext)->pNext;
642 }
643
644 *num_callbacks = n;
645 return VK_SUCCESS;
646}
647
Mark Young6ba8abe2017-11-09 10:37:04 -0700648// This utility frees the arrays allocated by layer_copy_tmp_report_callbacks()
649static inline void layer_free_tmp_report_callbacks(VkDebugReportCallbackCreateInfoEXT *infos, VkDebugReportCallbackEXT *callbacks) {
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600650 free(infos);
651 free(callbacks);
652}
653
654// This utility enables all of the VkDebugReportCallbackCreateInfoEXT structs
Mark Young6ba8abe2017-11-09 10:37:04 -0700655// that were copied by layer_copy_tmp_report_callbacks()
656static inline VkResult layer_enable_tmp_report_callbacks(debug_report_data *debug_data, uint32_t num_callbacks,
657 VkDebugReportCallbackCreateInfoEXT *infos,
658 VkDebugReportCallbackEXT *callbacks) {
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600659 VkResult rtn = VK_SUCCESS;
660 for (uint32_t i = 0; i < num_callbacks; i++) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700661 rtn = layer_create_report_callback(debug_data, false, &infos[i], NULL, &callbacks[i]);
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600662 if (rtn != VK_SUCCESS) {
663 for (uint32_t j = 0; j < i; j++) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700664 layer_destroy_report_callback(debug_data, callbacks[j], NULL);
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600665 }
666 return rtn;
667 }
668 }
669 return rtn;
670}
671
672// This utility disables all of the VkDebugReportCallbackCreateInfoEXT structs
Mark Young6ba8abe2017-11-09 10:37:04 -0700673// that were copied by layer_copy_tmp_report_callbacks()
674static inline void layer_disable_tmp_report_callbacks(debug_report_data *debug_data, uint32_t num_callbacks,
675 VkDebugReportCallbackEXT *callbacks) {
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600676 for (uint32_t i = 0; i < num_callbacks; i++) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700677 layer_destroy_report_callback(debug_data, callbacks[i], NULL);
678 }
679}
680
681// This utility (called at vkCreateInstance() time), looks at a pNext chain.
682// It counts any VkDebugUtilsMessengerCreateInfoEXT structs that it finds. It
683// then allocates an array that can hold that many structs, as well as that
684// many VkDebugUtilsMessengerEXT handles. It then copies each
685// VkDebugUtilsMessengerCreateInfoEXT, and initializes each handle.
Mark Young8504ba62018-03-21 13:35:34 -0600686static inline VkResult layer_copy_tmp_debug_messengers(const void *pChain, uint32_t *num_messengers,
687 VkDebugUtilsMessengerCreateInfoEXT **infos,
688 VkDebugUtilsMessengerEXT **messengers) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700689 uint32_t n = *num_messengers = 0;
690
691 const void *pNext = pChain;
692 while (pNext) {
693 // 1st, count the number VkDebugUtilsMessengerCreateInfoEXT:
694 if (((VkDebugUtilsMessengerCreateInfoEXT *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT) {
695 n++;
696 }
697 pNext = (void *)((VkDebugUtilsMessengerCreateInfoEXT *)pNext)->pNext;
698 }
699 if (n == 0) {
700 return VK_SUCCESS;
701 }
702
703 // 2nd, allocate memory for each VkDebugUtilsMessengerCreateInfoEXT:
704 VkDebugUtilsMessengerCreateInfoEXT *pInfos = *infos =
705 ((VkDebugUtilsMessengerCreateInfoEXT *)malloc(n * sizeof(VkDebugUtilsMessengerCreateInfoEXT)));
706 if (!pInfos) {
707 return VK_ERROR_OUT_OF_HOST_MEMORY;
708 }
709 // 3rd, allocate memory for a unique handle for each messenger:
710 VkDebugUtilsMessengerEXT *pMessengers = *messengers =
711 ((VkDebugUtilsMessengerEXT *)malloc(n * sizeof(VkDebugUtilsMessengerEXT)));
712 if (!pMessengers) {
713 free(pInfos);
714 return VK_ERROR_OUT_OF_HOST_MEMORY;
715 }
716 // 4th, copy each VkDebugUtilsMessengerCreateInfoEXT for use by
717 // vkDestroyInstance, and assign a unique handle to each callback (just
718 // use the address of the copied VkDebugUtilsMessengerCreateInfoEXT):
719 pNext = pChain;
720 while (pNext) {
721 if (((VkInstanceCreateInfo *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT) {
722 memcpy(pInfos, pNext, sizeof(VkDebugUtilsMessengerCreateInfoEXT));
723 *pMessengers++ = (VkDebugUtilsMessengerEXT)pInfos++;
724 }
725 pNext = (void *)((VkInstanceCreateInfo *)pNext)->pNext;
726 }
727
728 *num_messengers = n;
729 return VK_SUCCESS;
730}
731
732// This utility frees the arrays allocated by layer_copy_tmp_debug_messengers()
Mark Young8504ba62018-03-21 13:35:34 -0600733static inline void layer_free_tmp_debug_messengers(VkDebugUtilsMessengerCreateInfoEXT *infos,
734 VkDebugUtilsMessengerEXT *messengers) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700735 free(infos);
736 free(messengers);
737}
738
739// This utility enables all of the VkDebugUtilsMessengerCreateInfoEXT structs
740// that were copied by layer_copy_tmp_debug_messengers()
Mark Young8504ba62018-03-21 13:35:34 -0600741static inline VkResult layer_enable_tmp_debug_messengers(debug_report_data *debug_data, uint32_t num_messengers,
742 VkDebugUtilsMessengerCreateInfoEXT *infos,
743 VkDebugUtilsMessengerEXT *messengers) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700744 VkResult rtn = VK_SUCCESS;
745 for (uint32_t i = 0; i < num_messengers; i++) {
746 rtn = layer_create_messenger_callback(debug_data, false, &infos[i], NULL, &messengers[i]);
747 if (rtn != VK_SUCCESS) {
748 for (uint32_t j = 0; j < i; j++) {
749 layer_destroy_messenger_callback(debug_data, messengers[j], NULL);
750 }
751 return rtn;
752 }
753 }
754 return rtn;
755}
756
757// This utility disables all of the VkDebugUtilsMessengerCreateInfoEXT structs
758// that were copied by layer_copy_tmp_debug_messengers()
Mark Young8504ba62018-03-21 13:35:34 -0600759static inline void layer_disable_tmp_debug_messengers(debug_report_data *debug_data, uint32_t num_messengers,
760 VkDebugUtilsMessengerEXT *messengers) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700761 for (uint32_t i = 0; i < num_messengers; i++) {
762 layer_destroy_messenger_callback(debug_data, messengers[i], NULL);
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600763 }
764}
765
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600766// Checks if the message will get logged.
767// Allows layer to defer collecting & formating data if the
768// message will be discarded.
Mark Young6ba8abe2017-11-09 10:37:04 -0700769static inline bool will_log_msg(debug_report_data *debug_data, VkFlags msg_flags) {
770 VkFlags local_severity = 0;
771 VkFlags local_type = 0;
772 DebugReportFlagsToAnnotFlags(msg_flags, true, &local_severity, &local_type);
773 if (!debug_data || !(debug_data->active_severities & local_severity) || !(debug_data->active_types & local_type)) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600774 // Message is not wanted
Courtney Goeltzenleuchter6a564a12015-09-18 16:30:24 -0600775 return false;
776 }
777
778 return true;
779}
John Zulauf6664e272018-01-17 11:00:22 -0700780#ifndef WIN32
Mark Lobodzinski1bcbdf92018-02-07 10:00:22 -0700781static inline int string_sprintf(std::string *output, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
John Zulauf6664e272018-01-17 11:00:22 -0700782#endif
Mark Lobodzinski1bcbdf92018-02-07 10:00:22 -0700783static inline int string_sprintf(std::string *output, const char *fmt, ...) {
John Zulauf6664e272018-01-17 11:00:22 -0700784 std::string &formatted = *output;
785 va_list argptr;
786 va_start(argptr, fmt);
787 int reserve = vsnprintf(nullptr, 0, fmt, argptr);
788 va_end(argptr);
789 formatted.reserve(reserve + 1);
790 va_start(argptr, fmt);
791 int result = vsnprintf((char *)formatted.data(), formatted.capacity(), fmt, argptr);
792 va_end(argptr);
793 assert(result == reserve);
794 return result;
795}
Courtney Goeltzenleuchter6a564a12015-09-18 16:30:24 -0600796
Chris Forbes8a25bce2016-03-24 12:06:35 +1300797#ifdef WIN32
798static inline int vasprintf(char **strp, char const *fmt, va_list ap) {
799 *strp = nullptr;
800 int size = _vscprintf(fmt, ap);
801 if (size >= 0) {
Mark Lobodzinski729a8d32017-01-26 12:16:30 -0700802 *strp = (char *)malloc(size + 1);
Chris Forbes8a25bce2016-03-24 12:06:35 +1300803 if (!*strp) {
804 return -1;
805 }
Mark Lobodzinski729a8d32017-01-26 12:16:30 -0700806 _vsnprintf(*strp, size + 1, fmt, ap);
Chris Forbes8a25bce2016-03-24 12:06:35 +1300807 }
808 return size;
809}
810#endif
811
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600812// Output log message via DEBUG_REPORT
813// Takes format and variable arg list so that output string
814// is only computed if a message needs to be logged
Michael Lentine010f4692015-11-03 16:19:46 -0800815#ifndef WIN32
Mark Young6ba8abe2017-11-09 10:37:04 -0700816static inline bool log_msg(const debug_report_data *debug_data, VkFlags msg_flags, VkDebugReportObjectTypeEXT object_type,
817 uint64_t src_object, size_t location, int32_t msg_code, const char *layer_prefix, const char *format,
818 ...) __attribute__((format(printf, 8, 9)));
Michael Lentine010f4692015-11-03 16:19:46 -0800819#endif
Mark Young6ba8abe2017-11-09 10:37:04 -0700820static inline bool log_msg(const debug_report_data *debug_data, VkFlags msg_flags, VkDebugReportObjectTypeEXT object_type,
821 uint64_t src_object, size_t location, int32_t msg_code, const char *layer_prefix, const char *format,
Dustin Graves8f1eab92016-04-05 09:41:17 -0600822 ...) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700823 VkFlags local_severity = 0;
824 VkFlags local_type = 0;
825 DebugReportFlagsToAnnotFlags(msg_flags, true, &local_severity, &local_type);
826 if (!debug_data || !(debug_data->active_severities & local_severity) || !(debug_data->active_types & local_type)) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600827 // Message is not wanted
Courtney Goeltzenleuchter06640832015-09-04 13:52:24 -0600828 return false;
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600829 }
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600830
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600831 va_list argptr;
832 va_start(argptr, format);
Chris Forbes8a25bce2016-03-24 12:06:35 +1300833 char *str;
Chris Forbesed6a1b32016-04-28 14:27:19 +1200834 if (-1 == vasprintf(&str, format, argptr)) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600835 // On failure, glibc vasprintf leaves str undefined
Chris Forbesed6a1b32016-04-28 14:27:19 +1200836 str = nullptr;
837 }
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600838 va_end(argptr);
Mark Young6ba8abe2017-11-09 10:37:04 -0700839 bool result = debug_log_msg(debug_data, msg_flags, object_type, src_object, location, msg_code, layer_prefix,
840 str ? str : "Allocation failure");
Chris Forbes8a25bce2016-03-24 12:06:35 +1300841 free(str);
842 return result;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600843}
844
Mark Young6ba8abe2017-11-09 10:37:04 -0700845static inline VKAPI_ATTR VkBool32 VKAPI_CALL report_log_callback(VkFlags msg_flags, VkDebugReportObjectTypeEXT obj_type,
846 uint64_t src_object, size_t location, int32_t msg_code,
847 const char *layer_prefix, const char *message, void *user_data) {
848 char msg_flag_string[30];
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600849
Mark Young6ba8abe2017-11-09 10:37:04 -0700850 PrintMessageFlags(msg_flags, msg_flag_string);
Courtney Goeltzenleuchter2f25bb42015-06-14 11:29:24 -0600851
Mark Young8504ba62018-03-21 13:35:34 -0600852 fprintf((FILE *)user_data, "%s(%s): location: %lu msg_code: %d: %s\n", layer_prefix, msg_flag_string, (unsigned long)location,
853 msg_code, message);
Mark Young6ba8abe2017-11-09 10:37:04 -0700854 fflush((FILE *)user_data);
Courtney Goeltzenleuchter06640832015-09-04 13:52:24 -0600855
856 return false;
Courtney Goeltzenleuchter2f25bb42015-06-14 11:29:24 -0600857}
Courtney Goeltzenleuchter5907ac42015-10-05 14:41:34 -0600858
Mark Young6ba8abe2017-11-09 10:37:04 -0700859static inline VKAPI_ATTR VkBool32 VKAPI_CALL report_win32_debug_output_msg(VkFlags msg_flags, VkDebugReportObjectTypeEXT obj_type,
860 uint64_t src_object, size_t location, int32_t msg_code,
861 const char *layer_prefix, const char *message,
862 void *user_data) {
Courtney Goeltzenleuchter5907ac42015-10-05 14:41:34 -0600863#ifdef WIN32
Mark Young6ba8abe2017-11-09 10:37:04 -0700864 char msg_flag_string[30];
Courtney Goeltzenleuchter5907ac42015-10-05 14:41:34 -0600865 char buf[2048];
866
Mark Young6ba8abe2017-11-09 10:37:04 -0700867 PrintMessageFlags(msg_flags, msg_flag_string);
Mark Young8504ba62018-03-21 13:35:34 -0600868 _snprintf(buf, sizeof(buf) - 1, "%s (%s): location: " PRINTF_SIZE_T_SPECIFIER " msg_code: %d: %s\n", layer_prefix,
869 msg_flag_string, location, msg_code, message);
Courtney Goeltzenleuchter5907ac42015-10-05 14:41:34 -0600870
871 OutputDebugString(buf);
872#endif
873
874 return false;
875}
876
Mark Young6ba8abe2017-11-09 10:37:04 -0700877static inline VKAPI_ATTR VkBool32 VKAPI_CALL DebugBreakCallback(VkFlags msgFlags, VkDebugReportObjectTypeEXT obj_type,
878 uint64_t src_object, size_t location, int32_t msg_code,
879 const char *layer_prefix, const char *message, void *user_data) {
Mark Lobodzinskic9d81652017-08-10 11:01:17 -0600880#ifdef WIN32
881 DebugBreak();
882#else
883 raise(SIGTRAP);
884#endif
885
886 return false;
887}
888
Mark Young6ba8abe2017-11-09 10:37:04 -0700889static inline VKAPI_ATTR VkBool32 VKAPI_CALL messenger_log_callback(VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
890 VkDebugUtilsMessageTypeFlagsEXT message_type,
891 const VkDebugUtilsMessengerCallbackDataEXT *callback_data,
892 void *user_data) {
893 char msg_severity[30];
894 char msg_type[30];
895
896 PrintMessageSeverity(message_severity, msg_severity);
897 PrintMessageType(message_type, msg_type);
898
Mark Young8504ba62018-03-21 13:35:34 -0600899 fprintf((FILE *)user_data, "%s(%s / %s): msgNum: %d - %s\n", callback_data->pMessageIdName, msg_severity, msg_type,
Mark Young6ba8abe2017-11-09 10:37:04 -0700900 callback_data->messageIdNumber, callback_data->pMessage);
Mark Young8504ba62018-03-21 13:35:34 -0600901 fprintf((FILE *)user_data, " Objects: %d\n", callback_data->objectCount);
902 for (uint32_t obj = 0; obj < callback_data->objectCount; ++obj) {
903 fprintf((FILE *)user_data, " [%d] 0x%" PRIx64 ", type: %d, name: %s\n", obj,
904 callback_data->pObjects[obj].objectHandle, callback_data->pObjects[obj].objectType,
905 callback_data->pObjects[obj].pObjectName);
906 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700907 fflush((FILE *)user_data);
908
909 return false;
Petr Krause9388f62017-05-13 20:53:12 +0200910}
911
Mark Young6ba8abe2017-11-09 10:37:04 -0700912static inline VKAPI_ATTR VkBool32 VKAPI_CALL messenger_win32_debug_output_msg(
913 VkDebugUtilsMessageSeverityFlagBitsEXT message_severity, VkDebugUtilsMessageTypeFlagsEXT message_type,
914 const VkDebugUtilsMessengerCallbackDataEXT *callback_data, void *user_data) {
915#ifdef WIN32
916 char buf[2048];
917 char msg_severity[30];
918 char msg_type[30];
Mark Lobodzinski863d5de2017-05-22 10:10:07 -0600919
Mark Young6ba8abe2017-11-09 10:37:04 -0700920 PrintMessageSeverity(message_severity, msg_severity);
921 PrintMessageType(message_type, msg_type);
922
Mark Young8504ba62018-03-21 13:35:34 -0600923 size_t buffer_space = sizeof(buf) - 1;
924 size_t remaining_space = buffer_space;
925 _snprintf(buf, sizeof(buf) - 1, "%s(%s / %s): msgNum: %d - %s\n", callback_data->pMessageIdName, msg_severity, msg_type,
926 callback_data->messageIdNumber, callback_data->pMessage);
927 remaining_space = buffer_space - strlen(buf);
928 _snprintf(buf, remaining_space, " Objects: %d\n", callback_data->objectCount);
929 for (uint32_t obj = 0; obj < callback_data->objectCount; ++obj) {
930 remaining_space = buffer_space - strlen(buf);
931 if (remaining_space > 0) {
932 _snprintf(buf, remaining_space, " [%d] 0x%" PRIx64 ", type: %d, name: %s\n", obj,
933 callback_data->pObjects[obj].objectHandle, callback_data->pObjects[obj].objectType,
934 callback_data->pObjects[obj].pObjectName);
935 }
936 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700937 OutputDebugString(buf);
938#endif
939
940 return false;
941}
942
943// This utility converts from the VkDebugUtilsLabelEXT structure into the logging version of the structure.
944// In the logging version, we only record what we absolutely need to convey back to the callbacks.
945static inline void InsertLabelIntoLog(const VkDebugUtilsLabelEXT *utils_label, std::vector<LoggingLabelData> &log_vector) {
946 LoggingLabelData log_label_data = {};
947 log_label_data.name = utils_label->pLabelName;
948 log_label_data.color[0] = utils_label->color[0];
949 log_label_data.color[1] = utils_label->color[1];
950 log_label_data.color[2] = utils_label->color[2];
951 log_label_data.color[3] = utils_label->color[3];
952 log_vector.push_back(log_label_data);
953}
954
Mark Young8504ba62018-03-21 13:35:34 -0600955static inline void BeginQueueDebugUtilsLabel(debug_report_data *report_data, VkQueue queue,
956 const VkDebugUtilsLabelEXT *label_info) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700957 if (nullptr != label_info && nullptr != label_info->pLabelName) {
958 auto label_iter = report_data->debugUtilsQueueLabels->find(queue);
959 if (label_iter == report_data->debugUtilsQueueLabels->end()) {
960 std::vector<LoggingLabelData> new_queue_labels;
961 InsertLabelIntoLog(label_info, new_queue_labels);
962 report_data->debugUtilsQueueLabels->insert({queue, new_queue_labels});
963 } else {
964 // If the last thing was a label insert, we need to pop it off of the label vector before any
965 // changes. This is because a label added with "vkQueueInsertDebugUtilsLabelEXT" is only a
966 // temporary location that exists until the next operation occurs. In this case, a new
967 // "vkQueueBeginDebugUtilsLabelEXT" has occurred erasing the previous inserted label.
968 if (report_data->queueLabelHasInsert) {
969 report_data->queueLabelHasInsert = false;
970 label_iter->second.pop_back();
971 }
972 InsertLabelIntoLog(label_info, label_iter->second);
973 }
974 }
975}
976
Mark Young8504ba62018-03-21 13:35:34 -0600977static inline void EndQueueDebugUtilsLabel(debug_report_data *report_data, VkQueue queue) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700978 auto label_iter = report_data->debugUtilsQueueLabels->find(queue);
979 if (label_iter != report_data->debugUtilsQueueLabels->end()) {
980 // If the last thing was a label insert, we need to pop it off of the label vector before any
981 // changes. This is because a label added with "vkQueueInsertDebugUtilsLabelEXT" is only a
982 // temporary location that exists until the next operation occurs. In this case, a
983 // "vkQueueEndDebugUtilsLabelEXT" has occurred erasing the inserted label.
984 if (report_data->queueLabelHasInsert) {
985 report_data->queueLabelHasInsert = false;
986 label_iter->second.pop_back();
987 }
988 // Now pop the normal item
989 label_iter->second.pop_back();
990 }
991}
992
Mark Young8504ba62018-03-21 13:35:34 -0600993static inline void InsertQueueDebugUtilsLabel(debug_report_data *report_data, VkQueue queue,
994 const VkDebugUtilsLabelEXT *label_info) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700995 if (nullptr != label_info && nullptr != label_info->pLabelName) {
996 auto label_iter = report_data->debugUtilsQueueLabels->find(queue);
997 if (label_iter == report_data->debugUtilsQueueLabels->end()) {
998 std::vector<LoggingLabelData> new_queue_labels;
999 InsertLabelIntoLog(label_info, new_queue_labels);
1000 report_data->debugUtilsQueueLabels->insert({queue, new_queue_labels});
1001 } else {
1002 // If the last thing was a label insert, we need to pop it off of the label vector before any
1003 // changes. This is because a label added with "vkQueueInsertDebugUtilsLabelEXT" is only a
1004 // temporary location that exists until the next operation occurs. In this case, a new
1005 // "vkQueueInsertDebugUtilsLabelEXT" has occurred erasing the previous inserted label.
1006 if (report_data->queueLabelHasInsert) {
1007 label_iter->second.pop_back();
1008 }
1009 // Insert this new label and mark it as one that has been "inserted" so we can remove it on
1010 // the next queue label operation.
1011 InsertLabelIntoLog(label_info, label_iter->second);
1012 report_data->queueLabelHasInsert = true;
1013 }
1014 }
1015}
1016
Mark Young8504ba62018-03-21 13:35:34 -06001017static inline void BeginCmdDebugUtilsLabel(debug_report_data *report_data, VkCommandBuffer command_buffer,
1018 const VkDebugUtilsLabelEXT *label_info) {
Mark Young6ba8abe2017-11-09 10:37:04 -07001019 if (nullptr != label_info && nullptr != label_info->pLabelName) {
1020 auto label_iter = report_data->debugUtilsCmdBufLabels->find(command_buffer);
1021 if (label_iter == report_data->debugUtilsCmdBufLabels->end()) {
1022 std::vector<LoggingLabelData> new_cmdbuf_labels;
1023 InsertLabelIntoLog(label_info, new_cmdbuf_labels);
1024 report_data->debugUtilsCmdBufLabels->insert({command_buffer, new_cmdbuf_labels});
1025 } else {
1026 // If the last thing was a label insert, we need to pop it off of the label vector before any
1027 // changes. This is because a label added with "vkCmdInsertDebugUtilsLabelEXT" is only a
1028 // temporary location that exists until the next operation occurs. In this case, a
1029 // "vkCmdBeginDebugUtilsLabelEXT" has occurred erasing the inserted label.
1030 if (report_data->cmdBufLabelHasInsert) {
1031 report_data->cmdBufLabelHasInsert = false;
1032 label_iter->second.pop_back();
1033 }
1034 InsertLabelIntoLog(label_info, label_iter->second);
1035 }
1036 }
1037}
1038
Mark Young8504ba62018-03-21 13:35:34 -06001039static inline void EndCmdDebugUtilsLabel(debug_report_data *report_data, VkCommandBuffer command_buffer) {
Mark Young6ba8abe2017-11-09 10:37:04 -07001040 auto label_iter = report_data->debugUtilsCmdBufLabels->find(command_buffer);
1041 if (label_iter != report_data->debugUtilsCmdBufLabels->end()) {
1042 // If the last thing was a label insert, we need to pop it off of the label vector before any
1043 // changes. This is because a label added with "vkCmdInsertDebugUtilsLabelEXT" is only a
1044 // temporary location that exists until the next operation occurs. In this case, a
1045 // "vkCmdEndDebugUtilsLabelEXT" has occurred erasing the inserted label.
1046 if (report_data->cmdBufLabelHasInsert) {
1047 report_data->cmdBufLabelHasInsert = false;
1048 label_iter->second.pop_back();
1049 }
1050 // Now pop the normal item
1051 label_iter->second.pop_back();
1052 }
1053}
1054
Mark Young8504ba62018-03-21 13:35:34 -06001055static inline void InsertCmdDebugUtilsLabel(debug_report_data *report_data, VkCommandBuffer command_buffer,
1056 const VkDebugUtilsLabelEXT *label_info) {
Mark Young6ba8abe2017-11-09 10:37:04 -07001057 if (nullptr != label_info && nullptr != label_info->pLabelName) {
1058 auto label_iter = report_data->debugUtilsCmdBufLabels->find(command_buffer);
1059 if (label_iter == report_data->debugUtilsCmdBufLabels->end()) {
1060 std::vector<LoggingLabelData> new_cmdbuf_labels;
1061 InsertLabelIntoLog(label_info, new_cmdbuf_labels);
1062 report_data->debugUtilsCmdBufLabels->insert({command_buffer, new_cmdbuf_labels});
1063 } else {
1064 // If the last thing was a label insert, we need to pop it off of the label vector before any
1065 // changes. This is because a label added with "vkCmdInsertDebugUtilsLabelEXT" is only a
1066 // temporary location that exists until the next operation occurs. In this case, a new
1067 // "vkCmdInsertDebugUtilsLabelEXT" has occurred erasing the previous inserted label.
1068 if (report_data->cmdBufLabelHasInsert) {
1069 label_iter->second.pop_back();
1070 }
1071 // Insert this new label and mark it as one that has been "inserted" so we can remove it on
1072 // the next command buffer label operation.
1073 InsertLabelIntoLog(label_info, label_iter->second);
1074 report_data->cmdBufLabelHasInsert = true;
1075 }
1076 }
1077}
Mark Lobodzinski863d5de2017-05-22 10:10:07 -06001078
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001079#endif // LAYER_LOGGING_H