Flutter Impeller
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 
11 #include "impeller/core/formats.h"
14 
15 namespace impeller {
16 
17 static constexpr const char* kInstanceLayer = "ImpellerInstance";
18 
19 CapabilitiesVK::CapabilitiesVK(bool enable_validations,
20  bool fatal_missing_validations,
21  bool use_embedder_extensions,
22  std::vector<std::string> instance_extensions,
23  std::vector<std::string> device_extensions)
24  : use_embedder_extensions_(use_embedder_extensions),
25  embedder_instance_extensions_(std::move(instance_extensions)),
26  embedder_device_extensions_(std::move(device_extensions)) {
27  if (!use_embedder_extensions_) {
28  auto extensions = vk::enumerateInstanceExtensionProperties();
29  auto layers = vk::enumerateInstanceLayerProperties();
30 
31  if (extensions.result != vk::Result::eSuccess ||
32  layers.result != vk::Result::eSuccess) {
33  return;
34  }
35 
36  for (const auto& ext : extensions.value) {
37  exts_[kInstanceLayer].insert(ext.extensionName);
38  }
39 
40  for (const auto& layer : layers.value) {
41  const std::string layer_name = layer.layerName;
42  auto layer_exts = vk::enumerateInstanceExtensionProperties(layer_name);
43  if (layer_exts.result != vk::Result::eSuccess) {
44  return;
45  }
46  for (const auto& layer_ext : layer_exts.value) {
47  exts_[layer_name].insert(layer_ext.extensionName);
48  }
49  }
50  } else {
51  for (const auto& ext : embedder_instance_extensions_) {
52  exts_[kInstanceLayer].insert(ext);
53  }
54  }
55 
56  validations_enabled_ =
57  enable_validations && HasLayer("VK_LAYER_KHRONOS_validation");
58  if (enable_validations && !validations_enabled_) {
59  FML_LOG(ERROR)
60  << "Requested Impeller context creation with validations but the "
61  "validation layers could not be found. Expect no Vulkan validation "
62  "checks!";
63  if (fatal_missing_validations) {
64  FML_LOG(FATAL) << "Validation missing. Exiting.";
65  }
66  }
67  if (validations_enabled_) {
68  FML_LOG(INFO) << "Vulkan validations are enabled.";
69  }
70  is_valid_ = true;
71 }
72 
74 
76  return is_valid_;
77 }
78 
80  return validations_enabled_;
81 }
82 
83 std::optional<std::vector<std::string>> CapabilitiesVK::GetEnabledLayers()
84  const {
85  std::vector<std::string> required;
86 
87  if (validations_enabled_) {
88  // The presence of this layer is already checked in the ctor.
89  required.push_back("VK_LAYER_KHRONOS_validation");
90  }
91 
92  return required;
93 }
94 
95 std::optional<std::vector<std::string>>
97  std::vector<std::string> required;
98 
99  if (!HasExtension("VK_KHR_surface")) {
100  // Swapchain support is required and this is a dependency of
101  // VK_KHR_swapchain.
102  VALIDATION_LOG << "Could not find the surface extension.";
103  return std::nullopt;
104  }
105  required.push_back("VK_KHR_surface");
106 
107  auto has_wsi = false;
108  if (HasExtension("VK_MVK_macos_surface")) {
109  required.push_back("VK_MVK_macos_surface");
110  has_wsi = true;
111  }
112 
113  if (HasExtension("VK_EXT_metal_surface")) {
114  required.push_back("VK_EXT_metal_surface");
115  has_wsi = true;
116  }
117 
118  if (HasExtension("VK_KHR_portability_enumeration")) {
119  required.push_back("VK_KHR_portability_enumeration");
120  has_wsi = true;
121  }
122 
123  if (HasExtension("VK_KHR_win32_surface")) {
124  required.push_back("VK_KHR_win32_surface");
125  has_wsi = true;
126  }
127 
128  if (HasExtension("VK_KHR_android_surface")) {
129  required.push_back("VK_KHR_android_surface");
130  has_wsi = true;
131  }
132 
133  if (HasExtension("VK_KHR_xcb_surface")) {
134  required.push_back("VK_KHR_xcb_surface");
135  has_wsi = true;
136  }
137 
138  if (HasExtension("VK_KHR_xlib_surface")) {
139  required.push_back("VK_KHR_xlib_surface");
140  has_wsi = true;
141  }
142 
143  if (HasExtension("VK_KHR_wayland_surface")) {
144  required.push_back("VK_KHR_wayland_surface");
145  has_wsi = true;
146  }
147 
148  if (!has_wsi) {
149  // Don't really care which WSI extension there is as long there is at least
150  // one.
151  VALIDATION_LOG << "Could not find a WSI extension.";
152  return std::nullopt;
153  }
154 
155  if (validations_enabled_) {
156  if (!HasExtension("VK_EXT_debug_utils")) {
157  VALIDATION_LOG << "Requested validations but could not find the "
158  "VK_EXT_debug_utils extension.";
159  return std::nullopt;
160  }
161  required.push_back("VK_EXT_debug_utils");
162 
163  if (HasExtension("VK_EXT_validation_features")) {
164  // It's valid to not have `VK_EXT_validation_features` available. That's
165  // the case when using AGI as a frame debugger.
166  required.push_back("VK_EXT_validation_features");
167  }
168  }
169 
170  return required;
171 }
172 
174  switch (ext) {
176  return VK_KHR_SWAPCHAIN_EXTENSION_NAME;
178  return "Unknown";
179  }
180  FML_UNREACHABLE();
181 }
182 
184  switch (ext) {
187  return "VK_ANDROID_external_memory_android_hardware_buffer";
189  return VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME;
191  return VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME;
193  return VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME;
195  return VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME;
197  return "Unknown";
198  }
199  FML_UNREACHABLE();
200 }
201 
203  switch (ext) {
205  return VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME;
207  return VK_KHR_EXTERNAL_FENCE_EXTENSION_NAME;
209  return VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME;
211  return VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME;
213  return "Unknown";
214  }
215 }
216 
218  switch (ext) {
220  return VK_EXT_PIPELINE_CREATION_FEEDBACK_EXTENSION_NAME;
222  return "VK_KHR_portability_subset";
224  return VK_EXT_IMAGE_COMPRESSION_CONTROL_EXTENSION_NAME;
226  return "Unknown";
227  }
228  FML_UNREACHABLE();
229 }
230 
231 template <class T>
232 static bool IterateExtensions(const std::function<bool(T)>& it) {
233  if (!it) {
234  return false;
235  }
236  for (size_t i = 0; i < static_cast<uint32_t>(T::kLast); i++) {
237  if (!it(static_cast<T>(i))) {
238  return false;
239  }
240  }
241  return true;
242 }
243 
244 static std::optional<std::set<std::string>> GetSupportedDeviceExtensions(
245  const vk::PhysicalDevice& physical_device) {
246  auto device_extensions = physical_device.enumerateDeviceExtensionProperties();
247  if (device_extensions.result != vk::Result::eSuccess) {
248  return std::nullopt;
249  }
250 
251  std::set<std::string> exts;
252  for (const auto& device_extension : device_extensions.value) {
253  exts.insert(device_extension.extensionName);
254  };
255 
256  return exts;
257 }
258 
259 std::optional<std::vector<std::string>>
261  const vk::PhysicalDevice& physical_device) const {
262  std::set<std::string> exts;
263 
264  if (!use_embedder_extensions_) {
265  auto maybe_exts = GetSupportedDeviceExtensions(physical_device);
266 
267  if (!maybe_exts.has_value()) {
268  return std::nullopt;
269  }
270  exts = maybe_exts.value();
271  } else {
272  for (const auto& ext : embedder_device_extensions_) {
273  exts.insert(ext);
274  }
275  }
276 
277  std::vector<std::string> enabled;
278 
279  auto for_each_common_extension = [&](RequiredCommonDeviceExtensionVK ext) {
280  auto name = GetExtensionName(ext);
281  if (exts.find(name) == exts.end()) {
282  VALIDATION_LOG << "Device does not support required extension: " << name;
283  return false;
284  }
285  enabled.push_back(name);
286  return true;
287  };
288 
289  auto for_each_android_extension = [&](RequiredAndroidDeviceExtensionVK ext) {
290 #ifdef FML_OS_ANDROID
291  auto name = GetExtensionName(ext);
292  if (exts.find(name) == exts.end()) {
293  VALIDATION_LOG << "Device does not support required Android extension: "
294  << name;
295  return false;
296  }
297  enabled.push_back(name);
298 #endif // FML_OS_ANDROID
299  return true;
300  };
301 
302  auto for_each_optional_android_extension =
304 #ifdef FML_OS_ANDROID
305  auto name = GetExtensionName(ext);
306  if (exts.find(name) != exts.end()) {
307  enabled.push_back(name);
308  }
309 #endif // FML_OS_ANDROID
310  return true;
311  };
312 
313  auto for_each_optional_extension = [&](OptionalDeviceExtensionVK ext) {
314  auto name = GetExtensionName(ext);
315  if (exts.find(name) != exts.end()) {
316  enabled.push_back(name);
317  }
318  return true;
319  };
320 
321  const auto iterate_extensions =
322  IterateExtensions<RequiredCommonDeviceExtensionVK>(
323  for_each_common_extension) &&
324  IterateExtensions<RequiredAndroidDeviceExtensionVK>(
325  for_each_android_extension) &&
326  IterateExtensions<OptionalDeviceExtensionVK>(
327  for_each_optional_extension) &&
328  IterateExtensions<OptionalAndroidDeviceExtensionVK>(
329  for_each_optional_android_extension);
330 
331  if (!iterate_extensions) {
332  VALIDATION_LOG << "Device not suitable since required extensions are not "
333  "supported.";
334  return std::nullopt;
335  }
336 
337  return enabled;
338 }
339 
340 static bool HasSuitableColorFormat(const vk::PhysicalDevice& device,
341  vk::Format format) {
342  const auto props = device.getFormatProperties(format);
343  // This needs to be more comprehensive.
344  return !!(props.optimalTilingFeatures &
345  vk::FormatFeatureFlagBits::eColorAttachment);
346 }
347 
348 static bool HasSuitableDepthStencilFormat(const vk::PhysicalDevice& device,
349  vk::Format format) {
350  const auto props = device.getFormatProperties(format);
351  return !!(props.optimalTilingFeatures &
352  vk::FormatFeatureFlagBits::eDepthStencilAttachment);
353 }
354 
356  const vk::PhysicalDevice& device) {
357  const auto has_color_format =
358  HasSuitableColorFormat(device, vk::Format::eR8G8B8A8Unorm);
359  const auto has_stencil_format =
360  HasSuitableDepthStencilFormat(device, vk::Format::eD32SfloatS8Uint) ||
361  HasSuitableDepthStencilFormat(device, vk::Format::eD24UnormS8Uint);
362  return has_color_format && has_stencil_format;
363 }
364 
365 static bool HasRequiredProperties(const vk::PhysicalDevice& physical_device) {
366  auto properties = physical_device.getProperties();
367  if (!(properties.limits.framebufferColorSampleCounts &
368  (vk::SampleCountFlagBits::e1 | vk::SampleCountFlagBits::e4))) {
369  return false;
370  }
371  return true;
372 }
373 
374 static bool HasRequiredQueues(const vk::PhysicalDevice& physical_device) {
375  auto queue_flags = vk::QueueFlags{};
376  for (const auto& queue : physical_device.getQueueFamilyProperties()) {
377  if (queue.queueCount == 0) {
378  continue;
379  }
380  queue_flags |= queue.queueFlags;
381  }
382  return static_cast<VkQueueFlags>(queue_flags &
383  (vk::QueueFlagBits::eGraphics |
384  vk::QueueFlagBits::eCompute |
385  vk::QueueFlagBits::eTransfer));
386 }
387 
388 template <class ExtensionEnum>
389 static bool IsExtensionInList(const std::vector<std::string>& list,
390  ExtensionEnum ext) {
391  const std::string name = GetExtensionName(ext);
392  return std::find(list.begin(), list.end(), name) != list.end();
393 }
394 
395 std::optional<CapabilitiesVK::PhysicalDeviceFeatures>
397  const vk::PhysicalDevice& device) const {
399  VALIDATION_LOG << "Device doesn't support the required formats.";
400  return std::nullopt;
401  }
402 
403  if (!HasRequiredProperties(device)) {
404  VALIDATION_LOG << "Device doesn't support the required properties.";
405  return std::nullopt;
406  }
407 
408  if (!HasRequiredQueues(device)) {
409  VALIDATION_LOG << "Device doesn't support the required queues.";
410  return std::nullopt;
411  }
412 
413  const auto enabled_extensions = GetEnabledDeviceExtensions(device);
414  if (!enabled_extensions.has_value()) {
415  VALIDATION_LOG << "Device doesn't support the required queues.";
416  return std::nullopt;
417  }
418 
419  PhysicalDeviceFeatures supported_chain;
420 
421  // Swiftshader seems to be fussy about just this structure even being in the
422  // chain. Just unlink it if its not supported. We already perform an
423  // extensions check on the other side when reading.
424  if (!IsExtensionInList(
425  enabled_extensions.value(),
427  supported_chain
428  .unlink<vk::PhysicalDeviceImageCompressionControlFeaturesEXT>();
429  }
430 
431  device.getFeatures2(&supported_chain.get());
432 
433  PhysicalDeviceFeatures required_chain;
434 
435  // Base features.
436  {
437  auto& required = required_chain.get().features;
438  const auto& supported = supported_chain.get().features;
439 
440  // We require this for enabling wireframes in the playground. But its not
441  // necessarily a big deal if we don't have this feature.
442  required.fillModeNonSolid = supported.fillModeNonSolid;
443  }
444  // VK_KHR_sampler_ycbcr_conversion features.
445  if (IsExtensionInList(
446  enabled_extensions.value(),
448  auto& required =
449  required_chain
450  .get<vk::PhysicalDeviceSamplerYcbcrConversionFeaturesKHR>();
451  const auto& supported =
452  supported_chain
453  .get<vk::PhysicalDeviceSamplerYcbcrConversionFeaturesKHR>();
454 
455  required.samplerYcbcrConversion = supported.samplerYcbcrConversion;
456  }
457 
458  // VK_EXT_image_compression_control
459  if (IsExtensionInList(
460  enabled_extensions.value(),
462  auto& required =
463  required_chain
464  .get<vk::PhysicalDeviceImageCompressionControlFeaturesEXT>();
465  const auto& supported =
466  supported_chain
467  .get<vk::PhysicalDeviceImageCompressionControlFeaturesEXT>();
468 
469  required.imageCompressionControl = supported.imageCompressionControl;
470  } else {
471  required_chain
472  .unlink<vk::PhysicalDeviceImageCompressionControlFeaturesEXT>();
473  }
474 
475  // Vulkan 1.1
476  {
477  auto& required =
478  required_chain.get<vk::PhysicalDevice16BitStorageFeatures>();
479  const auto& supported =
480  supported_chain.get<vk::PhysicalDevice16BitStorageFeatures>();
481 
482  required.uniformAndStorageBuffer16BitAccess =
483  supported.uniformAndStorageBuffer16BitAccess;
484  }
485 
486  return required_chain;
487 }
488 
489 bool CapabilitiesVK::HasLayer(const std::string& layer) const {
490  for (const auto& [found_layer, exts] : exts_) {
491  if (found_layer == layer) {
492  return true;
493  }
494  }
495  return false;
496 }
497 
498 bool CapabilitiesVK::HasExtension(const std::string& ext) const {
499  for (const auto& [layer, exts] : exts_) {
500  if (exts.find(ext) != exts.end()) {
501  return true;
502  }
503  }
504  return false;
505 }
506 
508  return has_primitive_restart_;
509 }
510 
512  default_color_format_ = pixel_format;
513 }
514 
516  const vk::PhysicalDevice& device,
517  const PhysicalDeviceFeatures& enabled_features) {
518  if (HasSuitableColorFormat(device, vk::Format::eR8G8B8A8Unorm)) {
519  default_color_format_ = PixelFormat::kR8G8B8A8UNormInt;
520  } else {
521  default_color_format_ = PixelFormat::kUnknown;
522  }
523 
524  if (HasSuitableDepthStencilFormat(device, vk::Format::eD24UnormS8Uint)) {
525  default_depth_stencil_format_ = PixelFormat::kD24UnormS8Uint;
526  } else if (HasSuitableDepthStencilFormat(device,
527  vk::Format::eD32SfloatS8Uint)) {
528  default_depth_stencil_format_ = PixelFormat::kD32FloatS8UInt;
529  } else {
530  default_depth_stencil_format_ = PixelFormat::kUnknown;
531  }
532 
533  if (HasSuitableDepthStencilFormat(device, vk::Format::eS8Uint)) {
534  default_stencil_format_ = PixelFormat::kS8UInt;
535  } else if (default_depth_stencil_format_ != PixelFormat::kUnknown) {
536  default_stencil_format_ = default_depth_stencil_format_;
537  }
538 
539  physical_device_ = device;
540  device_properties_ = device.getProperties();
541 
542  auto physical_properties_2 =
543  device.getProperties2<vk::PhysicalDeviceProperties2,
544  vk::PhysicalDeviceSubgroupProperties>();
545 
546  // Currently shaders only want access to arithmetic subgroup features.
547  // If that changes this needs to get updated, and so does Metal (which right
548  // now assumes it from compile time flags based on the MSL target version).
549 
550  supports_compute_subgroups_ =
551  !!(physical_properties_2.get<vk::PhysicalDeviceSubgroupProperties>()
552  .supportedOperations &
553  vk::SubgroupFeatureFlagBits::eArithmetic);
554 
555  {
556  // Query texture support.
557  // TODO(129784): Add a capability check for expected memory types.
558  vk::PhysicalDeviceMemoryProperties memory_properties;
559  device.getMemoryProperties(&memory_properties);
560 
561  for (auto i = 0u; i < memory_properties.memoryTypeCount; i++) {
562  if (memory_properties.memoryTypes[i].propertyFlags &
563  vk::MemoryPropertyFlagBits::eLazilyAllocated) {
564  supports_device_transient_textures_ = true;
565  }
566  }
567  }
568 
569  // Determine the optional device extensions this physical device supports.
570  {
571  required_common_device_extensions_.clear();
572  required_android_device_extensions_.clear();
573  optional_device_extensions_.clear();
574  optional_android_device_extensions_.clear();
575 
576  std::set<std::string> exts;
577  if (!use_embedder_extensions_) {
578  auto maybe_exts = GetSupportedDeviceExtensions(device);
579  if (!maybe_exts.has_value()) {
580  return false;
581  }
582  exts = maybe_exts.value();
583  } else {
584  for (const auto& ext : embedder_device_extensions_) {
585  exts.insert(ext);
586  }
587  }
588 
589  IterateExtensions<RequiredCommonDeviceExtensionVK>([&](auto ext) -> bool {
590  auto ext_name = GetExtensionName(ext);
591  if (exts.find(ext_name) != exts.end()) {
592  required_common_device_extensions_.insert(ext);
593  }
594  return true;
595  });
596  IterateExtensions<RequiredAndroidDeviceExtensionVK>([&](auto ext) -> bool {
597  auto ext_name = GetExtensionName(ext);
598  if (exts.find(ext_name) != exts.end()) {
599  required_android_device_extensions_.insert(ext);
600  }
601  return true;
602  });
603  IterateExtensions<OptionalDeviceExtensionVK>([&](auto ext) -> bool {
604  auto ext_name = GetExtensionName(ext);
605  if (exts.find(ext_name) != exts.end()) {
606  optional_device_extensions_.insert(ext);
607  }
608  return true;
609  });
610  IterateExtensions<OptionalAndroidDeviceExtensionVK>(
612  auto name = GetExtensionName(ext);
613  if (exts.find(name) != exts.end()) {
614  optional_android_device_extensions_.insert(ext);
615  }
616  return true;
617  });
618  }
619 
620  supports_texture_fixed_rate_compression_ =
621  enabled_features
622  .isLinked<vk::PhysicalDeviceImageCompressionControlFeaturesEXT>() &&
623  enabled_features
624  .get<vk::PhysicalDeviceImageCompressionControlFeaturesEXT>()
625  .imageCompressionControl;
626 
627  max_render_pass_attachment_size_ =
628  ISize{device_properties_.limits.maxFramebufferWidth,
629  device_properties_.limits.maxFramebufferHeight};
630 
631  // Molten, Vulkan on Metal, cannot support triangle fans because Metal doesn't
632  // support triangle fans.
633  // See VUID-VkPipelineInputAssemblyStateCreateInfo-triangleFans-04452.
634  has_triangle_fans_ =
636 
637  // External Fence/Semaphore for AHB swapchain
642  supports_external_fence_and_semaphore_ = true;
643  }
644 
645  minimum_uniform_alignment_ =
646  device_properties_.limits.minUniformBufferOffsetAlignment;
647 
648  return true;
649 }
650 
651 // |Capabilities|
653  return true;
654 }
655 
656 // |Capabilities|
658  return false;
659 }
660 
661 // |Capabilities|
663  return true;
664 }
665 
666 // |Capabilities|
668  return true;
669 }
670 
671 // |Capabilities|
673  return has_framebuffer_fetch_;
674 }
675 
676 // |Capabilities|
678  // Vulkan 1.1 requires support for compute.
679  return true;
680 }
681 
682 // |Capabilities|
684  // Set by |SetPhysicalDevice|.
685  return supports_compute_subgroups_;
686 }
687 
688 // |Capabilities|
690  return false;
691 }
692 
694  return true;
695 }
696 
697 // |Capabilities|
699  return supports_device_transient_textures_;
700 }
701 
702 // |Capabilities|
704  return default_color_format_;
705 }
706 
707 // |Capabilities|
709  return default_stencil_format_;
710 }
711 
712 // |Capabilities|
714  return default_depth_stencil_format_;
715 }
716 
717 const vk::PhysicalDeviceProperties&
719  return device_properties_;
720 }
721 
724 }
725 
727  return minimum_uniform_alignment_;
728 }
729 
731  return required_common_device_extensions_.find(ext) !=
732  required_common_device_extensions_.end();
733 }
734 
736  return required_android_device_extensions_.find(ext) !=
737  required_android_device_extensions_.end();
738 }
739 
741  return optional_device_extensions_.find(ext) !=
742  optional_device_extensions_.end();
743 }
744 
746  return optional_android_device_extensions_.find(ext) !=
747  optional_android_device_extensions_.end();
748 }
749 
751  return supports_texture_fixed_rate_compression_;
752 }
753 
754 std::optional<vk::ImageCompressionFixedRateFlagBitsEXT>
756  const FRCFormatDescriptor& desc) const {
757  if (compression_type != CompressionType::kLossy) {
758  return std::nullopt;
759  }
760  if (!supports_texture_fixed_rate_compression_) {
761  return std::nullopt;
762  }
763  // There are opportunities to hash and cache the FRCFormatDescriptor if
764  // needed.
765  vk::StructureChain<vk::PhysicalDeviceImageFormatInfo2,
766  vk::ImageCompressionControlEXT>
767  format_chain;
768 
769  auto& format_info = format_chain.get();
770 
771  format_info.format = desc.format;
772  format_info.type = desc.type;
773  format_info.tiling = desc.tiling;
774  format_info.usage = desc.usage;
775  format_info.flags = desc.flags;
776 
777  const auto kIdealFRCRate = vk::ImageCompressionFixedRateFlagBitsEXT::e4Bpc;
778 
779  std::array<vk::ImageCompressionFixedRateFlagsEXT, 1u> rates = {kIdealFRCRate};
780 
781  auto& compression = format_chain.get<vk::ImageCompressionControlEXT>();
782  compression.flags = vk::ImageCompressionFlagBitsEXT::eFixedRateExplicit;
783  compression.compressionControlPlaneCount = rates.size();
784  compression.pFixedRateFlags = rates.data();
785 
786  const auto [result, supported] = physical_device_.getImageFormatProperties2<
787  vk::ImageFormatProperties2, vk::ImageCompressionPropertiesEXT>(
788  format_chain.get());
789 
790  if (result != vk::Result::eSuccess ||
791  !supported.isLinked<vk::ImageCompressionPropertiesEXT>()) {
792  return std::nullopt;
793  }
794 
795  const auto& compression_props =
796  supported.get<vk::ImageCompressionPropertiesEXT>();
797 
798  if ((compression_props.imageCompressionFlags &
799  vk::ImageCompressionFlagBitsEXT::eFixedRateExplicit) &&
800  (compression_props.imageCompressionFixedRateFlags & kIdealFRCRate)) {
801  return kIdealFRCRate;
802  }
803 
804  return std::nullopt;
805 }
806 
808  return has_triangle_fans_;
809 }
810 
812  return max_render_pass_attachment_size_;
813 }
814 
816  has_primitive_restart_ = !workarounds.slow_primitive_restart_performance;
817  has_framebuffer_fetch_ = !workarounds.input_attachment_self_dependency_broken;
818 }
819 
821  return supports_external_fence_and_semaphore_;
822 }
823 
825  return false;
826 }
827 
828 } // namespace impeller
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 AreValidationsEnabled() 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
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.
vk::StructureChain< vk::PhysicalDeviceFeatures2, vk::PhysicalDeviceSamplerYcbcrConversionFeaturesKHR, vk::PhysicalDevice16BitStorageFeatures, vk::PhysicalDeviceImageCompressionControlFeaturesEXT > PhysicalDeviceFeatures
bool SupportsComputeSubgroups() const override
Whether the context backend supports configuring ComputePass command subgroups.
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 ...
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
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
Vector3 e1
static bool IterateExtensions(const std::function< bool(T)> &it)
static std::optional< std::set< std::string > > GetSupportedDeviceExtensions(const vk::PhysicalDevice &physical_device)
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 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 const char * GetExtensionName(RequiredCommonDeviceExtensionVK ext)
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: comparable.h:95
A pixel format and usage that is sufficient to check if images of that format and usage are suitable ...
vk::ImageCreateFlags flags
A non-exhaustive set of driver specific workarounds.
bool input_attachment_self_dependency_broken
#define VALIDATION_LOG
Definition: validation.h:91