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();
31 if (extensions.result != vk::Result::eSuccess ||
32 layers.result != vk::Result::eSuccess) {
36 for (
const auto& ext : extensions.value) {
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) {
46 for (
const auto& layer_ext : layer_exts.value) {
47 exts_[layer_name].insert(layer_ext.extensionName);
51 for (
const auto& ext : embedder_instance_extensions_) {
56 validations_enabled_ =
57 enable_validations && HasLayer(
"VK_LAYER_KHRONOS_validation");
58 if (enable_validations && !validations_enabled_) {
60 <<
"Requested Impeller context creation with validations but the "
61 "validation layers could not be found. Expect no Vulkan validation "
63 if (fatal_missing_validations) {
64 FML_LOG(FATAL) <<
"Validation missing. Exiting.";
67 if (validations_enabled_) {
68 FML_LOG(INFO) <<
"Vulkan validations are enabled.";
80 return validations_enabled_;
85 std::vector<std::string> required;
87 if (validations_enabled_) {
89 required.push_back(
"VK_LAYER_KHRONOS_validation");
95 std::optional<std::vector<std::string>>
97 std::vector<std::string> required;
105 required.push_back(
"VK_KHR_surface");
107 auto has_wsi =
false;
109 required.push_back(
"VK_MVK_macos_surface");
114 required.push_back(
"VK_EXT_metal_surface");
119 required.push_back(
"VK_KHR_portability_enumeration");
124 required.push_back(
"VK_KHR_win32_surface");
129 required.push_back(
"VK_KHR_android_surface");
134 required.push_back(
"VK_KHR_xcb_surface");
139 required.push_back(
"VK_KHR_xlib_surface");
144 required.push_back(
"VK_KHR_wayland_surface");
155 if (validations_enabled_) {
158 "VK_EXT_debug_utils extension.";
161 required.push_back(
"VK_EXT_debug_utils");
166 required.push_back(
"VK_EXT_validation_features");
176 return VK_KHR_SWAPCHAIN_EXTENSION_NAME;
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;
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;
220 return VK_EXT_PIPELINE_CREATION_FEEDBACK_EXTENSION_NAME;
222 return "VK_KHR_portability_subset";
224 return VK_EXT_IMAGE_COMPRESSION_CONTROL_EXTENSION_NAME;
236 for (
size_t i = 0; i < static_cast<uint32_t>(T::kLast); i++) {
237 if (!it(
static_cast<T
>(i))) {
245 const vk::PhysicalDevice& physical_device) {
246 auto device_extensions = physical_device.enumerateDeviceExtensionProperties();
247 if (device_extensions.result != vk::Result::eSuccess) {
251 std::set<std::string> exts;
252 for (
const auto& device_extension : device_extensions.value) {
253 exts.insert(device_extension.extensionName);
259 std::optional<std::vector<std::string>>
261 const vk::PhysicalDevice& physical_device)
const {
262 std::set<std::string> exts;
264 if (!use_embedder_extensions_) {
267 if (!maybe_exts.has_value()) {
270 exts = maybe_exts.value();
272 for (
const auto& ext : embedder_device_extensions_) {
277 std::vector<std::string> enabled;
281 if (exts.find(name) == exts.end()) {
282 VALIDATION_LOG <<
"Device does not support required extension: " << name;
285 enabled.push_back(name);
290 #ifdef FML_OS_ANDROID
292 if (exts.find(name) == exts.end()) {
293 VALIDATION_LOG <<
"Device does not support required Android extension: "
297 enabled.push_back(name);
302 auto for_each_optional_android_extension =
304 #ifdef FML_OS_ANDROID
306 if (exts.find(name) != exts.end()) {
307 enabled.push_back(name);
315 if (exts.find(name) != exts.end()) {
316 enabled.push_back(name);
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);
331 if (!iterate_extensions) {
332 VALIDATION_LOG <<
"Device not suitable since required extensions are not "
342 const auto props = device.getFormatProperties(format);
344 return !!(props.optimalTilingFeatures &
345 vk::FormatFeatureFlagBits::eColorAttachment);
350 const auto props = device.getFormatProperties(format);
351 return !!(props.optimalTilingFeatures &
352 vk::FormatFeatureFlagBits::eDepthStencilAttachment);
356 const vk::PhysicalDevice& device) {
357 const auto has_color_format =
359 const auto has_stencil_format =
362 return has_color_format && has_stencil_format;
366 auto properties = physical_device.getProperties();
367 if (!(properties.limits.framebufferColorSampleCounts &
375 auto queue_flags = vk::QueueFlags{};
376 for (
const auto& queue : physical_device.getQueueFamilyProperties()) {
377 if (queue.queueCount == 0) {
380 queue_flags |= queue.queueFlags;
382 return static_cast<VkQueueFlags
>(queue_flags &
383 (vk::QueueFlagBits::eGraphics |
384 vk::QueueFlagBits::eCompute |
385 vk::QueueFlagBits::eTransfer));
388 template <
class ExtensionEnum>
392 return std::find(list.begin(), list.end(), name) != list.end();
395 std::optional<CapabilitiesVK::PhysicalDeviceFeatures>
397 const vk::PhysicalDevice& device)
const {
404 VALIDATION_LOG <<
"Device doesn't support the required properties.";
414 if (!enabled_extensions.has_value()) {
425 enabled_extensions.value(),
428 .unlink<vk::PhysicalDeviceImageCompressionControlFeaturesEXT>();
431 device.getFeatures2(&supported_chain.get());
437 auto& required = required_chain.get().features;
438 const auto& supported = supported_chain.get().features;
442 required.fillModeNonSolid = supported.fillModeNonSolid;
446 enabled_extensions.value(),
450 .get<vk::PhysicalDeviceSamplerYcbcrConversionFeaturesKHR>();
451 const auto& supported =
453 .get<vk::PhysicalDeviceSamplerYcbcrConversionFeaturesKHR>();
455 required.samplerYcbcrConversion = supported.samplerYcbcrConversion;
460 enabled_extensions.value(),
464 .get<vk::PhysicalDeviceImageCompressionControlFeaturesEXT>();
465 const auto& supported =
467 .get<vk::PhysicalDeviceImageCompressionControlFeaturesEXT>();
469 required.imageCompressionControl = supported.imageCompressionControl;
472 .unlink<vk::PhysicalDeviceImageCompressionControlFeaturesEXT>();
478 required_chain.get<vk::PhysicalDevice16BitStorageFeatures>();
479 const auto& supported =
480 supported_chain.get<vk::PhysicalDevice16BitStorageFeatures>();
482 required.uniformAndStorageBuffer16BitAccess =
483 supported.uniformAndStorageBuffer16BitAccess;
486 return required_chain;
489 bool CapabilitiesVK::HasLayer(
const std::string& layer)
const {
490 for (
const auto& [found_layer, exts] : exts_) {
491 if (found_layer == layer) {
499 for (
const auto& [layer, exts] : exts_) {
500 if (exts.find(ext) != exts.end()) {
508 return has_primitive_restart_;
512 default_color_format_ = pixel_format;
516 const vk::PhysicalDevice& device,
527 vk::Format::eD32SfloatS8Uint)) {
536 default_stencil_format_ = default_depth_stencil_format_;
539 physical_device_ = device;
540 device_properties_ = device.getProperties();
542 auto physical_properties_2 =
543 device.getProperties2<vk::PhysicalDeviceProperties2,
544 vk::PhysicalDeviceSubgroupProperties>();
550 supports_compute_subgroups_ =
551 !!(physical_properties_2.get<vk::PhysicalDeviceSubgroupProperties>()
552 .supportedOperations &
553 vk::SubgroupFeatureFlagBits::eArithmetic);
558 vk::PhysicalDeviceMemoryProperties memory_properties;
559 device.getMemoryProperties(&memory_properties);
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;
571 required_common_device_extensions_.clear();
572 required_android_device_extensions_.clear();
573 optional_device_extensions_.clear();
574 optional_android_device_extensions_.clear();
576 std::set<std::string> exts;
577 if (!use_embedder_extensions_) {
579 if (!maybe_exts.has_value()) {
582 exts = maybe_exts.value();
584 for (
const auto& ext : embedder_device_extensions_) {
589 IterateExtensions<RequiredCommonDeviceExtensionVK>([&](
auto ext) ->
bool {
591 if (exts.find(ext_name) != exts.end()) {
592 required_common_device_extensions_.insert(ext);
596 IterateExtensions<RequiredAndroidDeviceExtensionVK>([&](
auto ext) ->
bool {
598 if (exts.find(ext_name) != exts.end()) {
599 required_android_device_extensions_.insert(ext);
603 IterateExtensions<OptionalDeviceExtensionVK>([&](
auto ext) ->
bool {
605 if (exts.find(ext_name) != exts.end()) {
606 optional_device_extensions_.insert(ext);
610 IterateExtensions<OptionalAndroidDeviceExtensionVK>(
613 if (exts.find(name) != exts.end()) {
614 optional_android_device_extensions_.insert(ext);
620 supports_texture_fixed_rate_compression_ =
622 .isLinked<vk::PhysicalDeviceImageCompressionControlFeaturesEXT>() &&
624 .get<vk::PhysicalDeviceImageCompressionControlFeaturesEXT>()
625 .imageCompressionControl;
627 max_render_pass_attachment_size_ =
628 ISize{device_properties_.limits.maxFramebufferWidth,
629 device_properties_.limits.maxFramebufferHeight};
642 supports_external_fence_and_semaphore_ =
true;
645 minimum_uniform_alignment_ =
646 device_properties_.limits.minUniformBufferOffsetAlignment;
673 return has_framebuffer_fetch_;
685 return supports_compute_subgroups_;
699 return supports_device_transient_textures_;
704 return default_color_format_;
709 return default_stencil_format_;
714 return default_depth_stencil_format_;
717 const vk::PhysicalDeviceProperties&
719 return device_properties_;
727 return minimum_uniform_alignment_;
731 return required_common_device_extensions_.find(ext) !=
732 required_common_device_extensions_.end();
736 return required_android_device_extensions_.find(ext) !=
737 required_android_device_extensions_.end();
741 return optional_device_extensions_.find(ext) !=
742 optional_device_extensions_.end();
746 return optional_android_device_extensions_.find(ext) !=
747 optional_android_device_extensions_.end();
751 return supports_texture_fixed_rate_compression_;
754 std::optional<vk::ImageCompressionFixedRateFlagBitsEXT>
760 if (!supports_texture_fixed_rate_compression_) {
765 vk::StructureChain<vk::PhysicalDeviceImageFormatInfo2,
766 vk::ImageCompressionControlEXT>
769 auto& format_info = format_chain.get();
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;
777 const auto kIdealFRCRate = vk::ImageCompressionFixedRateFlagBitsEXT::e4Bpc;
779 std::array<vk::ImageCompressionFixedRateFlagsEXT, 1u> rates = {kIdealFRCRate};
781 auto& compression = format_chain.get<vk::ImageCompressionControlEXT>();
782 compression.flags = vk::ImageCompressionFlagBitsEXT::eFixedRateExplicit;
783 compression.compressionControlPlaneCount = rates.size();
784 compression.pFixedRateFlags = rates.data();
786 const auto [result, supported] = physical_device_.getImageFormatProperties2<
787 vk::ImageFormatProperties2, vk::ImageCompressionPropertiesEXT>(
790 if (result != vk::Result::eSuccess ||
791 !supported.isLinked<vk::ImageCompressionPropertiesEXT>()) {
795 const auto& compression_props =
796 supported.get<vk::ImageCompressionPropertiesEXT>();
798 if ((compression_props.imageCompressionFlags &
799 vk::ImageCompressionFlagBitsEXT::eFixedRateExplicit) &&
800 (compression_props.imageCompressionFixedRateFlags & kIdealFRCRate)) {
801 return kIdealFRCRate;
808 return has_triangle_fans_;
812 return max_render_pass_attachment_size_;
821 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.
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
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...
@ kKHRSamplerYcbcrConversion
@ kKHRDedicatedAllocation
@ kANDROIDExternalMemoryAndroidHardwareBuffer
PixelFormat
The Pixel formats supported by Impeller. The naming convention denotes the usage of the component,...
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 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...
@ 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