blob: 03eb91fca82f3a2a5f0eee05c0796215ba4e30b1 [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,
Dave Houlton407df732018-08-06 17:58:24 -0600116 uint64_t src_object, size_t location, const char *layer_prefix, const char *message,
117 const char *text_vuid);
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,
Dave Houlton407df732018-08-06 17:58:24 -0600143 reinterpret_cast<uint64_t &>(cur_callback->messenger.messenger), 0, "DebugUtilsMessenger",
144 "Destroyed messenger\n", kVUIDUndefined);
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,
Dave Houlton407df732018-08-06 17:58:24 -0600177 reinterpret_cast<uint64_t &>(cur_callback->report.msgCallback), 0, "DebugReport", "Destroyed callback\n",
178 kVUIDUndefined);
Mark Young6ba8abe2017-11-09 10:37:04 -0700179 } 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,
Dave Houlton407df732018-08-06 17:58:24 -0600206 (uint64_t)current_callback->report.msgCallback, 0, "DebugReport",
207 "Debug Report callbacks not removed before DestroyInstance", kVUIDUndefined);
Mark Young6ba8abe2017-11-09 10:37:04 -0700208 } else {
209 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 -0600210 (uint64_t)current_callback->messenger.messenger, 0, "Messenger",
211 "Debug messengers not removed before DestroyInstance", kVUIDUndefined);
Mark Young6ba8abe2017-11-09 10:37:04 -0700212 }
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600213 free(current_callback);
214 current_callback = prev_callback;
215 }
216 *list_head = NULL;
217}
218
Mark Young6ba8abe2017-11-09 10:37:04 -0700219static inline bool debug_log_msg(const debug_report_data *debug_data, VkFlags msg_flags, VkDebugReportObjectTypeEXT object_type,
Dave Houlton407df732018-08-06 17:58:24 -0600220 uint64_t src_object, size_t location, const char *layer_prefix, const char *message,
221 const char *text_vuid) {
Dustin Graves8f1eab92016-04-05 09:41:17 -0600222 bool bail = false;
Mark Young6ba8abe2017-11-09 10:37:04 -0700223 VkLayerDbgFunctionNode *layer_dbg_node = NULL;
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600224
Mark Lobodzinski55a197f2016-06-21 15:54:57 -0600225 if (debug_data->debug_callback_list != NULL) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700226 layer_dbg_node = debug_data->debug_callback_list;
Mark Lobodzinski55a197f2016-06-21 15:54:57 -0600227 } else {
Mark Young6ba8abe2017-11-09 10:37:04 -0700228 layer_dbg_node = debug_data->default_debug_callback_list;
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600229 }
230
Mark Young6ba8abe2017-11-09 10:37:04 -0700231 VkDebugUtilsMessageSeverityFlagsEXT severity;
232 VkDebugUtilsMessageTypeFlagsEXT types;
233 VkDebugUtilsMessengerCallbackDataEXT callback_data;
234 VkDebugUtilsObjectNameInfoEXT object_name_info;
235
236 // Convert the info to the VK_EXT_debug_utils form in case we need it.
237 DebugReportFlagsToAnnotFlags(msg_flags, true, &severity, &types);
238 object_name_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
239 object_name_info.pNext = NULL;
240 object_name_info.objectType = convertDebugReportObjectToCoreObject(object_type);
241 object_name_info.objectHandle = (uint64_t)(uintptr_t)src_object;
242 object_name_info.pObjectName = NULL;
243
244 callback_data.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT;
245 callback_data.pNext = NULL;
246 callback_data.flags = 0;
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700247 callback_data.pMessageIdName = text_vuid;
Dave Houlton407df732018-08-06 17:58:24 -0600248 callback_data.messageIdNumber = 0; // deprecated, validation layers use only the pMessageIdName
Mark Young6ba8abe2017-11-09 10:37:04 -0700249 callback_data.pMessage = message;
250 callback_data.queueLabelCount = 0;
251 callback_data.pQueueLabels = NULL;
252 callback_data.cmdBufLabelCount = 0;
253 callback_data.pCmdBufLabels = NULL;
254 callback_data.objectCount = 1;
255 callback_data.pObjects = &object_name_info;
256
257 VkDebugUtilsLabelEXT *queue_labels = nullptr;
258 VkDebugUtilsLabelEXT *cmd_buf_labels = nullptr;
259 std::string new_debug_report_message = "";
260 std::ostringstream oss;
Mark Young6ba8abe2017-11-09 10:37:04 -0700261
262 if (0 != src_object) {
Mark Young8504ba62018-03-21 13:35:34 -0600263 oss << "Object: 0x" << std::hex << src_object;
Mark Young6ba8abe2017-11-09 10:37:04 -0700264 // If this is a queue, add any queue labels to the callback data.
265 if (VK_OBJECT_TYPE_QUEUE == object_name_info.objectType) {
266 auto label_iter = debug_data->debugUtilsQueueLabels->find(reinterpret_cast<VkQueue>(src_object));
267 if (label_iter != debug_data->debugUtilsQueueLabels->end()) {
268 queue_labels = new VkDebugUtilsLabelEXT[label_iter->second.size()];
269 if (nullptr != queue_labels) {
270 // Record the labels, but record them in reverse order since we want the
271 // most recent at the top.
272 uint32_t label_size = static_cast<uint32_t>(label_iter->second.size());
273 uint32_t last_index = label_size - 1;
274 for (uint32_t label = 0; label < label_size; ++label) {
275 queue_labels[last_index - label].sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
276 queue_labels[last_index - label].pNext = nullptr;
277 queue_labels[last_index - label].pLabelName = label_iter->second[label].name.c_str();
278 queue_labels[last_index - label].color[0] = label_iter->second[label].color[0];
279 queue_labels[last_index - label].color[1] = label_iter->second[label].color[1];
280 queue_labels[last_index - label].color[2] = label_iter->second[label].color[2];
281 queue_labels[last_index - label].color[3] = label_iter->second[label].color[3];
282 }
283 callback_data.queueLabelCount = label_size;
284 callback_data.pQueueLabels = queue_labels;
285 }
286 }
287 // If this is a command buffer, add any command buffer labels to the callback data.
288 } else if (VK_OBJECT_TYPE_COMMAND_BUFFER == object_name_info.objectType) {
289 auto label_iter = debug_data->debugUtilsCmdBufLabels->find(reinterpret_cast<VkCommandBuffer>(src_object));
290 if (label_iter != debug_data->debugUtilsCmdBufLabels->end()) {
291 cmd_buf_labels = new VkDebugUtilsLabelEXT[label_iter->second.size()];
292 if (nullptr != cmd_buf_labels) {
293 // Record the labels, but record them in reverse order since we want the
294 // most recent at the top.
295 uint32_t label_size = static_cast<uint32_t>(label_iter->second.size());
296 uint32_t last_index = label_size - 1;
297 for (uint32_t label = 0; label < label_size; ++label) {
298 cmd_buf_labels[last_index - label].sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
299 cmd_buf_labels[last_index - label].pNext = nullptr;
300 cmd_buf_labels[last_index - label].pLabelName = label_iter->second[label].name.c_str();
301 cmd_buf_labels[last_index - label].color[0] = label_iter->second[label].color[0];
302 cmd_buf_labels[last_index - label].color[1] = label_iter->second[label].color[1];
303 cmd_buf_labels[last_index - label].color[2] = label_iter->second[label].color[2];
304 cmd_buf_labels[last_index - label].color[3] = label_iter->second[label].color[3];
305 }
306 callback_data.cmdBufLabelCount = label_size;
307 callback_data.pCmdBufLabels = cmd_buf_labels;
308 }
309 }
310 }
311 // Look for any debug utils or marker names to use for this object
312 callback_data.pObjects[0].pObjectName = NULL;
313 auto utils_name_iter = debug_data->debugUtilsObjectNameMap->find(src_object);
314 if (utils_name_iter != debug_data->debugUtilsObjectNameMap->end()) {
315 callback_data.pObjects[0].pObjectName = utils_name_iter->second.c_str();
316 } else {
317 auto marker_name_iter = debug_data->debugObjectNameMap->find(src_object);
318 if (marker_name_iter != debug_data->debugObjectNameMap->end()) {
319 callback_data.pObjects[0].pObjectName = marker_name_iter->second.c_str();
320 }
321 }
322 if (NULL != callback_data.pObjects[0].pObjectName) {
Mark Young8504ba62018-03-21 13:35:34 -0600323 oss << " (Name = " << callback_data.pObjects[0].pObjectName << " : Type = ";
324 } else {
325 oss << " (Type = ";
Mark Young6ba8abe2017-11-09 10:37:04 -0700326 }
Mark Young8504ba62018-03-21 13:35:34 -0600327 oss << std::to_string(object_type) << ")";
328 } else {
329 oss << "Object: VK_NULL_HANDLE (Type = " << std::to_string(object_type) << ")";
Mark Young6ba8abe2017-11-09 10:37:04 -0700330 }
331 new_debug_report_message += oss.str();
332 new_debug_report_message += " | ";
333 new_debug_report_message += message;
334
335 while (layer_dbg_node) {
Mark Young8504ba62018-03-21 13:35:34 -0600336 // If the app uses the VK_EXT_debug_report extension, call all of those registered callbacks.
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700337 if (!layer_dbg_node->is_messenger && (layer_dbg_node->report.msgFlags & msg_flags)) {
338 if (text_vuid != nullptr) {
339 // If a text vuid is supplied for the old debug report extension, prepend it to the message string
340 new_debug_report_message.insert(0, " ] ");
341 new_debug_report_message.insert(0, text_vuid);
342 new_debug_report_message.insert(0, " [ ");
343 }
344
Dave Houlton407df732018-08-06 17:58:24 -0600345 if (layer_dbg_node->report.pfnMsgCallback(msg_flags, object_type, src_object, location, 0, layer_prefix,
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700346 new_debug_report_message.c_str(), layer_dbg_node->pUserData)) {
347 bail = true;
348 }
Mark Young8504ba62018-03-21 13:35:34 -0600349 // If the app uses the VK_EXT_debug_utils extension, call all of those registered callbacks.
Mark Young6ba8abe2017-11-09 10:37:04 -0700350 } else if (layer_dbg_node->is_messenger && (layer_dbg_node->messenger.messageSeverity & severity) &&
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700351 (layer_dbg_node->messenger.messageType & types)) {
352 if (layer_dbg_node->messenger.pfnUserCallback(static_cast<VkDebugUtilsMessageSeverityFlagBitsEXT>(severity), types,
353 &callback_data, layer_dbg_node->pUserData)) {
354 bail = true;
355 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700356 }
357 layer_dbg_node = layer_dbg_node->pNext;
358 }
359
360 if (nullptr != queue_labels) {
361 delete[] queue_labels;
362 }
363 if (nullptr != cmd_buf_labels) {
364 delete[] cmd_buf_labels;
365 }
366
367 return bail;
368}
369
370static inline void DebugAnnotFlagsToReportFlags(VkDebugUtilsMessageSeverityFlagBitsEXT da_severity,
371 VkDebugUtilsMessageTypeFlagsEXT da_type, VkDebugReportFlagsEXT *dr_flags) {
372 *dr_flags = 0;
373
374 if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) != 0) {
375 *dr_flags |= VK_DEBUG_REPORT_ERROR_BIT_EXT;
376 } else if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) != 0) {
377 if ((da_type & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT) != 0) {
378 *dr_flags |= VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
379 } else {
380 *dr_flags |= VK_DEBUG_REPORT_WARNING_BIT_EXT;
381 }
382 } else if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) != 0) {
383 *dr_flags |= VK_DEBUG_REPORT_INFORMATION_BIT_EXT;
384 } else if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) != 0) {
385 *dr_flags |= VK_DEBUG_REPORT_DEBUG_BIT_EXT;
386 }
387}
388
389static inline bool debug_messenger_log_msg(const debug_report_data *debug_data,
390 VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
391 VkDebugUtilsMessageTypeFlagsEXT message_type,
392 VkDebugUtilsMessengerCallbackDataEXT *callback_data) {
393 bool bail = false;
394 VkLayerDbgFunctionNode *layer_dbg_node = NULL;
395
396 if (debug_data->debug_callback_list != NULL) {
397 layer_dbg_node = debug_data->debug_callback_list;
398 } else {
399 layer_dbg_node = debug_data->default_debug_callback_list;
400 }
401
402 VkDebugReportFlagsEXT object_flags = 0;
403
404 DebugAnnotFlagsToReportFlags(message_severity, message_type, &object_flags);
405
406 while (layer_dbg_node) {
407 if (layer_dbg_node->is_messenger && (layer_dbg_node->messenger.messageSeverity & message_severity) &&
408 (layer_dbg_node->messenger.messageType & message_type)) {
409 // Loop through each object and give it the proper name if it was set.
410 for (uint32_t obj = 0; obj < callback_data->objectCount; obj++) {
411 auto it = debug_data->debugUtilsObjectNameMap->find(callback_data->pObjects[obj].objectHandle);
412 if (it == debug_data->debugUtilsObjectNameMap->end()) {
413 continue;
414 }
415 callback_data->pObjects[obj].pObjectName = it->second.c_str();
416 }
417 if (layer_dbg_node->messenger.pfnUserCallback(message_severity, message_type, callback_data,
418 layer_dbg_node->pUserData)) {
419 bail = true;
420 }
421 } else if (!layer_dbg_node->is_messenger && layer_dbg_node->report.msgFlags & object_flags) {
422 auto it = debug_data->debugObjectNameMap->find(callback_data->pObjects[0].objectHandle);
John Zulauf536649b2018-05-01 13:28:27 -0600423 VkDebugReportObjectTypeEXT object_type = convertCoreObjectToDebugReportObject(callback_data->pObjects[0].objectType);
Tony Barbour3431dac2017-06-19 16:50:37 -0600424 if (it == debug_data->debugObjectNameMap->end()) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700425 if (layer_dbg_node->report.pfnMsgCallback(object_flags, object_type, callback_data->pObjects[0].objectHandle, 0,
426 callback_data->messageIdNumber, callback_data->pMessageIdName,
427 callback_data->pMessage, layer_dbg_node->pUserData)) {
Tony Barbour3431dac2017-06-19 16:50:37 -0600428 bail = true;
429 }
430 } else {
431 std::string newMsg = "SrcObject name = ";
432 newMsg.append(it->second.c_str());
433 newMsg.append(" ");
Mark Young6ba8abe2017-11-09 10:37:04 -0700434 newMsg.append(callback_data->pMessage);
435 if (layer_dbg_node->report.pfnMsgCallback(object_flags, object_type, callback_data->pObjects[0].objectHandle, 0,
436 callback_data->messageIdNumber, callback_data->pMessageIdName,
437 newMsg.c_str(), layer_dbg_node->pUserData)) {
Tony Barbour3431dac2017-06-19 16:50:37 -0600438 bail = true;
439 }
Courtney Goeltzenleuchter06640832015-09-04 13:52:24 -0600440 }
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600441 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700442 layer_dbg_node = layer_dbg_node->pNext;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600443 }
Courtney Goeltzenleuchter06640832015-09-04 13:52:24 -0600444
445 return bail;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600446}
447
Mark Young6ba8abe2017-11-09 10:37:04 -0700448static inline debug_report_data *debug_utils_create_instance(
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700449 VkLayerInstanceDispatchTable *table, VkInstance inst, uint32_t extension_count,
Mark Young6ba8abe2017-11-09 10:37:04 -0700450 const char *const *enabled_extensions) // layer or extension name to be enabled
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600451{
Mark Youngaa1aa3a2016-07-05 16:41:50 -0600452 debug_report_data *debug_data = (debug_report_data *)malloc(sizeof(debug_report_data));
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700453 if (!debug_data) return NULL;
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600454
455 memset(debug_data, 0, sizeof(debug_report_data));
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600456 for (uint32_t i = 0; i < extension_count; i++) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600457 // TODO: Check other property fields
Mark Young6ba8abe2017-11-09 10:37:04 -0700458 if (strcmp(enabled_extensions[i], VK_EXT_DEBUG_REPORT_EXTENSION_NAME) == 0) {
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600459 debug_data->g_DEBUG_REPORT = true;
Mark Young6ba8abe2017-11-09 10:37:04 -0700460 } else if (strcmp(enabled_extensions[i], VK_EXT_DEBUG_UTILS_EXTENSION_NAME) == 0) {
461 debug_data->g_DEBUG_UTILS = true;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600462 }
463 }
Tony Barbour3431dac2017-06-19 16:50:37 -0600464 debug_data->debugObjectNameMap = new std::unordered_map<uint64_t, std::string>;
Mark Young6ba8abe2017-11-09 10:37:04 -0700465 debug_data->debugUtilsObjectNameMap = new std::unordered_map<uint64_t, std::string>;
466 debug_data->debugUtilsQueueLabels = new std::unordered_map<VkQueue, std::vector<LoggingLabelData>>;
467 debug_data->debugUtilsCmdBufLabels = new std::unordered_map<VkCommandBuffer, std::vector<LoggingLabelData>>;
468 debug_data->queueLabelHasInsert = false;
469 debug_data->cmdBufLabelHasInsert = false;
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600470 return debug_data;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600471}
472
Mark Young6ba8abe2017-11-09 10:37:04 -0700473static inline void layer_debug_utils_destroy_instance(debug_report_data *debug_data) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600474 if (debug_data) {
475 RemoveAllMessageCallbacks(debug_data, &debug_data->default_debug_callback_list);
476 RemoveAllMessageCallbacks(debug_data, &debug_data->debug_callback_list);
Tony Barbour3431dac2017-06-19 16:50:37 -0600477 delete debug_data->debugObjectNameMap;
Mark Young6ba8abe2017-11-09 10:37:04 -0700478 delete debug_data->debugUtilsObjectNameMap;
479 delete debug_data->debugUtilsQueueLabels;
480 delete debug_data->debugUtilsCmdBufLabels;
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600481 free(debug_data);
Courtney Goeltzenleuchteree4027d2015-06-28 13:01:17 -0600482 }
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600483}
484
Mark Young6ba8abe2017-11-09 10:37:04 -0700485static inline debug_report_data *layer_debug_utils_create_device(debug_report_data *instance_debug_data, VkDevice device) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600486 // DEBUG_REPORT shares data between Instance and Device,
487 // so just return instance's data pointer
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600488 return instance_debug_data;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600489}
490
Mark Young6ba8abe2017-11-09 10:37:04 -0700491static inline void layer_debug_utils_destroy_device(VkDevice device) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600492 // Nothing to do since we're using instance data record
493}
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600494
Mark Young6ba8abe2017-11-09 10:37:04 -0700495static inline void layer_destroy_messenger_callback(debug_report_data *debug_data, VkDebugUtilsMessengerEXT messenger,
496 const VkAllocationCallbacks *allocator) {
497 RemoveDebugUtilsMessenger(debug_data, &debug_data->debug_callback_list, messenger);
498 RemoveDebugUtilsMessenger(debug_data, &debug_data->default_debug_callback_list, messenger);
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600499}
500
Mark Young6ba8abe2017-11-09 10:37:04 -0700501static inline VkResult layer_create_messenger_callback(debug_report_data *debug_data, bool default_callback,
502 const VkDebugUtilsMessengerCreateInfoEXT *create_info,
503 const VkAllocationCallbacks *allocator,
504 VkDebugUtilsMessengerEXT *messenger) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700505 VkLayerDbgFunctionNode *pNewDbgFuncNode = (VkLayerDbgFunctionNode *)malloc(sizeof(VkLayerDbgFunctionNode));
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700506 if (!pNewDbgFuncNode) return VK_ERROR_OUT_OF_HOST_MEMORY;
Mark Young6ba8abe2017-11-09 10:37:04 -0700507 memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode));
508 pNewDbgFuncNode->is_messenger = true;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600509
Tobin Ehliseb7715d2015-09-21 09:36:47 -0600510 // Handle of 0 is logging_callback so use allocated Node address as unique handle
Mark Young6ba8abe2017-11-09 10:37:04 -0700511 if (!(*messenger)) *messenger = (VkDebugUtilsMessengerEXT)pNewDbgFuncNode;
512 pNewDbgFuncNode->messenger.messenger = *messenger;
513 pNewDbgFuncNode->messenger.pfnUserCallback = create_info->pfnUserCallback;
514 pNewDbgFuncNode->messenger.messageSeverity = create_info->messageSeverity;
515 pNewDbgFuncNode->messenger.messageType = create_info->messageType;
516 pNewDbgFuncNode->pUserData = create_info->pUserData;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600517
Mark Young6ba8abe2017-11-09 10:37:04 -0700518 debug_data->active_severities |= create_info->messageSeverity;
519 debug_data->active_types |= create_info->messageType;
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600520 if (default_callback) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700521 AddDebugCallbackNode(debug_data, &debug_data->default_debug_callback_list, pNewDbgFuncNode);
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600522 } else {
Mark Young6ba8abe2017-11-09 10:37:04 -0700523 AddDebugCallbackNode(debug_data, &debug_data->debug_callback_list, pNewDbgFuncNode);
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600524 }
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600525
Mark Young6ba8abe2017-11-09 10:37:04 -0700526 VkDebugUtilsMessengerCallbackDataEXT callback_data = {};
527 VkDebugUtilsObjectNameInfoEXT blank_object = {};
528 callback_data.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT;
529 callback_data.pNext = NULL;
530 callback_data.flags = 0;
531 callback_data.pMessageIdName = "Layer Internal Message";
532 callback_data.messageIdNumber = 0;
533 callback_data.pMessage = "Added messenger";
534 callback_data.queueLabelCount = 0;
535 callback_data.pQueueLabels = NULL;
536 callback_data.cmdBufLabelCount = 0;
537 callback_data.pCmdBufLabels = NULL;
538 callback_data.objectCount = 1;
539 callback_data.pObjects = &blank_object;
540 blank_object.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
541 blank_object.pNext = NULL;
542 blank_object.objectType = VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT;
543 blank_object.objectHandle = HandleToUint64(*messenger);
544 blank_object.pObjectName = NULL;
545 debug_messenger_log_msg(debug_data, VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT,
546 VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT, &callback_data);
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600547 return VK_SUCCESS;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600548}
549
Mark Young6ba8abe2017-11-09 10:37:04 -0700550static inline void layer_destroy_report_callback(debug_report_data *debug_data, VkDebugReportCallbackEXT callback,
551 const VkAllocationCallbacks *allocator) {
552 RemoveDebugUtilsMessageCallback(debug_data, &debug_data->debug_callback_list, callback);
553 RemoveDebugUtilsMessageCallback(debug_data, &debug_data->default_debug_callback_list, callback);
554}
555
556static inline VkResult layer_create_report_callback(debug_report_data *debug_data, bool default_callback,
557 const VkDebugReportCallbackCreateInfoEXT *create_info,
558 const VkAllocationCallbacks *allocator, VkDebugReportCallbackEXT *callback) {
559 VkLayerDbgFunctionNode *pNewDbgFuncNode = (VkLayerDbgFunctionNode *)malloc(sizeof(VkLayerDbgFunctionNode));
560 if (!pNewDbgFuncNode) {
561 return VK_ERROR_OUT_OF_HOST_MEMORY;
562 }
563 memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode));
564 pNewDbgFuncNode->is_messenger = false;
565
566 // Handle of 0 is logging_callback so use allocated Node address as unique handle
567 if (!(*callback)) *callback = (VkDebugReportCallbackEXT)pNewDbgFuncNode;
568 pNewDbgFuncNode->report.msgCallback = *callback;
569 pNewDbgFuncNode->report.pfnMsgCallback = create_info->pfnCallback;
570 pNewDbgFuncNode->report.msgFlags = create_info->flags;
571 pNewDbgFuncNode->pUserData = create_info->pUserData;
572
573 VkFlags local_severity = 0;
574 VkFlags local_type = 0;
575 DebugReportFlagsToAnnotFlags(create_info->flags, true, &local_severity, &local_type);
576 debug_data->active_severities |= local_severity;
577 debug_data->active_types |= local_type;
578 if (default_callback) {
579 AddDebugCallbackNode(debug_data, &debug_data->default_debug_callback_list, pNewDbgFuncNode);
580 } else {
581 AddDebugCallbackNode(debug_data, &debug_data->debug_callback_list, pNewDbgFuncNode);
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600582 }
583
Mark Young6ba8abe2017-11-09 10:37:04 -0700584 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 -0600585 "DebugReport", "Added callback", kVUIDUndefined);
Mark Young6ba8abe2017-11-09 10:37:04 -0700586 return VK_SUCCESS;
587}
588
589static inline PFN_vkVoidFunction debug_utils_get_instance_proc_addr(debug_report_data *debug_data, const char *func_name) {
590 if (!debug_data) {
591 return NULL;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600592 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700593 if (debug_data->g_DEBUG_REPORT) {
594 if (!strcmp(func_name, "vkCreateDebugReportCallbackEXT")) {
595 return (PFN_vkVoidFunction)vkCreateDebugReportCallbackEXT;
596 }
597 if (!strcmp(func_name, "vkDestroyDebugReportCallbackEXT")) {
598 return (PFN_vkVoidFunction)vkDestroyDebugReportCallbackEXT;
599 }
600 if (!strcmp(func_name, "vkDebugReportMessageEXT")) {
601 return (PFN_vkVoidFunction)vkDebugReportMessageEXT;
602 }
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600603 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700604 if (debug_data->g_DEBUG_UTILS) {
605 if (!strcmp(func_name, "vkCreateDebugUtilsMessengerEXT")) {
606 return (PFN_vkVoidFunction)vkCreateDebugUtilsMessengerEXT;
607 }
608 if (!strcmp(func_name, "vkDestroyDebugUtilsMessengerEXT")) {
609 return (PFN_vkVoidFunction)vkDestroyDebugUtilsMessengerEXT;
610 }
611 if (!strcmp(func_name, "vkSubmitDebugUtilsMessageEXT")) {
612 return (PFN_vkVoidFunction)vkSubmitDebugUtilsMessageEXT;
613 }
Courtney Goeltzenleuchter822e8d72015-11-30 15:28:25 -0700614 }
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600615 return NULL;
616}
617
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600618// This utility (called at vkCreateInstance() time), looks at a pNext chain.
619// It counts any VkDebugReportCallbackCreateInfoEXT structs that it finds. It
620// then allocates an array that can hold that many structs, as well as that
621// many VkDebugReportCallbackEXT handles. It then copies each
622// VkDebugReportCallbackCreateInfoEXT, and initializes each handle.
Mark Young6ba8abe2017-11-09 10:37:04 -0700623static inline VkResult layer_copy_tmp_report_callbacks(const void *pChain, uint32_t *num_callbacks,
624 VkDebugReportCallbackCreateInfoEXT **infos,
625 VkDebugReportCallbackEXT **callbacks) {
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600626 uint32_t n = *num_callbacks = 0;
627
628 const void *pNext = pChain;
629 while (pNext) {
630 // 1st, count the number VkDebugReportCallbackCreateInfoEXT:
631 if (((VkDebugReportCallbackCreateInfoEXT *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT) {
632 n++;
633 }
634 pNext = (void *)((VkDebugReportCallbackCreateInfoEXT *)pNext)->pNext;
635 }
636 if (n == 0) {
637 return VK_SUCCESS;
638 }
639
640 // 2nd, allocate memory for each VkDebugReportCallbackCreateInfoEXT:
641 VkDebugReportCallbackCreateInfoEXT *pInfos = *infos =
642 ((VkDebugReportCallbackCreateInfoEXT *)malloc(n * sizeof(VkDebugReportCallbackCreateInfoEXT)));
643 if (!pInfos) {
644 return VK_ERROR_OUT_OF_HOST_MEMORY;
645 }
646 // 3rd, allocate memory for a unique handle for each callback:
647 VkDebugReportCallbackEXT *pCallbacks = *callbacks = ((VkDebugReportCallbackEXT *)malloc(n * sizeof(VkDebugReportCallbackEXT)));
648 if (!pCallbacks) {
649 free(pInfos);
650 return VK_ERROR_OUT_OF_HOST_MEMORY;
651 }
652 // 4th, copy each VkDebugReportCallbackCreateInfoEXT for use by
653 // vkDestroyInstance, and assign a unique handle to each callback (just
654 // use the address of the copied VkDebugReportCallbackCreateInfoEXT):
655 pNext = pChain;
656 while (pNext) {
657 if (((VkInstanceCreateInfo *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT) {
658 memcpy(pInfos, pNext, sizeof(VkDebugReportCallbackCreateInfoEXT));
659 *pCallbacks++ = (VkDebugReportCallbackEXT)pInfos++;
660 }
661 pNext = (void *)((VkInstanceCreateInfo *)pNext)->pNext;
662 }
663
664 *num_callbacks = n;
665 return VK_SUCCESS;
666}
667
Mark Young6ba8abe2017-11-09 10:37:04 -0700668// This utility frees the arrays allocated by layer_copy_tmp_report_callbacks()
669static inline void layer_free_tmp_report_callbacks(VkDebugReportCallbackCreateInfoEXT *infos, VkDebugReportCallbackEXT *callbacks) {
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600670 free(infos);
671 free(callbacks);
672}
673
674// This utility enables all of the VkDebugReportCallbackCreateInfoEXT structs
Mark Young6ba8abe2017-11-09 10:37:04 -0700675// that were copied by layer_copy_tmp_report_callbacks()
676static inline VkResult layer_enable_tmp_report_callbacks(debug_report_data *debug_data, uint32_t num_callbacks,
677 VkDebugReportCallbackCreateInfoEXT *infos,
678 VkDebugReportCallbackEXT *callbacks) {
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600679 VkResult rtn = VK_SUCCESS;
680 for (uint32_t i = 0; i < num_callbacks; i++) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700681 rtn = layer_create_report_callback(debug_data, false, &infos[i], NULL, &callbacks[i]);
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600682 if (rtn != VK_SUCCESS) {
683 for (uint32_t j = 0; j < i; j++) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700684 layer_destroy_report_callback(debug_data, callbacks[j], NULL);
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600685 }
686 return rtn;
687 }
688 }
689 return rtn;
690}
691
692// This utility disables all of the VkDebugReportCallbackCreateInfoEXT structs
Mark Young6ba8abe2017-11-09 10:37:04 -0700693// that were copied by layer_copy_tmp_report_callbacks()
694static inline void layer_disable_tmp_report_callbacks(debug_report_data *debug_data, uint32_t num_callbacks,
695 VkDebugReportCallbackEXT *callbacks) {
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600696 for (uint32_t i = 0; i < num_callbacks; i++) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700697 layer_destroy_report_callback(debug_data, callbacks[i], NULL);
698 }
699}
700
701// This utility (called at vkCreateInstance() time), looks at a pNext chain.
702// It counts any VkDebugUtilsMessengerCreateInfoEXT structs that it finds. It
703// then allocates an array that can hold that many structs, as well as that
704// many VkDebugUtilsMessengerEXT handles. It then copies each
705// VkDebugUtilsMessengerCreateInfoEXT, and initializes each handle.
Mark Young8504ba62018-03-21 13:35:34 -0600706static inline VkResult layer_copy_tmp_debug_messengers(const void *pChain, uint32_t *num_messengers,
707 VkDebugUtilsMessengerCreateInfoEXT **infos,
708 VkDebugUtilsMessengerEXT **messengers) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700709 uint32_t n = *num_messengers = 0;
710
711 const void *pNext = pChain;
712 while (pNext) {
713 // 1st, count the number VkDebugUtilsMessengerCreateInfoEXT:
714 if (((VkDebugUtilsMessengerCreateInfoEXT *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT) {
715 n++;
716 }
717 pNext = (void *)((VkDebugUtilsMessengerCreateInfoEXT *)pNext)->pNext;
718 }
719 if (n == 0) {
720 return VK_SUCCESS;
721 }
722
723 // 2nd, allocate memory for each VkDebugUtilsMessengerCreateInfoEXT:
724 VkDebugUtilsMessengerCreateInfoEXT *pInfos = *infos =
725 ((VkDebugUtilsMessengerCreateInfoEXT *)malloc(n * sizeof(VkDebugUtilsMessengerCreateInfoEXT)));
726 if (!pInfos) {
727 return VK_ERROR_OUT_OF_HOST_MEMORY;
728 }
729 // 3rd, allocate memory for a unique handle for each messenger:
730 VkDebugUtilsMessengerEXT *pMessengers = *messengers =
731 ((VkDebugUtilsMessengerEXT *)malloc(n * sizeof(VkDebugUtilsMessengerEXT)));
732 if (!pMessengers) {
733 free(pInfos);
734 return VK_ERROR_OUT_OF_HOST_MEMORY;
735 }
736 // 4th, copy each VkDebugUtilsMessengerCreateInfoEXT for use by
737 // vkDestroyInstance, and assign a unique handle to each callback (just
738 // use the address of the copied VkDebugUtilsMessengerCreateInfoEXT):
739 pNext = pChain;
740 while (pNext) {
741 if (((VkInstanceCreateInfo *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT) {
742 memcpy(pInfos, pNext, sizeof(VkDebugUtilsMessengerCreateInfoEXT));
743 *pMessengers++ = (VkDebugUtilsMessengerEXT)pInfos++;
744 }
745 pNext = (void *)((VkInstanceCreateInfo *)pNext)->pNext;
746 }
747
748 *num_messengers = n;
749 return VK_SUCCESS;
750}
751
752// This utility frees the arrays allocated by layer_copy_tmp_debug_messengers()
Mark Young8504ba62018-03-21 13:35:34 -0600753static inline void layer_free_tmp_debug_messengers(VkDebugUtilsMessengerCreateInfoEXT *infos,
754 VkDebugUtilsMessengerEXT *messengers) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700755 free(infos);
756 free(messengers);
757}
758
759// This utility enables all of the VkDebugUtilsMessengerCreateInfoEXT structs
760// that were copied by layer_copy_tmp_debug_messengers()
Mark Young8504ba62018-03-21 13:35:34 -0600761static inline VkResult layer_enable_tmp_debug_messengers(debug_report_data *debug_data, uint32_t num_messengers,
762 VkDebugUtilsMessengerCreateInfoEXT *infos,
763 VkDebugUtilsMessengerEXT *messengers) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700764 VkResult rtn = VK_SUCCESS;
765 for (uint32_t i = 0; i < num_messengers; i++) {
766 rtn = layer_create_messenger_callback(debug_data, false, &infos[i], NULL, &messengers[i]);
767 if (rtn != VK_SUCCESS) {
768 for (uint32_t j = 0; j < i; j++) {
769 layer_destroy_messenger_callback(debug_data, messengers[j], NULL);
770 }
771 return rtn;
772 }
773 }
774 return rtn;
775}
776
777// This utility disables all of the VkDebugUtilsMessengerCreateInfoEXT structs
778// that were copied by layer_copy_tmp_debug_messengers()
Mark Young8504ba62018-03-21 13:35:34 -0600779static inline void layer_disable_tmp_debug_messengers(debug_report_data *debug_data, uint32_t num_messengers,
780 VkDebugUtilsMessengerEXT *messengers) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700781 for (uint32_t i = 0; i < num_messengers; i++) {
782 layer_destroy_messenger_callback(debug_data, messengers[i], NULL);
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600783 }
784}
785
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600786// Checks if the message will get logged.
787// Allows layer to defer collecting & formating data if the
788// message will be discarded.
Mark Young6ba8abe2017-11-09 10:37:04 -0700789static inline bool will_log_msg(debug_report_data *debug_data, VkFlags msg_flags) {
790 VkFlags local_severity = 0;
791 VkFlags local_type = 0;
792 DebugReportFlagsToAnnotFlags(msg_flags, true, &local_severity, &local_type);
793 if (!debug_data || !(debug_data->active_severities & local_severity) || !(debug_data->active_types & local_type)) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600794 // Message is not wanted
Courtney Goeltzenleuchter6a564a12015-09-18 16:30:24 -0600795 return false;
796 }
797
798 return true;
799}
John Zulauf6664e272018-01-17 11:00:22 -0700800#ifndef WIN32
Mark Lobodzinski1bcbdf92018-02-07 10:00:22 -0700801static inline int string_sprintf(std::string *output, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
John Zulauf6664e272018-01-17 11:00:22 -0700802#endif
Mark Lobodzinski1bcbdf92018-02-07 10:00:22 -0700803static inline int string_sprintf(std::string *output, const char *fmt, ...) {
John Zulauf6664e272018-01-17 11:00:22 -0700804 std::string &formatted = *output;
805 va_list argptr;
806 va_start(argptr, fmt);
807 int reserve = vsnprintf(nullptr, 0, fmt, argptr);
808 va_end(argptr);
809 formatted.reserve(reserve + 1);
810 va_start(argptr, fmt);
811 int result = vsnprintf((char *)formatted.data(), formatted.capacity(), fmt, argptr);
812 va_end(argptr);
813 assert(result == reserve);
814 return result;
815}
Courtney Goeltzenleuchter6a564a12015-09-18 16:30:24 -0600816
Chris Forbes8a25bce2016-03-24 12:06:35 +1300817#ifdef WIN32
818static inline int vasprintf(char **strp, char const *fmt, va_list ap) {
819 *strp = nullptr;
820 int size = _vscprintf(fmt, ap);
821 if (size >= 0) {
Mark Lobodzinski729a8d32017-01-26 12:16:30 -0700822 *strp = (char *)malloc(size + 1);
Chris Forbes8a25bce2016-03-24 12:06:35 +1300823 if (!*strp) {
824 return -1;
825 }
Mark Lobodzinski729a8d32017-01-26 12:16:30 -0700826 _vsnprintf(*strp, size + 1, fmt, ap);
Chris Forbes8a25bce2016-03-24 12:06:35 +1300827 }
828 return size;
829}
830#endif
831
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700832// Output log message via DEBUG_REPORT. Takes format and variable arg list so that output string is only computed if a message
833// needs to be logged
Michael Lentine010f4692015-11-03 16:19:46 -0800834#ifndef WIN32
Mark Young6ba8abe2017-11-09 10:37:04 -0700835static inline bool log_msg(const debug_report_data *debug_data, VkFlags msg_flags, VkDebugReportObjectTypeEXT object_type,
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700836 uint64_t src_object, std::string vuid_text, const char *format, ...)
837 __attribute__((format(printf, 6, 7)));
Michael Lentine010f4692015-11-03 16:19:46 -0800838#endif
Mark Young6ba8abe2017-11-09 10:37:04 -0700839static inline bool log_msg(const debug_report_data *debug_data, VkFlags msg_flags, VkDebugReportObjectTypeEXT object_type,
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700840 uint64_t src_object, std::string vuid_text, const char *format, ...) {
841 VkFlags local_severity = 0;
842 VkFlags local_type = 0;
843 DebugReportFlagsToAnnotFlags(msg_flags, true, &local_severity, &local_type);
844 if (!debug_data || !(debug_data->active_severities & local_severity) || !(debug_data->active_types & local_type)) {
845 // Message is not wanted
846 return false;
847 }
848
849 va_list argptr;
850 va_start(argptr, format);
851 char *str;
852 if (-1 == vasprintf(&str, format, argptr)) {
853 // On failure, glibc vasprintf leaves str undefined
854 str = nullptr;
855 }
856 va_end(argptr);
857
Dave Houlton407df732018-08-06 17:58:24 -0600858 std::string str_plus_spec_text(str ? str : "Allocation failure");
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700859
Dave Houlton407df732018-08-06 17:58:24 -0600860 // Append the spec error text to the error message, unless it's an UNASSIGNED or UNDEFINED vuid
861 if ((vuid_text.find("UNASSIGNED-") == std::string::npos) && (vuid_text.find(kVUIDUndefined) == std::string::npos)) {
862 if (vuid_to_error_text_map.find(vuid_text) == vuid_to_error_text_map.end()) {
863 // If this happens, you've hit a VUID string that isn't defined in the spec's json file
864 // Try running 'vk_validation_stats -c' to look for invalid VUID strings in the repo code
865 assert(0);
866 } else {
867 str_plus_spec_text += " The Vulkan spec states: ";
868 str_plus_spec_text += vuid_to_error_text_map[vuid_text];
869 }
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700870 }
871
Dave Houlton8e9f6542018-05-18 12:18:22 -0600872 // Append layer prefix with VUID string, pass in recovered legacy numerical VUID
Dave Houlton407df732018-08-06 17:58:24 -0600873 bool result = debug_log_msg(debug_data, msg_flags, object_type, src_object, 0, "Validation", str_plus_spec_text.c_str(),
874 vuid_text.c_str());
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700875
876 free(str);
877 return result;
878}
879
Mark Young6ba8abe2017-11-09 10:37:04 -0700880static inline VKAPI_ATTR VkBool32 VKAPI_CALL report_log_callback(VkFlags msg_flags, VkDebugReportObjectTypeEXT obj_type,
881 uint64_t src_object, size_t location, int32_t msg_code,
882 const char *layer_prefix, const char *message, void *user_data) {
883 char msg_flag_string[30];
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600884
Mark Young6ba8abe2017-11-09 10:37:04 -0700885 PrintMessageFlags(msg_flags, msg_flag_string);
Courtney Goeltzenleuchter2f25bb42015-06-14 11:29:24 -0600886
Mark Lobodzinskib1fd9d12018-03-30 14:26:00 -0600887 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 -0700888 fflush((FILE *)user_data);
Courtney Goeltzenleuchter06640832015-09-04 13:52:24 -0600889
890 return false;
Courtney Goeltzenleuchter2f25bb42015-06-14 11:29:24 -0600891}
Courtney Goeltzenleuchter5907ac42015-10-05 14:41:34 -0600892
Mark Young6ba8abe2017-11-09 10:37:04 -0700893static inline VKAPI_ATTR VkBool32 VKAPI_CALL report_win32_debug_output_msg(VkFlags msg_flags, VkDebugReportObjectTypeEXT obj_type,
894 uint64_t src_object, size_t location, int32_t msg_code,
895 const char *layer_prefix, const char *message,
896 void *user_data) {
Courtney Goeltzenleuchter5907ac42015-10-05 14:41:34 -0600897#ifdef WIN32
Mark Young6ba8abe2017-11-09 10:37:04 -0700898 char msg_flag_string[30];
Courtney Goeltzenleuchter5907ac42015-10-05 14:41:34 -0600899 char buf[2048];
900
Mark Young6ba8abe2017-11-09 10:37:04 -0700901 PrintMessageFlags(msg_flags, msg_flag_string);
Mark Lobodzinskib1fd9d12018-03-30 14:26:00 -0600902 _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 -0600903
904 OutputDebugString(buf);
905#endif
906
907 return false;
908}
909
Mark Young6ba8abe2017-11-09 10:37:04 -0700910static inline VKAPI_ATTR VkBool32 VKAPI_CALL DebugBreakCallback(VkFlags msgFlags, VkDebugReportObjectTypeEXT obj_type,
911 uint64_t src_object, size_t location, int32_t msg_code,
912 const char *layer_prefix, const char *message, void *user_data) {
Mark Lobodzinskic9d81652017-08-10 11:01:17 -0600913#ifdef WIN32
914 DebugBreak();
915#else
916 raise(SIGTRAP);
917#endif
918
919 return false;
920}
921
Mark Young6ba8abe2017-11-09 10:37:04 -0700922static inline VKAPI_ATTR VkBool32 VKAPI_CALL messenger_log_callback(VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
923 VkDebugUtilsMessageTypeFlagsEXT message_type,
924 const VkDebugUtilsMessengerCallbackDataEXT *callback_data,
925 void *user_data) {
926 char msg_severity[30];
927 char msg_type[30];
928
929 PrintMessageSeverity(message_severity, msg_severity);
930 PrintMessageType(message_type, msg_type);
931
Mark Young8504ba62018-03-21 13:35:34 -0600932 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 -0700933 callback_data->messageIdNumber, callback_data->pMessage);
Mark Young8504ba62018-03-21 13:35:34 -0600934 fprintf((FILE *)user_data, " Objects: %d\n", callback_data->objectCount);
935 for (uint32_t obj = 0; obj < callback_data->objectCount; ++obj) {
936 fprintf((FILE *)user_data, " [%d] 0x%" PRIx64 ", type: %d, name: %s\n", obj,
937 callback_data->pObjects[obj].objectHandle, callback_data->pObjects[obj].objectType,
938 callback_data->pObjects[obj].pObjectName);
939 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700940 fflush((FILE *)user_data);
941
942 return false;
Petr Krause9388f62017-05-13 20:53:12 +0200943}
944
Mark Young6ba8abe2017-11-09 10:37:04 -0700945static inline VKAPI_ATTR VkBool32 VKAPI_CALL messenger_win32_debug_output_msg(
946 VkDebugUtilsMessageSeverityFlagBitsEXT message_severity, VkDebugUtilsMessageTypeFlagsEXT message_type,
947 const VkDebugUtilsMessengerCallbackDataEXT *callback_data, void *user_data) {
948#ifdef WIN32
949 char buf[2048];
950 char msg_severity[30];
951 char msg_type[30];
Mark Lobodzinski863d5de2017-05-22 10:10:07 -0600952
Mark Young6ba8abe2017-11-09 10:37:04 -0700953 PrintMessageSeverity(message_severity, msg_severity);
954 PrintMessageType(message_type, msg_type);
955
Mark Young8504ba62018-03-21 13:35:34 -0600956 size_t buffer_space = sizeof(buf) - 1;
957 size_t remaining_space = buffer_space;
958 _snprintf(buf, sizeof(buf) - 1, "%s(%s / %s): msgNum: %d - %s\n", callback_data->pMessageIdName, msg_severity, msg_type,
959 callback_data->messageIdNumber, callback_data->pMessage);
960 remaining_space = buffer_space - strlen(buf);
961 _snprintf(buf, remaining_space, " Objects: %d\n", callback_data->objectCount);
962 for (uint32_t obj = 0; obj < callback_data->objectCount; ++obj) {
963 remaining_space = buffer_space - strlen(buf);
964 if (remaining_space > 0) {
965 _snprintf(buf, remaining_space, " [%d] 0x%" PRIx64 ", type: %d, name: %s\n", obj,
966 callback_data->pObjects[obj].objectHandle, callback_data->pObjects[obj].objectType,
967 callback_data->pObjects[obj].pObjectName);
968 }
969 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700970 OutputDebugString(buf);
971#endif
972
973 return false;
974}
975
976// This utility converts from the VkDebugUtilsLabelEXT structure into the logging version of the structure.
977// In the logging version, we only record what we absolutely need to convey back to the callbacks.
978static inline void InsertLabelIntoLog(const VkDebugUtilsLabelEXT *utils_label, std::vector<LoggingLabelData> &log_vector) {
979 LoggingLabelData log_label_data = {};
980 log_label_data.name = utils_label->pLabelName;
981 log_label_data.color[0] = utils_label->color[0];
982 log_label_data.color[1] = utils_label->color[1];
983 log_label_data.color[2] = utils_label->color[2];
984 log_label_data.color[3] = utils_label->color[3];
985 log_vector.push_back(log_label_data);
986}
987
Mark Young8504ba62018-03-21 13:35:34 -0600988static inline void BeginQueueDebugUtilsLabel(debug_report_data *report_data, VkQueue queue,
989 const VkDebugUtilsLabelEXT *label_info) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700990 if (nullptr != label_info && nullptr != label_info->pLabelName) {
991 auto label_iter = report_data->debugUtilsQueueLabels->find(queue);
992 if (label_iter == report_data->debugUtilsQueueLabels->end()) {
993 std::vector<LoggingLabelData> new_queue_labels;
994 InsertLabelIntoLog(label_info, new_queue_labels);
995 report_data->debugUtilsQueueLabels->insert({queue, new_queue_labels});
996 } else {
997 // If the last thing was a label insert, we need to pop it off of the label vector before any
998 // changes. This is because a label added with "vkQueueInsertDebugUtilsLabelEXT" is only a
999 // temporary location that exists until the next operation occurs. In this case, a new
1000 // "vkQueueBeginDebugUtilsLabelEXT" has occurred erasing the previous inserted label.
1001 if (report_data->queueLabelHasInsert) {
1002 report_data->queueLabelHasInsert = false;
1003 label_iter->second.pop_back();
1004 }
1005 InsertLabelIntoLog(label_info, label_iter->second);
1006 }
1007 }
1008}
1009
Mark Young8504ba62018-03-21 13:35:34 -06001010static inline void EndQueueDebugUtilsLabel(debug_report_data *report_data, VkQueue queue) {
Mark Young6ba8abe2017-11-09 10:37:04 -07001011 auto label_iter = report_data->debugUtilsQueueLabels->find(queue);
1012 if (label_iter != report_data->debugUtilsQueueLabels->end()) {
1013 // If the last thing was a label insert, we need to pop it off of the label vector before any
1014 // changes. This is because a label added with "vkQueueInsertDebugUtilsLabelEXT" is only a
1015 // temporary location that exists until the next operation occurs. In this case, a
1016 // "vkQueueEndDebugUtilsLabelEXT" has occurred erasing the inserted label.
1017 if (report_data->queueLabelHasInsert) {
1018 report_data->queueLabelHasInsert = false;
1019 label_iter->second.pop_back();
1020 }
1021 // Now pop the normal item
1022 label_iter->second.pop_back();
1023 }
1024}
1025
Mark Young8504ba62018-03-21 13:35:34 -06001026static inline void InsertQueueDebugUtilsLabel(debug_report_data *report_data, VkQueue queue,
1027 const VkDebugUtilsLabelEXT *label_info) {
Mark Young6ba8abe2017-11-09 10:37:04 -07001028 if (nullptr != label_info && nullptr != label_info->pLabelName) {
1029 auto label_iter = report_data->debugUtilsQueueLabels->find(queue);
1030 if (label_iter == report_data->debugUtilsQueueLabels->end()) {
1031 std::vector<LoggingLabelData> new_queue_labels;
1032 InsertLabelIntoLog(label_info, new_queue_labels);
1033 report_data->debugUtilsQueueLabels->insert({queue, new_queue_labels});
1034 } else {
1035 // If the last thing was a label insert, we need to pop it off of the label vector before any
1036 // changes. This is because a label added with "vkQueueInsertDebugUtilsLabelEXT" is only a
1037 // temporary location that exists until the next operation occurs. In this case, a new
1038 // "vkQueueInsertDebugUtilsLabelEXT" has occurred erasing the previous inserted label.
1039 if (report_data->queueLabelHasInsert) {
1040 label_iter->second.pop_back();
1041 }
1042 // Insert this new label and mark it as one that has been "inserted" so we can remove it on
1043 // the next queue label operation.
1044 InsertLabelIntoLog(label_info, label_iter->second);
1045 report_data->queueLabelHasInsert = true;
1046 }
1047 }
1048}
1049
Mark Young8504ba62018-03-21 13:35:34 -06001050static inline void BeginCmdDebugUtilsLabel(debug_report_data *report_data, VkCommandBuffer command_buffer,
1051 const VkDebugUtilsLabelEXT *label_info) {
Mark Young6ba8abe2017-11-09 10:37:04 -07001052 if (nullptr != label_info && nullptr != label_info->pLabelName) {
1053 auto label_iter = report_data->debugUtilsCmdBufLabels->find(command_buffer);
1054 if (label_iter == report_data->debugUtilsCmdBufLabels->end()) {
1055 std::vector<LoggingLabelData> new_cmdbuf_labels;
1056 InsertLabelIntoLog(label_info, new_cmdbuf_labels);
1057 report_data->debugUtilsCmdBufLabels->insert({command_buffer, new_cmdbuf_labels});
1058 } else {
1059 // If the last thing was a label insert, we need to pop it off of the label vector before any
1060 // changes. This is because a label added with "vkCmdInsertDebugUtilsLabelEXT" is only a
1061 // temporary location that exists until the next operation occurs. In this case, a
1062 // "vkCmdBeginDebugUtilsLabelEXT" has occurred erasing the inserted label.
1063 if (report_data->cmdBufLabelHasInsert) {
1064 report_data->cmdBufLabelHasInsert = false;
1065 label_iter->second.pop_back();
1066 }
1067 InsertLabelIntoLog(label_info, label_iter->second);
1068 }
1069 }
1070}
1071
Mark Young8504ba62018-03-21 13:35:34 -06001072static inline void EndCmdDebugUtilsLabel(debug_report_data *report_data, VkCommandBuffer command_buffer) {
Mark Young6ba8abe2017-11-09 10:37:04 -07001073 auto label_iter = report_data->debugUtilsCmdBufLabels->find(command_buffer);
1074 if (label_iter != report_data->debugUtilsCmdBufLabels->end()) {
1075 // If the last thing was a label insert, we need to pop it off of the label vector before any
1076 // changes. This is because a label added with "vkCmdInsertDebugUtilsLabelEXT" is only a
1077 // temporary location that exists until the next operation occurs. In this case, a
1078 // "vkCmdEndDebugUtilsLabelEXT" has occurred erasing the inserted label.
1079 if (report_data->cmdBufLabelHasInsert) {
1080 report_data->cmdBufLabelHasInsert = false;
1081 label_iter->second.pop_back();
1082 }
1083 // Now pop the normal item
1084 label_iter->second.pop_back();
1085 }
1086}
1087
Mark Young8504ba62018-03-21 13:35:34 -06001088static inline void InsertCmdDebugUtilsLabel(debug_report_data *report_data, VkCommandBuffer command_buffer,
1089 const VkDebugUtilsLabelEXT *label_info) {
Mark Young6ba8abe2017-11-09 10:37:04 -07001090 if (nullptr != label_info && nullptr != label_info->pLabelName) {
1091 auto label_iter = report_data->debugUtilsCmdBufLabels->find(command_buffer);
1092 if (label_iter == report_data->debugUtilsCmdBufLabels->end()) {
1093 std::vector<LoggingLabelData> new_cmdbuf_labels;
1094 InsertLabelIntoLog(label_info, new_cmdbuf_labels);
1095 report_data->debugUtilsCmdBufLabels->insert({command_buffer, new_cmdbuf_labels});
1096 } else {
1097 // If the last thing was a label insert, we need to pop it off of the label vector before any
1098 // changes. This is because a label added with "vkCmdInsertDebugUtilsLabelEXT" is only a
1099 // temporary location that exists until the next operation occurs. In this case, a new
1100 // "vkCmdInsertDebugUtilsLabelEXT" has occurred erasing the previous inserted label.
1101 if (report_data->cmdBufLabelHasInsert) {
1102 label_iter->second.pop_back();
1103 }
1104 // Insert this new label and mark it as one that has been "inserted" so we can remove it on
1105 // the next command buffer label operation.
1106 InsertLabelIntoLog(label_info, label_iter->second);
1107 report_data->cmdBufLabelHasInsert = true;
1108 }
1109 }
1110}
Mark Lobodzinski863d5de2017-05-22 10:10:07 -06001111
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001112#endif // LAYER_LOGGING_H