18 auto extensions = vk::enumerateInstanceExtensionProperties();
19 auto layers = vk::enumerateInstanceLayerProperties();
21 if (extensions.result != vk::Result::eSuccess ||
22 layers.result != vk::Result::eSuccess) {
26 for (
const auto& ext : extensions.value) {
30 for (
const auto& layer : layers.value) {
31 const std::string layer_name = layer.layerName;
32 auto layer_exts = vk::enumerateInstanceExtensionProperties(layer_name);
33 if (layer_exts.result != vk::Result::eSuccess) {
36 for (
const auto& layer_ext : layer_exts.value) {
37 exts_[layer_name].insert(layer_ext.extensionName);
41 validations_enabled_ =
42 enable_validations && HasLayer(
"VK_LAYER_KHRONOS_validation");
43 if (enable_validations && !validations_enabled_) {
45 <<
"Requested Impeller context creation with validations but the "
46 "validation layers could not be found. Expect no Vulkan validation "
49 if (validations_enabled_) {
50 FML_LOG(INFO) <<
"Vulkan validations are enabled.";
62 return validations_enabled_;
67 std::vector<std::string> required;
69 if (validations_enabled_) {
71 required.push_back(
"VK_LAYER_KHRONOS_validation");
77 std::optional<std::vector<std::string>>
79 std::vector<std::string> required;
87 required.push_back(
"VK_KHR_surface");
91 required.push_back(
"VK_MVK_macos_surface");
96 required.push_back(
"VK_EXT_metal_surface");
101 required.push_back(
"VK_KHR_portability_enumeration");
106 required.push_back(
"VK_KHR_win32_surface");
111 required.push_back(
"VK_KHR_android_surface");
116 required.push_back(
"VK_KHR_xcb_surface");
121 required.push_back(
"VK_KHR_xlib_surface");
126 required.push_back(
"VK_KHR_wayland_surface");
137 if (validations_enabled_) {
140 "VK_EXT_debug_utils extension.";
143 required.push_back(
"VK_EXT_debug_utils");
148 required.push_back(
"VK_EXT_validation_features");
158 return VK_KHR_SWAPCHAIN_EXTENSION_NAME;
169 return "VK_ANDROID_external_memory_android_hardware_buffer";
171 return VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME;
173 return VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME;
175 return VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME;
177 return VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME;
187 return VK_EXT_PIPELINE_CREATION_FEEDBACK_EXTENSION_NAME;
189 return "VK_KHR_portability_subset";
201 for (
size_t i = 0; i < static_cast<uint32_t>(T::kLast); i++) {
202 if (!it(
static_cast<T
>(i))) {
210 const vk::PhysicalDevice& physical_device) {
211 auto device_extensions = physical_device.enumerateDeviceExtensionProperties();
212 if (device_extensions.result != vk::Result::eSuccess) {
216 std::set<std::string> exts;
217 for (
const auto& device_extension : device_extensions.value) {
218 exts.insert(device_extension.extensionName);
224 std::optional<std::vector<std::string>>
226 const vk::PhysicalDevice& physical_device)
const {
229 if (!exts.has_value()) {
233 std::vector<std::string> enabled;
237 if (exts->find(name) == exts->end()) {
238 VALIDATION_LOG <<
"Device does not support required extension: " << name;
241 enabled.push_back(name);
246 #ifdef FML_OS_ANDROID
248 if (exts->find(name) == exts->end()) {
249 VALIDATION_LOG <<
"Device does not support required Android extension: "
253 enabled.push_back(name);
254 #endif // FML_OS_ANDROID
260 if (exts->find(name) != exts->end()) {
261 enabled.push_back(name);
266 const auto iterate_extensions =
267 IterateExtensions<RequiredCommonDeviceExtensionVK>(
268 for_each_common_extension) &&
269 IterateExtensions<RequiredAndroidDeviceExtensionVK>(
270 for_each_android_extension) &&
271 IterateExtensions<OptionalDeviceExtensionVK>(for_each_optional_extension);
273 if (!iterate_extensions) {
274 VALIDATION_LOG <<
"Device not suitable since required extensions are not "
284 const auto props = device.getFormatProperties(format);
286 return !!(props.optimalTilingFeatures &
287 vk::FormatFeatureFlagBits::eColorAttachment);
292 const auto props = device.getFormatProperties(format);
293 return !!(props.optimalTilingFeatures &
294 vk::FormatFeatureFlagBits::eDepthStencilAttachment);
298 const vk::PhysicalDevice& device) {
299 const auto has_color_format =
301 const auto has_stencil_format =
304 return has_color_format && has_stencil_format;
308 auto properties = physical_device.getProperties();
309 if (!(properties.limits.framebufferColorSampleCounts &
310 (vk::SampleCountFlagBits::e1 | vk::SampleCountFlagBits::e4))) {
317 auto queue_flags = vk::QueueFlags{};
318 for (
const auto& queue : physical_device.getQueueFamilyProperties()) {
319 if (queue.queueCount == 0) {
322 queue_flags |= queue.queueFlags;
324 return static_cast<VkQueueFlags
>(queue_flags &
325 (vk::QueueFlagBits::eGraphics |
326 vk::QueueFlagBits::eCompute |
327 vk::QueueFlagBits::eTransfer));
330 template <
class ExtensionEnum>
334 return std::find(list.begin(), list.end(), name) != list.end();
337 std::optional<CapabilitiesVK::PhysicalDeviceFeatures>
339 const vk::PhysicalDevice& device)
const {
346 VALIDATION_LOG <<
"Device doesn't support the required properties.";
356 if (!enabled_extensions.has_value()) {
362 device.getFeatures2(&supported_chain.get());
368 auto& required = required_chain.get().features;
369 const auto& supported = supported_chain.get().features;
373 required.fillModeNonSolid = supported.fillModeNonSolid;
377 enabled_extensions.value(),
381 .get<vk::PhysicalDeviceSamplerYcbcrConversionFeaturesKHR>();
382 const auto& supported =
384 .get<vk::PhysicalDeviceSamplerYcbcrConversionFeaturesKHR>();
386 required.samplerYcbcrConversion = supported.samplerYcbcrConversion;
389 return required_chain;
392 bool CapabilitiesVK::HasLayer(
const std::string& layer)
const {
393 for (
const auto& [found_layer, exts] : exts_) {
394 if (found_layer == layer) {
402 for (
const auto& [layer, exts] : exts_) {
403 if (exts.find(ext) != exts.end()) {
411 default_color_format_ = pixel_format;
418 vk::Format::eD24UnormS8Uint)) {
427 default_stencil_format_ = default_depth_stencil_format_;
430 device_properties_ = device.getProperties();
432 auto physical_properties_2 =
433 device.getProperties2<vk::PhysicalDeviceProperties2,
434 vk::PhysicalDeviceSubgroupProperties>();
440 supports_compute_subgroups_ =
441 !!(physical_properties_2.get<vk::PhysicalDeviceSubgroupProperties>()
442 .supportedOperations &
443 vk::SubgroupFeatureFlagBits::eArithmetic);
449 vk::PhysicalDeviceMemoryProperties memory_properties;
450 device.getMemoryProperties(&memory_properties);
452 for (
auto i = 0u; i < memory_properties.memoryTypeCount; i++) {
453 if (memory_properties.memoryTypes[i].propertyFlags &
454 vk::MemoryPropertyFlagBits::eLazilyAllocated) {
455 supports_device_transient_textures_ =
true;
462 required_common_device_extensions_.clear();
463 required_android_device_extensions_.clear();
464 optional_device_extensions_.clear();
466 if (!exts.has_value()) {
469 IterateExtensions<RequiredCommonDeviceExtensionVK>([&](
auto ext) ->
bool {
471 if (exts->find(ext_name) != exts->end()) {
472 required_common_device_extensions_.insert(ext);
476 IterateExtensions<RequiredAndroidDeviceExtensionVK>([&](
auto ext) ->
bool {
478 if (exts->find(ext_name) != exts->end()) {
479 required_android_device_extensions_.insert(ext);
483 IterateExtensions<OptionalDeviceExtensionVK>([&](
auto ext) ->
bool {
485 if (exts->find(ext_name) != exts->end()) {
486 optional_device_extensions_.insert(ext);
534 return supports_compute_subgroups_;
548 return supports_device_transient_textures_;
553 return default_color_format_;
558 return default_stencil_format_;
563 return default_depth_stencil_format_;
566 const vk::PhysicalDeviceProperties&
568 return device_properties_;
576 return required_common_device_extensions_.find(ext) !=
577 required_common_device_extensions_.end();
581 return required_android_device_extensions_.find(ext) !=
582 required_android_device_extensions_.end();
586 return optional_device_extensions_.find(ext) !=
587 optional_device_extensions_.end();