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