7 #include "fml/concurrent_message_loop.h"
11 #include <sys/resource.h>
13 #endif // FML_OS_ANDROID
21 #include "flutter/fml/cpu_affinity.h"
22 #include "flutter/fml/trace_event.h"
36 VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
49 const vk::Instance& instance) {
50 for (
const auto& device : instance.enumeratePhysicalDevices().value) {
59 std::initializer_list<QueueIndexVK> queues) {
60 std::map<
size_t ,
size_t > family_index_map;
61 for (
const auto& queue : queues) {
62 family_index_map[queue.family] = 0;
64 for (
const auto& queue : queues) {
65 auto value = family_index_map[queue.family];
66 family_index_map[queue.family] = std::max(value, queue.index);
69 static float kQueuePriority = 1.0f;
70 std::vector<vk::DeviceQueueCreateInfo> infos;
71 for (
const auto& item : family_index_map) {
72 vk::DeviceQueueCreateInfo info;
73 info.setQueueFamilyIndex(item.first);
74 info.setQueueCount(item.second + 1);
75 info.setQueuePriorities(kQueuePriority);
76 infos.push_back(info);
81 static std::optional<QueueIndexVK>
PickQueue(
const vk::PhysicalDevice& device,
82 vk::QueueFlagBits flags) {
85 const auto families = device.getQueueFamilyProperties();
86 for (
size_t i = 0u; i < families.size(); i++) {
87 if (!(families[i].queueFlags & flags)) {
96 auto context = std::shared_ptr<ContextVK>(
new ContextVK());
97 context->Setup(std::move(settings));
98 if (!context->IsValid()) {
105 thread_local uint64_t tls_context_count = 0;
106 uint64_t CalculateHash(
void* ptr) {
109 return ++tls_context_count;
113 ContextVK::ContextVK() : hash_(CalculateHash(this)) {}
116 if (device_holder_ && device_holder_->device) {
117 [[maybe_unused]]
auto result = device_holder_->device->waitIdle();
126 void ContextVK::Setup(Settings settings) {
127 TRACE_EVENT0(
"impeller",
"ContextVK::Setup");
129 if (!settings.proc_address_callback) {
133 queue_submit_thread_ = std::make_unique<fml::Thread>(
"QueueSubmitThread");
134 queue_submit_thread_->GetTaskRunner()->PostTask([]() {
136 fml::RequestAffinity(fml::CpuAffinity::kEfficiency);
139 raster_message_loop_ = fml::ConcurrentMessageLoop::Create(
140 std::min(4u, std::thread::hardware_concurrency()));
141 raster_message_loop_->PostTaskToAllWorkers([]() {
144 fml::RequestAffinity(fml::CpuAffinity::kNotPerformance);
145 #ifdef FML_OS_ANDROID
146 if (::setpriority(PRIO_PROCESS, gettid(), -5) != 0) {
147 FML_LOG(ERROR) <<
"Failed to set Workers task runner priority";
149 #endif // FML_OS_ANDROID
152 auto& dispatcher = VULKAN_HPP_DEFAULT_DISPATCHER;
153 dispatcher.init(settings.proc_address_callback);
159 auto enable_validation = settings.enable_validation;
161 #if defined(FML_OS_ANDROID) && !defined(NDEBUG)
162 enable_validation =
true;
166 std::shared_ptr<CapabilitiesVK>(
new CapabilitiesVK(enable_validation));
168 if (!caps->IsValid()) {
175 auto enabled_layers = caps->GetEnabledLayers();
176 auto enabled_extensions = caps->GetEnabledInstanceExtensions();
178 if (!enabled_layers.has_value() || !enabled_extensions.has_value()) {
183 vk::InstanceCreateFlags instance_flags = {};
185 if (std::find(enabled_extensions.value().begin(),
186 enabled_extensions.value().end(),
187 "VK_KHR_portability_enumeration") !=
188 enabled_extensions.value().end()) {
189 instance_flags |= vk::InstanceCreateFlagBits::eEnumeratePortabilityKHR;
192 std::vector<const char*> enabled_layers_c;
193 std::vector<const char*> enabled_extensions_c;
195 for (
const auto& layer : enabled_layers.value()) {
196 enabled_layers_c.push_back(layer.c_str());
199 for (
const auto& ext : enabled_extensions.value()) {
200 enabled_extensions_c.push_back(ext.c_str());
203 vk::ApplicationInfo application_info;
204 application_info.setApplicationVersion(VK_API_VERSION_1_0);
205 application_info.setApiVersion(VK_API_VERSION_1_1);
206 application_info.setEngineVersion(VK_API_VERSION_1_0);
207 application_info.setPEngineName(
"Impeller");
208 application_info.setPApplicationName(
"Impeller");
210 vk::StructureChain<vk::InstanceCreateInfo, vk::ValidationFeaturesEXT>
213 if (!caps->AreValidationsEnabled()) {
214 instance_chain.unlink<vk::ValidationFeaturesEXT>();
217 std::vector<vk::ValidationFeatureEnableEXT> enabled_validations = {
218 vk::ValidationFeatureEnableEXT::eSynchronizationValidation,
221 auto validation = instance_chain.get<vk::ValidationFeaturesEXT>();
222 validation.setEnabledValidationFeatures(enabled_validations);
224 auto instance_info = instance_chain.get<vk::InstanceCreateInfo>();
225 instance_info.setPEnabledLayerNames(enabled_layers_c);
226 instance_info.setPEnabledExtensionNames(enabled_extensions_c);
227 instance_info.setPApplicationInfo(&application_info);
228 instance_info.setFlags(instance_flags);
230 auto device_holder = std::make_shared<DeviceHolderImpl>();
232 auto instance = vk::createInstanceUnique(instance_info);
233 if (instance.result != vk::Result::eSuccess) {
235 << vk::to_string(instance.result);
238 device_holder->instance = std::move(instance.value);
240 dispatcher.init(device_holder->instance.get());
249 std::make_unique<DebugReportVK>(*caps, device_holder->instance.get());
251 if (!debug_report->IsValid()) {
260 auto physical_device =
262 if (!physical_device.has_value()) {
266 device_holder->physical_device = physical_device.value();
272 auto graphics_queue =
273 PickQueue(device_holder->physical_device, vk::QueueFlagBits::eGraphics);
274 auto transfer_queue =
275 PickQueue(device_holder->physical_device, vk::QueueFlagBits::eTransfer);
277 PickQueue(device_holder->physical_device, vk::QueueFlagBits::eCompute);
279 if (!graphics_queue.has_value()) {
283 if (!transfer_queue.has_value()) {
284 FML_LOG(INFO) <<
"Dedicated transfer queue not avialable.";
285 transfer_queue = graphics_queue.value();
287 if (!compute_queue.has_value()) {
295 auto enabled_device_extensions =
296 caps->GetEnabledDeviceExtensions(device_holder->physical_device);
297 if (!enabled_device_extensions.has_value()) {
303 std::vector<const char*> enabled_device_extensions_c;
304 for (
const auto& ext : enabled_device_extensions.value()) {
305 enabled_device_extensions_c.push_back(ext.c_str());
309 {graphics_queue.value(), compute_queue.value(), transfer_queue.value()});
311 const auto enabled_features =
312 caps->GetEnabledDeviceFeatures(device_holder->physical_device);
313 if (!enabled_features.has_value()) {
319 vk::DeviceCreateInfo device_info;
321 device_info.setQueueCreateInfos(queue_create_infos);
322 device_info.setPEnabledExtensionNames(enabled_device_extensions_c);
323 device_info.setPEnabledFeatures(&enabled_features.value());
328 device_holder->physical_device.createDeviceUnique(device_info);
329 if (device_result.result != vk::Result::eSuccess) {
333 device_holder->device = std::move(device_result.value);
336 if (!caps->SetPhysicalDevice(device_holder->physical_device)) {
344 auto allocator = std::shared_ptr<AllocatorVK>(
new AllocatorVK(
346 application_info.apiVersion,
347 device_holder->physical_device,
349 device_holder->instance.get(),
353 if (!allocator->IsValid()) {
361 auto pipeline_library = std::shared_ptr<PipelineLibraryVK>(
362 new PipelineLibraryVK(device_holder,
364 std::move(settings.cache_directory),
365 raster_message_loop_->GetTaskRunner()
368 if (!pipeline_library->IsValid()) {
373 auto sampler_library =
374 std::shared_ptr<SamplerLibraryVK>(
new SamplerLibraryVK(device_holder));
376 auto shader_library = std::shared_ptr<ShaderLibraryVK>(
377 new ShaderLibraryVK(device_holder,
378 settings.shader_libraries_data)
381 if (!shader_library->IsValid()) {
390 std::shared_ptr<FenceWaiterVK>(
new FenceWaiterVK(device_holder));
396 if (!resource_manager) {
401 auto command_pool_recycler =
402 std::make_shared<CommandPoolRecyclerVK>(weak_from_this());
403 if (!command_pool_recycler) {
408 auto descriptor_pool_recycler =
409 std::make_shared<DescriptorPoolRecyclerVK>(weak_from_this());
410 if (!descriptor_pool_recycler) {
418 QueuesVK queues(device_holder->device.get(),
419 graphics_queue.value(),
420 compute_queue.value(),
421 transfer_queue.value()
423 if (!queues.IsValid()) {
428 VkPhysicalDeviceProperties physical_device_properties;
429 dispatcher.vkGetPhysicalDeviceProperties(device_holder->physical_device,
430 &physical_device_properties);
435 device_holder_ = std::move(device_holder);
436 debug_report_ = std::move(debug_report);
437 allocator_ = std::move(allocator);
438 shader_library_ = std::move(shader_library);
439 sampler_library_ = std::move(sampler_library);
440 pipeline_library_ = std::move(pipeline_library);
441 queues_ = std::move(queues);
442 device_capabilities_ = std::move(caps);
443 fence_waiter_ = std::move(fence_waiter);
444 resource_manager_ = std::move(resource_manager);
445 command_pool_recycler_ = std::move(command_pool_recycler);
446 descriptor_pool_recycler_ = std::move(descriptor_pool_recycler);
447 device_name_ = std::string(physical_device_properties.deviceName);
479 return shader_library_;
483 return sampler_library_;
487 return pipeline_library_;
491 return std::shared_ptr<CommandBufferVK>(
493 CreateGraphicsCommandEncoderFactory())
498 return *device_holder_->instance;
502 return device_holder_->device.get();
506 return queue_submit_thread_->GetTaskRunner();
509 const std::shared_ptr<fml::ConcurrentTaskRunner>
511 return raster_message_loop_->GetTaskRunner();
520 fence_waiter_.reset();
521 resource_manager_.reset();
523 queue_submit_thread_->Join();
524 raster_message_loop_->Terminate();
528 return std::make_shared<SurfaceContextVK>(shared_from_this());
532 return device_capabilities_;
540 return device_holder_->physical_device;
544 return fence_waiter_;
548 return resource_manager_;
553 return command_pool_recycler_;
556 std::unique_ptr<CommandEncoderFactoryVK>
557 ContextVK::CreateGraphicsCommandEncoderFactory()
const {
558 return std::make_unique<CommandEncoderFactoryVK>(weak_from_this());