mirror of
https://gitlab.freedesktop.org/mesa/vulkan-wsi-layer.git
synced 2026-01-06 21:10:20 +01:00
Handle present request for multiple swapchains
Adds an additional semaphore for every swapchain image to be waited for before the present engine access an image. During a present request with multiple swapchains, these semaphores are grouped together and are signaled after the incoming pWaitSemaphores signal. Signed-off-by: Iason Paraskevopoulos <iason.paraskevopoulos@arm.com> Change-Id: I94cabbf5f7d9a45dceef60eec7773b48ccc32078
This commit is contained in:
parent
02203b8412
commit
17204773df
4 changed files with 104 additions and 4 deletions
|
|
@ -120,6 +120,8 @@ struct instance_dispatch_table
|
|||
REQUIRED(FreeMemory) \
|
||||
REQUIRED(CreateFence) \
|
||||
REQUIRED(DestroyFence) \
|
||||
REQUIRED(CreateSemaphore) \
|
||||
REQUIRED(DestroySemaphore) \
|
||||
REQUIRED(ResetFences) \
|
||||
REQUIRED(WaitForFences) \
|
||||
REQUIRED(DestroyDevice) \
|
||||
|
|
|
|||
|
|
@ -127,6 +127,54 @@ VKAPI_ATTR VkResult wsi_layer_vkAcquireNextImageKHR(VkDevice device, VkSwapchain
|
|||
return sc->acquire_next_image(timeout, semaphore, fence, pImageIndex);
|
||||
}
|
||||
|
||||
static VkResult submit_wait_request(VkQueue queue, const VkPresentInfoKHR &present_info,
|
||||
layer::device_private_data &device_data)
|
||||
{
|
||||
util::vector<VkSemaphore> swapchain_semaphores{ util::allocator(device_data.get_allocator(),
|
||||
VK_SYSTEM_ALLOCATION_SCOPE_COMMAND) };
|
||||
if (!swapchain_semaphores.try_resize(present_info.swapchainCount))
|
||||
{
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < present_info.swapchainCount; ++i)
|
||||
{
|
||||
auto swapchain = reinterpret_cast<wsi::swapchain_base *>(present_info.pSwapchains[i]);
|
||||
swapchain_semaphores[i] = swapchain->get_image_present_semaphore(present_info.pImageIndices[i]);
|
||||
}
|
||||
|
||||
util::vector<VkPipelineStageFlags> pipeline_stage_flags{ util::allocator::get_generic() };
|
||||
if (!pipeline_stage_flags.try_resize(present_info.waitSemaphoreCount))
|
||||
{
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < present_info.waitSemaphoreCount; ++i)
|
||||
{
|
||||
pipeline_stage_flags[i] = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
|
||||
}
|
||||
|
||||
VkSubmitInfo submit_info = {
|
||||
VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
||||
NULL,
|
||||
present_info.waitSemaphoreCount,
|
||||
present_info.pWaitSemaphores,
|
||||
pipeline_stage_flags.data(),
|
||||
0,
|
||||
NULL,
|
||||
static_cast<uint32_t>(swapchain_semaphores.size()),
|
||||
swapchain_semaphores.data(),
|
||||
};
|
||||
|
||||
VkResult result = device_data.disp.QueueSubmit(queue, 1, &submit_info, VK_NULL_HANDLE);
|
||||
if (result != VK_SUCCESS)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VKAPI_ATTR VkResult wsi_layer_vkQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo)
|
||||
{
|
||||
assert(queue != VK_NULL_HANDLE);
|
||||
|
|
@ -139,6 +187,20 @@ VKAPI_ATTR VkResult wsi_layer_vkQueuePresentKHR(VkQueue queue, const VkPresentIn
|
|||
return device_data.disp.QueuePresentKHR(queue, pPresentInfo);
|
||||
}
|
||||
|
||||
/* Avoid allocating on the heap when there is only one swapchain. */
|
||||
VkResult res = VK_SUCCESS;
|
||||
const VkPresentInfoKHR *present_info = pPresentInfo;
|
||||
if (pPresentInfo->swapchainCount > 1)
|
||||
{
|
||||
res = submit_wait_request(queue, *pPresentInfo, device_data);
|
||||
if (res != VK_SUCCESS)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
|
||||
present_info = nullptr;
|
||||
}
|
||||
|
||||
VkResult ret = VK_SUCCESS;
|
||||
for (uint32_t i = 0; i < pPresentInfo->swapchainCount; ++i)
|
||||
{
|
||||
|
|
@ -147,7 +209,7 @@ VKAPI_ATTR VkResult wsi_layer_vkQueuePresentKHR(VkQueue queue, const VkPresentIn
|
|||
wsi::swapchain_base *sc = reinterpret_cast<wsi::swapchain_base *>(swapc);
|
||||
assert(sc != nullptr);
|
||||
|
||||
VkResult res = sc->queue_present(queue, pPresentInfo, pPresentInfo->pImageIndices[i]);
|
||||
res = sc->queue_present(queue, present_info, pPresentInfo->pImageIndices[i]);
|
||||
|
||||
if (pPresentInfo->pResults != nullptr)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -199,7 +199,9 @@ VkResult swapchain_base::init(VkDevice device, const VkSwapchainCreateInfoKHR *s
|
|||
|
||||
/* Init image to invalid values. */
|
||||
if (!m_swapchain_images.try_resize(swapchain_create_info->minImageCount))
|
||||
{
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
|
||||
/* We have allocated images, we can call the platform init function if something needs to be done. */
|
||||
bool use_presentation_thread = true;
|
||||
|
|
@ -249,6 +251,15 @@ VkResult swapchain_base::init(VkDevice device, const VkSwapchainCreateInfoKHR *s
|
|||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
VkSemaphoreCreateInfo semaphore_info = {};
|
||||
semaphore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
|
||||
result = m_device_data.disp.CreateSemaphore(m_device, &semaphore_info, get_allocation_callbacks(),
|
||||
&img.present_semaphore);
|
||||
if (result != VK_SUCCESS)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
m_device_data.disp.GetDeviceQueue(m_device, 0, 0, &m_queue);
|
||||
|
|
@ -352,6 +363,8 @@ void swapchain_base::teardown()
|
|||
{
|
||||
/* Call implementation specific release */
|
||||
destroy_image(img);
|
||||
|
||||
m_device_data.disp.DestroySemaphore(m_device, img.present_semaphore, get_allocation_callbacks());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -481,8 +494,15 @@ VkResult swapchain_base::notify_presentation_engine(uint32_t image_index)
|
|||
VkResult swapchain_base::queue_present(VkQueue queue, const VkPresentInfoKHR *present_info, const uint32_t image_index)
|
||||
{
|
||||
|
||||
VkResult result = image_set_present_payload(m_swapchain_images[image_index], queue, present_info->pWaitSemaphores,
|
||||
present_info->waitSemaphoreCount);
|
||||
const VkSemaphore *wait_semaphores = &m_swapchain_images[image_index].present_semaphore;
|
||||
uint32_t sem_count = 1;
|
||||
if (present_info != nullptr)
|
||||
{
|
||||
wait_semaphores = present_info->pWaitSemaphores;
|
||||
sem_count = present_info->waitSemaphoreCount;
|
||||
}
|
||||
|
||||
VkResult result = image_set_present_payload(m_swapchain_images[image_index], queue, wait_semaphores, sem_count);
|
||||
if (result != VK_SUCCESS)
|
||||
{
|
||||
return result;
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ struct swapchain_image
|
|||
|
||||
VkImage image{VK_NULL_HANDLE};
|
||||
status status{swapchain_image::INVALID};
|
||||
VkSemaphore present_semaphore{ VK_NULL_HANDLE };
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -124,7 +125,10 @@ public:
|
|||
*
|
||||
* @param queue The queue to which the submission will be made to.
|
||||
*
|
||||
* @param pPresentInfo Information about the swapchain and image to be presented.
|
||||
* @param present_info Information about the swapchain and image to be presented.
|
||||
* If it is nullptr it means that the presentation request will wait on the
|
||||
* image's \p present_semaphore and not the semaphores that come with
|
||||
* \p present_info.
|
||||
*
|
||||
* @param imageIndex The index of the image to be presented.
|
||||
*
|
||||
|
|
@ -169,6 +173,18 @@ public:
|
|||
virtual VkResult bind_swapchain_image(VkDevice &device, const VkBindImageMemoryInfo *bind_image_mem_info,
|
||||
const VkBindImageMemorySwapchainInfoKHR *bind_sc_info) = 0;
|
||||
|
||||
/**
|
||||
* @brief Get image's present semaphore
|
||||
*
|
||||
* @param image_index Image's index
|
||||
*
|
||||
* @return the image's present_semaphore
|
||||
*/
|
||||
VkSemaphore get_image_present_semaphore(uint32_t image_index)
|
||||
{
|
||||
return m_swapchain_images[image_index].present_semaphore;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
layer::device_private_data &m_device_data;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue