7 #include "fml/concurrent_message_loop.h"
14 #include <sys/resource.h>
16 #endif // FML_OS_ANDROID
24 #include "flutter/fml/cpu_affinity.h"
25 #include "flutter/fml/trace_event.h"
41 VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
54 const vk::Instance& instance) {
55 for (
const auto& device : instance.enumeratePhysicalDevices().value) {
64 std::initializer_list<QueueIndexVK> queues) {
65 std::map<
size_t ,
size_t > family_index_map;
66 for (
const auto& queue : queues) {
67 family_index_map[queue.family] = 0;
69 for (
const auto& queue : queues) {
70 auto value = family_index_map[queue.family];
71 family_index_map[queue.family] = std::max(value, queue.index);
74 static float kQueuePriority = 1.0f;
75 std::vector<vk::DeviceQueueCreateInfo> infos;
76 for (
const auto& item : family_index_map) {
77 vk::DeviceQueueCreateInfo info;
78 info.setQueueFamilyIndex(item.first);
79 info.setQueueCount(item.second + 1);
80 info.setQueuePriorities(kQueuePriority);
81 infos.push_back(info);
86 static std::optional<QueueIndexVK>
PickQueue(
const vk::PhysicalDevice& device,
87 vk::QueueFlagBits flags) {
90 const auto families = device.getQueueFamilyProperties();
91 for (
size_t i = 0u; i < families.size(); i++) {
92 if (!(families[i].queueFlags & flags)) {
101 auto context = std::shared_ptr<ContextVK>(
new ContextVK());
102 context->Setup(std::move(settings));
103 if (!context->IsValid()) {
113 return std::clamp(hardware_concurrency / 2ull, 1ull, 4ull);
117 thread_local uint64_t tls_context_count = 0;
118 uint64_t CalculateHash(
void* ptr) {
121 return ++tls_context_count;
125 ContextVK::ContextVK() : hash_(CalculateHash(this)) {}
128 if (device_holder_ && device_holder_->device) {
129 [[maybe_unused]]
auto result = device_holder_->device->waitIdle();
138 void ContextVK::Setup(Settings settings) {
139 TRACE_EVENT0(
"impeller",
"ContextVK::Setup");
141 if (!settings.proc_address_callback) {
145 raster_message_loop_ = fml::ConcurrentMessageLoop::Create(
147 raster_message_loop_->PostTaskToAllWorkers([]() {
150 fml::RequestAffinity(fml::CpuAffinity::kNotPerformance);
151 #ifdef FML_OS_ANDROID
152 if (::setpriority(PRIO_PROCESS, gettid(), -5) != 0) {
153 FML_LOG(ERROR) <<
"Failed to set Workers task runner priority";
155 #endif // FML_OS_ANDROID
158 auto& dispatcher = VULKAN_HPP_DEFAULT_DISPATCHER;
159 dispatcher.init(settings.proc_address_callback);
165 auto enable_validation = settings.enable_validation;
167 #if defined(FML_OS_ANDROID) && !defined(NDEBUG)
168 enable_validation =
true;
172 std::shared_ptr<CapabilitiesVK>(
new CapabilitiesVK(enable_validation));
174 if (!caps->IsValid()) {
181 auto enabled_layers = caps->GetEnabledLayers();
182 auto enabled_extensions = caps->GetEnabledInstanceExtensions();
184 if (!enabled_layers.has_value() || !enabled_extensions.has_value()) {
189 vk::InstanceCreateFlags instance_flags = {};
191 if (std::find(enabled_extensions.value().begin(),
192 enabled_extensions.value().end(),
193 "VK_KHR_portability_enumeration") !=
194 enabled_extensions.value().end()) {
195 instance_flags |= vk::InstanceCreateFlagBits::eEnumeratePortabilityKHR;
198 std::vector<const char*> enabled_layers_c;
199 std::vector<const char*> enabled_extensions_c;
201 for (
const auto& layer : enabled_layers.value()) {
202 enabled_layers_c.push_back(layer.c_str());
205 for (
const auto& ext : enabled_extensions.value()) {
206 enabled_extensions_c.push_back(ext.c_str());
209 vk::ApplicationInfo application_info;
210 application_info.setApplicationVersion(VK_API_VERSION_1_0);
211 application_info.setApiVersion(VK_API_VERSION_1_1);
212 application_info.setEngineVersion(VK_API_VERSION_1_0);
213 application_info.setPEngineName(
"Impeller");
214 application_info.setPApplicationName(
"Impeller");
216 vk::StructureChain<vk::InstanceCreateInfo, vk::ValidationFeaturesEXT>
219 if (!caps->AreValidationsEnabled()) {
220 instance_chain.unlink<vk::ValidationFeaturesEXT>();
223 std::vector<vk::ValidationFeatureEnableEXT> enabled_validations = {
224 vk::ValidationFeatureEnableEXT::eSynchronizationValidation,
227 auto validation = instance_chain.get<vk::ValidationFeaturesEXT>();
228 validation.setEnabledValidationFeatures(enabled_validations);
230 auto instance_info = instance_chain.get<vk::InstanceCreateInfo>();
231 instance_info.setPEnabledLayerNames(enabled_layers_c);
232 instance_info.setPEnabledExtensionNames(enabled_extensions_c);
233 instance_info.setPApplicationInfo(&application_info);
234 instance_info.setFlags(instance_flags);
236 auto device_holder = std::make_shared<DeviceHolderImpl>();
238 auto instance = vk::createInstanceUnique(instance_info);
239 if (instance.result != vk::Result::eSuccess) {
241 << vk::to_string(instance.result);
244 device_holder->instance = std::move(instance.value);
246 dispatcher.init(device_holder->instance.get());
255 std::make_unique<DebugReportVK>(*caps, device_holder->instance.get());
257 if (!debug_report->IsValid()) {
266 auto physical_device =
268 if (!physical_device.has_value()) {
272 device_holder->physical_device = physical_device.value();
278 auto graphics_queue =
279 PickQueue(device_holder->physical_device, vk::QueueFlagBits::eGraphics);
280 auto transfer_queue =
281 PickQueue(device_holder->physical_device, vk::QueueFlagBits::eTransfer);
283 PickQueue(device_holder->physical_device, vk::QueueFlagBits::eCompute);
285 if (!graphics_queue.has_value()) {
289 if (!transfer_queue.has_value()) {
290 FML_LOG(INFO) <<
"Dedicated transfer queue not avialable.";
291 transfer_queue = graphics_queue.value();
293 if (!compute_queue.has_value()) {
301 auto enabled_device_extensions =
302 caps->GetEnabledDeviceExtensions(device_holder->physical_device);
303 if (!enabled_device_extensions.has_value()) {
309 std::vector<const char*> enabled_device_extensions_c;
310 for (
const auto& ext : enabled_device_extensions.value()) {
311 enabled_device_extensions_c.push_back(ext.c_str());
315 {graphics_queue.value(), compute_queue.value(), transfer_queue.value()});
317 const auto enabled_features =
318 caps->GetEnabledDeviceFeatures(device_holder->physical_device);
319 if (!enabled_features.has_value()) {
325 vk::DeviceCreateInfo device_info;
327 device_info.setPNext(&enabled_features.value().get());
328 device_info.setQueueCreateInfos(queue_create_infos);
329 device_info.setPEnabledExtensionNames(enabled_device_extensions_c);
334 device_holder->physical_device.createDeviceUnique(device_info);
335 if (device_result.result != vk::Result::eSuccess) {
339 device_holder->device = std::move(device_result.value);
342 if (!caps->SetPhysicalDevice(device_holder->physical_device)) {
350 auto allocator = std::shared_ptr<AllocatorVK>(
new AllocatorVK(
352 application_info.apiVersion,
353 device_holder->physical_device,
355 device_holder->instance.get(),
359 if (!allocator->IsValid()) {
367 auto pipeline_library = std::shared_ptr<PipelineLibraryVK>(
368 new PipelineLibraryVK(device_holder,
370 std::move(settings.cache_directory),
371 raster_message_loop_->GetTaskRunner()
374 if (!pipeline_library->IsValid()) {
379 auto sampler_library =
380 std::shared_ptr<SamplerLibraryVK>(
new SamplerLibraryVK(device_holder));
382 auto shader_library = std::shared_ptr<ShaderLibraryVK>(
383 new ShaderLibraryVK(device_holder,
384 settings.shader_libraries_data)
387 if (!shader_library->IsValid()) {
396 std::shared_ptr<FenceWaiterVK>(
new FenceWaiterVK(device_holder));
402 if (!resource_manager) {
407 auto command_pool_recycler =
408 std::make_shared<CommandPoolRecyclerVK>(weak_from_this());
409 if (!command_pool_recycler) {
414 auto descriptor_pool_recycler =
415 std::make_shared<DescriptorPoolRecyclerVK>(weak_from_this());
416 if (!descriptor_pool_recycler) {
424 QueuesVK queues(device_holder->device.get(),
425 graphics_queue.value(),
426 compute_queue.value(),
427 transfer_queue.value()
429 if (!queues.IsValid()) {
434 VkPhysicalDeviceProperties physical_device_properties;
435 dispatcher.vkGetPhysicalDeviceProperties(device_holder->physical_device,
436 &physical_device_properties);
441 device_holder_ = std::move(device_holder);
443 std::make_unique<DriverInfoVK>(device_holder_->physical_device);
444 debug_report_ = std::move(debug_report);
445 allocator_ = std::move(allocator);
446 shader_library_ = std::move(shader_library);
447 sampler_library_ = std::move(sampler_library);
448 pipeline_library_ = std::move(pipeline_library);
449 yuv_conversion_library_ = std::shared_ptr<YUVConversionLibraryVK>(
450 new YUVConversionLibraryVK(device_holder_));
451 queues_ = std::move(queues);
452 device_capabilities_ = std::move(caps);
453 fence_waiter_ = std::move(fence_waiter);
454 resource_manager_ = std::move(resource_manager);
455 command_pool_recycler_ = std::move(command_pool_recycler);
456 descriptor_pool_recycler_ = std::move(descriptor_pool_recycler);
457 device_name_ = std::string(physical_device_properties.deviceName);
458 command_queue_vk_ = std::make_shared<CommandQueueVK>(weak_from_this());
463 gpu_tracer_ = std::make_shared<GPUTracerVK>(weak_from_this(),
464 settings.enable_gpu_tracing);
465 gpu_tracer_->InitializeQueryPool(*
this);
492 return shader_library_;
496 return sampler_library_;
500 return pipeline_library_;
504 return std::shared_ptr<CommandBufferVK>(
506 CreateGraphicsCommandEncoderFactory())
511 return *device_holder_->instance;
515 return device_holder_->device.get();
518 const std::shared_ptr<fml::ConcurrentTaskRunner>
520 return raster_message_loop_->GetTaskRunner();
529 fence_waiter_.reset();
530 resource_manager_.reset();
532 raster_message_loop_->Terminate();
536 return std::make_shared<SurfaceContextVK>(shared_from_this());
540 return device_capabilities_;
548 return device_holder_->physical_device;
552 return fence_waiter_;
556 return resource_manager_;
561 return command_pool_recycler_;
564 std::unique_ptr<CommandEncoderFactoryVK>
565 ContextVK::CreateGraphicsCommandEncoderFactory()
const {
566 return std::make_unique<CommandEncoderFactoryVK>(weak_from_this());
575 return descriptor_pool_recycler_;
579 return command_queue_vk_;
594 color.texture->GetTextureDescriptor().format,
595 color.texture->GetTextureDescriptor().sample_count,
603 depth->texture->GetTextureDescriptor().format,
604 depth->texture->GetTextureDescriptor().sample_count,
609 stencil.has_value()) {
611 stencil->texture->GetTextureDescriptor().format,
612 stencil->texture->GetTextureDescriptor().sample_count,
613 stencil->load_action,
614 stencil->store_action
621 const std::shared_ptr<YUVConversionLibraryVK>&
623 return yuv_conversion_library_;