blob: d21e9ffa5c7e3b452924e32526e9c0199a37f3e2 [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>
Ricardo Garcia008cebb2019-05-06 11:10:08 +020041#include <utility>
John Zulaufc64f97c2019-04-10 10:34:52 -060042
43#include "vk_typemap_helper.h"
Mark Lobodzinskib87f9022016-05-24 16:04:56 -060044#include "vk_loader_layer.h"
Tobin Ehlis2d9deec2016-04-21 14:19:26 -060045#include "vk_layer_config.h"
Tobin Ehlisa0cb02e2015-07-03 10:15:26 -060046#include "vk_layer_data.h"
Tobin Ehlis2d9deec2016-04-21 14:19:26 -060047#include "vk_loader_platform.h"
48#include "vulkan/vk_layer.h"
Mark Young6ba8abe2017-11-09 10:37:04 -070049#include "vk_object_types.h"
John Zulauf2c2ccd42019-04-05 13:13:13 -060050#include "cast_utils.h"
Mark Lobodzinski487a0d12018-03-30 10:09:03 -060051#include "vk_validation_error_messages.h"
Lenny Komow4c0da772018-07-03 10:17:21 -060052#include "vk_layer_dispatch_table.h"
Mark Young6ba8abe2017-11-09 10:37:04 -070053
Dave Houlton57ae22f2018-05-18 16:20:52 -060054// Suppress unused warning on Linux
55#if defined(__GNUC__)
Dave Houltoncfcecbf2018-05-31 16:20:57 -060056#define DECORATE_UNUSED __attribute__((unused))
57#else
58#define DECORATE_UNUSED
Dave Houlton57ae22f2018-05-18 16:20:52 -060059#endif
60
Mark Lobodzinski706e15a2018-12-12 15:35:29 -070061#if defined __ANDROID__
62#include <android/log.h>
63#define LOGCONSOLE(...) ((void)__android_log_print(ANDROID_LOG_INFO, "VALIDATION", __VA_ARGS__))
64#else
65#define LOGCONSOLE(...) \
66 { \
67 printf(__VA_ARGS__); \
68 printf("\n"); \
69 }
70#endif
71
Dave Houltoncfcecbf2018-05-31 16:20:57 -060072static const char DECORATE_UNUSED *kVUIDUndefined = "VUID_Undefined";
Dave Houlton8e9f6542018-05-18 12:18:22 -060073
Dave Houltoncfcecbf2018-05-31 16:20:57 -060074#undef DECORATE_UNUSED
Dave Houlton57ae22f2018-05-18 16:20:52 -060075
Mark Young6ba8abe2017-11-09 10:37:04 -070076// TODO: Could be autogenerated for the specific handles for extra type safety...
77template <typename HANDLE_T>
John Zulauf2c2ccd42019-04-05 13:13:13 -060078static inline uint64_t HandleToUint64(HANDLE_T h) {
79 return CastToUint64<HANDLE_T>(h);
Mark Young6ba8abe2017-11-09 10:37:04 -070080}
81
82static inline uint64_t HandleToUint64(uint64_t h) { return h; }
83
84// Data we store per label for logging
John Zulaufc64f97c2019-04-10 10:34:52 -060085struct LoggingLabel {
Mark Young6ba8abe2017-11-09 10:37:04 -070086 std::string name;
John Zulaufc64f97c2019-04-10 10:34:52 -060087 std::array<float, 4> color;
88
89 void Reset() { *this = LoggingLabel(); }
90 bool Empty() const { return name.empty(); }
91
92 VkDebugUtilsLabelEXT Export() const {
93 auto out = lvl_init_struct<VkDebugUtilsLabelEXT>();
94 out.pLabelName = name.c_str();
95 std::copy(color.cbegin(), color.cend(), out.color);
96 return out;
97 };
98
Jeremy Hayesd0549f62019-06-05 10:15:36 -060099 LoggingLabel() : name(), color({{0.f, 0.f, 0.f, 0.f}}) {}
John Zulaufc64f97c2019-04-10 10:34:52 -0600100 LoggingLabel(const VkDebugUtilsLabelEXT *label_info) {
101 if (label_info && label_info->pLabelName) {
102 name = label_info->pLabelName;
103 std::copy_n(std::begin(label_info->color), 4, color.begin());
104 } else {
105 Reset();
106 }
107 }
Ricardo Garcia008cebb2019-05-06 11:10:08 +0200108
109 LoggingLabel(const LoggingLabel &) = default;
110 LoggingLabel &operator=(const LoggingLabel &) = default;
111 LoggingLabel &operator=(LoggingLabel &&) = default;
112 LoggingLabel(LoggingLabel &&) = default;
113
114 template <typename Name, typename Vec>
115 LoggingLabel(Name &&name_, Vec &&vec_) : name(std::forward<Name>(name_)), color(std::forward<Vec>(vec_)) {}
John Zulaufc64f97c2019-04-10 10:34:52 -0600116};
117
118struct LoggingLabelState {
119 std::vector<LoggingLabel> labels;
120 LoggingLabel insert_label;
121
122 // Export the labels, but in reverse order since we want the most recent at the top.
123 std::vector<VkDebugUtilsLabelEXT> Export() const {
124 size_t count = labels.size() + (insert_label.Empty() ? 0 : 1);
125 std::vector<VkDebugUtilsLabelEXT> out(count);
126
127 if (!count) return out;
128
129 size_t index = count - 1;
130 if (!insert_label.Empty()) {
131 out[index--] = insert_label.Export();
132 }
133 for (const auto &label : labels) {
134 out[index--] = label.Export();
135 }
136 return out;
137 }
138};
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600139
locke-lunarg58c086f2019-06-14 18:05:26 -0600140static inline int string_sprintf(std::string *output, const char *fmt, ...);
141
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600142typedef struct _debug_report_data {
Mark Lobodzinski12813302019-02-07 15:03:06 -0700143 VkLayerDbgFunctionNode *debug_callback_list{nullptr};
144 VkLayerDbgFunctionNode *default_debug_callback_list{nullptr};
145 VkDebugUtilsMessageSeverityFlagsEXT active_severities{0};
146 VkDebugUtilsMessageTypeFlagsEXT active_types{0};
147 bool g_DEBUG_REPORT{false};
148 bool g_DEBUG_UTILS{false};
149 bool queueLabelHasInsert{false};
150 bool cmdBufLabelHasInsert{false};
locke-lunarg0261e742019-08-13 21:47:18 -0600151 std::unordered_map<uint64_t, std::string> debugObjectNameMap;
152 std::unordered_map<uint64_t, std::string> debugUtilsObjectNameMap;
John Zulaufc64f97c2019-04-10 10:34:52 -0600153 std::unordered_map<VkQueue, std::unique_ptr<LoggingLabelState>> debugUtilsQueueLabels;
154 std::unordered_map<VkCommandBuffer, std::unique_ptr<LoggingLabelState>> debugUtilsCmdBufLabels;
Mark Lobodzinski25ac7b02019-02-07 13:22:56 -0700155 // This mutex is defined as mutable since the normal usage for a debug report object is as 'const'. The mutable keyword allows
156 // the layers to continue this pattern, but also allows them to use/change this specific member for synchronization purposes.
157 mutable std::mutex debug_report_mutex;
Mark Lobodzinskiaaeed7c2019-02-07 10:19:40 -0700158
159 void DebugReportSetUtilsObjectName(const VkDebugUtilsObjectNameInfoEXT *pNameInfo) {
Mark Lobodzinski25ac7b02019-02-07 13:22:56 -0700160 std::unique_lock<std::mutex> lock(debug_report_mutex);
locke-lunarg0261e742019-08-13 21:47:18 -0600161 if (pNameInfo->pObjectName) {
162 debugUtilsObjectNameMap[pNameInfo->objectHandle] = pNameInfo->pObjectName;
Mark Lobodzinskiaaeed7c2019-02-07 10:19:40 -0700163 } else {
Mark Lobodzinski12813302019-02-07 15:03:06 -0700164 debugUtilsObjectNameMap.erase(pNameInfo->objectHandle);
Mark Lobodzinskiaaeed7c2019-02-07 10:19:40 -0700165 }
166 }
167
168 void DebugReportSetMarkerObjectName(const VkDebugMarkerObjectNameInfoEXT *pNameInfo) {
Mark Lobodzinski25ac7b02019-02-07 13:22:56 -0700169 std::unique_lock<std::mutex> lock(debug_report_mutex);
locke-lunarg0261e742019-08-13 21:47:18 -0600170 if (pNameInfo->pObjectName) {
171 debugObjectNameMap[pNameInfo->object] = pNameInfo->pObjectName;
Mark Lobodzinskiaaeed7c2019-02-07 10:19:40 -0700172 } else {
Mark Lobodzinski12813302019-02-07 15:03:06 -0700173 debugObjectNameMap.erase(pNameInfo->object);
Mark Lobodzinskiaaeed7c2019-02-07 10:19:40 -0700174 }
175 }
176
177 std::string DebugReportGetUtilsObjectName(const uint64_t object) const {
178 std::string label = "";
Mark Lobodzinski61a6d622019-02-14 14:11:24 -0700179 const auto utils_name_iter = debugUtilsObjectNameMap.find(object);
Mark Lobodzinski12813302019-02-07 15:03:06 -0700180 if (utils_name_iter != debugUtilsObjectNameMap.end()) {
locke-lunarg0261e742019-08-13 21:47:18 -0600181 label = utils_name_iter->second;
Mark Lobodzinskiaaeed7c2019-02-07 10:19:40 -0700182 }
183 return label;
184 }
185
186 std::string DebugReportGetMarkerObjectName(const uint64_t object) const {
187 std::string label = "";
Mark Lobodzinski61a6d622019-02-14 14:11:24 -0700188 const auto marker_name_iter = debugObjectNameMap.find(object);
Mark Lobodzinski12813302019-02-07 15:03:06 -0700189 if (marker_name_iter != debugObjectNameMap.end()) {
locke-lunarg0261e742019-08-13 21:47:18 -0600190 label = marker_name_iter->second;
Mark Lobodzinskiaaeed7c2019-02-07 10:19:40 -0700191 }
192 return label;
193 }
194
locke-lunarg58c086f2019-06-14 18:05:26 -0600195 std::string FormatHandle(const char *handle_type_name, uint64_t handle) const {
196 std::string handle_name = DebugReportGetUtilsObjectName(handle);
197 if (handle_name.empty()) {
198 handle_name = DebugReportGetMarkerObjectName(handle);
199 }
Locke26335512019-02-18 13:49:02 -0700200
locke-lunarg58c086f2019-06-14 18:05:26 -0600201 std::string ret;
202 string_sprintf(&ret, "%s 0x%" PRIxLEAST64 "[%s]", handle_type_name, handle, handle_name.c_str());
Locke26335512019-02-18 13:49:02 -0700203 return ret;
204 }
205
John Zulauf4fea6622019-04-01 11:38:18 -0600206 std::string FormatHandle(const VulkanTypedHandle &handle) const {
207 return FormatHandle(object_string[handle.type], handle.handle);
208 }
209
John Zulauf2c2ccd42019-04-05 13:13:13 -0600210 template <typename HANDLE_T>
locke-lunarg58c086f2019-06-14 18:05:26 -0600211 std::string FormatHandle(HANDLE_T handle) const {
212 return FormatHandle(VkHandleInfo<HANDLE_T>::Typename(), HandleToUint64(handle));
John Zulauf2c2ccd42019-04-05 13:13:13 -0600213 }
214
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600215} debug_report_data;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600216
Tobin Ehlis8d6acde2017-02-08 07:40:40 -0700217template debug_report_data *GetLayerDataPtr<debug_report_data>(void *data_key,
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700218 std::unordered_map<void *, debug_report_data *> &data_map);
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600219
Mark Young6ba8abe2017-11-09 10:37:04 -0700220static inline void DebugReportFlagsToAnnotFlags(VkDebugReportFlagsEXT dr_flags, bool default_flag_is_spec,
221 VkDebugUtilsMessageSeverityFlagsEXT *da_severity,
222 VkDebugUtilsMessageTypeFlagsEXT *da_type) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700223 *da_severity = 0;
Mark Youngfbaae712018-10-04 14:33:50 -0600224 *da_type = 0;
Mark Youngc2347792018-05-30 08:41:25 -0600225 // If it's explicitly listed as a performance warning, treat it as a performance message.
226 // Otherwise, treat it as a validation issue.
227 if ((dr_flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) != 0) {
Mark Youngfbaae712018-10-04 14:33:50 -0600228 *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
229 *da_severity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
Mark Youngc2347792018-05-30 08:41:25 -0600230 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700231 if ((dr_flags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) != 0) {
Mark Youngfbaae712018-10-04 14:33:50 -0600232 *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 -0700233 *da_severity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT;
Mark Young6ba8abe2017-11-09 10:37:04 -0700234 }
235 if ((dr_flags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) != 0) {
Mark Youngfbaae712018-10-04 14:33:50 -0600236 *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;
Mark Young6ba8abe2017-11-09 10:37:04 -0700237 *da_severity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
Mark Young6ba8abe2017-11-09 10:37:04 -0700238 }
Mark Youngfbaae712018-10-04 14:33:50 -0600239 if ((dr_flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) != 0) {
240 *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;
Mark Young6ba8abe2017-11-09 10:37:04 -0700241 *da_severity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
242 }
243 if ((dr_flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) != 0) {
Mark Youngfbaae712018-10-04 14:33:50 -0600244 *da_type |= VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;
Mark Young6ba8abe2017-11-09 10:37:04 -0700245 *da_severity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
246 }
247}
248
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600249// Forward Declarations
Mark Young6ba8abe2017-11-09 10:37:04 -0700250static inline bool debug_log_msg(const debug_report_data *debug_data, VkFlags msg_flags, VkDebugReportObjectTypeEXT object_type,
Dave Houlton407df732018-08-06 17:58:24 -0600251 uint64_t src_object, size_t location, const char *layer_prefix, const char *message,
252 const char *text_vuid);
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600253
254// Add a debug message callback node structure to the specified callback linked list
Mark Young6ba8abe2017-11-09 10:37:04 -0700255static inline void AddDebugCallbackNode(debug_report_data *debug_data, VkLayerDbgFunctionNode **list_head,
256 VkLayerDbgFunctionNode *new_node) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600257 new_node->pNext = *list_head;
258 *list_head = new_node;
259}
260
Mark Young6ba8abe2017-11-09 10:37:04 -0700261// Remove specified debug messenger node structure from the specified linked list
262static inline void RemoveDebugUtilsMessenger(debug_report_data *debug_data, VkLayerDbgFunctionNode **list_head,
263 VkDebugUtilsMessengerEXT messenger) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600264 VkLayerDbgFunctionNode *cur_callback = *list_head;
Mark Youngfbaae712018-10-04 14:33:50 -0600265 VkLayerDbgFunctionNode *prev_callback = nullptr;
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600266 bool matched = false;
Mark Young6ba8abe2017-11-09 10:37:04 -0700267 VkFlags local_severities = 0;
268 VkFlags local_types = 0;
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600269
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600270 while (cur_callback) {
Mark Youngfbaae712018-10-04 14:33:50 -0600271 if (cur_callback->is_messenger) {
272 // If it's actually a messenger, then set it up for deletion.
273 if (cur_callback->messenger.messenger == messenger) {
274 matched = true;
275 if (*list_head == cur_callback) {
276 *list_head = cur_callback->pNext;
277 } else {
278 assert(nullptr != prev_callback);
279 prev_callback->pNext = cur_callback->pNext;
280 }
281 debug_log_msg(debug_data, VK_DEBUG_REPORT_DEBUG_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT,
282 reinterpret_cast<uint64_t &>(cur_callback->messenger.messenger), 0, "DebugUtilsMessenger",
283 "Destroyed messenger\n", kVUIDUndefined);
284 } else {
285 // If it's not the one we're looking for, just keep the types/severities
286 local_severities |= cur_callback->messenger.messageSeverity;
287 local_types |= cur_callback->messenger.messageType;
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600288 }
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600289 } else {
Mark Youngfbaae712018-10-04 14:33:50 -0600290 // If it's not a messenger, just keep the types/severities
291 VkFlags this_severities = 0;
292 VkFlags this_types = 0;
293 DebugReportFlagsToAnnotFlags(cur_callback->report.msgFlags, true, &this_severities, &this_types);
294 local_severities |= this_severities;
295 local_types |= this_types;
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600296 }
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600297 if (matched) {
Mark Youngfbaae712018-10-04 14:33:50 -0600298 free(cur_callback);
299 matched = false;
300 // Intentionally keep the last prev_callback, but select the proper cur_callback
301 if (nullptr != prev_callback) {
302 cur_callback = prev_callback->pNext;
303 } else {
304 cur_callback = *list_head;
305 }
306 } else {
307 prev_callback = cur_callback;
308 cur_callback = cur_callback->pNext;
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600309 }
310 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700311 debug_data->active_severities = local_severities;
312 debug_data->active_types = local_types;
313}
314
315// Remove specified debug message callback node structure from the specified callback linked list
316static inline void RemoveDebugUtilsMessageCallback(debug_report_data *debug_data, VkLayerDbgFunctionNode **list_head,
317 VkDebugReportCallbackEXT callback) {
318 VkLayerDbgFunctionNode *cur_callback = *list_head;
Mark Youngfbaae712018-10-04 14:33:50 -0600319 VkLayerDbgFunctionNode *prev_callback = nullptr;
Mark Young6ba8abe2017-11-09 10:37:04 -0700320 bool matched = false;
321 VkFlags local_severities = 0;
322 VkFlags local_types = 0;
323
324 while (cur_callback) {
Mark Youngfbaae712018-10-04 14:33:50 -0600325 if (!cur_callback->is_messenger) {
326 // If it's actually a callback, then set it up for deletion.
327 if (cur_callback->report.msgCallback == callback) {
328 matched = true;
329 if (*list_head == cur_callback) {
330 *list_head = cur_callback->pNext;
331 } else {
332 assert(nullptr != prev_callback);
333 prev_callback->pNext = cur_callback->pNext;
334 }
335 debug_log_msg(debug_data, VK_DEBUG_REPORT_DEBUG_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT,
336 reinterpret_cast<uint64_t &>(cur_callback->report.msgCallback), 0, "DebugReport",
337 "Destroyed callback\n", kVUIDUndefined);
338 } else {
339 // If it's not the one we're looking for, just keep the types/severities
340 VkFlags this_severities = 0;
341 VkFlags this_types = 0;
342 DebugReportFlagsToAnnotFlags(cur_callback->report.msgFlags, true, &this_severities, &this_types);
343 local_severities |= this_severities;
344 local_types |= this_types;
Mark Young6ba8abe2017-11-09 10:37:04 -0700345 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700346 } else {
Mark Youngfbaae712018-10-04 14:33:50 -0600347 // If it's not a callback, just keep the types/severities
348 local_severities |= cur_callback->messenger.messageSeverity;
349 local_types |= cur_callback->messenger.messageType;
Mark Young6ba8abe2017-11-09 10:37:04 -0700350 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700351 if (matched) {
Mark Youngfbaae712018-10-04 14:33:50 -0600352 free(cur_callback);
353 matched = false;
354 // Intentionally keep the last prev_callback, but select the proper cur_callback
355 if (nullptr != prev_callback) {
356 cur_callback = prev_callback->pNext;
357 } else {
358 cur_callback = *list_head;
359 }
360 } else {
361 prev_callback = cur_callback;
362 cur_callback = cur_callback->pNext;
Mark Young6ba8abe2017-11-09 10:37:04 -0700363 }
364 }
365 debug_data->active_severities = local_severities;
366 debug_data->active_types = local_types;
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600367}
368
369// Removes all debug callback function nodes from the specified callback linked lists and frees their resources
370static inline void RemoveAllMessageCallbacks(debug_report_data *debug_data, VkLayerDbgFunctionNode **list_head) {
371 VkLayerDbgFunctionNode *current_callback = *list_head;
372 VkLayerDbgFunctionNode *prev_callback = current_callback;
373
374 while (current_callback) {
375 prev_callback = current_callback->pNext;
Mark Young6ba8abe2017-11-09 10:37:04 -0700376 if (!current_callback->is_messenger) {
377 debug_log_msg(debug_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT,
Dave Houlton407df732018-08-06 17:58:24 -0600378 (uint64_t)current_callback->report.msgCallback, 0, "DebugReport",
379 "Debug Report callbacks not removed before DestroyInstance", kVUIDUndefined);
Mark Young6ba8abe2017-11-09 10:37:04 -0700380 } else {
381 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 -0600382 (uint64_t)current_callback->messenger.messenger, 0, "Messenger",
383 "Debug messengers not removed before DestroyInstance", kVUIDUndefined);
Mark Young6ba8abe2017-11-09 10:37:04 -0700384 }
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600385 free(current_callback);
386 current_callback = prev_callback;
387 }
388 *list_head = NULL;
389}
390
Mark Young6ba8abe2017-11-09 10:37:04 -0700391static inline bool debug_log_msg(const debug_report_data *debug_data, VkFlags msg_flags, VkDebugReportObjectTypeEXT object_type,
Dave Houlton407df732018-08-06 17:58:24 -0600392 uint64_t src_object, size_t location, const char *layer_prefix, const char *message,
393 const char *text_vuid) {
Dustin Graves8f1eab92016-04-05 09:41:17 -0600394 bool bail = false;
Mark Young6ba8abe2017-11-09 10:37:04 -0700395 VkLayerDbgFunctionNode *layer_dbg_node = NULL;
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600396
Mark Lobodzinski55a197f2016-06-21 15:54:57 -0600397 if (debug_data->debug_callback_list != NULL) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700398 layer_dbg_node = debug_data->debug_callback_list;
Mark Lobodzinski55a197f2016-06-21 15:54:57 -0600399 } else {
Mark Young6ba8abe2017-11-09 10:37:04 -0700400 layer_dbg_node = debug_data->default_debug_callback_list;
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600401 }
402
Mark Young6ba8abe2017-11-09 10:37:04 -0700403 VkDebugUtilsMessageSeverityFlagsEXT severity;
404 VkDebugUtilsMessageTypeFlagsEXT types;
405 VkDebugUtilsMessengerCallbackDataEXT callback_data;
406 VkDebugUtilsObjectNameInfoEXT object_name_info;
407
408 // Convert the info to the VK_EXT_debug_utils form in case we need it.
409 DebugReportFlagsToAnnotFlags(msg_flags, true, &severity, &types);
410 object_name_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
411 object_name_info.pNext = NULL;
412 object_name_info.objectType = convertDebugReportObjectToCoreObject(object_type);
413 object_name_info.objectHandle = (uint64_t)(uintptr_t)src_object;
414 object_name_info.pObjectName = NULL;
Mark Lobodzinski5d98ba12019-03-25 13:35:01 -0600415 std::string object_label = {};
Mark Young6ba8abe2017-11-09 10:37:04 -0700416
417 callback_data.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT;
418 callback_data.pNext = NULL;
419 callback_data.flags = 0;
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700420 callback_data.pMessageIdName = text_vuid;
Dave Houlton407df732018-08-06 17:58:24 -0600421 callback_data.messageIdNumber = 0; // deprecated, validation layers use only the pMessageIdName
Mark Young6ba8abe2017-11-09 10:37:04 -0700422 callback_data.pMessage = message;
423 callback_data.queueLabelCount = 0;
424 callback_data.pQueueLabels = NULL;
425 callback_data.cmdBufLabelCount = 0;
426 callback_data.pCmdBufLabels = NULL;
427 callback_data.objectCount = 1;
428 callback_data.pObjects = &object_name_info;
429
John Zulaufc64f97c2019-04-10 10:34:52 -0600430 std::vector<VkDebugUtilsLabelEXT> queue_labels;
431 std::vector<VkDebugUtilsLabelEXT> cmd_buf_labels;
Mark Young6ba8abe2017-11-09 10:37:04 -0700432 std::string new_debug_report_message = "";
433 std::ostringstream oss;
Mark Young6ba8abe2017-11-09 10:37:04 -0700434
435 if (0 != src_object) {
Mark Young8504ba62018-03-21 13:35:34 -0600436 oss << "Object: 0x" << std::hex << src_object;
Mark Young6ba8abe2017-11-09 10:37:04 -0700437 // If this is a queue, add any queue labels to the callback data.
438 if (VK_OBJECT_TYPE_QUEUE == object_name_info.objectType) {
Mark Lobodzinski12813302019-02-07 15:03:06 -0700439 auto label_iter = debug_data->debugUtilsQueueLabels.find(reinterpret_cast<VkQueue>(src_object));
440 if (label_iter != debug_data->debugUtilsQueueLabels.end()) {
John Zulaufc64f97c2019-04-10 10:34:52 -0600441 queue_labels = label_iter->second->Export();
442 callback_data.queueLabelCount = static_cast<uint32_t>(queue_labels.size());
443 callback_data.pQueueLabels = queue_labels.empty() ? nullptr : queue_labels.data();
Mark Young6ba8abe2017-11-09 10:37:04 -0700444 }
445 // If this is a command buffer, add any command buffer labels to the callback data.
446 } else if (VK_OBJECT_TYPE_COMMAND_BUFFER == object_name_info.objectType) {
Mark Lobodzinski12813302019-02-07 15:03:06 -0700447 auto label_iter = debug_data->debugUtilsCmdBufLabels.find(reinterpret_cast<VkCommandBuffer>(src_object));
448 if (label_iter != debug_data->debugUtilsCmdBufLabels.end()) {
John Zulaufc64f97c2019-04-10 10:34:52 -0600449 cmd_buf_labels = label_iter->second->Export();
450 callback_data.cmdBufLabelCount = static_cast<uint32_t>(cmd_buf_labels.size());
451 callback_data.pCmdBufLabels = cmd_buf_labels.empty() ? nullptr : cmd_buf_labels.data();
Mark Young6ba8abe2017-11-09 10:37:04 -0700452 }
453 }
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -0700454
Mark Young6ba8abe2017-11-09 10:37:04 -0700455 // Look for any debug utils or marker names to use for this object
Mark Lobodzinski5d98ba12019-03-25 13:35:01 -0600456 object_label = debug_data->DebugReportGetUtilsObjectName(src_object);
457 if (object_label.empty()) {
458 object_label = debug_data->DebugReportGetMarkerObjectName(src_object);
Mark Young6ba8abe2017-11-09 10:37:04 -0700459 }
Mark Lobodzinski5d98ba12019-03-25 13:35:01 -0600460 if (!object_label.empty()) {
461 object_name_info.pObjectName = object_label.c_str();
462 oss << " (Name = " << object_label << " : Type = ";
Mark Young8504ba62018-03-21 13:35:34 -0600463 } else {
464 oss << " (Type = ";
Mark Young6ba8abe2017-11-09 10:37:04 -0700465 }
Mark Young8504ba62018-03-21 13:35:34 -0600466 oss << std::to_string(object_type) << ")";
467 } else {
468 oss << "Object: VK_NULL_HANDLE (Type = " << std::to_string(object_type) << ")";
Mark Young6ba8abe2017-11-09 10:37:04 -0700469 }
470 new_debug_report_message += oss.str();
471 new_debug_report_message += " | ";
472 new_debug_report_message += message;
473
474 while (layer_dbg_node) {
Mark Young8504ba62018-03-21 13:35:34 -0600475 // If the app uses the VK_EXT_debug_report extension, call all of those registered callbacks.
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700476 if (!layer_dbg_node->is_messenger && (layer_dbg_node->report.msgFlags & msg_flags)) {
477 if (text_vuid != nullptr) {
478 // If a text vuid is supplied for the old debug report extension, prepend it to the message string
479 new_debug_report_message.insert(0, " ] ");
480 new_debug_report_message.insert(0, text_vuid);
481 new_debug_report_message.insert(0, " [ ");
482 }
483
Dave Houlton407df732018-08-06 17:58:24 -0600484 if (layer_dbg_node->report.pfnMsgCallback(msg_flags, object_type, src_object, location, 0, layer_prefix,
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700485 new_debug_report_message.c_str(), layer_dbg_node->pUserData)) {
486 bail = true;
487 }
Mark Young8504ba62018-03-21 13:35:34 -0600488 // If the app uses the VK_EXT_debug_utils extension, call all of those registered callbacks.
Mark Young6ba8abe2017-11-09 10:37:04 -0700489 } else if (layer_dbg_node->is_messenger && (layer_dbg_node->messenger.messageSeverity & severity) &&
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700490 (layer_dbg_node->messenger.messageType & types)) {
491 if (layer_dbg_node->messenger.pfnUserCallback(static_cast<VkDebugUtilsMessageSeverityFlagBitsEXT>(severity), types,
492 &callback_data, layer_dbg_node->pUserData)) {
493 bail = true;
494 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700495 }
496 layer_dbg_node = layer_dbg_node->pNext;
497 }
498
Mark Young6ba8abe2017-11-09 10:37:04 -0700499 return bail;
500}
501
502static inline void DebugAnnotFlagsToReportFlags(VkDebugUtilsMessageSeverityFlagBitsEXT da_severity,
503 VkDebugUtilsMessageTypeFlagsEXT da_type, VkDebugReportFlagsEXT *dr_flags) {
504 *dr_flags = 0;
505
506 if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) != 0) {
507 *dr_flags |= VK_DEBUG_REPORT_ERROR_BIT_EXT;
508 } else if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) != 0) {
509 if ((da_type & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT) != 0) {
510 *dr_flags |= VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
511 } else {
512 *dr_flags |= VK_DEBUG_REPORT_WARNING_BIT_EXT;
513 }
514 } else if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) != 0) {
515 *dr_flags |= VK_DEBUG_REPORT_INFORMATION_BIT_EXT;
516 } else if ((da_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) != 0) {
517 *dr_flags |= VK_DEBUG_REPORT_DEBUG_BIT_EXT;
518 }
519}
520
521static inline bool debug_messenger_log_msg(const debug_report_data *debug_data,
522 VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
523 VkDebugUtilsMessageTypeFlagsEXT message_type,
Shannon McPherson7fbbe362018-12-03 11:57:42 -0700524 VkDebugUtilsMessengerCallbackDataEXT *callback_data,
525 const VkDebugUtilsMessengerEXT *messenger) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700526 bool bail = false;
527 VkLayerDbgFunctionNode *layer_dbg_node = NULL;
528
529 if (debug_data->debug_callback_list != NULL) {
530 layer_dbg_node = debug_data->debug_callback_list;
531 } else {
532 layer_dbg_node = debug_data->default_debug_callback_list;
533 }
534
535 VkDebugReportFlagsEXT object_flags = 0;
536
537 DebugAnnotFlagsToReportFlags(message_severity, message_type, &object_flags);
538
Shannon McPherson7fbbe362018-12-03 11:57:42 -0700539 VkDebugUtilsObjectNameInfoEXT object_name_info;
540 object_name_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
541 object_name_info.pNext = NULL;
542 object_name_info.objectType = VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT;
543 object_name_info.objectHandle = HandleToUint64(*messenger);
544 object_name_info.pObjectName = NULL;
545 callback_data->pObjects = &object_name_info;
546 callback_data->objectCount = 1;
547
Mark Young6ba8abe2017-11-09 10:37:04 -0700548 while (layer_dbg_node) {
549 if (layer_dbg_node->is_messenger && (layer_dbg_node->messenger.messageSeverity & message_severity) &&
550 (layer_dbg_node->messenger.messageType & message_type)) {
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -0700551 std::string messenger_label = debug_data->DebugReportGetUtilsObjectName(object_name_info.objectHandle);
552 if (!messenger_label.empty()) {
553 object_name_info.pObjectName = messenger_label.c_str();
Mark Young6ba8abe2017-11-09 10:37:04 -0700554 }
555 if (layer_dbg_node->messenger.pfnUserCallback(message_severity, message_type, callback_data,
556 layer_dbg_node->pUserData)) {
557 bail = true;
558 }
559 } else if (!layer_dbg_node->is_messenger && layer_dbg_node->report.msgFlags & object_flags) {
John Zulauf536649b2018-05-01 13:28:27 -0600560 VkDebugReportObjectTypeEXT object_type = convertCoreObjectToDebugReportObject(callback_data->pObjects[0].objectType);
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -0700561 std::string marker_label = debug_data->DebugReportGetMarkerObjectName(object_name_info.objectHandle);
562 if (marker_label.empty()) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700563 if (layer_dbg_node->report.pfnMsgCallback(object_flags, object_type, callback_data->pObjects[0].objectHandle, 0,
564 callback_data->messageIdNumber, callback_data->pMessageIdName,
565 callback_data->pMessage, layer_dbg_node->pUserData)) {
Tony Barbour3431dac2017-06-19 16:50:37 -0600566 bail = true;
567 }
568 } else {
Mark Lobodzinskifa4d6a62019-02-07 10:23:21 -0700569 std::string newMsg = "SrcObject name = " + marker_label;
Tony Barbour3431dac2017-06-19 16:50:37 -0600570 newMsg.append(" ");
Mark Young6ba8abe2017-11-09 10:37:04 -0700571 newMsg.append(callback_data->pMessage);
572 if (layer_dbg_node->report.pfnMsgCallback(object_flags, object_type, callback_data->pObjects[0].objectHandle, 0,
573 callback_data->messageIdNumber, callback_data->pMessageIdName,
574 newMsg.c_str(), layer_dbg_node->pUserData)) {
Tony Barbour3431dac2017-06-19 16:50:37 -0600575 bail = true;
576 }
Courtney Goeltzenleuchter06640832015-09-04 13:52:24 -0600577 }
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600578 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700579 layer_dbg_node = layer_dbg_node->pNext;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600580 }
Courtney Goeltzenleuchter06640832015-09-04 13:52:24 -0600581
582 return bail;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600583}
584
Mark Young6ba8abe2017-11-09 10:37:04 -0700585static inline debug_report_data *debug_utils_create_instance(
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700586 VkLayerInstanceDispatchTable *table, VkInstance inst, uint32_t extension_count,
Mark Young6ba8abe2017-11-09 10:37:04 -0700587 const char *const *enabled_extensions) // layer or extension name to be enabled
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600588{
Mark Lobodzinski12813302019-02-07 15:03:06 -0700589 debug_report_data *debug_data = new debug_report_data;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600590 for (uint32_t i = 0; i < extension_count; i++) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700591 if (strcmp(enabled_extensions[i], VK_EXT_DEBUG_REPORT_EXTENSION_NAME) == 0) {
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600592 debug_data->g_DEBUG_REPORT = true;
Mark Young6ba8abe2017-11-09 10:37:04 -0700593 } else if (strcmp(enabled_extensions[i], VK_EXT_DEBUG_UTILS_EXTENSION_NAME) == 0) {
594 debug_data->g_DEBUG_UTILS = true;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600595 }
596 }
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600597 return debug_data;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600598}
599
Mark Young6ba8abe2017-11-09 10:37:04 -0700600static inline void layer_debug_utils_destroy_instance(debug_report_data *debug_data) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600601 if (debug_data) {
Mark Lobodzinski25ac7b02019-02-07 13:22:56 -0700602 std::unique_lock<std::mutex> lock(debug_data->debug_report_mutex);
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600603 RemoveAllMessageCallbacks(debug_data, &debug_data->default_debug_callback_list);
604 RemoveAllMessageCallbacks(debug_data, &debug_data->debug_callback_list);
Mark Lobodzinski25ac7b02019-02-07 13:22:56 -0700605 lock.unlock();
Mark Lobodzinski12813302019-02-07 15:03:06 -0700606 delete (debug_data);
Courtney Goeltzenleuchteree4027d2015-06-28 13:01:17 -0600607 }
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600608}
609
Mark Young6ba8abe2017-11-09 10:37:04 -0700610static inline debug_report_data *layer_debug_utils_create_device(debug_report_data *instance_debug_data, VkDevice device) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600611 // DEBUG_REPORT shares data between Instance and Device,
612 // so just return instance's data pointer
Courtney Goeltzenleuchterb9f0bf32015-06-14 09:50:18 -0600613 return instance_debug_data;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600614}
615
Mark Young6ba8abe2017-11-09 10:37:04 -0700616static inline void layer_debug_utils_destroy_device(VkDevice device) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600617 // Nothing to do since we're using instance data record
618}
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600619
Mark Young6ba8abe2017-11-09 10:37:04 -0700620static inline void layer_destroy_messenger_callback(debug_report_data *debug_data, VkDebugUtilsMessengerEXT messenger,
621 const VkAllocationCallbacks *allocator) {
Mark Lobodzinski25ac7b02019-02-07 13:22:56 -0700622 std::unique_lock<std::mutex> lock(debug_data->debug_report_mutex);
Mark Young6ba8abe2017-11-09 10:37:04 -0700623 RemoveDebugUtilsMessenger(debug_data, &debug_data->debug_callback_list, messenger);
624 RemoveDebugUtilsMessenger(debug_data, &debug_data->default_debug_callback_list, messenger);
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600625}
626
Mark Young6ba8abe2017-11-09 10:37:04 -0700627static inline VkResult layer_create_messenger_callback(debug_report_data *debug_data, bool default_callback,
628 const VkDebugUtilsMessengerCreateInfoEXT *create_info,
629 const VkAllocationCallbacks *allocator,
630 VkDebugUtilsMessengerEXT *messenger) {
Mark Lobodzinski25ac7b02019-02-07 13:22:56 -0700631 std::unique_lock<std::mutex> lock(debug_data->debug_report_mutex);
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700632 VkLayerDbgFunctionNode *pNewDbgFuncNode = (VkLayerDbgFunctionNode *)malloc(sizeof(VkLayerDbgFunctionNode));
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700633 if (!pNewDbgFuncNode) return VK_ERROR_OUT_OF_HOST_MEMORY;
Mark Young6ba8abe2017-11-09 10:37:04 -0700634 memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode));
635 pNewDbgFuncNode->is_messenger = true;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600636
Tobin Ehliseb7715d2015-09-21 09:36:47 -0600637 // Handle of 0 is logging_callback so use allocated Node address as unique handle
Mark Young6ba8abe2017-11-09 10:37:04 -0700638 if (!(*messenger)) *messenger = (VkDebugUtilsMessengerEXT)pNewDbgFuncNode;
639 pNewDbgFuncNode->messenger.messenger = *messenger;
640 pNewDbgFuncNode->messenger.pfnUserCallback = create_info->pfnUserCallback;
641 pNewDbgFuncNode->messenger.messageSeverity = create_info->messageSeverity;
642 pNewDbgFuncNode->messenger.messageType = create_info->messageType;
643 pNewDbgFuncNode->pUserData = create_info->pUserData;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600644
Mark Young6ba8abe2017-11-09 10:37:04 -0700645 debug_data->active_severities |= create_info->messageSeverity;
646 debug_data->active_types |= create_info->messageType;
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600647 if (default_callback) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700648 AddDebugCallbackNode(debug_data, &debug_data->default_debug_callback_list, pNewDbgFuncNode);
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600649 } else {
Mark Young6ba8abe2017-11-09 10:37:04 -0700650 AddDebugCallbackNode(debug_data, &debug_data->debug_callback_list, pNewDbgFuncNode);
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600651 }
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600652
Mark Young6ba8abe2017-11-09 10:37:04 -0700653 VkDebugUtilsMessengerCallbackDataEXT callback_data = {};
Mark Young6ba8abe2017-11-09 10:37:04 -0700654 callback_data.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT;
655 callback_data.pNext = NULL;
656 callback_data.flags = 0;
657 callback_data.pMessageIdName = "Layer Internal Message";
658 callback_data.messageIdNumber = 0;
659 callback_data.pMessage = "Added messenger";
660 callback_data.queueLabelCount = 0;
661 callback_data.pQueueLabels = NULL;
662 callback_data.cmdBufLabelCount = 0;
663 callback_data.pCmdBufLabels = NULL;
Shannon McPherson7fbbe362018-12-03 11:57:42 -0700664 callback_data.objectCount = 0;
665 callback_data.pObjects = NULL;
Mark Young6ba8abe2017-11-09 10:37:04 -0700666 debug_messenger_log_msg(debug_data, VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT,
Shannon McPherson7fbbe362018-12-03 11:57:42 -0700667 VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT, &callback_data, messenger);
Courtney Goeltzenleuchtere45acec2015-06-14 12:03:26 -0600668 return VK_SUCCESS;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600669}
670
Mark Young6ba8abe2017-11-09 10:37:04 -0700671static inline void layer_destroy_report_callback(debug_report_data *debug_data, VkDebugReportCallbackEXT callback,
672 const VkAllocationCallbacks *allocator) {
Mark Lobodzinski25ac7b02019-02-07 13:22:56 -0700673 std::unique_lock<std::mutex> lock(debug_data->debug_report_mutex);
Mark Young6ba8abe2017-11-09 10:37:04 -0700674 RemoveDebugUtilsMessageCallback(debug_data, &debug_data->debug_callback_list, callback);
675 RemoveDebugUtilsMessageCallback(debug_data, &debug_data->default_debug_callback_list, callback);
676}
677
678static inline VkResult layer_create_report_callback(debug_report_data *debug_data, bool default_callback,
679 const VkDebugReportCallbackCreateInfoEXT *create_info,
680 const VkAllocationCallbacks *allocator, VkDebugReportCallbackEXT *callback) {
Mark Lobodzinski25ac7b02019-02-07 13:22:56 -0700681 std::unique_lock<std::mutex> lock(debug_data->debug_report_mutex);
Mark Young6ba8abe2017-11-09 10:37:04 -0700682 VkLayerDbgFunctionNode *pNewDbgFuncNode = (VkLayerDbgFunctionNode *)malloc(sizeof(VkLayerDbgFunctionNode));
683 if (!pNewDbgFuncNode) {
684 return VK_ERROR_OUT_OF_HOST_MEMORY;
685 }
686 memset(pNewDbgFuncNode, 0, sizeof(VkLayerDbgFunctionNode));
687 pNewDbgFuncNode->is_messenger = false;
688
689 // Handle of 0 is logging_callback so use allocated Node address as unique handle
690 if (!(*callback)) *callback = (VkDebugReportCallbackEXT)pNewDbgFuncNode;
691 pNewDbgFuncNode->report.msgCallback = *callback;
692 pNewDbgFuncNode->report.pfnMsgCallback = create_info->pfnCallback;
693 pNewDbgFuncNode->report.msgFlags = create_info->flags;
694 pNewDbgFuncNode->pUserData = create_info->pUserData;
695
696 VkFlags local_severity = 0;
697 VkFlags local_type = 0;
698 DebugReportFlagsToAnnotFlags(create_info->flags, true, &local_severity, &local_type);
699 debug_data->active_severities |= local_severity;
700 debug_data->active_types |= local_type;
701 if (default_callback) {
702 AddDebugCallbackNode(debug_data, &debug_data->default_debug_callback_list, pNewDbgFuncNode);
703 } else {
704 AddDebugCallbackNode(debug_data, &debug_data->debug_callback_list, pNewDbgFuncNode);
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600705 }
706
Mark Young6ba8abe2017-11-09 10:37:04 -0700707 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 -0600708 "DebugReport", "Added callback", kVUIDUndefined);
Mark Young6ba8abe2017-11-09 10:37:04 -0700709 return VK_SUCCESS;
710}
711
712static inline PFN_vkVoidFunction debug_utils_get_instance_proc_addr(debug_report_data *debug_data, const char *func_name) {
713 if (!debug_data) {
714 return NULL;
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600715 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700716 if (debug_data->g_DEBUG_REPORT) {
717 if (!strcmp(func_name, "vkCreateDebugReportCallbackEXT")) {
718 return (PFN_vkVoidFunction)vkCreateDebugReportCallbackEXT;
719 }
720 if (!strcmp(func_name, "vkDestroyDebugReportCallbackEXT")) {
721 return (PFN_vkVoidFunction)vkDestroyDebugReportCallbackEXT;
722 }
723 if (!strcmp(func_name, "vkDebugReportMessageEXT")) {
724 return (PFN_vkVoidFunction)vkDebugReportMessageEXT;
725 }
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600726 }
Mark Young6ba8abe2017-11-09 10:37:04 -0700727 if (debug_data->g_DEBUG_UTILS) {
728 if (!strcmp(func_name, "vkCreateDebugUtilsMessengerEXT")) {
729 return (PFN_vkVoidFunction)vkCreateDebugUtilsMessengerEXT;
730 }
731 if (!strcmp(func_name, "vkDestroyDebugUtilsMessengerEXT")) {
732 return (PFN_vkVoidFunction)vkDestroyDebugUtilsMessengerEXT;
733 }
734 if (!strcmp(func_name, "vkSubmitDebugUtilsMessageEXT")) {
735 return (PFN_vkVoidFunction)vkSubmitDebugUtilsMessageEXT;
736 }
Courtney Goeltzenleuchter822e8d72015-11-30 15:28:25 -0700737 }
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -0600738 return NULL;
739}
740
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600741// This utility (called at vkCreateInstance() time), looks at a pNext chain.
742// It counts any VkDebugReportCallbackCreateInfoEXT structs that it finds. It
743// then allocates an array that can hold that many structs, as well as that
744// many VkDebugReportCallbackEXT handles. It then copies each
745// VkDebugReportCallbackCreateInfoEXT, and initializes each handle.
Mark Young6ba8abe2017-11-09 10:37:04 -0700746static inline VkResult layer_copy_tmp_report_callbacks(const void *pChain, uint32_t *num_callbacks,
747 VkDebugReportCallbackCreateInfoEXT **infos,
748 VkDebugReportCallbackEXT **callbacks) {
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600749 uint32_t n = *num_callbacks = 0;
750
751 const void *pNext = pChain;
752 while (pNext) {
753 // 1st, count the number VkDebugReportCallbackCreateInfoEXT:
754 if (((VkDebugReportCallbackCreateInfoEXT *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT) {
755 n++;
756 }
757 pNext = (void *)((VkDebugReportCallbackCreateInfoEXT *)pNext)->pNext;
758 }
759 if (n == 0) {
760 return VK_SUCCESS;
761 }
762
763 // 2nd, allocate memory for each VkDebugReportCallbackCreateInfoEXT:
764 VkDebugReportCallbackCreateInfoEXT *pInfos = *infos =
765 ((VkDebugReportCallbackCreateInfoEXT *)malloc(n * sizeof(VkDebugReportCallbackCreateInfoEXT)));
766 if (!pInfos) {
767 return VK_ERROR_OUT_OF_HOST_MEMORY;
768 }
769 // 3rd, allocate memory for a unique handle for each callback:
770 VkDebugReportCallbackEXT *pCallbacks = *callbacks = ((VkDebugReportCallbackEXT *)malloc(n * sizeof(VkDebugReportCallbackEXT)));
771 if (!pCallbacks) {
772 free(pInfos);
773 return VK_ERROR_OUT_OF_HOST_MEMORY;
774 }
775 // 4th, copy each VkDebugReportCallbackCreateInfoEXT for use by
776 // vkDestroyInstance, and assign a unique handle to each callback (just
777 // use the address of the copied VkDebugReportCallbackCreateInfoEXT):
778 pNext = pChain;
779 while (pNext) {
780 if (((VkInstanceCreateInfo *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT) {
781 memcpy(pInfos, pNext, sizeof(VkDebugReportCallbackCreateInfoEXT));
782 *pCallbacks++ = (VkDebugReportCallbackEXT)pInfos++;
783 }
784 pNext = (void *)((VkInstanceCreateInfo *)pNext)->pNext;
785 }
786
787 *num_callbacks = n;
788 return VK_SUCCESS;
789}
790
Mark Young6ba8abe2017-11-09 10:37:04 -0700791// This utility frees the arrays allocated by layer_copy_tmp_report_callbacks()
792static inline void layer_free_tmp_report_callbacks(VkDebugReportCallbackCreateInfoEXT *infos, VkDebugReportCallbackEXT *callbacks) {
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600793 free(infos);
794 free(callbacks);
795}
796
797// This utility enables all of the VkDebugReportCallbackCreateInfoEXT structs
Mark Young6ba8abe2017-11-09 10:37:04 -0700798// that were copied by layer_copy_tmp_report_callbacks()
799static inline VkResult layer_enable_tmp_report_callbacks(debug_report_data *debug_data, uint32_t num_callbacks,
800 VkDebugReportCallbackCreateInfoEXT *infos,
801 VkDebugReportCallbackEXT *callbacks) {
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600802 VkResult rtn = VK_SUCCESS;
803 for (uint32_t i = 0; i < num_callbacks; i++) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700804 rtn = layer_create_report_callback(debug_data, false, &infos[i], NULL, &callbacks[i]);
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600805 if (rtn != VK_SUCCESS) {
806 for (uint32_t j = 0; j < i; j++) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700807 layer_destroy_report_callback(debug_data, callbacks[j], NULL);
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600808 }
809 return rtn;
810 }
811 }
812 return rtn;
813}
814
815// This utility disables all of the VkDebugReportCallbackCreateInfoEXT structs
Mark Young6ba8abe2017-11-09 10:37:04 -0700816// that were copied by layer_copy_tmp_report_callbacks()
817static inline void layer_disable_tmp_report_callbacks(debug_report_data *debug_data, uint32_t num_callbacks,
818 VkDebugReportCallbackEXT *callbacks) {
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600819 for (uint32_t i = 0; i < num_callbacks; i++) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700820 layer_destroy_report_callback(debug_data, callbacks[i], NULL);
821 }
822}
823
824// This utility (called at vkCreateInstance() time), looks at a pNext chain.
825// It counts any VkDebugUtilsMessengerCreateInfoEXT structs that it finds. It
826// then allocates an array that can hold that many structs, as well as that
827// many VkDebugUtilsMessengerEXT handles. It then copies each
828// VkDebugUtilsMessengerCreateInfoEXT, and initializes each handle.
Mark Young8504ba62018-03-21 13:35:34 -0600829static inline VkResult layer_copy_tmp_debug_messengers(const void *pChain, uint32_t *num_messengers,
830 VkDebugUtilsMessengerCreateInfoEXT **infos,
831 VkDebugUtilsMessengerEXT **messengers) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700832 uint32_t n = *num_messengers = 0;
833
834 const void *pNext = pChain;
835 while (pNext) {
836 // 1st, count the number VkDebugUtilsMessengerCreateInfoEXT:
837 if (((VkDebugUtilsMessengerCreateInfoEXT *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT) {
838 n++;
839 }
840 pNext = (void *)((VkDebugUtilsMessengerCreateInfoEXT *)pNext)->pNext;
841 }
842 if (n == 0) {
843 return VK_SUCCESS;
844 }
845
846 // 2nd, allocate memory for each VkDebugUtilsMessengerCreateInfoEXT:
847 VkDebugUtilsMessengerCreateInfoEXT *pInfos = *infos =
848 ((VkDebugUtilsMessengerCreateInfoEXT *)malloc(n * sizeof(VkDebugUtilsMessengerCreateInfoEXT)));
849 if (!pInfos) {
850 return VK_ERROR_OUT_OF_HOST_MEMORY;
851 }
852 // 3rd, allocate memory for a unique handle for each messenger:
853 VkDebugUtilsMessengerEXT *pMessengers = *messengers =
854 ((VkDebugUtilsMessengerEXT *)malloc(n * sizeof(VkDebugUtilsMessengerEXT)));
855 if (!pMessengers) {
856 free(pInfos);
857 return VK_ERROR_OUT_OF_HOST_MEMORY;
858 }
859 // 4th, copy each VkDebugUtilsMessengerCreateInfoEXT for use by
860 // vkDestroyInstance, and assign a unique handle to each callback (just
861 // use the address of the copied VkDebugUtilsMessengerCreateInfoEXT):
862 pNext = pChain;
863 while (pNext) {
864 if (((VkInstanceCreateInfo *)pNext)->sType == VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT) {
865 memcpy(pInfos, pNext, sizeof(VkDebugUtilsMessengerCreateInfoEXT));
866 *pMessengers++ = (VkDebugUtilsMessengerEXT)pInfos++;
867 }
868 pNext = (void *)((VkInstanceCreateInfo *)pNext)->pNext;
869 }
870
871 *num_messengers = n;
872 return VK_SUCCESS;
873}
874
875// This utility frees the arrays allocated by layer_copy_tmp_debug_messengers()
Mark Young8504ba62018-03-21 13:35:34 -0600876static inline void layer_free_tmp_debug_messengers(VkDebugUtilsMessengerCreateInfoEXT *infos,
877 VkDebugUtilsMessengerEXT *messengers) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700878 free(infos);
879 free(messengers);
880}
881
882// This utility enables all of the VkDebugUtilsMessengerCreateInfoEXT structs
883// that were copied by layer_copy_tmp_debug_messengers()
Mark Young8504ba62018-03-21 13:35:34 -0600884static inline VkResult layer_enable_tmp_debug_messengers(debug_report_data *debug_data, uint32_t num_messengers,
885 VkDebugUtilsMessengerCreateInfoEXT *infos,
886 VkDebugUtilsMessengerEXT *messengers) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700887 VkResult rtn = VK_SUCCESS;
888 for (uint32_t i = 0; i < num_messengers; i++) {
889 rtn = layer_create_messenger_callback(debug_data, false, &infos[i], NULL, &messengers[i]);
890 if (rtn != VK_SUCCESS) {
891 for (uint32_t j = 0; j < i; j++) {
892 layer_destroy_messenger_callback(debug_data, messengers[j], NULL);
893 }
894 return rtn;
895 }
896 }
897 return rtn;
898}
899
900// This utility disables all of the VkDebugUtilsMessengerCreateInfoEXT structs
901// that were copied by layer_copy_tmp_debug_messengers()
Mark Young8504ba62018-03-21 13:35:34 -0600902static inline void layer_disable_tmp_debug_messengers(debug_report_data *debug_data, uint32_t num_messengers,
903 VkDebugUtilsMessengerEXT *messengers) {
Mark Young6ba8abe2017-11-09 10:37:04 -0700904 for (uint32_t i = 0; i < num_messengers; i++) {
905 layer_destroy_messenger_callback(debug_data, messengers[i], NULL);
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600906 }
907}
908
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600909// Checks if the message will get logged.
910// Allows layer to defer collecting & formating data if the
911// message will be discarded.
Mark Young6ba8abe2017-11-09 10:37:04 -0700912static inline bool will_log_msg(debug_report_data *debug_data, VkFlags msg_flags) {
913 VkFlags local_severity = 0;
914 VkFlags local_type = 0;
915 DebugReportFlagsToAnnotFlags(msg_flags, true, &local_severity, &local_type);
916 if (!debug_data || !(debug_data->active_severities & local_severity) || !(debug_data->active_types & local_type)) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600917 // Message is not wanted
Courtney Goeltzenleuchter6a564a12015-09-18 16:30:24 -0600918 return false;
919 }
920
921 return true;
922}
John Zulauf6664e272018-01-17 11:00:22 -0700923#ifndef WIN32
Mark Lobodzinski1bcbdf92018-02-07 10:00:22 -0700924static inline int string_sprintf(std::string *output, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
John Zulauf6664e272018-01-17 11:00:22 -0700925#endif
Mark Lobodzinski1bcbdf92018-02-07 10:00:22 -0700926static inline int string_sprintf(std::string *output, const char *fmt, ...) {
John Zulauf6664e272018-01-17 11:00:22 -0700927 std::string &formatted = *output;
928 va_list argptr;
929 va_start(argptr, fmt);
930 int reserve = vsnprintf(nullptr, 0, fmt, argptr);
931 va_end(argptr);
John Zulaufdeaa0132018-12-12 16:22:30 -0700932 formatted.reserve(reserve + 1); // Set the storage length long enough to hold the output + null
933 formatted.resize(reserve); // Set the *logical* length to be what vsprintf will write
John Zulauf6664e272018-01-17 11:00:22 -0700934 va_start(argptr, fmt);
935 int result = vsnprintf((char *)formatted.data(), formatted.capacity(), fmt, argptr);
936 va_end(argptr);
937 assert(result == reserve);
John Zulaufdeaa0132018-12-12 16:22:30 -0700938 assert((formatted.size() == strlen(formatted.c_str())));
John Zulauf6664e272018-01-17 11:00:22 -0700939 return result;
940}
Courtney Goeltzenleuchter6a564a12015-09-18 16:30:24 -0600941
Chris Forbes8a25bce2016-03-24 12:06:35 +1300942#ifdef WIN32
943static inline int vasprintf(char **strp, char const *fmt, va_list ap) {
944 *strp = nullptr;
945 int size = _vscprintf(fmt, ap);
946 if (size >= 0) {
Mark Lobodzinski729a8d32017-01-26 12:16:30 -0700947 *strp = (char *)malloc(size + 1);
Chris Forbes8a25bce2016-03-24 12:06:35 +1300948 if (!*strp) {
949 return -1;
950 }
Mark Lobodzinski729a8d32017-01-26 12:16:30 -0700951 _vsnprintf(*strp, size + 1, fmt, ap);
Chris Forbes8a25bce2016-03-24 12:06:35 +1300952 }
953 return size;
954}
955#endif
956
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700957// Output log message via DEBUG_REPORT. Takes format and variable arg list so that output string is only computed if a message
958// needs to be logged
Michael Lentine010f4692015-11-03 16:19:46 -0800959#ifndef WIN32
Mark Young6ba8abe2017-11-09 10:37:04 -0700960static inline bool log_msg(const debug_report_data *debug_data, VkFlags msg_flags, VkDebugReportObjectTypeEXT object_type,
Matthew Ruschb7be7442019-06-30 00:58:04 -0700961 uint64_t src_object, const std::string &vuid_text, const char *format, ...)
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700962 __attribute__((format(printf, 6, 7)));
Michael Lentine010f4692015-11-03 16:19:46 -0800963#endif
Mark Young6ba8abe2017-11-09 10:37:04 -0700964static inline bool log_msg(const debug_report_data *debug_data, VkFlags msg_flags, VkDebugReportObjectTypeEXT object_type,
Matthew Ruschb7be7442019-06-30 00:58:04 -0700965 uint64_t src_object, const std::string &vuid_text, const char *format, ...) {
Mark Lobodzinski12813302019-02-07 15:03:06 -0700966 if (!debug_data) return false;
Mark Lobodzinski25ac7b02019-02-07 13:22:56 -0700967 std::unique_lock<std::mutex> lock(debug_data->debug_report_mutex);
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700968 VkFlags local_severity = 0;
969 VkFlags local_type = 0;
970 DebugReportFlagsToAnnotFlags(msg_flags, true, &local_severity, &local_type);
971 if (!debug_data || !(debug_data->active_severities & local_severity) || !(debug_data->active_types & local_type)) {
972 // Message is not wanted
973 return false;
974 }
975
976 va_list argptr;
977 va_start(argptr, format);
978 char *str;
979 if (-1 == vasprintf(&str, format, argptr)) {
980 // On failure, glibc vasprintf leaves str undefined
981 str = nullptr;
982 }
983 va_end(argptr);
984
Dave Houlton407df732018-08-06 17:58:24 -0600985 std::string str_plus_spec_text(str ? str : "Allocation failure");
Mark Lobodzinski316c18c2018-02-21 09:48:42 -0700986
Dave Houlton407df732018-08-06 17:58:24 -0600987 // Append the spec error text to the error message, unless it's an UNASSIGNED or UNDEFINED vuid
988 if ((vuid_text.find("UNASSIGNED-") == std::string::npos) && (vuid_text.find(kVUIDUndefined) == std::string::npos)) {
Dave Houlton4d9b2f82018-10-24 18:21:06 -0600989 // Linear search makes no assumptions about the layout of the string table
990 // This is not fast, but it does not need to be at this point in the error reporting path
991 uint32_t num_vuids = sizeof(vuid_spec_text) / sizeof(vuid_spec_text_pair);
992 const char *spec_text = nullptr;
993 for (uint32_t i = 0; i < num_vuids; i++) {
994 if (0 == strcmp(vuid_text.c_str(), vuid_spec_text[i].vuid)) {
995 spec_text = vuid_spec_text[i].spec_text;
996 break;
997 }
998 }
999
1000 if (nullptr == spec_text) {
Dave Houlton407df732018-08-06 17:58:24 -06001001 // If this happens, you've hit a VUID string that isn't defined in the spec's json file
1002 // Try running 'vk_validation_stats -c' to look for invalid VUID strings in the repo code
1003 assert(0);
1004 } else {
1005 str_plus_spec_text += " The Vulkan spec states: ";
Dave Houlton4d9b2f82018-10-24 18:21:06 -06001006 str_plus_spec_text += spec_text;
Dave Houlton407df732018-08-06 17:58:24 -06001007 }
Mark Lobodzinski316c18c2018-02-21 09:48:42 -07001008 }
1009
Dave Houlton8e9f6542018-05-18 12:18:22 -06001010 // Append layer prefix with VUID string, pass in recovered legacy numerical VUID
Dave Houlton407df732018-08-06 17:58:24 -06001011 bool result = debug_log_msg(debug_data, msg_flags, object_type, src_object, 0, "Validation", str_plus_spec_text.c_str(),
1012 vuid_text.c_str());
Mark Lobodzinski316c18c2018-02-21 09:48:42 -07001013
1014 free(str);
1015 return result;
1016}
1017
Mark Young6ba8abe2017-11-09 10:37:04 -07001018static inline VKAPI_ATTR VkBool32 VKAPI_CALL report_log_callback(VkFlags msg_flags, VkDebugReportObjectTypeEXT obj_type,
1019 uint64_t src_object, size_t location, int32_t msg_code,
1020 const char *layer_prefix, const char *message, void *user_data) {
Mark Lobodzinski706e15a2018-12-12 15:35:29 -07001021 std::ostringstream msg_buffer;
Mark Young6ba8abe2017-11-09 10:37:04 -07001022 char msg_flag_string[30];
Courtney Goeltzenleuchter7d8503b2015-06-11 15:58:51 -06001023
Mark Young6ba8abe2017-11-09 10:37:04 -07001024 PrintMessageFlags(msg_flags, msg_flag_string);
Courtney Goeltzenleuchter2f25bb42015-06-14 11:29:24 -06001025
Mark Lobodzinski706e15a2018-12-12 15:35:29 -07001026 msg_buffer << layer_prefix << "(" << msg_flag_string << "): msg_code: " << msg_code << ": " << message << "\n";
1027 const std::string tmp = msg_buffer.str();
1028 const char *cstr = tmp.c_str();
1029
1030 fprintf((FILE *)user_data, "%s", cstr);
Mark Young6ba8abe2017-11-09 10:37:04 -07001031 fflush((FILE *)user_data);
Courtney Goeltzenleuchter06640832015-09-04 13:52:24 -06001032
Mark Lobodzinski706e15a2018-12-12 15:35:29 -07001033#if defined __ANDROID__
1034 LOGCONSOLE("%s", cstr);
1035#endif
1036
Courtney Goeltzenleuchter06640832015-09-04 13:52:24 -06001037 return false;
Courtney Goeltzenleuchter2f25bb42015-06-14 11:29:24 -06001038}
Courtney Goeltzenleuchter5907ac42015-10-05 14:41:34 -06001039
Mark Young6ba8abe2017-11-09 10:37:04 -07001040static inline VKAPI_ATTR VkBool32 VKAPI_CALL report_win32_debug_output_msg(VkFlags msg_flags, VkDebugReportObjectTypeEXT obj_type,
1041 uint64_t src_object, size_t location, int32_t msg_code,
1042 const char *layer_prefix, const char *message,
1043 void *user_data) {
Courtney Goeltzenleuchter5907ac42015-10-05 14:41:34 -06001044#ifdef WIN32
Mark Young6ba8abe2017-11-09 10:37:04 -07001045 char msg_flag_string[30];
Courtney Goeltzenleuchter5907ac42015-10-05 14:41:34 -06001046 char buf[2048];
1047
Mark Young6ba8abe2017-11-09 10:37:04 -07001048 PrintMessageFlags(msg_flags, msg_flag_string);
Mark Lobodzinskib1fd9d12018-03-30 14:26:00 -06001049 _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 -06001050
1051 OutputDebugString(buf);
1052#endif
1053
1054 return false;
1055}
1056
Mark Young6ba8abe2017-11-09 10:37:04 -07001057static inline VKAPI_ATTR VkBool32 VKAPI_CALL DebugBreakCallback(VkFlags msgFlags, VkDebugReportObjectTypeEXT obj_type,
1058 uint64_t src_object, size_t location, int32_t msg_code,
1059 const char *layer_prefix, const char *message, void *user_data) {
Mark Lobodzinskic9d81652017-08-10 11:01:17 -06001060#ifdef WIN32
1061 DebugBreak();
1062#else
1063 raise(SIGTRAP);
1064#endif
1065
1066 return false;
1067}
1068
Mark Lobodzinski3b7ee882019-07-03 14:43:38 -06001069static inline VKAPI_ATTR VkBool32 VKAPI_CALL MessengerBreakCallback(VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
1070 VkDebugUtilsMessageTypeFlagsEXT message_type,
1071 const VkDebugUtilsMessengerCallbackDataEXT *callback_data,
1072 void *user_data) {
1073#ifdef WIN32
1074 DebugBreak();
1075#else
1076 raise(SIGTRAP);
1077#endif
1078
1079 return false;
1080}
1081
Mark Young6ba8abe2017-11-09 10:37:04 -07001082static inline VKAPI_ATTR VkBool32 VKAPI_CALL messenger_log_callback(VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
1083 VkDebugUtilsMessageTypeFlagsEXT message_type,
1084 const VkDebugUtilsMessengerCallbackDataEXT *callback_data,
1085 void *user_data) {
Mark Lobodzinski706e15a2018-12-12 15:35:29 -07001086 std::ostringstream msg_buffer;
Mark Young6ba8abe2017-11-09 10:37:04 -07001087 char msg_severity[30];
1088 char msg_type[30];
1089
1090 PrintMessageSeverity(message_severity, msg_severity);
1091 PrintMessageType(message_type, msg_type);
1092
Mark Lobodzinski706e15a2018-12-12 15:35:29 -07001093 msg_buffer << callback_data->pMessageIdName << "(" << msg_severity << " / " << msg_type
1094 << "): msgNum: " << callback_data->messageIdNumber << " - " << callback_data->pMessage << "\n";
1095 msg_buffer << " Objects: " << callback_data->objectCount << "\n";
Mark Young8504ba62018-03-21 13:35:34 -06001096 for (uint32_t obj = 0; obj < callback_data->objectCount; ++obj) {
Mark Lobodzinski706e15a2018-12-12 15:35:29 -07001097 msg_buffer << " [" << obj << "] " << std::hex << std::showbase
1098 << HandleToUint64(callback_data->pObjects[obj].objectHandle) << ", type: " << std::dec << std::noshowbase
1099 << callback_data->pObjects[obj].objectType
1100 << ", name: " << (callback_data->pObjects[obj].pObjectName ? callback_data->pObjects[obj].pObjectName : "NULL")
1101 << "\n";
Mark Young8504ba62018-03-21 13:35:34 -06001102 }
Mark Lobodzinski706e15a2018-12-12 15:35:29 -07001103 const std::string tmp = msg_buffer.str();
1104 const char *cstr = tmp.c_str();
1105 fprintf((FILE *)user_data, "%s", cstr);
Mark Young6ba8abe2017-11-09 10:37:04 -07001106 fflush((FILE *)user_data);
1107
Mark Lobodzinski706e15a2018-12-12 15:35:29 -07001108#if defined __ANDROID__
1109 LOGCONSOLE("%s", cstr);
1110#endif
1111
Mark Young6ba8abe2017-11-09 10:37:04 -07001112 return false;
Petr Krause9388f62017-05-13 20:53:12 +02001113}
1114
Mark Young6ba8abe2017-11-09 10:37:04 -07001115static inline VKAPI_ATTR VkBool32 VKAPI_CALL messenger_win32_debug_output_msg(
1116 VkDebugUtilsMessageSeverityFlagBitsEXT message_severity, VkDebugUtilsMessageTypeFlagsEXT message_type,
1117 const VkDebugUtilsMessengerCallbackDataEXT *callback_data, void *user_data) {
1118#ifdef WIN32
Mark Lobodzinski3be125e2018-11-19 09:58:10 -07001119 std::ostringstream msg_buffer;
Mark Young6ba8abe2017-11-09 10:37:04 -07001120 char msg_severity[30];
1121 char msg_type[30];
Mark Lobodzinski863d5de2017-05-22 10:10:07 -06001122
Mark Young6ba8abe2017-11-09 10:37:04 -07001123 PrintMessageSeverity(message_severity, msg_severity);
1124 PrintMessageType(message_type, msg_type);
1125
Mark Lobodzinski3be125e2018-11-19 09:58:10 -07001126 msg_buffer << callback_data->pMessageIdName << "(" << msg_severity << " / " << msg_type
1127 << "): msgNum: " << callback_data->messageIdNumber << " - " << callback_data->pMessage << "\n";
1128 msg_buffer << " Objects: " << callback_data->objectCount << "\n";
1129
Mark Young8504ba62018-03-21 13:35:34 -06001130 for (uint32_t obj = 0; obj < callback_data->objectCount; ++obj) {
Mark Lobodzinski3be125e2018-11-19 09:58:10 -07001131 msg_buffer << " [" << obj << "] " << std::hex << std::showbase
1132 << HandleToUint64(callback_data->pObjects[obj].objectHandle) << ", type: " << std::dec << std::noshowbase
1133 << callback_data->pObjects[obj].objectType
1134 << ", name: " << (callback_data->pObjects[obj].pObjectName ? callback_data->pObjects[obj].pObjectName : "NULL")
1135 << "\n";
Mark Young8504ba62018-03-21 13:35:34 -06001136 }
Mark Lobodzinski3be125e2018-11-19 09:58:10 -07001137 const std::string tmp = msg_buffer.str();
1138 const char *cstr = tmp.c_str();
1139 OutputDebugString(cstr);
Mark Young6ba8abe2017-11-09 10:37:04 -07001140#endif
1141
1142 return false;
1143}
1144
John Zulaufc64f97c2019-04-10 10:34:52 -06001145template <typename Map>
1146static LoggingLabelState *GetLoggingLabelState(Map *map, typename Map::key_type key, bool insert) {
1147 auto iter = map->find(key);
1148 LoggingLabelState *label_state = nullptr;
1149 if (iter == map->end()) {
1150 if (insert) {
1151 // Add a label state if not present
1152 label_state = new LoggingLabelState();
1153 auto inserted = map->insert(std::make_pair(key, std::unique_ptr<LoggingLabelState>(new LoggingLabelState())));
1154 assert(inserted.second);
1155 iter = inserted.first;
1156 label_state = iter->second.get();
1157 }
1158 } else {
1159 label_state = iter->second.get();
1160 }
1161 return label_state;
Mark Young6ba8abe2017-11-09 10:37:04 -07001162}
1163
Mark Young8504ba62018-03-21 13:35:34 -06001164static inline void BeginQueueDebugUtilsLabel(debug_report_data *report_data, VkQueue queue,
1165 const VkDebugUtilsLabelEXT *label_info) {
Mark Lobodzinski25ac7b02019-02-07 13:22:56 -07001166 std::unique_lock<std::mutex> lock(report_data->debug_report_mutex);
Mark Young6ba8abe2017-11-09 10:37:04 -07001167 if (nullptr != label_info && nullptr != label_info->pLabelName) {
John Zulaufc64f97c2019-04-10 10:34:52 -06001168 auto *label_state = GetLoggingLabelState(&report_data->debugUtilsQueueLabels, queue, /* insert */ true);
1169 assert(label_state);
1170 label_state->labels.push_back(LoggingLabel(label_info));
1171
1172 // TODO: Determine if this is the correct semantics for insert label vs. begin/end, perserving existing semantics for now
1173 label_state->insert_label.Reset();
Mark Young6ba8abe2017-11-09 10:37:04 -07001174 }
1175}
1176
Mark Young8504ba62018-03-21 13:35:34 -06001177static inline void EndQueueDebugUtilsLabel(debug_report_data *report_data, VkQueue queue) {
Mark Lobodzinski25ac7b02019-02-07 13:22:56 -07001178 std::unique_lock<std::mutex> lock(report_data->debug_report_mutex);
John Zulaufc64f97c2019-04-10 10:34:52 -06001179 auto *label_state = GetLoggingLabelState(&report_data->debugUtilsQueueLabels, queue, /* insert */ false);
1180 if (label_state) {
1181 // Pop the normal item
1182 if (!label_state->labels.empty()) {
1183 label_state->labels.pop_back();
Mark Young6ba8abe2017-11-09 10:37:04 -07001184 }
John Zulaufc64f97c2019-04-10 10:34:52 -06001185
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 InsertQueueDebugUtilsLabel(debug_report_data *report_data, VkQueue queue,
1192 const VkDebugUtilsLabelEXT *label_info) {
Mark Lobodzinski25ac7b02019-02-07 13:22:56 -07001193 std::unique_lock<std::mutex> lock(report_data->debug_report_mutex);
John Zulaufc64f97c2019-04-10 10:34:52 -06001194 auto *label_state = GetLoggingLabelState(&report_data->debugUtilsQueueLabels, queue, /* insert */ true);
1195
1196 // TODO: Determine if this is the correct semantics for insert label vs. begin/end, perserving existing semantics for now
1197 label_state->insert_label = LoggingLabel(label_info);
Mark Young6ba8abe2017-11-09 10:37:04 -07001198}
1199
Mark Young8504ba62018-03-21 13:35:34 -06001200static inline void BeginCmdDebugUtilsLabel(debug_report_data *report_data, VkCommandBuffer command_buffer,
1201 const VkDebugUtilsLabelEXT *label_info) {
Mark Lobodzinski25ac7b02019-02-07 13:22:56 -07001202 std::unique_lock<std::mutex> lock(report_data->debug_report_mutex);
Mark Young6ba8abe2017-11-09 10:37:04 -07001203 if (nullptr != label_info && nullptr != label_info->pLabelName) {
John Zulaufc64f97c2019-04-10 10:34:52 -06001204 auto *label_state = GetLoggingLabelState(&report_data->debugUtilsCmdBufLabels, command_buffer, /* insert */ true);
1205 assert(label_state);
1206 label_state->labels.push_back(LoggingLabel(label_info));
1207
1208 // TODO: Determine if this is the correct semantics for insert label vs. begin/end, perserving existing semantics for now
1209 label_state->insert_label.Reset();
Mark Young6ba8abe2017-11-09 10:37:04 -07001210 }
1211}
1212
Mark Young8504ba62018-03-21 13:35:34 -06001213static inline void EndCmdDebugUtilsLabel(debug_report_data *report_data, VkCommandBuffer command_buffer) {
Mark Lobodzinski25ac7b02019-02-07 13:22:56 -07001214 std::unique_lock<std::mutex> lock(report_data->debug_report_mutex);
John Zulaufc64f97c2019-04-10 10:34:52 -06001215 auto *label_state = GetLoggingLabelState(&report_data->debugUtilsCmdBufLabels, command_buffer, /* insert */ false);
1216 if (label_state) {
1217 // Pop the normal item
1218 if (!label_state->labels.empty()) {
1219 label_state->labels.pop_back();
Mark Young6ba8abe2017-11-09 10:37:04 -07001220 }
John Zulaufc64f97c2019-04-10 10:34:52 -06001221
1222 // TODO: Determine if this is the correct semantics for insert label vs. begin/end, perserving existing semantics for now
1223 label_state->insert_label.Reset();
Mark Young6ba8abe2017-11-09 10:37:04 -07001224 }
1225}
1226
Mark Young8504ba62018-03-21 13:35:34 -06001227static inline void InsertCmdDebugUtilsLabel(debug_report_data *report_data, VkCommandBuffer command_buffer,
1228 const VkDebugUtilsLabelEXT *label_info) {
Mark Lobodzinski25ac7b02019-02-07 13:22:56 -07001229 std::unique_lock<std::mutex> lock(report_data->debug_report_mutex);
John Zulaufc64f97c2019-04-10 10:34:52 -06001230 auto *label_state = GetLoggingLabelState(&report_data->debugUtilsCmdBufLabels, command_buffer, /* insert */ true);
1231 assert(label_state);
1232
1233 // TODO: Determine if this is the correct semantics for insert label vs. begin/end, perserving existing semantics for now
1234 label_state->insert_label = LoggingLabel(label_info);
1235}
1236
1237// Current tracking beyond a single command buffer scope is incorrect, and even when it is we need to be able to clean up
1238static inline void ResetCmdDebugUtilsLabel(debug_report_data *report_data, VkCommandBuffer command_buffer) {
1239 std::unique_lock<std::mutex> lock(report_data->debug_report_mutex);
1240 auto *label_state = GetLoggingLabelState(&report_data->debugUtilsCmdBufLabels, command_buffer, /* insert */ false);
1241 if (label_state) {
1242 label_state->labels.clear();
1243 label_state->insert_label.Reset();
Mark Young6ba8abe2017-11-09 10:37:04 -07001244 }
1245}
Mark Lobodzinski863d5de2017-05-22 10:10:07 -06001246
John Zulaufc64f97c2019-04-10 10:34:52 -06001247static inline void EraseCmdDebugUtilsLabel(debug_report_data *report_data, VkCommandBuffer command_buffer) {
1248 report_data->debugUtilsCmdBufLabels.erase(command_buffer);
1249}
1250
Mark Lobodzinski64318ba2017-01-26 13:34:13 -07001251#endif // LAYER_LOGGING_H