blob: 0ed651b55407ad657e283163c0ba9fb4ae9eab37 [file] [log] [blame]
Mark Lobodzinskifeb61fe2019-01-10 08:56:57 -07001/* Copyright (c) 2015-2019 The Khronos Group Inc.
2 * Copyright (c) 2015-2019 Valve Corporation
3 * Copyright (c) 2015-2019 LunarG, Inc.
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -06004 *
Jon Ashburn3ebf1252016-04-19 11:30:31 -06005 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -06008 *
Jon Ashburn3ebf1252016-04-19 11:30:31 -06009 * http://www.apache.org/licenses/LICENSE-2.0
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060010 *
Jon Ashburn3ebf1252016-04-19 11:30:31 -060011 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060016 *
Courtney Goeltzenleuchter05559522015-10-30 11:14:30 -060017 * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
18 * Author: Tobin Ehlis <tobin@lunarg.com>
Mark Young6ba8abe2017-11-09 10:37:04 -070019 * Author: Mark Young <marky@lunarg.com>
Dave Houlton4d9b2f82018-10-24 18:21:06 -060020 * Author: Dave Houlton <daveh@lunarg.com>
Courtney Goeltzenleuchter05559522015-10-30 11:14:30 -060021 *
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -060022 */
23
24#ifndef LAYER_LOGGING_H
25#define LAYER_LOGGING_H
26
John Zulaufc64f97c2019-04-10 10:34:52 -060027#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
42#include "vk_typemap_helper.h"
Mark Lobodzinskib87f9022016-05-24 16:04:56 -060043#include "vk_loader_layer.h"
Tobin Ehlis2d9deec2016-04-21 14:19:26 -060044#include "vk_layer_config.h"
Tobin Ehlisa0cb02e2015-07-03 10:15:26 -060045#include "vk_layer_data.h"
Tobin Ehlis2d9deec2016-04-21 14:19:26 -060046#include "vk_loader_platform.h"
47#include "vulkan/vk_layer.h"
Mark Young6ba8abe2017-11-09 10:37:04 -070048#include "vk_object_types.h"
Mark Lobodzinski487a0d12018-03-30 10:09:03 -060049#include "vk_validation_error_messages.h"
Lenny Komow4c0da772018-07-03 10:17:21 -060050#include "vk_layer_dispatch_table.h"
Mark Young6ba8abe2017-11-09 10:37:04 -070051
Dave Houlton57ae22f2018-05-18 16:20:52 -060052// Suppress unused warning on Linux
53#if defined(__GNUC__)
Dave Houltoncfcecbf2018-05-31 16:20:57 -060054#define DECORATE_UNUSED __attribute__((unused))
55#else
56#define DECORATE_UNUSED
Dave Houlton57ae22f2018-05-18 16:20:52 -060057#endif
58
Mark Lobodzinski706e15a2018-12-12 15:35:29 -070059#if defined __ANDROID__
60#include <android/log.h>
61#define LOGCONSOLE(...) ((void)__android_log_print(ANDROID_LOG_INFO, "VALIDATION", __VA_ARGS__))
62#else
63#define LOGCONSOLE(...) \
64 { \
65 printf(__VA_ARGS__); \
66 printf("\n"); \
67 }
68#endif
69
Dave Houltoncfcecbf2018-05-31 16:20:57 -060070static const char DECORATE_UNUSED *kVUIDUndefined = "VUID_Undefined";
Dave Houlton8e9f6542018-05-18 12:18:22 -060071
Dave Houltoncfcecbf2018-05-31 16:20:57 -060072#undef DECORATE_UNUSED
Dave Houlton57ae22f2018-05-18 16:20:52 -060073
Mark Young6ba8abe2017-11-09 10:37:04 -070074// TODO: Could be autogenerated for the specific handles for extra type safety...
75template <typename HANDLE_T>
76static inline uint64_t HandleToUint64(HANDLE_T *h) {
77 return reinterpret_cast<uint64_t>(h);
78}
79
80static inline uint64_t HandleToUint64(uint64_t h) { return h; }
81
82// Data we store per label for logging
John Zulaufc64f97c2019-04-10 10:34:52 -060083struct LoggingLabel {
Mark Young6ba8abe2017-11-09 10:37:04 -070084 std::string name;
John Zulaufc64f97c2019-04-10 10:34:52 -060085 std::array<float, 4> color;
86
87 void Reset() { *this = LoggingLabel(); }
88 bool Empty() const { return name.empty(); }
89
90 VkDebugUtilsLabelEXT Export() const {
91 auto out = lvl_init_struct<VkDebugUtilsLabelEXT>();
92 out.pLabelName = name.c_str();
93 std::copy(color.cbegin(), color.cend(), out.color);
94 return out;
95 };
96
97 LoggingLabel() : name(), color({0.f, 0.f, 0.f, 0.f}) {}
98 LoggingLabel(const LoggingLabel &other) : name(other.name), color(other.color) {}
99 LoggingLabel(const VkDebugUtilsLabelEXT *label_info) {
100 if (label_info && label_info->pLabelName) {
101 name = label_info->pLabelName;
102 std::copy_n(std::begin(label_info->color), 4, color.begin());
103 } else {
104 Reset();
105 }
106 }
107};
108
109struct LoggingLabelState {
110 std::vector<LoggingLabel> labels;
111 LoggingLabel insert_label;
112
113 // Export the labels, but in reverse order since we want the most recent at the top.
114 std::vector<VkDebugUtilsLabelEXT> Export() const {
115 size_t count = labels.size() + (insert_label.Empty() ? 0 : 1);
116 std::vector<VkDebugUtilsLabelEXT> out(count);
117
118 if (!count) return out;
119
120 size_t index = count - 1;
121 if (!insert_label.Empty()) {
122 out[index--] = insert_label.Export();
123 }
124 for (const auto &label : labels) {
125 out[index--] = label.Export();
126 }
127 return out;
128 }
129};
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600130
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600131typedef struct _debug_report_data {
Mark Lobodzinski12813302019-02-07 15:03:06 -0700132 VkLayerDbgFunctionNode *debug_callback_list{nullptr};
133 VkLayerDbgFunctionNode *default_debug_callback_list{nullptr};
134 VkDebugUtilsMessageSeverityFlagsEXT active_severities{0};
135 VkDebugUtilsMessageTypeFlagsEXT active_types{0};
136 bool g_DEBUG_REPORT{false};
137 bool g_DEBUG_UTILS{false};
138 bool queueLabelHasInsert{false};
139 bool cmdBufLabelHasInsert{false};
140 std::unordered_map<uint64_t, std::string> debugObjectNameMap;
141 std::unordered_map<uint64_t, std::string> debugUtilsObjectNameMap;
John Zulaufc64f97c2019-04-10 10:34:52 -0600142 std::unordered_map<VkQueue, std::unique_ptr<LoggingLabelState>> debugUtilsQueueLabels;
143 std::unordered_map<VkCommandBuffer, std::unique_ptr<LoggingLabelState>> debugUtilsCmdBufLabels;
Mark Lobodzinski25ac7b02019-02-07 13:22:56 -0700144 // This mutex is defined as mutable since the normal usage for a debug report object is as 'const'. The mutable keyword allows
145 // the layers to continue this pattern, but also allows them to use/change this specific member for synchronization purposes.
146 mutable std::mutex debug_report_mutex;
Mark Lobodzinskiaaeed7c2019-02-07 10:19:40 -0700147
148 void DebugReportSetUtilsObjectName(const VkDebugUtilsObjectNameInfoEXT *pNameInfo) {
Mark Lobodzinski25ac7b02019-02-07 13:22:56 -0700149 std::unique_lock<std::mutex> lock(debug_report_mutex);
Mark Lobodzinskiaaeed7c2019-02-07 10:19:40 -0700150 if (pNameInfo->pObjectName) {
Mark Lobodzinski20075722019-02-25 09:34:49 -0700151 debugUtilsObjectNameMap[pNameInfo->objectHandle] = pNameInfo->pObjectName;
Mark Lobodzinskiaaeed7c2019-02-07 10:19:40 -0700152 } else {
Mark Lobodzinski12813302019-02-07 15:03:06 -0700153 debugUtilsObjectNameMap.erase(pNameInfo->objectHandle);
Mark Lobodzinskiaaeed7c2019-02-07 10:19:40 -0700154 }
155 }
156
157 void DebugReportSetMarkerObjectName(const VkDebugMarkerObjectNameInfoEXT *pNameInfo) {
Mark Lobodzinski25ac7b02019-02-07 13:22:56 -0700158 std::unique_lock<std::mutex> lock(debug_report_mutex);
Mark Lobodzinskiaaeed7c2019-02-07 10:19:40 -0700159 if (pNameInfo->pObjectName) {
Mark Lobodzinski20075722019-02-25 09:34:49 -0700160 debugObjectNameMap[pNameInfo->object] = pNameInfo->pObjectName;
Mark Lobodzinskiaaeed7c2019-02-07 10:19:40 -0700161 } else {
Mark Lobodzinski12813302019-02-07 15:03:06 -0700162 debugObjectNameMap.erase(pNameInfo->object);
Mark Lobodzinskiaaeed7c2019-02-07 10:19:40 -0700163 }
164 }
165
166 std::string DebugReportGetUtilsObjectName(const uint64_t object) const {
167 std::string label = "";
Mark Lobodzinski61a6d622019-02-14 14:11:24 -0700168 const auto utils_name_iter = debugUtilsObjectNameMap.find(object);
Mark Lobodzinski12813302019-02-07 15:03:06 -0700169 if (utils_name_iter != debugUtilsObjectNameMap.end()) {
Mark Lobodzinskiaaeed7c2019-02-07 10:19:40 -0700170 label = utils_name_iter->second;
171 }
172 return label;
173 }
174
175 std::string DebugReportGetMarkerObjectName(const uint64_t object) const {
176 std::string label = "";
Mark Lobodzinski61a6d622019-02-14 14:11:24 -0700177 const auto marker_name_iter = debugObjectNameMap.find(object);
Mark Lobodzinski12813302019-02-07 15:03:06 -0700178 if (marker_name_iter != debugObjectNameMap.end()) {
Mark Lobodzinskiaaeed7c2019-02-07 10:19:40 -0700179 label = marker_name_iter->second;
180 }
181 return label;
182 }
183
Locke26335512019-02-18 13:49:02 -0700184 template <typename HANDLE_T>
185 std::string FormatHandle(HANDLE_T *h) const {
186 return FormatHandle(HandleToUint64(h));
187 }
188
189 std::string FormatHandle(uint64_t h) const {
Locked4722ab2019-02-25 12:25:35 -0700190 char uint64_string[64];
191 sprintf(uint64_string, "0x%" PRIxLEAST64, h);
192 std::string ret = uint64_string;
Locke26335512019-02-18 13:49:02 -0700193
194 std::string name = DebugReportGetUtilsObjectName(h);
195 if (name.empty()) {
196 name = DebugReportGetMarkerObjectName(h);
197 }
198 if (!name.empty()) {
199 ret.append("[");
200 ret.append(name);
201 ret.append("]");
202 }
203 return ret;
204 }
205
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600206} debug_report_data;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600207
Tobin Ehlis8d6acde2017-02-08 07:40:40 -0700208template debug_report_data *GetLayerDataPtr<debug_report_data>(void *data_key,
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700209 std::unordered_map<void *, debug_report_data *> &data_map);
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600210
Mark Young6ba8abe2017-11-09 10:37:04 -0700211static inline void DebugReportFlagsToAnnotFlags(VkDebugReportFlagsEXT dr_flags, bool default_flag_is_spec,
212 VkDebugUtilsMessageSeverityFlagsEXT *da_severity,
213 VkDebugUtilsMessageTypeFlagsEXT *da_type) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700214 *da_severity = 0;
Mark Youngfbaae712018-10-04 14:33:50 -0600215 *da_type = 0;
Mark Youngc2347792018-05-30 08:41:25 -0600216 // If it's explicitly listed as a performance warning, treat it as a performance message.
217 // Otherwise, treat it as a validation issue.
218 if ((dr_flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) != 0) {
Mark Youngfbaae712018-10-04 14:33:50 -0600219 *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
220 *da_severity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
Mark Youngc2347792018-05-30 08:41:25 -0600221 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700222 if ((dr_flags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) != 0) {
Mark Youngfbaae712018-10-04 14:33:50 -0600223 *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;
Mark Young6ba8abe2017-11-09 10:37:04 -0700224 *da_severity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT;
Mark Young6ba8abe2017-11-09 10:37:04 -0700225 }
226 if ((dr_flags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) != 0) {
Mark Youngfbaae712018-10-04 14:33:50 -0600227 *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;
Mark Young6ba8abe2017-11-09 10:37:04 -0700228 *da_severity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
Mark Young6ba8abe2017-11-09 10:37:04 -0700229 }
Mark Youngfbaae712018-10-04 14:33:50 -0600230 if ((dr_flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) != 0) {
231 *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;
Mark Young6ba8abe2017-11-09 10:37:04 -0700232 *da_severity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
233 }
234 if ((dr_flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) != 0) {
Mark Youngfbaae712018-10-04 14:33:50 -0600235 *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;
Mark Young6ba8abe2017-11-09 10:37:04 -0700236 *da_severity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
237 }
238}
239
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600240// Forward Declarations
Mark Young6ba8abe2017-11-09 10:37:04 -0700241static inline bool debug_log_msg(const debug_report_data *debug_data, VkFlags msg_flags, VkDebugReportObjectTypeEXT object_type,
Dave Houlton407df732018-08-06 17:58:24 -0600242 uint64_t src_object, size_t location, const char *layer_prefix, const char *message,
243 const char *text_vuid);
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600244
245// Add a debug message callback node structure to the specified callback linked list
Mark Young6ba8abe2017-11-09 10:37:04 -0700246static inline void AddDebugCallbackNode(debug_report_data *debug_data, VkLayerDbgFunctionNode **list_head,
247 VkLayerDbgFunctionNode *new_node) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600248 new_node->pNext = *list_head;
249 *list_head = new_node;
250}
251
Mark Young6ba8abe2017-11-09 10:37:04 -0700252// Remove specified debug messenger node structure from the specified linked list
253static inline void RemoveDebugUtilsMessenger(debug_report_data *debug_data, VkLayerDbgFunctionNode **list_head,
254 VkDebugUtilsMessengerEXT messenger) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600255 VkLayerDbgFunctionNode *cur_callback = *list_head;
Mark Youngfbaae712018-10-04 14:33:50 -0600256 VkLayerDbgFunctionNode *prev_callback = nullptr;
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600257 bool matched = false;
Mark Young6ba8abe2017-11-09 10:37:04 -0700258 VkFlags local_severities = 0;
259 VkFlags local_types = 0;
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600260
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600261 while (cur_callback) {
Mark Youngfbaae712018-10-04 14:33:50 -0600262 if (cur_callback->is_messenger) {
263 // If it's actually a messenger, then set it up for deletion.
264 if (cur_callback->messenger.messenger == messenger) {
265 matched = true;
266 if (*list_head == cur_callback) {
267 *list_head = cur_callback->pNext;
268 } else {
269 assert(nullptr != prev_callback);
270 prev_callback->pNext = cur_callback->pNext;
271 }
272 debug_log_msg(debug_data, VK_DEBUG_REPORT_DEBUG_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT,
273 reinterpret_cast<uint64_t &>(cur_callback->messenger.messenger), 0, "DebugUtilsMessenger",
274 "Destroyed messenger\n", kVUIDUndefined);
275 } else {
276 // If it's not the one we're looking for, just keep the types/severities
277 local_severities |= cur_callback->messenger.messageSeverity;
278 local_types |= cur_callback->messenger.messageType;
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600279 }
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600280 } else {
Mark Youngfbaae712018-10-04 14:33:50 -0600281 // If it's not a messenger, 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;
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600287 }
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600288 if (matched) {
Mark Youngfbaae712018-10-04 14:33:50 -0600289 free(cur_callback);
290 matched = false;
291 // Intentionally keep the last prev_callback, but select the proper cur_callback
292 if (nullptr != prev_callback) {
293 cur_callback = prev_callback->pNext;
294 } else {
295 cur_callback = *list_head;
296 }
297 } else {
298 prev_callback = cur_callback;
299 cur_callback = cur_callback->pNext;
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600300 }
301 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700302 debug_data->active_severities = local_severities;
303 debug_data->active_types = local_types;
304}
305
306// Remove specified debug message callback node structure from the specified callback linked list
307static inline void RemoveDebugUtilsMessageCallback(debug_report_data *debug_data, VkLayerDbgFunctionNode **list_head,
308 VkDebugReportCallbackEXT callback) {
309 VkLayerDbgFunctionNode *cur_callback = *list_head;
Mark Youngfbaae712018-10-04 14:33:50 -0600310 VkLayerDbgFunctionNode *prev_callback = nullptr;
Mark Young6ba8abe2017-11-09 10:37:04 -0700311 bool matched = false;
312 VkFlags local_severities = 0;
313 VkFlags local_types = 0;
314
315 while (cur_callback) {
Mark Youngfbaae712018-10-04 14:33:50 -0600316 if (!cur_callback->is_messenger) {
317 // If it's actually a callback, then set it up for deletion.
318 if (cur_callback->report.msgCallback == callback) {
319 matched = true;
320 if (*list_head == cur_callback) {
321 *list_head = cur_callback->pNext;
322 } else {
323 assert(nullptr != prev_callback);
324 prev_callback->pNext = cur_callback->pNext;
325 }
326 debug_log_msg(debug_data, VK_DEBUG_REPORT_DEBUG_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT,
327 reinterpret_cast<uint64_t &>(cur_callback->report.msgCallback), 0, "DebugReport",
328 "Destroyed callback\n", kVUIDUndefined);
329 } else {
330 // If it's not the one we're looking for, just keep the types/severities
331 VkFlags this_severities = 0;
332 VkFlags this_types = 0;
333 DebugReportFlagsToAnnotFlags(cur_callback->report.msgFlags, true, &this_severities, &this_types);
334 local_severities |= this_severities;
335 local_types |= this_types;
Mark Young6ba8abe2017-11-09 10:37:04 -0700336 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700337 } else {
Mark Youngfbaae712018-10-04 14:33:50 -0600338 // If it's not a callback, just keep the types/severities
339 local_severities |= cur_callback->messenger.messageSeverity;
340 local_types |= cur_callback->messenger.messageType;
Mark Young6ba8abe2017-11-09 10:37:04 -0700341 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700342 if (matched) {
Mark Youngfbaae712018-10-04 14:33:50 -0600343 free(cur_callback);
344 matched = false;
345 // Intentionally keep the last prev_callback, but select the proper cur_callback
346 if (nullptr != prev_callback) {
347 cur_callback = prev_callback->pNext;
348 } else {
349 cur_callback = *list_head;
350 }
351 } else {
352 prev_callback = cur_callback;
353 cur_callback = cur_callback->pNext;
Mark Young6ba8abe2017-11-09 10:37:04 -0700354 }
355 }
356 debug_data->active_severities = local_severities;
357 debug_data->active_types = local_types;
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600358}
359
360// Removes all debug callback function nodes from the specified callback linked lists and frees their resources
361static inline void RemoveAllMessageCallbacks(debug_report_data *debug_data, VkLayerDbgFunctionNode **list_head) {
362 VkLayerDbgFunctionNode *current_callback = *list_head;
363 VkLayerDbgFunctionNode *prev_callback = current_callback;
364
365 while (current_callback) {
366 prev_callback = current_callback->pNext;
Mark Young6ba8abe2017-11-09 10:37:04 -0700367 if (!current_callback->is_messenger) {
368 debug_log_msg(debug_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT,
Dave Houlton407df732018-08-06 17:58:24 -0600369 (uint64_t)current_callback->report.msgCallback, 0, "DebugReport",
370 "Debug Report callbacks not removed before DestroyInstance", kVUIDUndefined);
Mark Young6ba8abe2017-11-09 10:37:04 -0700371 } else {
372 debug_log_msg(debug_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT,
Dave Houlton407df732018-08-06 17:58:24 -0600373 (uint64_t)current_callback->messenger.messenger, 0, "Messenger",
374 "Debug messengers not removed before DestroyInstance", kVUIDUndefined);
Mark Young6ba8abe2017-11-09 10:37:04 -0700375 }
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600376 free(current_callback);
377 current_callback = prev_callback;
378 }
379 *list_head = NULL;
380}
381
Mark Young6ba8abe2017-11-09 10:37:04 -0700382static inline bool debug_log_msg(const debug_report_data *debug_data, VkFlags msg_flags, VkDebugReportObjectTypeEXT object_type,
Dave Houlton407df732018-08-06 17:58:24 -0600383 uint64_t src_object, size_t location, const char *layer_prefix, const char *message,
384 const char *text_vuid) {
Dustin Graves8f1eab92016-04-05 09:41:17 -0600385 bool bail = false;
Mark Young6ba8abe2017-11-09 10:37:04 -0700386 VkLayerDbgFunctionNode *layer_dbg_node = NULL;
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600387
Mark Lobodzinski55a197f2016-06-21 15:54:57 -0600388 if (debug_data->debug_callback_list != NULL) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700389 layer_dbg_node = debug_data->debug_callback_list;
Mark Lobodzinski55a197f2016-06-21 15:54:57 -0600390 } else {
Mark Young6ba8abe2017-11-09 10:37:04 -0700391 layer_dbg_node = debug_data->default_debug_callback_list;
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600392 }
393
Mark Young6ba8abe2017-11-09 10:37:04 -0700394 VkDebugUtilsMessageSeverityFlagsEXT severity;
395 VkDebugUtilsMessageTypeFlagsEXT types;
396 VkDebugUtilsMessengerCallbackDataEXT callback_data;
397 VkDebugUtilsObjectNameInfoEXT object_name_info;
398
399 // Convert the info to the VK_EXT_debug_utils form in case we need it.
400 DebugReportFlagsToAnnotFlags(msg_flags, true, &severity, &types);
401 object_name_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
402 object_name_info.pNext = NULL;
403 object_name_info.objectType = convertDebugReportObjectToCoreObject(object_type);
404 object_name_info.objectHandle = (uint64_t)(uintptr_t)src_object;
405 object_name_info.pObjectName = NULL;
Mark Lobodzinski5d98ba12019-03-25 13:35:01 -0600406 std::string object_label = {};
Mark Young6ba8abe2017-11-09 10:37:04 -0700407
408 callback_data.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT;
409 callback_data.pNext = NULL;
410 callback_data.flags = 0;
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700411 callback_data.pMessageIdName = text_vuid;
Dave Houlton407df732018-08-06 17:58:24 -0600412 callback_data.messageIdNumber = 0; // deprecated, validation layers use only the pMessageIdName
Mark Young6ba8abe2017-11-09 10:37:04 -0700413 callback_data.pMessage = message;
414 callback_data.queueLabelCount = 0;
415 callback_data.pQueueLabels = NULL;
416 callback_data.cmdBufLabelCount = 0;
417 callback_data.pCmdBufLabels = NULL;
418 callback_data.objectCount = 1;
419 callback_data.pObjects = &object_name_info;
420
John Zulaufc64f97c2019-04-10 10:34:52 -0600421 std::vector<VkDebugUtilsLabelEXT> queue_labels;
422 std::vector<VkDebugUtilsLabelEXT> cmd_buf_labels;
Mark Young6ba8abe2017-11-09 10:37:04 -0700423 std::string new_debug_report_message = "";
424 std::ostringstream oss;
Mark Young6ba8abe2017-11-09 10:37:04 -0700425
426 if (0 != src_object) {
Mark Young8504ba62018-03-21 13:35:34 -0600427 oss << "Object: 0x" << std::hex << src_object;
Mark Young6ba8abe2017-11-09 10:37:04 -0700428 // If this is a queue, add any queue labels to the callback data.
429 if (VK_OBJECT_TYPE_QUEUE == object_name_info.objectType) {
Mark Lobodzinski12813302019-02-07 15:03:06 -0700430 auto label_iter = debug_data->debugUtilsQueueLabels.find(reinterpret_cast<VkQueue>(src_object));
431 if (label_iter != debug_data->debugUtilsQueueLabels.end()) {
John Zulaufc64f97c2019-04-10 10:34:52 -0600432 queue_labels = label_iter->second->Export();
433 callback_data.queueLabelCount = static_cast<uint32_t>(queue_labels.size());
434 callback_data.pQueueLabels = queue_labels.empty() ? nullptr : queue_labels.data();
Mark Young6ba8abe2017-11-09 10:37:04 -0700435 }
436 // If this is a command buffer, add any command buffer labels to the callback data.
437 } else if (VK_OBJECT_TYPE_COMMAND_BUFFER == object_name_info.objectType) {
Mark Lobodzinski12813302019-02-07 15:03:06 -0700438 auto label_iter = debug_data->debugUtilsCmdBufLabels.find(reinterpret_cast<VkCommandBuffer>(src_object));
439 if (label_iter != debug_data->debugUtilsCmdBufLabels.end()) {
John Zulaufc64f97c2019-04-10 10:34:52 -0600440 cmd_buf_labels = label_iter->second->Export();
441 callback_data.cmdBufLabelCount = static_cast<uint32_t>(cmd_buf_labels.size());
442 callback_data.pCmdBufLabels = cmd_buf_labels.empty() ? nullptr : cmd_buf_labels.data();
Mark Young6ba8abe2017-11-09 10:37:04 -0700443 }
444 }
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -0700445
Mark Young6ba8abe2017-11-09 10:37:04 -0700446 // Look for any debug utils or marker names to use for this object
Mark Lobodzinski5d98ba12019-03-25 13:35:01 -0600447 object_label = debug_data->DebugReportGetUtilsObjectName(src_object);
448 if (object_label.empty()) {
449 object_label = debug_data->DebugReportGetMarkerObjectName(src_object);
Mark Young6ba8abe2017-11-09 10:37:04 -0700450 }
Mark Lobodzinski5d98ba12019-03-25 13:35:01 -0600451 if (!object_label.empty()) {
452 object_name_info.pObjectName = object_label.c_str();
453 oss << " (Name = " << object_label << " : Type = ";
Mark Young8504ba62018-03-21 13:35:34 -0600454 } else {
455 oss << " (Type = ";
Mark Young6ba8abe2017-11-09 10:37:04 -0700456 }
Mark Young8504ba62018-03-21 13:35:34 -0600457 oss << std::to_string(object_type) << ")";
458 } else {
459 oss << "Object: VK_NULL_HANDLE (Type = " << std::to_string(object_type) << ")";
Mark Young6ba8abe2017-11-09 10:37:04 -0700460 }
461 new_debug_report_message += oss.str();
462 new_debug_report_message += " | ";
463 new_debug_report_message += message;
464
465 while (layer_dbg_node) {
Mark Young8504ba62018-03-21 13:35:34 -0600466 // If the app uses the VK_EXT_debug_report extension, call all of those registered callbacks.
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700467 if (!layer_dbg_node->is_messenger && (layer_dbg_node->report.msgFlags & msg_flags)) {
468 if (text_vuid != nullptr) {
469 // If a text vuid is supplied for the old debug report extension, prepend it to the message string
470 new_debug_report_message.insert(0, " ] ");
471 new_debug_report_message.insert(0, text_vuid);
472 new_debug_report_message.insert(0, " [ ");
473 }
474
Dave Houlton407df732018-08-06 17:58:24 -0600475 if (layer_dbg_node->report.pfnMsgCallback(msg_flags, object_type, src_object, location, 0, layer_prefix,
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700476 new_debug_report_message.c_str(), layer_dbg_node->pUserData)) {
477 bail = true;
478 }
Mark Young8504ba62018-03-21 13:35:34 -0600479 // If the app uses the VK_EXT_debug_utils extension, call all of those registered callbacks.
Mark Young6ba8abe2017-11-09 10:37:04 -0700480 } else if (layer_dbg_node->is_messenger && (layer_dbg_node->messenger.messageSeverity & severity) &&
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700481 (layer_dbg_node->messenger.messageType & types)) {
482 if (layer_dbg_node->messenger.pfnUserCallback(static_cast<VkDebugUtilsMessageSeverityFlagBitsEXT>(severity), types,
483 &callback_data, layer_dbg_node->pUserData)) {
484 bail = true;
485 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700486 }
487 layer_dbg_node = layer_dbg_node->pNext;
488 }
489
Mark Young6ba8abe2017-11-09 10:37:04 -0700490 return bail;
491}
492
493static inline void DebugAnnotFlagsToReportFlags(VkDebugUtilsMessageSeverityFlagBitsEXT da_severity,
494 VkDebugUtilsMessageTypeFlagsEXT da_type, VkDebugReportFlagsEXT *dr_flags) {
495 *dr_flags = 0;
496
497 if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) != 0) {
498 *dr_flags |= VK_DEBUG_REPORT_ERROR_BIT_EXT;
499 } else if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) != 0) {
500 if ((da_type & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT) != 0) {
501 *dr_flags |= VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
502 } else {
503 *dr_flags |= VK_DEBUG_REPORT_WARNING_BIT_EXT;
504 }
505 } else if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) != 0) {
506 *dr_flags |= VK_DEBUG_REPORT_INFORMATION_BIT_EXT;
507 } else if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) != 0) {
508 *dr_flags |= VK_DEBUG_REPORT_DEBUG_BIT_EXT;
509 }
510}
511
512static inline bool debug_messenger_log_msg(const debug_report_data *debug_data,
513 VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
514 VkDebugUtilsMessageTypeFlagsEXT message_type,
Shannon McPherson7fbbe362018-12-03 11:57:42 -0700515 VkDebugUtilsMessengerCallbackDataEXT *callback_data,
516 const VkDebugUtilsMessengerEXT *messenger) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700517 bool bail = false;
518 VkLayerDbgFunctionNode *layer_dbg_node = NULL;
519
520 if (debug_data->debug_callback_list != NULL) {
521 layer_dbg_node = debug_data->debug_callback_list;
522 } else {
523 layer_dbg_node = debug_data->default_debug_callback_list;
524 }
525
526 VkDebugReportFlagsEXT object_flags = 0;
527
528 DebugAnnotFlagsToReportFlags(message_severity, message_type, &object_flags);
529
Shannon McPherson7fbbe362018-12-03 11:57:42 -0700530 VkDebugUtilsObjectNameInfoEXT object_name_info;
531 object_name_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
532 object_name_info.pNext = NULL;
533 object_name_info.objectType = VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT;
534 object_name_info.objectHandle = HandleToUint64(*messenger);
535 object_name_info.pObjectName = NULL;
536 callback_data->pObjects = &object_name_info;
537 callback_data->objectCount = 1;
538
Mark Young6ba8abe2017-11-09 10:37:04 -0700539 while (layer_dbg_node) {
540 if (layer_dbg_node->is_messenger && (layer_dbg_node->messenger.messageSeverity & message_severity) &&
541 (layer_dbg_node->messenger.messageType & message_type)) {
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -0700542 std::string messenger_label = debug_data->DebugReportGetUtilsObjectName(object_name_info.objectHandle);
543 if (!messenger_label.empty()) {
544 object_name_info.pObjectName = messenger_label.c_str();
Mark Young6ba8abe2017-11-09 10:37:04 -0700545 }
546 if (layer_dbg_node->messenger.pfnUserCallback(message_severity, message_type, callback_data,
547 layer_dbg_node->pUserData)) {
548 bail = true;
549 }
550 } else if (!layer_dbg_node->is_messenger && layer_dbg_node->report.msgFlags & object_flags) {
John Zulauf536649b2018-05-01 13:28:27 -0600551 VkDebugReportObjectTypeEXT object_type = convertCoreObjectToDebugReportObject(callback_data->pObjects[0].objectType);
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -0700552 std::string marker_label = debug_data->DebugReportGetMarkerObjectName(object_name_info.objectHandle);
553 if (marker_label.empty()) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700554 if (layer_dbg_node->report.pfnMsgCallback(object_flags, object_type, callback_data->pObjects[0].objectHandle, 0,
555 callback_data->messageIdNumber, callback_data->pMessageIdName,
556 callback_data->pMessage, layer_dbg_node->pUserData)) {
Tony Barbour3431dac2017-06-19 16:50:37 -0600557 bail = true;
558 }
559 } else {
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -0700560 std::string newMsg = "SrcObject name = " + marker_label;
Tony Barbour3431dac2017-06-19 16:50:37 -0600561 newMsg.append(" ");
Mark Young6ba8abe2017-11-09 10:37:04 -0700562 newMsg.append(callback_data->pMessage);
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 newMsg.c_str(), layer_dbg_node->pUserData)) {
Tony Barbour3431dac2017-06-19 16:50:37 -0600566 bail = true;
567 }
Courtney Goeltzenleuchter06640832015-09-04 13:52:24 -0600568 }
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600569 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700570 layer_dbg_node = layer_dbg_node->pNext;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600571 }
Courtney Goeltzenleuchter06640832015-09-04 13:52:24 -0600572
573 return bail;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600574}
575
Mark Young6ba8abe2017-11-09 10:37:04 -0700576static inline debug_report_data *debug_utils_create_instance(
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700577 VkLayerInstanceDispatchTable *table, VkInstance inst, uint32_t extension_count,
Mark Young6ba8abe2017-11-09 10:37:04 -0700578 const char *const *enabled_extensions) // layer or extension name to be enabled
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600579{
Mark Lobodzinski12813302019-02-07 15:03:06 -0700580 debug_report_data *debug_data = new debug_report_data;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600581 for (uint32_t i = 0; i < extension_count; i++) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700582 if (strcmp(enabled_extensions[i], VK_EXT_DEBUG_REPORT_EXTENSION_NAME) == 0) {
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600583 debug_data->g_DEBUG_REPORT = true;
Mark Young6ba8abe2017-11-09 10:37:04 -0700584 } else if (strcmp(enabled_extensions[i], VK_EXT_DEBUG_UTILS_EXTENSION_NAME) == 0) {
585 debug_data->g_DEBUG_UTILS = true;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600586 }
587 }
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600588 return debug_data;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600589}
590
Mark Young6ba8abe2017-11-09 10:37:04 -0700591static inline void layer_debug_utils_destroy_instance(debug_report_data *debug_data) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600592 if (debug_data) {
Mark Lobodzinski25ac7b02019-02-07 13:22:56 -0700593 std::unique_lock<std::mutex> lock(debug_data->debug_report_mutex);
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600594 RemoveAllMessageCallbacks(debug_data, &debug_data->default_debug_callback_list);
595 RemoveAllMessageCallbacks(debug_data, &debug_data->debug_callback_list);
Mark Lobodzinski25ac7b02019-02-07 13:22:56 -0700596 lock.unlock();
Mark Lobodzinski12813302019-02-07 15:03:06 -0700597 delete (debug_data);
Courtney Goeltzenleuchteree4027d2015-06-28 13:01:17 -0600598 }
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600599}
600
Mark Young6ba8abe2017-11-09 10:37:04 -0700601static inline debug_report_data *layer_debug_utils_create_device(debug_report_data *instance_debug_data, VkDevice device) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600602 // DEBUG_REPORT shares data between Instance and Device,
603 // so just return instance's data pointer
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600604 return instance_debug_data;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600605}
606
Mark Young6ba8abe2017-11-09 10:37:04 -0700607static inline void layer_debug_utils_destroy_device(VkDevice device) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600608 // Nothing to do since we're using instance data record
609}
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600610
Mark Young6ba8abe2017-11-09 10:37:04 -0700611static inline void layer_destroy_messenger_callback(debug_report_data *debug_data, VkDebugUtilsMessengerEXT messenger,
612 const VkAllocationCallbacks *allocator) {
Mark Lobodzinski25ac7b02019-02-07 13:22:56 -0700613 std::unique_lock<std::mutex> lock(debug_data->debug_report_mutex);
Mark Young6ba8abe2017-11-09 10:37:04 -0700614 RemoveDebugUtilsMessenger(debug_data, &debug_data->debug_callback_list, messenger);
615 RemoveDebugUtilsMessenger(debug_data, &debug_data->default_debug_callback_list, messenger);
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600616}
617
Mark Young6ba8abe2017-11-09 10:37:04 -0700618static inline VkResult layer_create_messenger_callback(debug_report_data *debug_data, bool default_callback,
619 const VkDebugUtilsMessengerCreateInfoEXT *create_info,
620 const VkAllocationCallbacks *allocator,
621 VkDebugUtilsMessengerEXT *messenger) {
Mark Lobodzinski25ac7b02019-02-07 13:22:56 -0700622 std::unique_lock<std::mutex> lock(debug_data->debug_report_mutex);
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700623 VkLayerDbgFunctionNode *pNewDbgFuncNode = (VkLayerDbgFunctionNode *)malloc(sizeof(VkLayerDbgFunctionNode));
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700624 if (!pNewDbgFuncNode) return VK_ERROR_OUT_OF_HOST_MEMORY;
Mark Young6ba8abe2017-11-09 10:37:04 -0700625 memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode));
626 pNewDbgFuncNode->is_messenger = true;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600627
Tobin Ehliseb7715d2015-09-21 09:36:47 -0600628 // Handle of 0 is logging_callback so use allocated Node address as unique handle
Mark Young6ba8abe2017-11-09 10:37:04 -0700629 if (!(*messenger)) *messenger = (VkDebugUtilsMessengerEXT)pNewDbgFuncNode;
630 pNewDbgFuncNode->messenger.messenger = *messenger;
631 pNewDbgFuncNode->messenger.pfnUserCallback = create_info->pfnUserCallback;
632 pNewDbgFuncNode->messenger.messageSeverity = create_info->messageSeverity;
633 pNewDbgFuncNode->messenger.messageType = create_info->messageType;
634 pNewDbgFuncNode->pUserData = create_info->pUserData;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600635
Mark Young6ba8abe2017-11-09 10:37:04 -0700636 debug_data->active_severities |= create_info->messageSeverity;
637 debug_data->active_types |= create_info->messageType;
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600638 if (default_callback) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700639 AddDebugCallbackNode(debug_data, &debug_data->default_debug_callback_list, pNewDbgFuncNode);
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600640 } else {
Mark Young6ba8abe2017-11-09 10:37:04 -0700641 AddDebugCallbackNode(debug_data, &debug_data->debug_callback_list, pNewDbgFuncNode);
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600642 }
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600643
Mark Young6ba8abe2017-11-09 10:37:04 -0700644 VkDebugUtilsMessengerCallbackDataEXT callback_data = {};
Mark Young6ba8abe2017-11-09 10:37:04 -0700645 callback_data.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT;
646 callback_data.pNext = NULL;
647 callback_data.flags = 0;
648 callback_data.pMessageIdName = "Layer Internal Message";
649 callback_data.messageIdNumber = 0;
650 callback_data.pMessage = "Added messenger";
651 callback_data.queueLabelCount = 0;
652 callback_data.pQueueLabels = NULL;
653 callback_data.cmdBufLabelCount = 0;
654 callback_data.pCmdBufLabels = NULL;
Shannon McPherson7fbbe362018-12-03 11:57:42 -0700655 callback_data.objectCount = 0;
656 callback_data.pObjects = NULL;
Mark Young6ba8abe2017-11-09 10:37:04 -0700657 debug_messenger_log_msg(debug_data, VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT,
Shannon McPherson7fbbe362018-12-03 11:57:42 -0700658 VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT, &callback_data, messenger);
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600659 return VK_SUCCESS;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600660}
661
Mark Young6ba8abe2017-11-09 10:37:04 -0700662static inline void layer_destroy_report_callback(debug_report_data *debug_data, VkDebugReportCallbackEXT callback,
663 const VkAllocationCallbacks *allocator) {
Mark Lobodzinski25ac7b02019-02-07 13:22:56 -0700664 std::unique_lock<std::mutex> lock(debug_data->debug_report_mutex);
Mark Young6ba8abe2017-11-09 10:37:04 -0700665 RemoveDebugUtilsMessageCallback(debug_data, &debug_data->debug_callback_list, callback);
666 RemoveDebugUtilsMessageCallback(debug_data, &debug_data->default_debug_callback_list, callback);
667}
668
669static inline VkResult layer_create_report_callback(debug_report_data *debug_data, bool default_callback,
670 const VkDebugReportCallbackCreateInfoEXT *create_info,
671 const VkAllocationCallbacks *allocator, VkDebugReportCallbackEXT *callback) {
Mark Lobodzinski25ac7b02019-02-07 13:22:56 -0700672 std::unique_lock<std::mutex> lock(debug_data->debug_report_mutex);
Mark Young6ba8abe2017-11-09 10:37:04 -0700673 VkLayerDbgFunctionNode *pNewDbgFuncNode = (VkLayerDbgFunctionNode *)malloc(sizeof(VkLayerDbgFunctionNode));
674 if (!pNewDbgFuncNode) {
675 return VK_ERROR_OUT_OF_HOST_MEMORY;
676 }
677 memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode));
678 pNewDbgFuncNode->is_messenger = false;
679
680 // Handle of 0 is logging_callback so use allocated Node address as unique handle
681 if (!(*callback)) *callback = (VkDebugReportCallbackEXT)pNewDbgFuncNode;
682 pNewDbgFuncNode->report.msgCallback = *callback;
683 pNewDbgFuncNode->report.pfnMsgCallback = create_info->pfnCallback;
684 pNewDbgFuncNode->report.msgFlags = create_info->flags;
685 pNewDbgFuncNode->pUserData = create_info->pUserData;
686
687 VkFlags local_severity = 0;
688 VkFlags local_type = 0;
689 DebugReportFlagsToAnnotFlags(create_info->flags, true, &local_severity, &local_type);
690 debug_data->active_severities |= local_severity;
691 debug_data->active_types |= local_type;
692 if (default_callback) {
693 AddDebugCallbackNode(debug_data, &debug_data->default_debug_callback_list, pNewDbgFuncNode);
694 } else {
695 AddDebugCallbackNode(debug_data, &debug_data->debug_callback_list, pNewDbgFuncNode);
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600696 }
697
Mark Young6ba8abe2017-11-09 10:37:04 -0700698 debug_log_msg(debug_data, VK_DEBUG_REPORT_DEBUG_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT, (uint64_t)*callback, 0,
Dave Houlton407df732018-08-06 17:58:24 -0600699 "DebugReport", "Added callback", kVUIDUndefined);
Mark Young6ba8abe2017-11-09 10:37:04 -0700700 return VK_SUCCESS;
701}
702
703static inline PFN_vkVoidFunction debug_utils_get_instance_proc_addr(debug_report_data *debug_data, const char *func_name) {
704 if (!debug_data) {
705 return NULL;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600706 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700707 if (debug_data->g_DEBUG_REPORT) {
708 if (!strcmp(func_name, "vkCreateDebugReportCallbackEXT")) {
709 return (PFN_vkVoidFunction)vkCreateDebugReportCallbackEXT;
710 }
711 if (!strcmp(func_name, "vkDestroyDebugReportCallbackEXT")) {
712 return (PFN_vkVoidFunction)vkDestroyDebugReportCallbackEXT;
713 }
714 if (!strcmp(func_name, "vkDebugReportMessageEXT")) {
715 return (PFN_vkVoidFunction)vkDebugReportMessageEXT;
716 }
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600717 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700718 if (debug_data->g_DEBUG_UTILS) {
719 if (!strcmp(func_name, "vkCreateDebugUtilsMessengerEXT")) {
720 return (PFN_vkVoidFunction)vkCreateDebugUtilsMessengerEXT;
721 }
722 if (!strcmp(func_name, "vkDestroyDebugUtilsMessengerEXT")) {
723 return (PFN_vkVoidFunction)vkDestroyDebugUtilsMessengerEXT;
724 }
725 if (!strcmp(func_name, "vkSubmitDebugUtilsMessageEXT")) {
726 return (PFN_vkVoidFunction)vkSubmitDebugUtilsMessageEXT;
727 }
Courtney Goeltzenleuchter822e8d72015-11-30 15:28:25 -0700728 }
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600729 return NULL;
730}
731
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600732// This utility (called at vkCreateInstance() time), looks at a pNext chain.
733// It counts any VkDebugReportCallbackCreateInfoEXT structs that it finds. It
734// then allocates an array that can hold that many structs, as well as that
735// many VkDebugReportCallbackEXT handles. It then copies each
736// VkDebugReportCallbackCreateInfoEXT, and initializes each handle.
Mark Young6ba8abe2017-11-09 10:37:04 -0700737static inline VkResult layer_copy_tmp_report_callbacks(const void *pChain, uint32_t *num_callbacks,
738 VkDebugReportCallbackCreateInfoEXT **infos,
739 VkDebugReportCallbackEXT **callbacks) {
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600740 uint32_t n = *num_callbacks = 0;
741
742 const void *pNext = pChain;
743 while (pNext) {
744 // 1st, count the number VkDebugReportCallbackCreateInfoEXT:
745 if (((VkDebugReportCallbackCreateInfoEXT *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT) {
746 n++;
747 }
748 pNext = (void *)((VkDebugReportCallbackCreateInfoEXT *)pNext)->pNext;
749 }
750 if (n == 0) {
751 return VK_SUCCESS;
752 }
753
754 // 2nd, allocate memory for each VkDebugReportCallbackCreateInfoEXT:
755 VkDebugReportCallbackCreateInfoEXT *pInfos = *infos =
756 ((VkDebugReportCallbackCreateInfoEXT *)malloc(n * sizeof(VkDebugReportCallbackCreateInfoEXT)));
757 if (!pInfos) {
758 return VK_ERROR_OUT_OF_HOST_MEMORY;
759 }
760 // 3rd, allocate memory for a unique handle for each callback:
761 VkDebugReportCallbackEXT *pCallbacks = *callbacks = ((VkDebugReportCallbackEXT *)malloc(n * sizeof(VkDebugReportCallbackEXT)));
762 if (!pCallbacks) {
763 free(pInfos);
764 return VK_ERROR_OUT_OF_HOST_MEMORY;
765 }
766 // 4th, copy each VkDebugReportCallbackCreateInfoEXT for use by
767 // vkDestroyInstance, and assign a unique handle to each callback (just
768 // use the address of the copied VkDebugReportCallbackCreateInfoEXT):
769 pNext = pChain;
770 while (pNext) {
771 if (((VkInstanceCreateInfo *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT) {
772 memcpy(pInfos, pNext, sizeof(VkDebugReportCallbackCreateInfoEXT));
773 *pCallbacks++ = (VkDebugReportCallbackEXT)pInfos++;
774 }
775 pNext = (void *)((VkInstanceCreateInfo *)pNext)->pNext;
776 }
777
778 *num_callbacks = n;
779 return VK_SUCCESS;
780}
781
Mark Young6ba8abe2017-11-09 10:37:04 -0700782// This utility frees the arrays allocated by layer_copy_tmp_report_callbacks()
783static inline void layer_free_tmp_report_callbacks(VkDebugReportCallbackCreateInfoEXT *infos, VkDebugReportCallbackEXT *callbacks) {
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600784 free(infos);
785 free(callbacks);
786}
787
788// This utility enables all of the VkDebugReportCallbackCreateInfoEXT structs
Mark Young6ba8abe2017-11-09 10:37:04 -0700789// that were copied by layer_copy_tmp_report_callbacks()
790static inline VkResult layer_enable_tmp_report_callbacks(debug_report_data *debug_data, uint32_t num_callbacks,
791 VkDebugReportCallbackCreateInfoEXT *infos,
792 VkDebugReportCallbackEXT *callbacks) {
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600793 VkResult rtn = VK_SUCCESS;
794 for (uint32_t i = 0; i < num_callbacks; i++) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700795 rtn = layer_create_report_callback(debug_data, false, &infos[i], NULL, &callbacks[i]);
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600796 if (rtn != VK_SUCCESS) {
797 for (uint32_t j = 0; j < i; j++) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700798 layer_destroy_report_callback(debug_data, callbacks[j], NULL);
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600799 }
800 return rtn;
801 }
802 }
803 return rtn;
804}
805
806// This utility disables all of the VkDebugReportCallbackCreateInfoEXT structs
Mark Young6ba8abe2017-11-09 10:37:04 -0700807// that were copied by layer_copy_tmp_report_callbacks()
808static inline void layer_disable_tmp_report_callbacks(debug_report_data *debug_data, uint32_t num_callbacks,
809 VkDebugReportCallbackEXT *callbacks) {
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600810 for (uint32_t i = 0; i < num_callbacks; i++) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700811 layer_destroy_report_callback(debug_data, callbacks[i], NULL);
812 }
813}
814
815// This utility (called at vkCreateInstance() time), looks at a pNext chain.
816// It counts any VkDebugUtilsMessengerCreateInfoEXT structs that it finds. It
817// then allocates an array that can hold that many structs, as well as that
818// many VkDebugUtilsMessengerEXT handles. It then copies each
819// VkDebugUtilsMessengerCreateInfoEXT, and initializes each handle.
Mark Young8504ba62018-03-21 13:35:34 -0600820static inline VkResult layer_copy_tmp_debug_messengers(const void *pChain, uint32_t *num_messengers,
821 VkDebugUtilsMessengerCreateInfoEXT **infos,
822 VkDebugUtilsMessengerEXT **messengers) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700823 uint32_t n = *num_messengers = 0;
824
825 const void *pNext = pChain;
826 while (pNext) {
827 // 1st, count the number VkDebugUtilsMessengerCreateInfoEXT:
828 if (((VkDebugUtilsMessengerCreateInfoEXT *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT) {
829 n++;
830 }
831 pNext = (void *)((VkDebugUtilsMessengerCreateInfoEXT *)pNext)->pNext;
832 }
833 if (n == 0) {
834 return VK_SUCCESS;
835 }
836
837 // 2nd, allocate memory for each VkDebugUtilsMessengerCreateInfoEXT:
838 VkDebugUtilsMessengerCreateInfoEXT *pInfos = *infos =
839 ((VkDebugUtilsMessengerCreateInfoEXT *)malloc(n * sizeof(VkDebugUtilsMessengerCreateInfoEXT)));
840 if (!pInfos) {
841 return VK_ERROR_OUT_OF_HOST_MEMORY;
842 }
843 // 3rd, allocate memory for a unique handle for each messenger:
844 VkDebugUtilsMessengerEXT *pMessengers = *messengers =
845 ((VkDebugUtilsMessengerEXT *)malloc(n * sizeof(VkDebugUtilsMessengerEXT)));
846 if (!pMessengers) {
847 free(pInfos);
848 return VK_ERROR_OUT_OF_HOST_MEMORY;
849 }
850 // 4th, copy each VkDebugUtilsMessengerCreateInfoEXT for use by
851 // vkDestroyInstance, and assign a unique handle to each callback (just
852 // use the address of the copied VkDebugUtilsMessengerCreateInfoEXT):
853 pNext = pChain;
854 while (pNext) {
855 if (((VkInstanceCreateInfo *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT) {
856 memcpy(pInfos, pNext, sizeof(VkDebugUtilsMessengerCreateInfoEXT));
857 *pMessengers++ = (VkDebugUtilsMessengerEXT)pInfos++;
858 }
859 pNext = (void *)((VkInstanceCreateInfo *)pNext)->pNext;
860 }
861
862 *num_messengers = n;
863 return VK_SUCCESS;
864}
865
866// This utility frees the arrays allocated by layer_copy_tmp_debug_messengers()
Mark Young8504ba62018-03-21 13:35:34 -0600867static inline void layer_free_tmp_debug_messengers(VkDebugUtilsMessengerCreateInfoEXT *infos,
868 VkDebugUtilsMessengerEXT *messengers) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700869 free(infos);
870 free(messengers);
871}
872
873// This utility enables all of the VkDebugUtilsMessengerCreateInfoEXT structs
874// that were copied by layer_copy_tmp_debug_messengers()
Mark Young8504ba62018-03-21 13:35:34 -0600875static inline VkResult layer_enable_tmp_debug_messengers(debug_report_data *debug_data, uint32_t num_messengers,
876 VkDebugUtilsMessengerCreateInfoEXT *infos,
877 VkDebugUtilsMessengerEXT *messengers) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700878 VkResult rtn = VK_SUCCESS;
879 for (uint32_t i = 0; i < num_messengers; i++) {
880 rtn = layer_create_messenger_callback(debug_data, false, &infos[i], NULL, &messengers[i]);
881 if (rtn != VK_SUCCESS) {
882 for (uint32_t j = 0; j < i; j++) {
883 layer_destroy_messenger_callback(debug_data, messengers[j], NULL);
884 }
885 return rtn;
886 }
887 }
888 return rtn;
889}
890
891// This utility disables all of the VkDebugUtilsMessengerCreateInfoEXT structs
892// that were copied by layer_copy_tmp_debug_messengers()
Mark Young8504ba62018-03-21 13:35:34 -0600893static inline void layer_disable_tmp_debug_messengers(debug_report_data *debug_data, uint32_t num_messengers,
894 VkDebugUtilsMessengerEXT *messengers) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700895 for (uint32_t i = 0; i < num_messengers; i++) {
896 layer_destroy_messenger_callback(debug_data, messengers[i], NULL);
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600897 }
898}
899
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600900// Checks if the message will get logged.
901// Allows layer to defer collecting & formating data if the
902// message will be discarded.
Mark Young6ba8abe2017-11-09 10:37:04 -0700903static inline bool will_log_msg(debug_report_data *debug_data, VkFlags msg_flags) {
904 VkFlags local_severity = 0;
905 VkFlags local_type = 0;
906 DebugReportFlagsToAnnotFlags(msg_flags, true, &local_severity, &local_type);
907 if (!debug_data || !(debug_data->active_severities & local_severity) || !(debug_data->active_types & local_type)) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600908 // Message is not wanted
Courtney Goeltzenleuchter6a564a12015-09-18 16:30:24 -0600909 return false;
910 }
911
912 return true;
913}
John Zulauf6664e272018-01-17 11:00:22 -0700914#ifndef WIN32
Mark Lobodzinski1bcbdf92018-02-07 10:00:22 -0700915static inline int string_sprintf(std::string *output, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
John Zulauf6664e272018-01-17 11:00:22 -0700916#endif
Mark Lobodzinski1bcbdf92018-02-07 10:00:22 -0700917static inline int string_sprintf(std::string *output, const char *fmt, ...) {
John Zulauf6664e272018-01-17 11:00:22 -0700918 std::string &formatted = *output;
919 va_list argptr;
920 va_start(argptr, fmt);
921 int reserve = vsnprintf(nullptr, 0, fmt, argptr);
922 va_end(argptr);
John Zulaufdeaa0132018-12-12 16:22:30 -0700923 formatted.reserve(reserve + 1); // Set the storage length long enough to hold the output + null
924 formatted.resize(reserve); // Set the *logical* length to be what vsprintf will write
John Zulauf6664e272018-01-17 11:00:22 -0700925 va_start(argptr, fmt);
926 int result = vsnprintf((char *)formatted.data(), formatted.capacity(), fmt, argptr);
927 va_end(argptr);
928 assert(result == reserve);
John Zulaufdeaa0132018-12-12 16:22:30 -0700929 assert((formatted.size() == strlen(formatted.c_str())));
John Zulauf6664e272018-01-17 11:00:22 -0700930 return result;
931}
Courtney Goeltzenleuchter6a564a12015-09-18 16:30:24 -0600932
Chris Forbes8a25bce2016-03-24 12:06:35 +1300933#ifdef WIN32
934static inline int vasprintf(char **strp, char const *fmt, va_list ap) {
935 *strp = nullptr;
936 int size = _vscprintf(fmt, ap);
937 if (size >= 0) {
Mark Lobodzinski729a8d32017-01-26 12:16:30 -0700938 *strp = (char *)malloc(size + 1);
Chris Forbes8a25bce2016-03-24 12:06:35 +1300939 if (!*strp) {
940 return -1;
941 }
Mark Lobodzinski729a8d32017-01-26 12:16:30 -0700942 _vsnprintf(*strp, size + 1, fmt, ap);
Chris Forbes8a25bce2016-03-24 12:06:35 +1300943 }
944 return size;
945}
946#endif
947
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700948// Output log message via DEBUG_REPORT. Takes format and variable arg list so that output string is only computed if a message
949// needs to be logged
Michael Lentine010f4692015-11-03 16:19:46 -0800950#ifndef WIN32
Mark Young6ba8abe2017-11-09 10:37:04 -0700951static inline bool log_msg(const debug_report_data *debug_data, VkFlags msg_flags, VkDebugReportObjectTypeEXT object_type,
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700952 uint64_t src_object, std::string vuid_text, const char *format, ...)
953 __attribute__((format(printf, 6, 7)));
Michael Lentine010f4692015-11-03 16:19:46 -0800954#endif
Mark Young6ba8abe2017-11-09 10:37:04 -0700955static inline bool log_msg(const debug_report_data *debug_data, VkFlags msg_flags, VkDebugReportObjectTypeEXT object_type,
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700956 uint64_t src_object, std::string vuid_text, const char *format, ...) {
Mark Lobodzinski12813302019-02-07 15:03:06 -0700957 if (!debug_data) return false;
Mark Lobodzinski25ac7b02019-02-07 13:22:56 -0700958 std::unique_lock<std::mutex> lock(debug_data->debug_report_mutex);
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700959 VkFlags local_severity = 0;
960 VkFlags local_type = 0;
961 DebugReportFlagsToAnnotFlags(msg_flags, true, &local_severity, &local_type);
962 if (!debug_data || !(debug_data->active_severities & local_severity) || !(debug_data->active_types & local_type)) {
963 // Message is not wanted
964 return false;
965 }
966
967 va_list argptr;
968 va_start(argptr, format);
969 char *str;
970 if (-1 == vasprintf(&str, format, argptr)) {
971 // On failure, glibc vasprintf leaves str undefined
972 str = nullptr;
973 }
974 va_end(argptr);
975
Dave Houlton407df732018-08-06 17:58:24 -0600976 std::string str_plus_spec_text(str ? str : "Allocation failure");
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700977
Dave Houlton407df732018-08-06 17:58:24 -0600978 // Append the spec error text to the error message, unless it's an UNASSIGNED or UNDEFINED vuid
979 if ((vuid_text.find("UNASSIGNED-") == std::string::npos) && (vuid_text.find(kVUIDUndefined) == std::string::npos)) {
Dave Houlton4d9b2f82018-10-24 18:21:06 -0600980 // Linear search makes no assumptions about the layout of the string table
981 // This is not fast, but it does not need to be at this point in the error reporting path
982 uint32_t num_vuids = sizeof(vuid_spec_text) / sizeof(vuid_spec_text_pair);
983 const char *spec_text = nullptr;
984 for (uint32_t i = 0; i < num_vuids; i++) {
985 if (0 == strcmp(vuid_text.c_str(), vuid_spec_text[i].vuid)) {
986 spec_text = vuid_spec_text[i].spec_text;
987 break;
988 }
989 }
990
991 if (nullptr == spec_text) {
Dave Houlton407df732018-08-06 17:58:24 -0600992 // If this happens, you've hit a VUID string that isn't defined in the spec's json file
993 // Try running 'vk_validation_stats -c' to look for invalid VUID strings in the repo code
994 assert(0);
995 } else {
996 str_plus_spec_text += " The Vulkan spec states: ";
Dave Houlton4d9b2f82018-10-24 18:21:06 -0600997 str_plus_spec_text += spec_text;
Dave Houlton407df732018-08-06 17:58:24 -0600998 }
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700999 }
1000
Dave Houlton8e9f6542018-05-18 12:18:22 -06001001 // Append layer prefix with VUID string, pass in recovered legacy numerical VUID
Dave Houlton407df732018-08-06 17:58:24 -06001002 bool result = debug_log_msg(debug_data, msg_flags, object_type, src_object, 0, "Validation", str_plus_spec_text.c_str(),
1003 vuid_text.c_str());
Mark Lobodzinski316c18c2018-02-21 09:48:42 -07001004
1005 free(str);
1006 return result;
1007}
1008
Mark Young6ba8abe2017-11-09 10:37:04 -07001009static inline VKAPI_ATTR VkBool32 VKAPI_CALL report_log_callback(VkFlags msg_flags, VkDebugReportObjectTypeEXT obj_type,
1010 uint64_t src_object, size_t location, int32_t msg_code,
1011 const char *layer_prefix, const char *message, void *user_data) {
Mark Lobodzinski706e15a2018-12-12 15:35:29 -07001012 std::ostringstream msg_buffer;
Mark Young6ba8abe2017-11-09 10:37:04 -07001013 char msg_flag_string[30];
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -06001014
Mark Young6ba8abe2017-11-09 10:37:04 -07001015 PrintMessageFlags(msg_flags, msg_flag_string);
Courtney Goeltzenleuchter2f25bb42015-06-14 11:29:24 -06001016
Mark Lobodzinski706e15a2018-12-12 15:35:29 -07001017 msg_buffer << layer_prefix << "(" << msg_flag_string << "): msg_code: " << msg_code << ": " << message << "\n";
1018 const std::string tmp = msg_buffer.str();
1019 const char *cstr = tmp.c_str();
1020
1021 fprintf((FILE *)user_data, "%s", cstr);
Mark Young6ba8abe2017-11-09 10:37:04 -07001022 fflush((FILE *)user_data);
Courtney Goeltzenleuchter06640832015-09-04 13:52:24 -06001023
Mark Lobodzinski706e15a2018-12-12 15:35:29 -07001024#if defined __ANDROID__
1025 LOGCONSOLE("%s", cstr);
1026#endif
1027
Courtney Goeltzenleuchter06640832015-09-04 13:52:24 -06001028 return false;
Courtney Goeltzenleuchter2f25bb42015-06-14 11:29:24 -06001029}
Courtney Goeltzenleuchter5907ac42015-10-05 14:41:34 -06001030
Mark Young6ba8abe2017-11-09 10:37:04 -07001031static inline VKAPI_ATTR VkBool32 VKAPI_CALL report_win32_debug_output_msg(VkFlags msg_flags, VkDebugReportObjectTypeEXT obj_type,
1032 uint64_t src_object, size_t location, int32_t msg_code,
1033 const char *layer_prefix, const char *message,
1034 void *user_data) {
Courtney Goeltzenleuchter5907ac42015-10-05 14:41:34 -06001035#ifdef WIN32
Mark Young6ba8abe2017-11-09 10:37:04 -07001036 char msg_flag_string[30];
Courtney Goeltzenleuchter5907ac42015-10-05 14:41:34 -06001037 char buf[2048];
1038
Mark Young6ba8abe2017-11-09 10:37:04 -07001039 PrintMessageFlags(msg_flags, msg_flag_string);
Mark Lobodzinskib1fd9d12018-03-30 14:26:00 -06001040 _snprintf(buf, sizeof(buf) - 1, "%s (%s): msg_code: %d: %s\n", layer_prefix, msg_flag_string, msg_code, message);
Courtney Goeltzenleuchter5907ac42015-10-05 14:41:34 -06001041
1042 OutputDebugString(buf);
1043#endif
1044
1045 return false;
1046}
1047
Mark Young6ba8abe2017-11-09 10:37:04 -07001048static inline VKAPI_ATTR VkBool32 VKAPI_CALL DebugBreakCallback(VkFlags msgFlags, VkDebugReportObjectTypeEXT obj_type,
1049 uint64_t src_object, size_t location, int32_t msg_code,
1050 const char *layer_prefix, const char *message, void *user_data) {
Mark Lobodzinskic9d81652017-08-10 11:01:17 -06001051#ifdef WIN32
1052 DebugBreak();
1053#else
1054 raise(SIGTRAP);
1055#endif
1056
1057 return false;
1058}
1059
Mark Young6ba8abe2017-11-09 10:37:04 -07001060static inline VKAPI_ATTR VkBool32 VKAPI_CALL messenger_log_callback(VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
1061 VkDebugUtilsMessageTypeFlagsEXT message_type,
1062 const VkDebugUtilsMessengerCallbackDataEXT *callback_data,
1063 void *user_data) {
Mark Lobodzinski706e15a2018-12-12 15:35:29 -07001064 std::ostringstream msg_buffer;
Mark Young6ba8abe2017-11-09 10:37:04 -07001065 char msg_severity[30];
1066 char msg_type[30];
1067
1068 PrintMessageSeverity(message_severity, msg_severity);
1069 PrintMessageType(message_type, msg_type);
1070
Mark Lobodzinski706e15a2018-12-12 15:35:29 -07001071 msg_buffer << callback_data->pMessageIdName << "(" << msg_severity << " / " << msg_type
1072 << "): msgNum: " << callback_data->messageIdNumber << " - " << callback_data->pMessage << "\n";
1073 msg_buffer << " Objects: " << callback_data->objectCount << "\n";
Mark Young8504ba62018-03-21 13:35:34 -06001074 for (uint32_t obj = 0; obj < callback_data->objectCount; ++obj) {
Mark Lobodzinski706e15a2018-12-12 15:35:29 -07001075 msg_buffer << " [" << obj << "] " << std::hex << std::showbase
1076 << HandleToUint64(callback_data->pObjects[obj].objectHandle) << ", type: " << std::dec << std::noshowbase
1077 << callback_data->pObjects[obj].objectType
1078 << ", name: " << (callback_data->pObjects[obj].pObjectName ? callback_data->pObjects[obj].pObjectName : "NULL")
1079 << "\n";
Mark Young8504ba62018-03-21 13:35:34 -06001080 }
Mark Lobodzinski706e15a2018-12-12 15:35:29 -07001081 const std::string tmp = msg_buffer.str();
1082 const char *cstr = tmp.c_str();
1083 fprintf((FILE *)user_data, "%s", cstr);
Mark Young6ba8abe2017-11-09 10:37:04 -07001084 fflush((FILE *)user_data);
1085
Mark Lobodzinski706e15a2018-12-12 15:35:29 -07001086#if defined __ANDROID__
1087 LOGCONSOLE("%s", cstr);
1088#endif
1089
Mark Young6ba8abe2017-11-09 10:37:04 -07001090 return false;
Petr Krause9388f62017-05-13 20:53:12 +02001091}
1092
Mark Young6ba8abe2017-11-09 10:37:04 -07001093static inline VKAPI_ATTR VkBool32 VKAPI_CALL messenger_win32_debug_output_msg(
1094 VkDebugUtilsMessageSeverityFlagBitsEXT message_severity, VkDebugUtilsMessageTypeFlagsEXT message_type,
1095 const VkDebugUtilsMessengerCallbackDataEXT *callback_data, void *user_data) {
1096#ifdef WIN32
Mark Lobodzinski3be125e2018-11-19 09:58:10 -07001097 std::ostringstream msg_buffer;
Mark Young6ba8abe2017-11-09 10:37:04 -07001098 char msg_severity[30];
1099 char msg_type[30];
Mark Lobodzinski863d5de2017-05-22 10:10:07 -06001100
Mark Young6ba8abe2017-11-09 10:37:04 -07001101 PrintMessageSeverity(message_severity, msg_severity);
1102 PrintMessageType(message_type, msg_type);
1103
Mark Lobodzinski3be125e2018-11-19 09:58:10 -07001104 msg_buffer << callback_data->pMessageIdName << "(" << msg_severity << " / " << msg_type
1105 << "): msgNum: " << callback_data->messageIdNumber << " - " << callback_data->pMessage << "\n";
1106 msg_buffer << " Objects: " << callback_data->objectCount << "\n";
1107
Mark Young8504ba62018-03-21 13:35:34 -06001108 for (uint32_t obj = 0; obj < callback_data->objectCount; ++obj) {
Mark Lobodzinski3be125e2018-11-19 09:58:10 -07001109 msg_buffer << " [" << obj << "] " << std::hex << std::showbase
1110 << HandleToUint64(callback_data->pObjects[obj].objectHandle) << ", type: " << std::dec << std::noshowbase
1111 << callback_data->pObjects[obj].objectType
1112 << ", name: " << (callback_data->pObjects[obj].pObjectName ? callback_data->pObjects[obj].pObjectName : "NULL")
1113 << "\n";
Mark Young8504ba62018-03-21 13:35:34 -06001114 }
Mark Lobodzinski3be125e2018-11-19 09:58:10 -07001115 const std::string tmp = msg_buffer.str();
1116 const char *cstr = tmp.c_str();
1117 OutputDebugString(cstr);
Mark Young6ba8abe2017-11-09 10:37:04 -07001118#endif
1119
1120 return false;
1121}
1122
John Zulaufc64f97c2019-04-10 10:34:52 -06001123template <typename Map>
1124static LoggingLabelState *GetLoggingLabelState(Map *map, typename Map::key_type key, bool insert) {
1125 auto iter = map->find(key);
1126 LoggingLabelState *label_state = nullptr;
1127 if (iter == map->end()) {
1128 if (insert) {
1129 // Add a label state if not present
1130 label_state = new LoggingLabelState();
1131 auto inserted = map->insert(std::make_pair(key, std::unique_ptr<LoggingLabelState>(new LoggingLabelState())));
1132 assert(inserted.second);
1133 iter = inserted.first;
1134 label_state = iter->second.get();
1135 }
1136 } else {
1137 label_state = iter->second.get();
1138 }
1139 return label_state;
Mark Young6ba8abe2017-11-09 10:37:04 -07001140}
1141
Mark Young8504ba62018-03-21 13:35:34 -06001142static inline void BeginQueueDebugUtilsLabel(debug_report_data *report_data, VkQueue queue,
1143 const VkDebugUtilsLabelEXT *label_info) {
Mark Lobodzinski25ac7b02019-02-07 13:22:56 -07001144 std::unique_lock<std::mutex> lock(report_data->debug_report_mutex);
Mark Young6ba8abe2017-11-09 10:37:04 -07001145 if (nullptr != label_info && nullptr != label_info->pLabelName) {
John Zulaufc64f97c2019-04-10 10:34:52 -06001146 auto *label_state = GetLoggingLabelState(&report_data->debugUtilsQueueLabels, queue, /* insert */ true);
1147 assert(label_state);
1148 label_state->labels.push_back(LoggingLabel(label_info));
1149
1150 // TODO: Determine if this is the correct semantics for insert label vs. begin/end, perserving existing semantics for now
1151 label_state->insert_label.Reset();
Mark Young6ba8abe2017-11-09 10:37:04 -07001152 }
1153}
1154
Mark Young8504ba62018-03-21 13:35:34 -06001155static inline void EndQueueDebugUtilsLabel(debug_report_data *report_data, VkQueue queue) {
Mark Lobodzinski25ac7b02019-02-07 13:22:56 -07001156 std::unique_lock<std::mutex> lock(report_data->debug_report_mutex);
John Zulaufc64f97c2019-04-10 10:34:52 -06001157 auto *label_state = GetLoggingLabelState(&report_data->debugUtilsQueueLabels, queue, /* insert */ false);
1158 if (label_state) {
1159 // Pop the normal item
1160 if (!label_state->labels.empty()) {
1161 label_state->labels.pop_back();
Mark Young6ba8abe2017-11-09 10:37:04 -07001162 }
John Zulaufc64f97c2019-04-10 10:34:52 -06001163
1164 // TODO: Determine if this is the correct semantics for insert label vs. begin/end, perserving existing semantics for now
1165 label_state->insert_label.Reset();
Mark Young6ba8abe2017-11-09 10:37:04 -07001166 }
1167}
1168
Mark Young8504ba62018-03-21 13:35:34 -06001169static inline void InsertQueueDebugUtilsLabel(debug_report_data *report_data, VkQueue queue,
1170 const VkDebugUtilsLabelEXT *label_info) {
Mark Lobodzinski25ac7b02019-02-07 13:22:56 -07001171 std::unique_lock<std::mutex> lock(report_data->debug_report_mutex);
John Zulaufc64f97c2019-04-10 10:34:52 -06001172 auto *label_state = GetLoggingLabelState(&report_data->debugUtilsQueueLabels, queue, /* insert */ true);
1173
1174 // TODO: Determine if this is the correct semantics for insert label vs. begin/end, perserving existing semantics for now
1175 label_state->insert_label = LoggingLabel(label_info);
Mark Young6ba8abe2017-11-09 10:37:04 -07001176}
1177
Mark Young8504ba62018-03-21 13:35:34 -06001178static inline void BeginCmdDebugUtilsLabel(debug_report_data *report_data, VkCommandBuffer command_buffer,
1179 const VkDebugUtilsLabelEXT *label_info) {
Mark Lobodzinski25ac7b02019-02-07 13:22:56 -07001180 std::unique_lock<std::mutex> lock(report_data->debug_report_mutex);
Mark Young6ba8abe2017-11-09 10:37:04 -07001181 if (nullptr != label_info && nullptr != label_info->pLabelName) {
John Zulaufc64f97c2019-04-10 10:34:52 -06001182 auto *label_state = GetLoggingLabelState(&report_data->debugUtilsCmdBufLabels, command_buffer, /* insert */ true);
1183 assert(label_state);
1184 label_state->labels.push_back(LoggingLabel(label_info));
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();
Mark Young6ba8abe2017-11-09 10:37:04 -07001188 }
1189}
1190
Mark Young8504ba62018-03-21 13:35:34 -06001191static inline void EndCmdDebugUtilsLabel(debug_report_data *report_data, VkCommandBuffer command_buffer) {
Mark Lobodzinski25ac7b02019-02-07 13:22:56 -07001192 std::unique_lock<std::mutex> lock(report_data->debug_report_mutex);
John Zulaufc64f97c2019-04-10 10:34:52 -06001193 auto *label_state = GetLoggingLabelState(&report_data->debugUtilsCmdBufLabels, command_buffer, /* insert */ false);
1194 if (label_state) {
1195 // Pop the normal item
1196 if (!label_state->labels.empty()) {
1197 label_state->labels.pop_back();
Mark Young6ba8abe2017-11-09 10:37:04 -07001198 }
John Zulaufc64f97c2019-04-10 10:34:52 -06001199
1200 // TODO: Determine if this is the correct semantics for insert label vs. begin/end, perserving existing semantics for now
1201 label_state->insert_label.Reset();
Mark Young6ba8abe2017-11-09 10:37:04 -07001202 }
1203}
1204
Mark Young8504ba62018-03-21 13:35:34 -06001205static inline void InsertCmdDebugUtilsLabel(debug_report_data *report_data, VkCommandBuffer command_buffer,
1206 const VkDebugUtilsLabelEXT *label_info) {
Mark Lobodzinski25ac7b02019-02-07 13:22:56 -07001207 std::unique_lock<std::mutex> lock(report_data->debug_report_mutex);
John Zulaufc64f97c2019-04-10 10:34:52 -06001208 auto *label_state = GetLoggingLabelState(&report_data->debugUtilsCmdBufLabels, command_buffer, /* insert */ true);
1209 assert(label_state);
1210
1211 // TODO: Determine if this is the correct semantics for insert label vs. begin/end, perserving existing semantics for now
1212 label_state->insert_label = LoggingLabel(label_info);
1213}
1214
1215// Current tracking beyond a single command buffer scope is incorrect, and even when it is we need to be able to clean up
1216static inline void ResetCmdDebugUtilsLabel(debug_report_data *report_data, VkCommandBuffer command_buffer) {
1217 std::unique_lock<std::mutex> lock(report_data->debug_report_mutex);
1218 auto *label_state = GetLoggingLabelState(&report_data->debugUtilsCmdBufLabels, command_buffer, /* insert */ false);
1219 if (label_state) {
1220 label_state->labels.clear();
1221 label_state->insert_label.Reset();
Mark Young6ba8abe2017-11-09 10:37:04 -07001222 }
1223}
Mark Lobodzinski863d5de2017-05-22 10:10:07 -06001224
John Zulaufc64f97c2019-04-10 10:34:52 -06001225static inline void EraseCmdDebugUtilsLabel(debug_report_data *report_data, VkCommandBuffer command_buffer) {
1226 report_data->debugUtilsCmdBufLabels.erase(command_buffer);
1227}
1228
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001229#endif // LAYER_LOGGING_H