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