Flutter Engine
 
Loading...
Searching...
No Matches
vulkan_application.cc
Go to the documentation of this file.
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
6
7#include <utility>
8#include <vector>
9
11#include "vulkan_device.h"
12#include "vulkan_utilities.h"
13
14namespace vulkan {
15
16// static
17VKAPI_ATTR VkBool32
18VulkanApplication::DebugReportCallback(VkDebugReportFlagsEXT flags,
19 VkDebugReportObjectTypeEXT objectType,
20 uint64_t object,
21 size_t location,
22 int32_t messageCode,
23 const char* pLayerPrefix,
24 const char* pMessage,
25 void* pUserData) {
26 auto application = static_cast<VulkanApplication*>(pUserData);
27 if (application->initialization_logs_enabled_) {
28 application->initialization_logs_ += pMessage;
29 application->initialization_logs_ += "\n";
30 }
31
32 return VK_FALSE;
33}
34
36 VulkanProcTable& p_vk, // NOLINT
37 const std::string& application_name,
38 std::vector<std::string> enabled_extensions,
39 uint32_t application_version,
40 uint32_t api_version,
42 : valid_(false),
43 enable_validation_layers_(enable_validation_layers),
44 api_version_(api_version),
45 vk_(p_vk) {
46 // Check if we want to enable debugging.
47 std::vector<VkExtensionProperties> supported_extensions =
48 GetSupportedInstanceExtensions(vk_);
49 bool enable_instance_debugging =
50 enable_validation_layers_ &&
51 ExtensionSupported(supported_extensions,
53
54 // Configure extensions.
55
56 if (enable_instance_debugging) {
57 enabled_extensions.emplace_back(VulkanDebugReport::DebugExtensionName());
58 }
59#if OS_FUCHSIA
60 if (ExtensionSupported(supported_extensions,
61 VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME)) {
62 // VK_KHR_get_physical_device_properties2 is a dependency of the memory
63 // capabilities extension, so the validation layers require that it be
64 // enabled.
65 enabled_extensions.emplace_back(
66 VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
67 enabled_extensions.emplace_back(
68 VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME);
69 }
70#endif
71
72 std::vector<const char*> extensions;
73
74 extensions.reserve(enabled_extensions.size());
75 for (size_t i = 0; i < enabled_extensions.size(); i++) {
76 extensions.push_back(enabled_extensions[i].c_str());
77 }
78
79 // Configure layers.
80
81 const std::vector<std::string> enabled_layers =
82 InstanceLayersToEnable(vk_, enable_validation_layers_);
83
84 std::vector<const char*> layers;
85
86 layers.reserve(enabled_layers.size());
87 for (size_t i = 0; i < enabled_layers.size(); i++) {
88 layers.push_back(enabled_layers[i].c_str());
89 }
90
91 // Configure init structs.
92
93 const VkApplicationInfo info = {
94 .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
95 .pNext = nullptr,
96 .pApplicationName = application_name.c_str(),
97 .applicationVersion = application_version,
98 .pEngineName = "FlutterEngine",
99 .engineVersion = VK_MAKE_VERSION(1, 0, 0),
100 .apiVersion = api_version_,
101 };
102
103 const VkDebugReportCallbackCreateInfoEXT debug_report_info = {
104 .sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT,
105 .pNext = nullptr,
106 .flags = VK_DEBUG_REPORT_INFORMATION_BIT_EXT |
107 VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_ERROR_BIT_EXT |
108 VK_DEBUG_REPORT_DEBUG_BIT_EXT,
109 .pfnCallback = &DebugReportCallback,
110 .pUserData = this};
111
112 const VkInstanceCreateInfo create_info = {
113 .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
114 .pNext = ExtensionSupported(supported_extensions,
115 VK_EXT_DEBUG_REPORT_EXTENSION_NAME)
116 ? &debug_report_info
117 : nullptr,
118 .flags = 0,
119 .pApplicationInfo = &info,
120 .enabledLayerCount = static_cast<uint32_t>(layers.size()),
121 .ppEnabledLayerNames = layers.data(),
122 .enabledExtensionCount = static_cast<uint32_t>(extensions.size()),
123 .ppEnabledExtensionNames = extensions.data(),
124 };
125
126 // Perform initialization.
127
128 VkInstance instance = VK_NULL_HANDLE;
129
130 if (VK_CALL_LOG_ERROR(vk_.CreateInstance(&create_info, nullptr, &instance)) !=
131 VK_SUCCESS) {
132 FML_LOG(ERROR) << "Creating application instance failed with error:\n"
133 << initialization_logs_;
134 return;
135 }
136
137 // The debug report callback will also be used in vkDestroyInstance, but we
138 // don't need its data there.
139 initialization_logs_enabled_ = false;
140 initialization_logs_.clear();
141
142 // Now that we have an instance, set up instance proc table entries.
144 FML_DLOG(INFO) << "Could not set up instance proc addresses.";
145 return;
146 }
147
148 instance_ = VulkanHandle<VkInstance>{instance, [this](VkInstance i) {
149 FML_DLOG(INFO)
150 << "Destroying Vulkan instance";
151 vk_.DestroyInstance(i, nullptr);
152 }};
153
154 if (enable_instance_debugging) {
155 auto debug_report = std::make_unique<VulkanDebugReport>(vk_, instance_);
156 if (!debug_report->IsValid()) {
157 FML_DLOG(INFO) << "Vulkan debugging was enabled but could not be set up "
158 "for this instance.";
159 } else {
160 debug_report_ = std::move(debug_report);
161 FML_DLOG(INFO) << "Debug reporting is enabled.";
162 }
163 }
164
165 valid_ = true;
166}
167
169
171 return valid_;
172}
173
175 return api_version_;
176}
177
179 return instance_;
180}
181
185
186std::vector<VkPhysicalDevice> VulkanApplication::GetPhysicalDevices() const {
187 if (!IsValid()) {
188 return {};
189 }
190
191 uint32_t device_count = 0;
192 if (VK_CALL_LOG_ERROR(vk_.EnumeratePhysicalDevices(instance_, &device_count,
193 nullptr)) != VK_SUCCESS) {
194 FML_DLOG(INFO) << "Could not enumerate physical device.";
195 return {};
196 }
197
198 if (device_count == 0) {
199 // No available devices.
200 FML_DLOG(INFO) << "No physical devices found.";
201 return {};
202 }
203
204 std::vector<VkPhysicalDevice> physical_devices;
205
206 physical_devices.resize(device_count);
207
208 if (VK_CALL_LOG_ERROR(vk_.EnumeratePhysicalDevices(
209 instance_, &device_count, physical_devices.data())) != VK_SUCCESS) {
210 FML_DLOG(INFO) << "Could not enumerate physical device.";
211 return {};
212 }
213
214 return physical_devices;
215}
216
217std::unique_ptr<VulkanDevice>
219 for (auto device_handle : GetPhysicalDevices()) {
220 auto logical_device = std::make_unique<VulkanDevice>(
221 vk_, VulkanHandle<VkPhysicalDevice>(device_handle),
222 enable_validation_layers_);
223 if (logical_device->IsValid()) {
224 return logical_device;
225 }
226 }
227 FML_DLOG(INFO) << "Could not acquire compatible logical device.";
228 return nullptr;
229}
230
231std::vector<VkExtensionProperties>
232VulkanApplication::GetSupportedInstanceExtensions(
233 const VulkanProcTable& vk) const {
234 if (!vk.EnumerateInstanceExtensionProperties) {
235 return std::vector<VkExtensionProperties>();
236 }
237
238 uint32_t count = 0;
239 if (VK_CALL_LOG_ERROR(vk.EnumerateInstanceExtensionProperties(
240 nullptr, &count, nullptr)) != VK_SUCCESS) {
241 return std::vector<VkExtensionProperties>();
242 }
243
244 if (count == 0) {
245 return std::vector<VkExtensionProperties>();
246 }
247
248 std::vector<VkExtensionProperties> properties;
249 properties.resize(count);
250 if (VK_CALL_LOG_ERROR(vk.EnumerateInstanceExtensionProperties(
251 nullptr, &count, properties.data())) != VK_SUCCESS) {
252 return std::vector<VkExtensionProperties>();
253 }
254
255 return properties;
256}
257
258bool VulkanApplication::ExtensionSupported(
259 const std::vector<VkExtensionProperties>& supported_instance_extensions,
260 const std::string& extension_name) {
261 uint32_t count = supported_instance_extensions.size();
262 for (size_t i = 0; i < count; i++) {
263 if (strncmp(supported_instance_extensions[i].extensionName,
264 extension_name.c_str(), extension_name.size()) == 0) {
265 return true;
266 }
267 }
268
269 return false;
270}
271
272} // namespace vulkan
const VulkanHandle< VkInstance > & GetInstance() const
std::unique_ptr< VulkanDevice > AcquireFirstCompatibleLogicalDevice() const
VulkanApplication(VulkanProcTable &vk, const std::string &application_name, std::vector< std::string > enabled_extensions, uint32_t application_version=VK_MAKE_VERSION(1, 0, 0), uint32_t api_version=VK_MAKE_VERSION(1, 0, 0), bool enable_validation_layers=false)
static std::string DebugExtensionName()
bool SetupInstanceProcAddresses(const VulkanHandle< VkInstance > &instance)
bool enable_validation_layers
Definition main.cc:36
VkInstance instance
Definition main.cc:64
const FlutterLayer ** layers
#define FML_DLOG(severity)
Definition logging.h:121
#define FML_LOG(severity)
Definition logging.h:101
std::vector< std::string > InstanceLayersToEnable(const VulkanProcTable &vk, bool enable_validation_layers)
FlutterSize size
The size of the layer (in physical pixels).
Definition embedder.h:2147
#define VK_CALL_LOG_ERROR(expression)