VK_EXT_present_timing updates for Wayland

This commit updates time domain used in the
VK_PRESENT_STAGE_IMAGE_FIRST_PIXEL_VISIBLE_BIT_EXT present stage
in the Wayland backend.

Change-Id: I0d158d0eea6608edd532fbebadb18713d5486d6b
Signed-off-by: Fufu Fang <fufu.fang@arm.com>
Signed-off-by: Alex Bates <alex.bates@arm.com>
This commit is contained in:
Fufu Fang 2025-03-07 10:28:00 +00:00 committed by Alex Bates
parent 6958c14113
commit e765b38308
6 changed files with 86 additions and 10 deletions

View file

@ -37,11 +37,13 @@ wsi_ext_present_timing_wayland::wsi_ext_present_timing_wayland(const util::alloc
}
util::unique_ptr<wsi_ext_present_timing_wayland> wsi_ext_present_timing_wayland::create(
const util::allocator &allocator)
VkTimeDomainKHR image_first_pixel_visible_time_domain, const util::allocator &allocator)
{
std::array<util::unique_ptr<wsi::vulkan_time_domain>, 1> time_domains_array = {
std::array<util::unique_ptr<wsi::vulkan_time_domain>, 2> time_domains_array = {
allocator.make_unique<wsi::vulkan_time_domain>(VK_PRESENT_STAGE_QUEUE_OPERATIONS_END_BIT_EXT,
VK_TIME_DOMAIN_DEVICE_KHR)
VK_TIME_DOMAIN_DEVICE_KHR),
allocator.make_unique<wsi::vulkan_time_domain>(VK_PRESENT_STAGE_IMAGE_FIRST_PIXEL_VISIBLE_BIT_EXT,
image_first_pixel_visible_time_domain)
};
return wsi_ext_present_timing::create<wsi_ext_present_timing_wayland>(allocator, time_domains_array);
@ -55,4 +57,4 @@ VkResult wsi_ext_present_timing_wayland::get_swapchain_timing_properties(
timing_properties.variableRefreshDelay = 0;
return VK_SUCCESS;
}
}

View file

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

View file

@ -72,9 +72,21 @@ zwp_linux_dmabuf_v1_modifier_impl(void *data, struct zwp_linux_dmabuf_v1 *dma_bu
drm_supported_formats->is_out_of_memory = !drm_supported_formats->formats->try_push_back(format);
}
}
/* Handler for clock_id event of the wp_presentation interface. */
VWL_CAPI_CALL(void)
wp_presentation_clock_id_impl(void *data, struct wp_presentation *wp_presentation,
uint32_t compositor_clockid) VWL_API_POST
{
UNUSED(wp_presentation);
clockid_t *clockid = static_cast<clockid_t *>(data);
*clockid = compositor_clockid;
}
} // namespace
/*
/**
* @brief Get supported formats and modifiers using the zwp_linux_dmabuf_v1 interface.
*
* @param[in] display The wl_display that is being used.
@ -122,6 +134,35 @@ static VkResult get_supported_formats_and_modifiers(wl_display *display, wl_even
return VK_SUCCESS;
}
/**
* @brief Set the clock_id using the wp_presentation interface
*
* @retval VK_SUCCESS Indicates success.
* @retval VK_ERROR_UNKNOWN Indicates one of the Wayland functions failed.
*/
static VkResult get_clock_id(wl_display *display, wl_event_queue *queue, wp_presentation *presentation_interface,
clockid_t *clockid)
{
const wp_presentation_listener presentation_listener = {
.clock_id = wp_presentation_clock_id_impl,
};
int res = wp_presentation_add_listener(presentation_interface, &presentation_listener, clockid);
if (res < 0)
{
WSI_LOG_ERROR("Failed to add wp_presentation listener.");
return VK_ERROR_UNKNOWN;
}
res = wl_display_roundtrip_queue(display, queue);
if (res < 0)
{
WSI_LOG_ERROR("Roundtrip failed.");
return VK_ERROR_UNKNOWN;
}
return VK_SUCCESS;
}
struct surface::init_parameters
{
const util::allocator &allocator;
@ -262,6 +303,12 @@ bool surface::init()
return false;
}
vk_res = get_clock_id(wayland_display, surface_queue.get(), presentation_time_interface.get(), &m_clockid);
if (vk_res != VK_SUCCESS)
{
return false;
}
return true;
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021-2025 Arm Limited.
* Copyright (c) 2021, 2024-2025 Arm Limited.
*
* SPDX-License-Identifier: MIT
*
@ -31,6 +31,7 @@
#ifndef __STDC_VERSION__
#define __STDC_VERSION__ 0
#endif
#include <sys/types.h>
#include <wayland-client.h>
#include "wsi/surface.hpp"
@ -149,6 +150,14 @@ public:
*/
bool wait_next_frame_event();
/**
* @brief Return the clockid of the surface
*/
clockid_t clockid()
{
return m_clockid;
}
private:
/**
* @brief Initialize the WSI surface by creating Wayland queues and linking to Wayland protocols.
@ -189,7 +198,7 @@ private:
wayland_owner<wp_presentation> presentation_time_interface;
/**
* Container for a callback object for the latest frame done event.
* @brief Container for a callback object for the latest frame done event.
*
* The callback object should be destroyed before the queue so any new events
* on the queue will be discarded. If a proxy object is destroyed after a queue,
@ -205,6 +214,11 @@ private:
* callback to indicate the server is ready for the next buffer.
*/
bool present_pending;
/**
* @brief Stores the clock ID reported by the wp_presentation interface
*/
clockid_t m_clockid;
};
} // namespace wayland

View file

@ -424,7 +424,8 @@ void surface_properties::get_present_timing_surface_caps(
present_timing_surface_caps->presentTimingSupported = VK_TRUE;
present_timing_surface_caps->presentAtAbsoluteTimeSupported = VK_FALSE;
present_timing_surface_caps->presentAtRelativeTimeSupported = VK_FALSE;
present_timing_surface_caps->presentStageQueries = VK_PRESENT_STAGE_QUEUE_OPERATIONS_END_BIT_EXT;
present_timing_surface_caps->presentStageQueries =
VK_PRESENT_STAGE_QUEUE_OPERATIONS_END_BIT_EXT | VK_PRESENT_STAGE_IMAGE_FIRST_PIXEL_VISIBLE_BIT_EXT;
present_timing_surface_caps->presentStageTargets = 0;
}
#endif

View file

@ -127,7 +127,18 @@ 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_wayland::create(m_allocator)))
/*
* Default to a raw hardware-based time that is not subject to NTP adjustments or
* the incremental adjustments performed by adjtime(3)
*/
VkTimeDomainKHR image_first_pixel_visible_time_domain = VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_KHR;
if (m_wsi_surface->clockid() == CLOCK_MONOTONIC)
{
image_first_pixel_visible_time_domain = VK_TIME_DOMAIN_CLOCK_MONOTONIC_KHR;
}
if (!add_swapchain_extension(
wsi_ext_present_timing_wayland::create(image_first_pixel_visible_time_domain, m_allocator)))
{
return VK_ERROR_OUT_OF_HOST_MEMORY;
}