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();
34 if (extensions.result != vk::Result::eSuccess ||
35 layers.result != vk::Result::eSuccess) {
39 for (
const auto& ext : extensions.value) {
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) {
49 for (
const auto& layer_ext : layer_exts.value) {
50 exts_[layer_name].insert(layer_ext.extensionName);
54 for (
const auto& ext : embedder_instance_extensions_) {
59 validations_enabled_ =
60 enable_validations && HasLayer(
"VK_LAYER_KHRONOS_validation");
61 if (enable_validations && !validations_enabled_) {
63 <<
"Requested Impeller context creation with validations but the "
64 "validation layers could not be found. Expect no Vulkan validation "
66 if (fatal_missing_validations) {
67 FML_LOG(FATAL) <<
"Validation missing. Exiting.";
70 if (validations_enabled_) {
71 FML_LOG(INFO) <<
"Vulkan validations are enabled.";
83 return validations_enabled_;
88 std::vector<std::string> required;
90 if (validations_enabled_) {
92 required.push_back(
"VK_LAYER_KHRONOS_validation");
98std::optional<std::vector<std::string>>
100 std::vector<std::string> required;
108 required.push_back(
"VK_KHR_surface");
110 auto has_wsi =
false;
112 required.push_back(
"VK_MVK_macos_surface");
117 required.push_back(
"VK_EXT_metal_surface");
122 required.push_back(
"VK_KHR_portability_enumeration");
127 required.push_back(
"VK_KHR_win32_surface");
132 required.push_back(
"VK_KHR_android_surface");
137 required.push_back(
"VK_KHR_xcb_surface");
142 required.push_back(
"VK_KHR_xlib_surface");
147 required.push_back(
"VK_KHR_wayland_surface");
158 if (validations_enabled_) {
161 "VK_EXT_debug_utils extension.";
164 required.push_back(
"VK_EXT_debug_utils");
169 required.push_back(
"VK_EXT_validation_features");
179 return VK_KHR_SWAPCHAIN_EXTENSION_NAME;
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;
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;
223 return VK_EXT_PIPELINE_CREATION_FEEDBACK_EXTENSION_NAME;
225 return "VK_KHR_portability_subset";
227 return VK_EXT_IMAGE_COMPRESSION_CONTROL_EXTENSION_NAME;
239 for (
size_t i = 0; i < static_cast<uint32_t>(T::kLast);
i++) {
240 if (!it(
static_cast<T
>(
i))) {
249 auto device_extensions =
physical_device.enumerateDeviceExtensionProperties();
250 if (device_extensions.result != vk::Result::eSuccess) {
254 std::set<std::string> exts;
255 for (
const auto& device_extension : device_extensions.value) {
256 exts.insert(device_extension.extensionName);
262std::optional<std::vector<std::string>>
265 std::set<std::string> exts;
267 if (!use_embedder_extensions_) {
270 if (!maybe_exts.has_value()) {
273 exts = maybe_exts.value();
275 for (
const auto& ext : embedder_device_extensions_) {
280 std::vector<std::string> enabled;
284 if (exts.find(
name) == exts.end()) {
288 enabled.push_back(
name);
295 if (exts.find(
name) == exts.end()) {
296 VALIDATION_LOG <<
"Device does not support required Android extension: "
300 enabled.push_back(
name);
305 auto for_each_optional_android_extension =
309 if (exts.find(
name) != exts.end()) {
310 enabled.push_back(
name);
318 if (exts.find(
name) != exts.end()) {
319 enabled.push_back(
name);
324 const auto iterate_extensions =
325 IterateExtensions<RequiredCommonDeviceExtensionVK>(
326 for_each_common_extension) &&
327 IterateExtensions<RequiredAndroidDeviceExtensionVK>(
328 for_each_android_extension) &&
329 IterateExtensions<OptionalDeviceExtensionVK>(
330 for_each_optional_extension) &&
331 IterateExtensions<OptionalAndroidDeviceExtensionVK>(
332 for_each_optional_android_extension);
334 if (!iterate_extensions) {
335 VALIDATION_LOG <<
"Device not suitable since required extensions are not "
347 return !!(props.optimalTilingFeatures &
348 vk::FormatFeatureFlagBits::eColorAttachment);
354 return !!(props.optimalTilingFeatures &
355 vk::FormatFeatureFlagBits::eDepthStencilAttachment);
359 const vk::PhysicalDevice&
device) {
360 const auto has_color_format =
362 const auto has_stencil_format =
365 return has_color_format && has_stencil_format;
370 if (!(properties.limits.framebufferColorSampleCounts &
371 (vk::SampleCountFlagBits::e1 | vk::SampleCountFlagBits::e4))) {
378 auto queue_flags = vk::QueueFlags{};
380 if (
queue.queueCount == 0) {
383 queue_flags |=
queue.queueFlags;
385 return static_cast<VkQueueFlags
>(queue_flags &
386 (vk::QueueFlagBits::eGraphics |
387 vk::QueueFlagBits::eCompute |
388 vk::QueueFlagBits::eTransfer));
391template <
class ExtensionEnum>
395 return std::find(list.begin(), list.end(),
name) != list.end();
398std::optional<CapabilitiesVK::PhysicalDeviceFeatures>
400 const vk::PhysicalDevice&
device)
const {
407 VALIDATION_LOG <<
"Device doesn't support the required properties.";
417 if (!enabled_extensions.has_value()) {
428 enabled_extensions.value(),
431 .unlink<vk::PhysicalDeviceImageCompressionControlFeaturesEXT>();
434 device.getFeatures2(&supported_chain.get());
440 auto& required = required_chain.get().features;
441 const auto& supported = supported_chain.get().features;
445 required.fillModeNonSolid = supported.fillModeNonSolid;
449 enabled_extensions.value(),
453 .get<vk::PhysicalDeviceSamplerYcbcrConversionFeaturesKHR>();
454 const auto& supported =
456 .get<vk::PhysicalDeviceSamplerYcbcrConversionFeaturesKHR>();
458 required.samplerYcbcrConversion = supported.samplerYcbcrConversion;
463 enabled_extensions.value(),
467 .get<vk::PhysicalDeviceImageCompressionControlFeaturesEXT>();
468 const auto& supported =
470 .get<vk::PhysicalDeviceImageCompressionControlFeaturesEXT>();
472 required.imageCompressionControl = supported.imageCompressionControl;
475 .unlink<vk::PhysicalDeviceImageCompressionControlFeaturesEXT>();
481 required_chain.get<vk::PhysicalDevice16BitStorageFeatures>();
482 const auto& supported =
483 supported_chain.get<vk::PhysicalDevice16BitStorageFeatures>();
485 required.uniformAndStorageBuffer16BitAccess =
486 supported.uniformAndStorageBuffer16BitAccess;
489 return required_chain;
492bool CapabilitiesVK::HasLayer(
const std::string& layer)
const {
493 for (
const auto& [found_layer, exts] : exts_) {
494 if (found_layer == layer) {
502 for (
const auto& [layer, exts] : exts_) {
503 if (exts.find(ext) != exts.end()) {
511 return has_primitive_restart_;
519 default_color_format_ = pixel_format;
523 const vk::PhysicalDevice&
device,
534 vk::Format::eD32SfloatS8Uint)) {
543 default_stencil_format_ = default_depth_stencil_format_;
546 physical_device_ =
device;
547 device_properties_ =
device.getProperties();
549 auto physical_properties_2 =
550 device.getProperties2<vk::PhysicalDeviceProperties2,
551 vk::PhysicalDeviceSubgroupProperties>();
557 supports_compute_subgroups_ =
558 !!(physical_properties_2.get<vk::PhysicalDeviceSubgroupProperties>()
559 .supportedOperations &
560 vk::SubgroupFeatureFlagBits::eArithmetic);
565 vk::PhysicalDeviceMemoryProperties memory_properties;
566 device.getMemoryProperties(&memory_properties);
568 for (
auto i = 0u;
i < memory_properties.memoryTypeCount;
i++) {
569 if (memory_properties.memoryTypes[
i].propertyFlags &
570 vk::MemoryPropertyFlagBits::eLazilyAllocated) {
571 supports_device_transient_textures_ =
true;
578 required_common_device_extensions_.clear();
579 required_android_device_extensions_.clear();
580 optional_device_extensions_.clear();
581 optional_android_device_extensions_.clear();
583 std::set<std::string> exts;
584 if (!use_embedder_extensions_) {
586 if (!maybe_exts.has_value()) {
589 exts = maybe_exts.value();
591 for (
const auto& ext : embedder_device_extensions_) {
596 IterateExtensions<RequiredCommonDeviceExtensionVK>([&](
auto ext) ->
bool {
598 if (exts.find(ext_name) != exts.end()) {
599 required_common_device_extensions_.insert(ext);
603 IterateExtensions<RequiredAndroidDeviceExtensionVK>([&](
auto ext) ->
bool {
605 if (exts.find(ext_name) != exts.end()) {
606 required_android_device_extensions_.insert(ext);
610 IterateExtensions<OptionalDeviceExtensionVK>([&](
auto ext) ->
bool {
612 if (exts.find(ext_name) != exts.end()) {
613 optional_device_extensions_.insert(ext);
617 IterateExtensions<OptionalAndroidDeviceExtensionVK>(
620 if (exts.find(
name) != exts.end()) {
621 optional_android_device_extensions_.insert(ext);
627 supports_texture_fixed_rate_compression_ =
629 .isLinked<vk::PhysicalDeviceImageCompressionControlFeaturesEXT>() &&
631 .get<vk::PhysicalDeviceImageCompressionControlFeaturesEXT>()
632 .imageCompressionControl;
634 max_render_pass_attachment_size_ =
635 ISize{device_properties_.limits.maxFramebufferWidth,
636 device_properties_.limits.maxFramebufferHeight};
649 supports_external_fence_and_semaphore_ =
true;
652 minimum_uniform_alignment_ =
653 device_properties_.limits.minUniformBufferOffsetAlignment;
654 minimum_storage_alignment_ =
655 device_properties_.limits.minStorageBufferOffsetAlignment;
682 return has_framebuffer_fetch_;
694 return supports_compute_subgroups_;
708 return supports_device_transient_textures_;
713 return default_color_format_;
718 return default_stencil_format_;
723 return default_depth_stencil_format_;
726const vk::PhysicalDeviceProperties&
728 return device_properties_;
736 return minimum_uniform_alignment_;
740 return minimum_storage_alignment_;
748 return required_common_device_extensions_.find(ext) !=
749 required_common_device_extensions_.end();
753 return required_android_device_extensions_.find(ext) !=
754 required_android_device_extensions_.end();
758 return optional_device_extensions_.find(ext) !=
759 optional_device_extensions_.end();
763 return optional_android_device_extensions_.find(ext) !=
764 optional_android_device_extensions_.end();
768 return supports_texture_fixed_rate_compression_;
771std::optional<vk::ImageCompressionFixedRateFlagBitsEXT>
777 if (!supports_texture_fixed_rate_compression_) {
782 vk::StructureChain<vk::PhysicalDeviceImageFormatInfo2,
783 vk::ImageCompressionControlEXT>
786 auto& format_info = format_chain.get();
788 format_info.format = desc.
format;
789 format_info.type = desc.
type;
790 format_info.tiling = desc.
tiling;
791 format_info.usage = desc.
usage;
792 format_info.flags = desc.
flags;
794 const auto kIdealFRCRate = vk::ImageCompressionFixedRateFlagBitsEXT::e4Bpc;
796 std::array<vk::ImageCompressionFixedRateFlagsEXT, 1u> rates = {kIdealFRCRate};
798 auto& compression = format_chain.get<vk::ImageCompressionControlEXT>();
799 compression.flags = vk::ImageCompressionFlagBitsEXT::eFixedRateExplicit;
800 compression.compressionControlPlaneCount = rates.size();
801 compression.pFixedRateFlags = rates.data();
803 const auto [result, supported] = physical_device_.getImageFormatProperties2<
804 vk::ImageFormatProperties2, vk::ImageCompressionPropertiesEXT>(
807 if (result != vk::Result::eSuccess ||
808 !supported.isLinked<vk::ImageCompressionPropertiesEXT>()) {
812 const auto& compression_props =
813 supported.get<vk::ImageCompressionPropertiesEXT>();
815 if ((compression_props.imageCompressionFlags &
816 vk::ImageCompressionFlagBitsEXT::eFixedRateExplicit) &&
817 (compression_props.imageCompressionFixedRateFlags & kIdealFRCRate)) {
818 return kIdealFRCRate;
825 return has_triangle_fans_;
829 return max_render_pass_attachment_size_;
838 return supports_external_fence_and_semaphore_;
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.
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
VkPhysicalDevice physical_device
const FlutterLayer ** layers
uint32_t uint32_t * format
#define FML_LOG(severity)
#define FML_UNREACHABLE()
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...
@ kKHRSamplerYcbcrConversion
@ kKHRDedicatedAllocation
@ kANDROIDExternalMemoryAndroidHardwareBuffer
PixelFormat
The Pixel formats supported by Impeller. The naming convention denotes the usage of the component,...
static std::optional< std::set< std::string > > GetSupportedDeviceExtensions(const vk::PhysicalDevice &physical_device)
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.
@ kKHRExternalSemaphoreFd
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...
@ kEXTImageCompressionControl
@ kVKKHRPortabilitySubset
@ kEXTPipelineCreationFeedback
static bool HasRequiredQueues(const vk::PhysicalDevice &physical_device)
A non-exhaustive set of driver specific workarounds.
bool slow_primitive_restart_performance
bool input_attachment_self_dependency_broken