diff --git a/layer/private_data.hpp b/layer/private_data.hpp index d64ed13..d342fb6 100644 --- a/layer/private_data.hpp +++ b/layer/private_data.hpp @@ -262,7 +262,10 @@ static constexpr uint32_t API_VERSION_MAX = UINT32_MAX; /* The layer does not use these entrypoints directly but does use VkExternalImageFormatPropertiesKHR introduced by */ \ /* this extension. These are listed here in order to hide them from the application. */ \ EP(GetPhysicalDeviceExternalBufferPropertiesKHR, VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME, \ - VK_API_VERSION_1_1, false, GetPhysicalDeviceExternalBufferProperties) + VK_API_VERSION_1_1, false, GetPhysicalDeviceExternalBufferProperties) \ + /* VK_KHR_calibrated_timestamps */ \ + EP(GetPhysicalDeviceCalibrateableTimeDomainsKHR, VK_KHR_CALIBRATED_TIMESTAMPS_EXTENSION_NAME, API_VERSION_MAX, \ + false, ) /** * @brief Struct representing the instance dispatch table. diff --git a/wsi/headless/present_timing_handler.cpp b/wsi/headless/present_timing_handler.cpp index 86330db..b1d0be7 100644 --- a/wsi/headless/present_timing_handler.cpp +++ b/wsi/headless/present_timing_handler.cpp @@ -27,28 +27,92 @@ * * @brief Contains the functionality to implement features for present timing extension. */ - -#include "present_timing_handler.hpp" +#if VULKAN_WSI_LAYER_EXPERIMENTAL #include #include +#include +#include +#include "present_timing_handler.hpp" +#include "layer/private_data.hpp" wsi_ext_present_timing_headless::wsi_ext_present_timing_headless(const util::allocator &allocator) : wsi::wsi_ext_present_timing(allocator) { } +/** + * @brief Queries whether the driver supports the raw monotonic clock domain. + * + * This function invokes vkGetPhysicalDeviceCalibrateableTimeDomainsKHR twice: + * 1. To query the count of supported time domains. + * 2. To retrieve the list of supported time domains. + * + * @param device The Vulkan logical device whose physical device is queried. Must be valid. + * @return A std::optional with: + * - true if VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_KHR is supported. + * - false if VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_KHR is not supported. + * - std::nullopt if the query fails (e.g., vkGetPhysicalDeviceCalibrateableTimeDomainsKHR + * returns an error or memory allocation fails). + */ +static std::optional is_time_domain_clock_monotonic_raw_supported(const VkDevice &device) +{ + auto &dev_data = layer::device_private_data::get(device); + auto &physicalDevice = dev_data.physical_device; + auto &instance = dev_data.instance_data; + + uint32_t supported_domains_count = 0; + VkResult result = + instance.disp.GetPhysicalDeviceCalibrateableTimeDomainsKHR(physicalDevice, &supported_domains_count, nullptr); + if (result != VK_SUCCESS) + { + return std::nullopt; + } + + util::allocator allocator(instance.get_allocator(), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); + util::vector supported_domains(allocator); + if (!supported_domains.try_resize(supported_domains_count)) + { + return std::nullopt; + } + + result = instance.disp.GetPhysicalDeviceCalibrateableTimeDomainsKHR(physicalDevice, &supported_domains_count, + supported_domains.data()); + if (result != VK_SUCCESS) + { + return std::nullopt; + } + + bool supported = std::find(supported_domains.begin(), supported_domains.end(), + VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_KHR) != supported_domains.end(); + return supported; +} util::unique_ptr wsi_ext_present_timing_headless::create( - const util::allocator &allocator) + const VkDevice &device, const util::allocator &allocator) { + /* + * Select the hardware raw monotonic clock domain (unaffected by NTP or adjtime adjustments) + * when the driver supports it; otherwise use the standard monotonic clock. + */ + VkTimeDomainKHR monotonic_time_domain = VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_KHR; + + auto clock_monotonic_raw_support = is_time_domain_clock_monotonic_raw_supported(device); + if (!clock_monotonic_raw_support.has_value()) + { + return nullptr; + } + else if (clock_monotonic_raw_support.value() == false) + { + monotonic_time_domain = VK_TIME_DOMAIN_CLOCK_MONOTONIC_KHR; + } + std::array, 4> time_domains_array = { allocator.make_unique(VK_PRESENT_STAGE_QUEUE_OPERATIONS_END_BIT_EXT, VK_TIME_DOMAIN_DEVICE_KHR), - allocator.make_unique(VK_PRESENT_STAGE_IMAGE_LATCHED_BIT_EXT, - VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_KHR), + allocator.make_unique(VK_PRESENT_STAGE_IMAGE_LATCHED_BIT_EXT, monotonic_time_domain), allocator.make_unique(VK_PRESENT_STAGE_IMAGE_FIRST_PIXEL_OUT_BIT_EXT, - VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_KHR), + monotonic_time_domain), allocator.make_unique(VK_PRESENT_STAGE_IMAGE_FIRST_PIXEL_VISIBLE_BIT_EXT, - VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_KHR) + monotonic_time_domain) }; return wsi_ext_present_timing::create(allocator, time_domains_array); @@ -66,3 +130,4 @@ VkResult wsi_ext_present_timing_headless::get_swapchain_timing_properties( return VK_SUCCESS; } +#endif \ No newline at end of file diff --git a/wsi/headless/present_timing_handler.hpp b/wsi/headless/present_timing_handler.hpp index 37a0deb..3c70d58 100644 --- a/wsi/headless/present_timing_handler.hpp +++ b/wsi/headless/present_timing_handler.hpp @@ -41,7 +41,8 @@ class wsi_ext_present_timing_headless : public wsi::wsi_ext_present_timing { public: - static util::unique_ptr create(const util::allocator &allocator); + static util::unique_ptr create(const VkDevice &device, + const util::allocator &allocator); VkResult get_swapchain_timing_properties(uint64_t &timing_properties_counter, VkSwapchainTimingPropertiesEXT &timing_properties) override; diff --git a/wsi/headless/swapchain.cpp b/wsi/headless/swapchain.cpp index 6219fe5..459bf0e 100644 --- a/wsi/headless/swapchain.cpp +++ b/wsi/headless/swapchain.cpp @@ -106,7 +106,7 @@ VkResult swapchain::add_required_extensions(VkDevice device, const VkSwapchainCr bool swapchain_support_enabled = swapchain_create_info->flags & VK_SWAPCHAIN_CREATE_PRESENT_TIMING_BIT_EXT; if (swapchain_support_enabled) { - if (!add_swapchain_extension(wsi_ext_present_timing_headless::create(m_allocator))) + if (!add_swapchain_extension(wsi_ext_present_timing_headless::create(device, m_allocator))) { return VK_ERROR_OUT_OF_HOST_MEMORY; }