Implement schedule present at relative time on headless

In this change, the schedule present at relative time is enabled for
headless backend.

Signed-off-by: Ginu Jacob <ginu.jacob@arm.com>
Change-Id: I15ff8170dfe93539e4c9a7ff20868b0916129546
This commit is contained in:
Ginu Jacob 2025-09-15 11:40:06 +00:00 committed by Rosen Zhelev
parent 681648c9e9
commit 7a46cdb679
4 changed files with 58 additions and 14 deletions

View file

@ -151,4 +151,17 @@ std::optional<uint64_t> wsi_ext_present_timing_headless::get_current_clock_time_
return now.tv_sec * static_cast<uint64_t>(1e9) + now.tv_nsec;
}
std::optional<uint64_t> wsi_ext_present_timing_headless::get_first_pixel_visible_timestamp_for_last_image() const
{
if (!m_first_pixel_visible_timestamp_for_last_image.has_value())
{
return std::nullopt;
}
return m_first_pixel_visible_timestamp_for_last_image.value();
}
void wsi_ext_present_timing_headless::set_first_pixel_visible_timestamp_for_last_image(uint64_t timestamp)
{
m_first_pixel_visible_timestamp_for_last_image = timestamp;
}
#endif

View file

@ -67,6 +67,19 @@ public:
*/
std::optional<uint64_t> get_current_clock_time_ns() const;
/**
* @brief Get the first pixel visible timestamp for the last presented image.
*
* @return first pixel visible timestamp for the last presented image or std::nullopt in case of error.
*/
std::optional<uint64_t> get_first_pixel_visible_timestamp_for_last_image() const;
/**
* @brief Caches the first pixel visible timestamp for the last presented image.
*
*/
void set_first_pixel_visible_timestamp_for_last_image(uint64_t timestamp);
private:
wsi_ext_present_timing_headless(const util::allocator &allocator, VkDevice device, uint32_t num_images,
std::optional<VkTimeDomainEXT> monotonic_domain);
@ -76,6 +89,11 @@ private:
/* Monotonic time domain supported by the driver */
std::optional<VkTimeDomainEXT> m_monotonic_domain;
/**
* Timestamp for the last VK_PRESENT_STAGE_IMAGE_FIRST_PIXEL_VISIBLE_BIT_EXT stage.
*/
std::optional<uint64_t> m_first_pixel_visible_timestamp_for_last_image;
};
#endif

View file

@ -247,7 +247,7 @@ VkResult surface_properties::get_present_timing_surface_caps(
VkPhysicalDevice physical_device, VkPresentTimingSurfaceCapabilitiesEXT *present_timing_surface_caps)
{
present_timing_surface_caps->presentTimingSupported = VK_TRUE;
present_timing_surface_caps->presentAtAbsoluteTimeSupported = VK_TRUE;
present_timing_surface_caps->presentAtAbsoluteTimeSupported = VK_FALSE;
present_timing_surface_caps->presentAtRelativeTimeSupported = VK_FALSE;
VkPresentStageFlagsEXT monotonic_present_stages_supported = 0;
@ -264,6 +264,8 @@ VkResult surface_properties::get_present_timing_surface_caps(
monotonic_present_stages_supported |= VK_PRESENT_STAGE_REQUEST_DEQUEUED_BIT_EXT |
VK_PRESENT_STAGE_IMAGE_FIRST_PIXEL_OUT_BIT_EXT |
VK_PRESENT_STAGE_IMAGE_FIRST_PIXEL_VISIBLE_BIT_EXT;
present_timing_surface_caps->presentAtAbsoluteTimeSupported = VK_TRUE;
present_timing_surface_caps->presentAtRelativeTimeSupported = VK_TRUE;
}
present_timing_surface_caps->presentStageQueries =

View file

@ -227,25 +227,35 @@ void swapchain::present_image(const pending_present_request &pending_present)
if (ext_present_timing)
{
auto presentation_target = ext_present_timing->get_presentation_target_entry(pending_present.image_index);
uint64_t absolute_future_present_time_ns = 0;
if (presentation_target)
{
/* No support for relative presentation mode currently */
assert(!(presentation_target->m_flags & VK_PRESENT_TIMING_INFO_PRESENT_AT_RELATIVE_TIME_BIT_EXT));
if (!(presentation_target->m_flags & VK_PRESENT_TIMING_INFO_PRESENT_AT_RELATIVE_TIME_BIT_EXT))
if (presentation_target->m_flags & VK_PRESENT_TIMING_INFO_PRESENT_AT_RELATIVE_TIME_BIT_EXT)
{
std::optional<uint64_t> first_pixel_visible_timestamp_for_last_image =
ext_present_timing->get_first_pixel_visible_timestamp_for_last_image();
if (first_pixel_visible_timestamp_for_last_image.has_value())
{
absolute_future_present_time_ns =
first_pixel_visible_timestamp_for_last_image.value() + presentation_target->m_target_present_time;
}
}
else
{
/* No need to check whether we need to present at nearest refresh cycle since this backend is not
limited by the refresh cycles. */
uint64_t absolute_future_present_time_ns = presentation_target->m_target_present_time;
auto current_time_ns = ext_present_timing->get_current_clock_time_ns();
if (*current_time_ns < absolute_future_present_time_ns)
{
/* Sleep until we can schedule the image for completion.
* This is OK as the sleep should only be dispatched on the page_flip thread and not on main. */
assert(m_page_flip_thread_run);
absolute_future_present_time_ns = presentation_target->m_target_present_time;
}
auto current_time_ns = ext_present_timing->get_current_clock_time_ns();
if (*current_time_ns < absolute_future_present_time_ns)
{
/* Sleep until we can schedule the image for completion.
* This is OK as the sleep should only be dispatched on the page_flip thread and not on main. */
assert(m_page_flip_thread_run);
int64_t time_diff = absolute_future_present_time_ns - *current_time_ns;
std::this_thread::sleep_for(std::chrono::nanoseconds(time_diff));
}
int64_t time_diff = absolute_future_present_time_ns - *current_time_ns;
std::this_thread::sleep_for(std::chrono::nanoseconds(time_diff));
}
}
@ -268,6 +278,7 @@ void swapchain::present_image(const pending_present_request &pending_present)
/* Set all times to 0 as we were not able to query them. */
current_time = 0;
}
ext_present_timing->set_first_pixel_visible_timestamp_for_last_image(*current_time);
VkPresentStageFlagBitsEXT stages[] = {
VK_PRESENT_STAGE_REQUEST_DEQUEUED_BIT_EXT,