From 7c58549ec201c0df5281d686d68fd5fbb377ef04 Mon Sep 17 00:00:00 2001 From: Iason Paraskevopoulos Date: Wed, 2 Jul 2025 16:08:46 +0100 Subject: [PATCH] Add VkPastPresentationTimingFlagBitsEXT Handles VkPastPresentationTimingFlagBitsEXT in VkPastPresentationTimingInfoEXT. Changes present_timing_queue_set_size to return VK_NOT_READY when queue_size is bigger thank m_queue.size(). Change-Id: I4f8038c2b0060cfdac30754234536aa9ce42acbb Signed-off-by: Iason Paraskevopoulos --- layer/present_timing_api.cpp | 2 +- layer/wsi_layer_experimental.hpp | 9 +++++ wsi/extensions/present_timing.cpp | 66 +++++++++++++++++++++++-------- wsi/extensions/present_timing.hpp | 9 +++-- 4 files changed, 65 insertions(+), 21 deletions(-) diff --git a/layer/present_timing_api.cpp b/layer/present_timing_api.cpp index 62b75d5..5db043c 100644 --- a/layer/present_timing_api.cpp +++ b/layer/present_timing_api.cpp @@ -117,6 +117,6 @@ wsi_layer_vkGetPastPresentationTimingEXT( } auto *sc = reinterpret_cast(pPastPresentationTimingInfo->swapchain); auto *ext = sc->get_swapchain_extension(true); - return ext->get_past_presentation_results(pPastPresentationTimingProperties); + return ext->get_past_presentation_results(pPastPresentationTimingProperties, pPastPresentationTimingInfo->flags); } #endif /* VULKAN_WSI_LAYER_EXPERIMENTAL */ diff --git a/layer/wsi_layer_experimental.hpp b/layer/wsi_layer_experimental.hpp index 972ae64..27eac54 100644 --- a/layer/wsi_layer_experimental.hpp +++ b/layer/wsi_layer_experimental.hpp @@ -137,10 +137,19 @@ typedef struct VkPastPresentationTimingPropertiesEXT VkPastPresentationTimingEXT *pPresentationTimings; } VkPastPresentationTimingPropertiesEXT; +typedef VkFlags VkPastPresentationTimingFlagsEXT; + +typedef enum VkPastPresentationTimingFlagBitsEXT +{ + VK_PAST_PRESENTATION_TIMING_ALLOW_PARTIAL_RESULTS_BIT_EXT = 0x00000001, + VK_PAST_PRESENTATION_TIMING_ALLOW_OUT_OF_ORDER_RESULTS_BIT_EXT = 0x00000002, +} VkPastPresentationTimingFlagBitsEXT; + typedef struct VkPastPresentationTimingInfoEXT { VkStructureType sType; const void *pNext; + VkPastPresentationTimingFlagsEXT flags; VkSwapchainKHR swapchain; } VkPastPresentationTimingInfoEXT; diff --git a/wsi/extensions/present_timing.cpp b/wsi/extensions/present_timing.cpp index 12fd1c3..f2ef318 100644 --- a/wsi/extensions/present_timing.cpp +++ b/wsi/extensions/present_timing.cpp @@ -179,7 +179,7 @@ VkResult wsi_ext_present_timing::query_present_queue_end_timings() VkResult wsi_ext_present_timing::present_timing_queue_set_size(size_t queue_size) { const std::lock_guard lock(m_queue_mutex); - if (present_timing_get_num_outstanding_results() > queue_size) + if (m_queue.size() > queue_size) { return VK_NOT_READY; } @@ -283,21 +283,27 @@ VkSemaphore wsi_ext_present_timing::get_image_present_semaphore(uint32_t image_i return m_present_semaphore[image_index]; } -uint32_t wsi_ext_present_timing::get_num_available_results() +uint32_t wsi_ext_present_timing::get_num_available_results(VkPastPresentationTimingFlagsEXT flags) { uint32_t num_pending_results = 0; + const bool allow_partial = (flags & VK_PAST_PRESENTATION_TIMING_ALLOW_PARTIAL_RESULTS_BIT_EXT) != 0; + const bool allow_out_of_order = (flags & VK_PAST_PRESENTATION_TIMING_ALLOW_OUT_OF_ORDER_RESULTS_BIT_EXT) != 0; for (auto &slot : m_queue) { - if (slot.has_completed_stages()) + if (slot.has_completed_stages(allow_partial)) { num_pending_results++; } + else if (!allow_out_of_order) + { + break; + } } return num_pending_results; } VkResult wsi_ext_present_timing::get_past_presentation_results( - VkPastPresentationTimingPropertiesEXT *past_present_timing_properties) + VkPastPresentationTimingPropertiesEXT *past_present_timing_properties, VkPastPresentationTimingFlagsEXT flags) { const std::lock_guard lock(m_queue_mutex); @@ -306,7 +312,7 @@ VkResult wsi_ext_present_timing::get_past_presentation_results( TRY_LOG_CALL(query_present_queue_end_timings()); if (past_present_timing_properties->pPresentationTimings == nullptr) { - past_present_timing_properties->presentationTimingCount = get_num_available_results(); + past_present_timing_properties->presentationTimingCount = get_num_available_results(flags); return VK_SUCCESS; } @@ -317,6 +323,8 @@ VkResult wsi_ext_present_timing::get_past_presentation_results( uint64_t in = 0; uint64_t out = 0; uint64_t removed_entries = 0; + const bool allow_partial = (flags & VK_PAST_PRESENTATION_TIMING_ALLOW_PARTIAL_RESULTS_BIT_EXT) != 0; + const bool allow_out_of_order = (flags & VK_PAST_PRESENTATION_TIMING_ALLOW_OUT_OF_ORDER_RESULTS_BIT_EXT) != 0; /* * Single forward pass over the caller-supplied pPresentationTimings array: * @@ -341,8 +349,21 @@ VkResult wsi_ext_present_timing::get_past_presentation_results( return (e.m_present_id == present_id) && zero_extra_cond; }); - if (slot != m_queue.end() && slot->has_completed_stages()) + if (slot != m_queue.end()) { + if (!slot->has_completed_stages(allow_partial)) + { + if (allow_out_of_order) + { + in++; + continue; + } + else + { + break; + } + } + if (present_id == 0) { seen_zero = true; @@ -370,7 +391,7 @@ VkResult wsi_ext_present_timing::get_past_presentation_results( past_present_timing_properties->presentationTimingCount = out; - const bool incomplete = (out < in) || (out < (get_num_available_results() + removed_entries)); + const bool incomplete = (out < in) || (out < (get_num_available_results(flags) + removed_entries)); return incomplete ? VK_INCOMPLETE : VK_SUCCESS; } @@ -404,11 +425,14 @@ swapchain_presentation_entry::swapchain_presentation_entry(VkPresentStageFlagsEX } } -bool swapchain_presentation_entry::is_complete(VkPresentStageFlagBitsEXT stage) +std::optional swapchain_presentation_entry::is_complete(VkPresentStageFlagBitsEXT 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) : - false; + if (!stage_timing_optional.has_value()) + { + return std::nullopt; + } + return stage_timing_optional->get().m_set.load(std::memory_order_relaxed); } bool swapchain_presentation_entry::is_pending(VkPresentStageFlagBitsEXT stage) @@ -426,12 +450,22 @@ bool swapchain_presentation_entry::has_outstanding_stages() is_pending(VK_PRESENT_STAGE_IMAGE_FIRST_PIXEL_VISIBLE_BIT_EXT)); } -bool swapchain_presentation_entry::has_completed_stages() +bool swapchain_presentation_entry::has_completed_stages(bool allow_partial) { - return (is_complete(VK_PRESENT_STAGE_QUEUE_OPERATIONS_END_BIT_EXT) || - is_complete(VK_PRESENT_STAGE_IMAGE_LATCHED_BIT_EXT) || - is_complete(VK_PRESENT_STAGE_IMAGE_FIRST_PIXEL_OUT_BIT_EXT) || - is_complete(VK_PRESENT_STAGE_IMAGE_FIRST_PIXEL_VISIBLE_BIT_EXT)); + bool partial_result = false; + bool non_partial_result = true; + + for (const auto &stage : g_present_stages) + { + auto complete = is_complete(stage); + if (complete.has_value()) + { + partial_result |= complete.value(); + non_partial_result &= complete.value(); + } + } + + return allow_partial ? partial_result : non_partial_result; } std::optional> swapchain_presentation_entry::get_stage_timing( @@ -489,7 +523,7 @@ void swapchain_presentation_entry::populate(VkPastPresentationTimingEXT &timing) } } - /* If atleast one entry is made to the timings, update the other fields. */ + /* If at least one entry is made to the timings, update the other fields. */ if (stage_index != 0) { timing.presentId = m_present_id; diff --git a/wsi/extensions/present_timing.hpp b/wsi/extensions/present_timing.hpp index a47adcf..8abacd8 100644 --- a/wsi/extensions/present_timing.hpp +++ b/wsi/extensions/present_timing.hpp @@ -149,7 +149,7 @@ struct swapchain_presentation_entry * * @return true when the stage is completed and false otherwise. */ - bool is_complete(VkPresentStageFlagBitsEXT stage); + std::optional is_complete(VkPresentStageFlagBitsEXT stage); /** * @brief Check if a present stage is pending. @@ -172,7 +172,7 @@ struct swapchain_presentation_entry * * @return true when there are completed stages and false otherwise. */ - bool has_completed_stages(); + bool has_completed_stages(bool allow_partial); /** * @brief Populate a VkPastPresentationTimingEXT object. @@ -380,7 +380,8 @@ public: * * @return VK_SUCCESS when the requested results are returned, VK_INCOMPLETE when returning fewer results. */ - VkResult get_past_presentation_results(VkPastPresentationTimingPropertiesEXT *past_present_timing_properties); + VkResult get_past_presentation_results(VkPastPresentationTimingPropertiesEXT *past_present_timing_properties, + VkPastPresentationTimingFlagsEXT flags); /** * @brief Get the swapchain time domains @@ -502,7 +503,7 @@ private: * * @return The number of available results. */ - uint32_t get_num_available_results(); + uint32_t get_num_available_results(VkPastPresentationTimingFlagsEXT flags); /** * @pre Caller must hold m_queue_mutex