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) {
50 FML_LOG(FATAL) <<
"Validation missing. Exiting.";
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");
81 std::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");
162 return VK_KHR_SWAPCHAIN_EXTENSION_NAME;
173 return "VK_ANDROID_external_memory_android_hardware_buffer";
175 return VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME;
177 return VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME;
179 return VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME;
181 return VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME;
183 return VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME;
185 return VK_KHR_EXTERNAL_FENCE_EXTENSION_NAME;
187 return VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME;
189 return VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME;
199 return VK_EXT_PIPELINE_CREATION_FEEDBACK_EXTENSION_NAME;
201 return "VK_KHR_portability_subset";
213 for (
size_t i = 0; i < static_cast<uint32_t>(T::kLast); i++) {
214 if (!it(
static_cast<T
>(i))) {
222 const vk::PhysicalDevice& physical_device) {
223 auto device_extensions = physical_device.enumerateDeviceExtensionProperties();
224 if (device_extensions.result != vk::Result::eSuccess) {
228 std::set<std::string> exts;
229 for (
const auto& device_extension : device_extensions.value) {
230 exts.insert(device_extension.extensionName);
236 std::optional<std::vector<std::string>>
238 const vk::PhysicalDevice& physical_device)
const {
241 if (!exts.has_value()) {
245 std::vector<std::string> enabled;
249 if (exts->find(name) == exts->end()) {
250 VALIDATION_LOG <<
"Device does not support required extension: " << name;
253 enabled.push_back(name);
258 #ifdef FML_OS_ANDROID
260 if (exts->find(name) == exts->end()) {
261 VALIDATION_LOG <<
"Device does not support required Android extension: "
265 enabled.push_back(name);
266 #endif // FML_OS_ANDROID
272 if (exts->find(name) != exts->end()) {
273 enabled.push_back(name);
278 const auto iterate_extensions =
279 IterateExtensions<RequiredCommonDeviceExtensionVK>(
280 for_each_common_extension) &&
281 IterateExtensions<RequiredAndroidDeviceExtensionVK>(
282 for_each_android_extension) &&
283 IterateExtensions<OptionalDeviceExtensionVK>(for_each_optional_extension);
285 if (!iterate_extensions) {
286 VALIDATION_LOG <<
"Device not suitable since required extensions are not "
296 const auto props = device.getFormatProperties(format);
298 return !!(props.optimalTilingFeatures &
299 vk::FormatFeatureFlagBits::eColorAttachment);
304 const auto props = device.getFormatProperties(format);
305 return !!(props.optimalTilingFeatures &
306 vk::FormatFeatureFlagBits::eDepthStencilAttachment);
310 const vk::PhysicalDevice& device) {
311 const auto has_color_format =
313 const auto has_stencil_format =
316 return has_color_format && has_stencil_format;
320 auto properties = physical_device.getProperties();
321 if (!(properties.limits.framebufferColorSampleCounts &
322 (vk::SampleCountFlagBits::e1 | vk::SampleCountFlagBits::e4))) {
329 auto queue_flags = vk::QueueFlags{};
330 for (
const auto& queue : physical_device.getQueueFamilyProperties()) {
331 if (queue.queueCount == 0) {
334 queue_flags |= queue.queueFlags;
336 return static_cast<VkQueueFlags
>(queue_flags &
337 (vk::QueueFlagBits::eGraphics |
338 vk::QueueFlagBits::eCompute |
339 vk::QueueFlagBits::eTransfer));
342 template <
class ExtensionEnum>
346 return std::find(list.begin(), list.end(), name) != list.end();
349 std::optional<CapabilitiesVK::PhysicalDeviceFeatures>
351 const vk::PhysicalDevice& device)
const {
358 VALIDATION_LOG <<
"Device doesn't support the required properties.";
368 if (!enabled_extensions.has_value()) {
374 device.getFeatures2(&supported_chain.get());
380 auto& required = required_chain.get().features;
381 const auto& supported = supported_chain.get().features;
385 required.fillModeNonSolid = supported.fillModeNonSolid;
389 enabled_extensions.value(),
393 .get<vk::PhysicalDeviceSamplerYcbcrConversionFeaturesKHR>();
394 const auto& supported =
396 .get<vk::PhysicalDeviceSamplerYcbcrConversionFeaturesKHR>();
398 required.samplerYcbcrConversion = supported.samplerYcbcrConversion;
404 required_chain.get<vk::PhysicalDevice16BitStorageFeatures>();
405 const auto& supported =
406 supported_chain.get<vk::PhysicalDevice16BitStorageFeatures>();
408 required.uniformAndStorageBuffer16BitAccess =
409 supported.uniformAndStorageBuffer16BitAccess;
412 return required_chain;
415 bool CapabilitiesVK::HasLayer(
const std::string& layer)
const {
416 for (
const auto& [found_layer, exts] : exts_) {
417 if (found_layer == layer) {
425 for (
const auto& [layer, exts] : exts_) {
426 if (exts.find(ext) != exts.end()) {
434 default_color_format_ = pixel_format;
447 vk::Format::eD24UnormS8Uint)) {
456 default_stencil_format_ = default_depth_stencil_format_;
459 device_properties_ = device.getProperties();
461 auto physical_properties_2 =
462 device.getProperties2<vk::PhysicalDeviceProperties2,
463 vk::PhysicalDeviceSubgroupProperties>();
469 supports_compute_subgroups_ =
470 !!(physical_properties_2.get<vk::PhysicalDeviceSubgroupProperties>()
471 .supportedOperations &
472 vk::SubgroupFeatureFlagBits::eArithmetic);
478 vk::PhysicalDeviceMemoryProperties memory_properties;
479 device.getMemoryProperties(&memory_properties);
481 for (
auto i = 0u; i < memory_properties.memoryTypeCount; i++) {
482 if (memory_properties.memoryTypes[i].propertyFlags &
483 vk::MemoryPropertyFlagBits::eLazilyAllocated) {
484 supports_device_transient_textures_ =
true;
491 required_common_device_extensions_.clear();
492 required_android_device_extensions_.clear();
493 optional_device_extensions_.clear();
495 if (!exts.has_value()) {
498 IterateExtensions<RequiredCommonDeviceExtensionVK>([&](
auto ext) ->
bool {
500 if (exts->find(ext_name) != exts->end()) {
501 required_common_device_extensions_.insert(ext);
505 IterateExtensions<RequiredAndroidDeviceExtensionVK>([&](
auto ext) ->
bool {
507 if (exts->find(ext_name) != exts->end()) {
508 required_android_device_extensions_.insert(ext);
512 IterateExtensions<OptionalDeviceExtensionVK>([&](
auto ext) ->
bool {
514 if (exts->find(ext_name) != exts->end()) {
515 optional_device_extensions_.insert(ext);
558 return supports_compute_subgroups_;
572 return supports_device_transient_textures_;
577 return default_color_format_;
582 return default_stencil_format_;
587 return default_depth_stencil_format_;
590 const vk::PhysicalDeviceProperties&
592 return device_properties_;
600 return required_common_device_extensions_.find(ext) !=
601 required_common_device_extensions_.end();
605 return required_android_device_extensions_.find(ext) !=
606 required_android_device_extensions_.end();
610 return optional_device_extensions_.find(ext) !=
611 optional_device_extensions_.end();