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 "vulkan_debug_report.h"
6
7#include <algorithm>
8#include <iomanip>
9#include <vector>
10
11#include "flutter/fml/compiler_specific.h"
12#include "vulkan_utilities.h"
13
14namespace vulkan {
15
16static const VkDebugReportFlagsEXT kVulkanErrorFlags FML_ALLOW_UNUSED_TYPE =
17 VK_DEBUG_REPORT_WARNING_BIT_EXT |
18 VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT | VK_DEBUG_REPORT_ERROR_BIT_EXT;
19
20static const VkDebugReportFlagsEXT kVulkanInfoFlags FML_ALLOW_UNUSED_TYPE =
21 VK_DEBUG_REPORT_INFORMATION_BIT_EXT | VK_DEBUG_REPORT_DEBUG_BIT_EXT;
22
23std::string VulkanDebugReport::DebugExtensionName() {
24 return VK_EXT_DEBUG_REPORT_EXTENSION_NAME;
25}
26
27static const char* VkDebugReportFlagsEXTToString(VkDebugReportFlagsEXT flags) {
28 if (flags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) {
29 return "Information";
30 } else if (flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
31 return "Warning";
32 } else if (flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) {
33 return "Performance Warning";
34 } else if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
35 return "Error";
36 } else if (flags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) {
37 return "Debug";
38 }
39 return "UNKNOWN";
40}
41
42static const char* VkDebugReportObjectTypeEXTToString(
43 VkDebugReportObjectTypeEXT type) {
44 switch (type) {
45 case VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT:
46 return "Unknown";
47 case VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT:
48 return "Instance";
49 case VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT:
50 return "Physical Device";
51 case VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT:
52 return "Device";
53 case VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT:
54 return "Queue";
55 case VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT:
56 return "Semaphore";
57 case VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT:
58 return "Command Buffer";
59 case VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT:
60 return "Fence";
61 case VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT:
62 return "Device Memory";
63 case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT:
64 return "Buffer";
65 case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT:
66 return "Image";
67 case VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT:
68 return "Event";
69 case VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT:
70 return "Query Pool";
71 case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT:
72 return "Buffer View";
73 case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT:
74 return "Image_view";
75 case VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT:
76 return "Shader Module";
77 case VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_CACHE_EXT:
78 return "Pipeline Cache";
79 case VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_LAYOUT_EXT:
80 return "Pipeline Layout";
81 case VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT:
82 return "Render Pass";
83 case VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT:
84 return "Pipeline";
85 case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT:
86 return "Descriptor Set Layout";
87 case VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT:
88 return "Sampler";
89 case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT:
90 return "Descriptor Pool";
91 case VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT:
92 return "Descriptor Set";
93 case VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT:
94 return "Framebuffer";
95 case VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT:
96 return "Command Pool";
97 case VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT:
98 return "Surface";
99 case VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT:
100 return "Swapchain";
101 case VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT:
102 return "Debug";
103 default:
104 break;
105 }
106
107 return "Unknown";
108}
109
110static VKAPI_ATTR VkBool32
111#ifdef WIN32
112 __stdcall
113#endif
114 OnVulkanDebugReportCallback(VkDebugReportFlagsEXT flags,
115 VkDebugReportObjectTypeEXT object_type,
116 uint64_t object,
117 size_t location,
118 int32_t message_code,
119 const char* layer_prefix,
120 const char* message,
121 void* user_data) {
122 std::vector<std::pair<std::string, std::string>> items;
123
124 items.emplace_back(args: "Severity", args: VkDebugReportFlagsEXTToString(flags));
125
126 items.emplace_back(args: "Object Type",
127 args: VkDebugReportObjectTypeEXTToString(type: object_type));
128
129 items.emplace_back(args: "Object Handle", args: std::to_string(val: object));
130
131 if (location != 0) {
132 items.emplace_back(args: "Location", args: std::to_string(val: location));
133 }
134
135 if (message_code != 0) {
136 items.emplace_back(args: "Message Code", args: std::to_string(val: message_code));
137 }
138
139 if (layer_prefix != nullptr) {
140 items.emplace_back(args: "Layer", args&: layer_prefix);
141 }
142
143 if (message != nullptr) {
144 items.emplace_back(args: "Message", args&: message);
145 }
146
147 size_t padding = 0;
148
149 for (const auto& item : items) {
150 padding = std::max(a: padding, b: item.first.size());
151 }
152
153 padding += 1;
154
155 std::stringstream stream;
156
157 stream << std::endl;
158
159 stream << "--- Vulkan Debug Report ----------------------------------------";
160
161 stream << std::endl;
162
163 for (const auto& item : items) {
164 stream << "| " << std::setw(static_cast<int>(padding)) << item.first
165 << std::setw(0) << ": " << item.second << std::endl;
166 }
167
168 stream << "-----------------------------------------------------------------";
169
170 if (flags & kVulkanErrorFlags) {
171 if (ValidationErrorsFatal()) {
172 FML_DCHECK(false) << stream.str();
173 } else {
174 FML_LOG(ERROR) << stream.str();
175 }
176 } else {
177 FML_LOG(INFO) << stream.str();
178 }
179
180 // Returning false tells the layer not to stop when the event occurs, so
181 // they see the same behavior with and without validation layers enabled.
182 return VK_FALSE;
183}
184
185VulkanDebugReport::VulkanDebugReport(
186 const VulkanProcTable& p_vk,
187 const VulkanHandle<VkInstance>& application)
188 : vk(p_vk), application_(application), valid_(false) {
189 if (!vk.CreateDebugReportCallbackEXT || !vk.DestroyDebugReportCallbackEXT) {
190 return;
191 }
192
193 if (!application_) {
194 return;
195 }
196
197 VkDebugReportFlagsEXT flags = kVulkanErrorFlags;
198 if (ValidationLayerInfoMessagesEnabled()) {
199 flags |= kVulkanInfoFlags;
200 }
201 const VkDebugReportCallbackCreateInfoEXT create_info = {
202 .sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT,
203 .pNext = nullptr,
204 .flags = flags,
205 .pfnCallback = &vulkan::OnVulkanDebugReportCallback,
206 .pUserData = nullptr,
207 };
208
209 VkDebugReportCallbackEXT handle = VK_NULL_HANDLE;
210 if (VK_CALL_LOG_ERROR(vk.CreateDebugReportCallbackEXT(
211 application_, &create_info, nullptr, &handle)) != VK_SUCCESS) {
212 return;
213 }
214
215 handle_ = VulkanHandle<VkDebugReportCallbackEXT>{
216 handle, [this](VkDebugReportCallbackEXT handle) {
217 vk.DestroyDebugReportCallbackEXT(application_, handle, nullptr);
218 }};
219
220 valid_ = true;
221}
222
223VulkanDebugReport::~VulkanDebugReport() = default;
224
225bool VulkanDebugReport::IsValid() const {
226 return valid_;
227}
228
229} // namespace vulkan
230

source code of flutter_engine/flutter/vulkan/vulkan_debug_report.cc