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