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 "vulkan_utilities.h"
6#include "flutter/fml/build_config.h"
7
8#include <algorithm>
9#include <unordered_set>
10
11namespace vulkan {
12
13// Whether to show Vulkan validation layer info messages in addition
14// to the error messages.
15bool ValidationLayerInfoMessagesEnabled() {
16 return false;
17}
18
19bool ValidationErrorsFatal() {
20#if OS_FUCHSIA
21 return false;
22#endif
23 return true;
24}
25
26static std::vector<std::string> InstanceOrDeviceLayersToEnable(
27 const VulkanProcTable& vk,
28 VkPhysicalDevice physical_device,
29 bool enable_validation_layers) {
30 if (!enable_validation_layers) {
31 return {};
32 }
33
34 // NOTE: The loader is sensitive to the ordering here. Please do not rearrange
35 // this list.
36#if OS_FUCHSIA
37 // The other layers in the Fuchsia SDK seem to have a bug right now causing
38 // crashes, so it is only recommended that we use VK_LAYER_KHRONOS_validation
39 // until we have a confirmation that they are fixed.
40 const std::vector<std::string> candidates = {"VK_LAYER_KHRONOS_validation"};
41#else
42 const std::vector<std::string> candidates = {
43 "VK_LAYER_GOOGLE_threading", "VK_LAYER_LUNARG_parameter_validation",
44 "VK_LAYER_LUNARG_object_tracker", "VK_LAYER_LUNARG_core_validation",
45 "VK_LAYER_LUNARG_device_limits", "VK_LAYER_LUNARG_image",
46 "VK_LAYER_LUNARG_swapchain", "VK_LAYER_GOOGLE_unique_objects"};
47#endif
48
49 uint32_t count = 0;
50
51 if (physical_device == VK_NULL_HANDLE) {
52 if (VK_CALL_LOG_ERROR(vk.EnumerateInstanceLayerProperties(
53 &count, nullptr)) != VK_SUCCESS) {
54 return {};
55 }
56 } else {
57 if (VK_CALL_LOG_ERROR(vk.EnumerateDeviceLayerProperties(
58 physical_device, &count, nullptr)) != VK_SUCCESS) {
59 return {};
60 }
61 }
62
63 std::vector<VkLayerProperties> properties;
64 properties.resize(count);
65
66 if (physical_device == VK_NULL_HANDLE) {
67 if (VK_CALL_LOG_ERROR(vk.EnumerateInstanceLayerProperties(
68 &count, properties.data())) != VK_SUCCESS) {
69 return {};
70 }
71 } else {
72 if (VK_CALL_LOG_ERROR(vk.EnumerateDeviceLayerProperties(
73 physical_device, &count, properties.data())) != VK_SUCCESS) {
74 return {};
75 }
76 }
77
78 std::unordered_set<std::string> available_extensions;
79
80 for (size_t i = 0; i < count; i++) {
81 available_extensions.emplace(properties[i].layerName);
82 }
83
84 std::vector<std::string> available_candidates;
85
86 for (const auto& candidate : candidates) {
87 auto found = available_extensions.find(candidate);
88 if (found != available_extensions.end()) {
89 available_candidates.emplace_back(candidate);
90 }
91 }
92
93 return available_candidates;
94}
95
96std::vector<std::string> InstanceLayersToEnable(const VulkanProcTable& vk,
97 bool enable_validation_layers) {
98 return InstanceOrDeviceLayersToEnable(vk, VK_NULL_HANDLE,
99 enable_validation_layers);
100}
101
102std::vector<std::string> DeviceLayersToEnable(
103 const VulkanProcTable& vk,
104 const VulkanHandle<VkPhysicalDevice>& physical_device,
105 bool enable_validation_layers) {
106 if (!physical_device) {
107 return {};
108 }
109
110 return InstanceOrDeviceLayersToEnable(vk, physical_device,
111 enable_validation_layers);
112}
113
114} // namespace vulkan
115