blob: 9af840efa2c00dbc647d437ad67369476df9bea1 [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"
Tobin Ehlis2d9deec2016-04-21 14:19:26 -060029#include "vk_loader_platform.h"
30#include "vulkan/vk_layer.h"
Mark Young6ba8abe2017-11-09 10:37:04 -070031#include "vk_object_types.h"
Mark Lobodzinski487a0d12018-03-30 10:09:03 -060032#include "vk_validation_error_messages.h"
Lenny Komow4c0da772018-07-03 10:17:21 -060033#include "vk_layer_dispatch_table.h"
Mark Lobodzinskic9d81652017-08-10 11:01:17 -060034#include <signal.h>
Karl Schultzd7f37542016-05-10 11:36:08 -060035#include <cinttypes>
Tobin Ehlis2d9deec2016-04-21 14:19:26 -060036#include <stdarg.h>
37#include <stdbool.h>
38#include <stdio.h>
39#include <unordered_map>
Mark Lobodzinski97c4d512016-05-19 15:27:18 -060040#include <vector>
Mark Young6ba8abe2017-11-09 10:37:04 -070041#include <sstream>
42#include <string>
43
Dave Houlton57ae22f2018-05-18 16:20:52 -060044// Suppress unused warning on Linux
45#if defined(__GNUC__)
Dave Houltoncfcecbf2018-05-31 16:20:57 -060046#define DECORATE_UNUSED __attribute__((unused))
47#else
48#define DECORATE_UNUSED
Dave Houlton57ae22f2018-05-18 16:20:52 -060049#endif
50
Dave Houltoncfcecbf2018-05-31 16:20:57 -060051static const char DECORATE_UNUSED *kVUIDUndefined = "VUID_Undefined";
Dave Houlton8e9f6542018-05-18 12:18:22 -060052
Dave Houltoncfcecbf2018-05-31 16:20:57 -060053#undef DECORATE_UNUSED
Dave Houlton57ae22f2018-05-18 16:20:52 -060054
Mark Young6ba8abe2017-11-09 10:37:04 -070055// TODO: Could be autogenerated for the specific handles for extra type safety...
56template <typename HANDLE_T>
57static inline uint64_t HandleToUint64(HANDLE_T *h) {
58 return reinterpret_cast<uint64_t>(h);
59}
60
61static inline uint64_t HandleToUint64(uint64_t h) { return h; }
62
63// Data we store per label for logging
64typedef struct _LoggingLabelData {
65 std::string name;
66 float color[4];
67} LoggingLabelData;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060068
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -060069typedef struct _debug_report_data {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -060070 VkLayerDbgFunctionNode *debug_callback_list;
71 VkLayerDbgFunctionNode *default_debug_callback_list;
Mark Young6ba8abe2017-11-09 10:37:04 -070072 VkDebugUtilsMessageSeverityFlagsEXT active_severities;
73 VkDebugUtilsMessageTypeFlagsEXT active_types;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060074 bool g_DEBUG_REPORT;
Mark Young6ba8abe2017-11-09 10:37:04 -070075 bool g_DEBUG_UTILS;
Tony Barbour3431dac2017-06-19 16:50:37 -060076 std::unordered_map<uint64_t, std::string> *debugObjectNameMap;
Mark Young6ba8abe2017-11-09 10:37:04 -070077 std::unordered_map<uint64_t, std::string> *debugUtilsObjectNameMap;
78 std::unordered_map<VkQueue, std::vector<LoggingLabelData>> *debugUtilsQueueLabels;
79 bool queueLabelHasInsert;
80 std::unordered_map<VkCommandBuffer, std::vector<LoggingLabelData>> *debugUtilsCmdBufLabels;
81 bool cmdBufLabelHasInsert;
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -060082} debug_report_data;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060083
Tobin Ehlis8d6acde2017-02-08 07:40:40 -070084template debug_report_data *GetLayerDataPtr<debug_report_data>(void *data_key,
Jon Ashburn5484e0c2016-03-08 17:48:44 -070085 std::unordered_map<void *, debug_report_data *> &data_map);
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060086
Mark Young6ba8abe2017-11-09 10:37:04 -070087static inline void DebugReportFlagsToAnnotFlags(VkDebugReportFlagsEXT dr_flags, bool default_flag_is_spec,
88 VkDebugUtilsMessageSeverityFlagsEXT *da_severity,
89 VkDebugUtilsMessageTypeFlagsEXT *da_type) {
Mark Young6ba8abe2017-11-09 10:37:04 -070090 *da_severity = 0;
Mark Youngc2347792018-05-30 08:41:25 -060091 // If it's explicitly listed as a performance warning, treat it as a performance message.
92 // Otherwise, treat it as a validation issue.
93 if ((dr_flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) != 0) {
94 *da_type = VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
95 } else {
96 *da_type = VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;
97 }
Mark Young6ba8abe2017-11-09 10:37:04 -070098 if ((dr_flags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) != 0) {
99 *da_severity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT;
Mark Youngc2347792018-05-30 08:41:25 -0600100 // If this is a debug message, it's really intended for the general messages
101 *da_type = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT;
Mark Young6ba8abe2017-11-09 10:37:04 -0700102 }
103 if ((dr_flags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) != 0) {
104 *da_severity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
Mark Young6ba8abe2017-11-09 10:37:04 -0700105 }
Mark Youngc2347792018-05-30 08:41:25 -0600106 if ((dr_flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) != 0 || (dr_flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) != 0) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700107 *da_severity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
108 }
109 if ((dr_flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) != 0) {
110 *da_severity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
111 }
112}
113
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600114// Forward Declarations
Mark Young6ba8abe2017-11-09 10:37:04 -0700115static inline bool debug_log_msg(const debug_report_data *debug_data, VkFlags msg_flags, VkDebugReportObjectTypeEXT object_type,
116 uint64_t src_object, size_t location, int32_t msg_code, const char *layer_prefix,
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700117 const char *message, const char *text_vuid = NULL);
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600118
119// Add a debug message callback node structure to the specified callback linked list
Mark Young6ba8abe2017-11-09 10:37:04 -0700120static inline void AddDebugCallbackNode(debug_report_data *debug_data, VkLayerDbgFunctionNode **list_head,
121 VkLayerDbgFunctionNode *new_node) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600122 new_node->pNext = *list_head;
123 *list_head = new_node;
124}
125
Mark Young6ba8abe2017-11-09 10:37:04 -0700126// Remove specified debug messenger node structure from the specified linked list
127static inline void RemoveDebugUtilsMessenger(debug_report_data *debug_data, VkLayerDbgFunctionNode **list_head,
128 VkDebugUtilsMessengerEXT messenger) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600129 VkLayerDbgFunctionNode *cur_callback = *list_head;
130 VkLayerDbgFunctionNode *prev_callback = cur_callback;
131 bool matched = false;
Mark Young6ba8abe2017-11-09 10:37:04 -0700132 VkFlags local_severities = 0;
133 VkFlags local_types = 0;
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600134
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600135 while (cur_callback) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700136 if (cur_callback->is_messenger && cur_callback->messenger.messenger == messenger) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600137 matched = true;
138 prev_callback->pNext = cur_callback->pNext;
139 if (*list_head == cur_callback) {
140 *list_head = cur_callback->pNext;
141 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700142 debug_log_msg(debug_data, VK_DEBUG_REPORT_DEBUG_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT,
143 reinterpret_cast<uint64_t &>(cur_callback->messenger.messenger), 0, 0, "DebugUtilsMessenger",
144 "Destroyed messenger\n");
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600145 } else {
146 matched = false;
Mark Young6ba8abe2017-11-09 10:37:04 -0700147 local_severities |= cur_callback->messenger.messageSeverity;
148 local_types |= cur_callback->messenger.messageType;
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600149 }
150 prev_callback = cur_callback;
151 cur_callback = cur_callback->pNext;
152 if (matched) {
153 free(prev_callback);
154 }
155 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700156 debug_data->active_severities = local_severities;
157 debug_data->active_types = local_types;
158}
159
160// Remove specified debug message callback node structure from the specified callback linked list
161static inline void RemoveDebugUtilsMessageCallback(debug_report_data *debug_data, VkLayerDbgFunctionNode **list_head,
162 VkDebugReportCallbackEXT callback) {
163 VkLayerDbgFunctionNode *cur_callback = *list_head;
164 VkLayerDbgFunctionNode *prev_callback = cur_callback;
165 bool matched = false;
166 VkFlags local_severities = 0;
167 VkFlags local_types = 0;
168
169 while (cur_callback) {
170 if (!cur_callback->is_messenger && cur_callback->report.msgCallback == callback) {
171 matched = true;
172 prev_callback->pNext = cur_callback->pNext;
173 if (*list_head == cur_callback) {
174 *list_head = cur_callback->pNext;
175 }
176 debug_log_msg(debug_data, VK_DEBUG_REPORT_DEBUG_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT,
177 reinterpret_cast<uint64_t &>(cur_callback->report.msgCallback), 0, 0, "DebugReport",
178 "Destroyed callback\n");
179 } else {
180 matched = false;
181 VkFlags this_severities = 0;
182 VkFlags this_types = 0;
183 DebugReportFlagsToAnnotFlags(cur_callback->report.msgFlags, true, &this_severities, &this_types);
184 local_severities |= this_severities;
185 local_types |= this_types;
186 }
187 prev_callback = cur_callback;
188 cur_callback = cur_callback->pNext;
189 if (matched) {
190 free(prev_callback);
191 }
192 }
193 debug_data->active_severities = local_severities;
194 debug_data->active_types = local_types;
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600195}
196
197// Removes all debug callback function nodes from the specified callback linked lists and frees their resources
198static inline void RemoveAllMessageCallbacks(debug_report_data *debug_data, VkLayerDbgFunctionNode **list_head) {
199 VkLayerDbgFunctionNode *current_callback = *list_head;
200 VkLayerDbgFunctionNode *prev_callback = current_callback;
201
202 while (current_callback) {
203 prev_callback = current_callback->pNext;
Mark Young6ba8abe2017-11-09 10:37:04 -0700204 if (!current_callback->is_messenger) {
205 debug_log_msg(debug_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT,
206 (uint64_t)current_callback->report.msgCallback, 0, 0, "DebugReport",
207 "Debug Report callbacks not removed before DestroyInstance");
208 } else {
209 debug_log_msg(debug_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT,
210 (uint64_t)current_callback->messenger.messenger, 0, 0, "Messenger",
211 "Debug messengers not removed before DestroyInstance");
212 }
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600213 free(current_callback);
214 current_callback = prev_callback;
215 }
216 *list_head = NULL;
217}
218
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700219// Note that text_vuid is a default parameter, and is optional. See the above forward declaration
Mark Young6ba8abe2017-11-09 10:37:04 -0700220static inline bool debug_log_msg(const debug_report_data *debug_data, VkFlags msg_flags, VkDebugReportObjectTypeEXT object_type,
221 uint64_t src_object, size_t location, int32_t msg_code, const char *layer_prefix,
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700222 const char *message, const char *text_vuid) {
Dustin Graves8f1eab92016-04-05 09:41:17 -0600223 bool bail = false;
Mark Young6ba8abe2017-11-09 10:37:04 -0700224 VkLayerDbgFunctionNode *layer_dbg_node = NULL;
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600225
Mark Lobodzinski55a197f2016-06-21 15:54:57 -0600226 if (debug_data->debug_callback_list != NULL) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700227 layer_dbg_node = debug_data->debug_callback_list;
Mark Lobodzinski55a197f2016-06-21 15:54:57 -0600228 } else {
Mark Young6ba8abe2017-11-09 10:37:04 -0700229 layer_dbg_node = debug_data->default_debug_callback_list;
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600230 }
231
Mark Young6ba8abe2017-11-09 10:37:04 -0700232 VkDebugUtilsMessageSeverityFlagsEXT severity;
233 VkDebugUtilsMessageTypeFlagsEXT types;
234 VkDebugUtilsMessengerCallbackDataEXT callback_data;
235 VkDebugUtilsObjectNameInfoEXT object_name_info;
236
237 // Convert the info to the VK_EXT_debug_utils form in case we need it.
238 DebugReportFlagsToAnnotFlags(msg_flags, true, &severity, &types);
239 object_name_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
240 object_name_info.pNext = NULL;
241 object_name_info.objectType = convertDebugReportObjectToCoreObject(object_type);
242 object_name_info.objectHandle = (uint64_t)(uintptr_t)src_object;
243 object_name_info.pObjectName = NULL;
244
245 callback_data.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT;
246 callback_data.pNext = NULL;
247 callback_data.flags = 0;
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700248 callback_data.pMessageIdName = text_vuid;
Mark Young6ba8abe2017-11-09 10:37:04 -0700249 callback_data.messageIdNumber = msg_code;
250 callback_data.pMessage = message;
251 callback_data.queueLabelCount = 0;
252 callback_data.pQueueLabels = NULL;
253 callback_data.cmdBufLabelCount = 0;
254 callback_data.pCmdBufLabels = NULL;
255 callback_data.objectCount = 1;
256 callback_data.pObjects = &object_name_info;
257
258 VkDebugUtilsLabelEXT *queue_labels = nullptr;
259 VkDebugUtilsLabelEXT *cmd_buf_labels = nullptr;
260 std::string new_debug_report_message = "";
261 std::ostringstream oss;
Mark Young6ba8abe2017-11-09 10:37:04 -0700262
263 if (0 != src_object) {
Mark Young8504ba62018-03-21 13:35:34 -0600264 oss << "Object: 0x" << std::hex << src_object;
Mark Young6ba8abe2017-11-09 10:37:04 -0700265 // If this is a queue, add any queue labels to the callback data.
266 if (VK_OBJECT_TYPE_QUEUE == object_name_info.objectType) {
267 auto label_iter = debug_data->debugUtilsQueueLabels->find(reinterpret_cast<VkQueue>(src_object));
268 if (label_iter != debug_data->debugUtilsQueueLabels->end()) {
269 queue_labels = new VkDebugUtilsLabelEXT[label_iter->second.size()];
270 if (nullptr != queue_labels) {
271 // Record the labels, but record them in reverse order since we want the
272 // most recent at the top.
273 uint32_t label_size = static_cast<uint32_t>(label_iter->second.size());
274 uint32_t last_index = label_size - 1;
275 for (uint32_t label = 0; label < label_size; ++label) {
276 queue_labels[last_index - label].sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
277 queue_labels[last_index - label].pNext = nullptr;
278 queue_labels[last_index - label].pLabelName = label_iter->second[label].name.c_str();
279 queue_labels[last_index - label].color[0] = label_iter->second[label].color[0];
280 queue_labels[last_index - label].color[1] = label_iter->second[label].color[1];
281 queue_labels[last_index - label].color[2] = label_iter->second[label].color[2];
282 queue_labels[last_index - label].color[3] = label_iter->second[label].color[3];
283 }
284 callback_data.queueLabelCount = label_size;
285 callback_data.pQueueLabels = queue_labels;
286 }
287 }
288 // If this is a command buffer, add any command buffer labels to the callback data.
289 } else if (VK_OBJECT_TYPE_COMMAND_BUFFER == object_name_info.objectType) {
290 auto label_iter = debug_data->debugUtilsCmdBufLabels->find(reinterpret_cast<VkCommandBuffer>(src_object));
291 if (label_iter != debug_data->debugUtilsCmdBufLabels->end()) {
292 cmd_buf_labels = new VkDebugUtilsLabelEXT[label_iter->second.size()];
293 if (nullptr != cmd_buf_labels) {
294 // Record the labels, but record them in reverse order since we want the
295 // most recent at the top.
296 uint32_t label_size = static_cast<uint32_t>(label_iter->second.size());
297 uint32_t last_index = label_size - 1;
298 for (uint32_t label = 0; label < label_size; ++label) {
299 cmd_buf_labels[last_index - label].sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
300 cmd_buf_labels[last_index - label].pNext = nullptr;
301 cmd_buf_labels[last_index - label].pLabelName = label_iter->second[label].name.c_str();
302 cmd_buf_labels[last_index - label].color[0] = label_iter->second[label].color[0];
303 cmd_buf_labels[last_index - label].color[1] = label_iter->second[label].color[1];
304 cmd_buf_labels[last_index - label].color[2] = label_iter->second[label].color[2];
305 cmd_buf_labels[last_index - label].color[3] = label_iter->second[label].color[3];
306 }
307 callback_data.cmdBufLabelCount = label_size;
308 callback_data.pCmdBufLabels = cmd_buf_labels;
309 }
310 }
311 }
312 // Look for any debug utils or marker names to use for this object
313 callback_data.pObjects[0].pObjectName = NULL;
314 auto utils_name_iter = debug_data->debugUtilsObjectNameMap->find(src_object);
315 if (utils_name_iter != debug_data->debugUtilsObjectNameMap->end()) {
316 callback_data.pObjects[0].pObjectName = utils_name_iter->second.c_str();
317 } else {
318 auto marker_name_iter = debug_data->debugObjectNameMap->find(src_object);
319 if (marker_name_iter != debug_data->debugObjectNameMap->end()) {
320 callback_data.pObjects[0].pObjectName = marker_name_iter->second.c_str();
321 }
322 }
323 if (NULL != callback_data.pObjects[0].pObjectName) {
Mark Young8504ba62018-03-21 13:35:34 -0600324 oss << " (Name = " << callback_data.pObjects[0].pObjectName << " : Type = ";
325 } else {
326 oss << " (Type = ";
Mark Young6ba8abe2017-11-09 10:37:04 -0700327 }
Mark Young8504ba62018-03-21 13:35:34 -0600328 oss << std::to_string(object_type) << ")";
329 } else {
330 oss << "Object: VK_NULL_HANDLE (Type = " << std::to_string(object_type) << ")";
Mark Young6ba8abe2017-11-09 10:37:04 -0700331 }
332 new_debug_report_message += oss.str();
333 new_debug_report_message += " | ";
334 new_debug_report_message += message;
335
336 while (layer_dbg_node) {
Mark Young8504ba62018-03-21 13:35:34 -0600337 // If the app uses the VK_EXT_debug_report extension, call all of those registered callbacks.
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700338 if (!layer_dbg_node->is_messenger && (layer_dbg_node->report.msgFlags & msg_flags)) {
339 if (text_vuid != nullptr) {
340 // If a text vuid is supplied for the old debug report extension, prepend it to the message string
341 new_debug_report_message.insert(0, " ] ");
342 new_debug_report_message.insert(0, text_vuid);
343 new_debug_report_message.insert(0, " [ ");
344 }
345
346 if (layer_dbg_node->report.pfnMsgCallback(msg_flags, object_type, src_object, location, msg_code, layer_prefix,
347 new_debug_report_message.c_str(), layer_dbg_node->pUserData)) {
348 bail = true;
349 }
Mark Young8504ba62018-03-21 13:35:34 -0600350 // If the app uses the VK_EXT_debug_utils extension, call all of those registered callbacks.
Mark Young6ba8abe2017-11-09 10:37:04 -0700351 } else if (layer_dbg_node->is_messenger && (layer_dbg_node->messenger.messageSeverity & severity) &&
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700352 (layer_dbg_node->messenger.messageType & types)) {
353 if (layer_dbg_node->messenger.pfnUserCallback(static_cast<VkDebugUtilsMessageSeverityFlagBitsEXT>(severity), types,
354 &callback_data, layer_dbg_node->pUserData)) {
355 bail = true;
356 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700357 }
358 layer_dbg_node = layer_dbg_node->pNext;
359 }
360
361 if (nullptr != queue_labels) {
362 delete[] queue_labels;
363 }
364 if (nullptr != cmd_buf_labels) {
365 delete[] cmd_buf_labels;
366 }
367
368 return bail;
369}
370
371static inline void DebugAnnotFlagsToReportFlags(VkDebugUtilsMessageSeverityFlagBitsEXT da_severity,
372 VkDebugUtilsMessageTypeFlagsEXT da_type, VkDebugReportFlagsEXT *dr_flags) {
373 *dr_flags = 0;
374
375 if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) != 0) {
376 *dr_flags |= VK_DEBUG_REPORT_ERROR_BIT_EXT;
377 } else if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) != 0) {
378 if ((da_type & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT) != 0) {
379 *dr_flags |= VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
380 } else {
381 *dr_flags |= VK_DEBUG_REPORT_WARNING_BIT_EXT;
382 }
383 } else if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) != 0) {
384 *dr_flags |= VK_DEBUG_REPORT_INFORMATION_BIT_EXT;
385 } else if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) != 0) {
386 *dr_flags |= VK_DEBUG_REPORT_DEBUG_BIT_EXT;
387 }
388}
389
390static inline bool debug_messenger_log_msg(const debug_report_data *debug_data,
391 VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
392 VkDebugUtilsMessageTypeFlagsEXT message_type,
393 VkDebugUtilsMessengerCallbackDataEXT *callback_data) {
394 bool bail = false;
395 VkLayerDbgFunctionNode *layer_dbg_node = NULL;
396
397 if (debug_data->debug_callback_list != NULL) {
398 layer_dbg_node = debug_data->debug_callback_list;
399 } else {
400 layer_dbg_node = debug_data->default_debug_callback_list;
401 }
402
403 VkDebugReportFlagsEXT object_flags = 0;
404
405 DebugAnnotFlagsToReportFlags(message_severity, message_type, &object_flags);
406
407 while (layer_dbg_node) {
408 if (layer_dbg_node->is_messenger && (layer_dbg_node->messenger.messageSeverity & message_severity) &&
409 (layer_dbg_node->messenger.messageType & message_type)) {
410 // Loop through each object and give it the proper name if it was set.
411 for (uint32_t obj = 0; obj < callback_data->objectCount; obj++) {
412 auto it = debug_data->debugUtilsObjectNameMap->find(callback_data->pObjects[obj].objectHandle);
413 if (it == debug_data->debugUtilsObjectNameMap->end()) {
414 continue;
415 }
416 callback_data->pObjects[obj].pObjectName = it->second.c_str();
417 }
418 if (layer_dbg_node->messenger.pfnUserCallback(message_severity, message_type, callback_data,
419 layer_dbg_node->pUserData)) {
420 bail = true;
421 }
422 } else if (!layer_dbg_node->is_messenger && layer_dbg_node->report.msgFlags & object_flags) {
423 auto it = debug_data->debugObjectNameMap->find(callback_data->pObjects[0].objectHandle);
John Zulauf536649b2018-05-01 13:28:27 -0600424 VkDebugReportObjectTypeEXT object_type = convertCoreObjectToDebugReportObject(callback_data->pObjects[0].objectType);
Tony Barbour3431dac2017-06-19 16:50:37 -0600425 if (it == debug_data->debugObjectNameMap->end()) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700426 if (layer_dbg_node->report.pfnMsgCallback(object_flags, object_type, callback_data->pObjects[0].objectHandle, 0,
427 callback_data->messageIdNumber, callback_data->pMessageIdName,
428 callback_data->pMessage, layer_dbg_node->pUserData)) {
Tony Barbour3431dac2017-06-19 16:50:37 -0600429 bail = true;
430 }
431 } else {
432 std::string newMsg = "SrcObject name = ";
433 newMsg.append(it->second.c_str());
434 newMsg.append(" ");
Mark Young6ba8abe2017-11-09 10:37:04 -0700435 newMsg.append(callback_data->pMessage);
436 if (layer_dbg_node->report.pfnMsgCallback(object_flags, object_type, callback_data->pObjects[0].objectHandle, 0,
437 callback_data->messageIdNumber, callback_data->pMessageIdName,
438 newMsg.c_str(), layer_dbg_node->pUserData)) {
Tony Barbour3431dac2017-06-19 16:50:37 -0600439 bail = true;
440 }
Courtney Goeltzenleuchter06640832015-09-04 13:52:24 -0600441 }
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600442 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700443 layer_dbg_node = layer_dbg_node->pNext;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600444 }
Courtney Goeltzenleuchter06640832015-09-04 13:52:24 -0600445
446 return bail;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600447}
448
Mark Young6ba8abe2017-11-09 10:37:04 -0700449static inline debug_report_data *debug_utils_create_instance(
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700450 VkLayerInstanceDispatchTable *table, VkInstance inst, uint32_t extension_count,
Mark Young6ba8abe2017-11-09 10:37:04 -0700451 const char *const *enabled_extensions) // layer or extension name to be enabled
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600452{
Mark Youngaa1aa3a2016-07-05 16:41:50 -0600453 debug_report_data *debug_data = (debug_report_data *)malloc(sizeof(debug_report_data));
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700454 if (!debug_data) return NULL;
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600455
456 memset(debug_data, 0, sizeof(debug_report_data));
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600457 for (uint32_t i = 0; i < extension_count; i++) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600458 // TODO: Check other property fields
Mark Young6ba8abe2017-11-09 10:37:04 -0700459 if (strcmp(enabled_extensions[i], VK_EXT_DEBUG_REPORT_EXTENSION_NAME) == 0) {
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600460 debug_data->g_DEBUG_REPORT = true;
Mark Young6ba8abe2017-11-09 10:37:04 -0700461 } else if (strcmp(enabled_extensions[i], VK_EXT_DEBUG_UTILS_EXTENSION_NAME) == 0) {
462 debug_data->g_DEBUG_UTILS = true;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600463 }
464 }
Tony Barbour3431dac2017-06-19 16:50:37 -0600465 debug_data->debugObjectNameMap = new std::unordered_map<uint64_t, std::string>;
Mark Young6ba8abe2017-11-09 10:37:04 -0700466 debug_data->debugUtilsObjectNameMap = new std::unordered_map<uint64_t, std::string>;
467 debug_data->debugUtilsQueueLabels = new std::unordered_map<VkQueue, std::vector<LoggingLabelData>>;
468 debug_data->debugUtilsCmdBufLabels = new std::unordered_map<VkCommandBuffer, std::vector<LoggingLabelData>>;
469 debug_data->queueLabelHasInsert = false;
470 debug_data->cmdBufLabelHasInsert = false;
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600471 return debug_data;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600472}
473
Mark Young6ba8abe2017-11-09 10:37:04 -0700474static inline void layer_debug_utils_destroy_instance(debug_report_data *debug_data) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600475 if (debug_data) {
476 RemoveAllMessageCallbacks(debug_data, &debug_data->default_debug_callback_list);
477 RemoveAllMessageCallbacks(debug_data, &debug_data->debug_callback_list);
Tony Barbour3431dac2017-06-19 16:50:37 -0600478 delete debug_data->debugObjectNameMap;
Mark Young6ba8abe2017-11-09 10:37:04 -0700479 delete debug_data->debugUtilsObjectNameMap;
480 delete debug_data->debugUtilsQueueLabels;
481 delete debug_data->debugUtilsCmdBufLabels;
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600482 free(debug_data);
Courtney Goeltzenleuchteree4027d2015-06-28 13:01:17 -0600483 }
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600484}
485
Mark Young6ba8abe2017-11-09 10:37:04 -0700486static inline debug_report_data *layer_debug_utils_create_device(debug_report_data *instance_debug_data, VkDevice device) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600487 // DEBUG_REPORT shares data between Instance and Device,
488 // so just return instance's data pointer
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600489 return instance_debug_data;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600490}
491
Mark Young6ba8abe2017-11-09 10:37:04 -0700492static inline void layer_debug_utils_destroy_device(VkDevice device) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600493 // Nothing to do since we're using instance data record
494}
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600495
Mark Young6ba8abe2017-11-09 10:37:04 -0700496static inline void layer_destroy_messenger_callback(debug_report_data *debug_data, VkDebugUtilsMessengerEXT messenger,
497 const VkAllocationCallbacks *allocator) {
498 RemoveDebugUtilsMessenger(debug_data, &debug_data->debug_callback_list, messenger);
499 RemoveDebugUtilsMessenger(debug_data, &debug_data->default_debug_callback_list, messenger);
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600500}
501
Mark Young6ba8abe2017-11-09 10:37:04 -0700502static inline VkResult layer_create_messenger_callback(debug_report_data *debug_data, bool default_callback,
503 const VkDebugUtilsMessengerCreateInfoEXT *create_info,
504 const VkAllocationCallbacks *allocator,
505 VkDebugUtilsMessengerEXT *messenger) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700506 VkLayerDbgFunctionNode *pNewDbgFuncNode = (VkLayerDbgFunctionNode *)malloc(sizeof(VkLayerDbgFunctionNode));
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700507 if (!pNewDbgFuncNode) return VK_ERROR_OUT_OF_HOST_MEMORY;
Mark Young6ba8abe2017-11-09 10:37:04 -0700508 memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode));
509 pNewDbgFuncNode->is_messenger = true;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600510
Tobin Ehliseb7715d2015-09-21 09:36:47 -0600511 // Handle of 0 is logging_callback so use allocated Node address as unique handle
Mark Young6ba8abe2017-11-09 10:37:04 -0700512 if (!(*messenger)) *messenger = (VkDebugUtilsMessengerEXT)pNewDbgFuncNode;
513 pNewDbgFuncNode->messenger.messenger = *messenger;
514 pNewDbgFuncNode->messenger.pfnUserCallback = create_info->pfnUserCallback;
515 pNewDbgFuncNode->messenger.messageSeverity = create_info->messageSeverity;
516 pNewDbgFuncNode->messenger.messageType = create_info->messageType;
517 pNewDbgFuncNode->pUserData = create_info->pUserData;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600518
Mark Young6ba8abe2017-11-09 10:37:04 -0700519 debug_data->active_severities |= create_info->messageSeverity;
520 debug_data->active_types |= create_info->messageType;
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600521 if (default_callback) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700522 AddDebugCallbackNode(debug_data, &debug_data->default_debug_callback_list, pNewDbgFuncNode);
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600523 } else {
Mark Young6ba8abe2017-11-09 10:37:04 -0700524 AddDebugCallbackNode(debug_data, &debug_data->debug_callback_list, pNewDbgFuncNode);
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600525 }
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600526
Mark Young6ba8abe2017-11-09 10:37:04 -0700527 VkDebugUtilsMessengerCallbackDataEXT callback_data = {};
528 VkDebugUtilsObjectNameInfoEXT blank_object = {};
529 callback_data.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT;
530 callback_data.pNext = NULL;
531 callback_data.flags = 0;
532 callback_data.pMessageIdName = "Layer Internal Message";
533 callback_data.messageIdNumber = 0;
534 callback_data.pMessage = "Added messenger";
535 callback_data.queueLabelCount = 0;
536 callback_data.pQueueLabels = NULL;
537 callback_data.cmdBufLabelCount = 0;
538 callback_data.pCmdBufLabels = NULL;
539 callback_data.objectCount = 1;
540 callback_data.pObjects = &blank_object;
541 blank_object.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
542 blank_object.pNext = NULL;
543 blank_object.objectType = VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT;
544 blank_object.objectHandle = HandleToUint64(*messenger);
545 blank_object.pObjectName = NULL;
546 debug_messenger_log_msg(debug_data, VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT,
547 VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT, &callback_data);
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600548 return VK_SUCCESS;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600549}
550
Mark Young6ba8abe2017-11-09 10:37:04 -0700551static inline void layer_destroy_report_callback(debug_report_data *debug_data, VkDebugReportCallbackEXT callback,
552 const VkAllocationCallbacks *allocator) {
553 RemoveDebugUtilsMessageCallback(debug_data, &debug_data->debug_callback_list, callback);
554 RemoveDebugUtilsMessageCallback(debug_data, &debug_data->default_debug_callback_list, callback);
555}
556
557static inline VkResult layer_create_report_callback(debug_report_data *debug_data, bool default_callback,
558 const VkDebugReportCallbackCreateInfoEXT *create_info,
559 const VkAllocationCallbacks *allocator, VkDebugReportCallbackEXT *callback) {
560 VkLayerDbgFunctionNode *pNewDbgFuncNode = (VkLayerDbgFunctionNode *)malloc(sizeof(VkLayerDbgFunctionNode));
561 if (!pNewDbgFuncNode) {
562 return VK_ERROR_OUT_OF_HOST_MEMORY;
563 }
564 memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode));
565 pNewDbgFuncNode->is_messenger = false;
566
567 // Handle of 0 is logging_callback so use allocated Node address as unique handle
568 if (!(*callback)) *callback = (VkDebugReportCallbackEXT)pNewDbgFuncNode;
569 pNewDbgFuncNode->report.msgCallback = *callback;
570 pNewDbgFuncNode->report.pfnMsgCallback = create_info->pfnCallback;
571 pNewDbgFuncNode->report.msgFlags = create_info->flags;
572 pNewDbgFuncNode->pUserData = create_info->pUserData;
573
574 VkFlags local_severity = 0;
575 VkFlags local_type = 0;
576 DebugReportFlagsToAnnotFlags(create_info->flags, true, &local_severity, &local_type);
577 debug_data->active_severities |= local_severity;
578 debug_data->active_types |= local_type;
579 if (default_callback) {
580 AddDebugCallbackNode(debug_data, &debug_data->default_debug_callback_list, pNewDbgFuncNode);
581 } else {
582 AddDebugCallbackNode(debug_data, &debug_data->debug_callback_list, pNewDbgFuncNode);
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600583 }
584
Mark Young6ba8abe2017-11-09 10:37:04 -0700585 debug_log_msg(debug_data, VK_DEBUG_REPORT_DEBUG_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT, (uint64_t)*callback, 0,
586 0, "DebugReport", "Added callback");
587 return VK_SUCCESS;
588}
589
590static inline PFN_vkVoidFunction debug_utils_get_instance_proc_addr(debug_report_data *debug_data, const char *func_name) {
591 if (!debug_data) {
592 return NULL;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600593 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700594 if (debug_data->g_DEBUG_REPORT) {
595 if (!strcmp(func_name, "vkCreateDebugReportCallbackEXT")) {
596 return (PFN_vkVoidFunction)vkCreateDebugReportCallbackEXT;
597 }
598 if (!strcmp(func_name, "vkDestroyDebugReportCallbackEXT")) {
599 return (PFN_vkVoidFunction)vkDestroyDebugReportCallbackEXT;
600 }
601 if (!strcmp(func_name, "vkDebugReportMessageEXT")) {
602 return (PFN_vkVoidFunction)vkDebugReportMessageEXT;
603 }
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600604 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700605 if (debug_data->g_DEBUG_UTILS) {
606 if (!strcmp(func_name, "vkCreateDebugUtilsMessengerEXT")) {
607 return (PFN_vkVoidFunction)vkCreateDebugUtilsMessengerEXT;
608 }
609 if (!strcmp(func_name, "vkDestroyDebugUtilsMessengerEXT")) {
610 return (PFN_vkVoidFunction)vkDestroyDebugUtilsMessengerEXT;
611 }
612 if (!strcmp(func_name, "vkSubmitDebugUtilsMessageEXT")) {
613 return (PFN_vkVoidFunction)vkSubmitDebugUtilsMessageEXT;
614 }
Courtney Goeltzenleuchter822e8d72015-11-30 15:28:25 -0700615 }
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600616 return NULL;
617}
618
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600619// This utility (called at vkCreateInstance() time), looks at a pNext chain.
620// It counts any VkDebugReportCallbackCreateInfoEXT structs that it finds. It
621// then allocates an array that can hold that many structs, as well as that
622// many VkDebugReportCallbackEXT handles. It then copies each
623// VkDebugReportCallbackCreateInfoEXT, and initializes each handle.
Mark Young6ba8abe2017-11-09 10:37:04 -0700624static inline VkResult layer_copy_tmp_report_callbacks(const void *pChain, uint32_t *num_callbacks,
625 VkDebugReportCallbackCreateInfoEXT **infos,
626 VkDebugReportCallbackEXT **callbacks) {
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600627 uint32_t n = *num_callbacks = 0;
628
629 const void *pNext = pChain;
630 while (pNext) {
631 // 1st, count the number VkDebugReportCallbackCreateInfoEXT:
632 if (((VkDebugReportCallbackCreateInfoEXT *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT) {
633 n++;
634 }
635 pNext = (void *)((VkDebugReportCallbackCreateInfoEXT *)pNext)->pNext;
636 }
637 if (n == 0) {
638 return VK_SUCCESS;
639 }
640
641 // 2nd, allocate memory for each VkDebugReportCallbackCreateInfoEXT:
642 VkDebugReportCallbackCreateInfoEXT *pInfos = *infos =
643 ((VkDebugReportCallbackCreateInfoEXT *)malloc(n * sizeof(VkDebugReportCallbackCreateInfoEXT)));
644 if (!pInfos) {
645 return VK_ERROR_OUT_OF_HOST_MEMORY;
646 }
647 // 3rd, allocate memory for a unique handle for each callback:
648 VkDebugReportCallbackEXT *pCallbacks = *callbacks = ((VkDebugReportCallbackEXT *)malloc(n * sizeof(VkDebugReportCallbackEXT)));
649 if (!pCallbacks) {
650 free(pInfos);
651 return VK_ERROR_OUT_OF_HOST_MEMORY;
652 }
653 // 4th, copy each VkDebugReportCallbackCreateInfoEXT for use by
654 // vkDestroyInstance, and assign a unique handle to each callback (just
655 // use the address of the copied VkDebugReportCallbackCreateInfoEXT):
656 pNext = pChain;
657 while (pNext) {
658 if (((VkInstanceCreateInfo *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT) {
659 memcpy(pInfos, pNext, sizeof(VkDebugReportCallbackCreateInfoEXT));
660 *pCallbacks++ = (VkDebugReportCallbackEXT)pInfos++;
661 }
662 pNext = (void *)((VkInstanceCreateInfo *)pNext)->pNext;
663 }
664
665 *num_callbacks = n;
666 return VK_SUCCESS;
667}
668
Mark Young6ba8abe2017-11-09 10:37:04 -0700669// This utility frees the arrays allocated by layer_copy_tmp_report_callbacks()
670static inline void layer_free_tmp_report_callbacks(VkDebugReportCallbackCreateInfoEXT *infos, VkDebugReportCallbackEXT *callbacks) {
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600671 free(infos);
672 free(callbacks);
673}
674
675// This utility enables all of the VkDebugReportCallbackCreateInfoEXT structs
Mark Young6ba8abe2017-11-09 10:37:04 -0700676// that were copied by layer_copy_tmp_report_callbacks()
677static inline VkResult layer_enable_tmp_report_callbacks(debug_report_data *debug_data, uint32_t num_callbacks,
678 VkDebugReportCallbackCreateInfoEXT *infos,
679 VkDebugReportCallbackEXT *callbacks) {
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600680 VkResult rtn = VK_SUCCESS;
681 for (uint32_t i = 0; i < num_callbacks; i++) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700682 rtn = layer_create_report_callback(debug_data, false, &infos[i], NULL, &callbacks[i]);
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600683 if (rtn != VK_SUCCESS) {
684 for (uint32_t j = 0; j < i; j++) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700685 layer_destroy_report_callback(debug_data, callbacks[j], NULL);
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600686 }
687 return rtn;
688 }
689 }
690 return rtn;
691}
692
693// This utility disables all of the VkDebugReportCallbackCreateInfoEXT structs
Mark Young6ba8abe2017-11-09 10:37:04 -0700694// that were copied by layer_copy_tmp_report_callbacks()
695static inline void layer_disable_tmp_report_callbacks(debug_report_data *debug_data, uint32_t num_callbacks,
696 VkDebugReportCallbackEXT *callbacks) {
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600697 for (uint32_t i = 0; i < num_callbacks; i++) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700698 layer_destroy_report_callback(debug_data, callbacks[i], NULL);
699 }
700}
701
702// This utility (called at vkCreateInstance() time), looks at a pNext chain.
703// It counts any VkDebugUtilsMessengerCreateInfoEXT structs that it finds. It
704// then allocates an array that can hold that many structs, as well as that
705// many VkDebugUtilsMessengerEXT handles. It then copies each
706// VkDebugUtilsMessengerCreateInfoEXT, and initializes each handle.
Mark Young8504ba62018-03-21 13:35:34 -0600707static inline VkResult layer_copy_tmp_debug_messengers(const void *pChain, uint32_t *num_messengers,
708 VkDebugUtilsMessengerCreateInfoEXT **infos,
709 VkDebugUtilsMessengerEXT **messengers) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700710 uint32_t n = *num_messengers = 0;
711
712 const void *pNext = pChain;
713 while (pNext) {
714 // 1st, count the number VkDebugUtilsMessengerCreateInfoEXT:
715 if (((VkDebugUtilsMessengerCreateInfoEXT *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT) {
716 n++;
717 }
718 pNext = (void *)((VkDebugUtilsMessengerCreateInfoEXT *)pNext)->pNext;
719 }
720 if (n == 0) {
721 return VK_SUCCESS;
722 }
723
724 // 2nd, allocate memory for each VkDebugUtilsMessengerCreateInfoEXT:
725 VkDebugUtilsMessengerCreateInfoEXT *pInfos = *infos =
726 ((VkDebugUtilsMessengerCreateInfoEXT *)malloc(n * sizeof(VkDebugUtilsMessengerCreateInfoEXT)));
727 if (!pInfos) {
728 return VK_ERROR_OUT_OF_HOST_MEMORY;
729 }
730 // 3rd, allocate memory for a unique handle for each messenger:
731 VkDebugUtilsMessengerEXT *pMessengers = *messengers =
732 ((VkDebugUtilsMessengerEXT *)malloc(n * sizeof(VkDebugUtilsMessengerEXT)));
733 if (!pMessengers) {
734 free(pInfos);
735 return VK_ERROR_OUT_OF_HOST_MEMORY;
736 }
737 // 4th, copy each VkDebugUtilsMessengerCreateInfoEXT for use by
738 // vkDestroyInstance, and assign a unique handle to each callback (just
739 // use the address of the copied VkDebugUtilsMessengerCreateInfoEXT):
740 pNext = pChain;
741 while (pNext) {
742 if (((VkInstanceCreateInfo *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT) {
743 memcpy(pInfos, pNext, sizeof(VkDebugUtilsMessengerCreateInfoEXT));
744 *pMessengers++ = (VkDebugUtilsMessengerEXT)pInfos++;
745 }
746 pNext = (void *)((VkInstanceCreateInfo *)pNext)->pNext;
747 }
748
749 *num_messengers = n;
750 return VK_SUCCESS;
751}
752
753// This utility frees the arrays allocated by layer_copy_tmp_debug_messengers()
Mark Young8504ba62018-03-21 13:35:34 -0600754static inline void layer_free_tmp_debug_messengers(VkDebugUtilsMessengerCreateInfoEXT *infos,
755 VkDebugUtilsMessengerEXT *messengers) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700756 free(infos);
757 free(messengers);
758}
759
760// This utility enables all of the VkDebugUtilsMessengerCreateInfoEXT structs
761// that were copied by layer_copy_tmp_debug_messengers()
Mark Young8504ba62018-03-21 13:35:34 -0600762static inline VkResult layer_enable_tmp_debug_messengers(debug_report_data *debug_data, uint32_t num_messengers,
763 VkDebugUtilsMessengerCreateInfoEXT *infos,
764 VkDebugUtilsMessengerEXT *messengers) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700765 VkResult rtn = VK_SUCCESS;
766 for (uint32_t i = 0; i < num_messengers; i++) {
767 rtn = layer_create_messenger_callback(debug_data, false, &infos[i], NULL, &messengers[i]);
768 if (rtn != VK_SUCCESS) {
769 for (uint32_t j = 0; j < i; j++) {
770 layer_destroy_messenger_callback(debug_data, messengers[j], NULL);
771 }
772 return rtn;
773 }
774 }
775 return rtn;
776}
777
778// This utility disables all of the VkDebugUtilsMessengerCreateInfoEXT structs
779// that were copied by layer_copy_tmp_debug_messengers()
Mark Young8504ba62018-03-21 13:35:34 -0600780static inline void layer_disable_tmp_debug_messengers(debug_report_data *debug_data, uint32_t num_messengers,
781 VkDebugUtilsMessengerEXT *messengers) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700782 for (uint32_t i = 0; i < num_messengers; i++) {
783 layer_destroy_messenger_callback(debug_data, messengers[i], NULL);
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600784 }
785}
786
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600787// Checks if the message will get logged.
788// Allows layer to defer collecting & formating data if the
789// message will be discarded.
Mark Young6ba8abe2017-11-09 10:37:04 -0700790static inline bool will_log_msg(debug_report_data *debug_data, VkFlags msg_flags) {
791 VkFlags local_severity = 0;
792 VkFlags local_type = 0;
793 DebugReportFlagsToAnnotFlags(msg_flags, true, &local_severity, &local_type);
794 if (!debug_data || !(debug_data->active_severities & local_severity) || !(debug_data->active_types & local_type)) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600795 // Message is not wanted
Courtney Goeltzenleuchter6a564a12015-09-18 16:30:24 -0600796 return false;
797 }
798
799 return true;
800}
John Zulauf6664e272018-01-17 11:00:22 -0700801#ifndef WIN32
Mark Lobodzinski1bcbdf92018-02-07 10:00:22 -0700802static inline int string_sprintf(std::string *output, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
John Zulauf6664e272018-01-17 11:00:22 -0700803#endif
Mark Lobodzinski1bcbdf92018-02-07 10:00:22 -0700804static inline int string_sprintf(std::string *output, const char *fmt, ...) {
John Zulauf6664e272018-01-17 11:00:22 -0700805 std::string &formatted = *output;
806 va_list argptr;
807 va_start(argptr, fmt);
808 int reserve = vsnprintf(nullptr, 0, fmt, argptr);
809 va_end(argptr);
810 formatted.reserve(reserve + 1);
811 va_start(argptr, fmt);
812 int result = vsnprintf((char *)formatted.data(), formatted.capacity(), fmt, argptr);
813 va_end(argptr);
814 assert(result == reserve);
815 return result;
816}
Courtney Goeltzenleuchter6a564a12015-09-18 16:30:24 -0600817
Chris Forbes8a25bce2016-03-24 12:06:35 +1300818#ifdef WIN32
819static inline int vasprintf(char **strp, char const *fmt, va_list ap) {
820 *strp = nullptr;
821 int size = _vscprintf(fmt, ap);
822 if (size >= 0) {
Mark Lobodzinski729a8d32017-01-26 12:16:30 -0700823 *strp = (char *)malloc(size + 1);
Chris Forbes8a25bce2016-03-24 12:06:35 +1300824 if (!*strp) {
825 return -1;
826 }
Mark Lobodzinski729a8d32017-01-26 12:16:30 -0700827 _vsnprintf(*strp, size + 1, fmt, ap);
Chris Forbes8a25bce2016-03-24 12:06:35 +1300828 }
829 return size;
830}
831#endif
832
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700833// Output log message via DEBUG_REPORT. Takes format and variable arg list so that output string is only computed if a message
834// needs to be logged
Michael Lentine010f4692015-11-03 16:19:46 -0800835#ifndef WIN32
Mark Young6ba8abe2017-11-09 10:37:04 -0700836static inline bool log_msg(const debug_report_data *debug_data, VkFlags msg_flags, VkDebugReportObjectTypeEXT object_type,
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700837 uint64_t src_object, std::string vuid_text, const char *format, ...)
838 __attribute__((format(printf, 6, 7)));
Michael Lentine010f4692015-11-03 16:19:46 -0800839#endif
Mark Young6ba8abe2017-11-09 10:37:04 -0700840static inline bool log_msg(const debug_report_data *debug_data, VkFlags msg_flags, VkDebugReportObjectTypeEXT object_type,
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700841 uint64_t src_object, std::string vuid_text, const char *format, ...) {
842 VkFlags local_severity = 0;
843 VkFlags local_type = 0;
844 DebugReportFlagsToAnnotFlags(msg_flags, true, &local_severity, &local_type);
845 if (!debug_data || !(debug_data->active_severities & local_severity) || !(debug_data->active_types & local_type)) {
846 // Message is not wanted
847 return false;
848 }
849
850 va_list argptr;
851 va_start(argptr, format);
852 char *str;
853 if (-1 == vasprintf(&str, format, argptr)) {
854 // On failure, glibc vasprintf leaves str undefined
855 str = nullptr;
856 }
857 va_end(argptr);
858
859 std::string str_plus_spec_text(str);
860
Dave Houlton8e9f6542018-05-18 12:18:22 -0600861 // If the vuid string is in the error map: find the legacy enum, look up spec text, and tack it onto error message.
862 int32_t legacy_vuid_enum = VALIDATION_ERROR_UNDEFINED;
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700863 if (validation_error_text_map.find(vuid_text.c_str()) != validation_error_text_map.end()) {
Dave Houlton8e9f6542018-05-18 12:18:22 -0600864 legacy_vuid_enum = validation_error_text_map[vuid_text.c_str()];
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700865 str_plus_spec_text += " ";
Dave Houlton8e9f6542018-05-18 12:18:22 -0600866 str_plus_spec_text += validation_error_map[legacy_vuid_enum];
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700867 }
868
Dave Houlton8e9f6542018-05-18 12:18:22 -0600869 // Append layer prefix with VUID string, pass in recovered legacy numerical VUID
870 bool result = debug_log_msg(debug_data, msg_flags, object_type, src_object, 0, legacy_vuid_enum, "Validation",
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700871 str_plus_spec_text.c_str() ? str_plus_spec_text.c_str() : "Allocation failure", vuid_text.c_str());
872
873 free(str);
874 return result;
875}
876
Mark Young6ba8abe2017-11-09 10:37:04 -0700877static inline VKAPI_ATTR VkBool32 VKAPI_CALL report_log_callback(VkFlags msg_flags, 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) {
880 char msg_flag_string[30];
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600881
Mark Young6ba8abe2017-11-09 10:37:04 -0700882 PrintMessageFlags(msg_flags, msg_flag_string);
Courtney Goeltzenleuchter2f25bb42015-06-14 11:29:24 -0600883
Mark Lobodzinskib1fd9d12018-03-30 14:26:00 -0600884 fprintf((FILE *)user_data, "%s(%s): msg_code: %d: %s\n", layer_prefix, msg_flag_string, msg_code, message);
Mark Young6ba8abe2017-11-09 10:37:04 -0700885 fflush((FILE *)user_data);
Courtney Goeltzenleuchter06640832015-09-04 13:52:24 -0600886
887 return false;
Courtney Goeltzenleuchter2f25bb42015-06-14 11:29:24 -0600888}
Courtney Goeltzenleuchter5907ac42015-10-05 14:41:34 -0600889
Mark Young6ba8abe2017-11-09 10:37:04 -0700890static inline VKAPI_ATTR VkBool32 VKAPI_CALL report_win32_debug_output_msg(VkFlags msg_flags, VkDebugReportObjectTypeEXT obj_type,
891 uint64_t src_object, size_t location, int32_t msg_code,
892 const char *layer_prefix, const char *message,
893 void *user_data) {
Courtney Goeltzenleuchter5907ac42015-10-05 14:41:34 -0600894#ifdef WIN32
Mark Young6ba8abe2017-11-09 10:37:04 -0700895 char msg_flag_string[30];
Courtney Goeltzenleuchter5907ac42015-10-05 14:41:34 -0600896 char buf[2048];
897
Mark Young6ba8abe2017-11-09 10:37:04 -0700898 PrintMessageFlags(msg_flags, msg_flag_string);
Mark Lobodzinskib1fd9d12018-03-30 14:26:00 -0600899 _snprintf(buf, sizeof(buf) - 1, "%s (%s): msg_code: %d: %s\n", layer_prefix, msg_flag_string, msg_code, message);
Courtney Goeltzenleuchter5907ac42015-10-05 14:41:34 -0600900
901 OutputDebugString(buf);
902#endif
903
904 return false;
905}
906
Mark Young6ba8abe2017-11-09 10:37:04 -0700907static inline VKAPI_ATTR VkBool32 VKAPI_CALL DebugBreakCallback(VkFlags msgFlags, VkDebugReportObjectTypeEXT obj_type,
908 uint64_t src_object, size_t location, int32_t msg_code,
909 const char *layer_prefix, const char *message, void *user_data) {
Mark Lobodzinskic9d81652017-08-10 11:01:17 -0600910#ifdef WIN32
911 DebugBreak();
912#else
913 raise(SIGTRAP);
914#endif
915
916 return false;
917}
918
Mark Young6ba8abe2017-11-09 10:37:04 -0700919static inline VKAPI_ATTR VkBool32 VKAPI_CALL messenger_log_callback(VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
920 VkDebugUtilsMessageTypeFlagsEXT message_type,
921 const VkDebugUtilsMessengerCallbackDataEXT *callback_data,
922 void *user_data) {
923 char msg_severity[30];
924 char msg_type[30];
925
926 PrintMessageSeverity(message_severity, msg_severity);
927 PrintMessageType(message_type, msg_type);
928
Mark Young8504ba62018-03-21 13:35:34 -0600929 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 -0700930 callback_data->messageIdNumber, callback_data->pMessage);
Mark Young8504ba62018-03-21 13:35:34 -0600931 fprintf((FILE *)user_data, " Objects: %d\n", callback_data->objectCount);
932 for (uint32_t obj = 0; obj < callback_data->objectCount; ++obj) {
933 fprintf((FILE *)user_data, " [%d] 0x%" PRIx64 ", type: %d, name: %s\n", obj,
934 callback_data->pObjects[obj].objectHandle, callback_data->pObjects[obj].objectType,
935 callback_data->pObjects[obj].pObjectName);
936 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700937 fflush((FILE *)user_data);
938
939 return false;
Petr Krause9388f62017-05-13 20:53:12 +0200940}
941
Mark Young6ba8abe2017-11-09 10:37:04 -0700942static inline VKAPI_ATTR VkBool32 VKAPI_CALL messenger_win32_debug_output_msg(
943 VkDebugUtilsMessageSeverityFlagBitsEXT message_severity, VkDebugUtilsMessageTypeFlagsEXT message_type,
944 const VkDebugUtilsMessengerCallbackDataEXT *callback_data, void *user_data) {
945#ifdef WIN32
946 char buf[2048];
947 char msg_severity[30];
948 char msg_type[30];
Mark Lobodzinski863d5de2017-05-22 10:10:07 -0600949
Mark Young6ba8abe2017-11-09 10:37:04 -0700950 PrintMessageSeverity(message_severity, msg_severity);
951 PrintMessageType(message_type, msg_type);
952
Mark Young8504ba62018-03-21 13:35:34 -0600953 size_t buffer_space = sizeof(buf) - 1;
954 size_t remaining_space = buffer_space;
955 _snprintf(buf, sizeof(buf) - 1, "%s(%s / %s): msgNum: %d - %s\n", callback_data->pMessageIdName, msg_severity, msg_type,
956 callback_data->messageIdNumber, callback_data->pMessage);
957 remaining_space = buffer_space - strlen(buf);
958 _snprintf(buf, remaining_space, " Objects: %d\n", callback_data->objectCount);
959 for (uint32_t obj = 0; obj < callback_data->objectCount; ++obj) {
960 remaining_space = buffer_space - strlen(buf);
961 if (remaining_space > 0) {
962 _snprintf(buf, remaining_space, " [%d] 0x%" PRIx64 ", type: %d, name: %s\n", obj,
963 callback_data->pObjects[obj].objectHandle, callback_data->pObjects[obj].objectType,
964 callback_data->pObjects[obj].pObjectName);
965 }
966 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700967 OutputDebugString(buf);
968#endif
969
970 return false;
971}
972
973// This utility converts from the VkDebugUtilsLabelEXT structure into the logging version of the structure.
974// In the logging version, we only record what we absolutely need to convey back to the callbacks.
975static inline void InsertLabelIntoLog(const VkDebugUtilsLabelEXT *utils_label, std::vector<LoggingLabelData> &log_vector) {
976 LoggingLabelData log_label_data = {};
977 log_label_data.name = utils_label->pLabelName;
978 log_label_data.color[0] = utils_label->color[0];
979 log_label_data.color[1] = utils_label->color[1];
980 log_label_data.color[2] = utils_label->color[2];
981 log_label_data.color[3] = utils_label->color[3];
982 log_vector.push_back(log_label_data);
983}
984
Mark Young8504ba62018-03-21 13:35:34 -0600985static inline void BeginQueueDebugUtilsLabel(debug_report_data *report_data, VkQueue queue,
986 const VkDebugUtilsLabelEXT *label_info) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700987 if (nullptr != label_info && nullptr != label_info->pLabelName) {
988 auto label_iter = report_data->debugUtilsQueueLabels->find(queue);
989 if (label_iter == report_data->debugUtilsQueueLabels->end()) {
990 std::vector<LoggingLabelData> new_queue_labels;
991 InsertLabelIntoLog(label_info, new_queue_labels);
992 report_data->debugUtilsQueueLabels->insert({queue, new_queue_labels});
993 } else {
994 // If the last thing was a label insert, we need to pop it off of the label vector before any
995 // changes. This is because a label added with "vkQueueInsertDebugUtilsLabelEXT" is only a
996 // temporary location that exists until the next operation occurs. In this case, a new
997 // "vkQueueBeginDebugUtilsLabelEXT" has occurred erasing the previous inserted label.
998 if (report_data->queueLabelHasInsert) {
999 report_data->queueLabelHasInsert = false;
1000 label_iter->second.pop_back();
1001 }
1002 InsertLabelIntoLog(label_info, label_iter->second);
1003 }
1004 }
1005}
1006
Mark Young8504ba62018-03-21 13:35:34 -06001007static inline void EndQueueDebugUtilsLabel(debug_report_data *report_data, VkQueue queue) {
Mark Young6ba8abe2017-11-09 10:37:04 -07001008 auto label_iter = report_data->debugUtilsQueueLabels->find(queue);
1009 if (label_iter != report_data->debugUtilsQueueLabels->end()) {
1010 // If the last thing was a label insert, we need to pop it off of the label vector before any
1011 // changes. This is because a label added with "vkQueueInsertDebugUtilsLabelEXT" is only a
1012 // temporary location that exists until the next operation occurs. In this case, a
1013 // "vkQueueEndDebugUtilsLabelEXT" has occurred erasing the inserted label.
1014 if (report_data->queueLabelHasInsert) {
1015 report_data->queueLabelHasInsert = false;
1016 label_iter->second.pop_back();
1017 }
1018 // Now pop the normal item
1019 label_iter->second.pop_back();
1020 }
1021}
1022
Mark Young8504ba62018-03-21 13:35:34 -06001023static inline void InsertQueueDebugUtilsLabel(debug_report_data *report_data, VkQueue queue,
1024 const VkDebugUtilsLabelEXT *label_info) {
Mark Young6ba8abe2017-11-09 10:37:04 -07001025 if (nullptr != label_info && nullptr != label_info->pLabelName) {
1026 auto label_iter = report_data->debugUtilsQueueLabels->find(queue);
1027 if (label_iter == report_data->debugUtilsQueueLabels->end()) {
1028 std::vector<LoggingLabelData> new_queue_labels;
1029 InsertLabelIntoLog(label_info, new_queue_labels);
1030 report_data->debugUtilsQueueLabels->insert({queue, new_queue_labels});
1031 } else {
1032 // If the last thing was a label insert, we need to pop it off of the label vector before any
1033 // changes. This is because a label added with "vkQueueInsertDebugUtilsLabelEXT" is only a
1034 // temporary location that exists until the next operation occurs. In this case, a new
1035 // "vkQueueInsertDebugUtilsLabelEXT" has occurred erasing the previous inserted label.
1036 if (report_data->queueLabelHasInsert) {
1037 label_iter->second.pop_back();
1038 }
1039 // Insert this new label and mark it as one that has been "inserted" so we can remove it on
1040 // the next queue label operation.
1041 InsertLabelIntoLog(label_info, label_iter->second);
1042 report_data->queueLabelHasInsert = true;
1043 }
1044 }
1045}
1046
Mark Young8504ba62018-03-21 13:35:34 -06001047static inline void BeginCmdDebugUtilsLabel(debug_report_data *report_data, VkCommandBuffer command_buffer,
1048 const VkDebugUtilsLabelEXT *label_info) {
Mark Young6ba8abe2017-11-09 10:37:04 -07001049 if (nullptr != label_info && nullptr != label_info->pLabelName) {
1050 auto label_iter = report_data->debugUtilsCmdBufLabels->find(command_buffer);
1051 if (label_iter == report_data->debugUtilsCmdBufLabels->end()) {
1052 std::vector<LoggingLabelData> new_cmdbuf_labels;
1053 InsertLabelIntoLog(label_info, new_cmdbuf_labels);
1054 report_data->debugUtilsCmdBufLabels->insert({command_buffer, new_cmdbuf_labels});
1055 } else {
1056 // If the last thing was a label insert, we need to pop it off of the label vector before any
1057 // changes. This is because a label added with "vkCmdInsertDebugUtilsLabelEXT" is only a
1058 // temporary location that exists until the next operation occurs. In this case, a
1059 // "vkCmdBeginDebugUtilsLabelEXT" has occurred erasing the inserted label.
1060 if (report_data->cmdBufLabelHasInsert) {
1061 report_data->cmdBufLabelHasInsert = false;
1062 label_iter->second.pop_back();
1063 }
1064 InsertLabelIntoLog(label_info, label_iter->second);
1065 }
1066 }
1067}
1068
Mark Young8504ba62018-03-21 13:35:34 -06001069static inline void EndCmdDebugUtilsLabel(debug_report_data *report_data, VkCommandBuffer command_buffer) {
Mark Young6ba8abe2017-11-09 10:37:04 -07001070 auto label_iter = report_data->debugUtilsCmdBufLabels->find(command_buffer);
1071 if (label_iter != report_data->debugUtilsCmdBufLabels->end()) {
1072 // If the last thing was a label insert, we need to pop it off of the label vector before any
1073 // changes. This is because a label added with "vkCmdInsertDebugUtilsLabelEXT" is only a
1074 // temporary location that exists until the next operation occurs. In this case, a
1075 // "vkCmdEndDebugUtilsLabelEXT" has occurred erasing the inserted label.
1076 if (report_data->cmdBufLabelHasInsert) {
1077 report_data->cmdBufLabelHasInsert = false;
1078 label_iter->second.pop_back();
1079 }
1080 // Now pop the normal item
1081 label_iter->second.pop_back();
1082 }
1083}
1084
Mark Young8504ba62018-03-21 13:35:34 -06001085static inline void InsertCmdDebugUtilsLabel(debug_report_data *report_data, VkCommandBuffer command_buffer,
1086 const VkDebugUtilsLabelEXT *label_info) {
Mark Young6ba8abe2017-11-09 10:37:04 -07001087 if (nullptr != label_info && nullptr != label_info->pLabelName) {
1088 auto label_iter = report_data->debugUtilsCmdBufLabels->find(command_buffer);
1089 if (label_iter == report_data->debugUtilsCmdBufLabels->end()) {
1090 std::vector<LoggingLabelData> new_cmdbuf_labels;
1091 InsertLabelIntoLog(label_info, new_cmdbuf_labels);
1092 report_data->debugUtilsCmdBufLabels->insert({command_buffer, new_cmdbuf_labels});
1093 } else {
1094 // If the last thing was a label insert, we need to pop it off of the label vector before any
1095 // changes. This is because a label added with "vkCmdInsertDebugUtilsLabelEXT" is only a
1096 // temporary location that exists until the next operation occurs. In this case, a new
1097 // "vkCmdInsertDebugUtilsLabelEXT" has occurred erasing the previous inserted label.
1098 if (report_data->cmdBufLabelHasInsert) {
1099 label_iter->second.pop_back();
1100 }
1101 // Insert this new label and mark it as one that has been "inserted" so we can remove it on
1102 // the next command buffer label operation.
1103 InsertLabelIntoLog(label_info, label_iter->second);
1104 report_data->cmdBufLabelHasInsert = true;
1105 }
1106 }
1107}
Mark Lobodzinski863d5de2017-05-22 10:10:07 -06001108
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001109#endif // LAYER_LOGGING_H