diff --git a/layer/layer.cpp b/layer/layer.cpp index 0e5b304..d5187f1 100644 --- a/layer/layer.cpp +++ b/layer/layer.cpp @@ -246,12 +246,48 @@ VKAPI_ATTR VkResult create_device(VkPhysicalDevice physicalDevice, const VkDevic util::vector modified_enabled_extensions{ allocator }; util::extension_list enabled_extensions{ allocator }; +#if VULKAN_WSI_LAYER_EXPERIMENTAL + VkPhysicalDeviceMaintenance9FeaturesKHR maintenance9_features = {}; +#endif /* VULKAN_WSI_LAYER_EXPERIMENTAL */ const util::wsi_platform_set &enabled_platforms = inst_data.get_enabled_platforms(); if (!enabled_platforms.empty()) { TRY_LOG_CALL(enabled_extensions.add(pCreateInfo->ppEnabledExtensionNames, pCreateInfo->enabledExtensionCount)); TRY_LOG_CALL(wsi::add_device_extensions_required_by_layer(physicalDevice, enabled_platforms, enabled_extensions, inst_data.api_version)); +#if VULKAN_WSI_LAYER_EXPERIMENTAL + auto present_timing_supported = wsi::present_timing_dependencies_supported(physicalDevice); + if (std::holds_alternative(present_timing_supported)) + { + return std::get(present_timing_supported); + } + if (std::get(present_timing_supported)) + { + TRY_LOG_CALL(enabled_extensions.add(VK_KHR_MAINTENANCE_9_EXTENSION_NAME)); + + const auto *device_maintenance9_features = util::find_extension( + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_9_FEATURES_KHR, pCreateInfo->pNext); + if (device_maintenance9_features) + { + if (device_maintenance9_features->maintenance9 == VK_FALSE) + { + /* We are taking the same risk with the frame boundary features below. */ + auto *maintenance9_features_non_const = + const_cast(device_maintenance9_features); + maintenance9_features_non_const->maintenance9 = VK_TRUE; + } + } + else + { + maintenance9_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_9_FEATURES_KHR; + maintenance9_features.pNext = const_cast(modified_info.pNext); + maintenance9_features.maintenance9 = VK_TRUE; + + modified_info.pNext = &maintenance9_features; + } + } +#endif /* VULKAN_WSI_LAYER_EXPERIMENTAL */ + TRY_LOG_CALL(enabled_extensions.get_extension_strings(modified_enabled_extensions)); modified_info.ppEnabledExtensionNames = modified_enabled_extensions.data(); diff --git a/layer/private_data.hpp b/layer/private_data.hpp index ed845b2..7dafe1b 100644 --- a/layer/private_data.hpp +++ b/layer/private_data.hpp @@ -671,6 +671,12 @@ public: */ bool has_image_compression_support(VkPhysicalDevice phys_dev); + /** + * @brief Check if a physical device supports frame boundary. + * + * @param phys_dev The physical device to query. + * @return Whether frame boundary control is supported by the ICD. + */ bool has_frame_boundary_support(VkPhysicalDevice phys_dev); /** diff --git a/wsi/display/surface_properties.cpp b/wsi/display/surface_properties.cpp index 3d2dab1..f83686b 100644 --- a/wsi/display/surface_properties.cpp +++ b/wsi/display/surface_properties.cpp @@ -567,7 +567,7 @@ bool surface_properties::is_surface_extension_enabled(const layer::instance_priv } #if VULKAN_WSI_LAYER_EXPERIMENTAL -VkResult surface_properties::get_present_timing_surface_caps( +VkResult surface_properties::get_present_timing_surface_caps_internal( VkPhysicalDevice, VkPresentTimingSurfaceCapabilitiesEXT *present_timing_surface_caps) { present_timing_surface_caps->presentTimingSupported = VK_FALSE; diff --git a/wsi/display/surface_properties.hpp b/wsi/display/surface_properties.hpp index 13cd705..c8e68b5 100644 --- a/wsi/display/surface_properties.hpp +++ b/wsi/display/surface_properties.hpp @@ -66,11 +66,6 @@ public: bool is_surface_extension_enabled(const layer::instance_private_data &instance_data) override; -#if VULKAN_WSI_LAYER_EXPERIMENTAL - VkResult get_present_timing_surface_caps( - VkPhysicalDevice physical_device, VkPresentTimingSurfaceCapabilitiesEXT *present_timing_surface_caps) override; -#endif - static surface_properties &get_instance(); bool is_compatible_present_modes(VkPresentModeKHR present_mode_a, VkPresentModeKHR present_mode_b) override; @@ -86,6 +81,11 @@ private: void get_surface_present_scaling_and_gravity(VkSurfacePresentScalingCapabilitiesEXT *scaling_capabilities) override; void populate_present_mode_compatibilities() override; + +#if VULKAN_WSI_LAYER_EXPERIMENTAL + VkResult get_present_timing_surface_caps_internal( + VkPhysicalDevice physical_device, VkPresentTimingSurfaceCapabilitiesEXT *present_timing_surface_caps) override; +#endif }; } /* namespace display */ diff --git a/wsi/extensions/present_timing.cpp b/wsi/extensions/present_timing.cpp index c6e9881..7fffb3b 100644 --- a/wsi/extensions/present_timing.cpp +++ b/wsi/extensions/present_timing.cpp @@ -698,6 +698,42 @@ VkResult check_time_domain_support(VkPhysicalDevice physical_device, std::tuple< return VK_SUCCESS; } +std::variant present_timing_dependencies_supported(VkPhysicalDevice physical_device) +{ + auto &instance_data = layer::instance_private_data::get(physical_device); + util::vector properties{ util::allocator(instance_data.get_allocator(), + VK_SYSTEM_ALLOCATION_SCOPE_COMMAND) }; + uint32_t count = 0; + TRY_LOG(instance_data.disp.EnumerateDeviceExtensionProperties(physical_device, nullptr, &count, nullptr), + "Failed to enumurate properties of available physical device extensions"); + + if (!properties.try_resize(count)) + { + return VK_ERROR_OUT_OF_HOST_MEMORY; + } + + TRY_LOG(instance_data.disp.EnumerateDeviceExtensionProperties(physical_device, nullptr, &count, properties.data()), + "Failed to enumurate properties of available physical device extensions"); + + const bool maintenance9_supported = + std::find_if(properties.begin(), properties.end(), [](const VkExtensionProperties &ext) { + return strcmp(ext.extensionName, VK_KHR_MAINTENANCE_9_EXTENSION_NAME) == 0; + }) != properties.end(); + + if (!maintenance9_supported) + { + return false; + } + + VkPhysicalDeviceMaintenance9FeaturesKHR maintenance9 = { + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_9_FEATURES_KHR, nullptr, VK_FALSE + }; + VkPhysicalDeviceFeatures2KHR features = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR, &maintenance9, {} }; + + instance_data.disp.GetPhysicalDeviceFeatures2KHR(physical_device, &features); + + return maintenance9.maintenance9 != VK_FALSE; +} } /* namespace wsi */ #endif /* VULKAN_WSI_LAYER_EXPERIMENTAL */ diff --git a/wsi/extensions/present_timing.hpp b/wsi/extensions/present_timing.hpp index 8b5c8df..dc2e94e 100644 --- a/wsi/extensions/present_timing.hpp +++ b/wsi/extensions/present_timing.hpp @@ -46,6 +46,7 @@ #include #include #include +#include #include "wsi_extension.hpp" @@ -350,9 +351,12 @@ public: command_buffer = VK_NULL_HANDLE; } /* Allocate the command pool and query pool. */ - VkQueryPoolCreateInfo query_pool_info = { - VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, nullptr, 0, VK_QUERY_TYPE_TIMESTAMP, num_images, 0 - }; + VkQueryPoolCreateInfo query_pool_info = { VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, + nullptr, + VK_QUERY_POOL_CREATE_RESET_BIT_KHR, + VK_QUERY_TYPE_TIMESTAMP, + num_images, + 0 }; TRY_LOG_CALL(m_device.disp.CreateQueryPool(m_device.device, &query_pool_info, m_allocator.get_original_callbacks(), &m_query_pool)); VkCommandPoolCreateInfo command_pool_info{ VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, nullptr, @@ -778,5 +782,6 @@ private: VkResult check_time_domain_support(VkPhysicalDevice physical_device, std::tuple *domains, size_t domain_size); +std::variant present_timing_dependencies_supported(VkPhysicalDevice physical_device); } /* namespace wsi */ #endif diff --git a/wsi/headless/surface_properties.cpp b/wsi/headless/surface_properties.cpp index 971f22c..0bcb226 100644 --- a/wsi/headless/surface_properties.cpp +++ b/wsi/headless/surface_properties.cpp @@ -241,7 +241,7 @@ bool surface_properties::is_compatible_present_modes(VkPresentModeKHR present_mo } #if VULKAN_WSI_LAYER_EXPERIMENTAL -VkResult surface_properties::get_present_timing_surface_caps( +VkResult surface_properties::get_present_timing_surface_caps_internal( VkPhysicalDevice physical_device, VkPresentTimingSurfaceCapabilitiesEXT *present_timing_surface_caps) { present_timing_surface_caps->presentTimingSupported = VK_TRUE; diff --git a/wsi/headless/surface_properties.hpp b/wsi/headless/surface_properties.hpp index 5d530ec..82cd693 100644 --- a/wsi/headless/surface_properties.hpp +++ b/wsi/headless/surface_properties.hpp @@ -64,11 +64,6 @@ public: bool is_compatible_present_modes(VkPresentModeKHR present_mode_a, VkPresentModeKHR present_mode_b) override; -#if VULKAN_WSI_LAYER_EXPERIMENTAL - VkResult get_present_timing_surface_caps( - VkPhysicalDevice physical_device, VkPresentTimingSurfaceCapabilitiesEXT *present_timing_surface_caps) override; -#endif - private: /* List of supported presentation modes */ std::array m_supported_modes; @@ -79,6 +74,11 @@ private: void populate_present_mode_compatibilities() override; void get_surface_present_scaling_and_gravity(VkSurfacePresentScalingCapabilitiesEXT *scaling_capabilities) override; + +#if VULKAN_WSI_LAYER_EXPERIMENTAL + VkResult get_present_timing_surface_caps_internal( + VkPhysicalDevice physical_device, VkPresentTimingSurfaceCapabilitiesEXT *present_timing_surface_caps) override; +#endif }; } /* namespace headless */ diff --git a/wsi/surface_properties.cpp b/wsi/surface_properties.cpp index 8501400..b8c919a 100644 --- a/wsi/surface_properties.cpp +++ b/wsi/surface_properties.cpp @@ -24,6 +24,7 @@ #include "surface_properties.hpp" #include "layer/private_data.hpp" +#include "wsi/extensions/present_timing.hpp" namespace wsi { @@ -127,4 +128,28 @@ void get_surface_capabilities_common(VkPhysicalDevice physical_device, VkSurface VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; } +#if VULKAN_WSI_LAYER_EXPERIMENTAL +/** + * @brief Get the present timing surface capabilities for the specific VkSurface type. + */ +VkResult surface_properties::get_present_timing_surface_caps( + VkPhysicalDevice physical_device, VkPresentTimingSurfaceCapabilitiesEXT *present_timing_surface_caps) +{ + TRY_LOG_CALL(get_present_timing_surface_caps_internal(physical_device, present_timing_surface_caps)); + + auto present_timing_supported = wsi::present_timing_dependencies_supported(physical_device); + if (std::holds_alternative(present_timing_supported)) + { + return std::get(present_timing_supported); + } + + if (!std::get(present_timing_supported)) + { + present_timing_surface_caps->presentTimingSupported = VK_FALSE; + } + + return VK_SUCCESS; +} +#endif /* VULKAN_WSI_LAYER_EXPERIMENTAL */ + } /* namespace wsi */ diff --git a/wsi/surface_properties.hpp b/wsi/surface_properties.hpp index 01a5a39..ef8d23d 100644 --- a/wsi/surface_properties.hpp +++ b/wsi/surface_properties.hpp @@ -119,9 +119,9 @@ public: /** * @brief Get the present timing surface capabilities for the specific VkSurface type. */ - virtual VkResult get_present_timing_surface_caps( - VkPhysicalDevice physical_device, VkPresentTimingSurfaceCapabilitiesEXT *present_timing_surface_caps) = 0; -#endif + VkResult get_present_timing_surface_caps(VkPhysicalDevice physical_device, + VkPresentTimingSurfaceCapabilitiesEXT *present_timing_surface_caps); +#endif /* VULKAN_WSI_LAYER_EXPERIMENTAL */ /** * @brief Virtual destructor. @@ -133,6 +133,14 @@ private: * @brief Set which presentation modes are compatible with each other for a particular surface */ virtual void populate_present_mode_compatibilities() = 0; + +#if VULKAN_WSI_LAYER_EXPERIMENTAL + /** + * @brief Get the present timing surface capabilities for the specific VkSurface type. + */ + virtual VkResult get_present_timing_surface_caps_internal( + VkPhysicalDevice physical_device, VkPresentTimingSurfaceCapabilitiesEXT *present_timing_surface_caps) = 0; +#endif /* VULKAN_WSI_LAYER_EXPERIMENTAL */ }; class surface_format_properties diff --git a/wsi/wayland/surface_properties.cpp b/wsi/wayland/surface_properties.cpp index f0d2751..ac0ce07 100644 --- a/wsi/wayland/surface_properties.cpp +++ b/wsi/wayland/surface_properties.cpp @@ -455,7 +455,7 @@ bool surface_properties::is_compatible_present_modes(VkPresentModeKHR present_mo } #if VULKAN_WSI_LAYER_EXPERIMENTAL -VkResult surface_properties::get_present_timing_surface_caps( +VkResult surface_properties::get_present_timing_surface_caps_internal( VkPhysicalDevice physical_device, VkPresentTimingSurfaceCapabilitiesEXT *present_timing_surface_caps) { present_timing_surface_caps->presentTimingSupported = VK_TRUE; diff --git a/wsi/wayland/surface_properties.hpp b/wsi/wayland/surface_properties.hpp index 9d7af1d..4953e6d 100644 --- a/wsi/wayland/surface_properties.hpp +++ b/wsi/wayland/surface_properties.hpp @@ -75,10 +75,6 @@ public: bool is_compatible_present_modes(VkPresentModeKHR present_mode_a, VkPresentModeKHR present_mode_b) override; -#if VULKAN_WSI_LAYER_EXPERIMENTAL - VkResult get_present_timing_surface_caps( - VkPhysicalDevice physical_device, VkPresentTimingSurfaceCapabilitiesEXT *present_timing_surface_caps) override; -#endif private: surface_properties(); @@ -98,6 +94,11 @@ private: void populate_present_mode_compatibilities() override; void get_surface_present_scaling_and_gravity(VkSurfacePresentScalingCapabilitiesEXT *scaling_capabilities) override; + +#if VULKAN_WSI_LAYER_EXPERIMENTAL + VkResult get_present_timing_surface_caps_internal( + VkPhysicalDevice physical_device, VkPresentTimingSurfaceCapabilitiesEXT *present_timing_surface_caps) override; +#endif }; } // namespace wayland