Add a function for empty queue submit operations

Adds a helper function in synchronization.hpp, which makes an empty
vkQueueSubmit in order to chain wait with signal semaphores and fences.
This function is used in submit_wait_request and
fence_sync::set_payload.

Introduces queue_submit_semaphores for grouping the signal and wait
semaphores.

Change-Id: I6107a29f3410fad8250f998b0e4c2052ed1923b8
Signed-off-by: Iason Paraskevopoulos <iason.paraskevopoulos@arm.com>
Signed-off-by: Fufu Fang <fufu.fang@arm.com>
This commit is contained in:
Iason Paraskevopoulos 2024-04-09 16:04:28 +01:00 committed by Fufu Fang
parent d2b8eb3135
commit 01b4e9aeff
9 changed files with 103 additions and 97 deletions

View file

@ -37,6 +37,7 @@
#include "private_data.hpp"
#include "swapchain_api.hpp"
#include <util/helpers.hpp>
#include "wsi/synchronization.hpp"
VWL_VKAPI_CALL(VkResult)
wsi_layer_vkCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pSwapchainCreateInfo,
@ -138,31 +139,11 @@ static VkResult submit_wait_request(VkQueue queue, const VkPresentInfoKHR &prese
swapchain_semaphores[i] = swapchain->get_image_present_semaphore(present_info.pImageIndices[i]);
}
util::vector<VkPipelineStageFlags> pipeline_stage_flags{ util::allocator(device_data.get_allocator(),
VK_SYSTEM_ALLOCATION_SCOPE_COMMAND) };
if (!pipeline_stage_flags.try_resize(present_info.waitSemaphoreCount))
{
return VK_ERROR_OUT_OF_HOST_MEMORY;
}
wsi::queue_submit_semaphores semaphores = { present_info.pWaitSemaphores, present_info.waitSemaphoreCount,
swapchain_semaphores.data(),
static_cast<uint32_t>(swapchain_semaphores.size()) };
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(),
};
TRY(device_data.disp.QueueSubmit(queue, 1, &submit_info, VK_NULL_HANDLE));
TRY(wsi::sync_queue_submit(device_data, queue, VK_NULL_HANDLE, semaphores));
return VK_SUCCESS;
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017-2022, 2024 Arm Limited.
* Copyright (c) 2017-2024 Arm Limited.
*
* SPDX-License-Identifier: MIT
*
@ -50,9 +50,7 @@ struct image_data
swapchain::swapchain(layer::device_private_data &dev_data, const VkAllocationCallbacks *pAllocator)
: wsi::swapchain_base(dev_data, pAllocator)
#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN
, m_image_compression_control
{
}
, m_image_compression_control{}
#endif
{
}
@ -197,11 +195,11 @@ void swapchain::destroy_image(wsi::swapchain_image &image)
}
}
VkResult swapchain::image_set_present_payload(swapchain_image &image, VkQueue queue, const VkSemaphore *sem_payload,
uint32_t sem_count)
VkResult swapchain::image_set_present_payload(swapchain_image &image, VkQueue queue,
const queue_submit_semaphores &semaphores)
{
auto data = reinterpret_cast<image_data *>(image.data);
return data->present_fence.set_payload(queue, sem_payload, sem_count);
return data->present_fence.set_payload(queue, semaphores);
}
VkResult swapchain::image_wait_present(swapchain_image &image, uint64_t timeout)

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017-2019, 2021-2022, 2024 Arm Limited.
* Copyright (c) 2017-2024 Arm Limited.
*
* SPDX-License-Identifier: MIT
*
@ -86,8 +86,8 @@ protected:
*/
void destroy_image(wsi::swapchain_image &image);
VkResult image_set_present_payload(swapchain_image &image, VkQueue queue, const VkSemaphore *sem_payload,
uint32_t sem_count) override;
VkResult image_set_present_payload(swapchain_image &image, VkQueue queue,
const queue_submit_semaphores &semaphores) override;
VkResult image_wait_present(swapchain_image &image, uint64_t timeout) override;

View file

