Add support for VK_KHR_shared_presentable_image for headless backend

Support for VK_KHR_shared_presentable image added in swapchain_base.
Headless backend will report support for it through
vkGetPhysicalDeviceSurfacePresentModesKHR.

Signed-off-by: Dennis Wildmark <dennis.wildmark@arm.com>
Change-Id: Ibbbab0b8c8137fdd41df9889d7e183a8259c83ba
This commit is contained in:
Dennis Wildmark 2024-04-12 14:52:39 +02:00
parent fecfd94079
commit 8a74233de2
11 changed files with 130 additions and 32 deletions

View file

@ -180,6 +180,7 @@ if(BUILD_WSI_HEADLESS)
list(APPEND LINK_WSI_LIBS wsi_headless)
else()
list(APPEND JSON_COMMANDS COMMAND sed -i '/VK_EXT_headless_surface/d' ${CMAKE_CURRENT_BINARY_DIR}/VkLayer_window_system_integration.json)
list(APPEND JSON_COMMANDS COMMAND sed -i '/VK_KHR_shared_presentable_image/d' ${CMAKE_CURRENT_BINARY_DIR}/VkLayer_window_system_integration.json)
endif()
# Layer

View file

@ -17,6 +17,7 @@
{"name" : "VK_KHR_get_surface_capabilities2", "spec_version" : "1"}
],
"device_extensions": [
{"name": "VK_KHR_shared_presentable_image", "spec_version": "1", "entrypoints": ["vkGetSwapchainStatusKHR"]},
{"name": "VK_EXT_image_compression_control_swapchain", "spec_version": "1"},
{
"name": "VK_KHR_swapchain",

View file

@ -435,6 +435,11 @@ wsi_layer_vkGetDeviceProcAddr(VkDevice device, const char *funcName) VWL_API_POS
GET_PROC_ADDR(vkGetDeviceGroupPresentCapabilitiesKHR);
GET_PROC_ADDR(vkGetDeviceGroupSurfacePresentModesKHR);
}
if (layer::device_private_data::get(device).is_device_extension_enabled(
VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME))
{
GET_PROC_ADDR(vkGetSwapchainStatusKHR);
}
GET_PROC_ADDR(vkDestroyDevice);
GET_PROC_ADDR(vkCreateImage);

View file

@ -369,6 +369,8 @@ private:
EP(GetSwapchainImagesKHR, VK_KHR_SWAPCHAIN_EXTENSION_NAME, API_VERSION_MAX, false) \
EP(AcquireNextImageKHR, VK_KHR_SWAPCHAIN_EXTENSION_NAME, API_VERSION_MAX, false) \
EP(QueuePresentKHR, VK_KHR_SWAPCHAIN_EXTENSION_NAME, API_VERSION_MAX, false) \
/* VK_KHR_shared_presentable_image */ \
EP(GetSwapchainStatusKHR, VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME, API_VERSION_MAX, false) \
/* VK_KHR_device_group + VK_KHR_swapchain or */ \
/* 1.1 with VK_KHR_swapchain */ \
EP(AcquireNextImage2KHR, VK_KHR_DEVICE_GROUP_EXTENSION_NAME, VK_API_VERSION_1_1, false) \

View file

@ -382,3 +382,18 @@ wsi_layer_vkBindImageMemory2(VkDevice device, uint32_t bindInfoCount,
}
return endpoint_result;
}
VWL_VKAPI_CALL(VkResult)
wsi_layer_vkGetSwapchainStatusKHR(VkDevice device, VkSwapchainKHR swapchain) VWL_API_POST
{
auto &device_data = layer::device_private_data::get(device);
if (!device_data.layer_owns_swapchain(swapchain))
{
return device_data.disp.GetSwapchainStatusKHR(device, swapchain);
}
auto *sc = reinterpret_cast<wsi::swapchain_base *>(swapchain);
return sc->get_swapchain_status();
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2019 Arm Limited.
* Copyright (c) 2018-2019, 2024 Arm Limited.
*
* SPDX-License-Identifier: MIT
*
@ -76,3 +76,6 @@ wsi_layer_vkCreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo, c
VWL_VKAPI_CALL(VkResult)
wsi_layer_vkBindImageMemory2(VkDevice device, uint32_t bindInfoCount,
const VkBindImageMemoryInfo *pBindInfos) VWL_API_POST;
VWL_VKAPI_CALL(VkResult)
wsi_layer_vkGetSwapchainStatusKHR(VkDevice device, VkSwapchainKHR swapchain) VWL_API_POST;

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017-2019, 2021-2023 Arm Limited.
* Copyright (c) 2017-2019, 2021-2024 Arm Limited.
*
* SPDX-License-Identifier: MIT
*
@ -113,7 +113,12 @@ VkResult surface_properties::get_surface_present_modes(VkPhysicalDevice physical
UNUSED(physical_device);
UNUSED(surface);
static const std::array<VkPresentModeKHR, 2> modes = { VK_PRESENT_MODE_FIFO_KHR, VK_PRESENT_MODE_FIFO_RELAXED_KHR };
static const std::array<VkPresentModeKHR, 4> modes = {
VK_PRESENT_MODE_FIFO_KHR,
VK_PRESENT_MODE_FIFO_RELAXED_KHR,
VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR,
VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR,
};
return get_surface_present_modes_common(present_mode_count, present_modes, modes);
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017-2022 Arm Limited.
* Copyright (c) 2017-2022, 2024 Arm Limited.
*
* SPDX-License-Identifier: MIT
*
@ -50,7 +50,9 @@ 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
{
}
@ -61,6 +63,21 @@ swapchain::~swapchain()
teardown();
}
VkResult swapchain::init_platform(VkDevice device, const VkSwapchainCreateInfoKHR *swapchain_create_info,
bool &use_presentation_thread)
{
if (swapchain_create_info->presentMode == VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR)
{
use_presentation_thread = false;
}
else
{
use_presentation_thread = true;
}
return VK_SUCCESS;
}
VkResult swapchain::create_and_bind_swapchain_image(VkImageCreateInfo image_create, wsi::swapchain_image &image)
{
VkResult res = VK_SUCCESS;
@ -178,7 +195,6 @@ void swapchain::destroy_image(wsi::swapchain_image &image)
m_allocator.destroy(1, data);
image.data = nullptr;
}
}
VkResult swapchain::image_set_present_payload(swapchain_image &image, VkQueue queue, const VkSemaphore *sem_payload,

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017-2019, 2021-2022 Arm Limited.
* Copyright (c) 2017-2019, 2021-2022, 2024 Arm Limited.
*
* SPDX-License-Identifier: MIT
*
@ -57,11 +57,7 @@ protected:
* @brief Platform specific init
*/
VkResult init_platform(VkDevice device, const VkSwapchainCreateInfoKHR *swapchain_create_info,
bool &use_presentation_thread) override
{
use_presentation_thread = true;
return VK_SUCCESS;
};
bool &use_presentation_thread) override;
/**
* @brief Creates and binds a new swapchain image.
@ -109,7 +105,6 @@ protected:
const VkBindImageMemorySwapchainInfoKHR *bind_sc_info) override;
private:
#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN
VkImageCompressionControlEXT m_image_compression_control;
#endif

View file

@ -62,24 +62,47 @@ void swapchain_base::page_flip_thread()
*/
while (m_page_flip_thread_run)
{
/* Waiting for the page_flip_semaphore which will be signalled once there is an
* image to display.*/
if ((vk_res = m_page_flip_semaphore.wait(SEMAPHORE_TIMEOUT)) == VK_TIMEOUT)
{
/* Image is not ready yet. */
continue;
}
assert(vk_res == VK_SUCCESS);
/* We want to present the oldest queued for present image from our present queue,
* which we can find at the sc->pending_buffer_pool.head index. */
std::unique_lock<std::recursive_mutex> image_status_lock(m_image_status_mutex);
auto pending_index = m_pending_buffer_pool.pop_front();
assert(pending_index.has_value());
image_status_lock.unlock();
uint32_t image_index;
if (m_present_mode == VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR)
{
/* In continuous mode the application will only make one presentation request,
* therefore the page flip semaphore will only be signalled once. */
if (!m_first_present)
{
vk_res = VK_SUCCESS;
}
else if ((vk_res = m_page_flip_semaphore.wait(SEMAPHORE_TIMEOUT)) == VK_TIMEOUT)
{
/* Image is not ready yet. */
continue;
}
assert(vk_res == VK_SUCCESS);
/* For continuous mode there will be only one image in the swapchain.
* This image will always be used, and there is no pending state in this case. */
image_index = 0;
}
else
{
/* Waiting for the page_flip_semaphore which will be signalled once there is an
* image to display.*/
if ((vk_res = m_page_flip_semaphore.wait(SEMAPHORE_TIMEOUT)) == VK_TIMEOUT)
{
/* Image is not ready yet. */
continue;
}
/* We want to present the oldest queued for present image from our present queue,
* which we can find at the sc->pending_buffer_pool.head index. */
std::unique_lock<std::recursive_mutex> image_status_lock(m_image_status_mutex);
auto pending_index = m_pending_buffer_pool.pop_front();
assert(pending_index.has_value());
image_index = *pending_index;
}
/* We may need to wait for the payload of the present sync of the oldest pending image to be finished. */
while ((vk_res = image_wait_present(sc_images[*pending_index], timeout)) == VK_TIMEOUT)
while ((vk_res = image_wait_present(sc_images[image_index], timeout)) == VK_TIMEOUT)
{
WSI_LOG_WARNING("Timeout waiting for image's present fences, retrying..");
}
@ -90,7 +113,7 @@ void swapchain_base::page_flip_thread()
continue;
}
call_present(*pending_index);
call_present(image_index);
}
}
@ -157,10 +180,23 @@ void swapchain_base::unpresent_image(uint32_t presented_index)
{
std::unique_lock<std::recursive_mutex> image_status_lock(m_image_status_mutex);
m_swapchain_images[presented_index].status = swapchain_image::FREE;
if (m_present_mode == VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR ||
m_present_mode == VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR)
{
m_swapchain_images[presented_index].status = swapchain_image::ACQUIRED;
}
else
{
m_swapchain_images[presented_index].status = swapchain_image::FREE;
}
image_status_lock.unlock();
m_free_image_semaphore.post();
if (m_present_mode != VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR &&
m_present_mode != VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR)
{
m_free_image_semaphore.post();
}
}
swapchain_base::swapchain_base(layer::device_private_data &dev_data, const VkAllocationCallbacks *callbacks)
@ -519,6 +555,11 @@ VkResult swapchain_base::create_aliased_image_handle(VkImage *image)
return m_device_data.disp.CreateImage(m_device, &m_image_create_info, get_allocation_callbacks(), image);
}
VkResult swapchain_base::get_swapchain_status()
{
return get_error_state();
}
VkResult swapchain_base::notify_presentation_engine(uint32_t image_index)
{
const std::lock_guard<std::recursive_mutex> lock(m_image_status_mutex);
@ -563,6 +604,13 @@ VkResult swapchain_base::queue_present(VkQueue queue, const VkPresentInfoKHR *pr
sem_count = present_info->waitSemaphoreCount;
}
if (!m_page_flip_thread_run)
{
/* If the page flip thread is not running, we need to wait for any present payload here, before setting a new present payload. */
constexpr uint64_t WAIT_PRESENT_TIMEOUT = 1000000000; /* 1 second */
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));
TRY(notify_presentation_engine(image_index));

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017-2022 Arm Limited.
* Copyright (c) 2017-2022, 2024 Arm Limited.
*
* SPDX-License-Identifier: MIT
*
@ -207,6 +207,13 @@ public:
return m_swapchain_images[image_index].present_semaphore;
}
/**
* @brief Get the swapchain status.
*
* @return VK_SUCCESS
*/
VkResult get_swapchain_status();
protected:
layer::device_private_data &m_device_data;