9 #include <sys/resource.h>
11 #endif // FML_OS_ANDROID
19 #include "flutter/fml/cpu_affinity.h"
20 #include "flutter/fml/trace_event.h"
33 VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
46 const vk::Instance& instance) {
47 for (
const auto& device : instance.enumeratePhysicalDevices().value) {
56 std::initializer_list<QueueIndexVK> queues) {
57 std::map<
size_t ,
size_t > family_index_map;
58 for (
const auto& queue : queues) {
59 family_index_map[queue.family] = 0;
61 for (
const auto& queue : queues) {
62 auto value = family_index_map[queue.family];
63 family_index_map[queue.family] = std::max(value, queue.index);
66 static float kQueuePriority = 1.0f;
67 std::vector<vk::DeviceQueueCreateInfo> infos;
68 for (
const auto& item : family_index_map) {
69 vk::DeviceQueueCreateInfo info;
70 info.setQueueFamilyIndex(item.first);
71 info.setQueueCount(item.second + 1);
72 info.setQueuePriorities(kQueuePriority);
73 infos.push_back(info);
78 static std::optional<QueueIndexVK>
PickQueue(
const vk::PhysicalDevice& device,
79 vk::QueueFlagBits flags) {
82 const auto families = device.getQueueFamilyProperties();
83 for (
size_t i = 0u; i < families.size(); i++) {
84 if (!(families[i].queueFlags & flags)) {
93 auto context = std::shared_ptr<ContextVK>(
new ContextVK());
94 context->Setup(std::move(settings));
95 if (!context->IsValid()) {
102 thread_local uint64_t tls_context_count = 0;
103 uint64_t CalculateHash(
void* ptr) {
106 return ++tls_context_count;
110 ContextVK::ContextVK() : hash_(CalculateHash(this)) {}
113 if (device_holder_ && device_holder_->device) {
114 [[maybe_unused]]
auto result = device_holder_->device->waitIdle();
123 void ContextVK::Setup(Settings settings) {
124 TRACE_EVENT0(
"impeller",
"ContextVK::Setup");
126 if (!settings.proc_address_callback) {
130 raster_message_loop_ = fml::ConcurrentMessageLoop::Create(
131 std::min(4u, std::thread::hardware_concurrency()));
132 raster_message_loop_->PostTaskToAllWorkers([]() {
135 fml::RequestAffinity(fml::CpuAffinity::kNotPerformance);
136 #ifdef FML_OS_ANDROID
137 if (::setpriority(PRIO_PROCESS, gettid(), -5) != 0) {
138 FML_LOG(ERROR) <<
"Failed to set Workers task runner priority";
140 #endif // FML_OS_ANDROID
143 auto& dispatcher = VULKAN_HPP_DEFAULT_DISPATCHER;
144 dispatcher.init(settings.proc_address_callback);
150 auto enable_validation = settings.enable_validation;
152 #if defined(FML_OS_ANDROID) && !defined(NDEBUG)
153 enable_validation =
true;
157 std::shared_ptr<CapabilitiesVK>(
new CapabilitiesVK(enable_validation));
159 if (!caps->IsValid()) {
166 auto enabled_layers = caps->GetEnabledLayers();
167 auto enabled_extensions = caps->GetEnabledInstanceExtensions();
169 if (!enabled_layers.has_value() || !enabled_extensions.has_value()) {
174 vk::InstanceCreateFlags instance_flags = {};
176 if (std::find(enabled_extensions.value().begin(),
177 enabled_extensions.value().end(),
178 "VK_KHR_portability_enumeration") !=
179 enabled_extensions.value().end()) {
180 instance_flags |= vk::InstanceCreateFlagBits::eEnumeratePortabilityKHR;
183 std::vector<const char*> enabled_layers_c;
184 std::vector<const char*> enabled_extensions_c;
186 for (
const auto& layer : enabled_layers.value()) {
187 enabled_layers_c.push_back(layer.c_str());
190 for (
const auto& ext : enabled_extensions.value()) {
191 enabled_extensions_c.push_back(ext.c_str());
194 vk::ApplicationInfo application_info;
195 application_info.setApplicationVersion(VK_API_VERSION_1_0);
196 application_info.setApiVersion(VK_API_VERSION_1_1);
197 application_info.setEngineVersion(VK_API_VERSION_1_0);
198 application_info.setPEngineName(
"Impeller");
199 application_info.setPApplicationName(
"Impeller");
201 vk::StructureChain<vk::InstanceCreateInfo, vk::ValidationFeaturesEXT>
204 if (!caps->AreValidationsEnabled()) {
205 instance_chain.unlink<vk::ValidationFeaturesEXT>();
208 std::vector<vk::ValidationFeatureEnableEXT> enabled_validations = {
209 vk::ValidationFeatureEnableEXT::eSynchronizationValidation,
212 auto validation = instance_chain.get<vk::ValidationFeaturesEXT>();
213 validation.setEnabledValidationFeatures(enabled_validations);
215 auto instance_info = instance_chain.get<vk::InstanceCreateInfo>();
216 instance_info.setPEnabledLayerNames(enabled_layers_c);
217 instance_info.setPEnabledExtensionNames(enabled_extensions_c);
218 instance_info.setPApplicationInfo(&application_info);
219 instance_info.setFlags(instance_flags);
221 auto device_holder = std::make_shared<DeviceHolderImpl>();
223 auto instance = vk::createInstanceUnique(instance_info);
224 if (instance.result != vk::Result::eSuccess) {
226 << vk::to_string(instance.result);
229 device_holder->instance = std::move(instance.value);
231 dispatcher.init(device_holder->instance.get());
240 std::make_unique<DebugReportVK>(*caps, device_holder->instance.get());
242 if (!debug_report->IsValid()) {
251 auto physical_device =
253 if (!physical_device.has_value()) {
257 device_holder->physical_device = physical_device.value();
263 auto graphics_queue =
264 PickQueue(device_holder->physical_device, vk::QueueFlagBits::eGraphics);
265 auto transfer_queue =
266 PickQueue(device_holder->physical_device, vk::QueueFlagBits::eTransfer);
268 PickQueue(device_holder->physical_device, vk::QueueFlagBits::eCompute);
270 if (!graphics_queue.has_value()) {
274 if (!transfer_queue.has_value()) {
275 FML_LOG(INFO) <<
"Dedicated transfer queue not avialable.";
276 transfer_queue = graphics_queue.value();
278 if (!compute_queue.has_value()) {
286 auto enabled_device_extensions =
287 caps->GetEnabledDeviceExtensions(device_holder->physical_device);
288 if (!enabled_device_extensions.has_value()) {
294 std::vector<const char*> enabled_device_extensions_c;
295 for (
const auto& ext : enabled_device_extensions.value()) {
296 enabled_device_extensions_c.push_back(ext.c_str());
300 {graphics_queue.value(), compute_queue.value(), transfer_queue.value()});
302 const auto enabled_features =
303 caps->GetEnabledDeviceFeatures(device_holder->physical_device);
304 if (!enabled_features.has_value()) {
310 vk::DeviceCreateInfo device_info;
312 device_info.setQueueCreateInfos(queue_create_infos);
313 device_info.setPEnabledExtensionNames(enabled_device_extensions_c);
314 device_info.setPEnabledFeatures(&enabled_features.value());
319 device_holder->physical_device.createDeviceUnique(device_info);
320 if (device_result.result != vk::Result::eSuccess) {
324 device_holder->device = std::move(device_result.value);
327 if (!caps->SetPhysicalDevice(device_holder->physical_device)) {
335 auto allocator = std::shared_ptr<AllocatorVK>(
new AllocatorVK(
337 application_info.apiVersion,
338 device_holder->physical_device,
340 device_holder->instance.get(),
344 if (!allocator->IsValid()) {
352 auto pipeline_library = std::shared_ptr<PipelineLibraryVK>(
353 new PipelineLibraryVK(device_holder,
355 std::move(settings.cache_directory),
356 raster_message_loop_->GetTaskRunner()
359 if (!pipeline_library->IsValid()) {
364 auto sampler_library =
365 std::shared_ptr<SamplerLibraryVK>(
new SamplerLibraryVK(device_holder));
367 auto shader_library = std::shared_ptr<ShaderLibraryVK>(
368 new ShaderLibraryVK(device_holder,
369 settings.shader_libraries_data)
372 if (!shader_library->IsValid()) {
381 std::shared_ptr<FenceWaiterVK>(
new FenceWaiterVK(device_holder));
387 if (!resource_manager) {
392 auto command_pool_recycler =
393 std::make_shared<CommandPoolRecyclerVK>(weak_from_this());
394 if (!command_pool_recycler) {
402 QueuesVK queues(device_holder->device.get(),
403 graphics_queue.value(),
404 compute_queue.value(),
405 transfer_queue.value()
407 if (!queues.IsValid()) {
412 VkPhysicalDeviceProperties physical_device_properties;
413 dispatcher.vkGetPhysicalDeviceProperties(device_holder->physical_device,
414 &physical_device_properties);
419 device_holder_ = std::move(device_holder);
420 debug_report_ = std::move(debug_report);
421 allocator_ = std::move(allocator);
422 shader_library_ = std::move(shader_library);
423 sampler_library_ = std::move(sampler_library);
424 pipeline_library_ = std::move(pipeline_library);
425 queues_ = std::move(queues);
426 device_capabilities_ = std::move(caps);
427 fence_waiter_ = std::move(fence_waiter);
428 resource_manager_ = std::move(resource_manager);
429 command_pool_recycler_ = std::move(command_pool_recycler);
430 device_name_ = std::string(physical_device_properties.deviceName);
458 return shader_library_;
462 return sampler_library_;
466 return pipeline_library_;
470 return std::shared_ptr<CommandBufferVK>(
472 CreateGraphicsCommandEncoderFactory())
477 return *device_holder_->instance;
481 return device_holder_->device.get();
484 const std::shared_ptr<fml::ConcurrentTaskRunner>
486 return raster_message_loop_->GetTaskRunner();
495 fence_waiter_.reset();
496 resource_manager_.reset();
498 raster_message_loop_->Terminate();
502 return std::make_shared<SurfaceContextVK>(shared_from_this());
506 return device_capabilities_;
514 return device_holder_->physical_device;
518 return fence_waiter_;
522 return resource_manager_;
527 return command_pool_recycler_;
530 std::unique_ptr<CommandEncoderFactoryVK>
531 ContextVK::CreateGraphicsCommandEncoderFactory()
const {
532 return std::make_unique<CommandEncoderFactoryVK>(weak_from_this());