Flutter Engine
The Flutter Engine
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
10#include "flutter/vulkan/procs/vulkan_proc_table.h"
11#include "vulkan_device.h"
12#include "vulkan_utilities.h"
13
14namespace vulkan {
15
17 VulkanProcTable& p_vk, // NOLINT
18 const std::string& application_name,
19 std::vector<std::string> enabled_extensions,
20 uint32_t application_version,
21 uint32_t api_version,
22 bool enable_validation_layers)
23 : vk_(p_vk),
24 api_version_(api_version),
25 valid_(false),
26 enable_validation_layers_(enable_validation_layers) {
27 // Check if we want to enable debugging.
28 std::vector<VkExtensionProperties> supported_extensions =
29 GetSupportedInstanceExtensions(vk_);
30 bool enable_instance_debugging =
31 enable_validation_layers_ &&
32 ExtensionSupported(supported_extensions,
34
35 // Configure extensions.
36
37 if (enable_instance_debugging) {
38 enabled_extensions.emplace_back(VulkanDebugReport::DebugExtensionName());
39 }
40#if OS_FUCHSIA
41 if (ExtensionSupported(supported_extensions,
43 // VK_KHR_get_physical_device_properties2 is a dependency of the memory
44 // capabilities extension, so the validation layers require that it be
45 // enabled.
46 enabled_extensions.emplace_back(
48 enabled_extensions.emplace_back(
50 }
51#endif
52
53 std::vector<const char*> extensions;
54
55 for (size_t i = 0; i < enabled_extensions.size(); i++) {
56 extensions.push_back(enabled_extensions[i].c_str());
57 }
58
59 // Configure layers.
60
61 const std::vector<std::string> enabled_layers =
62 InstanceLayersToEnable(vk_, enable_validation_layers_);
63
64 std::vector<const char*> layers;
65
66 for (size_t i = 0; i < enabled_layers.size(); i++) {
67 layers.push_back(enabled_layers[i].c_str());
68 }
69
70 // Configure init structs.
71
72 const VkApplicationInfo info = {
74 .pNext = nullptr,
75 .pApplicationName = application_name.c_str(),
76 .applicationVersion = application_version,
77 .pEngineName = "FlutterEngine",
78 .engineVersion = VK_MAKE_VERSION(1, 0, 0),
79 .apiVersion = api_version_,
80 };
81
82 const VkInstanceCreateInfo create_info = {
84 .pNext = nullptr,
85 .flags = 0,
86 .pApplicationInfo = &info,
87 .enabledLayerCount = static_cast<uint32_t>(layers.size()),
88 .ppEnabledLayerNames = layers.data(),
89 .enabledExtensionCount = static_cast<uint32_t>(extensions.size()),
90 .ppEnabledExtensionNames = extensions.data(),
91 };
92
93 // Perform initialization.
94
95 VkInstance instance = VK_NULL_HANDLE;
96
97 if (VK_CALL_LOG_ERROR(vk_.CreateInstance(&create_info, nullptr, &instance)) !=
98 VK_SUCCESS) {
99 FML_DLOG(INFO) << "Could not create application instance.";
100 return;
101 }
102
103 // Now that we have an instance, set up instance proc table entries.
105 FML_DLOG(INFO) << "Could not set up instance proc addresses.";
106 return;
107 }
108
109 instance_ = VulkanHandle<VkInstance>{instance, [this](VkInstance i) {
110 FML_DLOG(INFO)
111 << "Destroying Vulkan instance";
112 vk_.DestroyInstance(i, nullptr);
113 }};
114
115 if (enable_instance_debugging) {
116 auto debug_report = std::make_unique<VulkanDebugReport>(vk_, instance_);
117 if (!debug_report->IsValid()) {
118 FML_DLOG(INFO) << "Vulkan debugging was enabled but could not be set up "
119 "for this instance.";
120 } else {
121 debug_report_ = std::move(debug_report);
122 FML_DLOG(INFO) << "Debug reporting is enabled.";
123 }
124 }
125
126 valid_ = true;
127}
128
130
132 return valid_;
133}
134
136 return api_version_;
137}
138
140 return instance_;
141}
142
144 instance_.ReleaseOwnership();
145}
146
147std::vector<VkPhysicalDevice> VulkanApplication::GetPhysicalDevices() const {
148 if (!IsValid()) {
149 return {};
150 }
151
152 uint32_t device_count = 0;
153 if (VK_CALL_LOG_ERROR(vk_.EnumeratePhysicalDevices(instance_, &device_count,
154 nullptr)) != VK_SUCCESS) {
155 FML_DLOG(INFO) << "Could not enumerate physical device.";
156 return {};
157 }
158
159 if (device_count == 0) {
160 // No available devices.
161 FML_DLOG(INFO) << "No physical devices found.";
162 return {};
163 }
164
165 std::vector<VkPhysicalDevice> physical_devices;
166
167 physical_devices.resize(device_count);
168
169 if (VK_CALL_LOG_ERROR(vk_.EnumeratePhysicalDevices(
170 instance_, &device_count, physical_devices.data())) != VK_SUCCESS) {
171 FML_DLOG(INFO) << "Could not enumerate physical device.";
172 return {};
173 }
174
175 return physical_devices;
176}
177
178std::unique_ptr<VulkanDevice>
180 for (auto device_handle : GetPhysicalDevices()) {
181 auto logical_device = std::make_unique<VulkanDevice>(
182 vk_, VulkanHandle<VkPhysicalDevice>(device_handle),
183 enable_validation_layers_);
184 if (logical_device->IsValid()) {
185 return logical_device;
186 }
187 }
188 FML_DLOG(INFO) << "Could not acquire compatible logical device.";
189 return nullptr;
190}
191
192std::vector<VkExtensionProperties>
193VulkanApplication::GetSupportedInstanceExtensions(
194 const VulkanProcTable& vk) const {
195 if (!vk.EnumerateInstanceExtensionProperties) {
196 return std::vector<VkExtensionProperties>();
197 }
198
199 uint32_t count = 0;
200 if (VK_CALL_LOG_ERROR(vk.EnumerateInstanceExtensionProperties(
201 nullptr, &count, nullptr)) != VK_SUCCESS) {
202 return std::vector<VkExtensionProperties>();
203 }
204
205 if (count == 0) {
206 return std::vector<VkExtensionProperties>();
207 }
208
209 std::vector<VkExtensionProperties> properties;
210 properties.resize(count);
211 if (VK_CALL_LOG_ERROR(vk.EnumerateInstanceExtensionProperties(
212 nullptr, &count, properties.data())) != VK_SUCCESS) {
213 return std::vector<VkExtensionProperties>();
214 }
215
216 return properties;
217}
218
219bool VulkanApplication::ExtensionSupported(
220 const std::vector<VkExtensionProperties>& supported_instance_extensions,
221 const std::string& extension_name) {
222 uint32_t count = supported_instance_extensions.size();
223 for (size_t i = 0; i < count; i++) {
224 if (strncmp(supported_instance_extensions[i].extensionName,
225 extension_name.c_str(), extension_name.size()) == 0) {
226 return true;
227 }
228 }
229
230 return false;
231}
232
233} // namespace vulkan
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
int count
Definition: FontMgrTest.cpp:50
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)
VkInstance instance
Definition: main.cc:48
#define FML_DLOG(severity)
Definition: logging.h:102
vk
Definition: malisc.py:42
std::vector< std::string > InstanceLayersToEnable(const VulkanProcTable &vk, bool enable_validation_layers)
VkStructureType sType
Definition: vulkan_core.h:3027
#define VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME
Definition: vulkan_core.h:8673
#define VK_MAKE_VERSION(major, minor, patch)
Definition: vulkan_core.h:78
#define VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME
Definition: vulkan_core.h:8511
@ VK_SUCCESS
Definition: vulkan_core.h:141
#define VK_NULL_HANDLE
Definition: vulkan_core.h:46
@ VK_STRUCTURE_TYPE_APPLICATION_INFO
Definition: vulkan_core.h:202
@ VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO
Definition: vulkan_core.h:203
#define VK_CALL_LOG_ERROR(expression)