mirror of
https://gitlab.freedesktop.org/mesa/vulkan-wsi-layer.git
synced 2025-12-20 06:50:08 +01:00
Implement monotonic stage timestamps on headless
Sets timestamps for `vkGetPastPresentationTimingEXT` for the remaining present stages on headless: - VK_PRESENT_STAGE_IMAGE_LATCHED_BIT_EXT - VK_PRESENT_STAGE_IMAGE_FIRST_PIXEL_OUT_BIT_EXT - VK_PRESENT_STAGE_IMAGE_FIRST_PIXEL_VISIBLE_BIT_EXT These are all set to the same value: when swapchain::present_image is called. It uses the best monotonic clock supported by the driver. No need for slot member variables to be atomic any more because they are only accessed while a lock on m_queue_mutex is held. Signed-off-by: Alex Bates <alex.bates@arm.com> Change-Id: I90ffc876890ee74620b7ba8da753794cae51dd36
This commit is contained in:
parent
24a77e8300
commit
c43dd058ed
6 changed files with 138 additions and 57 deletions
|
|
@ -62,6 +62,12 @@ wsi_ext_present_timing::wsi_ext_present_timing(const util::allocator &allocator,
|
||||||
, m_present_semaphore(allocator)
|
, m_present_semaphore(allocator)
|
||||||
, m_timestamp_period(0.f)
|
, m_timestamp_period(0.f)
|
||||||
{
|
{
|
||||||
|
if (layer::device_private_data::get(m_device).is_present_id_enabled())
|
||||||
|
{
|
||||||
|
WSI_LOG_ERROR(VK_EXT_PRESENT_TIMING_EXTENSION_NAME
|
||||||
|
" enabled but required extension " VK_KHR_PRESENT_ID_EXTENSION_NAME " is not enabled.");
|
||||||
|
}
|
||||||
|
|
||||||
VkPhysicalDeviceProperties2KHR physical_device_properties{};
|
VkPhysicalDeviceProperties2KHR physical_device_properties{};
|
||||||
physical_device_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR;
|
physical_device_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR;
|
||||||
const auto &dev = layer::device_private_data::get(m_device);
|
const auto &dev = layer::device_private_data::get(m_device);
|
||||||
|
|
@ -160,22 +166,28 @@ static inline uint64_t ticks_to_ns(uint64_t ticks, const float ×tamp_period
|
||||||
return static_cast<uint64_t>(std::llround(ns));
|
return static_cast<uint64_t>(std::llround(ns));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
swapchain_presentation_timing *wsi_ext_present_timing::get_pending_stage_timing(uint32_t image_index,
|
||||||
|
VkPresentStageFlagBitsEXT stage)
|
||||||
|
{
|
||||||
|
for (auto &entry : m_queue)
|
||||||
|
{
|
||||||
|
if (entry.m_image_index == image_index && entry.is_pending(stage))
|
||||||
|
{
|
||||||
|
return &entry.get_stage_timing(stage)->get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
VkResult wsi_ext_present_timing::get_queue_end_timing_to_queue(uint32_t image_index)
|
VkResult wsi_ext_present_timing::get_queue_end_timing_to_queue(uint32_t image_index)
|
||||||
{
|
{
|
||||||
for (auto &slot : m_queue)
|
if (auto timing = get_pending_stage_timing(image_index, VK_PRESENT_STAGE_QUEUE_OPERATIONS_END_BIT_EXT))
|
||||||
{
|
{
|
||||||
if ((slot.m_image_index == image_index) && slot.is_pending(VK_PRESENT_STAGE_QUEUE_OPERATIONS_END_BIT_EXT))
|
uint64_t time;
|
||||||
{
|
const layer::device_private_data &device_data = layer::device_private_data::get(m_device);
|
||||||
uint64_t time;
|
TRY(device_data.disp.GetQueryPoolResults(m_device, m_query_pool, image_index, 1, sizeof(time), &time, 0,
|
||||||
auto stage_timing_optional = slot.get_stage_timing(VK_PRESENT_STAGE_QUEUE_OPERATIONS_END_BIT_EXT);
|
VK_QUERY_RESULT_64_BIT));
|
||||||
const layer::device_private_data &device_data = layer::device_private_data::get(m_device);
|
timing->set_time(ticks_to_ns(time, m_timestamp_period));
|
||||||
TRY(device_data.disp.GetQueryPoolResults(m_device, m_query_pool, image_index, 1, sizeof(time), &time, 0,
|
|
||||||
VK_QUERY_RESULT_64_BIT));
|
|
||||||
stage_timing_optional->get().m_time.store(ticks_to_ns(time, m_timestamp_period));
|
|
||||||
stage_timing_optional->get().m_set.store(true, std::memory_order_release);
|
|
||||||
/* For an image index, there can only be one entry in the internal queue with pending results. */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return VK_SUCCESS;
|
return VK_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
@ -449,14 +461,13 @@ std::optional<bool> swapchain_presentation_entry::is_complete(VkPresentStageFlag
|
||||||
{
|
{
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
return stage_timing_optional->get().m_set.load(std::memory_order_relaxed);
|
return stage_timing_optional->get().m_set;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool swapchain_presentation_entry::is_pending(VkPresentStageFlagBitsEXT stage)
|
bool swapchain_presentation_entry::is_pending(VkPresentStageFlagBitsEXT stage)
|
||||||
{
|
{
|
||||||
auto stage_timing_optional = get_stage_timing(stage);
|
auto stage_timing_optional = get_stage_timing(stage);
|
||||||
return stage_timing_optional.has_value() ? !stage_timing_optional->get().m_set.load(std::memory_order_relaxed) :
|
return stage_timing_optional.has_value() ? !stage_timing_optional->get().m_set : false;
|
||||||
false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool swapchain_presentation_entry::has_outstanding_stages()
|
bool swapchain_presentation_entry::has_outstanding_stages()
|
||||||
|
|
@ -531,12 +542,11 @@ void swapchain_presentation_entry::populate(VkPastPresentationTimingEXT &timing)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stage_timing_optional->get().m_set.load(std::memory_order_acquire))
|
if (stage_timing_optional->get().m_set)
|
||||||
{
|
{
|
||||||
timing.timeDomainId = stage_timing_optional->get().m_timedomain_id;
|
timing.timeDomainId = stage_timing_optional->get().m_timedomain_id;
|
||||||
timing.pPresentStages[stage_index].stage = stage;
|
timing.pPresentStages[stage_index].stage = stage;
|
||||||
timing.pPresentStages[stage_index++].time =
|
timing.pPresentStages[stage_index++].time = stage_timing_optional->get().m_time;
|
||||||
stage_timing_optional->get().m_time.load(std::memory_order_relaxed);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -66,36 +66,29 @@ struct swapchain_presentation_timing
|
||||||
/**
|
/**
|
||||||
* Timestamp for this entry.
|
* Timestamp for this entry.
|
||||||
*/
|
*/
|
||||||
std::atomic<uint64_t> m_time{};
|
uint64_t m_time{};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Needed to mark “logically complete” timings even for presentations that the WSI
|
* Needed to mark “logically complete” timings even for presentations that the WSI
|
||||||
* implementation ultimately rejected (e.g. in MAILBOX the presentation engine
|
* implementation ultimately rejected (e.g. in MAILBOX the presentation engine
|
||||||
* rejected the one present request)
|
* rejected the one present request)
|
||||||
*/
|
*/
|
||||||
std::atomic<bool> m_set{};
|
bool m_set{};
|
||||||
|
|
||||||
swapchain_presentation_timing()
|
swapchain_presentation_timing()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
swapchain_presentation_timing(swapchain_presentation_timing &&rhs) noexcept
|
swapchain_presentation_timing(swapchain_presentation_timing &&) noexcept = default;
|
||||||
{
|
swapchain_presentation_timing &operator=(swapchain_presentation_timing &&) noexcept = default;
|
||||||
m_timedomain_id = rhs.m_timedomain_id;
|
|
||||||
m_time.store(rhs.m_time.load());
|
|
||||||
m_set.store(rhs.m_set.load());
|
|
||||||
}
|
|
||||||
|
|
||||||
swapchain_presentation_timing &operator=(swapchain_presentation_timing &&rhs) noexcept
|
|
||||||
{
|
|
||||||
m_timedomain_id = rhs.m_timedomain_id;
|
|
||||||
m_time.store(rhs.m_time.load());
|
|
||||||
m_set.store(rhs.m_set.load());
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
swapchain_presentation_timing(const swapchain_presentation_timing &) = delete;
|
swapchain_presentation_timing(const swapchain_presentation_timing &) = delete;
|
||||||
swapchain_presentation_timing &operator=(const swapchain_presentation_timing &) = delete;
|
swapchain_presentation_timing &operator=(const swapchain_presentation_timing &) = delete;
|
||||||
|
|
||||||
|
void set_time(uint64_t time)
|
||||||
|
{
|
||||||
|
m_time = time;
|
||||||
|
m_set = true;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -299,12 +292,12 @@ public:
|
||||||
*/
|
*/
|
||||||
WSI_DEFINE_EXTENSION(VK_EXT_PRESENT_TIMING_EXTENSION_NAME);
|
WSI_DEFINE_EXTENSION(VK_EXT_PRESENT_TIMING_EXTENSION_NAME);
|
||||||
|
|
||||||
template <typename T>
|
template <typename T, typename... arg_types>
|
||||||
static util::unique_ptr<T> create(const util::allocator &allocator,
|
static util::unique_ptr<T> create(const util::allocator &allocator,
|
||||||
util::unique_ptr<wsi::vulkan_time_domain> *domains, size_t domain_count,
|
util::unique_ptr<wsi::vulkan_time_domain> *domains, size_t domain_count,
|
||||||
VkDevice device, uint32_t num_images)
|
VkDevice device, uint32_t num_images, arg_types &&...args)
|
||||||
{
|
{
|
||||||
auto present_timing = allocator.make_unique<T>(allocator, device, num_images);
|
auto present_timing = allocator.make_unique<T>(allocator, device, num_images, std::forward<arg_types>(args)...);
|
||||||
for (size_t i = 0; i < domain_count; i++)
|
for (size_t i = 0; i < domain_count; i++)
|
||||||
{
|
{
|
||||||
if (!present_timing->get_swapchain_time_domains().add_time_domain(std::move(domains[i])))
|
if (!present_timing->get_swapchain_time_domains().add_time_domain(std::move(domains[i])))
|
||||||
|
|
@ -364,6 +357,22 @@ public:
|
||||||
VkResult add_presentation_entry(const layer::device_private_data &device, VkQueue queue, uint64_t present_id,
|
VkResult add_presentation_entry(const layer::device_private_data &device, VkQueue queue, uint64_t present_id,
|
||||||
uint32_t image_index, VkPresentStageFlagsEXT present_stage_queries);
|
uint32_t image_index, VkPresentStageFlagsEXT present_stage_queries);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the time for a stage, if it exists and is pending.
|
||||||
|
*
|
||||||
|
* @param image_index The index of the image in the present queue.
|
||||||
|
* @param stage The present stage to set the time for.
|
||||||
|
* @param time The time to set for the stage.
|
||||||
|
*/
|
||||||
|
void set_pending_stage_time(uint32_t image_index, VkPresentStageFlagBitsEXT stage, uint64_t time)
|
||||||
|
{
|
||||||
|
const std::lock_guard<std::mutex> lock(m_queue_mutex);
|
||||||
|
if (auto timing = get_pending_stage_timing(image_index, stage))
|
||||||
|
{
|
||||||
|
timing->set_time(time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the image's present semaphore.
|
* @brief Get the image's present semaphore.
|
||||||
*
|
*
|
||||||
|
|
@ -479,16 +488,33 @@ private:
|
||||||
*/
|
*/
|
||||||
VkResult init_timing_resources();
|
VkResult init_timing_resources();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @pre Caller must hold m_queue_mutex for the call and lifetime of the returned pointer.
|
||||||
|
*
|
||||||
|
* @brief Search for a pending presentation entry and access its timing info.
|
||||||
|
*
|
||||||
|
* For an image index, there can only be one entry in the queue with pending stages.
|
||||||
|
* This does not take a present ID because zero is a valid, nonunique value and thus cannot uniquely identify an
|
||||||
|
* entry.
|
||||||
|
*
|
||||||
|
* @param image_index The index of the image in the present queue.
|
||||||
|
* @param stage The present stage to get the entry for.
|
||||||
|
*
|
||||||
|
* @return Pointer to timing information for the stage, or nullptr if it is not found or it is not pending.
|
||||||
|
*/
|
||||||
|
swapchain_presentation_timing *get_pending_stage_timing(uint32_t image_index, VkPresentStageFlagBitsEXT stage);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @pre Caller must hold m_queue_mutex.
|
* @pre Caller must hold m_queue_mutex.
|
||||||
*
|
*
|
||||||
* @brief Get the queue end timings for an image.
|
* @brief Get the queue end timings for an image.
|
||||||
*
|
*
|
||||||
* Gets the queue end timings for a swapchain image and stores it in the internal queue.
|
* Gets the queue end timings for a swapchain image and stores it in the internal queue.
|
||||||
|
* If there is no pending entry for the image index, no-op.
|
||||||
*
|
*
|
||||||
* @param image_index The index of the image in the swapchain.
|
* @param image_index The index of the image in the swapchain.
|
||||||
*
|
*
|
||||||
* @return VK_SUCCESS if the query is successful and error if otherwise.
|
* @return VK_SUCCESS if the query is successful and error otherwise. VK_SUCCESS if no pending entry is found.
|
||||||
*/
|
*/
|
||||||
VkResult get_queue_end_timing_to_queue(uint32_t image_index);
|
VkResult get_queue_end_timing_to_queue(uint32_t image_index);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,8 +35,10 @@
|
||||||
#include "layer/private_data.hpp"
|
#include "layer/private_data.hpp"
|
||||||
|
|
||||||
wsi_ext_present_timing_headless::wsi_ext_present_timing_headless(const util::allocator &allocator, VkDevice device,
|
wsi_ext_present_timing_headless::wsi_ext_present_timing_headless(const util::allocator &allocator, VkDevice device,
|
||||||
uint32_t num_images)
|
uint32_t num_images,
|
||||||
|
std::optional<VkTimeDomainEXT> monotonic_domain)
|
||||||
: wsi::wsi_ext_present_timing(allocator, device, num_images)
|
: wsi::wsi_ext_present_timing(allocator, device, num_images)
|
||||||
|
, m_monotonic_domain(monotonic_domain)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -61,14 +63,12 @@ util::unique_ptr<wsi_ext_present_timing_headless> wsi_ext_present_timing_headles
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
VkTimeDomainEXT monotonic_domain_to_use = VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT;
|
std::optional<VkTimeDomainEXT> monotonic_domain;
|
||||||
bool monotonic_time_domain_supported = false;
|
|
||||||
for (auto [domain, supported] : monotonic_domains)
|
for (auto [domain, supported] : monotonic_domains)
|
||||||
{
|
{
|
||||||
monotonic_domain_to_use = domain;
|
|
||||||
if (supported)
|
if (supported)
|
||||||
{
|
{
|
||||||
monotonic_time_domain_supported = true;
|
monotonic_domain = domain;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -80,27 +80,27 @@ util::unique_ptr<wsi_ext_present_timing_headless> wsi_ext_present_timing_headles
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (monotonic_time_domain_supported)
|
if (monotonic_domain)
|
||||||
{
|
{
|
||||||
if (!domains.try_push_back(allocator.make_unique<wsi::vulkan_time_domain>(VK_PRESENT_STAGE_IMAGE_LATCHED_BIT_EXT,
|
if (!domains.try_push_back(
|
||||||
monotonic_domain_to_use)))
|
allocator.make_unique<wsi::vulkan_time_domain>(VK_PRESENT_STAGE_IMAGE_LATCHED_BIT_EXT, *monotonic_domain)))
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (!domains.try_push_back(allocator.make_unique<wsi::vulkan_time_domain>(
|
if (!domains.try_push_back(allocator.make_unique<wsi::vulkan_time_domain>(
|
||||||
VK_PRESENT_STAGE_IMAGE_FIRST_PIXEL_OUT_BIT_EXT, monotonic_domain_to_use)))
|
VK_PRESENT_STAGE_IMAGE_FIRST_PIXEL_OUT_BIT_EXT, *monotonic_domain)))
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (!domains.try_push_back(allocator.make_unique<wsi::vulkan_time_domain>(
|
if (!domains.try_push_back(allocator.make_unique<wsi::vulkan_time_domain>(
|
||||||
VK_PRESENT_STAGE_IMAGE_FIRST_PIXEL_VISIBLE_BIT_EXT, monotonic_domain_to_use)))
|
VK_PRESENT_STAGE_IMAGE_FIRST_PIXEL_VISIBLE_BIT_EXT, *monotonic_domain)))
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return wsi_ext_present_timing::create<wsi_ext_present_timing_headless>(allocator, domains.data(), domains.size(),
|
return wsi_ext_present_timing::create<wsi_ext_present_timing_headless>(allocator, domains.data(), domains.size(),
|
||||||
device, num_images);
|
device, num_images, monotonic_domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
VkResult wsi_ext_present_timing_headless::get_swapchain_timing_properties(
|
VkResult wsi_ext_present_timing_headless::get_swapchain_timing_properties(
|
||||||
|
|
|
||||||
|
|
@ -48,11 +48,27 @@ public:
|
||||||
VkResult get_swapchain_timing_properties(uint64_t &timing_properties_counter,
|
VkResult get_swapchain_timing_properties(uint64_t &timing_properties_counter,
|
||||||
VkSwapchainTimingPropertiesEXT &timing_properties) override;
|
VkSwapchainTimingPropertiesEXT &timing_properties) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get a monotonic time domain supported by the driver.
|
||||||
|
*
|
||||||
|
* If both MONOTONIC_RAW and MONOTONIC are supported, MONOTONIC_RAW is preferred.
|
||||||
|
*
|
||||||
|
* @return A supported monotonic time domain, or std::nullopt if no monotonic time domain is supported.
|
||||||
|
*/
|
||||||
|
std::optional<VkTimeDomainEXT> get_monotonic_domain() const
|
||||||
|
{
|
||||||
|
return m_monotonic_domain;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
wsi_ext_present_timing_headless(const util::allocator &allocator, VkDevice device, uint32_t num_images);
|
wsi_ext_present_timing_headless(const util::allocator &allocator, VkDevice device, uint32_t num_images,
|
||||||
|
std::optional<VkTimeDomainEXT> monotonic_domain);
|
||||||
|
|
||||||
/* Allow util::allocator to access the private constructor */
|
/* Allow util::allocator to access the private constructor */
|
||||||
friend util::allocator;
|
friend util::allocator;
|
||||||
|
|
||||||
|
/* Monotonic time domain supported by the driver */
|
||||||
|
std::optional<VkTimeDomainEXT> m_monotonic_domain;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -211,10 +211,38 @@ void swapchain::present_image(const pending_present_request &pending_present)
|
||||||
{
|
{
|
||||||
if (m_device_data.is_present_id_enabled())
|
if (m_device_data.is_present_id_enabled())
|
||||||
{
|
{
|
||||||
auto *ext = get_swapchain_extension<wsi_ext_present_id>(true);
|
auto *ext_present_id = get_swapchain_extension<wsi_ext_present_id>(true);
|
||||||
ext->mark_delivered(pending_present.present_id);
|
ext_present_id->mark_delivered(pending_present.present_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if VULKAN_WSI_LAYER_EXPERIMENTAL
|
||||||
|
auto *ext_present_timing = get_swapchain_extension<wsi_ext_present_timing_headless>(false);
|
||||||
|
if (ext_present_timing && ext_present_timing->get_monotonic_domain().has_value())
|
||||||
|
{
|
||||||
|
clockid_t clockid = ext_present_timing->get_monotonic_domain().value() == VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT ?
|
||||||
|
CLOCK_MONOTONIC :
|
||||||
|
CLOCK_MONOTONIC_RAW;
|
||||||
|
struct timespec now = {};
|
||||||
|
if (clock_gettime(clockid, &now) != 0)
|
||||||
|
{
|
||||||
|
WSI_LOG_ERROR("Failed to get time of clock %d, error: %d (%s)", clockid, errno, strerror(errno));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint64_t time = now.tv_sec * 1e9 + now.tv_nsec;
|
||||||
|
VkPresentStageFlagBitsEXT stages[] = {
|
||||||
|
VK_PRESENT_STAGE_IMAGE_LATCHED_BIT_EXT,
|
||||||
|
VK_PRESENT_STAGE_IMAGE_FIRST_PIXEL_OUT_BIT_EXT,
|
||||||
|
VK_PRESENT_STAGE_IMAGE_FIRST_PIXEL_VISIBLE_BIT_EXT,
|
||||||
|
};
|
||||||
|
for (auto stage : stages)
|
||||||
|
{
|
||||||
|
ext_present_timing->set_pending_stage_time(pending_present.image_index, stage, time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
unpresent_image(pending_present.image_index);
|
unpresent_image(pending_present.image_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -669,8 +669,6 @@ VkResult swapchain_base::queue_present(VkQueue queue, const VkPresentInfoKHR *pr
|
||||||
TRY(sync_queue_submit(m_device_data, queue, submit_info.present_fence, wait_semaphores));
|
TRY(sync_queue_submit(m_device_data, queue, submit_info.present_fence, wait_semaphores));
|
||||||
}
|
}
|
||||||
|
|
||||||
TRY(notify_presentation_engine(submit_info.pending_present));
|
|
||||||
|
|
||||||
#if VULKAN_WSI_LAYER_EXPERIMENTAL
|
#if VULKAN_WSI_LAYER_EXPERIMENTAL
|
||||||
if (present_timing_info != nullptr)
|
if (present_timing_info != nullptr)
|
||||||
{
|
{
|
||||||
|
|
@ -680,6 +678,9 @@ VkResult swapchain_base::queue_present(VkQueue queue, const VkPresentInfoKHR *pr
|
||||||
present_timing_info->presentStageQueries));
|
present_timing_info->presentStageQueries));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
TRY(notify_presentation_engine(submit_info.pending_present));
|
||||||
|
|
||||||
return VK_SUCCESS;
|
return VK_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue