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