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 // VK_KHR_sampler_ycbcr_conversion features.
457 enabled_extensions.value(),
459 auto& required =
460 required_chain
461 .get<vk::PhysicalDeviceSamplerYcbcrConversionFeaturesKHR>();
462 const auto& supported =
463 supported_chain
464 .get<vk::PhysicalDeviceSamplerYcbcrConversionFeaturesKHR>();
465
466 required.samplerYcbcrConversion = supported.samplerYcbcrConversion;
467 }
468
469 // VK_EXT_image_compression_control
471 enabled_extensions.value(),
473 auto& required =
474 required_chain
475 .get<vk::PhysicalDeviceImageCompressionControlFeaturesEXT>();
476 const auto& supported =
477 supported_chain
478 .get<vk::PhysicalDeviceImageCompressionControlFeaturesEXT>();
479
480 required.imageCompressionControl = supported.imageCompressionControl;
481 } else {
482 required_chain
483 .unlink<vk::PhysicalDeviceImageCompressionControlFeaturesEXT>();
484 }
485
486 // VK_EXT_texture_compression_astc_hdr
488 enabled_extensions.value(),
490 auto& required =
491 required_chain
492 .get<vk::PhysicalDeviceTextureCompressionASTCHDRFeatures>();
493 const auto& supported =
494 supported_chain
495 .get<vk::PhysicalDeviceTextureCompressionASTCHDRFeatures>();
496
497 required.textureCompressionASTC_HDR = supported.textureCompressionASTC_HDR;
498 } else {
499 required_chain
500 .unlink<vk::PhysicalDeviceTextureCompressionASTCHDRFeatures>();
501 }
502
503 // Vulkan 1.1
504 {
505 auto& required =
506 required_chain.get<vk::PhysicalDevice16BitStorageFeatures>();
507 const auto& supported =
508 supported_chain.get<vk::PhysicalDevice16BitStorageFeatures>();
509
510 required.uniformAndStorageBuffer16BitAccess =
511 supported.uniformAndStorageBuffer16BitAccess;
512 }
513
514 return required_chain;
515}
516
517bool CapabilitiesVK::HasLayer(const std::string& layer) const {
518 for (const auto& [found_layer, exts] : exts_) {
519 if (found_layer == layer) {
520 return true;
521 }
522 }
523 return false;
524}
525
526bool CapabilitiesVK::HasExtension(const std::string& ext) const {
527 for (const auto& [layer, exts] : exts_) {
528 if (exts.find(ext) != exts.end()) {
529 return true;
530 }
531 }
532 return false;
533}
534
536 return has_primitive_restart_;
537}
538
540 return true;
541}
542
544 return true;
545}
546
548 default_color_format_ = pixel_format;
549}
550
552 const vk::PhysicalDevice& device,
553 const PhysicalDeviceFeatures& enabled_features) {
554 if (HasSuitableColorFormat(device, vk::Format::eR8G8B8A8Unorm)) {
555 default_color_format_ = PixelFormat::kR8G8B8A8UNormInt;
556 } else {
557 default_color_format_ = PixelFormat::kUnknown;
558 }
559
560 if (HasSuitableDepthStencilFormat(device, vk::Format::eD24UnormS8Uint)) {
561 default_depth_stencil_format_ = PixelFormat::kD24UnormS8Uint;
563 vk::Format::eD32SfloatS8Uint)) {
564 default_depth_stencil_format_ = PixelFormat::kD32FloatS8UInt;
565 } else {
566 default_depth_stencil_format_ = PixelFormat::kUnknown;
567 }
568
569 if (HasSuitableDepthStencilFormat(device, vk::Format::eS8Uint)) {
570 default_stencil_format_ = PixelFormat::kS8UInt;
571 } else if (default_depth_stencil_format_ != PixelFormat::kUnknown) {
572 default_stencil_format_ = default_depth_stencil_format_;
573 }
574
575 physical_device_ = device;
576 device_properties_ = device.getProperties();
577
578 auto physical_properties_2 =
579 device.getProperties2<vk::PhysicalDeviceProperties2,
580 vk::PhysicalDeviceSubgroupProperties>();
581
582 // Currently shaders only want access to arithmetic subgroup features.
583 // If that changes this needs to get updated, and so does Metal (which right
584 // now assumes it from compile time flags based on the MSL target version).
585
586 supports_compute_subgroups_ =
587 !!(physical_properties_2.get<vk::PhysicalDeviceSubgroupProperties>()
588 .supportedOperations &
589 vk::SubgroupFeatureFlagBits::eArithmetic);
590
591 {
592 // Query texture support.
593 // TODO(129784): Add a capability check for expected memory types.
594 vk::PhysicalDeviceMemoryProperties memory_properties;
595 device.getMemoryProperties(&memory_properties);
596
597 for (auto i = 0u; i < memory_properties.memoryTypeCount; i++) {
598 if (memory_properties.memoryTypes[i].propertyFlags &
599 vk::MemoryPropertyFlagBits::eLazilyAllocated) {
600 supports_device_transient_textures_ = true;
601 }
602 }
603 }
604
605 // Determine the optional device extensions this physical device supports.
606 {
607 required_common_device_extensions_.clear();
608 required_android_device_extensions_.clear();
609 optional_device_extensions_.clear();
610 optional_android_device_extensions_.clear();
611
612 std::set<std::string> exts;
613 if (!use_embedder_extensions_) {
614 auto maybe_exts = GetSupportedDeviceExtensions(device);
615 if (!maybe_exts.has_value()) {
616 return false;
617 }
618 exts = maybe_exts.value();
619 } else {
620 for (const auto& ext : embedder_device_extensions_) {
621 exts.insert(ext);
622 }
623 }
624
625 IterateExtensions<RequiredCommonDeviceExtensionVK>([&](auto ext) -> bool {
626 auto ext_name = GetExtensionName(ext);
627 if (exts.find(ext_name) != exts.end()) {
628 required_common_device_extensions_.insert(ext);
629 }
630 return true;
631 });
632 IterateExtensions<RequiredAndroidDeviceExtensionVK>([&](auto ext) -> bool {
633 auto ext_name = GetExtensionName(ext);
634 if (exts.find(ext_name) != exts.end()) {
635 required_android_device_extensions_.insert(ext);
636 }
637 return true;
638 });
639 IterateExtensions<OptionalDeviceExtensionVK>([&](auto ext) -> bool {
640 auto ext_name = GetExtensionName(ext);
641 if (exts.find(ext_name) != exts.end()) {
642 optional_device_extensions_.insert(ext);
643 }
644 return true;
645 });
646 IterateExtensions<OptionalAndroidDeviceExtensionVK>(
648 auto name = GetExtensionName(ext);
649 if (exts.find(name) != exts.end()) {
650 optional_android_device_extensions_.insert(ext);
651 }
652 return true;
653 });
654 }
655
656 supports_texture_fixed_rate_compression_ =
657 enabled_features
658 .isLinked<vk::PhysicalDeviceImageCompressionControlFeaturesEXT>() &&
659 enabled_features
660 .get<vk::PhysicalDeviceImageCompressionControlFeaturesEXT>()
661 .imageCompressionControl;
662
663 {
664 const auto& features = enabled_features.get().features;
665 supports_texture_compression_bc_ = features.textureCompressionBC;
666 supports_texture_compression_etc2_ = features.textureCompressionETC2;
667 supports_texture_compression_astc_ = features.textureCompressionASTC_LDR;
668 }
669
670 supports_texture_compression_astc_hdr_ =
671 enabled_features
672 .isLinked<vk::PhysicalDeviceTextureCompressionASTCHDRFeatures>() &&
673 enabled_features
674 .get<vk::PhysicalDeviceTextureCompressionASTCHDRFeatures>()
675 .textureCompressionASTC_HDR;
676
677 max_render_pass_attachment_size_ =
678 ISize{device_properties_.limits.maxFramebufferWidth,
679 device_properties_.limits.maxFramebufferHeight};
680
681 // Molten, Vulkan on Metal, cannot support triangle fans because Metal doesn't
682 // support triangle fans.
683 // See VUID-VkPipelineInputAssemblyStateCreateInfo-triangleFans-04452.
684 has_triangle_fans_ =
686
687 // External Fence/Semaphore for AHB swapchain
692 supports_external_fence_and_semaphore_ = true;
693 }
694
695 minimum_uniform_alignment_ =
696 device_properties_.limits.minUniformBufferOffsetAlignment;
697 minimum_storage_alignment_ =
698 device_properties_.limits.minStorageBufferOffsetAlignment;
699
700 return true;
701}
702
703// |Capabilities|
705 return true;
706}
707
708// |Capabilities|
710 return false;
711}
712
713// |Capabilities|
715 return true;
716}
717
718// |Capabilities|
720 return true;
721}
722
723// |Capabilities|
725 return has_framebuffer_fetch_;
726}
727
728// |Capabilities|
730 // Vulkan 1.1 requires support for compute.
731 return true;
732}
733
734// |Capabilities|
736 // Set by |SetPhysicalDevice|.
737 return supports_compute_subgroups_;
738}
739
740// |Capabilities|
742 return false;
743}
744
746 return true;
747}
748
749// |Capabilities|
751 return supports_device_transient_textures_;
752}
753
754// |Capabilities|
756 return default_color_format_;
757}
758
759// |Capabilities|
761 return default_stencil_format_;
762}
763
764// |Capabilities|
766 return default_depth_stencil_format_;
767}
768
769const vk::PhysicalDeviceProperties&
771 return device_properties_;
772}
773
777
779 return minimum_uniform_alignment_;
780}
781
783 return minimum_storage_alignment_;
784}
785
787 return false;
788}
789
791 return required_common_device_extensions_.find(ext) !=
792 required_common_device_extensions_.end();
793}
794
796 return required_android_device_extensions_.find(ext) !=
797 required_android_device_extensions_.end();
798}
799
801 return optional_device_extensions_.find(ext) !=
802 optional_device_extensions_.end();
803}
804
806 return optional_android_device_extensions_.find(ext) !=
807 optional_android_device_extensions_.end();
808}
809
811 return supports_texture_fixed_rate_compression_;
812}
813
814std::optional<vk::ImageCompressionFixedRateFlagBitsEXT>
816 const FRCFormatDescriptor& desc) const {
817 if (compression_type != CompressionType::kLossy) {
818 return std::nullopt;
819 }
820 if (!supports_texture_fixed_rate_compression_) {
821 return std::nullopt;
822 }
823 // There are opportunities to hash and cache the FRCFormatDescriptor if
824 // needed.
825 vk::StructureChain<vk::PhysicalDeviceImageFormatInfo2,
826 vk::ImageCompressionControlEXT>
827 format_chain;
828
829 auto& format_info = format_chain.get();
830
831 format_info.format = desc.format;
832 format_info.type = desc.type;
833 format_info.tiling = desc.tiling;
834 format_info.usage = desc.usage;
835 format_info.flags = desc.flags;
836
837 const auto kIdealFRCRate = vk::ImageCompressionFixedRateFlagBitsEXT::e4Bpc;
838
839 std::array<vk::ImageCompressionFixedRateFlagsEXT, 1u> rates = {kIdealFRCRate};
840
841 auto& compression = format_chain.get<vk::ImageCompressionControlEXT>();
842 compression.flags = vk::ImageCompressionFlagBitsEXT::eFixedRateExplicit;
843 compression.compressionControlPlaneCount = rates.size();
844 compression.pFixedRateFlags = rates.data();
845
846 const auto [result, supported] = physical_device_.getImageFormatProperties2<
847 vk::ImageFormatProperties2, vk::ImageCompressionPropertiesEXT>(
848 format_chain.get());
849
850 if (result != vk::Result::eSuccess ||
851 !supported.isLinked<vk::ImageCompressionPropertiesEXT>()) {
852 return std::nullopt;
853 }
854
855 const auto& compression_props =
856 supported.get<vk::ImageCompressionPropertiesEXT>();
857
858 if ((compression_props.imageCompressionFlags &
859 vk::ImageCompressionFlagBitsEXT::eFixedRateExplicit) &&
860 (compression_props.imageCompressionFixedRateFlags & kIdealFRCRate)) {
861 return kIdealFRCRate;
862 }
863
864 return std::nullopt;
865}
866
868 return has_triangle_fans_;
869}
870
872 return max_render_pass_attachment_size_;
873}
874
876 has_primitive_restart_ = !workarounds.slow_primitive_restart_performance;
877 has_framebuffer_fetch_ = !workarounds.input_attachment_self_dependency_broken;
878}
879
881 return supports_external_fence_and_semaphore_;
882}
883
885 return false;
886}
887
889 return true;
890}
891
893 CompressedTextureFamily family) const {
894 switch (family) {
896 return supports_texture_compression_bc_;
898 return supports_texture_compression_etc2_;
900 return supports_texture_compression_astc_;
902 return supports_texture_compression_astc_hdr_;
903 }
904 return false;
905}
906
907} // namespace impeller
908
909// 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.
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