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