blob: 039e0d3bc4573bb7d9e113fcd683da6f022f1c6e [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 Youngfbaae712018-10-04 14:33:50 -060091 *da_type = 0;
Mark Youngc2347792018-05-30 08:41:25 -060092 // If it's explicitly listed as a performance warning, treat it as a performance message.
93 // Otherwise, treat it as a validation issue.
94 if ((dr_flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) != 0) {
Mark Youngfbaae712018-10-04 14:33:50 -060095 *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
96 *da_severity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
Mark Youngc2347792018-05-30 08:41:25 -060097 }
Mark Young6ba8abe2017-11-09 10:37:04 -070098 if ((dr_flags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) != 0) {
Mark Youngfbaae712018-10-04 14:33:50 -060099 *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;
Mark Young6ba8abe2017-11-09 10:37:04 -0700100 *da_severity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT;
Mark Young6ba8abe2017-11-09 10:37:04 -0700101 }
102 if ((dr_flags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) != 0) {
Mark Youngfbaae712018-10-04 14:33:50 -0600103 *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;
Mark Young6ba8abe2017-11-09 10:37:04 -0700104 *da_severity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
Mark Young6ba8abe2017-11-09 10:37:04 -0700105 }
Mark Youngfbaae712018-10-04 14:33:50 -0600106 if ((dr_flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) != 0) {
107 *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;
Mark Young6ba8abe2017-11-09 10:37:04 -0700108 *da_severity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
109 }
110 if ((dr_flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) != 0) {
Mark Youngfbaae712018-10-04 14:33:50 -0600111 *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;
Mark Young6ba8abe2017-11-09 10:37:04 -0700112 *da_severity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
113 }
114}
115
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600116// Forward Declarations
Mark Young6ba8abe2017-11-09 10:37:04 -0700117static inline bool debug_log_msg(const debug_report_data *debug_data, VkFlags msg_flags, VkDebugReportObjectTypeEXT object_type,
Dave Houlton407df732018-08-06 17:58:24 -0600118 uint64_t src_object, size_t location, const char *layer_prefix, const char *message,
119 const char *text_vuid);
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600120
121// Add a debug message callback node structure to the specified callback linked list
Mark Young6ba8abe2017-11-09 10:37:04 -0700122static inline void AddDebugCallbackNode(debug_report_data *debug_data, VkLayerDbgFunctionNode **list_head,
123 VkLayerDbgFunctionNode *new_node) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600124 new_node->pNext = *list_head;
125 *list_head = new_node;
126}
127
Mark Young6ba8abe2017-11-09 10:37:04 -0700128// Remove specified debug messenger node structure from the specified linked list
129static inline void RemoveDebugUtilsMessenger(debug_report_data *debug_data, VkLayerDbgFunctionNode **list_head,
130 VkDebugUtilsMessengerEXT messenger) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600131 VkLayerDbgFunctionNode *cur_callback = *list_head;
Mark Youngfbaae712018-10-04 14:33:50 -0600132 VkLayerDbgFunctionNode *prev_callback = nullptr;
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600133 bool matched = false;
Mark Young6ba8abe2017-11-09 10:37:04 -0700134 VkFlags local_severities = 0;
135 VkFlags local_types = 0;
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600136
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600137 while (cur_callback) {
Mark Youngfbaae712018-10-04 14:33:50 -0600138 if (cur_callback->is_messenger) {
139 // If it's actually a messenger, then set it up for deletion.
140 if (cur_callback->messenger.messenger == messenger) {
141 matched = true;
142 if (*list_head == cur_callback) {
143 *list_head = cur_callback->pNext;
144 } else {
145 assert(nullptr != prev_callback);
146 prev_callback->pNext = cur_callback->pNext;
147 }
148 debug_log_msg(debug_data, VK_DEBUG_REPORT_DEBUG_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT,
149 reinterpret_cast<uint64_t &>(cur_callback->messenger.messenger), 0, "DebugUtilsMessenger",
150 "Destroyed messenger\n", kVUIDUndefined);
151 } else {
152 // If it's not the one we're looking for, just keep the types/severities
153 local_severities |= cur_callback->messenger.messageSeverity;
154 local_types |= cur_callback->messenger.messageType;
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600155 }
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600156 } else {
Mark Youngfbaae712018-10-04 14:33:50 -0600157 // If it's not a messenger, just keep the types/severities
158 VkFlags this_severities = 0;
159 VkFlags this_types = 0;
160 DebugReportFlagsToAnnotFlags(cur_callback->report.msgFlags, true, &this_severities, &this_types);
161 local_severities |= this_severities;
162 local_types |= this_types;
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600163 }
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600164 if (matched) {
Mark Youngfbaae712018-10-04 14:33:50 -0600165 free(cur_callback);
166 matched = false;
167 // Intentionally keep the last prev_callback, but select the proper cur_callback
168 if (nullptr != prev_callback) {
169 cur_callback = prev_callback->pNext;
170 } else {
171 cur_callback = *list_head;
172 }
173 } else {
174 prev_callback = cur_callback;
175 cur_callback = cur_callback->pNext;
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600176 }
177 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700178 debug_data->active_severities = local_severities;
179 debug_data->active_types = local_types;
180}
181
182// Remove specified debug message callback node structure from the specified callback linked list
183static inline void RemoveDebugUtilsMessageCallback(debug_report_data *debug_data, VkLayerDbgFunctionNode **list_head,
184 VkDebugReportCallbackEXT callback) {
185 VkLayerDbgFunctionNode *cur_callback = *list_head;
Mark Youngfbaae712018-10-04 14:33:50 -0600186 VkLayerDbgFunctionNode *prev_callback = nullptr;
Mark Young6ba8abe2017-11-09 10:37:04 -0700187 bool matched = false;
188 VkFlags local_severities = 0;
189 VkFlags local_types = 0;
190
191 while (cur_callback) {
Mark Youngfbaae712018-10-04 14:33:50 -0600192 if (!cur_callback->is_messenger) {
193 // If it's actually a callback, then set it up for deletion.
194 if (cur_callback->report.msgCallback == callback) {
195 matched = true;
196 if (*list_head == cur_callback) {
197 *list_head = cur_callback->pNext;
198 } else {
199 assert(nullptr != prev_callback);
200 prev_callback->pNext = cur_callback->pNext;
201 }
202 debug_log_msg(debug_data, VK_DEBUG_REPORT_DEBUG_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT,
203 reinterpret_cast<uint64_t &>(cur_callback->report.msgCallback), 0, "DebugReport",
204 "Destroyed callback\n", kVUIDUndefined);
205 } else {
206 // If it's not the one we're looking for, just keep the types/severities
207 VkFlags this_severities = 0;
208 VkFlags this_types = 0;
209 DebugReportFlagsToAnnotFlags(cur_callback->report.msgFlags, true, &this_severities, &this_types);
210 local_severities |= this_severities;
211 local_types |= this_types;
Mark Young6ba8abe2017-11-09 10:37:04 -0700212 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700213 } else {
Mark Youngfbaae712018-10-04 14:33:50 -0600214 // If it's not a callback, just keep the types/severities
215 local_severities |= cur_callback->messenger.messageSeverity;
216 local_types |= cur_callback->messenger.messageType;
Mark Young6ba8abe2017-11-09 10:37:04 -0700217 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700218 if (matched) {
Mark Youngfbaae712018-10-04 14:33:50 -0600219 free(cur_callback);
220 matched = false;
221 // Intentionally keep the last prev_callback, but select the proper cur_callback
222 if (nullptr != prev_callback) {
223 cur_callback = prev_callback->pNext;
224 } else {
225 cur_callback = *list_head;
226 }
227 } else {
228 prev_callback = cur_callback;
229 cur_callback = cur_callback->pNext;
Mark Young6ba8abe2017-11-09 10:37:04 -0700230 }
231 }
232 debug_data->active_severities = local_severities;
233 debug_data->active_types = local_types;
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600234}
235
236// Removes all debug callback function nodes from the specified callback linked lists and frees their resources
237static inline void RemoveAllMessageCallbacks(debug_report_data *debug_data, VkLayerDbgFunctionNode **list_head) {
238 VkLayerDbgFunctionNode *current_callback = *list_head;
239 VkLayerDbgFunctionNode *prev_callback = current_callback;
240
241 while (current_callback) {
242 prev_callback = current_callback->pNext;
Mark Young6ba8abe2017-11-09 10:37:04 -0700243 if (!current_callback->is_messenger) {
244 debug_log_msg(debug_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT,
Dave Houlton407df732018-08-06 17:58:24 -0600245 (uint64_t)current_callback->report.msgCallback, 0, "DebugReport",
246 "Debug Report callbacks not removed before DestroyInstance", kVUIDUndefined);
Mark Young6ba8abe2017-11-09 10:37:04 -0700247 } else {
248 debug_log_msg(debug_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT,
Dave Houlton407df732018-08-06 17:58:24 -0600249 (uint64_t)current_callback->messenger.messenger, 0, "Messenger",
250 "Debug messengers not removed before DestroyInstance", kVUIDUndefined);
Mark Young6ba8abe2017-11-09 10:37:04 -0700251 }
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600252 free(current_callback);
253 current_callback = prev_callback;
254 }
255 *list_head = NULL;
256}
257
Mark Young6ba8abe2017-11-09 10:37:04 -0700258static inline bool debug_log_msg(const debug_report_data *debug_data, VkFlags msg_flags, VkDebugReportObjectTypeEXT object_type,
Dave Houlton407df732018-08-06 17:58:24 -0600259 uint64_t src_object, size_t location, const char *layer_prefix, const char *message,
260 const char *text_vuid) {
Dustin Graves8f1eab92016-04-05 09:41:17 -0600261 bool bail = false;
Mark Young6ba8abe2017-11-09 10:37:04 -0700262 VkLayerDbgFunctionNode *layer_dbg_node = NULL;
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600263
Mark Lobodzinski55a197f2016-06-21 15:54:57 -0600264 if (debug_data->debug_callback_list != NULL) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700265 layer_dbg_node = debug_data->debug_callback_list;
Mark Lobodzinski55a197f2016-06-21 15:54:57 -0600266 } else {
Mark Young6ba8abe2017-11-09 10:37:04 -0700267 layer_dbg_node = debug_data->default_debug_callback_list;
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600268 }
269
Mark Young6ba8abe2017-11-09 10:37:04 -0700270 VkDebugUtilsMessageSeverityFlagsEXT severity;
271 VkDebugUtilsMessageTypeFlagsEXT types;
272 VkDebugUtilsMessengerCallbackDataEXT callback_data;
273 VkDebugUtilsObjectNameInfoEXT object_name_info;
274
275 // Convert the info to the VK_EXT_debug_utils form in case we need it.
276 DebugReportFlagsToAnnotFlags(msg_flags, true, &severity, &types);
277 object_name_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
278 object_name_info.pNext = NULL;
279 object_name_info.objectType = convertDebugReportObjectToCoreObject(object_type);
280 object_name_info.objectHandle = (uint64_t)(uintptr_t)src_object;
281 object_name_info.pObjectName = NULL;
282
283 callback_data.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT;
284 callback_data.pNext = NULL;
285 callback_data.flags = 0;
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700286 callback_data.pMessageIdName = text_vuid;
Dave Houlton407df732018-08-06 17:58:24 -0600287 callback_data.messageIdNumber = 0; // deprecated, validation layers use only the pMessageIdName
Mark Young6ba8abe2017-11-09 10:37:04 -0700288 callback_data.pMessage = message;
289 callback_data.queueLabelCount = 0;
290 callback_data.pQueueLabels = NULL;
291 callback_data.cmdBufLabelCount = 0;
292 callback_data.pCmdBufLabels = NULL;
293 callback_data.objectCount = 1;
294 callback_data.pObjects = &object_name_info;
295
296 VkDebugUtilsLabelEXT *queue_labels = nullptr;
297 VkDebugUtilsLabelEXT *cmd_buf_labels = nullptr;
298 std::string new_debug_report_message = "";
299 std::ostringstream oss;
Mark Young6ba8abe2017-11-09 10:37:04 -0700300
301 if (0 != src_object) {
Mark Young8504ba62018-03-21 13:35:34 -0600302 oss << "Object: 0x" << std::hex << src_object;
Mark Young6ba8abe2017-11-09 10:37:04 -0700303 // If this is a queue, add any queue labels to the callback data.
304 if (VK_OBJECT_TYPE_QUEUE == object_name_info.objectType) {
305 auto label_iter = debug_data->debugUtilsQueueLabels->find(reinterpret_cast<VkQueue>(src_object));
306 if (label_iter != debug_data->debugUtilsQueueLabels->end()) {
307 queue_labels = new VkDebugUtilsLabelEXT[label_iter->second.size()];
308 if (nullptr != queue_labels) {
309 // Record the labels, but record them in reverse order since we want the
310 // most recent at the top.
311 uint32_t label_size = static_cast<uint32_t>(label_iter->second.size());
312 uint32_t last_index = label_size - 1;
313 for (uint32_t label = 0; label < label_size; ++label) {
314 queue_labels[last_index - label].sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
315 queue_labels[last_index - label].pNext = nullptr;
316 queue_labels[last_index - label].pLabelName = label_iter->second[label].name.c_str();
317 queue_labels[last_index - label].color[0] = label_iter->second[label].color[0];
318 queue_labels[last_index - label].color[1] = label_iter->second[label].color[1];
319 queue_labels[last_index - label].color[2] = label_iter->second[label].color[2];
320 queue_labels[last_index - label].color[3] = label_iter->second[label].color[3];
321 }
322 callback_data.queueLabelCount = label_size;
323 callback_data.pQueueLabels = queue_labels;
324 }
325 }
326 // If this is a command buffer, add any command buffer labels to the callback data.
327 } else if (VK_OBJECT_TYPE_COMMAND_BUFFER == object_name_info.objectType) {
328 auto label_iter = debug_data->debugUtilsCmdBufLabels->find(reinterpret_cast<VkCommandBuffer>(src_object));
329 if (label_iter != debug_data->debugUtilsCmdBufLabels->end()) {
330 cmd_buf_labels = new VkDebugUtilsLabelEXT[label_iter->second.size()];
331 if (nullptr != cmd_buf_labels) {
332 // Record the labels, but record them in reverse order since we want the
333 // most recent at the top.
334 uint32_t label_size = static_cast<uint32_t>(label_iter->second.size());
335 uint32_t last_index = label_size - 1;
336 for (uint32_t label = 0; label < label_size; ++label) {
337 cmd_buf_labels[last_index - label].sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
338 cmd_buf_labels[last_index - label].pNext = nullptr;
339 cmd_buf_labels[last_index - label].pLabelName = label_iter->second[label].name.c_str();
340 cmd_buf_labels[last_index - label].color[0] = label_iter->second[label].color[0];
341 cmd_buf_labels[last_index - label].color[1] = label_iter->second[label].color[1];
342 cmd_buf_labels[last_index - label].color[2] = label_iter->second[label].color[2];
343 cmd_buf_labels[last_index - label].color[3] = label_iter->second[label].color[3];
344 }
345 callback_data.cmdBufLabelCount = label_size;
346 callback_data.pCmdBufLabels = cmd_buf_labels;
347 }
348 }
349 }
350 // Look for any debug utils or marker names to use for this object
351 callback_data.pObjects[0].pObjectName = NULL;
352 auto utils_name_iter = debug_data->debugUtilsObjectNameMap->find(src_object);
353 if (utils_name_iter != debug_data->debugUtilsObjectNameMap->end()) {
354 callback_data.pObjects[0].pObjectName = utils_name_iter->second.c_str();
355 } else {
356 auto marker_name_iter = debug_data->debugObjectNameMap->find(src_object);
357 if (marker_name_iter != debug_data->debugObjectNameMap->end()) {
358 callback_data.pObjects[0].pObjectName = marker_name_iter->second.c_str();
359 }
360 }
361 if (NULL != callback_data.pObjects[0].pObjectName) {
Mark Young8504ba62018-03-21 13:35:34 -0600362 oss << " (Name = " << callback_data.pObjects[0].pObjectName << " : Type = ";
363 } else {
364 oss << " (Type = ";
Mark Young6ba8abe2017-11-09 10:37:04 -0700365 }
Mark Young8504ba62018-03-21 13:35:34 -0600366 oss << std::to_string(object_type) << ")";
367 } else {
368 oss << "Object: VK_NULL_HANDLE (Type = " << std::to_string(object_type) << ")";
Mark Young6ba8abe2017-11-09 10:37:04 -0700369 }
370 new_debug_report_message += oss.str();
371 new_debug_report_message += " | ";
372 new_debug_report_message += message;
373
374 while (layer_dbg_node) {
Mark Young8504ba62018-03-21 13:35:34 -0600375 // If the app uses the VK_EXT_debug_report extension, call all of those registered callbacks.
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700376 if (!layer_dbg_node->is_messenger && (layer_dbg_node->report.msgFlags & msg_flags)) {
377 if (text_vuid != nullptr) {
378 // If a text vuid is supplied for the old debug report extension, prepend it to the message string
379 new_debug_report_message.insert(0, " ] ");
380 new_debug_report_message.insert(0, text_vuid);
381 new_debug_report_message.insert(0, " [ ");
382 }
383
Dave Houlton407df732018-08-06 17:58:24 -0600384 if (layer_dbg_node->report.pfnMsgCallback(msg_flags, object_type, src_object, location, 0, layer_prefix,
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700385 new_debug_report_message.c_str(), layer_dbg_node->pUserData)) {
386 bail = true;
387 }
Mark Young8504ba62018-03-21 13:35:34 -0600388 // If the app uses the VK_EXT_debug_utils extension, call all of those registered callbacks.
Mark Young6ba8abe2017-11-09 10:37:04 -0700389 } else if (layer_dbg_node->is_messenger && (layer_dbg_node->messenger.messageSeverity & severity) &&
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700390 (layer_dbg_node->messenger.messageType & types)) {
391 if (layer_dbg_node->messenger.pfnUserCallback(static_cast<VkDebugUtilsMessageSeverityFlagBitsEXT>(severity), types,
392 &callback_data, layer_dbg_node->pUserData)) {
393 bail = true;
394 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700395 }
396 layer_dbg_node = layer_dbg_node->pNext;
397 }
398
399 if (nullptr != queue_labels) {
400 delete[] queue_labels;
401 }
402 if (nullptr != cmd_buf_labels) {
403 delete[] cmd_buf_labels;
404 }
405
406 return bail;
407}
408
409static inline void DebugAnnotFlagsToReportFlags(VkDebugUtilsMessageSeverityFlagBitsEXT da_severity,
410 VkDebugUtilsMessageTypeFlagsEXT da_type, VkDebugReportFlagsEXT *dr_flags) {
411 *dr_flags = 0;
412
413 if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) != 0) {
414 *dr_flags |= VK_DEBUG_REPORT_ERROR_BIT_EXT;
415 } else if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) != 0) {
416 if ((da_type & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT) != 0) {
417 *dr_flags |= VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
418 } else {
419 *dr_flags |= VK_DEBUG_REPORT_WARNING_BIT_EXT;
420 }
421 } else if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) != 0) {
422 *dr_flags |= VK_DEBUG_REPORT_INFORMATION_BIT_EXT;
423 } else if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) != 0) {
424 *dr_flags |= VK_DEBUG_REPORT_DEBUG_BIT_EXT;
425 }
426}
427
428static inline bool debug_messenger_log_msg(const debug_report_data *debug_data,
429 VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
430 VkDebugUtilsMessageTypeFlagsEXT message_type,
431 VkDebugUtilsMessengerCallbackDataEXT *callback_data) {
432 bool bail = false;
433 VkLayerDbgFunctionNode *layer_dbg_node = NULL;
434
435 if (debug_data->debug_callback_list != NULL) {
436 layer_dbg_node = debug_data->debug_callback_list;
437 } else {
438 layer_dbg_node = debug_data->default_debug_callback_list;
439 }
440
441 VkDebugReportFlagsEXT object_flags = 0;
442
443 DebugAnnotFlagsToReportFlags(message_severity, message_type, &object_flags);
444
445 while (layer_dbg_node) {
446 if (layer_dbg_node->is_messenger && (layer_dbg_node->messenger.messageSeverity & message_severity) &&
447 (layer_dbg_node->messenger.messageType & message_type)) {
448 // Loop through each object and give it the proper name if it was set.
449 for (uint32_t obj = 0; obj < callback_data->objectCount; obj++) {
450 auto it = debug_data->debugUtilsObjectNameMap->find(callback_data->pObjects[obj].objectHandle);
451 if (it == debug_data->debugUtilsObjectNameMap->end()) {
452 continue;
453 }
454 callback_data->pObjects[obj].pObjectName = it->second.c_str();
455 }
456 if (layer_dbg_node->messenger.pfnUserCallback(message_severity, message_type, callback_data,
457 layer_dbg_node->pUserData)) {
458 bail = true;
459 }
460 } else if (!layer_dbg_node->is_messenger && layer_dbg_node->report.msgFlags & object_flags) {
461 auto it = debug_data->debugObjectNameMap->find(callback_data->pObjects[0].objectHandle);
John Zulauf536649b2018-05-01 13:28:27 -0600462 VkDebugReportObjectTypeEXT object_type = convertCoreObjectToDebugReportObject(callback_data->pObjects[0].objectType);
Tony Barbour3431dac2017-06-19 16:50:37 -0600463 if (it == debug_data->debugObjectNameMap->end()) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700464 if (layer_dbg_node->report.pfnMsgCallback(object_flags, object_type, callback_data->pObjects[0].objectHandle, 0,
465 callback_data->messageIdNumber, callback_data->pMessageIdName,
466 callback_data->pMessage, layer_dbg_node->pUserData)) {
Tony Barbour3431dac2017-06-19 16:50:37 -0600467 bail = true;
468 }
469 } else {
470 std::string newMsg = "SrcObject name = ";
471 newMsg.append(it->second.c_str());
472 newMsg.append(" ");
Mark Young6ba8abe2017-11-09 10:37:04 -0700473 newMsg.append(callback_data->pMessage);
474 if (layer_dbg_node->report.pfnMsgCallback(object_flags, object_type, callback_data->pObjects[0].objectHandle, 0,
475 callback_data->messageIdNumber, callback_data->pMessageIdName,
476 newMsg.c_str(), layer_dbg_node->pUserData)) {
Tony Barbour3431dac2017-06-19 16:50:37 -0600477 bail = true;
478 }
Courtney Goeltzenleuchter06640832015-09-04 13:52:24 -0600479 }
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600480 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700481 layer_dbg_node = layer_dbg_node->pNext;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600482 }
Courtney Goeltzenleuchter06640832015-09-04 13:52:24 -0600483
484 return bail;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600485}
486
Mark Young6ba8abe2017-11-09 10:37:04 -0700487static inline debug_report_data *debug_utils_create_instance(
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700488 VkLayerInstanceDispatchTable *table, VkInstance inst, uint32_t extension_count,
Mark Young6ba8abe2017-11-09 10:37:04 -0700489 const char *const *enabled_extensions) // layer or extension name to be enabled
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600490{
Mark Youngaa1aa3a2016-07-05 16:41:50 -0600491 debug_report_data *debug_data = (debug_report_data *)malloc(sizeof(debug_report_data));
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700492 if (!debug_data) return NULL;
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600493
494 memset(debug_data, 0, sizeof(debug_report_data));
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600495 for (uint32_t i = 0; i < extension_count; i++) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600496 // TODO: Check other property fields
Mark Young6ba8abe2017-11-09 10:37:04 -0700497 if (strcmp(enabled_extensions[i], VK_EXT_DEBUG_REPORT_EXTENSION_NAME) == 0) {
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600498 debug_data->g_DEBUG_REPORT = true;
Mark Young6ba8abe2017-11-09 10:37:04 -0700499 } else if (strcmp(enabled_extensions[i], VK_EXT_DEBUG_UTILS_EXTENSION_NAME) == 0) {
500 debug_data->g_DEBUG_UTILS = true;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600501 }
502 }
Tony Barbour3431dac2017-06-19 16:50:37 -0600503 debug_data->debugObjectNameMap = new std::unordered_map<uint64_t, std::string>;
Mark Young6ba8abe2017-11-09 10:37:04 -0700504 debug_data->debugUtilsObjectNameMap = new std::unordered_map<uint64_t, std::string>;
505 debug_data->debugUtilsQueueLabels = new std::unordered_map<VkQueue, std::vector<LoggingLabelData>>;
506 debug_data->debugUtilsCmdBufLabels = new std::unordered_map<VkCommandBuffer, std::vector<LoggingLabelData>>;
507 debug_data->queueLabelHasInsert = false;
508 debug_data->cmdBufLabelHasInsert = false;
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600509 return debug_data;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600510}
511
Mark Young6ba8abe2017-11-09 10:37:04 -0700512static inline void layer_debug_utils_destroy_instance(debug_report_data *debug_data) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600513 if (debug_data) {
514 RemoveAllMessageCallbacks(debug_data, &debug_data->default_debug_callback_list);
515 RemoveAllMessageCallbacks(debug_data, &debug_data->debug_callback_list);
Tony Barbour3431dac2017-06-19 16:50:37 -0600516 delete debug_data->debugObjectNameMap;
Mark Young6ba8abe2017-11-09 10:37:04 -0700517 delete debug_data->debugUtilsObjectNameMap;
518 delete debug_data->debugUtilsQueueLabels;
519 delete debug_data->debugUtilsCmdBufLabels;
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600520 free(debug_data);
Courtney Goeltzenleuchteree4027d2015-06-28 13:01:17 -0600521 }
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600522}
523
Mark Young6ba8abe2017-11-09 10:37:04 -0700524static inline debug_report_data *layer_debug_utils_create_device(debug_report_data *instance_debug_data, VkDevice device) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600525 // DEBUG_REPORT shares data between Instance and Device,
526 // so just return instance's data pointer
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600527 return instance_debug_data;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600528}
529
Mark Young6ba8abe2017-11-09 10:37:04 -0700530static inline void layer_debug_utils_destroy_device(VkDevice device) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600531 // Nothing to do since we're using instance data record
532}
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600533
Mark Young6ba8abe2017-11-09 10:37:04 -0700534static inline void layer_destroy_messenger_callback(debug_report_data *debug_data, VkDebugUtilsMessengerEXT messenger,
535 const VkAllocationCallbacks *allocator) {
536 RemoveDebugUtilsMessenger(debug_data, &debug_data->debug_callback_list, messenger);
537 RemoveDebugUtilsMessenger(debug_data, &debug_data->default_debug_callback_list, messenger);
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600538}
539
Mark Young6ba8abe2017-11-09 10:37:04 -0700540static inline VkResult layer_create_messenger_callback(debug_report_data *debug_data, bool default_callback,
541 const VkDebugUtilsMessengerCreateInfoEXT *create_info,
542 const VkAllocationCallbacks *allocator,
543 VkDebugUtilsMessengerEXT *messenger) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700544 VkLayerDbgFunctionNode *pNewDbgFuncNode = (VkLayerDbgFunctionNode *)malloc(sizeof(VkLayerDbgFunctionNode));
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700545 if (!pNewDbgFuncNode) return VK_ERROR_OUT_OF_HOST_MEMORY;
Mark Young6ba8abe2017-11-09 10:37:04 -0700546 memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode));
547 pNewDbgFuncNode->is_messenger = true;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600548
Tobin Ehliseb7715d2015-09-21 09:36:47 -0600549 // Handle of 0 is logging_callback so use allocated Node address as unique handle
Mark Young6ba8abe2017-11-09 10:37:04 -0700550 if (!(*messenger)) *messenger = (VkDebugUtilsMessengerEXT)pNewDbgFuncNode;
551 pNewDbgFuncNode->messenger.messenger = *messenger;
552 pNewDbgFuncNode->messenger.pfnUserCallback = create_info->pfnUserCallback;
553 pNewDbgFuncNode->messenger.messageSeverity = create_info->messageSeverity;
554 pNewDbgFuncNode->messenger.messageType = create_info->messageType;
555 pNewDbgFuncNode->pUserData = create_info->pUserData;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600556
Mark Young6ba8abe2017-11-09 10:37:04 -0700557 debug_data->active_severities |= create_info->messageSeverity;
558 debug_data->active_types |= create_info->messageType;
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600559 if (default_callback) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700560 AddDebugCallbackNode(debug_data, &debug_data->default_debug_callback_list, pNewDbgFuncNode);
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600561 } else {
Mark Young6ba8abe2017-11-09 10:37:04 -0700562 AddDebugCallbackNode(debug_data, &debug_data->debug_callback_list, pNewDbgFuncNode);
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600563 }
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600564
Mark Young6ba8abe2017-11-09 10:37:04 -0700565 VkDebugUtilsMessengerCallbackDataEXT callback_data = {};
566 VkDebugUtilsObjectNameInfoEXT blank_object = {};
567 callback_data.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT;
568 callback_data.pNext = NULL;
569 callback_data.flags = 0;
570 callback_data.pMessageIdName = "Layer Internal Message";
571 callback_data.messageIdNumber = 0;
572 callback_data.pMessage = "Added messenger";
573 callback_data.queueLabelCount = 0;
574 callback_data.pQueueLabels = NULL;
575 callback_data.cmdBufLabelCount = 0;
576 callback_data.pCmdBufLabels = NULL;
577 callback_data.objectCount = 1;
578 callback_data.pObjects = &blank_object;
579 blank_object.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
580 blank_object.pNext = NULL;
581 blank_object.objectType = VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT;
582 blank_object.objectHandle = HandleToUint64(*messenger);
583 blank_object.pObjectName = NULL;
584 debug_messenger_log_msg(debug_data, VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT,
585 VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT, &callback_data);
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600586 return VK_SUCCESS;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600587}
588
Mark Young6ba8abe2017-11-09 10:37:04 -0700589static inline void layer_destroy_report_callback(debug_report_data *debug_data, VkDebugReportCallbackEXT callback,
590 const VkAllocationCallbacks *allocator) {
591 RemoveDebugUtilsMessageCallback(debug_data, &debug_data->debug_callback_list, callback);
592 RemoveDebugUtilsMessageCallback(debug_data, &debug_data->default_debug_callback_list, callback);
593}
594
595static inline VkResult layer_create_report_callback(debug_report_data *debug_data, bool default_callback,
596 const VkDebugReportCallbackCreateInfoEXT *create_info,
597 const VkAllocationCallbacks *allocator, VkDebugReportCallbackEXT *callback) {
598 VkLayerDbgFunctionNode *pNewDbgFuncNode = (VkLayerDbgFunctionNode *)malloc(sizeof(VkLayerDbgFunctionNode));
599 if (!pNewDbgFuncNode) {
600 return VK_ERROR_OUT_OF_HOST_MEMORY;
601 }
602 memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode));
603 pNewDbgFuncNode->is_messenger = false;
604
605 // Handle of 0 is logging_callback so use allocated Node address as unique handle
606 if (!(*callback)) *callback = (VkDebugReportCallbackEXT)pNewDbgFuncNode;
607 pNewDbgFuncNode->report.msgCallback = *callback;
608 pNewDbgFuncNode->report.pfnMsgCallback = create_info->pfnCallback;
609 pNewDbgFuncNode->report.msgFlags = create_info->flags;
610 pNewDbgFuncNode->pUserData = create_info->pUserData;
611
612 VkFlags local_severity = 0;
613 VkFlags local_type = 0;
614 DebugReportFlagsToAnnotFlags(create_info->flags, true, &local_severity, &local_type);
615 debug_data->active_severities |= local_severity;
616 debug_data->active_types |= local_type;
617 if (default_callback) {
618 AddDebugCallbackNode(debug_data, &debug_data->default_debug_callback_list, pNewDbgFuncNode);
619 } else {
620 AddDebugCallbackNode(debug_data, &debug_data->debug_callback_list, pNewDbgFuncNode);
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600621 }
622
Mark Young6ba8abe2017-11-09 10:37:04 -0700623 debug_log_msg(debug_data, VK_DEBUG_REPORT_DEBUG_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT, (uint64_t)*callback, 0,
Dave Houlton407df732018-08-06 17:58:24 -0600624 "DebugReport", "Added callback", kVUIDUndefined);
Mark Young6ba8abe2017-11-09 10:37:04 -0700625 return VK_SUCCESS;
626}
627
628static inline PFN_vkVoidFunction debug_utils_get_instance_proc_addr(debug_report_data *debug_data, const char *func_name) {
629 if (!debug_data) {
630 return NULL;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600631 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700632 if (debug_data->g_DEBUG_REPORT) {
633 if (!strcmp(func_name, "vkCreateDebugReportCallbackEXT")) {
634 return (PFN_vkVoidFunction)vkCreateDebugReportCallbackEXT;
635 }
636 if (!strcmp(func_name, "vkDestroyDebugReportCallbackEXT")) {
637 return (PFN_vkVoidFunction)vkDestroyDebugReportCallbackEXT;
638 }
639 if (!strcmp(func_name, "vkDebugReportMessageEXT")) {
640 return (PFN_vkVoidFunction)vkDebugReportMessageEXT;
641 }
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600642 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700643 if (debug_data->g_DEBUG_UTILS) {
644 if (!strcmp(func_name, "vkCreateDebugUtilsMessengerEXT")) {
645 return (PFN_vkVoidFunction)vkCreateDebugUtilsMessengerEXT;
646 }
647 if (!strcmp(func_name, "vkDestroyDebugUtilsMessengerEXT")) {
648 return (PFN_vkVoidFunction)vkDestroyDebugUtilsMessengerEXT;
649 }
650 if (!strcmp(func_name, "vkSubmitDebugUtilsMessageEXT")) {
651 return (PFN_vkVoidFunction)vkSubmitDebugUtilsMessageEXT;
652 }
Courtney Goeltzenleuchter822e8d72015-11-30 15:28:25 -0700653 }
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600654 return NULL;
655}
656
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600657// This utility (called at vkCreateInstance() time), looks at a pNext chain.
658// It counts any VkDebugReportCallbackCreateInfoEXT structs that it finds. It
659// then allocates an array that can hold that many structs, as well as that
660// many VkDebugReportCallbackEXT handles. It then copies each
661// VkDebugReportCallbackCreateInfoEXT, and initializes each handle.
Mark Young6ba8abe2017-11-09 10:37:04 -0700662static inline VkResult layer_copy_tmp_report_callbacks(const void *pChain, uint32_t *num_callbacks,
663 VkDebugReportCallbackCreateInfoEXT **infos,
664 VkDebugReportCallbackEXT **callbacks) {
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600665 uint32_t n = *num_callbacks = 0;
666
667 const void *pNext = pChain;
668 while (pNext) {
669 // 1st, count the number VkDebugReportCallbackCreateInfoEXT:
670 if (((VkDebugReportCallbackCreateInfoEXT *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT) {
671 n++;
672 }
673 pNext = (void *)((VkDebugReportCallbackCreateInfoEXT *)pNext)->pNext;
674 }
675 if (n == 0) {
676 return VK_SUCCESS;
677 }
678
679 // 2nd, allocate memory for each VkDebugReportCallbackCreateInfoEXT:
680 VkDebugReportCallbackCreateInfoEXT *pInfos = *infos =
681 ((VkDebugReportCallbackCreateInfoEXT *)malloc(n * sizeof(VkDebugReportCallbackCreateInfoEXT)));
682 if (!pInfos) {
683 return VK_ERROR_OUT_OF_HOST_MEMORY;
684 }
685 // 3rd, allocate memory for a unique handle for each callback:
686 VkDebugReportCallbackEXT *pCallbacks = *callbacks = ((VkDebugReportCallbackEXT *)malloc(n * sizeof(VkDebugReportCallbackEXT)));
687 if (!pCallbacks) {
688 free(pInfos);
689 return VK_ERROR_OUT_OF_HOST_MEMORY;
690 }
691 // 4th, copy each VkDebugReportCallbackCreateInfoEXT for use by
692 // vkDestroyInstance, and assign a unique handle to each callback (just
693 // use the address of the copied VkDebugReportCallbackCreateInfoEXT):
694 pNext = pChain;
695 while (pNext) {
696 if (((VkInstanceCreateInfo *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT) {
697 memcpy(pInfos, pNext, sizeof(VkDebugReportCallbackCreateInfoEXT));
698 *pCallbacks++ = (VkDebugReportCallbackEXT)pInfos++;
699 }
700 pNext = (void *)((VkInstanceCreateInfo *)pNext)->pNext;
701 }
702
703 *num_callbacks = n;
704 return VK_SUCCESS;
705}
706
Mark Young6ba8abe2017-11-09 10:37:04 -0700707// This utility frees the arrays allocated by layer_copy_tmp_report_callbacks()
708static inline void layer_free_tmp_report_callbacks(VkDebugReportCallbackCreateInfoEXT *infos, VkDebugReportCallbackEXT *callbacks) {
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600709 free(infos);
710 free(callbacks);
711}
712
713// This utility enables all of the VkDebugReportCallbackCreateInfoEXT structs
Mark Young6ba8abe2017-11-09 10:37:04 -0700714// that were copied by layer_copy_tmp_report_callbacks()
715static inline VkResult layer_enable_tmp_report_callbacks(debug_report_data *debug_data, uint32_t num_callbacks,
716 VkDebugReportCallbackCreateInfoEXT *infos,
717 VkDebugReportCallbackEXT *callbacks) {
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600718 VkResult rtn = VK_SUCCESS;
719 for (uint32_t i = 0; i < num_callbacks; i++) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700720 rtn = layer_create_report_callback(debug_data, false, &infos[i], NULL, &callbacks[i]);
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600721 if (rtn != VK_SUCCESS) {
722 for (uint32_t j = 0; j < i; j++) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700723 layer_destroy_report_callback(debug_data, callbacks[j], NULL);
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600724 }
725 return rtn;
726 }
727 }
728 return rtn;
729}
730
731// This utility disables all of the VkDebugReportCallbackCreateInfoEXT structs
Mark Young6ba8abe2017-11-09 10:37:04 -0700732// that were copied by layer_copy_tmp_report_callbacks()
733static inline void layer_disable_tmp_report_callbacks(debug_report_data *debug_data, uint32_t num_callbacks,
734 VkDebugReportCallbackEXT *callbacks) {
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600735 for (uint32_t i = 0; i < num_callbacks; i++) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700736 layer_destroy_report_callback(debug_data, callbacks[i], NULL);
737 }
738}
739
740// This utility (called at vkCreateInstance() time), looks at a pNext chain.
741// It counts any VkDebugUtilsMessengerCreateInfoEXT structs that it finds. It
742// then allocates an array that can hold that many structs, as well as that
743// many VkDebugUtilsMessengerEXT handles. It then copies each
744// VkDebugUtilsMessengerCreateInfoEXT, and initializes each handle.
Mark Young8504ba62018-03-21 13:35:34 -0600745static inline VkResult layer_copy_tmp_debug_messengers(const void *pChain, uint32_t *num_messengers,
746 VkDebugUtilsMessengerCreateInfoEXT **infos,
747 VkDebugUtilsMessengerEXT **messengers) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700748 uint32_t n = *num_messengers = 0;
749
750 const void *pNext = pChain;
751 while (pNext) {
752 // 1st, count the number VkDebugUtilsMessengerCreateInfoEXT:
753 if (((VkDebugUtilsMessengerCreateInfoEXT *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT) {
754 n++;
755 }
756 pNext = (void *)((VkDebugUtilsMessengerCreateInfoEXT *)pNext)->pNext;
757 }
758 if (n == 0) {
759 return VK_SUCCESS;
760 }
761
762 // 2nd, allocate memory for each VkDebugUtilsMessengerCreateInfoEXT:
763 VkDebugUtilsMessengerCreateInfoEXT *pInfos = *infos =
764 ((VkDebugUtilsMessengerCreateInfoEXT *)malloc(n * sizeof(VkDebugUtilsMessengerCreateInfoEXT)));
765 if (!pInfos) {
766 return VK_ERROR_OUT_OF_HOST_MEMORY;
767 }
768 // 3rd, allocate memory for a unique handle for each messenger:
769 VkDebugUtilsMessengerEXT *pMessengers = *messengers =
770 ((VkDebugUtilsMessengerEXT *)malloc(n * sizeof(VkDebugUtilsMessengerEXT)));
771 if (!pMessengers) {
772 free(pInfos);
773 return VK_ERROR_OUT_OF_HOST_MEMORY;
774 }
775 // 4th, copy each VkDebugUtilsMessengerCreateInfoEXT for use by
776 // vkDestroyInstance, and assign a unique handle to each callback (just
777 // use the address of the copied VkDebugUtilsMessengerCreateInfoEXT):
778 pNext = pChain;
779 while (pNext) {
780 if (((VkInstanceCreateInfo *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT) {
781 memcpy(pInfos, pNext, sizeof(VkDebugUtilsMessengerCreateInfoEXT));
782 *pMessengers++ = (VkDebugUtilsMessengerEXT)pInfos++;
783 }
784 pNext = (void *)((VkInstanceCreateInfo *)pNext)->pNext;
785 }
786
787 *num_messengers = n;
788 return VK_SUCCESS;
789}
790
791// This utility frees the arrays allocated by layer_copy_tmp_debug_messengers()
Mark Young8504ba62018-03-21 13:35:34 -0600792static inline void layer_free_tmp_debug_messengers(VkDebugUtilsMessengerCreateInfoEXT *infos,
793 VkDebugUtilsMessengerEXT *messengers) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700794 free(infos);
795 free(messengers);
796}
797
798// This utility enables all of the VkDebugUtilsMessengerCreateInfoEXT structs
799// that were copied by layer_copy_tmp_debug_messengers()
Mark Young8504ba62018-03-21 13:35:34 -0600800static inline VkResult layer_enable_tmp_debug_messengers(debug_report_data *debug_data, uint32_t num_messengers,
801 VkDebugUtilsMessengerCreateInfoEXT *infos,
802 VkDebugUtilsMessengerEXT *messengers) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700803 VkResult rtn = VK_SUCCESS;
804 for (uint32_t i = 0; i < num_messengers; i++) {
805 rtn = layer_create_messenger_callback(debug_data, false, &infos[i], NULL, &messengers[i]);
806 if (rtn != VK_SUCCESS) {
807 for (uint32_t j = 0; j < i; j++) {
808 layer_destroy_messenger_callback(debug_data, messengers[j], NULL);
809 }
810 return rtn;
811 }
812 }
813 return rtn;
814}
815
816// This utility disables all of the VkDebugUtilsMessengerCreateInfoEXT structs
817// that were copied by layer_copy_tmp_debug_messengers()
Mark Young8504ba62018-03-21 13:35:34 -0600818static inline void layer_disable_tmp_debug_messengers(debug_report_data *debug_data, uint32_t num_messengers,
819 VkDebugUtilsMessengerEXT *messengers) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700820 for (uint32_t i = 0; i < num_messengers; i++) {
821 layer_destroy_messenger_callback(debug_data, messengers[i], NULL);
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600822 }
823}
824
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600825// Checks if the message will get logged.
826// Allows layer to defer collecting & formating data if the
827// message will be discarded.
Mark Young6ba8abe2017-11-09 10:37:04 -0700828static inline bool will_log_msg(debug_report_data *debug_data, VkFlags msg_flags) {
829 VkFlags local_severity = 0;
830 VkFlags local_type = 0;
831 DebugReportFlagsToAnnotFlags(msg_flags, true, &local_severity, &local_type);
832 if (!debug_data || !(debug_data->active_severities & local_severity) || !(debug_data->active_types & local_type)) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600833 // Message is not wanted
Courtney Goeltzenleuchter6a564a12015-09-18 16:30:24 -0600834 return false;
835 }
836
837 return true;
838}
John Zulauf6664e272018-01-17 11:00:22 -0700839#ifndef WIN32
Mark Lobodzinski1bcbdf92018-02-07 10:00:22 -0700840static inline int string_sprintf(std::string *output, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
John Zulauf6664e272018-01-17 11:00:22 -0700841#endif
Mark Lobodzinski1bcbdf92018-02-07 10:00:22 -0700842static inline int string_sprintf(std::string *output, const char *fmt, ...) {
John Zulauf6664e272018-01-17 11:00:22 -0700843 std::string &formatted = *output;
844 va_list argptr;
845 va_start(argptr, fmt);
846 int reserve = vsnprintf(nullptr, 0, fmt, argptr);
847 va_end(argptr);
848 formatted.reserve(reserve + 1);
849 va_start(argptr, fmt);
850 int result = vsnprintf((char *)formatted.data(), formatted.capacity(), fmt, argptr);
851 va_end(argptr);
852 assert(result == reserve);
853 return result;
854}
Courtney Goeltzenleuchter6a564a12015-09-18 16:30:24 -0600855
Chris Forbes8a25bce2016-03-24 12:06:35 +1300856#ifdef WIN32
857static inline int vasprintf(char **strp, char const *fmt, va_list ap) {
858 *strp = nullptr;
859 int size = _vscprintf(fmt, ap);
860 if (size >= 0) {
Mark Lobodzinski729a8d32017-01-26 12:16:30 -0700861 *strp = (char *)malloc(size + 1);
Chris Forbes8a25bce2016-03-24 12:06:35 +1300862 if (!*strp) {
863 return -1;
864 }
Mark Lobodzinski729a8d32017-01-26 12:16:30 -0700865 _vsnprintf(*strp, size + 1, fmt, ap);
Chris Forbes8a25bce2016-03-24 12:06:35 +1300866 }
867 return size;
868}
869#endif
870
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700871// Output log message via DEBUG_REPORT. Takes format and variable arg list so that output string is only computed if a message
872// needs to be logged
Michael Lentine010f4692015-11-03 16:19:46 -0800873#ifndef WIN32
Mark Young6ba8abe2017-11-09 10:37:04 -0700874static inline bool log_msg(const debug_report_data *debug_data, VkFlags msg_flags, VkDebugReportObjectTypeEXT object_type,
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700875 uint64_t src_object, std::string vuid_text, const char *format, ...)
876 __attribute__((format(printf, 6, 7)));
Michael Lentine010f4692015-11-03 16:19:46 -0800877#endif
Mark Young6ba8abe2017-11-09 10:37:04 -0700878static inline bool log_msg(const debug_report_data *debug_data, VkFlags msg_flags, VkDebugReportObjectTypeEXT object_type,
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700879 uint64_t src_object, std::string vuid_text, const char *format, ...) {
880 VkFlags local_severity = 0;
881 VkFlags local_type = 0;
882 DebugReportFlagsToAnnotFlags(msg_flags, true, &local_severity, &local_type);
883 if (!debug_data || !(debug_data->active_severities & local_severity) || !(debug_data->active_types & local_type)) {
884 // Message is not wanted
885 return false;
886 }
887
888 va_list argptr;
889 va_start(argptr, format);
890 char *str;
891 if (-1 == vasprintf(&str, format, argptr)) {
892 // On failure, glibc vasprintf leaves str undefined
893 str = nullptr;
894 }
895 va_end(argptr);
896
Dave Houlton407df732018-08-06 17:58:24 -0600897 std::string str_plus_spec_text(str ? str : "Allocation failure");
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700898
Dave Houlton407df732018-08-06 17:58:24 -0600899 // Append the spec error text to the error message, unless it's an UNASSIGNED or UNDEFINED vuid
900 if ((vuid_text.find("UNASSIGNED-") == std::string::npos) && (vuid_text.find(kVUIDUndefined) == std::string::npos)) {
901 if (vuid_to_error_text_map.find(vuid_text) == vuid_to_error_text_map.end()) {
902 // If this happens, you've hit a VUID string that isn't defined in the spec's json file
903 // Try running 'vk_validation_stats -c' to look for invalid VUID strings in the repo code
904 assert(0);
905 } else {
906 str_plus_spec_text += " The Vulkan spec states: ";
907 str_plus_spec_text += vuid_to_error_text_map[vuid_text];
908 }
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700909 }
910
Dave Houlton8e9f6542018-05-18 12:18:22 -0600911 // Append layer prefix with VUID string, pass in recovered legacy numerical VUID
Dave Houlton407df732018-08-06 17:58:24 -0600912 bool result = debug_log_msg(debug_data, msg_flags, object_type, src_object, 0, "Validation", str_plus_spec_text.c_str(),
913 vuid_text.c_str());
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700914
915 free(str);
916 return result;
917}
918
Mark Young6ba8abe2017-11-09 10:37:04 -0700919static inline VKAPI_ATTR VkBool32 VKAPI_CALL report_log_callback(VkFlags msg_flags, VkDebugReportObjectTypeEXT obj_type,
920 uint64_t src_object, size_t location, int32_t msg_code,
921 const char *layer_prefix, const char *message, void *user_data) {
922 char msg_flag_string[30];
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600923
Mark Young6ba8abe2017-11-09 10:37:04 -0700924 PrintMessageFlags(msg_flags, msg_flag_string);
Courtney Goeltzenleuchter2f25bb42015-06-14 11:29:24 -0600925
Mark Lobodzinskib1fd9d12018-03-30 14:26:00 -0600926 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 -0700927 fflush((FILE *)user_data);
Courtney Goeltzenleuchter06640832015-09-04 13:52:24 -0600928
929 return false;
Courtney Goeltzenleuchter2f25bb42015-06-14 11:29:24 -0600930}
Courtney Goeltzenleuchter5907ac42015-10-05 14:41:34 -0600931
Mark Young6ba8abe2017-11-09 10:37:04 -0700932static inline VKAPI_ATTR VkBool32 VKAPI_CALL report_win32_debug_output_msg(VkFlags msg_flags, VkDebugReportObjectTypeEXT obj_type,
933 uint64_t src_object, size_t location, int32_t msg_code,
934 const char *layer_prefix, const char *message,
935 void *user_data) {
Courtney Goeltzenleuchter5907ac42015-10-05 14:41:34 -0600936#ifdef WIN32
Mark Young6ba8abe2017-11-09 10:37:04 -0700937 char msg_flag_string[30];
Courtney Goeltzenleuchter5907ac42015-10-05 14:41:34 -0600938 char buf[2048];
939
Mark Young6ba8abe2017-11-09 10:37:04 -0700940 PrintMessageFlags(msg_flags, msg_flag_string);
Mark Lobodzinskib1fd9d12018-03-30 14:26:00 -0600941 _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 -0600942
943 OutputDebugString(buf);
944#endif
945
946 return false;
947}
948
Mark Young6ba8abe2017-11-09 10:37:04 -0700949static inline VKAPI_ATTR VkBool32 VKAPI_CALL DebugBreakCallback(VkFlags msgFlags, VkDebugReportObjectTypeEXT obj_type,
950 uint64_t src_object, size_t location, int32_t msg_code,
951 const char *layer_prefix, const char *message, void *user_data) {
Mark Lobodzinskic9d81652017-08-10 11:01:17 -0600952#ifdef WIN32
953 DebugBreak();
954#else
955 raise(SIGTRAP);
956#endif
957
958 return false;
959}
960
Mark Young6ba8abe2017-11-09 10:37:04 -0700961static inline VKAPI_ATTR VkBool32 VKAPI_CALL messenger_log_callback(VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
962 VkDebugUtilsMessageTypeFlagsEXT message_type,
963 const VkDebugUtilsMessengerCallbackDataEXT *callback_data,
964 void *user_data) {
965 char msg_severity[30];
966 char msg_type[30];
967
968 PrintMessageSeverity(message_severity, msg_severity);
969 PrintMessageType(message_type, msg_type);
970
Mark Young8504ba62018-03-21 13:35:34 -0600971 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 -0700972 callback_data->messageIdNumber, callback_data->pMessage);
Mark Young8504ba62018-03-21 13:35:34 -0600973 fprintf((FILE *)user_data, " Objects: %d\n", callback_data->objectCount);
974 for (uint32_t obj = 0; obj < callback_data->objectCount; ++obj) {
975 fprintf((FILE *)user_data, " [%d] 0x%" PRIx64 ", type: %d, name: %s\n", obj,
976 callback_data->pObjects[obj].objectHandle, callback_data->pObjects[obj].objectType,
977 callback_data->pObjects[obj].pObjectName);
978 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700979 fflush((FILE *)user_data);
980
981 return false;
Petr Krause9388f62017-05-13 20:53:12 +0200982}
983
Mark Young6ba8abe2017-11-09 10:37:04 -0700984static inline VKAPI_ATTR VkBool32 VKAPI_CALL messenger_win32_debug_output_msg(
985 VkDebugUtilsMessageSeverityFlagBitsEXT message_severity, VkDebugUtilsMessageTypeFlagsEXT message_type,
986 const VkDebugUtilsMessengerCallbackDataEXT *callback_data, void *user_data) {
987#ifdef WIN32
988 char buf[2048];
989 char msg_severity[30];
990 char msg_type[30];
Mark Lobodzinski863d5de2017-05-22 10:10:07 -0600991
Mark Young6ba8abe2017-11-09 10:37:04 -0700992 PrintMessageSeverity(message_severity, msg_severity);
993 PrintMessageType(message_type, msg_type);
994
Mark Young8504ba62018-03-21 13:35:34 -0600995 size_t buffer_space = sizeof(buf) - 1;
996 size_t remaining_space = buffer_space;
997 _snprintf(buf, sizeof(buf) - 1, "%s(%s / %s): msgNum: %d - %s\n", callback_data->pMessageIdName, msg_severity, msg_type,
998 callback_data->messageIdNumber, callback_data->pMessage);
999 remaining_space = buffer_space - strlen(buf);
1000 _snprintf(buf, remaining_space, " Objects: %d\n", callback_data->objectCount);
1001 for (uint32_t obj = 0; obj < callback_data->objectCount; ++obj) {
1002 remaining_space = buffer_space - strlen(buf);
1003 if (remaining_space > 0) {
1004 _snprintf(buf, remaining_space, " [%d] 0x%" PRIx64 ", type: %d, name: %s\n", obj,
1005 callback_data->pObjects[obj].objectHandle, callback_data->pObjects[obj].objectType,
1006 callback_data->pObjects[obj].pObjectName);
1007 }
1008 }
Mark Young6ba8abe2017-11-09 10:37:04 -07001009 OutputDebugString(buf);
1010#endif
1011
1012 return false;
1013}
1014
1015// This utility converts from the VkDebugUtilsLabelEXT structure into the logging version of the structure.
1016// In the logging version, we only record what we absolutely need to convey back to the callbacks.
1017static inline void InsertLabelIntoLog(const VkDebugUtilsLabelEXT *utils_label, std::vector<LoggingLabelData> &log_vector) {
1018 LoggingLabelData log_label_data = {};
1019 log_label_data.name = utils_label->pLabelName;
1020 log_label_data.color[0] = utils_label->color[0];
1021 log_label_data.color[1] = utils_label->color[1];
1022 log_label_data.color[2] = utils_label->color[2];
1023 log_label_data.color[3] = utils_label->color[3];
1024 log_vector.push_back(log_label_data);
1025}
1026
Mark Young8504ba62018-03-21 13:35:34 -06001027static inline void BeginQueueDebugUtilsLabel(debug_report_data *report_data, VkQueue queue,
1028 const VkDebugUtilsLabelEXT *label_info) {
Mark Young6ba8abe2017-11-09 10:37:04 -07001029 if (nullptr != label_info && nullptr != label_info->pLabelName) {
1030 auto label_iter = report_data->debugUtilsQueueLabels->find(queue);
1031 if (label_iter == report_data->debugUtilsQueueLabels->end()) {
1032 std::vector<LoggingLabelData> new_queue_labels;
1033 InsertLabelIntoLog(label_info, new_queue_labels);
1034 report_data->debugUtilsQueueLabels->insert({queue, new_queue_labels});
1035 } else {
1036 // If the last thing was a label insert, we need to pop it off of the label vector before any
1037 // changes. This is because a label added with "vkQueueInsertDebugUtilsLabelEXT" is only a
1038 // temporary location that exists until the next operation occurs. In this case, a new
1039 // "vkQueueBeginDebugUtilsLabelEXT" has occurred erasing the previous inserted label.
1040 if (report_data->queueLabelHasInsert) {
1041 report_data->queueLabelHasInsert = false;
1042 label_iter->second.pop_back();
1043 }
1044 InsertLabelIntoLog(label_info, label_iter->second);
1045 }
1046 }
1047}
1048
Mark Young8504ba62018-03-21 13:35:34 -06001049static inline void EndQueueDebugUtilsLabel(debug_report_data *report_data, VkQueue queue) {
Mark Young6ba8abe2017-11-09 10:37:04 -07001050 auto label_iter = report_data->debugUtilsQueueLabels->find(queue);
1051 if (label_iter != report_data->debugUtilsQueueLabels->end()) {
1052 // If the last thing was a label insert, we need to pop it off of the label vector before any
1053 // changes. This is because a label added with "vkQueueInsertDebugUtilsLabelEXT" is only a
1054 // temporary location that exists until the next operation occurs. In this case, a
1055 // "vkQueueEndDebugUtilsLabelEXT" has occurred erasing the inserted label.
1056 if (report_data->queueLabelHasInsert) {
1057 report_data->queueLabelHasInsert = false;
1058 label_iter->second.pop_back();
1059 }
1060 // Now pop the normal item
1061 label_iter->second.pop_back();
1062 }
1063}
1064
Mark Young8504ba62018-03-21 13:35:34 -06001065static inline void InsertQueueDebugUtilsLabel(debug_report_data *report_data, VkQueue queue,
1066 const VkDebugUtilsLabelEXT *label_info) {
Mark Young6ba8abe2017-11-09 10:37:04 -07001067 if (nullptr != label_info && nullptr != label_info->pLabelName) {
1068 auto label_iter = report_data->debugUtilsQueueLabels->find(queue);
1069 if (label_iter == report_data->debugUtilsQueueLabels->end()) {
1070 std::vector<LoggingLabelData> new_queue_labels;
1071 InsertLabelIntoLog(label_info, new_queue_labels);
1072 report_data->debugUtilsQueueLabels->insert({queue, new_queue_labels});
1073 } else {
1074 // If the last thing was a label insert, we need to pop it off of the label vector before any
1075 // changes. This is because a label added with "vkQueueInsertDebugUtilsLabelEXT" is only a
1076 // temporary location that exists until the next operation occurs. In this case, a new
1077 // "vkQueueInsertDebugUtilsLabelEXT" has occurred erasing the previous inserted label.
1078 if (report_data->queueLabelHasInsert) {
1079 label_iter->second.pop_back();
1080 }
1081 // Insert this new label and mark it as one that has been "inserted" so we can remove it on
1082 // the next queue label operation.
1083 InsertLabelIntoLog(label_info, label_iter->second);
1084 report_data->queueLabelHasInsert = true;
1085 }
1086 }
1087}
1088
Mark Young8504ba62018-03-21 13:35:34 -06001089static inline void BeginCmdDebugUtilsLabel(debug_report_data *report_data, VkCommandBuffer command_buffer,
1090 const VkDebugUtilsLabelEXT *label_info) {
Mark Young6ba8abe2017-11-09 10:37:04 -07001091 if (nullptr != label_info && nullptr != label_info->pLabelName) {
1092 auto label_iter = report_data->debugUtilsCmdBufLabels->find(command_buffer);
1093 if (label_iter == report_data->debugUtilsCmdBufLabels->end()) {
1094 std::vector<LoggingLabelData> new_cmdbuf_labels;
1095 InsertLabelIntoLog(label_info, new_cmdbuf_labels);
1096 report_data->debugUtilsCmdBufLabels->insert({command_buffer, new_cmdbuf_labels});
1097 } else {
1098 // If the last thing was a label insert, we need to pop it off of the label vector before any
1099 // changes. This is because a label added with "vkCmdInsertDebugUtilsLabelEXT" is only a
1100 // temporary location that exists until the next operation occurs. In this case, a
1101 // "vkCmdBeginDebugUtilsLabelEXT" has occurred erasing the inserted label.
1102 if (report_data->cmdBufLabelHasInsert) {
1103 report_data->cmdBufLabelHasInsert = false;
1104 label_iter->second.pop_back();
1105 }
1106 InsertLabelIntoLog(label_info, label_iter->second);
1107 }
1108 }
1109}
1110
Mark Young8504ba62018-03-21 13:35:34 -06001111static inline void EndCmdDebugUtilsLabel(debug_report_data *report_data, VkCommandBuffer command_buffer) {
Mark Young6ba8abe2017-11-09 10:37:04 -07001112 auto label_iter = report_data->debugUtilsCmdBufLabels->find(command_buffer);
1113 if (label_iter != report_data->debugUtilsCmdBufLabels->end()) {
1114 // If the last thing was a label insert, we need to pop it off of the label vector before any
1115 // changes. This is because a label added with "vkCmdInsertDebugUtilsLabelEXT" is only a
1116 // temporary location that exists until the next operation occurs. In this case, a
1117 // "vkCmdEndDebugUtilsLabelEXT" has occurred erasing the inserted label.
1118 if (report_data->cmdBufLabelHasInsert) {
1119 report_data->cmdBufLabelHasInsert = false;
1120 label_iter->second.pop_back();
1121 }
1122 // Now pop the normal item
1123 label_iter->second.pop_back();
1124 }
1125}
1126
Mark Young8504ba62018-03-21 13:35:34 -06001127static inline void InsertCmdDebugUtilsLabel(debug_report_data *report_data, VkCommandBuffer command_buffer,
1128 const VkDebugUtilsLabelEXT *label_info) {
Mark Young6ba8abe2017-11-09 10:37:04 -07001129 if (nullptr != label_info && nullptr != label_info->pLabelName) {
1130 auto label_iter = report_data->debugUtilsCmdBufLabels->find(command_buffer);
1131 if (label_iter == report_data->debugUtilsCmdBufLabels->end()) {
1132 std::vector<LoggingLabelData> new_cmdbuf_labels;
1133 InsertLabelIntoLog(label_info, new_cmdbuf_labels);
1134 report_data->debugUtilsCmdBufLabels->insert({command_buffer, new_cmdbuf_labels});
1135 } else {
1136 // If the last thing was a label insert, we need to pop it off of the label vector before any
1137 // changes. This is because a label added with "vkCmdInsertDebugUtilsLabelEXT" is only a
1138 // temporary location that exists until the next operation occurs. In this case, a new
1139 // "vkCmdInsertDebugUtilsLabelEXT" has occurred erasing the previous inserted label.
1140 if (report_data->cmdBufLabelHasInsert) {
1141 label_iter->second.pop_back();
1142 }
1143 // Insert this new label and mark it as one that has been "inserted" so we can remove it on
1144 // the next command buffer label operation.
1145 InsertLabelIntoLog(label_info, label_iter->second);
1146 report_data->cmdBufLabelHasInsert = true;
1147 }
1148 }
1149}
Mark Lobodzinski863d5de2017-05-22 10:10:07 -06001150
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001151#endif // LAYER_LOGGING_H