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"
40 VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
52 const vk::Instance& instance) {
53 for (
const auto& device : instance.enumeratePhysicalDevices().value) {
62 std::initializer_list<QueueIndexVK> queues) {
63 std::map<
size_t ,
size_t > family_index_map;
64 for (
const auto& queue : queues) {
65 family_index_map[queue.family] = 0;
67 for (
const auto& queue : queues) {
68 auto value = family_index_map[queue.family];
69 family_index_map[queue.family] = std::max(value, queue.index);
72 static float kQueuePriority = 1.0f;
73 std::vector<vk::DeviceQueueCreateInfo> infos;
74 for (
const auto& item : family_index_map) {
75 vk::DeviceQueueCreateInfo info;
76 info.setQueueFamilyIndex(item.first);
77 info.setQueueCount(item.second + 1);
78 info.setQueuePriorities(kQueuePriority);
79 infos.push_back(info);
84 static std::optional<QueueIndexVK>
PickQueue(
const vk::PhysicalDevice& device,
85 vk::QueueFlagBits flags) {
88 const auto families = device.getQueueFamilyProperties();
89 for (
size_t i = 0u; i < families.size(); i++) {
90 if (!(families[i].queueFlags & flags)) {
99 auto context = std::shared_ptr<ContextVK>(
new ContextVK());
100 context->Setup(std::move(settings));
101 if (!context->IsValid()) {
111 return std::clamp(hardware_concurrency / 2ull, 1ull, 4ull);
115 thread_local uint64_t tls_context_count = 0;
116 uint64_t CalculateHash(
void* ptr) {
119 return ++tls_context_count;
123 ContextVK::ContextVK() : hash_(CalculateHash(this)) {}
126 if (device_holder_ && device_holder_->device) {
127 [[maybe_unused]]
auto result = device_holder_->device->waitIdle();
136 void ContextVK::Setup(Settings settings) {
137 TRACE_EVENT0(
"impeller",
"ContextVK::Setup");
139 if (!settings.proc_address_callback) {
145 raster_message_loop_->PostTaskToAllWorkers([]() {
148 fml::RequestAffinity(fml::CpuAffinity::kNotPerformance);
149 #ifdef FML_OS_ANDROID
150 if (::setpriority(PRIO_PROCESS, gettid(), -5) != 0) {
151 FML_LOG(ERROR) <<
"Failed to set Workers task runner priority";
153 #endif // FML_OS_ANDROID
156 auto& dispatcher = VULKAN_HPP_DEFAULT_DISPATCHER;
157 dispatcher.init(settings.proc_address_callback);
159 auto caps = std::shared_ptr<CapabilitiesVK>(
new CapabilitiesVK(
160 settings.enable_validation, settings.fatal_missing_validations));
162 if (!caps->IsValid()) {
169 auto enabled_layers = caps->GetEnabledLayers();
170 auto enabled_extensions = caps->GetEnabledInstanceExtensions();
172 if (!enabled_layers.has_value() || !enabled_extensions.has_value()) {
177 vk::InstanceCreateFlags instance_flags = {};
179 if (std::find(enabled_extensions.value().begin(),
180 enabled_extensions.value().end(),
181 "VK_KHR_portability_enumeration") !=
182 enabled_extensions.value().end()) {
183 instance_flags |= vk::InstanceCreateFlagBits::eEnumeratePortabilityKHR;
186 std::vector<const char*> enabled_layers_c;
187 std::vector<const char*> enabled_extensions_c;
189 for (
const auto& layer : enabled_layers.value()) {
190 enabled_layers_c.push_back(layer.c_str());
193 for (
const auto& ext : enabled_extensions.value()) {
194 enabled_extensions_c.push_back(ext.c_str());
197 vk::ApplicationInfo application_info;
198 application_info.setApplicationVersion(VK_API_VERSION_1_0);
199 application_info.setApiVersion(VK_API_VERSION_1_1);
200 application_info.setEngineVersion(VK_API_VERSION_1_0);
201 application_info.setPEngineName(
"Impeller");
202 application_info.setPApplicationName(
"Impeller");
204 vk::StructureChain<vk::InstanceCreateInfo, vk::ValidationFeaturesEXT>
207 if (!caps->AreValidationsEnabled()) {
208 instance_chain.unlink<vk::ValidationFeaturesEXT>();
211 std::vector<vk::ValidationFeatureEnableEXT> enabled_validations = {
212 vk::ValidationFeatureEnableEXT::eSynchronizationValidation,
215 auto validation = instance_chain.get<vk::ValidationFeaturesEXT>();
216 validation.setEnabledValidationFeatures(enabled_validations);
218 auto instance_info = instance_chain.get<vk::InstanceCreateInfo>();
219 instance_info.setPEnabledLayerNames(enabled_layers_c);
220 instance_info.setPEnabledExtensionNames(enabled_extensions_c);
221 instance_info.setPApplicationInfo(&application_info);
222 instance_info.setFlags(instance_flags);
224 auto device_holder = std::make_shared<DeviceHolderImpl>();
226 auto instance = vk::createInstanceUnique(instance_info);
227 if (instance.result != vk::Result::eSuccess) {
229 << vk::to_string(instance.result);
232 device_holder->instance = std::move(instance.value);
234 dispatcher.init(device_holder->instance.get());
243 std::make_unique<DebugReportVK>(*caps, device_holder->instance.get());
245 if (!debug_report->IsValid()) {
254 auto physical_device =
256 if (!physical_device.has_value()) {
260 device_holder->physical_device = physical_device.value();
266 auto graphics_queue =
267 PickQueue(device_holder->physical_device, vk::QueueFlagBits::eGraphics);
268 auto transfer_queue =
269 PickQueue(device_holder->physical_device, vk::QueueFlagBits::eTransfer);
271 PickQueue(device_holder->physical_device, vk::QueueFlagBits::eCompute);
273 if (!graphics_queue.has_value()) {
277 if (!transfer_queue.has_value()) {
278 transfer_queue = graphics_queue.value();
280 if (!compute_queue.has_value()) {
288 auto enabled_device_extensions =
289 caps->GetEnabledDeviceExtensions(device_holder->physical_device);
290 if (!enabled_device_extensions.has_value()) {
296 std::vector<const char*> enabled_device_extensions_c;
297 for (
const auto& ext : enabled_device_extensions.value()) {
298 enabled_device_extensions_c.push_back(ext.c_str());
302 {graphics_queue.value(), compute_queue.value(), transfer_queue.value()});
304 const auto enabled_features =
305 caps->GetEnabledDeviceFeatures(device_holder->physical_device);
306 if (!enabled_features.has_value()) {
312 vk::DeviceCreateInfo device_info;
314 device_info.setPNext(&enabled_features.value().get());
315 device_info.setQueueCreateInfos(queue_create_infos);
316 device_info.setPEnabledExtensionNames(enabled_device_extensions_c);
321 device_holder->physical_device.createDeviceUnique(device_info);
322 if (device_result.result != vk::Result::eSuccess) {
326 device_holder->device = std::move(device_result.value);
329 if (!caps->SetPhysicalDevice(device_holder->physical_device,
330 *enabled_features)) {
338 auto allocator = std::shared_ptr<AllocatorVK>(
new AllocatorVK(
340 application_info.apiVersion,
341 device_holder->physical_device,
343 device_holder->instance.get(),
347 if (!allocator->IsValid()) {
355 auto pipeline_library = std::shared_ptr<PipelineLibraryVK>(
356 new PipelineLibraryVK(device_holder,
358 std::move(settings.cache_directory),
359 raster_message_loop_->GetTaskRunner()
362 if (!pipeline_library->IsValid()) {
367 auto sampler_library =
368 std::shared_ptr<SamplerLibraryVK>(
new SamplerLibraryVK(device_holder));
370 auto shader_library = std::shared_ptr<ShaderLibraryVK>(
371 new ShaderLibraryVK(device_holder,
372 settings.shader_libraries_data)
375 if (!shader_library->IsValid()) {
384 std::shared_ptr<FenceWaiterVK>(
new FenceWaiterVK(device_holder));
390 if (!resource_manager) {
395 auto command_pool_recycler =
396 std::make_shared<CommandPoolRecyclerVK>(weak_from_this());
397 if (!command_pool_recycler) {
402 auto descriptor_pool_recycler =
403 std::make_shared<DescriptorPoolRecyclerVK>(weak_from_this());
404 if (!descriptor_pool_recycler) {
412 QueuesVK queues(device_holder->device.get(),
413 graphics_queue.value(),
414 compute_queue.value(),
415 transfer_queue.value()
417 if (!queues.IsValid()) {
422 VkPhysicalDeviceProperties physical_device_properties;
423 dispatcher.vkGetPhysicalDeviceProperties(device_holder->physical_device,
424 &physical_device_properties);
429 device_holder_ = std::move(device_holder);
431 std::make_unique<DriverInfoVK>(device_holder_->physical_device);
432 debug_report_ = std::move(debug_report);
433 allocator_ = std::move(allocator);
434 shader_library_ = std::move(shader_library);
435 sampler_library_ = std::move(sampler_library);
436 pipeline_library_ = std::move(pipeline_library);
437 yuv_conversion_library_ = std::shared_ptr<YUVConversionLibraryVK>(
438 new YUVConversionLibraryVK(device_holder_));
439 queues_ = std::move(queues);
440 device_capabilities_ = std::move(caps);
441 fence_waiter_ = std::move(fence_waiter);
442 resource_manager_ = std::move(resource_manager);
443 command_pool_recycler_ = std::move(command_pool_recycler);
444 descriptor_pool_recycler_ = std::move(descriptor_pool_recycler);
445 device_name_ = std::string(physical_device_properties.deviceName);
446 command_queue_vk_ = std::make_shared<CommandQueueVK>(weak_from_this());
447 should_disable_surface_control_ = settings.disable_surface_control;
452 gpu_tracer_ = std::make_shared<GPUTracerVK>(weak_from_this(),
453 settings.enable_gpu_tracing);
454 gpu_tracer_->InitializeQueryPool(*
this);
481 return shader_library_;
485 return sampler_library_;
489 return pipeline_library_;
494 auto tls_pool = recycler->Get();
499 auto tracked_objects = std::make_shared<TrackedObjectsVK>(
500 weak_from_this(), std::move(tls_pool),
GetGPUTracer()->CreateGPUProbe());
503 if (!tracked_objects || !tracked_objects->IsValid() || !queue) {
507 vk::CommandBufferBeginInfo begin_info;
508 begin_info.flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit;
509 if (tracked_objects->GetCommandBuffer().begin(begin_info) !=
510 vk::Result::eSuccess) {
515 tracked_objects->GetGPUProbe().RecordCmdBufferStart(
516 tracked_objects->GetCommandBuffer());
521 std::move(tracked_objects),
527 return *device_holder_->instance;
531 return device_holder_->device.get();
534 const std::shared_ptr<fml::ConcurrentTaskRunner>
536 return raster_message_loop_->GetTaskRunner();
545 fence_waiter_.reset();
546 resource_manager_.reset();
548 raster_message_loop_->Terminate();
552 return std::make_shared<SurfaceContextVK>(shared_from_this());
556 return device_capabilities_;
564 return device_holder_->physical_device;
568 return fence_waiter_;
572 return resource_manager_;
577 return command_pool_recycler_;
586 return descriptor_pool_recycler_;
590 return command_queue_vk_;
605 color.texture->GetTextureDescriptor().format,
606 color.texture->GetTextureDescriptor().sample_count,
614 depth->texture->GetTextureDescriptor().format,
615 depth->texture->GetTextureDescriptor().sample_count,
620 stencil.has_value()) {
622 stencil->texture->GetTextureDescriptor().format,
623 stencil->texture->GetTextureDescriptor().sample_count,
624 stencil->load_action,
625 stencil->store_action
633 command_pool_recycler_->Dispose();
636 const std::shared_ptr<YUVConversionLibraryVK>&
638 return yuv_conversion_library_;
646 return should_disable_surface_control_;