| // Copyright 2019 Google LLC |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #include "third_party/mlir_edge/iree/hal/vulkan/debug_reporter.h" |
| |
| #include "third_party/mlir_edge/iree/base/tracing.h" |
| #include "third_party/mlir_edge/iree/hal/vulkan/status_util.h" |
| |
| namespace iree { |
| namespace hal { |
| namespace vulkan { |
| |
| namespace { |
| |
| // NOTE: |user_data| may be nullptr if we are being called during instance |
| // creation. Otherwise it is a pointer to the DebugReporter instance. |
| |
| // NOTE: this callback must be thread safe and must be careful not to reach too |
| // far outside of the call - it is called in-context from arbitrary threads with |
| // some amount of Vulkan state on the stack. Assume that creating or deleting |
| // Vulkan objects, issuing most Vulkan commands, etc are off-limits. |
| |
| VKAPI_ATTR VkBool32 VKAPI_CALL DebugUtilsMessageCallback( |
| VkDebugUtilsMessageSeverityFlagBitsEXT message_severity, |
| VkDebugUtilsMessageTypeFlagsEXT message_type, |
| const VkDebugUtilsMessengerCallbackDataEXT* callback_data, |
| void* user_data) { |
| // TODO(benvanik): better logging once we have switched logging APIs. |
| LOG(ERROR) << callback_data->pMessage; |
| |
| return VK_FALSE; // VK_TRUE is reserved for future use. |
| } |
| |
| VKAPI_ATTR VkBool32 VKAPI_CALL DebugReportCallback( |
| 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) { |
| // TODO(benvanik): better logging once we have switched logging APIs. |
| LOG(ERROR) << message; |
| |
| return VK_FALSE; // VK_TRUE is reserved for future use. |
| } |
| |
| } // namespace |
| |
| // static |
| void DebugReporter::PopulateStaticCreateInfo( |
| VkDebugUtilsMessengerCreateInfoEXT* create_info) { |
| create_info->sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; |
| create_info->pNext = nullptr; |
| create_info->flags = 0; |
| |
| // TODO(benvanik): only enable the severities that logging has enabled. |
| create_info->messageSeverity = |
| VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | |
| VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT | |
| VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | |
| VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; |
| |
| // TODO(benvanik): allow filtering by category as a flag. |
| create_info->messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | |
| VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | |
| VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT; |
| |
| create_info->pfnUserCallback = DebugUtilsMessageCallback; |
| create_info->pUserData = nullptr; |
| } |
| |
| // static |
| void DebugReporter::PopulateStaticCreateInfo( |
| VkDebugReportCallbackCreateInfoEXT* create_info) { |
| create_info->sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT; |
| create_info->pNext = nullptr; |
| create_info->flags = 0; |
| |
| // TODO(benvanik): only enable the severities that logging has enabled. |
| create_info->flags |= |
| VK_DEBUG_REPORT_INFORMATION_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | |
| VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT | |
| VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_DEBUG_BIT_EXT; |
| |
| create_info->pfnCallback = DebugReportCallback; |
| create_info->pUserData = nullptr; |
| } |
| |
| // static |
| StatusOr<std::unique_ptr<DebugReporter>> |
| DebugReporter::CreateDebugUtilsMessenger( |
| VkInstance instance, const ref_ptr<DynamicSymbols>& syms, |
| const VkAllocationCallbacks* allocation_callbacks) { |
| IREE_TRACE_SCOPE0("DebugReporter::CreateDebugUtilsMessenger"); |
| |
| auto debug_reporter = |
| absl::WrapUnique(new DebugReporter(instance, syms, allocation_callbacks)); |
| |
| VkDebugUtilsMessengerCreateInfoEXT create_info; |
| PopulateStaticCreateInfo(&create_info); |
| create_info.pUserData = debug_reporter.get(); |
| |
| VK_RETURN_IF_ERROR(syms->vkCreateDebugUtilsMessengerEXT( |
| instance, &create_info, allocation_callbacks, |
| &debug_reporter->messenger_)); |
| |
| return debug_reporter; |
| } |
| |
| // static |
| StatusOr<std::unique_ptr<DebugReporter>> |
| DebugReporter::CreateDebugReportCallback( |
| VkInstance instance, const ref_ptr<DynamicSymbols>& syms, |
| const VkAllocationCallbacks* allocation_callbacks) { |
| IREE_TRACE_SCOPE0("DebugReporter::CreateDebugReportCallback"); |
| |
| auto debug_reporter = |
| absl::WrapUnique(new DebugReporter(instance, syms, allocation_callbacks)); |
| |
| VkDebugReportCallbackCreateInfoEXT create_info; |
| PopulateStaticCreateInfo(&create_info); |
| create_info.pUserData = debug_reporter.get(); |
| |
| VK_RETURN_IF_ERROR(syms->vkCreateDebugReportCallbackEXT( |
| instance, &create_info, allocation_callbacks, |
| &debug_reporter->callback_)); |
| |
| return debug_reporter; |
| } |
| |
| DebugReporter::DebugReporter(VkInstance instance, |
| const ref_ptr<DynamicSymbols>& syms, |
| const VkAllocationCallbacks* allocation_callbacks) |
| : instance_(instance), |
| syms_(add_ref(syms)), |
| allocation_callbacks_(allocation_callbacks) {} |
| |
| DebugReporter::~DebugReporter() { |
| IREE_TRACE_SCOPE0("DebugReporter::dtor"); |
| if (messenger_ != VK_NULL_HANDLE) { |
| syms_->vkDestroyDebugUtilsMessengerEXT(instance_, messenger_, |
| allocation_callbacks_); |
| } |
| if (callback_ != VK_NULL_HANDLE) { |
| syms_->vkDestroyDebugReportCallbackEXT(instance_, callback_, |
| allocation_callbacks_); |
| } |
| } |
| |
| } // namespace vulkan |
| } // namespace hal |
| } // namespace iree |