| Flutter Impeller |

debug_report_vk.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "impeller/renderer/backend/vulkan/debug_report_vk.h"
6
7 #include "impeller/base/validation.h"
8 #include "impeller/renderer/backend/vulkan/capabilities_vk.h"
9
10 namespace impeller {
11
12 DebugReportVK::DebugReportVK(const CapabilitiesVK& caps,
13 const vk::Instance& instance) {
14 if (!caps.AreValidationsEnabled()) {
15 is_valid_ = true;
16 return;
17 }
18
19 vk::DebugUtilsMessengerCreateInfoEXT messenger_info;
20 messenger_info.messageSeverity =
21 vk::DebugUtilsMessageSeverityFlagBitsEXT::eWarning |
22 vk::DebugUtilsMessageSeverityFlagBitsEXT::eError;
23 messenger_info.messageType =
24 vk::DebugUtilsMessageTypeFlagBitsEXT::eGeneral |
25 vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance |
26 vk::DebugUtilsMessageTypeFlagBitsEXT::eValidation;
27 messenger_info.pUserData = this;
28 messenger_info.pfnUserCallback = DebugUtilsMessengerCallback;
29
30 auto messenger = instance.createDebugUtilsMessengerEXTUnique(messenger_info);
31
32 if (messenger.result != vk::Result::eSuccess) {
33 FML_LOG(ERROR) << "Could not create debug messenger: "
34 << vk::to_string(messenger.result);
35 return;
36 }
37
38 messenger_ = std::move(messenger.value);
39 is_valid_ = true;
40 }
41
42 DebugReportVK::~DebugReportVK() = default;
43
44 bool DebugReportVK::IsValid() const {
45 return is_valid_;
46 }
47
48 static std::string JoinLabels(const VkDebugUtilsLabelEXT* labels,
49 size_t count) {
50 std::stringstream stream;
51 for (size_t i = 0u; i < count; i++) {
52 stream << labels[i].pLabelName;
53 if (i != count - 1u) {
54 stream << ", ";
55 }
56 }
57 return stream.str();
58 }
59
60 static std::string JoinVKDebugUtilsObjectNameInfoEXT(
61 const VkDebugUtilsObjectNameInfoEXT* names,
62 size_t count) {
63 std::stringstream stream;
64 for (size_t i = 0u; i < count; i++) {
65 stream << vk::to_string(vk::ObjectType(names[i].objectType)) << " ["
66 << names[i].objectHandle << "] [";
67 if (names[i].pObjectName != nullptr) {
68 stream << names[i].pObjectName;
69 } else {
70 stream << "UNNAMED";
71 }
72 stream << "]";
73 if (i != count - 1u) {
74 stream << ", ";
75 }
76 }
77 return stream.str();
78 }
79
80 VKAPI_ATTR VkBool32 VKAPI_CALL DebugReportVK::DebugUtilsMessengerCallback(
81 VkDebugUtilsMessageSeverityFlagBitsEXT severity,
82 VkDebugUtilsMessageTypeFlagsEXT type,
83 const VkDebugUtilsMessengerCallbackDataEXT* callback_data,
84 void* debug_report) {
85 auto result =
86 reinterpret_cast<DebugReportVK*>(debug_report)
87 ->OnDebugCallback(
88 static_cast<vk::DebugUtilsMessageSeverityFlagBitsEXT>(
89 severity), //
90 static_cast<vk::DebugUtilsMessageTypeFlagsEXT>(type), //
91 callback_data //
92 );
93 switch (result) {
94 case Result::kContinue:
95 return VK_FALSE;
96 case Result::kAbort:
97 return VK_TRUE;
98 }
99 return VK_FALSE;
100 }
101
102 DebugReportVK::Result DebugReportVK::OnDebugCallback(
103 vk::DebugUtilsMessageSeverityFlagBitsEXT severity,
104 vk::DebugUtilsMessageTypeFlagsEXT type,
105 const VkDebugUtilsMessengerCallbackDataEXT* data) {
106 // Issue in older versions of the SDK.
107 // https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/3554
108 if (strstr(data->pMessageIdName, "CoreValidation-Shader-OutputNotConsumed") !=
109 nullptr) {
110 return Result::kContinue;
111 }
112
113 // This is a real error but we can't fix it due to our headers being too
114 // old. More more details see:
115 // https://vulkan.lunarg.com/doc/view/1.3.224.1/mac/1.3-extensions/vkspec.html#VUID-VkImageViewCreateInfo-imageViewFormatSwizzle-04465
116 // This validation error currently only trips on macOS due to the use of
117 // texture swizzles.
118 if (data->messageIdNumber == static_cast<int32_t>(0x82ae5050)) {
119 return Result::kContinue;
120 }
121
122 std::vector<std::pair<std::string, std::string>> items;
123
124 items.emplace_back("Severity", vk::to_string(severity));
125
126 items.emplace_back("Type", vk::to_string(type));
127
128 if (data->pMessageIdName) {
129 items.emplace_back("ID Name", data->pMessageIdName);
130 }
131
132 items.emplace_back("ID Number", std::to_string(data->messageIdNumber));
133
134 if (auto queues = JoinLabels(data->pQueueLabels, data->queueLabelCount);
135 !queues.empty()) {
136 items.emplace_back("Queue Breadcrumbs", std::move(queues));
137 } else {
138 items.emplace_back("Queue Breadcrumbs", "[NONE]");
139 }
140
141 if (auto cmd_bufs = JoinLabels(data->pCmdBufLabels, data->cmdBufLabelCount);
142 !cmd_bufs.empty()) {
143 items.emplace_back("CMD Buffer Breadcrumbs", std::move(cmd_bufs));
144 } else {
145 items.emplace_back("CMD Buffer Breadcrumbs", "[NONE]");
146 }
147
148 if (auto related =
149 JoinVKDebugUtilsObjectNameInfoEXT(data->pObjects, data->objectCount);
150 !related.empty()) {
151 items.emplace_back("Related Objects", std::move(related));
152 }
153
154 if (data->pMessage) {
155 items.emplace_back("Trigger", data->pMessage);
156 }
157
158 size_t padding = 0;
159
160 for (const auto& item : items) {
161 padding = std::max(padding, item.first.size());
162 }
163
164 padding += 1;
165
166 std::stringstream stream;
167
168 stream << std::endl;
169
170 stream << "--- Vulkan Debug Report ----------------------------------------";
171
172 stream << std::endl;
173
174 for (const auto& item : items) {
175 stream << "| " << std::setw(static_cast<int>(padding)) << item.first
176 << std::setw(0) << ": " << item.second << std::endl;
177 }
178
179 stream << "-----------------------------------------------------------------";
180
181 if (type == vk::DebugUtilsMessageTypeFlagBitsEXT::ePerformance) {
182 FML_LOG(INFO) << stream.str();
183 } else {
184 VALIDATION_LOG << stream.str();
185 }
186
187 return Result::kContinue;
188 }
189
190 } // namespace impeller
impeller::DebugReportVK::IsValid
bool IsValid() const
Definition: debug_report_vk.cc:44
validation.h
capabilities_vk.h
debug_report_vk.h
impeller::JoinVKDebugUtilsObjectNameInfoEXT
static std::string JoinVKDebugUtilsObjectNameInfoEXT(const VkDebugUtilsObjectNameInfoEXT *names, size_t count)
Definition: debug_report_vk.cc:60
impeller::CapabilitiesVK
The Vulkan layers and extensions wrangler.
Definition: capabilities_vk.h:30
VALIDATION_LOG
#define VALIDATION_LOG
Definition: validation.h:60
impeller::DebugReportVK::~DebugReportVK
~DebugReportVK()
impeller::JoinLabels
static std::string JoinLabels(const VkDebugUtilsLabelEXT *labels, size_t count)
Definition: debug_report_vk.cc:48
impeller::CapabilitiesVK::AreValidationsEnabled
bool AreValidationsEnabled() const
Definition: capabilities_vk.cc:61
impeller
Definition: aiks_context.cc:10
impeller::DebugReportVK::DebugReportVK
DebugReportVK(const CapabilitiesVK &caps, const vk::Instance &instance)
Definition: debug_report_vk.cc:12