|  | // 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_utilities.h" | 
|  | #include "flutter/fml/build_config.h" | 
|  |  | 
|  | #include <algorithm> | 
|  | #include <unordered_set> | 
|  |  | 
|  | namespace vulkan { | 
|  |  | 
|  | // Whether to show Vulkan validation layer info messages in addition | 
|  | // to the error messages. | 
|  | bool ValidationLayerInfoMessagesEnabled() { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | bool ValidationErrorsFatal() { | 
|  | #if OS_FUCHSIA | 
|  | return false; | 
|  | #endif | 
|  | return true; | 
|  | } | 
|  |  | 
|  | static std::vector<std::string> InstanceOrDeviceLayersToEnable( | 
|  | const VulkanProcTable& vk, | 
|  | VkPhysicalDevice physical_device, | 
|  | bool enable_validation_layers) { | 
|  | if (!enable_validation_layers) { | 
|  | return {}; | 
|  | } | 
|  |  | 
|  | // NOTE: The loader is sensitive to the ordering here. Please do not rearrange | 
|  | // this list. | 
|  | #if OS_FUCHSIA | 
|  | // The other layers in the Fuchsia SDK seem to have a bug right now causing | 
|  | // crashes, so it is only recommended that we use VK_LAYER_KHRONOS_validation | 
|  | // until we have a confirmation that they are fixed. | 
|  | const std::vector<std::string> candidates = {"VK_LAYER_KHRONOS_validation"}; | 
|  | #else | 
|  | const std::vector<std::string> candidates = { | 
|  | "VK_LAYER_GOOGLE_threading",      "VK_LAYER_LUNARG_parameter_validation", | 
|  | "VK_LAYER_LUNARG_object_tracker", "VK_LAYER_LUNARG_core_validation", | 
|  | "VK_LAYER_LUNARG_device_limits",  "VK_LAYER_LUNARG_image", | 
|  | "VK_LAYER_LUNARG_swapchain",      "VK_LAYER_GOOGLE_unique_objects"}; | 
|  | #endif | 
|  |  | 
|  | uint32_t count = 0; | 
|  |  | 
|  | if (physical_device == VK_NULL_HANDLE) { | 
|  | if (VK_CALL_LOG_ERROR(vk.EnumerateInstanceLayerProperties( | 
|  | &count, nullptr)) != VK_SUCCESS) { | 
|  | return {}; | 
|  | } | 
|  | } else { | 
|  | if (VK_CALL_LOG_ERROR(vk.EnumerateDeviceLayerProperties( | 
|  | physical_device, &count, nullptr)) != VK_SUCCESS) { | 
|  | return {}; | 
|  | } | 
|  | } | 
|  |  | 
|  | std::vector<VkLayerProperties> properties; | 
|  | properties.resize(count); | 
|  |  | 
|  | if (physical_device == VK_NULL_HANDLE) { | 
|  | if (VK_CALL_LOG_ERROR(vk.EnumerateInstanceLayerProperties( | 
|  | &count, properties.data())) != VK_SUCCESS) { | 
|  | return {}; | 
|  | } | 
|  | } else { | 
|  | if (VK_CALL_LOG_ERROR(vk.EnumerateDeviceLayerProperties( | 
|  | physical_device, &count, properties.data())) != VK_SUCCESS) { | 
|  | return {}; | 
|  | } | 
|  | } | 
|  |  | 
|  | std::unordered_set<std::string> available_extensions; | 
|  |  | 
|  | for (size_t i = 0; i < count; i++) { | 
|  | available_extensions.emplace(properties[i].layerName); | 
|  | } | 
|  |  | 
|  | std::vector<std::string> available_candidates; | 
|  |  | 
|  | for (const auto& candidate : candidates) { | 
|  | auto found = available_extensions.find(candidate); | 
|  | if (found != available_extensions.end()) { | 
|  | available_candidates.emplace_back(candidate); | 
|  | } | 
|  | } | 
|  |  | 
|  | return available_candidates; | 
|  | } | 
|  |  | 
|  | std::vector<std::string> InstanceLayersToEnable(const VulkanProcTable& vk, | 
|  | bool enable_validation_layers) { | 
|  | return InstanceOrDeviceLayersToEnable(vk, VK_NULL_HANDLE, | 
|  | enable_validation_layers); | 
|  | } | 
|  |  | 
|  | std::vector<std::string> DeviceLayersToEnable( | 
|  | const VulkanProcTable& vk, | 
|  | const VulkanHandle<VkPhysicalDevice>& physical_device, | 
|  | bool enable_validation_layers) { | 
|  | if (!physical_device) { | 
|  | return {}; | 
|  | } | 
|  |  | 
|  | return InstanceOrDeviceLayersToEnable(vk, physical_device, | 
|  | enable_validation_layers); | 
|  | } | 
|  |  | 
|  | }  // namespace vulkan |