Merge 'Handle VkPresentTimingsInfoEXT' into 'main'

See merge request mesa/vulkan-wsi-layer!116
This commit is contained in:
Rosen Zhelev 2024-10-16 09:40:28 +00:00
commit e8cacef0de
5 changed files with 153 additions and 3 deletions

View file

@ -29,6 +29,7 @@
*/
#include <cassert>
#include "wsi_layer_experimental.hpp"
#include "wsi/swapchain_base.hpp"
#if VULKAN_WSI_LAYER_EXPERIMENTAL
@ -38,8 +39,9 @@
VWL_VKAPI_CALL(VkResult)
wsi_layer_vkSetSwapchainPresentTimingQueueSizeEXT(VkDevice device, VkSwapchainKHR swapchain, uint32_t size) VWL_API_POST
{
VkResult result = VK_SUCCESS;
return result;
assert(swapchain != VK_NULL_HANDLE);
auto *sc = reinterpret_cast<wsi::swapchain_base *>(swapchain);
return sc->presentation_timing_queue_set_size(size);
}
/**

View file

@ -187,10 +187,17 @@ wsi_layer_vkQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo)
VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_FENCE_INFO_EXT, present_info->pNext);
const auto swapchain_present_mode_info = util::find_extension<VkSwapchainPresentModeInfoEXT>(
VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_MODE_INFO_EXT, present_info->pNext);
#if VULKAN_WSI_LAYER_EXPERIMENTAL
const auto present_timings_info =
util::find_extension<VkPresentTimingsInfoEXT>(VK_STRUCTURE_TYPE_PRESENT_TIMINGS_INFO_EXT, present_info->pNext);
if (present_timings_info)
{
assert(present_timings_info->swapchainCount == pPresentInfo->swapchainCount);
}
#endif
for (uint32_t i = 0; i < pPresentInfo->swapchainCount; ++i)
{
VkSwapchainKHR swapc = pPresentInfo->pSwapchains[i];
auto *sc = reinterpret_cast<wsi::swapchain_base *>(swapc);
assert(sc != nullptr);
@ -213,6 +220,13 @@ wsi_layer_vkQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo)
present_params.use_image_present_semaphore = use_image_present_semaphore;
present_params.handle_present_frame_boundary_event = frame_boundary_event_handled;
#if VULKAN_WSI_LAYER_EXPERIMENTAL
if (present_timings_info)
{
present_params.present_timing_info = &(present_timings_info->pTimingInfos[i]);
}
#endif
VkResult res = sc->queue_present(queue, present_info, present_params);
if (pPresentInfo->pResults != nullptr)
{

View file

@ -368,6 +368,30 @@ public:
return false;
}
}
/**
* @brief Like std::vector::reserve but doesn't throw on out of memory errors.
*
* @param size The new capacity of the container. Same as std::vector::reserve.
* @return true If the container was resized successfuly.
* @return false If the host has run out of memory or when there is a length error.
*/
bool try_reserve(size_t size) noexcept
{
try
{
base::reserve(size);
return true;
}
catch (std::bad_alloc &e)
{
return false;
}
catch (const std::length_error &e)
{
return false;
}
}
};
} /* namespace util */

View file

@ -224,6 +224,9 @@ swapchain_base::swapchain_base(layer::device_private_data &dev_data, const VkAll
, m_error_state(VK_NOT_READY)
, m_started_presenting(false)
, m_frame_boundary_handler(m_device_data)
#if VULKAN_WSI_LAYER_EXPERIMENTAL
, m_presentation_timing(m_allocator)
#endif
{
}
@ -669,6 +672,22 @@ VkResult swapchain_base::notify_presentation_engine(const pending_present_reques
VkResult swapchain_base::queue_present(VkQueue queue, const VkPresentInfoKHR *present_info,
const swapchain_presentation_parameters &submit_info)
{
#if VULKAN_WSI_LAYER_EXPERIMENTAL
if (submit_info.present_timing_info)
{
wsi::swapchain_presentation_entry presentation_entry = {};
presentation_entry.present_id = submit_info.pending_present.present_id;
if ((m_presentation_timing.size()) >= m_presentation_timing.capacity())
{
return VK_ERROR_PRESENT_TIMING_QUEUE_FULL_EXT;
}
if (!m_presentation_timing.try_push_back(presentation_entry))
{
return VK_ERROR_OUT_OF_HOST_MEMORY;
}
}
#endif
if (submit_info.switch_presentation_mode)
{
@ -844,4 +863,48 @@ void swapchain_base::set_present_id(uint64_t value)
}
}
#if VULKAN_WSI_LAYER_EXPERIMENTAL
VkResult swapchain_base::presentation_timing_queue_set_size(size_t queue_size)
{
if (presentation_timing_get_num_outstanding_results() > queue_size)
{
return VK_NOT_READY;
}
util::vector<swapchain_presentation_entry> presentation_timing(
util::allocator(m_allocator, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE));
if (!presentation_timing.try_reserve(queue_size))
{
return VK_ERROR_OUT_OF_HOST_MEMORY;
}
for (auto iter : m_presentation_timing)
{
if (iter.is_outstanding)
{
if (!presentation_timing.try_push_back(iter))
{
return VK_ERROR_OUT_OF_HOST_MEMORY;
}
}
}
m_presentation_timing.swap(presentation_timing);
return VK_SUCCESS;
}
size_t swapchain_base::presentation_timing_get_num_outstanding_results()
{
size_t num_outstanding = 0;
for (const auto &iter : m_presentation_timing)
{
if (iter.is_outstanding)
{
num_outstanding++;
}
}
return num_outstanding;
}
#endif
} /* namespace wsi */

View file

@ -110,8 +110,29 @@ struct swapchain_presentation_parameters
* to underlying layers/ICD if the feature is enabled.
*/
VkBool32 handle_present_frame_boundary_event{ true };
#if VULKAN_WSI_LAYER_EXPERIMENTAL
/**
* Pointer to the present timing info.
*/
const VkPresentTimingInfoEXT *present_timing_info{ nullptr };
#endif
};
#if VULKAN_WSI_LAYER_EXPERIMENTAL
struct swapchain_presentation_entry
{
/**
* Whether this entry is an outstanding result or not.
*/
bool is_outstanding{ false };
/**
* The present id.
*/
uint64_t present_id{ 0 };
};
#endif
#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN
struct image_compression_control_params
{
@ -274,6 +295,18 @@ public:
*/
VkResult is_bind_allowed(uint32_t image_index) const;
#if VULKAN_WSI_LAYER_EXPERIMENTAL
/**
* @brief Set the size for the presentation timing queue
*
* @param queue_size The new queue size to set.
*
* @return VK_SUCCESS on success, VK_ERROR_OUT_OF_HOST_MEMORY when there is not enough memory, VK_NOT_READY otherwise.
* .
*/
VkResult presentation_timing_queue_set_size(size_t queue_size);
#endif
protected:
layer::device_private_data &m_device_data;
@ -710,6 +743,20 @@ private:
*
*/
frame_boundary_handler m_frame_boundary_handler;
#if VULKAN_WSI_LAYER_EXPERIMENTAL
/**
* @brief Queue for presentation timings.
*/
util::vector<swapchain_presentation_entry> m_presentation_timing;
/**
* @brief Get the size of the presentation timing queue
*
* @return queue size of the presentation timestamp queue.
*/
size_t presentation_timing_get_num_outstanding_results();
#endif
};
} /* namespace wsi */