Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
capabilities_vk.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 <algorithm>
8#include <array>
9
14
15// vulkan.hpp generates some clang-tidy warnings.
16// NOLINTBEGIN(clang-analyzer-security.PointerSub)
17
18namespace impeller {
19
20static constexpr const char* kInstanceLayer = "ImpellerInstance";
21
22CapabilitiesVK::CapabilitiesVK(bool enable_validations,
23 bool fatal_missing_validations,
24 bool use_embedder_extensions,
25 std::vector<std::string> instance_extensions,
26 std::vector<std::string> device_extensions)
27 : use_embedder_extensions_(use_embedder_extensions),
28 embedder_instance_extensions_(std::move(instance_extensions)),
29 embedder_device_extensions_(std::move(device_extensions)) {
30 if (!use_embedder_extensions_) {
31 auto extensions = vk::enumerateInstanceExtensionProperties();
32 auto layers = vk::enumerateInstanceLayerProperties();
33
34 if (extensions.result != vk::Result::eSuccess ||
35 layers.result != vk::Result::eSuccess) {
36 return;
37 }
38
39 for (const auto& ext : extensions.value) {
40 exts_[kInstanceLayer].insert(ext.extensionName);
41 }
42
43 for (const auto& layer : layers.value) {
44 const std::string layer_name = layer.layerName;
45 auto layer_exts = vk::enumerateInstanceExtensionProperties(layer_name);
46 if (layer_exts.result != vk::Result::eSuccess) {
47 return;
48 }
49 for (const auto& layer_ext : layer_exts.value) {
50 exts_[layer_name].insert(layer_ext.extensionName);
51 }
52 }
53 } else {
54 for (const auto& ext : embedder_instance_extensions_) {
55 exts_[kInstanceLayer].insert(ext);
56 }
57 }
58
59 validations_enabled_ =
60 enable_validations && HasLayer("VK_LAYER_KHRONOS_validation");
61 if (enable_validations && !validations_enabled_) {
62 FML_LOG(ERROR)
63 << "Requested Impeller context creation with validations but the "
64 "validation layers could not be found. Expect no Vulkan validation "
65 "checks!";
66 if (fatal_missing_validations) {
67 FML_LOG(FATAL) << "Validation missing. Exiting.";
68 }
69 }
70 if (validations_enabled_) {
71 FML_LOG(INFO) << "Vulkan validations are enabled.";
72 }
73 is_valid_ = true;
74}
75
77
79 return is_valid_;
80}
81
83 return validations_enabled_;
84}
85
86std::optional<std::vector<std::string>> CapabilitiesVK::GetEnabledLayers()
87 const {
88 std::vector<std::string> required;
89
90 if (validations_enabled_) {
91 // The presence of this layer is already checked in the ctor.
92 required.push_back("VK_LAYER_KHRONOS_validation");
93 }
94
95 return required;
96}
97
98std::optional<std::vector<std::string>>
100 std::vector<std::string> required;
101
102 if (!HasExtension("VK_KHR_surface")) {
103 // Swapchain support is required and this is a dependency of
104 // VK_KHR_swapchain.
105 VALIDATION_LOG << "Could not find the surface extension.";
106 return std::nullopt;
107 }
108 required.push_back("VK_KHR_surface");
109
110 auto has_wsi = false;
111 if (HasExtension("VK_MVK_macos_surface")) {
112 required.push_back("VK_MVK_macos_surface");
113 has_wsi = true;
114 }
115
116 if (HasExtension("VK_EXT_metal_surface")) {
117 required.push_back("VK_EXT_metal_surface");
118 has_wsi = true;
119 }
120
121 if (HasExtension("VK_KHR_portability_enumeration")) {
122 required.push_back("VK_KHR_portability_enumeration");
123 has_wsi = true;
124 }
125
126 if (HasExtension("VK_KHR_win32_surface")) {
127 required.push_back("VK_KHR_win32_surface");
128 has_wsi = true;
129 }
130
131 if (HasExtension("VK_KHR_android_surface")) {
132 required.push_back("VK_KHR_android_surface");
133 has_wsi = true;
134 }
135
136 if (HasExtension("VK_KHR_xcb_surface")) {
137 required.push_back("VK_KHR_xcb_surface");
138 has_wsi = true;
139 }
140
141 if (HasExtension("VK_KHR_xlib_surface")) {
142 required.push_back("VK_KHR_xlib_surface");
143 has_wsi = true;
144 }
145
146 if (HasExtension("VK_KHR_wayland_surface")) {
147 required.push_back("VK_KHR_wayland_surface");
148 has_wsi = true;
149 }
150
151 if (!has_wsi) {
152 // Don't really care which WSI extension there is as long there is at least
153 // one.
154 VALIDATION_LOG << "Could not find a WSI extension.";
155 return std::nullopt;
156 }
157
158 if (validations_enabled_) {
159 if (!HasExtension("VK_EXT_debug_utils")) {
160 VALIDATION_LOG << "Requested validations but could not find the "
161 "VK_EXT_debug_utils extension.";
162 return std::nullopt;
163 }
164 required.push_back("VK_EXT_debug_utils");
165
166 if (HasExtension("VK_EXT_validation_features")) {
167 // It's valid to not have `VK_EXT_validation_features` available. That's
168 // the case when using AGI as a frame debugger.
169 required.push_back("VK_EXT_validation_features");
170 }
171 }
172
173 return required;
174}
175
177 switch (ext) {
179 return VK_KHR_SWAPCHAIN_EXTENSION_NAME;
181 return "Unknown";
182 }
184}
185
187 switch (ext) {
190 return "VK_ANDROID_external_memory_android_hardware_buffer";
192 return VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME;
194 return VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME;
196 return VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME;
198 return VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME;
200 return "Unknown";
201 }
203}
204
206 switch (ext) {
208 return VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME;
210 return VK_KHR_EXTERNAL_FENCE_EXTENSION_NAME;
212 return VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME;
214 return VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME;
216 return "Unknown";
217 }
218}
219
221 switch (ext) {
223 return VK_EXT_PIPELINE_CREATION_FEEDBACK_EXTENSION_NAME;
225 return "VK_KHR_portability_subset";
227 return VK_EXT_IMAGE_COMPRESSION_CONTROL_EXTENSION_NAME;
229 return VK_EXT_TEXTURE_COMPRESSION_ASTC_HDR_EXTENSION_NAME;
231 return "Unknown";
232 }
234}
235
236template <class T>
237static bool IterateExtensions(const std::function<bool(T)>& it) {
238 if (!it) {
239 return false;
240 }
241 for (size_t i = 0; i < static_cast<uint32_t>(T::kLast); i++) {
242 if (!it(static_cast<T>(i))) {
243 return false;
244 }
245 }
246 return true;
247}
248
249static std::optional<std::set<std::string>> GetSupportedDeviceExtensions(
250 const vk::PhysicalDevice& physical_device) {
251 auto device_extensions = physical_device.enumerateDeviceExtensionProperties();
252 if (device_extensions.result != vk::Result::eSuccess) {
253 return std::nullopt;
254 }
255
256 std::set<std::string> exts;
257 for (const auto& device_extension : device_extensions.value) {
258 exts.insert(device_extension.extensionName);
259 };
260
261 return exts;
262}
263
264std::optional<std::vector<std::string>>
266 const vk::PhysicalDevice& physical_device) const {
267 std::set<std::string> exts;
268
269 if (!use_embedder_extensions_) {
271
272 if (!maybe_exts.has_value()) {
273 return std::nullopt;
274 }
275 exts = maybe_exts.value();
276 } else {
277 for (const auto& ext : embedder_device_extensions_) {
278 exts.insert(ext);
279 }
280 }
281
282 std::vector<std::string> enabled;
283
284 auto for_each_common_extension = [&](RequiredCommonDeviceExtensionVK ext) {
285 auto name = GetExtensionName(ext);
286 if (exts.find(name) == exts.end()) {
287 VALIDATION_LOG << "Device does not support required extension: " << name;
288 return false;
289 }
290 enabled.push_back(name);
291 return true;
292 };
293
294 auto for_each_android_extension = [&](RequiredAndroidDeviceExtensionVK ext) {
295#ifdef FML_OS_ANDROID
296 auto name = GetExtensionName(ext);
297 if (exts.find(name) == exts.end()) {
298 VALIDATION_LOG << "Device does not support required Android extension: "
299 << name;
300 return false;
301 }
302 enabled.push_back(name);
303#endif // FML_OS_ANDROID
304 return true;
305 };
306
307 auto for_each_optional_android_extension =
309#ifdef FML_OS_ANDROID
310 auto name = GetExtensionName(ext);
311 if (exts.find(name) != exts.end()) {
312 enabled.push_back(name);
313 }
314#endif // FML_OS_ANDROID
315 return true;
316 };
317
318 auto for_each_optional_extension = [&](OptionalDeviceExtensionVK ext) {
319 auto name = GetExtensionName(ext);
320 if (exts.find(name) != exts.end()) {
321 enabled.push_back(name);
322 }
323 return true;
324 };
325
326 const auto iterate_extensions =
327 IterateExtensions<RequiredCommonDeviceExtensionVK>(
328 for_each_common_extension) &&
329 IterateExtensions<RequiredAndroidDeviceExtensionVK>(
330 for_each_android_extension) &&
331 IterateExtensions<OptionalDeviceExtensionVK>(
332 for_each_optional_extension) &&
333 IterateExtensions<OptionalAndroidDeviceExtensionVK>(
334 for_each_optional_android_extension);
335
336 if (!iterate_extensions) {
337 VALIDATION_LOG << "Device not suitable since required extensions are not "
338 "supported.";
339 return std::nullopt;
340 }
341
342 return enabled;
343}
344
345static bool HasSuitableColorFormat(const vk::PhysicalDevice& device,
346 vk::Format format) {
347 const auto props = device.getFormatProperties(format);
348 // This needs to be more comprehensive.
349 return !!(props.optimalTilingFeatures &
350 vk::FormatFeatureFlagBits::eColorAttachment);
351}
352
353static bool HasSuitableDepthStencilFormat(const vk::PhysicalDevice& device,
354 vk::Format format) {
355 const auto props = device.getFormatProperties(format);
356 return !!(props.optimalTilingFeatures &
357 vk::FormatFeatureFlagBits::eDepthStencilAttachment);
358}
359
361 const vk::PhysicalDevice& device) {
362 const auto has_color_format =
363 HasSuitableColorFormat(device, vk::Format::eR8G8B8A8Unorm);
364 const auto has_stencil_format =
365 HasSuitableDepthStencilFormat(device, vk::Format::eD32SfloatS8Uint) ||
366 HasSuitableDepthStencilFormat(device, vk::Format::eD24UnormS8Uint);
367 return has_color_format && has_stencil_format;
368}
369
370static bool HasRequiredProperties(const vk::PhysicalDevice& physical_device) {
371 auto properties = physical_device.getProperties();
372 if (!(properties.limits.framebufferColorSampleCounts &
373 (vk::SampleCountFlagBits::e1 | vk::SampleCountFlagBits::e4))) {
374 return false;
375 }
376 return true;
377}
378
379static bool HasRequiredQueues(const vk::PhysicalDevice& physical_device) {
380 auto queue_flags = vk::QueueFlags{};
381 for (const auto& queue : physical_device.getQueueFamilyProperties()) {
382 if (queue.queueCount == 0) {
383 continue;
384 }
385 queue_flags |= queue.queueFlags;
386 }
387 return static_cast<VkQueueFlags>(queue_flags &
388 (vk::QueueFlagBits::eGraphics |
389 vk::QueueFlagBits::eCompute |
390 vk::QueueFlagBits::eTransfer));
391}
392
393template <class ExtensionEnum>
394static bool IsExtensionInList(const std::vector<std::string>& list,
395 ExtensionEnum ext) {
396 const std::string name = GetExtensionName(ext);
397 return std::find(list.begin(), list.end(), name) != list.end();
398}
399
400std::optional<CapabilitiesVK::PhysicalDeviceFeatures>
402 const vk::PhysicalDevice& device) const {
404 VALIDATION_LOG << "Device doesn't support the required formats.";
405 return std::nullopt;
406 }
407
409 VALIDATION_LOG << "Device doesn't support the required properties.";
410 return std::nullopt;
411 }
412
414 VALIDATION_LOG << "Device doesn't support the required queues.";
415 return std::nullopt;
416 }
417
418 const auto enabled_extensions = GetEnabledDeviceExtensions(device);
419 if (!enabled_extensions.has_value()) {
420 VALIDATION_LOG << "Device doesn't support the required queues.";
421 return std::nullopt;
422 }
423
424 PhysicalDeviceFeatures supported_chain;
425
426 // Swiftshader seems to be fussy about just this structure even being in the
427 // chain. Just unlink it if its not supported. We already perform an
428 // extensions check on the other side when reading.
430 enabled_extensions.value(),
432 supported_chain
433 .unlink<vk::PhysicalDeviceImageCompressionControlFeaturesEXT>();
434 }
436 enabled_extensions.value(),
438 supported_chain
439 .unlink<vk::PhysicalDeviceTextureCompressionASTCHDRFeatures>();
440 }
441
442 device.getFeatures2(&supported_chain.get());
443
444 PhysicalDeviceFeatures required_chain;
445
446 // Base features.
447 {
448 auto& required = required_chain.get().features;
449 const auto& supported = supported_chain.get().features;
450
451 // We require this for enabling wireframes in the playground. But its not
452 // necessarily a big deal if we don't have this feature.
453 required.fillModeNonSolid = supported.fillModeNonSolid;
454
455 // Enable anisotropic filtering when available. Samplers with
456 // `max_anisotropy` greater than 1 may only be created when this feature
457 // is enabled.
458 required.samplerAnisotropy = supported.samplerAnisotropy;
459 }
460 // VK_KHR_sampler_ycbcr_conversion features.
462 enabled_extensions.value(),
464 auto& required =
465 required_chain
466 .get<vk::PhysicalDeviceSamplerYcbcrConversionFeaturesKHR>();
467 const auto& supported =
468 supported_chain
469 .get<vk::PhysicalDeviceSamplerYcbcrConversionFeaturesKHR>();
470
471 required.samplerYcbcrConversion = supported.samplerYcbcrConversion;
472 }
473
474 // VK_EXT_image_compression_control
476 enabled_extensions.value(),
478 auto& required =
479 required_chain
480 .get<vk::PhysicalDeviceImageCompressionControlFeaturesEXT>();
481 const auto& supported =
482 supported_chain
483 .get<vk::PhysicalDeviceImageCompressionControlFeaturesEXT>();
484
485 required.imageCompressionControl = supported.imageCompressionControl;
486 } else {
487 required_chain
488 .unlink<vk::PhysicalDeviceImageCompressionControlFeaturesEXT>();
489 }
490
491 // VK_EXT_texture_compression_astc_hdr
493 enabled_extensions.value(),
495 auto& required =
496 required_chain
497 .get<vk::PhysicalDeviceTextureCompressionASTCHDRFeatures>();
498 const auto& supported =
499 supported_chain
500 .get<vk::PhysicalDeviceTextureCompressionASTCHDRFeatures>();
501
502 required.textureCompressionASTC_HDR = supported.textureCompressionASTC_HDR;
503 } else {
504 required_chain
505 .unlink<vk::PhysicalDeviceTextureCompressionASTCHDRFeatures>();
506 }
507
508 // Vulkan 1.1
509 {
510 auto& required =
511 required_chain.get<vk::PhysicalDevice16BitStorageFeatures>();
512 const auto& supported =
513 supported_chain.get<vk::PhysicalDevice16BitStorageFeatures>();
514
515 required.uniformAndStorageBuffer16BitAccess =
516 supported.uniformAndStorageBuffer16BitAccess;
517 }
518
519 return required_chain;
520}
521
522bool CapabilitiesVK::HasLayer(const std::string& layer) const {
523 for (const auto& [found_layer, exts] : exts_) {
524 if (found_layer == layer) {
525 return true;
526 }
527 }
528 return false;
529}
530
531bool CapabilitiesVK::HasExtension(const std::string& ext) const {
532 for (const auto& [layer, exts] : exts_) {
533 if (exts.find(ext) != exts.end()) {
534 return true;
535 }
536 }
537 return false;
538}
539
541 return has_primitive_restart_;
542}
543
545 return true;
546}
547
549 return true;
550}
551
553 default_color_format_ = pixel_format;
554}
555
557 const vk::PhysicalDevice& device,
558 const PhysicalDeviceFeatures& enabled_features) {
559 if (HasSuitableColorFormat(device, vk::Format::eR8G8B8A8Unorm)) {
560 default_color_format_ = PixelFormat::kR8G8B8A8UNormInt;
561 } else {
562 default_color_format_ = PixelFormat::kUnknown;
563 }
564
565 if (HasSuitableDepthStencilFormat(device, vk::Format::eD24UnormS8Uint)) {
566 default_depth_stencil_format_ = PixelFormat::kD24UnormS8Uint;
568 vk::Format::eD32SfloatS8Uint)) {
569 default_depth_stencil_format_ = PixelFormat::kD32FloatS8UInt;
570 } else {
571 default_depth_stencil_format_ = PixelFormat::kUnknown;
572 }
573
574 if (HasSuitableDepthStencilFormat(device, vk::Format::eS8Uint)) {
575 default_stencil_format_ = PixelFormat::kS8UInt;
576 } else if (default_depth_stencil_format_ != PixelFormat::kUnknown) {
577 default_stencil_format_ = default_depth_stencil_format_;
578 }
579
580 physical_device_ = device;
581 device_properties_ = device.getProperties();
582
583 auto physical_properties_2 =
584 device.getProperties2<vk::PhysicalDeviceProperties2,
585 vk::PhysicalDeviceSubgroupProperties>();
586
587 // Currently shaders only want access to arithmetic subgroup features.
588 // If that changes this needs to get updated, and so does Metal (which right
589 // now assumes it from compile time flags based on the MSL target version).
590
591 supports_compute_subgroups_ =
592 !!(physical_properties_2.get<vk::PhysicalDeviceSubgroupProperties>()
593 .supportedOperations &
594 vk::SubgroupFeatureFlagBits::eArithmetic);
595
596 {
597 // Query texture support.
598 // TODO(129784): Add a capability check for expected memory types.
599 vk::PhysicalDeviceMemoryProperties memory_properties;
600 device.getMemoryProperties(&memory_properties);
601
602 for (auto i = 0u; i < memory_properties.memoryTypeCount; i++) {
603 if (memory_properties.memoryTypes[i].propertyFlags &
604 vk::MemoryPropertyFlagBits::eLazilyAllocated) {
605 supports_device_transient_textures_ = true;
606 }
607 }
608 }
609
610 // Determine the optional device extensions this physical device supports.
611 {
612 required_common_device_extensions_.clear();
613 required_android_device_extensions_.clear();
614 optional_device_extensions_.clear();
615 optional_android_device_extensions_.clear();
616
617 std::set<std::string> exts;
618 if (!use_embedder_extensions_) {
619 auto maybe_exts = GetSupportedDeviceExtensions(device);
620 if (!maybe_exts.has_value()) {
621 return false;
622 }
623 exts = maybe_exts.value();
624 } else {
625 for (const auto& ext : embedder_device_extensions_) {
626 exts.insert(ext);
627 }
628 }
629
630 IterateExtensions<RequiredCommonDeviceExtensionVK>([&](auto ext) -> bool {
631 auto ext_name = GetExtensionName(ext);
632 if (exts.find(ext_name) != exts.end()) {
633 required_common_device_extensions_.insert(ext);
634 }
635 return true;
636 });
637 IterateExtensions<RequiredAndroidDeviceExtensionVK>([&](auto ext) -> bool {
638 auto ext_name = GetExtensionName(ext);
639 if (exts.find(ext_name) != exts.end()) {
640 required_android_device_extensions_.insert(ext);
641 }
642 return true;
643 });
644 IterateExtensions<OptionalDeviceExtensionVK>([&](auto ext) -> bool {
645 auto ext_name = GetExtensionName(ext);
646 if (exts.find(ext_name) != exts.end()) {
647 optional_device_extensions_.insert(ext);
648 }
649 return true;
650 });
651 IterateExtensions<OptionalAndroidDeviceExtensionVK>(
653 auto name = GetExtensionName(ext);
654 if (exts.find(name) != exts.end()) {
655 optional_android_device_extensions_.insert(ext);
656 }
657 return true;
658 });
659 }
660
661 supports_texture_fixed_rate_compression_ =
662 enabled_features
663 .isLinked<vk::PhysicalDeviceImageCompressionControlFeaturesEXT>() &&
664 enabled_features
665 .get<vk::PhysicalDeviceImageCompressionControlFeaturesEXT>()
666 .imageCompressionControl;
667
668 {
669 const auto& features = enabled_features.get().features;
670 supports_texture_compression_bc_ = features.textureCompressionBC;
671 supports_texture_compression_etc2_ = features.textureCompressionETC2;
672 supports_texture_compression_astc_ = features.textureCompressionASTC_LDR;
673 }
674
675 supports_texture_compression_astc_hdr_ =
676 enabled_features
677 .isLinked<vk::PhysicalDeviceTextureCompressionASTCHDRFeatures>() &&
678 enabled_features
679 .get<vk::PhysicalDeviceTextureCompressionASTCHDRFeatures>()
680 .textureCompressionASTC_HDR;
681
682 max_render_pass_attachment_size_ =
683 ISize{device_properties_.limits.maxFramebufferWidth,
684 device_properties_.limits.maxFramebufferHeight};
685
686 // Anisotropic filtering is gated on the samplerAnisotropy feature. When the
687 // feature is unavailable, report a maximum of 1 (disabled). The device limit
688 // is a float but is always an integer in practice, so floor it.
689 max_sampler_anisotropy_ =
690 enabled_features.get().features.samplerAnisotropy
691 ? static_cast<uint32_t>(
692 device_properties_.limits.maxSamplerAnisotropy)
693 : 1u;
694
695 // Molten, Vulkan on Metal, cannot support triangle fans because Metal doesn't
696 // support triangle fans.
697 // See VUID-VkPipelineInputAssemblyStateCreateInfo-triangleFans-04452.
698 has_triangle_fans_ =
700
701 // External Fence/Semaphore for AHB swapchain
706 supports_external_fence_and_semaphore_ = true;
707 }
708
709 minimum_uniform_alignment_ =
710 device_properties_.limits.minUniformBufferOffsetAlignment;
711 minimum_storage_alignment_ =
712 device_properties_.limits.minStorageBufferOffsetAlignment;
713
714 return true;
715}
716
717// |Capabilities|
719 return true;
720}
721
722// |Capabilities|
724 return false;
725}
726
727// |Capabilities|
729 return true;
730}
731
732// |Capabilities|
734 return true;
735}
736
737// |Capabilities|
739 return has_framebuffer_fetch_;
740}
741
742// |Capabilities|
744 // Vulkan 1.1 requires support for compute.
745 return true;
746}
747
748// |Capabilities|
750 // Set by |SetPhysicalDevice|.
751 return supports_compute_subgroups_;
752}
753
754// |Capabilities|
756 return false;
757}
758
760 return true;
761}
762
763// |Capabilities|
765 return supports_device_transient_textures_;
766}
767
768// |Capabilities|
770 return default_color_format_;
771}
772
773// |Capabilities|
775 return default_stencil_format_;
776}
777
778// |Capabilities|
780 return default_depth_stencil_format_;
781}
782
783const vk::PhysicalDeviceProperties&
785 return device_properties_;
786}
787
791
793 return minimum_uniform_alignment_;
794}
795
797 return minimum_storage_alignment_;
798}
799
801 return false;
802}
803
805 return required_common_device_extensions_.find(ext) !=
806 required_common_device_extensions_.end();
807}
808
810 return required_android_device_extensions_.find(ext) !=
811 required_android_device_extensions_.end();
812}
813
815 return optional_device_extensions_.find(ext) !=
816 optional_device_extensions_.end();
817}
818
820 return optional_android_device_extensions_.find(ext) !=
821 optional_android_device_extensions_.end();
822}
823
825 return supports_texture_fixed_rate_compression_;
826}
827
828std::optional<vk::ImageCompressionFixedRateFlagBitsEXT>
830 const FRCFormatDescriptor& desc) const {
831 if (compression_type != CompressionType::kLossy) {
832 return std::nullopt;
833 }
834 if (!supports_texture_fixed_rate_compression_) {
835 return std::nullopt;
836 }
837 // There are opportunities to hash and cache the FRCFormatDescriptor if
838 // needed.
839 vk::StructureChain<vk::PhysicalDeviceImageFormatInfo2,
840 vk::ImageCompressionControlEXT>
841 format_chain;
842
843 auto& format_info = format_chain.get();
844
845 format_info.format = desc.format;
846 format_info.type = desc.type;
847 format_info.tiling = desc.tiling;
848 format_info.usage = desc.usage;
849 format_info.flags = desc.flags;
850
851 const auto kIdealFRCRate = vk::ImageCompressionFixedRateFlagBitsEXT::e4Bpc;
852
853 std::array<vk::ImageCompressionFixedRateFlagsEXT, 1u> rates = {kIdealFRCRate};
854
855 auto& compression = format_chain.get<vk::ImageCompressionControlEXT>();
856 compression.flags = vk::ImageCompressionFlagBitsEXT::eFixedRateExplicit;
857 compression.compressionControlPlaneCount = rates.size();
858 compression.pFixedRateFlags = rates.data();
859
860 const auto [result, supported] = physical_device_.getImageFormatProperties2<
861 vk::ImageFormatProperties2, vk::ImageCompressionPropertiesEXT>(
862 format_chain.get());
863
864 if (result != vk::Result::eSuccess ||
865 !supported.isLinked<vk::ImageCompressionPropertiesEXT>()) {
866 return std::nullopt;
867 }
868
869 const auto& compression_props =
870 supported.get<vk::ImageCompressionPropertiesEXT>();
871
872 if ((compression_props.imageCompressionFlags &
873 vk::ImageCompressionFlagBitsEXT::eFixedRateExplicit) &&
874 (compression_props.imageCompressionFixedRateFlags & kIdealFRCRate)) {
875 return kIdealFRCRate;
876 }
877
878 return std::nullopt;
879}
880
882 return has_triangle_fans_;
883}
884
886 return max_render_pass_attachment_size_;
887}
888
890 return max_sampler_anisotropy_;
891}
892
894 has_primitive_restart_ = !workarounds.slow_primitive_restart_performance;
895 has_framebuffer_fetch_ = !workarounds.input_attachment_self_dependency_broken;
896}
897
899 return supports_external_fence_and_semaphore_;
900}
901
903 return false;
904}
905
907 return true;
908}
909
911 CompressedTextureFamily family) const {
912 switch (family) {
914 return supports_texture_compression_bc_;
916 return supports_texture_compression_etc2_;
918 return supports_texture_compression_astc_;
920 return supports_texture_compression_astc_hdr_;
921 }
922 return false;
923}
924
925} // namespace impeller
926
927// NOLINTEND(clang-analyzer-security.PointerSub)
bool SupportsFramebufferRenderMipmap() const override
Whether a non-zero mip level of a texture can be attached as a render target. Rendering into a cube m...
bool SupportsTriangleFan() const override
Whether the primitive type TriangleFan is supported by the backend.
size_t GetMinimumUniformAlignment() const override
The minimum alignment of uniform value offsets in bytes.
bool SupportsDeviceTransientTextures() const override
Whether the context backend supports allocating StorageMode::kDeviceTransient (aka "memoryless") text...
std::optional< std::vector< std::string > > GetEnabledInstanceExtensions() const
bool SetPhysicalDevice(const vk::PhysicalDevice &physical_device, const PhysicalDeviceFeatures &enabled_features)
ISize GetMaximumRenderPassAttachmentSize() const override
Return the maximum size of a render pass attachment.
bool SupportsSSBO() const override
Whether the context backend supports binding Shader Storage Buffer Objects (SSBOs) to pipelines.
bool SupportsFramebufferFetch() const override
Whether the context backend is able to support pipelines with shaders that read from the framebuffer ...
bool SupportsExternalSemaphoreExtensions() const
bool SupportsManuallyMippedTextures() const override
Whether a texture whose mip levels were uploaded by hand (rather than produced by BlitPass::GenerateM...
CapabilitiesVK(bool enable_validations, bool fatal_missing_validations=false, bool use_embedder_extensions=false, std::vector< std::string > instance_extensions={}, std::vector< std::string > device_extensions={})
bool SupportsOffscreenMSAA() const override
Whether the context backend supports attaching offscreen MSAA color/stencil textures.
bool SupportsCompute() const override
Whether the context backend supports ComputePass.
bool HasExtension(RequiredCommonDeviceExtensionVK ext) const
std::optional< vk::ImageCompressionFixedRateFlagBitsEXT > GetSupportedFRCRate(CompressionType compression_type, const FRCFormatDescriptor &desc) const
Get the fixed compression rate supported by the context for the given format and usage.
void SetOffscreenFormat(PixelFormat pixel_format) const
PixelFormat GetDefaultStencilFormat() const override
Returns a supported PixelFormat for textures that store stencil information. May include a depth chan...
void ApplyWorkarounds(const WorkaroundsVK &workarounds)
Update capabilities for the given set of workarounds.
bool SupportsComputeSubgroups() const override
Whether the context backend supports configuring ComputePass command subgroups.
size_t GetMinimumStorageBufferAlignment() const override
The minimum alignment of storage buffer value offsets in bytes.
PixelFormat GetDefaultDepthStencilFormat() const override
Returns a supported PixelFormat for textures that store both a stencil and depth component....
bool SupportsTextureToTextureBlits() const override
Whether the context backend supports blitting from one texture region to another texture region (via ...
bool Supports32BitPrimitiveIndices() const override
Whether 32-bit values are supported in index buffers used to draw primitives.
std::optional< std::vector< std::string > > GetEnabledDeviceExtensions(const vk::PhysicalDevice &physical_device) const
bool SupportsReadFromResolve() const override
Whether the context backend supports binding the current RenderPass attachments. This is supported if...
bool SupportsDecalSamplerAddressMode() const override
Whether the context backend supports SamplerAddressMode::Decal.
bool SupportsPrimitiveRestart() const override
Whether primitive restart is supported.
std::optional< std::vector< std::string > > GetEnabledLayers() const
bool SupportsTextureFixedRateCompression() const
bool NeedsPartitionedHostBuffer() const override
Whether the host buffer should use separate device buffers for indexes from other data.
PixelFormat GetDefaultGlyphAtlasFormat() const override
Returns the default pixel format for the alpha bitmap glyph atlas.
PixelFormat GetDefaultColorFormat() const override
Returns a supported PixelFormat for textures that store 4-channel colors (red/green/blue/alpha).
const vk::PhysicalDeviceProperties & GetPhysicalDeviceProperties() const
bool SupportsExtendedRangeFormats() const override
Whether the XR formats are supported on this device.
uint32_t GetMaxSamplerAnisotropy() const override
The maximum anisotropy clamp supported by device samplers.
bool SupportsImplicitResolvingMSAA() const override
Whether the context backend supports multisampled rendering to the on-screen surface without requirin...
std::optional< PhysicalDeviceFeatures > GetEnabledDeviceFeatures(const vk::PhysicalDevice &physical_device) const
bool SupportsTextureCompression(CompressedTextureFamily family) const override
Whether the given family of block-compressed texture formats is supported by this device....
vk::StructureChain< vk::PhysicalDeviceFeatures2, vk::PhysicalDeviceSamplerYcbcrConversionFeaturesKHR, vk::PhysicalDevice16BitStorageFeatures, vk::PhysicalDeviceImageCompressionControlFeaturesEXT, vk::PhysicalDeviceTextureCompressionASTCHDRFeatures > PhysicalDeviceFeatures
VkPhysicalDevice physical_device
Definition main.cc:67
VkDevice device
Definition main.cc:69
VkQueue queue
Definition main.cc:71
const FlutterLayer ** layers
uint32_t uint32_t * format
#define FML_LOG(severity)
Definition logging.h:101
#define FML_UNREACHABLE()
Definition logging.h:128
const char * name
Definition fuchsia.cc:50
std::vector< std::string > device_extensions
std::vector< std::string > instance_extensions
static bool IterateExtensions(const std::function< bool(T)> &it)
static const char * GetExtensionName(RequiredCommonDeviceExtensionVK ext)
static bool PhysicalDeviceSupportsRequiredFormats(const vk::PhysicalDevice &device)
static bool HasRequiredProperties(const vk::PhysicalDevice &physical_device)
static bool IsExtensionInList(const std::vector< std::string > &list, ExtensionEnum ext)
static bool HasSuitableColorFormat(const vk::PhysicalDevice &device, vk::Format format)
RequiredAndroidDeviceExtensionVK
A device extension available on all Android platforms. Without the presence of these extensions on An...
PixelFormat
The Pixel formats supported by Impeller. The naming convention denotes the usage of the component,...
Definition formats.h:99
static std::optional< std::set< std::string > > GetSupportedDeviceExtensions(const vk::PhysicalDevice &physical_device)
CompressedTextureFamily
The family of a block-compressed pixel format. GPUs support compressed formats on a per-family basis,...
Definition formats.h:146
@ kASTCHDR
ASTC HDR. A separate device feature from ASTC LDR.
@ kBC
S3TC, RGTC, and BPTC (BC1 through BC7). Desktop GPUs.
@ kETC2
ETC2 and EAC. Mobile, OpenGL ES 3.0, and WebGL2.
@ kASTC
ASTC LDR. Modern mobile and some desktop.
static bool HasSuitableDepthStencilFormat(const vk::PhysicalDevice &device, vk::Format format)
RequiredCommonDeviceExtensionVK
A device extension available on all platforms. Without the presence of these extensions,...
OptionalAndroidDeviceExtensionVK
A device extension available on some Android platforms.
static constexpr const char * kInstanceLayer
CompressionType
Additional compression to apply to a texture. This value is ignored on platforms which do not support...
OptionalDeviceExtensionVK
A device extension enabled if available. Subsystems cannot assume availability and must check if thes...
static bool HasRequiredQueues(const vk::PhysicalDevice &physical_device)
Definition ref_ptr.h:261
A pixel format and usage that is sufficient to check if images of that format and usage are suitable ...
A non-exhaustive set of driver specific workarounds.
#define VALIDATION_LOG
Definition validation.h:91