23 bool fatal_missing_validations,
24 bool use_embedder_extensions,
27 : use_embedder_extensions_(use_embedder_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;
229 return VK_EXT_TEXTURE_COMPRESSION_ASTC_HDR_EXTENSION_NAME;
241 for (
size_t i = 0; i < static_cast<uint32_t>(T::kLast);
i++) {
242 if (!it(
static_cast<T
>(
i))) {
256 std::set<std::string> exts;
258 exts.insert(device_extension.extensionName);
264std::optional<std::vector<std::string>>
267 std::set<std::string> exts;
269 if (!use_embedder_extensions_) {
272 if (!maybe_exts.has_value()) {
275 exts = maybe_exts.value();
277 for (
const auto& ext : embedder_device_extensions_) {
282 std::vector<std::string> enabled;
286 if (exts.find(
name) == exts.end()) {
290 enabled.push_back(
name);
297 if (exts.find(
name) == exts.end()) {
298 VALIDATION_LOG <<
"Device does not support required Android extension: "
302 enabled.push_back(
name);
307 auto for_each_optional_android_extension =
311 if (exts.find(
name) != exts.end()) {
312 enabled.push_back(
name);
320 if (exts.find(
name) != exts.end()) {
321 enabled.push_back(
name);
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);
336 if (!iterate_extensions) {
337 VALIDATION_LOG <<
"Device not suitable since required extensions are not "
349 return !!(props.optimalTilingFeatures &
350 vk::FormatFeatureFlagBits::eColorAttachment);
356 return !!(props.optimalTilingFeatures &
357 vk::FormatFeatureFlagBits::eDepthStencilAttachment);
361 const vk::PhysicalDevice&
device) {
362 const auto has_color_format =
364 const auto has_stencil_format =
367 return has_color_format && has_stencil_format;
372 if (!(properties.limits.framebufferColorSampleCounts &
373 (vk::SampleCountFlagBits::e1 | vk::SampleCountFlagBits::e4))) {
380 auto queue_flags = vk::QueueFlags{};
382 if (
queue.queueCount == 0) {
385 queue_flags |=
queue.queueFlags;
387 return static_cast<VkQueueFlags
>(queue_flags &
388 (vk::QueueFlagBits::eGraphics |
389 vk::QueueFlagBits::eCompute |
390 vk::QueueFlagBits::eTransfer));
393template <
class ExtensionEnum>
397 return std::find(list.begin(), list.end(),
name) != list.end();
400std::optional<CapabilitiesVK::PhysicalDeviceFeatures>
402 const vk::PhysicalDevice&
device)
const {
409 VALIDATION_LOG <<
"Device doesn't support the required properties.";
419 if (!enabled_extensions.has_value()) {
430 enabled_extensions.value(),
433 .unlink<vk::PhysicalDeviceImageCompressionControlFeaturesEXT>();
436 enabled_extensions.value(),
439 .unlink<vk::PhysicalDeviceTextureCompressionASTCHDRFeatures>();
442 device.getFeatures2(&supported_chain.get());
448 auto& required = required_chain.get().features;
449 const auto& supported = supported_chain.get().features;
453 required.fillModeNonSolid = supported.fillModeNonSolid;
457 enabled_extensions.value(),
461 .get<vk::PhysicalDeviceSamplerYcbcrConversionFeaturesKHR>();
462 const auto& supported =
464 .get<vk::PhysicalDeviceSamplerYcbcrConversionFeaturesKHR>();
466 required.samplerYcbcrConversion = supported.samplerYcbcrConversion;
471 enabled_extensions.value(),
475 .get<vk::PhysicalDeviceImageCompressionControlFeaturesEXT>();
476 const auto& supported =
478 .get<vk::PhysicalDeviceImageCompressionControlFeaturesEXT>();
480 required.imageCompressionControl = supported.imageCompressionControl;
483 .unlink<vk::PhysicalDeviceImageCompressionControlFeaturesEXT>();
488 enabled_extensions.value(),
492 .get<vk::PhysicalDeviceTextureCompressionASTCHDRFeatures>();
493 const auto& supported =
495 .get<vk::PhysicalDeviceTextureCompressionASTCHDRFeatures>();
497 required.textureCompressionASTC_HDR = supported.textureCompressionASTC_HDR;
500 .unlink<vk::PhysicalDeviceTextureCompressionASTCHDRFeatures>();
506 required_chain.get<vk::PhysicalDevice16BitStorageFeatures>();
507 const auto& supported =
508 supported_chain.get<vk::PhysicalDevice16BitStorageFeatures>();
510 required.uniformAndStorageBuffer16BitAccess =
511 supported.uniformAndStorageBuffer16BitAccess;
514 return required_chain;
517bool CapabilitiesVK::HasLayer(
const std::string& layer)
const {
518 for (
const auto& [found_layer, exts] : exts_) {
519 if (found_layer == layer) {
527 for (
const auto& [layer, exts] : exts_) {
528 if (exts.find(ext) != exts.end()) {
536 return has_primitive_restart_;
548 default_color_format_ = pixel_format;
552 const vk::PhysicalDevice&
device,
563 vk::Format::eD32SfloatS8Uint)) {
572 default_stencil_format_ = default_depth_stencil_format_;
575 physical_device_ =
device;
576 device_properties_ =
device.getProperties();
578 auto physical_properties_2 =
579 device.getProperties2<vk::PhysicalDeviceProperties2,
580 vk::PhysicalDeviceSubgroupProperties>();
586 supports_compute_subgroups_ =
587 !!(physical_properties_2.get<vk::PhysicalDeviceSubgroupProperties>()
588 .supportedOperations &
589 vk::SubgroupFeatureFlagBits::eArithmetic);
594 vk::PhysicalDeviceMemoryProperties memory_properties;
595 device.getMemoryProperties(&memory_properties);
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;
607 required_common_device_extensions_.clear();
608 required_android_device_extensions_.clear();
609 optional_device_extensions_.clear();
610 optional_android_device_extensions_.clear();
612 std::set<std::string> exts;
613 if (!use_embedder_extensions_) {
615 if (!maybe_exts.has_value()) {
618 exts = maybe_exts.value();
620 for (
const auto& ext : embedder_device_extensions_) {
625 IterateExtensions<RequiredCommonDeviceExtensionVK>([&](
auto ext) ->
bool {
627 if (exts.find(ext_name) != exts.end()) {
628 required_common_device_extensions_.insert(ext);
632 IterateExtensions<RequiredAndroidDeviceExtensionVK>([&](
auto ext) ->
bool {
634 if (exts.find(ext_name) != exts.end()) {
635 required_android_device_extensions_.insert(ext);
639 IterateExtensions<OptionalDeviceExtensionVK>([&](
auto ext) ->
bool {
641 if (exts.find(ext_name) != exts.end()) {
642 optional_device_extensions_.insert(ext);
646 IterateExtensions<OptionalAndroidDeviceExtensionVK>(
649 if (exts.find(
name) != exts.end()) {
650 optional_android_device_extensions_.insert(ext);
656 supports_texture_fixed_rate_compression_ =
658 .isLinked<vk::PhysicalDeviceImageCompressionControlFeaturesEXT>() &&
660 .get<vk::PhysicalDeviceImageCompressionControlFeaturesEXT>()
661 .imageCompressionControl;
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;
670 supports_texture_compression_astc_hdr_ =
672 .isLinked<vk::PhysicalDeviceTextureCompressionASTCHDRFeatures>() &&
674 .get<vk::PhysicalDeviceTextureCompressionASTCHDRFeatures>()
675 .textureCompressionASTC_HDR;
677 max_render_pass_attachment_size_ =
678 ISize{device_properties_.limits.maxFramebufferWidth,
679 device_properties_.limits.maxFramebufferHeight};
692 supports_external_fence_and_semaphore_ =
true;
695 minimum_uniform_alignment_ =
696 device_properties_.limits.minUniformBufferOffsetAlignment;
697 minimum_storage_alignment_ =
698 device_properties_.limits.minStorageBufferOffsetAlignment;
725 return has_framebuffer_fetch_;
737 return supports_compute_subgroups_;
751 return supports_device_transient_textures_;
756 return default_color_format_;
761 return default_stencil_format_;
766 return default_depth_stencil_format_;
769const vk::PhysicalDeviceProperties&
771 return device_properties_;
779 return minimum_uniform_alignment_;
783 return minimum_storage_alignment_;
791 return required_common_device_extensions_.find(ext) !=
792 required_common_device_extensions_.end();
796 return required_android_device_extensions_.find(ext) !=
797 required_android_device_extensions_.end();
801 return optional_device_extensions_.find(ext) !=
802 optional_device_extensions_.end();
806 return optional_android_device_extensions_.find(ext) !=
807 optional_android_device_extensions_.end();
811 return supports_texture_fixed_rate_compression_;
814std::optional<vk::ImageCompressionFixedRateFlagBitsEXT>
820 if (!supports_texture_fixed_rate_compression_) {
825 vk::StructureChain<vk::PhysicalDeviceImageFormatInfo2,
826 vk::ImageCompressionControlEXT>
829 auto& format_info = format_chain.get();
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;
837 const auto kIdealFRCRate = vk::ImageCompressionFixedRateFlagBitsEXT::e4Bpc;
839 std::array<vk::ImageCompressionFixedRateFlagsEXT, 1u> rates = {kIdealFRCRate};
841 auto& compression = format_chain.get<vk::ImageCompressionControlEXT>();
842 compression.flags = vk::ImageCompressionFlagBitsEXT::eFixedRateExplicit;
843 compression.compressionControlPlaneCount = rates.size();
844 compression.pFixedRateFlags = rates.data();
846 const auto [result, supported] = physical_device_.getImageFormatProperties2<
847 vk::ImageFormatProperties2, vk::ImageCompressionPropertiesEXT>(
850 if (result != vk::Result::eSuccess ||
851 !supported.isLinked<vk::ImageCompressionPropertiesEXT>()) {
855 const auto& compression_props =
856 supported.get<vk::ImageCompressionPropertiesEXT>();
858 if ((compression_props.imageCompressionFlags &
859 vk::ImageCompressionFlagBitsEXT::eFixedRateExplicit) &&
860 (compression_props.imageCompressionFixedRateFlags & kIdealFRCRate)) {
861 return kIdealFRCRate;
868 return has_triangle_fans_;
872 return max_render_pass_attachment_size_;
881 return supports_external_fence_and_semaphore_;
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_;
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 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
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
const FlutterLayer ** layers
uint32_t uint32_t * format
#define FML_LOG(severity)
#define FML_UNREACHABLE()
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...
@ 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)
CompressedTextureFamily
The family of a block-compressed pixel format. GPUs support compressed formats on a per-family basis,...
@ 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.
@ 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
@ kEXTTextureCompressionAstcHdr
@ 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