mirror of
https://gitlab.freedesktop.org/mesa/vulkan-wsi-layer.git
synced 2025-12-28 08:30:10 +01:00
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:
parent
d2b8eb3135
commit
01b4e9aeff
9 changed files with 103 additions and 97 deletions
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue