12 #include "vulkan/vulkan_core.h"
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 "
50 if (validations_enabled_) {
51 FML_LOG(INFO) <<
"Vulkan validations are enabled.";
63 return validations_enabled_;
68 std::vector<std::string> required;
70 if (validations_enabled_) {
72 required.push_back(
"VK_LAYER_KHRONOS_validation");
78 std::optional<std::vector<std::string>>
80 std::vector<std::string> required;
82 if (!HasExtension(
"VK_KHR_surface")) {
88 required.push_back(
"VK_KHR_surface");
91 if (HasExtension(
"VK_MVK_macos_surface")) {
92 required.push_back(
"VK_MVK_macos_surface");
96 if (HasExtension(
"VK_EXT_metal_surface")) {
97 required.push_back(
"VK_EXT_metal_surface");
101 if (HasExtension(
"VK_KHR_portability_enumeration")) {
102 required.push_back(
"VK_KHR_portability_enumeration");
106 if (HasExtension(
"VK_KHR_win32_surface")) {
107 required.push_back(
"VK_KHR_win32_surface");
111 if (HasExtension(
"VK_KHR_android_surface")) {
112 required.push_back(
"VK_KHR_android_surface");
116 if (HasExtension(
"VK_KHR_xcb_surface")) {
117 required.push_back(
"VK_KHR_xcb_surface");
121 if (HasExtension(
"VK_KHR_xlib_surface")) {
122 required.push_back(
"VK_KHR_xlib_surface");
126 if (HasExtension(
"VK_KHR_wayland_surface")) {
127 required.push_back(
"VK_KHR_wayland_surface");
138 if (validations_enabled_) {
139 if (!HasExtension(
"VK_EXT_debug_utils")) {
141 "VK_EXT_debug_utils extension.";
144 required.push_back(
"VK_EXT_debug_utils");
146 if (HasExtension(
"VK_EXT_validation_features")) {
149 required.push_back(
"VK_EXT_validation_features");
159 return VK_EXT_PIPELINE_CREATION_FEEDBACK_EXTENSION_NAME;
161 return VK_ARM_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_EXTENSION_NAME;
163 return VK_EXT_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_EXTENSION_NAME;
182 const vk::PhysicalDevice& physical_device) {
183 auto device_extensions = physical_device.enumerateDeviceExtensionProperties();
184 if (device_extensions.result != vk::Result::eSuccess) {
188 std::set<std::string> exts;
189 for (
const auto& device_extension : device_extensions.value) {
190 exts.insert(device_extension.extensionName);
196 std::optional<std::vector<std::string>>
198 const vk::PhysicalDevice& physical_device)
const {
201 if (!exts.has_value()) {
205 std::vector<std::string> enabled;
207 if (exts->find(
"VK_KHR_swapchain") == exts->end()) {
208 VALIDATION_LOG <<
"Device does not support the swapchain extension.";
211 enabled.push_back(
"VK_KHR_swapchain");
214 if (exts->find(
"VK_KHR_portability_subset") != exts->end()) {
215 enabled.push_back(
"VK_KHR_portability_subset");
218 #ifdef FML_OS_ANDROID
219 if (exts->find(
"VK_ANDROID_external_memory_android_hardware_buffer") ==
222 <<
"Device does not support "
223 "VK_ANDROID_external_memory_android_hardware_buffer extension.";
226 enabled.push_back(
"VK_ANDROID_external_memory_android_hardware_buffer");
227 enabled.push_back(
"VK_EXT_queue_family_foreign");
233 if (exts->find(ext_name) != exts->end()) {
234 enabled.push_back(ext_name);
243 const auto props = device.getFormatProperties(format);
245 return !!(props.optimalTilingFeatures &
246 vk::FormatFeatureFlagBits::eColorAttachment);
251 const auto props = device.getFormatProperties(format);
252 return !!(props.optimalTilingFeatures &
253 vk::FormatFeatureFlagBits::eDepthStencilAttachment);
257 const vk::PhysicalDevice& device) {
258 const auto has_color_format =
260 const auto has_stencil_format =
264 return has_color_format && has_stencil_format;
268 auto properties = physical_device.getProperties();
269 if (!(properties.limits.framebufferColorSampleCounts &
270 (vk::SampleCountFlagBits::e1 | vk::SampleCountFlagBits::e4))) {
277 auto queue_flags = vk::QueueFlags{};
278 for (
const auto& queue : physical_device.getQueueFamilyProperties()) {
279 if (queue.queueCount == 0) {
282 queue_flags |= queue.queueFlags;
284 return static_cast<VkQueueFlags
>(queue_flags &
285 (vk::QueueFlagBits::eGraphics |
286 vk::QueueFlagBits::eCompute |
287 vk::QueueFlagBits::eTransfer));
290 std::optional<vk::PhysicalDeviceFeatures>
292 const vk::PhysicalDevice& device)
const {
299 VALIDATION_LOG <<
"Device doesn't support the required properties.";
313 const auto device_features = device.getFeatures();
315 vk::PhysicalDeviceFeatures required;
319 required.fillModeNonSolid = device_features.fillModeNonSolid;
324 bool CapabilitiesVK::HasLayer(
const std::string& layer)
const {
325 for (
const auto& [found_layer, exts] : exts_) {
326 if (found_layer == layer) {
333 bool CapabilitiesVK::HasExtension(
const std::string& ext)
const {
334 for (
const auto& [layer, exts] : exts_) {
335 if (exts.find(ext) != exts.end()) {
343 default_color_format_ = pixel_format;
350 vk::Format::eD24UnormS8Uint)) {
359 default_stencil_format_ = default_depth_stencil_format_;
364 device_properties_ = device.getProperties();
366 auto physical_properties_2 =
367 device.getProperties2<vk::PhysicalDeviceProperties2,
368 vk::PhysicalDeviceSubgroupProperties>();
374 supports_compute_subgroups_ =
375 !!(physical_properties_2.get<vk::PhysicalDeviceSubgroupProperties>()
376 .supportedOperations &
377 vk::SubgroupFeatureFlagBits::eArithmetic);
383 vk::PhysicalDeviceMemoryProperties memory_properties;
384 device.getMemoryProperties(&memory_properties);
386 for (
auto i = 0u; i < memory_properties.memoryTypeCount; i++) {
387 if (memory_properties.memoryTypes[i].propertyFlags &
388 vk::MemoryPropertyFlagBits::eLazilyAllocated) {
389 supports_device_transient_textures_ =
true;
396 optional_device_extensions_.clear();
398 if (!exts.has_value()) {
403 if (exts->find(ext_name) != exts->end()) {
404 optional_device_extensions_.insert(ext);
410 supports_framebuffer_fetch_ =
411 (optional_device_extensions_.find(
414 optional_device_extensions_.end() ||
415 optional_device_extensions_.find(
418 optional_device_extensions_.end());
451 return supports_framebuffer_fetch_;
463 return supports_compute_subgroups_;
477 return supports_device_transient_textures_;
482 return default_color_format_;
487 return default_stencil_format_;
492 return default_depth_stencil_format_;
495 const vk::PhysicalDeviceProperties&
497 return device_properties_;
502 return optional_device_extensions_.find(extension) !=
503 optional_device_extensions_.end();