@ -489,25 +489,15 @@ VkResult swapchain_base::acquire_next_image(uint64_t timeout, VkSemaphore semaph
}
/* Fallback for when importing fence/semaphore sync FDs is unsupported by the ICD. */
VkResult retval = VK_SUCCESS;
if (VK_NULL_HANDLE != semaphore || VK_NULL_HANDLE != fence)
{
VkSubmitInfo submit = { VK_STRUCTURE_TYPE_SUBMIT_INFO };
queue_submit_semaphores semaphores = {
nullptr,
0,
(semaphore != VK_NULL_HANDLE) ? &semaphore : nullptr,
(semaphore != VK_NULL_HANDLE) ? 1u : 0,
};
TRY(sync_queue_submit(m_device_data, m_queue, fence, semaphores));
if (VK_NULL_HANDLE != semaphore)
{
submit.signalSemaphoreCount = 1;
submit.pSignalSemaphores = &semaphore;
}
submit.commandBufferCount = 0;
submit.pCommandBuffers = nullptr;
retval = m_device_data.disp.QueueSubmit(m_queue, 1, &submit, fence);
assert(retval == VK_SUCCESS);
}
return retval;
return VK_SUCCESS;
}
VkResult swapchain_base::get_swapchain_images(uint32_t *swapchain_image_count, VkImage *swapchain_images)
@ -611,7 +601,10 @@ VkResult swapchain_base::queue_present(VkQueue queue, const VkPresentInfoKHR *pr
TRY_LOG_CALL(image_wait_present(m_swapchain_images[image_index], WAIT_PRESENT_TIMEOUT));
}
TRY_LOG_CALL(image_set_present_payload(m_swapchain_images[image_index], queue, wait_semaphores, sem_count));
queue_submit_semaphores semaphores = { wait_semaphores, sem_count, nullptr, 0 };
TRY_LOG_CALL(image_set_present_payload(m_swapchain_images[image_index], queue, semaphores));
TRY(notify_presentation_engine(image_index));
return VK_SUCCESS;

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017-2022, 2024 Arm Limited.
* Copyright (c) 2017-2024 Arm Limited.
*
* SPDX-License-Identifier: MIT
*
@ -460,13 +460,12 @@ protected:
*
* @param[in] image The swapchain image for which to set a present payload.
* @param queue A Vulkan queue that can be used for any Vulkan commands needed.
* @param[in] sem_payload Array of Vulkan semaphores that constitute the payload.
* @param sem_count Number of elements in @p sem_payload
* @param[in] semaphores The wait and signal semaphores and their number of elements.
*
* @return VK_SUCCESS on success or an error code otherwise.
*/
virtual VkResult image_set_present_payload(swapchain_image &image, VkQueue queue, const VkSemaphore *sem_payload,
uint32_t sem_count) = 0;
virtual VkResult image_set_present_payload(swapchain_image &image, VkQueue queue,
const queue_submit_semaphores &semaphores) = 0;
/**
* @brief Waits for the present payload of an image if necessary.

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021-2023 Arm Limited.
* Copyright (c) 2021-2024 Arm Limited.
*
* SPDX-License-Identifier: MIT
*
@ -30,6 +30,7 @@
#include "synchronization.hpp"
#include "layer/private_data.hpp"
#include "util/helpers.hpp"
#include <algorithm>
@ -93,7 +94,7 @@ VkResult fence_sync::wait_payload(uint64_t timeout)
return res;
}
VkResult fence_sync::set_payload(VkQueue queue, const VkSemaphore *sem_payload, uint32_t sem_count)
VkResult fence_sync::set_payload(VkQueue queue, const queue_submit_semaphores &semaphores)
{
VkResult result = dev->disp.ResetFences(dev->device, 1, &fence);
if (result != VK_SUCCESS)
@ -101,32 +102,8 @@ VkResult fence_sync::set_payload(VkQueue queue, const VkSemaphore *sem_payload,
return result;
}
has_payload = false;
/* When the semaphore that comes in is signalled, we know that all work is done. So, we do not
* want to block any future Vulkan queue work on it. So, we pass in BOTTOM_OF_PIPE bit as the
* wait flag.
*/
VkPipelineStageFlags pipeline_stage_flag = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
VkPipelineStageFlags *pipeline_stage_flag_data = &pipeline_stage_flag;
util::vector<VkPipelineStageFlags> pipeline_stage_flags_vector{ util::allocator(
dev->get_allocator(), VK_SYSTEM_ALLOCATION_SCOPE_COMMAND) };
/* Try to avoid memory allocation for single semaphore */
if (sem_count > 1)
{
if (!pipeline_stage_flags_vector.try_resize(sem_count))
{
return VK_ERROR_OUT_OF_HOST_MEMORY;
}
std::fill(pipeline_stage_flags_vector.begin(), pipeline_stage_flags_vector.end(),
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT);
pipeline_stage_flag_data = pipeline_stage_flags_vector.data();
}
VkSubmitInfo submit_info = {
VK_STRUCTURE_TYPE_SUBMIT_INFO, nullptr, sem_count, sem_payload, pipeline_stage_flag_data, 0, nullptr, 0, nullptr
};
result = dev->disp.QueueSubmit(queue, 1, &submit_info, fence);
result = sync_queue_submit(*dev, queue, fence, semaphores);
if (result == VK_SUCCESS)
{
has_payload = true;
@ -192,4 +169,42 @@ std::optional<util::fd_owner> sync_fd_fence_sync::export_sync_fd()
return std::nullopt;
}
VkResult sync_queue_submit(const layer::device_private_data &device, VkQueue queue, VkFence fence,
const queue_submit_semaphores &semaphores)
{
/* When the semaphore that comes in is signalled, we know that all work is done. So, we do not
* want to block any future Vulkan queue work on it. So, we pass in BOTTOM_OF_PIPE bit as the
* wait flag.
*/
VkPipelineStageFlags pipeline_stage_flag = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
VkPipelineStageFlags *pipeline_stage_flag_data = &pipeline_stage_flag;
util::vector<VkPipelineStageFlags> pipeline_stage_flags_vector{ util::allocator(
device.get_allocator(), VK_SYSTEM_ALLOCATION_SCOPE_COMMAND) };
/* Try to avoid memory allocation for single semaphore */
if (semaphores.wait_semaphores_count > 1)
{
if (!pipeline_stage_flags_vector.try_resize(semaphores.wait_semaphores_count))
{
return VK_ERROR_OUT_OF_HOST_MEMORY;
}
std::fill(pipeline_stage_flags_vector.begin(), pipeline_stage_flags_vector.end(),
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT);
pipeline_stage_flag_data = pipeline_stage_flags_vector.data();
}
VkSubmitInfo submit_info = { VK_STRUCTURE_TYPE_SUBMIT_INFO,
nullptr,
semaphores.wait_semaphores_count,
semaphores.wait_semaphores,
pipeline_stage_flag_data,
0,
nullptr,
semaphores.signal_semaphores_count,
semaphores.signal_semaphores };
TRY(device.disp.QueueSubmit(queue, 1, &submit_info, fence));
return VK_SUCCESS;
}
} /* namespace wsi */

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021-2022, 2024 Arm Limited.
* Copyright (c) 2021-2024 Arm Limited.
*
* SPDX-License-Identifier: MIT
*
@ -45,6 +45,14 @@ class instance_private_data;
namespace wsi
{
struct queue_submit_semaphores
{
const VkSemaphore *wait_semaphores;
uint32_t wait_semaphores_count;
const VkSemaphore *signal_semaphores;
uint32_t signal_semaphores_count;
};
/**
* Synchronization using a Vulkan Fence object.
*/
@ -86,13 +94,12 @@ public:
*
* @note This method is not threadsafe.
*
* @param queue The Vulkan queue that may be used to submit synchronization commands.
* @param[in] sem_payload Array of Vulkan Semaphores that comprise the payload.
* @param sem_count Number of elements in @p sem_payload.
* @param queue The Vulkan queue that may be used to submit synchronization commands.
* @param semaphores The wait and signal semaphores.
*
* @return VK_SUCCESS on success or other error code on failing to set the payload.
*/
VkResult set_payload(VkQueue queue, const VkSemaphore *sem_payload, uint32_t sem_count);
VkResult set_payload(VkQueue queue, const queue_submit_semaphores &semaphores);
protected:
/**
@ -175,4 +182,17 @@ private:
sync_fd_fence_sync(layer::device_private_data &device, VkFence vk_fence);
};
/**
* @brief Submit an empty queue operation for synchronization.
*
* @param device The device private data for the fence.
* @param queue The Vulkan queue that may be used to submit synchronization commands.
* @param fence The fence to be signalled, it could be VK_NULL_HANDLE in the absence
* of a fence to be signalled.
* @param semaphores The wait and signal semaphores.
*
* @return VK_SUCCESS on success, an appropiate error code otherwise.
*/
VkResult sync_queue_submit(const layer::device_private_data &device, VkQueue queue, VkFence fence,
const queue_submit_semaphores &semaphores);
} /* namespace wsi */

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017-2019, 2021-2024 Arm Limited.
* Copyright (c) 2017-2024 Arm Limited.
*
* SPDX-License-Identifier: MIT
*
@ -552,11 +552,11 @@ VkResult swapchain::get_free_buffer(uint64_t *timeout)
}
}
VkResult swapchain::image_set_present_payload(swapchain_image &image, VkQueue queue, const VkSemaphore *sem_payload,
uint32_t sem_count)
VkResult swapchain::image_set_present_payload(swapchain_image &image, VkQueue queue,
const queue_submit_semaphores &semaphores)
{
auto image_data = reinterpret_cast<wayland_image_data *>(image.data);
return image_data->present_fence.set_payload(queue, sem_payload, sem_count);
return image_data->present_fence.set_payload(queue, semaphores);
}
VkResult swapchain::image_wait_present(swapchain_image &, uint64_t)

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017-2019, 2021-2022, 2024 Arm Limited.
* Copyright (c) 2017-2024 Arm Limited.
*
* SPDX-License-Identifier: MIT
*
@ -137,8 +137,8 @@ protected:
*/
VkResult get_free_buffer(uint64_t *timeout) override;
VkResult image_set_present_payload(swapchain_image &image, VkQueue queue, const VkSemaphore *sem_payload,
uint32_t sem_count) override;
VkResult image_set_present_payload(swapchain_image &image, VkQueue queue,
const queue_submit_semaphores &semaphores) override;
VkResult image_wait_present(swapchain_image &image, uint64_t timeout) override;