Support WSI present timing if time domain supported

This commit is contained in:
Maged Elnaggar 2025-05-16 08:26:19 +00:00 committed by Dennis Tsiang
parent c3b192ac2f
commit 16e77d770a
4 changed files with 79 additions and 10 deletions

View file

@ -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.

View file

@ -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 <cstdint>
#include <array>
#include <optional>
#include <algorithm>
#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<bool> 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<bool> 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<VkTimeDomainEXT> 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> 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<util::unique_ptr<wsi::vulkan_time_domain>, 4> time_domains_array = {
allocator.make_unique<wsi::vulkan_time_domain>(VK_PRESENT_STAGE_QUEUE_OPERATIONS_END_BIT_EXT,
VK_TIME_DOMAIN_DEVICE_KHR),
allocator.make_unique<wsi::vulkan_time_domain>(VK_PRESENT_STAGE_IMAGE_LATCHED_BIT_EXT,
VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_KHR),
allocator.make_unique<wsi::vulkan_time_domain>(VK_PRESENT_STAGE_IMAGE_LATCHED_BIT_EXT, monotonic_time_domain),
allocator.make_unique<wsi::vulkan_time_domain>(VK_PRESENT_STAGE_IMAGE_FIRST_PIXEL_OUT_BIT_EXT,
VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_KHR),
monotonic_time_domain),
allocator.make_unique<wsi::vulkan_time_domain>(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<wsi_ext_present_timing_headless>(allocator, time_domains_array);
@ -66,3 +130,4 @@ VkResult wsi_ext_present_timing_headless::get_swapchain_timing_properties(
return VK_SUCCESS;
}
#endif

View file

@ -41,7 +41,8 @@
class wsi_ext_present_timing_headless : public wsi::wsi_ext_present_timing
{
public:
static util::unique_ptr<wsi_ext_present_timing_headless> create(const util::allocator &allocator);
static util::unique_ptr<wsi_ext_present_timing_headless> create(const VkDevice &device,
const util::allocator &allocator);
VkResult get_swapchain_timing_properties(uint64_t &timing_properties_counter,
VkSwapchainTimingPropertiesEXT &timing_properties) override;

View file

@ -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;
}