• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_application.h"
6 
7 #include <utility>
8 #include <vector>
9 
10 #include "flutter/vulkan/vulkan_device.h"
11 #ifdef RS_ENABLE_VK
12 #include "flutter/vulkan/vulkan_hilog.h"
13 #endif
14 #include "flutter/vulkan/vulkan_proc_table.h"
15 #include "flutter/vulkan/vulkan_utilities.h"
16 
17 namespace vulkan {
18 
VulkanApplication(VulkanProcTable & p_vk,const std::string & application_name,std::vector<std::string> enabled_extensions,uint32_t application_version,uint32_t api_version)19 VulkanApplication::VulkanApplication(
20     VulkanProcTable& p_vk,
21     const std::string& application_name,
22     std::vector<std::string> enabled_extensions,
23     uint32_t application_version,
24     uint32_t api_version)
25     : vk(p_vk), api_version_(api_version), valid_(false) {
26   // Check if we want to enable debugging.
27   std::vector<VkExtensionProperties> supported_extensions =
28       GetSupportedInstanceExtensions(vk);
29   bool enable_instance_debugging =
30       IsDebuggingEnabled() &&
31       ExtensionSupported(supported_extensions,
32                          VulkanDebugReport::DebugExtensionName());
33 
34   // Configure extensions.
35 
36   if (enable_instance_debugging) {
37     enabled_extensions.emplace_back(VulkanDebugReport::DebugExtensionName());
38   }
39 #if OS_FUCHSIA
40   if (ExtensionSupported(supported_extensions,
41                          VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME)) {
42     // VK_KHR_get_physical_device_properties2 is a dependency of the memory
43     // capabilities extension, so the validation layers require that it be
44     // enabled.
45     enabled_extensions.emplace_back(
46         VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
47     enabled_extensions.emplace_back(
48         VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME);
49   }
50 #endif
51 
52   const char* extensions[enabled_extensions.size()];
53 
54   for (size_t i = 0; i < enabled_extensions.size(); i++) {
55     extensions[i] = enabled_extensions[i].c_str();
56   }
57 
58   // Configure layers.
59 
60   const std::vector<std::string> enabled_layers = InstanceLayersToEnable(vk);
61 
62   const char* layers[enabled_layers.size()];
63 
64   for (size_t i = 0; i < enabled_layers.size(); i++) {
65     layers[i] = enabled_layers[i].c_str();
66   }
67 
68   // Configure init structs.
69 
70 #ifdef RS_ENABLE_VK
71   const VkApplicationInfo info = {
72       .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
73       .pNext = nullptr,
74       .pApplicationName = application_name.c_str(),
75       .applicationVersion = application_version,
76       .pEngineName = "Rosen",
77       .engineVersion = VK_MAKE_VERSION(1, 0, 0),
78       .apiVersion = api_version_,
79   };
80 #else
81   const VkApplicationInfo info = {
82       .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
83       .pNext = nullptr,
84       .pApplicationName = application_name.c_str(),
85       .applicationVersion = application_version,
86       .pEngineName = "FlutterEngine",
87       .engineVersion = VK_MAKE_VERSION(1, 0, 0),
88       .apiVersion = api_version_,
89   };
90 #endif
91 
92   const VkInstanceCreateInfo create_info = {
93       .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
94       .pNext = nullptr,
95       .flags = 0,
96       .pApplicationInfo = &info,
97       .enabledLayerCount = static_cast<uint32_t>(enabled_layers.size()),
98       .ppEnabledLayerNames = layers,
99       .enabledExtensionCount = static_cast<uint32_t>(enabled_extensions.size()),
100       .ppEnabledExtensionNames = extensions,
101   };
102 
103   // Perform initialization.
104 
105   VkInstance instance = VK_NULL_HANDLE;
106 
107   if (VK_CALL_LOG_ERROR(vk.CreateInstance(&create_info, nullptr, &instance)) !=
108       VK_SUCCESS) {
109 #ifdef RS_ENABLE_VK
110     LOGE("Could not create application instance.");
111 #else
112     FML_DLOG(INFO) << "Could not create application instance.";
113 #endif
114     return;
115   }
116 
117   // Now that we have an instance, setup instance proc table entries.
118   if (!vk.SetupInstanceProcAddresses(instance)) {
119 #ifdef RS_ENABLE_VK
120     LOGE("Could not setup instance proc addresses.");
121 #else
122     FML_DLOG(INFO) << "Could not setup instance proc addresses.";
123 #endif
124     return;
125   }
126 
127   instance_ = {instance, [this](VkInstance i) {
128 #ifdef RS_ENABLE_VK
129                  LOGE("Destroying Vulkan instance");
130 #else
131                  FML_LOG(INFO) << "Destroying Vulkan instance";
132 #endif
133                  vk.DestroyInstance(i, nullptr);
134                }};
135 
136   if (enable_instance_debugging) {
137     auto debug_report = std::make_unique<VulkanDebugReport>(vk, instance_);
138     if (!debug_report->IsValid()) {
139 #ifdef RS_ENABLE_VK
140       LOGE("Vulkan debugging was enabled but could not be setup for this instance.");
141 #else
142       FML_LOG(INFO) << "Vulkan debugging was enabled but could not be setup "
143                        "for this instance.";
144 #endif
145     } else {
146       debug_report_ = std::move(debug_report);
147 #ifdef RS_ENABLE_VK
148       LOGE("Debug reporting is enabled.");
149 #else
150       FML_DLOG(INFO) << "Debug reporting is enabled.";
151 #endif
152     }
153   }
154 
155   valid_ = true;
156 }
157 
158 VulkanApplication::~VulkanApplication() = default;
159 
IsValid() const160 bool VulkanApplication::IsValid() const {
161   return valid_;
162 }
163 
GetAPIVersion() const164 uint32_t VulkanApplication::GetAPIVersion() const {
165   return api_version_;
166 }
167 
GetInstance() const168 const VulkanHandle<VkInstance>& VulkanApplication::GetInstance() const {
169   return instance_;
170 }
171 
ReleaseInstanceOwnership()172 void VulkanApplication::ReleaseInstanceOwnership() {
173   instance_.ReleaseOwnership();
174 }
175 
GetPhysicalDevices() const176 std::vector<VkPhysicalDevice> VulkanApplication::GetPhysicalDevices() const {
177   if (!IsValid()) {
178     return {};
179   }
180 
181   uint32_t device_count = 0;
182   if (VK_CALL_LOG_ERROR(vk.EnumeratePhysicalDevices(instance_, &device_count,
183                                                     nullptr)) != VK_SUCCESS) {
184 #ifdef RS_ENABLE_VK
185     LOGE("Could not enumerate physical device.");
186 #else
187     FML_DLOG(INFO) << "Could not enumerate physical device.";
188 #endif
189     return {};
190   }
191 
192   if (device_count == 0) {
193     // No available devices.
194 #ifdef RS_ENABLE_VK
195     LOGE("No physical devices found.");
196 #else
197     FML_DLOG(INFO) << "No physical devices found.";
198 #endif
199     return {};
200   }
201 
202   std::vector<VkPhysicalDevice> physical_devices;
203 
204   physical_devices.resize(device_count);
205 
206   if (VK_CALL_LOG_ERROR(vk.EnumeratePhysicalDevices(
207           instance_, &device_count, physical_devices.data())) != VK_SUCCESS) {
208 #ifdef RS_ENABLE_VK
209     LOGE("Could not enumerate physical device.");
210 #else
211     FML_DLOG(INFO) << "Could not enumerate physical device.";
212 #endif
213     return {};
214   }
215 
216   return physical_devices;
217 }
218 
219 std::unique_ptr<VulkanDevice>
AcquireFirstCompatibleLogicalDevice() const220 VulkanApplication::AcquireFirstCompatibleLogicalDevice() const {
221   for (auto device_handle : GetPhysicalDevices()) {
222     auto logical_device = std::make_unique<VulkanDevice>(vk, device_handle);
223     if (logical_device->IsValid()) {
224       return logical_device;
225     }
226   }
227 #ifdef RS_ENABLE_VK
228   LOGE("Could not acquire compatible logical device.");
229 #else
230   FML_DLOG(INFO) << "Could not acquire compatible logical device.";
231 #endif
232   return nullptr;
233 }
234 
235 std::vector<VkExtensionProperties>
GetSupportedInstanceExtensions(const VulkanProcTable & vk) const236 VulkanApplication::GetSupportedInstanceExtensions(
237     const VulkanProcTable& vk) const {
238   if (!vk.EnumerateInstanceExtensionProperties) {
239     return std::vector<VkExtensionProperties>();
240   }
241 
242   uint32_t count = 0;
243   if (VK_CALL_LOG_ERROR(vk.EnumerateInstanceExtensionProperties(
244           nullptr, &count, nullptr)) != VK_SUCCESS) {
245     return std::vector<VkExtensionProperties>();
246   }
247 
248   if (count == 0) {
249     return std::vector<VkExtensionProperties>();
250   }
251 
252   std::vector<VkExtensionProperties> properties;
253   properties.resize(count);
254   if (VK_CALL_LOG_ERROR(vk.EnumerateInstanceExtensionProperties(
255           nullptr, &count, properties.data())) != VK_SUCCESS) {
256     return std::vector<VkExtensionProperties>();
257   }
258 
259   return properties;
260 }
261 
ExtensionSupported(const std::vector<VkExtensionProperties> & supported_instance_extensions,std::string extension_name)262 bool VulkanApplication::ExtensionSupported(
263     const std::vector<VkExtensionProperties>& supported_instance_extensions,
264     std::string extension_name) {
265   uint32_t count = supported_instance_extensions.size();
266   for (size_t i = 0; i < count; i++) {
267     if (strncmp(supported_instance_extensions[i].extensionName,
268                 extension_name.c_str(), extension_name.size()) == 0) {
269       return true;
270     }
271   }
272 
273   return false;
274 }
275 
276 }  // namespace vulkan
277