• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (c) 2015-2019 The Khronos Group Inc.
2  * Copyright (c) 2015-2019 Valve Corporation
3  * Copyright (c) 2015-2019 LunarG, Inc.
4  *
5  * 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
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * 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.
16  *
17  * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
18  * Author: Tobin Ehlis <tobin@lunarg.com>
19  * Author: Mark Young <marky@lunarg.com>
20  * Author: Dave Houlton <daveh@lunarg.com>
21  *
22  */
23 
24 #ifndef LAYER_LOGGING_H
25 #define LAYER_LOGGING_H
26 
27 #include <cinttypes>
28 #include <signal.h>
29 #include <stdarg.h>
30 #include <stdbool.h>
31 #include <stdio.h>
32 
33 #include <algorithm>
34 #include <array>
35 #include <memory>
36 #include <mutex>
37 #include <sstream>
38 #include <string>
39 #include <vector>
40 #include <unordered_map>
41 #include <utility>
42 
43 #include "vk_typemap_helper.h"
44 #include "vk_loader_layer.h"
45 #include "vk_layer_config.h"
46 #include "vk_layer_data.h"
47 #include "vk_loader_platform.h"
48 #include "vulkan/vk_layer.h"
49 #include "vk_object_types.h"
50 #include "cast_utils.h"
51 #include "vk_validation_error_messages.h"
52 #include "vk_layer_dispatch_table.h"
53 
54 // Suppress unused warning on Linux
55 #if defined(__GNUC__)
56 #define DECORATE_UNUSED __attribute__((unused))
57 #else
58 #define DECORATE_UNUSED
59 #endif
60 
61 #if defined __ANDROID__
62 #include <android/log.h>
63 #define LOGCONSOLE(...) ((void)__android_log_print(ANDROID_LOG_INFO, "VALIDATION", __VA_ARGS__))
64 #else
65 #define LOGCONSOLE(...)      \
66     {                        \
67         printf(__VA_ARGS__); \
68         printf("\n");        \
69     }
70 #endif
71 
72 static const char DECORATE_UNUSED *kVUIDUndefined = "VUID_Undefined";
73 
74 #undef DECORATE_UNUSED
75 
76 // TODO: Could be autogenerated for the specific handles for extra type safety...
77 template <typename HANDLE_T>
HandleToUint64(HANDLE_T h)78 static inline uint64_t HandleToUint64(HANDLE_T h) {
79     return CastToUint64<HANDLE_T>(h);
80 }
81 
HandleToUint64(uint64_t h)82 static inline uint64_t HandleToUint64(uint64_t h) { return h; }
83 
84 // Data we store per label for logging
85 struct LoggingLabel {
86     std::string name;
87     std::array<float, 4> color;
88 
ResetLoggingLabel89     void Reset() { *this = LoggingLabel(); }
EmptyLoggingLabel90     bool Empty() const { return name.empty(); }
91 
ExportLoggingLabel92     VkDebugUtilsLabelEXT Export() const {
93         auto out = lvl_init_struct<VkDebugUtilsLabelEXT>();
94         out.pLabelName = name.c_str();
95         std::copy(color.cbegin(), color.cend(), out.color);
96         return out;
97     };
98 
LoggingLabelLoggingLabel99     LoggingLabel() : name(), color({{0.f, 0.f, 0.f, 0.f}}) {}
LoggingLabelLoggingLabel100     LoggingLabel(const VkDebugUtilsLabelEXT *label_info) {
101         if (label_info && label_info->pLabelName) {
102             name = label_info->pLabelName;
103             std::copy_n(std::begin(label_info->color), 4, color.begin());
104         } else {
105             Reset();
106         }
107     }
108 
109     LoggingLabel(const LoggingLabel &) = default;
110     LoggingLabel &operator=(const LoggingLabel &) = default;
111     LoggingLabel &operator=(LoggingLabel &&) = default;
112     LoggingLabel(LoggingLabel &&) = default;
113 
114     template <typename Name, typename Vec>
LoggingLabelLoggingLabel115     LoggingLabel(Name &&name_, Vec &&vec_) : name(std::forward<Name>(name_)), color(std::forward<Vec>(vec_)) {}
116 };
117 
118 struct LoggingLabelState {
119     std::vector<LoggingLabel> labels;
120     LoggingLabel insert_label;
121 
122     // Export the labels, but in reverse order since we want the most recent at the top.
ExportLoggingLabelState123     std::vector<VkDebugUtilsLabelEXT> Export() const {
124         size_t count = labels.size() + (insert_label.Empty() ? 0 : 1);
125         std::vector<VkDebugUtilsLabelEXT> out(count);
126 
127         if (!count) return out;
128 
129         size_t index = count - 1;
130         if (!insert_label.Empty()) {
131             out[index--] = insert_label.Export();
132         }
133         for (const auto &label : labels) {
134             out[index--] = label.Export();
135         }
136         return out;
137     }
138 };
139 
140 static inline int string_sprintf(std::string *output, const char *fmt, ...);
141 
142 typedef struct _debug_report_data {
143     VkLayerDbgFunctionNode *debug_callback_list{nullptr};
144     VkLayerDbgFunctionNode *default_debug_callback_list{nullptr};
145     VkDebugUtilsMessageSeverityFlagsEXT active_severities{0};
146     VkDebugUtilsMessageTypeFlagsEXT active_types{0};
147     bool g_DEBUG_REPORT{false};
148     bool g_DEBUG_UTILS{false};
149     bool queueLabelHasInsert{false};
150     bool cmdBufLabelHasInsert{false};
151     std::unordered_map<uint64_t, std::string> debugObjectNameMap;
152     std::unordered_map<uint64_t, std::string> debugUtilsObjectNameMap;
153     std::unordered_map<VkQueue, std::unique_ptr<LoggingLabelState>> debugUtilsQueueLabels;
154     std::unordered_map<VkCommandBuffer, std::unique_ptr<LoggingLabelState>> debugUtilsCmdBufLabels;
155     // This mutex is defined as mutable since the normal usage for a debug report object is as 'const'. The mutable keyword allows
156     // the layers to continue this pattern, but also allows them to use/change this specific member for synchronization purposes.
157     mutable std::mutex debug_report_mutex;
158 
DebugReportSetUtilsObjectName_debug_report_data159     void DebugReportSetUtilsObjectName(const VkDebugUtilsObjectNameInfoEXT *pNameInfo) {
160         std::unique_lock<std::mutex> lock(debug_report_mutex);
161         if (pNameInfo->pObjectName) {
162             debugUtilsObjectNameMap[pNameInfo->objectHandle] = pNameInfo->pObjectName;
163         } else {
164             debugUtilsObjectNameMap.erase(pNameInfo->objectHandle);
165         }
166     }
167 
DebugReportSetMarkerObjectName_debug_report_data168     void DebugReportSetMarkerObjectName(const VkDebugMarkerObjectNameInfoEXT *pNameInfo) {
169         std::unique_lock<std::mutex> lock(debug_report_mutex);
170         if (pNameInfo->pObjectName) {
171             debugObjectNameMap[pNameInfo->object] = pNameInfo->pObjectName;
172         } else {
173             debugObjectNameMap.erase(pNameInfo->object);
174         }
175     }
176 
DebugReportGetUtilsObjectName_debug_report_data177     std::string DebugReportGetUtilsObjectName(const uint64_t object) const {
178         std::string label = "";
179         const auto utils_name_iter = debugUtilsObjectNameMap.find(object);
180         if (utils_name_iter != debugUtilsObjectNameMap.end()) {
181             label = utils_name_iter->second;
182         }
183         return label;
184     }
185 
DebugReportGetMarkerObjectName_debug_report_data186     std::string DebugReportGetMarkerObjectName(const uint64_t object) const {
187         std::string label = "";
188         const auto marker_name_iter = debugObjectNameMap.find(object);
189         if (marker_name_iter != debugObjectNameMap.end()) {
190             label = marker_name_iter->second;
191         }
192         return label;
193     }
194 
FormatHandle_debug_report_data195     std::string FormatHandle(const char *handle_type_name, uint64_t handle) const {
196         std::string handle_name = DebugReportGetUtilsObjectName(handle);
197         if (handle_name.empty()) {
198             handle_name = DebugReportGetMarkerObjectName(handle);
199         }
200 
201         std::string ret;
202         string_sprintf(&ret, "%s 0x%" PRIxLEAST64 "[%s]", handle_type_name, handle, handle_name.c_str());
203         return ret;
204     }
205 
FormatHandle_debug_report_data206     std::string FormatHandle(const VulkanTypedHandle &handle) const {
207         return FormatHandle(object_string[handle.type], handle.handle);
208     }
209 
210     template <typename HANDLE_T>
FormatHandle_debug_report_data211     std::string FormatHandle(HANDLE_T handle) const {
212         return FormatHandle(VkHandleInfo<HANDLE_T>::Typename(), HandleToUint64(handle));
213     }
214 
215 } debug_report_data;
216 
217 template debug_report_data *GetLayerDataPtr<debug_report_data>(void *data_key,
218                                                                std::unordered_map<void *, debug_report_data *> &data_map);
219 
DebugReportFlagsToAnnotFlags(VkDebugReportFlagsEXT dr_flags,bool default_flag_is_spec,VkDebugUtilsMessageSeverityFlagsEXT * da_severity,VkDebugUtilsMessageTypeFlagsEXT * da_type)220 static inline void DebugReportFlagsToAnnotFlags(VkDebugReportFlagsEXT dr_flags, bool default_flag_is_spec,
221                                                 VkDebugUtilsMessageSeverityFlagsEXT *da_severity,
222                                                 VkDebugUtilsMessageTypeFlagsEXT *da_type) {
223     *da_severity = 0;
224     *da_type = 0;
225     // If it's explicitly listed as a performance warning, treat it as a performance message.
226     // Otherwise, treat it as a validation issue.
227     if ((dr_flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) != 0) {
228         *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
229         *da_severity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
230     }
231     if ((dr_flags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) != 0) {
232         *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;
233         *da_severity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT;
234     }
235     if ((dr_flags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) != 0) {
236         *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;
237         *da_severity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
238     }
239     if ((dr_flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) != 0) {
240         *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;
241         *da_severity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
242     }
243     if ((dr_flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) != 0) {
244         *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;
245         *da_severity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
246     }
247 }
248 
249 // Forward Declarations
250 static inline bool debug_log_msg(const debug_report_data *debug_data, VkFlags msg_flags, VkDebugReportObjectTypeEXT object_type,
251                                  uint64_t src_object, size_t location, const char *layer_prefix, const char *message,
252                                  const char *text_vuid);
253 
254 // Add a debug message callback node structure to the specified callback linked list
AddDebugCallbackNode(debug_report_data * debug_data,VkLayerDbgFunctionNode ** list_head,VkLayerDbgFunctionNode * new_node)255 static inline void AddDebugCallbackNode(debug_report_data *debug_data, VkLayerDbgFunctionNode **list_head,
256                                         VkLayerDbgFunctionNode *new_node) {
257     new_node->pNext = *list_head;
258     *list_head = new_node;
259 }
260 
261 // Remove specified debug messenger node structure from the specified linked list
RemoveDebugUtilsMessenger(debug_report_data * debug_data,VkLayerDbgFunctionNode ** list_head,VkDebugUtilsMessengerEXT messenger)262 static inline void RemoveDebugUtilsMessenger(debug_report_data *debug_data, VkLayerDbgFunctionNode **list_head,
263                                              VkDebugUtilsMessengerEXT messenger) {
264     VkLayerDbgFunctionNode *cur_callback = *list_head;
265     VkLayerDbgFunctionNode *prev_callback = nullptr;
266     bool matched = false;
267     VkFlags local_severities = 0;
268     VkFlags local_types = 0;
269 
270     while (cur_callback) {
271         if (cur_callback->is_messenger) {
272             // If it's actually a messenger, then set it up for deletion.
273             if (cur_callback->messenger.messenger == messenger) {
274                 matched = true;
275                 if (*list_head == cur_callback) {
276                     *list_head = cur_callback->pNext;
277                 } else {
278                     assert(nullptr != prev_callback);
279                     prev_callback->pNext = cur_callback->pNext;
280                 }
281                 debug_log_msg(debug_data, VK_DEBUG_REPORT_DEBUG_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT,
282                               reinterpret_cast<uint64_t &>(cur_callback->messenger.messenger), 0, "DebugUtilsMessenger",
283                               "Destroyed messenger\n", kVUIDUndefined);
284             } else {
285                 // If it's not the one we're looking for, just keep the types/severities
286                 local_severities |= cur_callback->messenger.messageSeverity;
287                 local_types |= cur_callback->messenger.messageType;
288             }
289         } else {
290             // If it's not a messenger, just keep the types/severities
291             VkFlags this_severities = 0;
292             VkFlags this_types = 0;
293             DebugReportFlagsToAnnotFlags(cur_callback->report.msgFlags, true, &this_severities, &this_types);
294             local_severities |= this_severities;
295             local_types |= this_types;
296         }
297         if (matched) {
298             free(cur_callback);
299             matched = false;
300             // Intentionally keep the last prev_callback, but select the proper cur_callback
301             if (nullptr != prev_callback) {
302                 cur_callback = prev_callback->pNext;
303             } else {
304                 cur_callback = *list_head;
305             }
306         } else {
307             prev_callback = cur_callback;
308             cur_callback = cur_callback->pNext;
309         }
310     }
311     debug_data->active_severities = local_severities;
312     debug_data->active_types = local_types;
313 }
314 
315 // Remove specified debug message callback node structure from the specified callback linked list
RemoveDebugUtilsMessageCallback(debug_report_data * debug_data,VkLayerDbgFunctionNode ** list_head,VkDebugReportCallbackEXT callback)316 static inline void RemoveDebugUtilsMessageCallback(debug_report_data *debug_data, VkLayerDbgFunctionNode **list_head,
317                                                    VkDebugReportCallbackEXT callback) {
318     VkLayerDbgFunctionNode *cur_callback = *list_head;
319     VkLayerDbgFunctionNode *prev_callback = nullptr;
320     bool matched = false;
321     VkFlags local_severities = 0;
322     VkFlags local_types = 0;
323 
324     while (cur_callback) {
325         if (!cur_callback->is_messenger) {
326             // If it's actually a callback, then set it up for deletion.
327             if (cur_callback->report.msgCallback == callback) {
328                 matched = true;
329                 if (*list_head == cur_callback) {
330                     *list_head = cur_callback->pNext;
331                 } else {
332                     assert(nullptr != prev_callback);
333                     prev_callback->pNext = cur_callback->pNext;
334                 }
335                 debug_log_msg(debug_data, VK_DEBUG_REPORT_DEBUG_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT,
336                               reinterpret_cast<uint64_t &>(cur_callback->report.msgCallback), 0, "DebugReport",
337                               "Destroyed callback\n", kVUIDUndefined);
338             } else {
339                 // If it's not the one we're looking for, just keep the types/severities
340                 VkFlags this_severities = 0;
341                 VkFlags this_types = 0;
342                 DebugReportFlagsToAnnotFlags(cur_callback->report.msgFlags, true, &this_severities, &this_types);
343                 local_severities |= this_severities;
344                 local_types |= this_types;
345             }
346         } else {
347             // If it's not a callback, just keep the types/severities
348             local_severities |= cur_callback->messenger.messageSeverity;
349             local_types |= cur_callback->messenger.messageType;
350         }
351         if (matched) {
352             free(cur_callback);
353             matched = false;
354             // Intentionally keep the last prev_callback, but select the proper cur_callback
355             if (nullptr != prev_callback) {
356                 cur_callback = prev_callback->pNext;
357             } else {
358                 cur_callback = *list_head;
359             }
360         } else {
361             prev_callback = cur_callback;
362             cur_callback = cur_callback->pNext;
363         }
364     }
365     debug_data->active_severities = local_severities;
366     debug_data->active_types = local_types;
367 }
368 
369 // Removes all debug callback function nodes from the specified callback linked lists and frees their resources
RemoveAllMessageCallbacks(debug_report_data * debug_data,VkLayerDbgFunctionNode ** list_head)370 static inline void RemoveAllMessageCallbacks(debug_report_data *debug_data, VkLayerDbgFunctionNode **list_head) {
371     VkLayerDbgFunctionNode *current_callback = *list_head;
372     VkLayerDbgFunctionNode *prev_callback = current_callback;
373 
374     while (current_callback) {
375         prev_callback = current_callback->pNext;
376         if (!current_callback->is_messenger) {
377             debug_log_msg(debug_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT,
378                           (uint64_t)current_callback->report.msgCallback, 0, "DebugReport",
379                           "Debug Report callbacks not removed before DestroyInstance", kVUIDUndefined);
380         } else {
381             debug_log_msg(debug_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT,
382                           (uint64_t)current_callback->messenger.messenger, 0, "Messenger",
383                           "Debug messengers not removed before DestroyInstance", kVUIDUndefined);
384         }
385         free(current_callback);
386         current_callback = prev_callback;
387     }
388     *list_head = NULL;
389 }
390 
debug_log_msg(const debug_report_data * debug_data,VkFlags msg_flags,VkDebugReportObjectTypeEXT object_type,uint64_t src_object,size_t location,const char * layer_prefix,const char * message,const char * text_vuid)391 static inline bool debug_log_msg(const debug_report_data *debug_data, VkFlags msg_flags, VkDebugReportObjectTypeEXT object_type,
392                                  uint64_t src_object, size_t location, const char *layer_prefix, const char *message,
393                                  const char *text_vuid) {
394     bool bail = false;
395     VkLayerDbgFunctionNode *layer_dbg_node = NULL;
396 
397     if (debug_data->debug_callback_list != NULL) {
398         layer_dbg_node = debug_data->debug_callback_list;
399     } else {
400         layer_dbg_node = debug_data->default_debug_callback_list;
401     }
402 
403     VkDebugUtilsMessageSeverityFlagsEXT severity;
404     VkDebugUtilsMessageTypeFlagsEXT types;
405     VkDebugUtilsMessengerCallbackDataEXT callback_data;
406     VkDebugUtilsObjectNameInfoEXT object_name_info;
407 
408     // Convert the info to the VK_EXT_debug_utils form in case we need it.
409     DebugReportFlagsToAnnotFlags(msg_flags, true, &severity, &types);
410     object_name_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
411     object_name_info.pNext = NULL;
412     object_name_info.objectType = convertDebugReportObjectToCoreObject(object_type);
413     object_name_info.objectHandle = (uint64_t)(uintptr_t)src_object;
414     object_name_info.pObjectName = NULL;
415     std::string object_label = {};
416 
417     callback_data.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT;
418     callback_data.pNext = NULL;
419     callback_data.flags = 0;
420     callback_data.pMessageIdName = text_vuid;
421     callback_data.messageIdNumber = 0;  // deprecated, validation layers use only the pMessageIdName
422     callback_data.pMessage = message;
423     callback_data.queueLabelCount = 0;
424     callback_data.pQueueLabels = NULL;
425     callback_data.cmdBufLabelCount = 0;
426     callback_data.pCmdBufLabels = NULL;
427     callback_data.objectCount = 1;
428     callback_data.pObjects = &object_name_info;
429 
430     std::vector<VkDebugUtilsLabelEXT> queue_labels;
431     std::vector<VkDebugUtilsLabelEXT> cmd_buf_labels;
432     std::string new_debug_report_message = "";
433     std::ostringstream oss;
434 
435     if (0 != src_object) {
436         oss << "Object: 0x" << std::hex << src_object;
437         // If this is a queue, add any queue labels to the callback data.
438         if (VK_OBJECT_TYPE_QUEUE == object_name_info.objectType) {
439             auto label_iter = debug_data->debugUtilsQueueLabels.find(reinterpret_cast<VkQueue>(src_object));
440             if (label_iter != debug_data->debugUtilsQueueLabels.end()) {
441                 queue_labels = label_iter->second->Export();
442                 callback_data.queueLabelCount = static_cast<uint32_t>(queue_labels.size());
443                 callback_data.pQueueLabels = queue_labels.empty() ? nullptr : queue_labels.data();
444             }
445             // If this is a command buffer, add any command buffer labels to the callback data.
446         } else if (VK_OBJECT_TYPE_COMMAND_BUFFER == object_name_info.objectType) {
447             auto label_iter = debug_data->debugUtilsCmdBufLabels.find(reinterpret_cast<VkCommandBuffer>(src_object));
448             if (label_iter != debug_data->debugUtilsCmdBufLabels.end()) {
449                 cmd_buf_labels = label_iter->second->Export();
450                 callback_data.cmdBufLabelCount = static_cast<uint32_t>(cmd_buf_labels.size());
451                 callback_data.pCmdBufLabels = cmd_buf_labels.empty() ? nullptr : cmd_buf_labels.data();
452             }
453         }
454 
455         // Look for any debug utils or marker names to use for this object
456         object_label = debug_data->DebugReportGetUtilsObjectName(src_object);
457         if (object_label.empty()) {
458             object_label = debug_data->DebugReportGetMarkerObjectName(src_object);
459         }
460         if (!object_label.empty()) {
461             object_name_info.pObjectName = object_label.c_str();
462             oss << " (Name = " << object_label << " : Type = ";
463         } else {
464             oss << " (Type = ";
465         }
466         oss << std::to_string(object_type) << ")";
467     } else {
468         oss << "Object: VK_NULL_HANDLE (Type = " << std::to_string(object_type) << ")";
469     }
470     new_debug_report_message += oss.str();
471     new_debug_report_message += " | ";
472     new_debug_report_message += message;
473 
474     while (layer_dbg_node) {
475         // If the app uses the VK_EXT_debug_report extension, call all of those registered callbacks.
476         if (!layer_dbg_node->is_messenger && (layer_dbg_node->report.msgFlags & msg_flags)) {
477             if (text_vuid != nullptr) {
478                 // If a text vuid is supplied for the old debug report extension, prepend it to the message string
479                 new_debug_report_message.insert(0, " ] ");
480                 new_debug_report_message.insert(0, text_vuid);
481                 new_debug_report_message.insert(0, " [ ");
482             }
483 
484             if (layer_dbg_node->report.pfnMsgCallback(msg_flags, object_type, src_object, location, 0, layer_prefix,
485                                                       new_debug_report_message.c_str(), layer_dbg_node->pUserData)) {
486                 bail = true;
487             }
488             // If the app uses the VK_EXT_debug_utils extension, call all of those registered callbacks.
489         } else if (layer_dbg_node->is_messenger && (layer_dbg_node->messenger.messageSeverity & severity) &&
490                    (layer_dbg_node->messenger.messageType & types)) {
491             if (layer_dbg_node->messenger.pfnUserCallback(static_cast<VkDebugUtilsMessageSeverityFlagBitsEXT>(severity), types,
492                                                           &callback_data, layer_dbg_node->pUserData)) {
493                 bail = true;
494             }
495         }
496         layer_dbg_node = layer_dbg_node->pNext;
497     }
498 
499     return bail;
500 }
501 
DebugAnnotFlagsToReportFlags(VkDebugUtilsMessageSeverityFlagBitsEXT da_severity,VkDebugUtilsMessageTypeFlagsEXT da_type,VkDebugReportFlagsEXT * dr_flags)502 static inline void DebugAnnotFlagsToReportFlags(VkDebugUtilsMessageSeverityFlagBitsEXT da_severity,
503                                                 VkDebugUtilsMessageTypeFlagsEXT da_type, VkDebugReportFlagsEXT *dr_flags) {
504     *dr_flags = 0;
505 
506     if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) != 0) {
507         *dr_flags |= VK_DEBUG_REPORT_ERROR_BIT_EXT;
508     } else if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) != 0) {
509         if ((da_type & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT) != 0) {
510             *dr_flags |= VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
511         } else {
512             *dr_flags |= VK_DEBUG_REPORT_WARNING_BIT_EXT;
513         }
514     } else if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) != 0) {
515         *dr_flags |= VK_DEBUG_REPORT_INFORMATION_BIT_EXT;
516     } else if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) != 0) {
517         *dr_flags |= VK_DEBUG_REPORT_DEBUG_BIT_EXT;
518     }
519 }
520 
debug_messenger_log_msg(const debug_report_data * debug_data,VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,VkDebugUtilsMessageTypeFlagsEXT message_type,VkDebugUtilsMessengerCallbackDataEXT * callback_data,const VkDebugUtilsMessengerEXT * messenger)521 static inline bool debug_messenger_log_msg(const debug_report_data *debug_data,
522                                            VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
523                                            VkDebugUtilsMessageTypeFlagsEXT message_type,
524                                            VkDebugUtilsMessengerCallbackDataEXT *callback_data,
525                                            const VkDebugUtilsMessengerEXT *messenger) {
526     bool bail = false;
527     VkLayerDbgFunctionNode *layer_dbg_node = NULL;
528 
529     if (debug_data->debug_callback_list != NULL) {
530         layer_dbg_node = debug_data->debug_callback_list;
531     } else {
532         layer_dbg_node = debug_data->default_debug_callback_list;
533     }
534 
535     VkDebugReportFlagsEXT object_flags = 0;
536 
537     DebugAnnotFlagsToReportFlags(message_severity, message_type, &object_flags);
538 
539     VkDebugUtilsObjectNameInfoEXT object_name_info;
540     object_name_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
541     object_name_info.pNext = NULL;
542     object_name_info.objectType = VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT;
543     object_name_info.objectHandle = HandleToUint64(*messenger);
544     object_name_info.pObjectName = NULL;
545     callback_data->pObjects = &object_name_info;
546     callback_data->objectCount = 1;
547 
548     while (layer_dbg_node) {
549         if (layer_dbg_node->is_messenger && (layer_dbg_node->messenger.messageSeverity & message_severity) &&
550             (layer_dbg_node->messenger.messageType & message_type)) {
551             std::string messenger_label = debug_data->DebugReportGetUtilsObjectName(object_name_info.objectHandle);
552             if (!messenger_label.empty()) {
553                 object_name_info.pObjectName = messenger_label.c_str();
554             }
555             if (layer_dbg_node->messenger.pfnUserCallback(message_severity, message_type, callback_data,
556                                                           layer_dbg_node->pUserData)) {
557                 bail = true;
558             }
559         } else if (!layer_dbg_node->is_messenger && layer_dbg_node->report.msgFlags & object_flags) {
560             VkDebugReportObjectTypeEXT object_type = convertCoreObjectToDebugReportObject(callback_data->pObjects[0].objectType);
561             std::string marker_label = debug_data->DebugReportGetMarkerObjectName(object_name_info.objectHandle);
562             if (marker_label.empty()) {
563                 if (layer_dbg_node->report.pfnMsgCallback(object_flags, object_type, callback_data->pObjects[0].objectHandle, 0,
564                                                           callback_data->messageIdNumber, callback_data->pMessageIdName,
565                                                           callback_data->pMessage, layer_dbg_node->pUserData)) {
566                     bail = true;
567                 }
568             } else {
569                 std::string newMsg = "SrcObject name = " + marker_label;
570                 newMsg.append(" ");
571                 newMsg.append(callback_data->pMessage);
572                 if (layer_dbg_node->report.pfnMsgCallback(object_flags, object_type, callback_data->pObjects[0].objectHandle, 0,
573                                                           callback_data->messageIdNumber, callback_data->pMessageIdName,
574                                                           newMsg.c_str(), layer_dbg_node->pUserData)) {
575                     bail = true;
576                 }
577             }
578         }
579         layer_dbg_node = layer_dbg_node->pNext;
580     }
581 
582     return bail;
583 }
584 
debug_utils_create_instance(VkLayerInstanceDispatchTable * table,VkInstance inst,uint32_t extension_count,const char * const * enabled_extensions)585 static inline debug_report_data *debug_utils_create_instance(
586     VkLayerInstanceDispatchTable *table, VkInstance inst, uint32_t extension_count,
587     const char *const *enabled_extensions)  // layer or extension name to be enabled
588 {
589     debug_report_data *debug_data = new debug_report_data;
590     for (uint32_t i = 0; i < extension_count; i++) {
591         if (strcmp(enabled_extensions[i], VK_EXT_DEBUG_REPORT_EXTENSION_NAME) == 0) {
592             debug_data->g_DEBUG_REPORT = true;
593         } else if (strcmp(enabled_extensions[i], VK_EXT_DEBUG_UTILS_EXTENSION_NAME) == 0) {
594             debug_data->g_DEBUG_UTILS = true;
595         }
596     }
597     return debug_data;
598 }
599 
layer_debug_utils_destroy_instance(debug_report_data * debug_data)600 static inline void layer_debug_utils_destroy_instance(debug_report_data *debug_data) {
601     if (debug_data) {
602         std::unique_lock<std::mutex> lock(debug_data->debug_report_mutex);
603         RemoveAllMessageCallbacks(debug_data, &debug_data->default_debug_callback_list);
604         RemoveAllMessageCallbacks(debug_data, &debug_data->debug_callback_list);
605         lock.unlock();
606         delete (debug_data);
607     }
608 }
609 
layer_debug_utils_create_device(debug_report_data * instance_debug_data,VkDevice device)610 static inline debug_report_data *layer_debug_utils_create_device(debug_report_data *instance_debug_data, VkDevice device) {
611     // DEBUG_REPORT shares data between Instance and Device,
612     // so just return instance's data pointer
613     return instance_debug_data;
614 }
615 
layer_debug_utils_destroy_device(VkDevice device)616 static inline void layer_debug_utils_destroy_device(VkDevice device) {
617     // Nothing to do since we're using instance data record
618 }
619 
layer_destroy_messenger_callback(debug_report_data * debug_data,VkDebugUtilsMessengerEXT messenger,const VkAllocationCallbacks * allocator)620 static inline void layer_destroy_messenger_callback(debug_report_data *debug_data, VkDebugUtilsMessengerEXT messenger,
621                                                     const VkAllocationCallbacks *allocator) {
622     std::unique_lock<std::mutex> lock(debug_data->debug_report_mutex);
623     RemoveDebugUtilsMessenger(debug_data, &debug_data->debug_callback_list, messenger);
624     RemoveDebugUtilsMessenger(debug_data, &debug_data->default_debug_callback_list, messenger);
625 }
626 
layer_create_messenger_callback(debug_report_data * debug_data,bool default_callback,const VkDebugUtilsMessengerCreateInfoEXT * create_info,const VkAllocationCallbacks * allocator,VkDebugUtilsMessengerEXT * messenger)627 static inline VkResult layer_create_messenger_callback(debug_report_data *debug_data, bool default_callback,
628                                                        const VkDebugUtilsMessengerCreateInfoEXT *create_info,
629                                                        const VkAllocationCallbacks *allocator,
630                                                        VkDebugUtilsMessengerEXT *messenger) {
631     std::unique_lock<std::mutex> lock(debug_data->debug_report_mutex);
632     VkLayerDbgFunctionNode *pNewDbgFuncNode = (VkLayerDbgFunctionNode *)malloc(sizeof(VkLayerDbgFunctionNode));
633     if (!pNewDbgFuncNode) return VK_ERROR_OUT_OF_HOST_MEMORY;
634     memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode));
635     pNewDbgFuncNode->is_messenger = true;
636 
637     // Handle of 0 is logging_callback so use allocated Node address as unique handle
638     if (!(*messenger)) *messenger = (VkDebugUtilsMessengerEXT)pNewDbgFuncNode;
639     pNewDbgFuncNode->messenger.messenger = *messenger;
640     pNewDbgFuncNode->messenger.pfnUserCallback = create_info->pfnUserCallback;
641     pNewDbgFuncNode->messenger.messageSeverity = create_info->messageSeverity;
642     pNewDbgFuncNode->messenger.messageType = create_info->messageType;
643     pNewDbgFuncNode->pUserData = create_info->pUserData;
644 
645     debug_data->active_severities |= create_info->messageSeverity;
646     debug_data->active_types |= create_info->messageType;
647     if (default_callback) {
648         AddDebugCallbackNode(debug_data, &debug_data->default_debug_callback_list, pNewDbgFuncNode);
649     } else {
650         AddDebugCallbackNode(debug_data, &debug_data->debug_callback_list, pNewDbgFuncNode);
651     }
652 
653     VkDebugUtilsMessengerCallbackDataEXT callback_data = {};
654     callback_data.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT;
655     callback_data.pNext = NULL;
656     callback_data.flags = 0;
657     callback_data.pMessageIdName = "Layer Internal Message";
658     callback_data.messageIdNumber = 0;
659     callback_data.pMessage = "Added messenger";
660     callback_data.queueLabelCount = 0;
661     callback_data.pQueueLabels = NULL;
662     callback_data.cmdBufLabelCount = 0;
663     callback_data.pCmdBufLabels = NULL;
664     callback_data.objectCount = 0;
665     callback_data.pObjects = NULL;
666     debug_messenger_log_msg(debug_data, VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT,
667                             VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT, &callback_data, messenger);
668     return VK_SUCCESS;
669 }
670 
layer_destroy_report_callback(debug_report_data * debug_data,VkDebugReportCallbackEXT callback,const VkAllocationCallbacks * allocator)671 static inline void layer_destroy_report_callback(debug_report_data *debug_data, VkDebugReportCallbackEXT callback,
672                                                  const VkAllocationCallbacks *allocator) {
673     std::unique_lock<std::mutex> lock(debug_data->debug_report_mutex);
674     RemoveDebugUtilsMessageCallback(debug_data, &debug_data->debug_callback_list, callback);
675     RemoveDebugUtilsMessageCallback(debug_data, &debug_data->default_debug_callback_list, callback);
676 }
677 
layer_create_report_callback(debug_report_data * debug_data,bool default_callback,const VkDebugReportCallbackCreateInfoEXT * create_info,const VkAllocationCallbacks * allocator,VkDebugReportCallbackEXT * callback)678 static inline VkResult layer_create_report_callback(debug_report_data *debug_data, bool default_callback,
679                                                     const VkDebugReportCallbackCreateInfoEXT *create_info,
680                                                     const VkAllocationCallbacks *allocator, VkDebugReportCallbackEXT *callback) {
681     std::unique_lock<std::mutex> lock(debug_data->debug_report_mutex);
682     VkLayerDbgFunctionNode *pNewDbgFuncNode = (VkLayerDbgFunctionNode *)malloc(sizeof(VkLayerDbgFunctionNode));
683     if (!pNewDbgFuncNode) {
684         return VK_ERROR_OUT_OF_HOST_MEMORY;
685     }
686     memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode));
687     pNewDbgFuncNode->is_messenger = false;
688 
689     // Handle of 0 is logging_callback so use allocated Node address as unique handle
690     if (!(*callback)) *callback = (VkDebugReportCallbackEXT)pNewDbgFuncNode;
691     pNewDbgFuncNode->report.msgCallback = *callback;
692     pNewDbgFuncNode->report.pfnMsgCallback = create_info->pfnCallback;
693     pNewDbgFuncNode->report.msgFlags = create_info->flags;
694     pNewDbgFuncNode->pUserData = create_info->pUserData;
695 
696     VkFlags local_severity = 0;
697     VkFlags local_type = 0;
698     DebugReportFlagsToAnnotFlags(create_info->flags, true, &local_severity, &local_type);
699     debug_data->active_severities |= local_severity;
700     debug_data->active_types |= local_type;
701     if (default_callback) {
702         AddDebugCallbackNode(debug_data, &debug_data->default_debug_callback_list, pNewDbgFuncNode);
703     } else {
704         AddDebugCallbackNode(debug_data, &debug_data->debug_callback_list, pNewDbgFuncNode);
705     }
706 
707     debug_log_msg(debug_data, VK_DEBUG_REPORT_DEBUG_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT, (uint64_t)*callback, 0,
708                   "DebugReport", "Added callback", kVUIDUndefined);
709     return VK_SUCCESS;
710 }
711 
debug_utils_get_instance_proc_addr(debug_report_data * debug_data,const char * func_name)712 static inline PFN_vkVoidFunction debug_utils_get_instance_proc_addr(debug_report_data *debug_data, const char *func_name) {
713     if (!debug_data) {
714         return NULL;
715     }
716     if (debug_data->g_DEBUG_REPORT) {
717         if (!strcmp(func_name, "vkCreateDebugReportCallbackEXT")) {
718             return (PFN_vkVoidFunction)vkCreateDebugReportCallbackEXT;
719         }
720         if (!strcmp(func_name, "vkDestroyDebugReportCallbackEXT")) {
721             return (PFN_vkVoidFunction)vkDestroyDebugReportCallbackEXT;
722         }
723         if (!strcmp(func_name, "vkDebugReportMessageEXT")) {
724             return (PFN_vkVoidFunction)vkDebugReportMessageEXT;
725         }
726     }
727     if (debug_data->g_DEBUG_UTILS) {
728         if (!strcmp(func_name, "vkCreateDebugUtilsMessengerEXT")) {
729             return (PFN_vkVoidFunction)vkCreateDebugUtilsMessengerEXT;
730         }
731         if (!strcmp(func_name, "vkDestroyDebugUtilsMessengerEXT")) {
732             return (PFN_vkVoidFunction)vkDestroyDebugUtilsMessengerEXT;
733         }
734         if (!strcmp(func_name, "vkSubmitDebugUtilsMessageEXT")) {
735             return (PFN_vkVoidFunction)vkSubmitDebugUtilsMessageEXT;
736         }
737     }
738     return NULL;
739 }
740 
741 // This utility (called at vkCreateInstance() time), looks at a pNext chain.
742 // It counts any VkDebugReportCallbackCreateInfoEXT structs that it finds.  It
743 // then allocates an array that can hold that many structs, as well as that
744 // many VkDebugReportCallbackEXT handles.  It then copies each
745 // VkDebugReportCallbackCreateInfoEXT, and initializes each handle.
layer_copy_tmp_report_callbacks(const void * pChain,uint32_t * num_callbacks,VkDebugReportCallbackCreateInfoEXT ** infos,VkDebugReportCallbackEXT ** callbacks)746 static inline VkResult layer_copy_tmp_report_callbacks(const void *pChain, uint32_t *num_callbacks,
747                                                        VkDebugReportCallbackCreateInfoEXT **infos,
748                                                        VkDebugReportCallbackEXT **callbacks) {
749     uint32_t n = *num_callbacks = 0;
750 
751     const void *pNext = pChain;
752     while (pNext) {
753         // 1st, count the number VkDebugReportCallbackCreateInfoEXT:
754         if (((VkDebugReportCallbackCreateInfoEXT *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT) {
755             n++;
756         }
757         pNext = (void *)((VkDebugReportCallbackCreateInfoEXT *)pNext)->pNext;
758     }
759     if (n == 0) {
760         return VK_SUCCESS;
761     }
762 
763     // 2nd, allocate memory for each VkDebugReportCallbackCreateInfoEXT:
764     VkDebugReportCallbackCreateInfoEXT *pInfos = *infos =
765         ((VkDebugReportCallbackCreateInfoEXT *)malloc(n * sizeof(VkDebugReportCallbackCreateInfoEXT)));
766     if (!pInfos) {
767         return VK_ERROR_OUT_OF_HOST_MEMORY;
768     }
769     // 3rd, allocate memory for a unique handle for each callback:
770     VkDebugReportCallbackEXT *pCallbacks = *callbacks = ((VkDebugReportCallbackEXT *)malloc(n * sizeof(VkDebugReportCallbackEXT)));
771     if (!pCallbacks) {
772         free(pInfos);
773         return VK_ERROR_OUT_OF_HOST_MEMORY;
774     }
775     // 4th, copy each VkDebugReportCallbackCreateInfoEXT for use by
776     // vkDestroyInstance, and assign a unique handle to each callback (just
777     // use the address of the copied VkDebugReportCallbackCreateInfoEXT):
778     pNext = pChain;
779     while (pNext) {
780         if (((VkInstanceCreateInfo *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT) {
781             memcpy(pInfos, pNext, sizeof(VkDebugReportCallbackCreateInfoEXT));
782             *pCallbacks++ = (VkDebugReportCallbackEXT)pInfos++;
783         }
784         pNext = (void *)((VkInstanceCreateInfo *)pNext)->pNext;
785     }
786 
787     *num_callbacks = n;
788     return VK_SUCCESS;
789 }
790 
791 // This utility frees the arrays allocated by layer_copy_tmp_report_callbacks()
layer_free_tmp_report_callbacks(VkDebugReportCallbackCreateInfoEXT * infos,VkDebugReportCallbackEXT * callbacks)792 static inline void layer_free_tmp_report_callbacks(VkDebugReportCallbackCreateInfoEXT *infos, VkDebugReportCallbackEXT *callbacks) {
793     free(infos);
794     free(callbacks);
795 }
796 
797 // This utility enables all of the VkDebugReportCallbackCreateInfoEXT structs
798 // that were copied by layer_copy_tmp_report_callbacks()
layer_enable_tmp_report_callbacks(debug_report_data * debug_data,uint32_t num_callbacks,VkDebugReportCallbackCreateInfoEXT * infos,VkDebugReportCallbackEXT * callbacks)799 static inline VkResult layer_enable_tmp_report_callbacks(debug_report_data *debug_data, uint32_t num_callbacks,
800                                                          VkDebugReportCallbackCreateInfoEXT *infos,
801                                                          VkDebugReportCallbackEXT *callbacks) {
802     VkResult rtn = VK_SUCCESS;
803     for (uint32_t i = 0; i < num_callbacks; i++) {
804         rtn = layer_create_report_callback(debug_data, false, &infos[i], NULL, &callbacks[i]);
805         if (rtn != VK_SUCCESS) {
806             for (uint32_t j = 0; j < i; j++) {
807                 layer_destroy_report_callback(debug_data, callbacks[j], NULL);
808             }
809             return rtn;
810         }
811     }
812     return rtn;
813 }
814 
815 // This utility disables all of the VkDebugReportCallbackCreateInfoEXT structs
816 // that were copied by layer_copy_tmp_report_callbacks()
layer_disable_tmp_report_callbacks(debug_report_data * debug_data,uint32_t num_callbacks,VkDebugReportCallbackEXT * callbacks)817 static inline void layer_disable_tmp_report_callbacks(debug_report_data *debug_data, uint32_t num_callbacks,
818                                                       VkDebugReportCallbackEXT *callbacks) {
819     for (uint32_t i = 0; i < num_callbacks; i++) {
820         layer_destroy_report_callback(debug_data, callbacks[i], NULL);
821     }
822 }
823 
824 // This utility (called at vkCreateInstance() time), looks at a pNext chain.
825 // It counts any VkDebugUtilsMessengerCreateInfoEXT structs that it finds.  It
826 // then allocates an array that can hold that many structs, as well as that
827 // many VkDebugUtilsMessengerEXT handles.  It then copies each
828 // VkDebugUtilsMessengerCreateInfoEXT, and initializes each handle.
layer_copy_tmp_debug_messengers(const void * pChain,uint32_t * num_messengers,VkDebugUtilsMessengerCreateInfoEXT ** infos,VkDebugUtilsMessengerEXT ** messengers)829 static inline VkResult layer_copy_tmp_debug_messengers(const void *pChain, uint32_t *num_messengers,
830                                                        VkDebugUtilsMessengerCreateInfoEXT **infos,
831                                                        VkDebugUtilsMessengerEXT **messengers) {
832     uint32_t n = *num_messengers = 0;
833 
834     const void *pNext = pChain;
835     while (pNext) {
836         // 1st, count the number VkDebugUtilsMessengerCreateInfoEXT:
837         if (((VkDebugUtilsMessengerCreateInfoEXT *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT) {
838             n++;
839         }
840         pNext = (void *)((VkDebugUtilsMessengerCreateInfoEXT *)pNext)->pNext;
841     }
842     if (n == 0) {
843         return VK_SUCCESS;
844     }
845 
846     // 2nd, allocate memory for each VkDebugUtilsMessengerCreateInfoEXT:
847     VkDebugUtilsMessengerCreateInfoEXT *pInfos = *infos =
848         ((VkDebugUtilsMessengerCreateInfoEXT *)malloc(n * sizeof(VkDebugUtilsMessengerCreateInfoEXT)));
849     if (!pInfos) {
850         return VK_ERROR_OUT_OF_HOST_MEMORY;
851     }
852     // 3rd, allocate memory for a unique handle for each messenger:
853     VkDebugUtilsMessengerEXT *pMessengers = *messengers =
854         ((VkDebugUtilsMessengerEXT *)malloc(n * sizeof(VkDebugUtilsMessengerEXT)));
855     if (!pMessengers) {
856         free(pInfos);
857         return VK_ERROR_OUT_OF_HOST_MEMORY;
858     }
859     // 4th, copy each VkDebugUtilsMessengerCreateInfoEXT for use by
860     // vkDestroyInstance, and assign a unique handle to each callback (just
861     // use the address of the copied VkDebugUtilsMessengerCreateInfoEXT):
862     pNext = pChain;
863     while (pNext) {
864         if (((VkInstanceCreateInfo *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT) {
865             memcpy(pInfos, pNext, sizeof(VkDebugUtilsMessengerCreateInfoEXT));
866             *pMessengers++ = (VkDebugUtilsMessengerEXT)pInfos++;
867         }
868         pNext = (void *)((VkInstanceCreateInfo *)pNext)->pNext;
869     }
870 
871     *num_messengers = n;
872     return VK_SUCCESS;
873 }
874 
875 // This utility frees the arrays allocated by layer_copy_tmp_debug_messengers()
layer_free_tmp_debug_messengers(VkDebugUtilsMessengerCreateInfoEXT * infos,VkDebugUtilsMessengerEXT * messengers)876 static inline void layer_free_tmp_debug_messengers(VkDebugUtilsMessengerCreateInfoEXT *infos,
877                                                    VkDebugUtilsMessengerEXT *messengers) {
878     free(infos);
879     free(messengers);
880 }
881 
882 // This utility enables all of the VkDebugUtilsMessengerCreateInfoEXT structs
883 // that were copied by layer_copy_tmp_debug_messengers()
layer_enable_tmp_debug_messengers(debug_report_data * debug_data,uint32_t num_messengers,VkDebugUtilsMessengerCreateInfoEXT * infos,VkDebugUtilsMessengerEXT * messengers)884 static inline VkResult layer_enable_tmp_debug_messengers(debug_report_data *debug_data, uint32_t num_messengers,
885                                                          VkDebugUtilsMessengerCreateInfoEXT *infos,
886                                                          VkDebugUtilsMessengerEXT *messengers) {
887     VkResult rtn = VK_SUCCESS;
888     for (uint32_t i = 0; i < num_messengers; i++) {
889         rtn = layer_create_messenger_callback(debug_data, false, &infos[i], NULL, &messengers[i]);
890         if (rtn != VK_SUCCESS) {
891             for (uint32_t j = 0; j < i; j++) {
892                 layer_destroy_messenger_callback(debug_data, messengers[j], NULL);
893             }
894             return rtn;
895         }
896     }
897     return rtn;
898 }
899 
900 // This utility disables all of the VkDebugUtilsMessengerCreateInfoEXT structs
901 // that were copied by layer_copy_tmp_debug_messengers()
layer_disable_tmp_debug_messengers(debug_report_data * debug_data,uint32_t num_messengers,VkDebugUtilsMessengerEXT * messengers)902 static inline void layer_disable_tmp_debug_messengers(debug_report_data *debug_data, uint32_t num_messengers,
903                                                       VkDebugUtilsMessengerEXT *messengers) {
904     for (uint32_t i = 0; i < num_messengers; i++) {
905         layer_destroy_messenger_callback(debug_data, messengers[i], NULL);
906     }
907 }
908 
909 // Checks if the message will get logged.
910 // Allows layer to defer collecting & formating data if the
911 // message will be discarded.
will_log_msg(debug_report_data * debug_data,VkFlags msg_flags)912 static inline bool will_log_msg(debug_report_data *debug_data, VkFlags msg_flags) {
913     VkFlags local_severity = 0;
914     VkFlags local_type = 0;
915     DebugReportFlagsToAnnotFlags(msg_flags, true, &local_severity, &local_type);
916     if (!debug_data || !(debug_data->active_severities & local_severity) || !(debug_data->active_types & local_type)) {
917         // Message is not wanted
918         return false;
919     }
920 
921     return true;
922 }
923 #ifndef WIN32
924 static inline int string_sprintf(std::string *output, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
925 #endif
string_sprintf(std::string * output,const char * fmt,...)926 static inline int string_sprintf(std::string *output, const char *fmt, ...) {
927     std::string &formatted = *output;
928     va_list argptr;
929     va_start(argptr, fmt);
930     int reserve = vsnprintf(nullptr, 0, fmt, argptr);
931     va_end(argptr);
932     formatted.reserve(reserve + 1);  // Set the storage length long enough to hold the output + null
933     formatted.resize(reserve);       // Set the *logical* length to be what vsprintf will write
934     va_start(argptr, fmt);
935     int result = vsnprintf((char *)formatted.data(), formatted.capacity(), fmt, argptr);
936     va_end(argptr);
937     assert(result == reserve);
938     assert((formatted.size() == strlen(formatted.c_str())));
939     return result;
940 }
941 
942 #ifdef WIN32
vasprintf(char ** strp,char const * fmt,va_list ap)943 static inline int vasprintf(char **strp, char const *fmt, va_list ap) {
944     *strp = nullptr;
945     int size = _vscprintf(fmt, ap);
946     if (size >= 0) {
947         *strp = (char *)malloc(size + 1);
948         if (!*strp) {
949             return -1;
950         }
951         _vsnprintf(*strp, size + 1, fmt, ap);
952     }
953     return size;
954 }
955 #endif
956 
957 // Output log message via DEBUG_REPORT. Takes format and variable arg list so that output string is only computed if a message
958 // needs to be logged
959 #ifndef WIN32
960 static inline bool log_msg(const debug_report_data *debug_data, VkFlags msg_flags, VkDebugReportObjectTypeEXT object_type,
961                            uint64_t src_object, const std::string &vuid_text, const char *format, ...)
962     __attribute__((format(printf, 6, 7)));
963 #endif
log_msg(const debug_report_data * debug_data,VkFlags msg_flags,VkDebugReportObjectTypeEXT object_type,uint64_t src_object,const std::string & vuid_text,const char * format,...)964 static inline bool log_msg(const debug_report_data *debug_data, VkFlags msg_flags, VkDebugReportObjectTypeEXT object_type,
965                            uint64_t src_object, const std::string &vuid_text, const char *format, ...) {
966     if (!debug_data) return false;
967     std::unique_lock<std::mutex> lock(debug_data->debug_report_mutex);
968     VkFlags local_severity = 0;
969     VkFlags local_type = 0;
970     DebugReportFlagsToAnnotFlags(msg_flags, true, &local_severity, &local_type);
971     if (!debug_data || !(debug_data->active_severities & local_severity) || !(debug_data->active_types & local_type)) {
972         // Message is not wanted
973         return false;
974     }
975 
976     va_list argptr;
977     va_start(argptr, format);
978     char *str;
979     if (-1 == vasprintf(&str, format, argptr)) {
980         // On failure, glibc vasprintf leaves str undefined
981         str = nullptr;
982     }
983     va_end(argptr);
984 
985     std::string str_plus_spec_text(str ? str : "Allocation failure");
986 
987     // Append the spec error text to the error message, unless it's an UNASSIGNED or UNDEFINED vuid
988     if ((vuid_text.find("UNASSIGNED-") == std::string::npos) && (vuid_text.find(kVUIDUndefined) == std::string::npos)) {
989         // Linear search makes no assumptions about the layout of the string table
990         // This is not fast, but it does not need to be at this point in the error reporting path
991         uint32_t num_vuids = sizeof(vuid_spec_text) / sizeof(vuid_spec_text_pair);
992         const char *spec_text = nullptr;
993         for (uint32_t i = 0; i < num_vuids; i++) {
994             if (0 == strcmp(vuid_text.c_str(), vuid_spec_text[i].vuid)) {
995                 spec_text = vuid_spec_text[i].spec_text;
996                 break;
997             }
998         }
999 
1000         if (nullptr == spec_text) {
1001             // If this happens, you've hit a VUID string that isn't defined in the spec's json file
1002             // Try running 'vk_validation_stats -c' to look for invalid VUID strings in the repo code
1003             assert(0);
1004         } else {
1005             str_plus_spec_text += " The Vulkan spec states: ";
1006             str_plus_spec_text += spec_text;
1007         }
1008     }
1009 
1010     // Append layer prefix with VUID string, pass in recovered legacy numerical VUID
1011     bool result = debug_log_msg(debug_data, msg_flags, object_type, src_object, 0, "Validation", str_plus_spec_text.c_str(),
1012                                 vuid_text.c_str());
1013 
1014     free(str);
1015     return result;
1016 }
1017 
report_log_callback(VkFlags msg_flags,VkDebugReportObjectTypeEXT obj_type,uint64_t src_object,size_t location,int32_t msg_code,const char * layer_prefix,const char * message,void * user_data)1018 static inline VKAPI_ATTR VkBool32 VKAPI_CALL report_log_callback(VkFlags msg_flags, VkDebugReportObjectTypeEXT obj_type,
1019                                                                  uint64_t src_object, size_t location, int32_t msg_code,
1020                                                                  const char *layer_prefix, const char *message, void *user_data) {
1021     std::ostringstream msg_buffer;
1022     char msg_flag_string[30];
1023 
1024     PrintMessageFlags(msg_flags, msg_flag_string);
1025 
1026     msg_buffer << layer_prefix << "(" << msg_flag_string << "): msg_code: " << msg_code << ": " << message << "\n";
1027     const std::string tmp = msg_buffer.str();
1028     const char *cstr = tmp.c_str();
1029 
1030     fprintf((FILE *)user_data, "%s", cstr);
1031     fflush((FILE *)user_data);
1032 
1033 #if defined __ANDROID__
1034     LOGCONSOLE("%s", cstr);
1035 #endif
1036 
1037     return false;
1038 }
1039 
report_win32_debug_output_msg(VkFlags msg_flags,VkDebugReportObjectTypeEXT obj_type,uint64_t src_object,size_t location,int32_t msg_code,const char * layer_prefix,const char * message,void * user_data)1040 static inline VKAPI_ATTR VkBool32 VKAPI_CALL report_win32_debug_output_msg(VkFlags msg_flags, VkDebugReportObjectTypeEXT obj_type,
1041                                                                            uint64_t src_object, size_t location, int32_t msg_code,
1042                                                                            const char *layer_prefix, const char *message,
1043                                                                            void *user_data) {
1044 #ifdef WIN32
1045     char msg_flag_string[30];
1046     char buf[2048];
1047 
1048     PrintMessageFlags(msg_flags, msg_flag_string);
1049     _snprintf(buf, sizeof(buf) - 1, "%s (%s): msg_code: %d: %s\n", layer_prefix, msg_flag_string, msg_code, message);
1050 
1051     OutputDebugString(buf);
1052 #endif
1053 
1054     return false;
1055 }
1056 
DebugBreakCallback(VkFlags msgFlags,VkDebugReportObjectTypeEXT obj_type,uint64_t src_object,size_t location,int32_t msg_code,const char * layer_prefix,const char * message,void * user_data)1057 static inline VKAPI_ATTR VkBool32 VKAPI_CALL DebugBreakCallback(VkFlags msgFlags, VkDebugReportObjectTypeEXT obj_type,
1058                                                                 uint64_t src_object, size_t location, int32_t msg_code,
1059                                                                 const char *layer_prefix, const char *message, void *user_data) {
1060 #ifdef WIN32
1061     DebugBreak();
1062 #else
1063     raise(SIGTRAP);
1064 #endif
1065 
1066     return false;
1067 }
1068 
MessengerBreakCallback(VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,VkDebugUtilsMessageTypeFlagsEXT message_type,const VkDebugUtilsMessengerCallbackDataEXT * callback_data,void * user_data)1069 static inline VKAPI_ATTR VkBool32 VKAPI_CALL MessengerBreakCallback(VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
1070                                                                     VkDebugUtilsMessageTypeFlagsEXT message_type,
1071                                                                     const VkDebugUtilsMessengerCallbackDataEXT *callback_data,
1072                                                                     void *user_data) {
1073 #ifdef WIN32
1074     DebugBreak();
1075 #else
1076     raise(SIGTRAP);
1077 #endif
1078 
1079     return false;
1080 }
1081 
messenger_log_callback(VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,VkDebugUtilsMessageTypeFlagsEXT message_type,const VkDebugUtilsMessengerCallbackDataEXT * callback_data,void * user_data)1082 static inline VKAPI_ATTR VkBool32 VKAPI_CALL messenger_log_callback(VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
1083                                                                     VkDebugUtilsMessageTypeFlagsEXT message_type,
1084                                                                     const VkDebugUtilsMessengerCallbackDataEXT *callback_data,
1085                                                                     void *user_data) {
1086     std::ostringstream msg_buffer;
1087     char msg_severity[30];
1088     char msg_type[30];
1089 
1090     PrintMessageSeverity(message_severity, msg_severity);
1091     PrintMessageType(message_type, msg_type);
1092 
1093     msg_buffer << callback_data->pMessageIdName << "(" << msg_severity << " / " << msg_type
1094                << "): msgNum: " << callback_data->messageIdNumber << " - " << callback_data->pMessage << "\n";
1095     msg_buffer << "    Objects: " << callback_data->objectCount << "\n";
1096     for (uint32_t obj = 0; obj < callback_data->objectCount; ++obj) {
1097         msg_buffer << "        [" << obj << "] " << std::hex << std::showbase
1098                    << HandleToUint64(callback_data->pObjects[obj].objectHandle) << ", type: " << std::dec << std::noshowbase
1099                    << callback_data->pObjects[obj].objectType
1100                    << ", name: " << (callback_data->pObjects[obj].pObjectName ? callback_data->pObjects[obj].pObjectName : "NULL")
1101                    << "\n";
1102     }
1103     const std::string tmp = msg_buffer.str();
1104     const char *cstr = tmp.c_str();
1105     fprintf((FILE *)user_data, "%s", cstr);
1106     fflush((FILE *)user_data);
1107 
1108 #if defined __ANDROID__
1109     LOGCONSOLE("%s", cstr);
1110 #endif
1111 
1112     return false;
1113 }
1114 
messenger_win32_debug_output_msg(VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,VkDebugUtilsMessageTypeFlagsEXT message_type,const VkDebugUtilsMessengerCallbackDataEXT * callback_data,void * user_data)1115 static inline VKAPI_ATTR VkBool32 VKAPI_CALL messenger_win32_debug_output_msg(
1116     VkDebugUtilsMessageSeverityFlagBitsEXT message_severity, VkDebugUtilsMessageTypeFlagsEXT message_type,
1117     const VkDebugUtilsMessengerCallbackDataEXT *callback_data, void *user_data) {
1118 #ifdef WIN32
1119     std::ostringstream msg_buffer;
1120     char msg_severity[30];
1121     char msg_type[30];
1122 
1123     PrintMessageSeverity(message_severity, msg_severity);
1124     PrintMessageType(message_type, msg_type);
1125 
1126     msg_buffer << callback_data->pMessageIdName << "(" << msg_severity << " / " << msg_type
1127                << "): msgNum: " << callback_data->messageIdNumber << " - " << callback_data->pMessage << "\n";
1128     msg_buffer << "    Objects: " << callback_data->objectCount << "\n";
1129 
1130     for (uint32_t obj = 0; obj < callback_data->objectCount; ++obj) {
1131         msg_buffer << "       [" << obj << "]  " << std::hex << std::showbase
1132                    << HandleToUint64(callback_data->pObjects[obj].objectHandle) << ", type: " << std::dec << std::noshowbase
1133                    << callback_data->pObjects[obj].objectType
1134                    << ", name: " << (callback_data->pObjects[obj].pObjectName ? callback_data->pObjects[obj].pObjectName : "NULL")
1135                    << "\n";
1136     }
1137     const std::string tmp = msg_buffer.str();
1138     const char *cstr = tmp.c_str();
1139     OutputDebugString(cstr);
1140 #endif
1141 
1142     return false;
1143 }
1144 
1145 template <typename Map>
GetLoggingLabelState(Map * map,typename Map::key_type key,bool insert)1146 static LoggingLabelState *GetLoggingLabelState(Map *map, typename Map::key_type key, bool insert) {
1147     auto iter = map->find(key);
1148     LoggingLabelState *label_state = nullptr;
1149     if (iter == map->end()) {
1150         if (insert) {
1151             // Add a label state if not present
1152             label_state = new LoggingLabelState();
1153             auto inserted = map->insert(std::make_pair(key, std::unique_ptr<LoggingLabelState>(new LoggingLabelState())));
1154             assert(inserted.second);
1155             iter = inserted.first;
1156             label_state = iter->second.get();
1157         }
1158     } else {
1159         label_state = iter->second.get();
1160     }
1161     return label_state;
1162 }
1163 
BeginQueueDebugUtilsLabel(debug_report_data * report_data,VkQueue queue,const VkDebugUtilsLabelEXT * label_info)1164 static inline void BeginQueueDebugUtilsLabel(debug_report_data *report_data, VkQueue queue,
1165                                              const VkDebugUtilsLabelEXT *label_info) {
1166     std::unique_lock<std::mutex> lock(report_data->debug_report_mutex);
1167     if (nullptr != label_info && nullptr != label_info->pLabelName) {
1168         auto *label_state = GetLoggingLabelState(&report_data->debugUtilsQueueLabels, queue, /* insert */ true);
1169         assert(label_state);
1170         label_state->labels.push_back(LoggingLabel(label_info));
1171 
1172         // TODO: Determine if this is the correct semantics for insert label vs. begin/end, perserving existing semantics for now
1173         label_state->insert_label.Reset();
1174     }
1175 }
1176 
EndQueueDebugUtilsLabel(debug_report_data * report_data,VkQueue queue)1177 static inline void EndQueueDebugUtilsLabel(debug_report_data *report_data, VkQueue queue) {
1178     std::unique_lock<std::mutex> lock(report_data->debug_report_mutex);
1179     auto *label_state = GetLoggingLabelState(&report_data->debugUtilsQueueLabels, queue, /* insert */ false);
1180     if (label_state) {
1181         // Pop the normal item
1182         if (!label_state->labels.empty()) {
1183             label_state->labels.pop_back();
1184         }
1185 
1186         // TODO: Determine if this is the correct semantics for insert label vs. begin/end, perserving existing semantics for now
1187         label_state->insert_label.Reset();
1188     }
1189 }
1190 
InsertQueueDebugUtilsLabel(debug_report_data * report_data,VkQueue queue,const VkDebugUtilsLabelEXT * label_info)1191 static inline void InsertQueueDebugUtilsLabel(debug_report_data *report_data, VkQueue queue,
1192                                               const VkDebugUtilsLabelEXT *label_info) {
1193     std::unique_lock<std::mutex> lock(report_data->debug_report_mutex);
1194     auto *label_state = GetLoggingLabelState(&report_data->debugUtilsQueueLabels, queue, /* insert */ true);
1195 
1196     // TODO: Determine if this is the correct semantics for insert label vs. begin/end, perserving existing semantics for now
1197     label_state->insert_label = LoggingLabel(label_info);
1198 }
1199 
BeginCmdDebugUtilsLabel(debug_report_data * report_data,VkCommandBuffer command_buffer,const VkDebugUtilsLabelEXT * label_info)1200 static inline void BeginCmdDebugUtilsLabel(debug_report_data *report_data, VkCommandBuffer command_buffer,
1201                                            const VkDebugUtilsLabelEXT *label_info) {
1202     std::unique_lock<std::mutex> lock(report_data->debug_report_mutex);
1203     if (nullptr != label_info && nullptr != label_info->pLabelName) {
1204         auto *label_state = GetLoggingLabelState(&report_data->debugUtilsCmdBufLabels, command_buffer, /* insert */ true);
1205         assert(label_state);
1206         label_state->labels.push_back(LoggingLabel(label_info));
1207 
1208         // TODO: Determine if this is the correct semantics for insert label vs. begin/end, perserving existing semantics for now
1209         label_state->insert_label.Reset();
1210     }
1211 }
1212 
EndCmdDebugUtilsLabel(debug_report_data * report_data,VkCommandBuffer command_buffer)1213 static inline void EndCmdDebugUtilsLabel(debug_report_data *report_data, VkCommandBuffer command_buffer) {
1214     std::unique_lock<std::mutex> lock(report_data->debug_report_mutex);
1215     auto *label_state = GetLoggingLabelState(&report_data->debugUtilsCmdBufLabels, command_buffer, /* insert */ false);
1216     if (label_state) {
1217         // Pop the normal item
1218         if (!label_state->labels.empty()) {
1219             label_state->labels.pop_back();
1220         }
1221 
1222         // TODO: Determine if this is the correct semantics for insert label vs. begin/end, perserving existing semantics for now
1223         label_state->insert_label.Reset();
1224     }
1225 }
1226 
InsertCmdDebugUtilsLabel(debug_report_data * report_data,VkCommandBuffer command_buffer,const VkDebugUtilsLabelEXT * label_info)1227 static inline void InsertCmdDebugUtilsLabel(debug_report_data *report_data, VkCommandBuffer command_buffer,
1228                                             const VkDebugUtilsLabelEXT *label_info) {
1229     std::unique_lock<std::mutex> lock(report_data->debug_report_mutex);
1230     auto *label_state = GetLoggingLabelState(&report_data->debugUtilsCmdBufLabels, command_buffer, /* insert */ true);
1231     assert(label_state);
1232 
1233     // TODO: Determine if this is the correct semantics for insert label vs. begin/end, perserving existing semantics for now
1234     label_state->insert_label = LoggingLabel(label_info);
1235 }
1236 
1237 // Current tracking beyond a single command buffer scope is incorrect, and even when it is we need to be able to clean up
ResetCmdDebugUtilsLabel(debug_report_data * report_data,VkCommandBuffer command_buffer)1238 static inline void ResetCmdDebugUtilsLabel(debug_report_data *report_data, VkCommandBuffer command_buffer) {
1239     std::unique_lock<std::mutex> lock(report_data->debug_report_mutex);
1240     auto *label_state = GetLoggingLabelState(&report_data->debugUtilsCmdBufLabels, command_buffer, /* insert */ false);
1241     if (label_state) {
1242         label_state->labels.clear();
1243         label_state->insert_label.Reset();
1244     }
1245 }
1246 
EraseCmdDebugUtilsLabel(debug_report_data * report_data,VkCommandBuffer command_buffer)1247 static inline void EraseCmdDebugUtilsLabel(debug_report_data *report_data, VkCommandBuffer command_buffer) {
1248     report_data->debugUtilsCmdBufLabels.erase(command_buffer);
1249 }
1250 
1251 #endif  // LAYER_LOGGING_H
1252