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  exts = std::set(embedder_device_extensions_.begin(),
273  embedder_device_extensions_.end());
274  }
275 
276  std::vector<std::string> enabled;
277 
278  auto for_each_common_extension = [&](RequiredCommonDeviceExtensionVK ext) {
279  auto name = GetExtensionName(ext);
280  if (exts.find(name) == exts.end()) {
281  VALIDATION_LOG << "Device does not support required extension: " << name;
282  return false;
283  }
284  enabled.push_back(name);
285  return true;
286  };
287 
288  auto for_each_android_extension = [&](RequiredAndroidDeviceExtensionVK ext) {
289 #ifdef FML_OS_ANDROID
290  auto name = GetExtensionName(ext);
291  if (exts.find(name) == exts.end()) {
292  VALIDATION_LOG << "Device does not support required Android extension: "
293  << name;
294  return false;
295  }
296  enabled.push_back(name);
297 #endif // FML_OS_ANDROID
298  return true;
299  };
300 
301  auto for_each_optional_android_extension =
303 #ifdef FML_OS_ANDROID
304  auto name = GetExtensionName(ext);
305  if (exts.find(name) != exts.end()) {
306  enabled.push_back(name);
307  }
308 #endif // FML_OS_ANDROID
309  return true;
310  };
311 
312  auto for_each_optional_extension = [&](OptionalDeviceExtensionVK ext) {
313  auto name = GetExtensionName(ext);
314  if (exts.find(name) != exts.end()) {
315  enabled.push_back(name);
316  }
317  return true;
318  };
319 
320  const auto iterate_extensions =
321  IterateExtensions<RequiredCommonDeviceExtensionVK>(
322  for_each_common_extension) &&
323  IterateExtensions<RequiredAndroidDeviceExtensionVK>(
324  for_each_android_extension) &&
325  IterateExtensions<OptionalDeviceExtensionVK>(
326  for_each_optional_extension) &&
327  IterateExtensions<OptionalAndroidDeviceExtensionVK>(
328  for_each_optional_android_extension);
329 
330  if (!iterate_extensions) {
331  VALIDATION_LOG << "Device not suitable since required extensions are not "
332  "supported.";
333  return std::nullopt;
334  }
335 
336  return enabled;
337 }
338 
339 static bool HasSuitableColorFormat(const vk::PhysicalDevice& device,
340  vk::Format format) {
341  const auto props = device.getFormatProperties(format);
342  // This needs to be more comprehensive.
343  return !!(props.optimalTilingFeatures &
344  vk::FormatFeatureFlagBits::eColorAttachment);
345 }
346 
347 static bool HasSuitableDepthStencilFormat(const vk::PhysicalDevice& device,
348  vk::Format format) {
349  const auto props = device.getFormatProperties(format);
350  return !!(props.optimalTilingFeatures &
351  vk::FormatFeatureFlagBits::eDepthStencilAttachment);
352 }
353 
355  const vk::PhysicalDevice& device) {
356  const auto has_color_format =
357  HasSuitableColorFormat(device, vk::Format::eR8G8B8A8Unorm);
358  const auto has_stencil_format =
359  HasSuitableDepthStencilFormat(device, vk::Format::eD32SfloatS8Uint) ||
360  HasSuitableDepthStencilFormat(device, vk::Format::eD24UnormS8Uint);
361  return has_color_format && has_stencil_format;
362 }
363 
364 static bool HasRequiredProperties(const vk::PhysicalDevice& physical_device) {
365  auto properties = physical_device.getProperties();
366  if (!(properties.limits.framebufferColorSampleCounts &
367  (vk::SampleCountFlagBits::e1 | vk::SampleCountFlagBits::e4))) {
368  return false;
369  }
370  return true;
371 }
372 
373 static bool HasRequiredQueues(const vk::PhysicalDevice& physical_device) {
374  auto queue_flags = vk::QueueFlags{};
375  for (const auto& queue : physical_device.getQueueFamilyProperties()) {
376  if (queue.queueCount == 0) {
377  continue;
378  }
379  queue_flags |= queue.queueFlags;
380  }
381  return static_cast<VkQueueFlags>(queue_flags &
382  (vk::QueueFlagBits::eGraphics |
383  vk::QueueFlagBits::eCompute |
384  vk::QueueFlagBits::eTransfer));
385 }
386 
387 template <class ExtensionEnum>
388 static bool IsExtensionInList(const std::vector<std::string>& list,
389  ExtensionEnum ext) {
390  const std::string name = GetExtensionName(ext);
391  return std::find(list.begin(), list.end(), name) != list.end();
392 }
393 
394 std::optional<CapabilitiesVK::PhysicalDeviceFeatures>
396  const vk::PhysicalDevice& device) const {
398  VALIDATION_LOG << "Device doesn't support the required formats.";
399  return std::nullopt;
400  }
401 
402  if (!HasRequiredProperties(device)) {
403  VALIDATION_LOG << "Device doesn't support the required properties.";
404  return std::nullopt;
405  }
406 
407  if (!HasRequiredQueues(device)) {
408  VALIDATION_LOG << "Device doesn't support the required queues.";
409  return std::nullopt;
410  }
411 
412  const auto enabled_extensions = GetEnabledDeviceExtensions(device);
413  if (!enabled_extensions.has_value()) {
414  VALIDATION_LOG << "Device doesn't support the required queues.";
415  return std::nullopt;
416  }
417 
418  PhysicalDeviceFeatures supported_chain;
419 
420  // Swiftshader seems to be fussy about just this structure even being in the
421  // chain. Just unlink it if its not supported. We already perform an
422  // extensions check on the other side when reading.
423  if (!IsExtensionInList(
424  enabled_extensions.value(),
426  supported_chain
427  .unlink<vk::PhysicalDeviceImageCompressionControlFeaturesEXT>();
428  }
429 
430  device.getFeatures2(&supported_chain.get());
431 
432  PhysicalDeviceFeatures required_chain;
433 
434  // Base features.
435  {
436  auto& required = required_chain.get().features;
437  const auto& supported = supported_chain.get().features;
438 
439  // We require this for enabling wireframes in the playground. But its not
440  // necessarily a big deal if we don't have this feature.
441  required.fillModeNonSolid = supported.fillModeNonSolid;
442  }
443  // VK_KHR_sampler_ycbcr_conversion features.
444  if (IsExtensionInList(
445  enabled_extensions.value(),
447  auto& required =
448  required_chain
449  .get<vk::PhysicalDeviceSamplerYcbcrConversionFeaturesKHR>();
450  const auto& supported =
451  supported_chain
452  .get<vk::PhysicalDeviceSamplerYcbcrConversionFeaturesKHR>();
453 
454  required.samplerYcbcrConversion = supported.samplerYcbcrConversion;
455  }
456 
457  // VK_EXT_image_compression_control
458  if (IsExtensionInList(
459  enabled_extensions.value(),
461  auto& required =
462  required_chain
463  .get<vk::PhysicalDeviceImageCompressionControlFeaturesEXT>();
464  const auto& supported =
465  supported_chain
466  .get<vk::PhysicalDeviceImageCompressionControlFeaturesEXT>();
467 
468  required.imageCompressionControl = supported.imageCompressionControl;
469  } else {
470  required_chain
471  .unlink<vk::PhysicalDeviceImageCompressionControlFeaturesEXT>();
472  }
473 
474  // Vulkan 1.1
475  {
476  auto& required =
477  required_chain.get<vk::PhysicalDevice16BitStorageFeatures>();
478  const auto& supported =
479  supported_chain.get<vk::PhysicalDevice16BitStorageFeatures>();
480 
481  required.uniformAndStorageBuffer16BitAccess =
482  supported.uniformAndStorageBuffer16BitAccess;
483  }
484 
485  return required_chain;
486 }
487 
488 bool CapabilitiesVK::HasLayer(const std::string& layer) const {
489  for (const auto& [found_layer, exts] : exts_) {
490  if (found_layer == layer) {
491  return true;
492  }
493  }
494  return false;
495 }
496 
497 bool CapabilitiesVK::HasExtension(const std::string& ext) const {
498  for (const auto& [layer, exts] : exts_) {
499  if (exts.find(ext) != exts.end()) {
500  return true;
501  }
502  }
503  return false;
504 }
505 
507  return has_primitive_restart_;
508 }
509 
511  default_color_format_ = pixel_format;
512 }
513 
515  const vk::PhysicalDevice& device,
516  const PhysicalDeviceFeatures& enabled_features) {
517  if (HasSuitableColorFormat(device, vk::Format::eR8G8B8A8Unorm)) {
518  default_color_format_ = PixelFormat::kR8G8B8A8UNormInt;
519  } else {
520  default_color_format_ = PixelFormat::kUnknown;
521  }
522 
523  if (HasSuitableDepthStencilFormat(device, vk::Format::eD32SfloatS8Uint)) {
524  default_depth_stencil_format_ = PixelFormat::kD32FloatS8UInt;
525  } else if (HasSuitableDepthStencilFormat(device,
526  vk::Format::eD24UnormS8Uint)) {
527  default_depth_stencil_format_ = PixelFormat::kD24UnormS8Uint;
528  } else {
529  default_depth_stencil_format_ = PixelFormat::kUnknown;
530  }
531 
532  if (HasSuitableDepthStencilFormat(device, vk::Format::eS8Uint)) {
533  default_stencil_format_ = PixelFormat::kS8UInt;
534  } else if (default_depth_stencil_format_ != PixelFormat::kUnknown) {
535  default_stencil_format_ = default_depth_stencil_format_;
536  }
537 
538  physical_device_ = device;
539  device_properties_ = device.getProperties();
540 
541  auto physical_properties_2 =
542  device.getProperties2<vk::PhysicalDeviceProperties2,
543  vk::PhysicalDeviceSubgroupProperties>();
544 
545  // Currently shaders only want access to arithmetic subgroup features.
546  // If that changes this needs to get updated, and so does Metal (which right
547  // now assumes it from compile time flags based on the MSL target version).
548 
549  supports_compute_subgroups_ =
550  !!(physical_properties_2.get<vk::PhysicalDeviceSubgroupProperties>()
551  .supportedOperations &
552  vk::SubgroupFeatureFlagBits::eArithmetic);
553 
554  {
555  // Query texture support.
556  // TODO(129784): Add a capability check for expected memory types.
557  vk::PhysicalDeviceMemoryProperties memory_properties;
558  device.getMemoryProperties(&memory_properties);
559 
560  for (auto i = 0u; i < memory_properties.memoryTypeCount; i++) {
561  if (memory_properties.memoryTypes[i].propertyFlags &
562  vk::MemoryPropertyFlagBits::eLazilyAllocated) {
563  supports_device_transient_textures_ = true;
564  }
565  }
566  }
567 
568  // Determine the optional device extensions this physical device supports.
569  {
570  required_common_device_extensions_.clear();
571  required_android_device_extensions_.clear();
572  optional_device_extensions_.clear();
573  optional_android_device_extensions_.clear();
574 
575  std::set<std::string> exts;
576  if (!use_embedder_extensions_) {
577  auto maybe_exts = GetSupportedDeviceExtensions(device);
578  if (!maybe_exts.has_value()) {
579  return false;
580  }
581  exts = maybe_exts.value();
582  } else {
583  exts = std::set(embedder_device_extensions_.begin(),
584  embedder_device_extensions_.end());
585  }
586 
587  IterateExtensions<RequiredCommonDeviceExtensionVK>([&](auto ext) -> bool {
588  auto ext_name = GetExtensionName(ext);
589  if (exts.find(ext_name) != exts.end()) {
590  required_common_device_extensions_.insert(ext);
591  }
592  return true;
593  });
594  IterateExtensions<RequiredAndroidDeviceExtensionVK>([&](auto ext) -> bool {
595  auto ext_name = GetExtensionName(ext);
596  if (exts.find(ext_name) != exts.end()) {
597  required_android_device_extensions_.insert(ext);
598  }
599  return true;
600  });
601  IterateExtensions<OptionalDeviceExtensionVK>([&](auto ext) -> bool {
602  auto ext_name = GetExtensionName(ext);
603  if (exts.find(ext_name) != exts.end()) {
604  optional_device_extensions_.insert(ext);
605  }
606  return true;
607  });
608  IterateExtensions<OptionalAndroidDeviceExtensionVK>(
610  auto name = GetExtensionName(ext);
611  if (exts.find(name) != exts.end()) {
612  optional_android_device_extensions_.insert(ext);
613  }
614  return true;
615  });
616  }
617 
618  supports_texture_fixed_rate_compression_ =
619  enabled_features
620  .isLinked<vk::PhysicalDeviceImageCompressionControlFeaturesEXT>() &&
621  enabled_features
622  .get<vk::PhysicalDeviceImageCompressionControlFeaturesEXT>()
623  .imageCompressionControl;
624 
625  max_render_pass_attachment_size_ =
626  ISize{device_properties_.limits.maxFramebufferWidth,
627  device_properties_.limits.maxFramebufferHeight};
628 
629  // Molten, Vulkan on Metal, cannot support triangle fans because Metal doesn't
630  // support triangle fans.
631  // See VUID-VkPipelineInputAssemblyStateCreateInfo-triangleFans-04452.
632  has_triangle_fans_ =
634 
635  // External Fence/Semaphore for AHB swapchain
640  supports_external_fence_and_semaphore_ = true;
641  }
642 
643  return true;
644 }
645 
646 // |Capabilities|
648  return true;
649 }
650 
651 // |Capabilities|
653  return false;
654 }
655 
656 // |Capabilities|
658  return true;
659 }
660 
661 // |Capabilities|
663  return true;
664 }
665 
666 // |Capabilities|
668  return has_framebuffer_fetch_;
669 }
670 
671 // |Capabilities|
673  // Vulkan 1.1 requires support for compute.
674  return true;
675 }
676 
677 // |Capabilities|
679  // Set by |SetPhysicalDevice|.
680  return supports_compute_subgroups_;
681 }
682 
683 // |Capabilities|
685  return false;
686 }
687 
689  return true;
690 }
691 
692 // |Capabilities|
694  return supports_device_transient_textures_;
695 }
696 
697 // |Capabilities|
699  return default_color_format_;
700 }
701 
702 // |Capabilities|
704  return default_stencil_format_;
705 }
706 
707 // |Capabilities|
709  return default_depth_stencil_format_;
710 }
711 
712 const vk::PhysicalDeviceProperties&
714  return device_properties_;
715 }
716 
719 }
720 
722  return required_common_device_extensions_.find(ext) !=
723  required_common_device_extensions_.end();
724 }
725 
727  return required_android_device_extensions_.find(ext) !=
728  required_android_device_extensions_.end();
729 }
730 
732  return optional_device_extensions_.find(ext) !=
733  optional_device_extensions_.end();
734 }
735 
737  return optional_android_device_extensions_.find(ext) !=
738  optional_android_device_extensions_.end();
739 }
740 
742  return supports_texture_fixed_rate_compression_;
743 }
744 
745 std::optional<vk::ImageCompressionFixedRateFlagBitsEXT>
747  const FRCFormatDescriptor& desc) const {
748  if (compression_type != CompressionType::kLossy) {
749  return std::nullopt;
750  }
751  if (!supports_texture_fixed_rate_compression_) {
752  return std::nullopt;
753  }
754  // There are opportunities to hash and cache the FRCFormatDescriptor if
755  // needed.
756  vk::StructureChain<vk::PhysicalDeviceImageFormatInfo2,
757  vk::ImageCompressionControlEXT>
758  format_chain;
759 
760  auto& format_info = format_chain.get();
761 
762  format_info.format = desc.format;
763  format_info.type = desc.type;
764  format_info.tiling = desc.tiling;
765  format_info.usage = desc.usage;
766  format_info.flags = desc.flags;
767 
768  const auto kIdealFRCRate = vk::ImageCompressionFixedRateFlagBitsEXT::e4Bpc;
769 
770  std::array<vk::ImageCompressionFixedRateFlagsEXT, 1u> rates = {kIdealFRCRate};
771 
772  auto& compression = format_chain.get<vk::ImageCompressionControlEXT>();
773  compression.flags = vk::ImageCompressionFlagBitsEXT::eFixedRateExplicit;
774  compression.compressionControlPlaneCount = rates.size();
775  compression.pFixedRateFlags = rates.data();
776 
777  const auto [result, supported] = physical_device_.getImageFormatProperties2<
778  vk::ImageFormatProperties2, vk::ImageCompressionPropertiesEXT>(
779  format_chain.get());
780 
781  if (result != vk::Result::eSuccess ||
782  !supported.isLinked<vk::ImageCompressionPropertiesEXT>()) {
783  return std::nullopt;
784  }
785 
786  const auto& compression_props =
787  supported.get<vk::ImageCompressionPropertiesEXT>();
788 
789  if ((compression_props.imageCompressionFlags &
790  vk::ImageCompressionFlagBitsEXT::eFixedRateExplicit) &&
791  (compression_props.imageCompressionFixedRateFlags & kIdealFRCRate)) {
792  return kIdealFRCRate;
793  }
794 
795  return std::nullopt;
796 }
797 
799  return has_triangle_fans_;
800 }
801 
803  return max_render_pass_attachment_size_;
804 }
805 
807  has_primitive_restart_ = !workarounds.slow_primitive_restart_performance;
808  has_framebuffer_fetch_ = !workarounds.input_attachment_self_dependency_broken;
809 }
810 
812  return supports_external_fence_and_semaphore_;
813 }
814 
816  return false;
817 }
818 
819 } // namespace impeller
bool SupportsTriangleFan() const override
Whether the primitive type TriangleFan is supported by the backend.
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