18 bool fatal_missing_validations) {
19 auto extensions = vk::enumerateInstanceExtensionProperties();
20 auto layers = vk::enumerateInstanceLayerProperties();
22 if (extensions.result != vk::Result::eSuccess ||
23 layers.result != vk::Result::eSuccess) {
27 for (
const auto& ext : extensions.value) {
31 for (
const auto& layer : layers.value) {
32 const std::string layer_name = layer.layerName;
33 auto layer_exts = vk::enumerateInstanceExtensionProperties(layer_name);
34 if (layer_exts.result != vk::Result::eSuccess) {
37 for (
const auto& layer_ext : layer_exts.value) {
38 exts_[layer_name].insert(layer_ext.extensionName);
42 validations_enabled_ =
43 enable_validations && HasLayer(
"VK_LAYER_KHRONOS_validation");
44 if (enable_validations && !validations_enabled_) {
46 <<
"Requested Impeller context creation with validations but the "
47 "validation layers could not be found. Expect no Vulkan validation "
49 if (fatal_missing_validations) {
53 if (validations_enabled_) {
54 FML_LOG(INFO) <<
"Vulkan validations are enabled.";
66 return validations_enabled_;
71 std::vector<std::string> required;
73 if (validations_enabled_) {
75 required.push_back(
"VK_LAYER_KHRONOS_validation");
81std::optional<std::vector<std::string>>
83 std::vector<std::string> required;
91 required.push_back(
"VK_KHR_surface");
95 required.push_back(
"VK_MVK_macos_surface");
100 required.push_back(
"VK_EXT_metal_surface");
105 required.push_back(
"VK_KHR_portability_enumeration");
110 required.push_back(
"VK_KHR_win32_surface");
115 required.push_back(
"VK_KHR_android_surface");
120 required.push_back(
"VK_KHR_xcb_surface");
125 required.push_back(
"VK_KHR_xlib_surface");
130 required.push_back(
"VK_KHR_wayland_surface");
141 if (validations_enabled_) {
144 "VK_EXT_debug_utils extension.";
147 required.push_back(
"VK_EXT_debug_utils");
152 required.push_back(
"VK_EXT_validation_features");
173 return "VK_ANDROID_external_memory_android_hardware_buffer";
193 return "VK_KHR_portability_subset";
205 for (
size_t i = 0; i < static_cast<uint32_t>(T::kLast); i++) {
206 if (!it(
static_cast<T>(i))) {
215 auto device_extensions =
physical_device.enumerateDeviceExtensionProperties();
216 if (device_extensions.result != vk::Result::eSuccess) {
220 std::set<std::string> exts;
221 for (
const auto& device_extension : device_extensions.value) {
222 exts.insert(device_extension.extensionName);
228std::optional<std::vector<std::string>>
233 if (!exts.has_value()) {
237 std::vector<std::string> enabled;
241 if (exts->find(
name) == exts->end()) {
245 enabled.push_back(
name);
252 if (exts->find(
name) == exts->end()) {
253 VALIDATION_LOG <<
"Device does not support required Android extension: "
257 enabled.push_back(
name);
264 if (exts->find(
name) != exts->end()) {
265 enabled.push_back(
name);
270 const auto iterate_extensions =
271 IterateExtensions<RequiredCommonDeviceExtensionVK>(
272 for_each_common_extension) &&
273 IterateExtensions<RequiredAndroidDeviceExtensionVK>(
274 for_each_android_extension) &&
275 IterateExtensions<OptionalDeviceExtensionVK>(for_each_optional_extension);
277 if (!iterate_extensions) {
278 VALIDATION_LOG <<
"Device not suitable since required extensions are not "
290 return !!(props.optimalTilingFeatures &
291 vk::FormatFeatureFlagBits::eColorAttachment);
297 return !!(props.optimalTilingFeatures &
298 vk::FormatFeatureFlagBits::eDepthStencilAttachment);
302 const vk::PhysicalDevice&
device) {
303 const auto has_color_format =
305 const auto has_stencil_format =
308 return has_color_format && has_stencil_format;
313 if (!(properties.limits.framebufferColorSampleCounts &
314 (vk::SampleCountFlagBits::e1 | vk::SampleCountFlagBits::e4))) {
321 auto queue_flags = vk::QueueFlags{};
323 if (
queue.queueCount == 0) {
326 queue_flags |=
queue.queueFlags;
329 (vk::QueueFlagBits::eGraphics |
330 vk::QueueFlagBits::eCompute |
331 vk::QueueFlagBits::eTransfer));
334template <
class ExtensionEnum>
338 return std::find(list.begin(), list.end(),
name) != list.end();
341std::optional<CapabilitiesVK::PhysicalDeviceFeatures>
343 const vk::PhysicalDevice&
device)
const {
350 VALIDATION_LOG <<
"Device doesn't support the required properties.";
360 if (!enabled_extensions.has_value()) {
366 device.getFeatures2(&supported_chain.get());
372 auto& required = required_chain.get().features;
373 const auto& supported = supported_chain.get().features;
377 required.fillModeNonSolid = supported.fillModeNonSolid;
381 enabled_extensions.value(),
385 .get<vk::PhysicalDeviceSamplerYcbcrConversionFeaturesKHR>();
386 const auto& supported =
388 .get<vk::PhysicalDeviceSamplerYcbcrConversionFeaturesKHR>();
390 required.samplerYcbcrConversion = supported.samplerYcbcrConversion;
396 required_chain.get<vk::PhysicalDevice16BitStorageFeatures>();
397 const auto& supported =
398 supported_chain.get<vk::PhysicalDevice16BitStorageFeatures>();
400 required.uniformAndStorageBuffer16BitAccess =
401 supported.uniformAndStorageBuffer16BitAccess;
404 return required_chain;
407bool CapabilitiesVK::HasLayer(
const std::string& layer)
const {
408 for (
const auto& [found_layer, exts] : exts_) {
409 if (found_layer == layer) {
417 for (
const auto& [layer, exts] : exts_) {
418 if (exts.find(ext) != exts.end()) {
426 default_color_format_ = pixel_format;
439 vk::Format::eD24UnormS8Uint)) {
448 default_stencil_format_ = default_depth_stencil_format_;
451 device_properties_ =
device.getProperties();
453 auto physical_properties_2 =
454 device.getProperties2<vk::PhysicalDeviceProperties2,
455 vk::PhysicalDeviceSubgroupProperties>();
461 supports_compute_subgroups_ =
462 !!(physical_properties_2.get<vk::PhysicalDeviceSubgroupProperties>()
463 .supportedOperations &
464 vk::SubgroupFeatureFlagBits::eArithmetic);
470 vk::PhysicalDeviceMemoryProperties memory_properties;
471 device.getMemoryProperties(&memory_properties);
473 for (
auto i = 0u; i < memory_properties.memoryTypeCount; i++) {
474 if (memory_properties.memoryTypes[i].propertyFlags &
475 vk::MemoryPropertyFlagBits::eLazilyAllocated) {
476 supports_device_transient_textures_ =
true;
483 required_common_device_extensions_.clear();
484 required_android_device_extensions_.clear();
485 optional_device_extensions_.clear();
487 if (!exts.has_value()) {
490 IterateExtensions<RequiredCommonDeviceExtensionVK>([&](
auto ext) ->
bool {
492 if (exts->find(ext_name) != exts->end()) {
493 required_common_device_extensions_.insert(ext);
497 IterateExtensions<RequiredAndroidDeviceExtensionVK>([&](
auto ext) ->
bool {
499 if (exts->find(ext_name) != exts->end()) {
500 required_android_device_extensions_.insert(ext);
504 IterateExtensions<OptionalDeviceExtensionVK>([&](
auto ext) ->
bool {
506 if (exts->find(ext_name) != exts->end()) {
507 optional_device_extensions_.insert(ext);
555 return supports_compute_subgroups_;
569 return supports_device_transient_textures_;
574 return default_color_format_;
579 return default_stencil_format_;
584 return default_depth_stencil_format_;
587const vk::PhysicalDeviceProperties&
589 return device_properties_;
597 return required_common_device_extensions_.find(ext) !=
598 required_common_device_extensions_.end();
602 return required_android_device_extensions_.find(ext) !=
603 required_android_device_extensions_.end();
607 return optional_device_extensions_.find(ext) !=
608 optional_device_extensions_.end();
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 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 ...
CapabilitiesVK(bool enable_validations, bool fatal_missing_validations=false)
vk::StructureChain< vk::PhysicalDeviceFeatures2, vk::PhysicalDeviceSamplerYcbcrConversionFeaturesKHR, vk::PhysicalDevice16BitStorageFeatures > PhysicalDeviceFeatures
bool SupportsBufferToTextureBlits() const override
Whether the context backend supports blitting from a given DeviceBuffer view to a texture region (via...
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
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...
bool SetPhysicalDevice(const vk::PhysicalDevice &physical_device)
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.
std::optional< std::vector< std::string > > GetEnabledLayers() 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 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
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,...
static constexpr const char * kInstanceLayer
OptionalDeviceExtensionVK
A device extension enabled if available. Subsystems cannot assume availability and must check if thes...
@ kVKKHRPortabilitySubset
@ kEXTPipelineCreationFeedback
static bool HasRequiredQueues(const vk::PhysicalDevice &physical_device)
#define VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME
#define VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME
#define VK_EXT_PIPELINE_CREATION_FEEDBACK_EXTENSION_NAME
#define VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME
#define VK_KHR_SWAPCHAIN_EXTENSION_NAME
#define VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME