diff --git a/layer/swapchain_api.cpp b/layer/swapchain_api.cpp index 3183a16..d5222eb 100644 --- a/layer/swapchain_api.cpp +++ b/layer/swapchain_api.cpp @@ -37,6 +37,7 @@ #include "private_data.hpp" #include "swapchain_api.hpp" #include +#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 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(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(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; } diff --git a/wsi/headless/swapchain.cpp b/wsi/headless/swapchain.cpp index 59f9231..508c243 100644 --- a/wsi/headless/swapchain.cpp +++ b/wsi/headless/swapchain.cpp @@ -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); - 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) diff --git a/wsi/headless/swapchain.hpp b/wsi/headless/swapchain.hpp index 3d0573d..b247924 100644 --- a/wsi/headless/swapchain.hpp +++ b/wsi/headless/swapchain.hpp @@ -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; diff --git a/wsi/swapchain_base.cpp b/wsi/swapchain_base.cpp index d5654df..49a41dc 100644 --- a/wsi/swapchain_base.cpp +++ b/wsi/swapchain_base.cpp @@ -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; diff --git a/wsi/swapchain_base.hpp b/wsi/swapchain_base.hpp index 553de83..8ca729b 100644 --- a/wsi/swapchain_base.hpp +++ b/wsi/swapchain_base.hpp @@ -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. diff --git a/wsi/synchronization.cpp b/wsi/synchronization.cpp index 99692bc..c5bd123 100644 --- a/wsi/synchronization.cpp +++ b/wsi/synchronization.cpp @@ -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 @@ -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 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 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 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 */ diff --git a/wsi/synchronization.hpp b/wsi/synchronization.hpp index 2ad08f1..f816e14 100644 --- a/wsi/synchronization.hpp +++ b/wsi/synchronization.hpp @@ -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 */ diff --git a/wsi/wayland/swapchain.cpp b/wsi/wayland/swapchain.cpp index 112dbce..371fbea 100644 --- a/wsi/wayland/swapchain.cpp +++ b/wsi/wayland/swapchain.cpp @@ -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(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) diff --git a/wsi/wayland/swapchain.hpp b/wsi/wayland/swapchain.hpp index 41c14bb..d9fcc8b 100644 --- a/wsi/wayland/swapchain.hpp +++ b/wsi/wayland/swapchain.hpp @@ -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;