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;
458 required.samplerAnisotropy = supported.samplerAnisotropy;
462 enabled_extensions.value(),
466 .get<vk::PhysicalDeviceSamplerYcbcrConversionFeaturesKHR>();
467 const auto& supported =
469 .get<vk::PhysicalDeviceSamplerYcbcrConversionFeaturesKHR>();
471 required.samplerYcbcrConversion = supported.samplerYcbcrConversion;
476 enabled_extensions.value(),
480 .get<vk::PhysicalDeviceImageCompressionControlFeaturesEXT>();
481 const auto& supported =
483 .get<vk::PhysicalDeviceImageCompressionControlFeaturesEXT>();
485 required.imageCompressionControl = supported.imageCompressionControl;
488 .unlink<vk::PhysicalDeviceImageCompressionControlFeaturesEXT>();
493 enabled_extensions.value(),
497 .get<vk::PhysicalDeviceTextureCompressionASTCHDRFeatures>();
498 const auto& supported =
500 .get<vk::PhysicalDeviceTextureCompressionASTCHDRFeatures>();
502 required.textureCompressionASTC_HDR = supported.textureCompressionASTC_HDR;
505 .unlink<vk::PhysicalDeviceTextureCompressionASTCHDRFeatures>();
511 required_chain.get<vk::PhysicalDevice16BitStorageFeatures>();
512 const auto& supported =
513 supported_chain.get<vk::PhysicalDevice16BitStorageFeatures>();
515 required.uniformAndStorageBuffer16BitAccess =
516 supported.uniformAndStorageBuffer16BitAccess;
519 return required_chain;
522bool CapabilitiesVK::HasLayer(
const std::string& layer)
const {
523 for (
const auto& [found_layer, exts] : exts_) {
524 if (found_layer == layer) {
532 for (
const auto& [layer, exts] : exts_) {
533 if (exts.find(ext) != exts.end()) {
541 return has_primitive_restart_;
553 default_color_format_ = pixel_format;
557 const vk::PhysicalDevice&
device,
568 vk::Format::eD32SfloatS8Uint)) {
577 default_stencil_format_ = default_depth_stencil_format_;
580 physical_device_ =
device;
581 device_properties_ =
device.getProperties();
583 auto physical_properties_2 =
584 device.getProperties2<vk::PhysicalDeviceProperties2,
585 vk::PhysicalDeviceSubgroupProperties>();
591 supports_compute_subgroups_ =
592 !!(physical_properties_2.get<vk::PhysicalDeviceSubgroupProperties>()
593 .supportedOperations &
594 vk::SubgroupFeatureFlagBits::eArithmetic);
599 vk::PhysicalDeviceMemoryProperties memory_properties;
600 device.getMemoryProperties(&memory_properties);
602 for (
auto i = 0u;
i < memory_properties.memoryTypeCount;
i++) {
603 if (memory_properties.memoryTypes[
i].propertyFlags &
604 vk::MemoryPropertyFlagBits::eLazilyAllocated) {
605 supports_device_transient_textures_ =
true;
612 required_common_device_extensions_.clear();
613 required_android_device_extensions_.clear();
614 optional_device_extensions_.clear();
615 optional_android_device_extensions_.clear();
617 std::set<std::string> exts;
618 if (!use_embedder_extensions_) {
620 if (!maybe_exts.has_value()) {
623 exts = maybe_exts.value();
625 for (
const auto& ext : embedder_device_extensions_) {
630 IterateExtensions<RequiredCommonDeviceExtensionVK>([&](
auto ext) ->
bool {
632 if (exts.find(ext_name) != exts.end()) {
633 required_common_device_extensions_.insert(ext);
637 IterateExtensions<RequiredAndroidDeviceExtensionVK>([&](
auto ext) ->
bool {
639 if (exts.find(ext_name) != exts.end()) {
640 required_android_device_extensions_.insert(ext);
644 IterateExtensions<OptionalDeviceExtensionVK>([&](
auto ext) ->
bool {
646 if (exts.find(ext_name) != exts.end()) {
647 optional_device_extensions_.insert(ext);
651 IterateExtensions<OptionalAndroidDeviceExtensionVK>(
654 if (exts.find(
name) != exts.end()) {
655 optional_android_device_extensions_.insert(ext);
661 supports_texture_fixed_rate_compression_ =
663 .isLinked<vk::PhysicalDeviceImageCompressionControlFeaturesEXT>() &&
665 .get<vk::PhysicalDeviceImageCompressionControlFeaturesEXT>()
666 .imageCompressionControl;
669 const auto& features = enabled_features.get().features;
670 supports_texture_compression_bc_ = features.textureCompressionBC;
671 supports_texture_compression_etc2_ = features.textureCompressionETC2;
672 supports_texture_compression_astc_ = features.textureCompressionASTC_LDR;
675 supports_texture_compression_astc_hdr_ =
677 .isLinked<vk::PhysicalDeviceTextureCompressionASTCHDRFeatures>() &&
679 .get<vk::PhysicalDeviceTextureCompressionASTCHDRFeatures>()
680 .textureCompressionASTC_HDR;
682 max_render_pass_attachment_size_ =
683 ISize{device_properties_.limits.maxFramebufferWidth,
684 device_properties_.limits.maxFramebufferHeight};
689 max_sampler_anisotropy_ =
690 enabled_features.get().features.samplerAnisotropy
691 ?
static_cast<uint32_t
>(
692 device_properties_.limits.maxSamplerAnisotropy)
706 supports_external_fence_and_semaphore_ =
true;
709 minimum_uniform_alignment_ =
710 device_properties_.limits.minUniformBufferOffsetAlignment;
711 minimum_storage_alignment_ =
712 device_properties_.limits.minStorageBufferOffsetAlignment;
739 return has_framebuffer_fetch_;
751 return supports_compute_subgroups_;
765 return supports_device_transient_textures_;
770 return default_color_format_;
775 return default_stencil_format_;
780 return default_depth_stencil_format_;
783const vk::PhysicalDeviceProperties&
785 return device_properties_;
793 return minimum_uniform_alignment_;
797 return minimum_storage_alignment_;
805 return required_common_device_extensions_.find(ext) !=
806 required_common_device_extensions_.end();
810 return required_android_device_extensions_.find(ext) !=
811 required_android_device_extensions_.end();
815 return optional_device_extensions_.find(ext) !=
816 optional_device_extensions_.end();
820 return optional_android_device_extensions_.find(ext) !=
821 optional_android_device_extensions_.end();
825 return supports_texture_fixed_rate_compression_;
828std::optional<vk::ImageCompressionFixedRateFlagBitsEXT>
834 if (!supports_texture_fixed_rate_compression_) {
839 vk::StructureChain<vk::PhysicalDeviceImageFormatInfo2,
840 vk::ImageCompressionControlEXT>
843 auto& format_info = format_chain.get();
845 format_info.format = desc.
format;
846 format_info.type = desc.
type;
847 format_info.tiling = desc.
tiling;
848 format_info.usage = desc.
usage;
849 format_info.flags = desc.
flags;
851 const auto kIdealFRCRate = vk::ImageCompressionFixedRateFlagBitsEXT::e4Bpc;
853 std::array<vk::ImageCompressionFixedRateFlagsEXT, 1u> rates = {kIdealFRCRate};
855 auto& compression = format_chain.get<vk::ImageCompressionControlEXT>();
856 compression.flags = vk::ImageCompressionFlagBitsEXT::eFixedRateExplicit;
857 compression.compressionControlPlaneCount = rates.size();
858 compression.pFixedRateFlags = rates.data();
860 const auto [result, supported] = physical_device_.getImageFormatProperties2<
861 vk::ImageFormatProperties2, vk::ImageCompressionPropertiesEXT>(
864 if (result != vk::Result::eSuccess ||
865 !supported.isLinked<vk::ImageCompressionPropertiesEXT>()) {
869 const auto& compression_props =
870 supported.get<vk::ImageCompressionPropertiesEXT>();
872 if ((compression_props.imageCompressionFlags &
873 vk::ImageCompressionFlagBitsEXT::eFixedRateExplicit) &&
874 (compression_props.imageCompressionFixedRateFlags & kIdealFRCRate)) {
875 return kIdealFRCRate;
882 return has_triangle_fans_;
886 return max_render_pass_attachment_size_;
890 return max_sampler_anisotropy_;
899 return supports_external_fence_and_semaphore_;
914 return supports_texture_compression_bc_;
916 return supports_texture_compression_etc2_;
918 return supports_texture_compression_astc_;
920 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.
uint32_t GetMaxSamplerAnisotropy() const override
The maximum anisotropy clamp supported by device samplers.
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