From f49c827dc7c3ad31c1cc131a1edbd9ca60e5e1c5 Mon Sep 17 00:00:00 2001 From: John Bauman Date: Tue, 1 Oct 2024 13:42:07 -0400 Subject: [PATCH] Log Vulkan loader errors if the instance failed creation on Fuchsia (flutter/engine#52935) Log Vulkan loader errors if the instance failed creation on Fuchsia The vulkan loader can output logs to help us debug why instance creation fails. To catch these logs, we need to pass a debug report callback to vkCreateInstance (since the only other debug report callback is set up after the instance is created). Outputting logs is currently only enabled on Fuchsia, since other platforms may have fallbacks and wouldn't want the error logspam. Fixes https://github.com/flutter/flutter/issues/82928 *If you had to change anything in the [flutter/tests] repo, include a link to the migration guide as per the [breaking change policy].* [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style --- .../src/flutter/vulkan/vulkan_application.cc | 47 +++++++++++++++++-- .../src/flutter/vulkan/vulkan_application.h | 21 +++++++-- 2 files changed, 59 insertions(+), 9 deletions(-) diff --git a/engine/src/flutter/vulkan/vulkan_application.cc b/engine/src/flutter/vulkan/vulkan_application.cc index 6b618b178a..8afb02eaf4 100644 --- a/engine/src/flutter/vulkan/vulkan_application.cc +++ b/engine/src/flutter/vulkan/vulkan_application.cc @@ -13,6 +13,25 @@ namespace vulkan { +// static +VKAPI_ATTR VkBool32 VulkanApplication::DebugReportCallback( + VkDebugReportFlagsEXT flags, + VkDebugReportObjectTypeEXT objectType, + uint64_t object, + size_t location, + int32_t messageCode, + const char* pLayerPrefix, + const char* pMessage, + void* pUserData) { + auto application = static_cast(pUserData); + if (application->initialization_logs_enabled_) { + application->initialization_logs_ += pMessage; + application->initialization_logs_ += "\n"; + } + + return VK_FALSE; +} + VulkanApplication::VulkanApplication( VulkanProcTable& p_vk, // NOLINT const std::string& application_name, @@ -20,10 +39,10 @@ VulkanApplication::VulkanApplication( uint32_t application_version, uint32_t api_version, bool enable_validation_layers) - : vk_(p_vk), + : valid_(false), + enable_validation_layers_(enable_validation_layers), api_version_(api_version), - valid_(false), - enable_validation_layers_(enable_validation_layers) { + vk_(p_vk) { // Check if we want to enable debugging. std::vector supported_extensions = GetSupportedInstanceExtensions(vk_); @@ -79,9 +98,21 @@ VulkanApplication::VulkanApplication( .apiVersion = api_version_, }; + const VkDebugReportCallbackCreateInfoEXT debug_report_info = { + .sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT, + .pNext = nullptr, + .flags = VK_DEBUG_REPORT_INFORMATION_BIT_EXT | + VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_ERROR_BIT_EXT | + VK_DEBUG_REPORT_DEBUG_BIT_EXT, + .pfnCallback = &DebugReportCallback, + .pUserData = this}; + const VkInstanceCreateInfo create_info = { .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, - .pNext = nullptr, + .pNext = ExtensionSupported(supported_extensions, + VK_EXT_DEBUG_REPORT_EXTENSION_NAME) + ? &debug_report_info + : nullptr, .flags = 0, .pApplicationInfo = &info, .enabledLayerCount = static_cast(layers.size()), @@ -96,10 +127,16 @@ VulkanApplication::VulkanApplication( if (VK_CALL_LOG_ERROR(vk_.CreateInstance(&create_info, nullptr, &instance)) != VK_SUCCESS) { - FML_DLOG(INFO) << "Could not create application instance."; + FML_LOG(ERROR) << "Creating application instance failed with error:\n" + << initialization_logs_; return; } + // The debug report callback will also be used in vkDestroyInstance, but we + // don't need its data there. + initialization_logs_enabled_ = false; + initialization_logs_.clear(); + // Now that we have an instance, set up instance proc table entries. if (!vk_.SetupInstanceProcAddresses(VulkanHandle(instance))) { FML_DLOG(INFO) << "Could not set up instance proc addresses."; diff --git a/engine/src/flutter/vulkan/vulkan_application.h b/engine/src/flutter/vulkan/vulkan_application.h index b30e49c0b2..eacb382868 100644 --- a/engine/src/flutter/vulkan/vulkan_application.h +++ b/engine/src/flutter/vulkan/vulkan_application.h @@ -44,12 +44,16 @@ class VulkanApplication { std::unique_ptr AcquireFirstCompatibleLogicalDevice() const; private: - VulkanProcTable& vk_; - VulkanHandle instance_; - uint32_t api_version_; - std::unique_ptr debug_report_; + // Located at the beginning so it outlives instance_. + std::string initialization_logs_; + bool initialization_logs_enabled_ = true; bool valid_; bool enable_validation_layers_; + uint8_t padding_; + uint32_t api_version_; + VulkanProcTable& vk_; + VulkanHandle instance_; + std::unique_ptr debug_report_; std::vector GetPhysicalDevices() const; std::vector GetSupportedInstanceExtensions( @@ -57,6 +61,15 @@ class VulkanApplication { bool ExtensionSupported( const std::vector& supported_extensions, const std::string& extension_name); + static VKAPI_ATTR VkBool32 DebugReportCallback( + VkDebugReportFlagsEXT flags, + VkDebugReportObjectTypeEXT objectType, + uint64_t object, + size_t location, + int32_t messageCode, + const char* pLayerPrefix, + const char* pMessage, + void* pUserData); FML_DISALLOW_COPY_AND_ASSIGN(VulkanApplication); };