mirror of
https://gitlab.freedesktop.org/mesa/vulkan-wsi-layer.git
synced 2025-12-20 06:50:08 +01:00
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:
parent
fecfd94079
commit
8a74233de2
11 changed files with 130 additions and 32 deletions
|
|
@ -180,6 +180,7 @@ if(BUILD_WSI_HEADLESS)
|
||||||
list(APPEND LINK_WSI_LIBS wsi_headless)
|
list(APPEND LINK_WSI_LIBS wsi_headless)
|
||||||
else()
|
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_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()
|
endif()
|
||||||
|
|
||||||
# Layer
|
# Layer
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
{"name" : "VK_KHR_get_surface_capabilities2", "spec_version" : "1"}
|
{"name" : "VK_KHR_get_surface_capabilities2", "spec_version" : "1"}
|
||||||
],
|
],
|
||||||
"device_extensions": [
|
"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_EXT_image_compression_control_swapchain", "spec_version": "1"},
|
||||||
{
|
{
|
||||||
"name": "VK_KHR_swapchain",
|
"name": "VK_KHR_swapchain",
|
||||||
|
|
|
||||||
|
|
@ -435,6 +435,11 @@ wsi_layer_vkGetDeviceProcAddr(VkDevice device, const char *funcName) VWL_API_POS
|
||||||
GET_PROC_ADDR(vkGetDeviceGroupPresentCapabilitiesKHR);
|
GET_PROC_ADDR(vkGetDeviceGroupPresentCapabilitiesKHR);
|
||||||
GET_PROC_ADDR(vkGetDeviceGroupSurfacePresentModesKHR);
|
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(vkDestroyDevice);
|
||||||
|
|
||||||
GET_PROC_ADDR(vkCreateImage);
|
GET_PROC_ADDR(vkCreateImage);
|
||||||
|
|
|
||||||
|
|
@ -369,6 +369,8 @@ private:
|
||||||
EP(GetSwapchainImagesKHR, VK_KHR_SWAPCHAIN_EXTENSION_NAME, API_VERSION_MAX, false) \
|
EP(GetSwapchainImagesKHR, VK_KHR_SWAPCHAIN_EXTENSION_NAME, API_VERSION_MAX, false) \
|
||||||
EP(AcquireNextImageKHR, 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) \
|
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 */ \
|
/* VK_KHR_device_group + VK_KHR_swapchain or */ \
|
||||||
/* 1.1 with VK_KHR_swapchain */ \
|
/* 1.1 with VK_KHR_swapchain */ \
|
||||||
EP(AcquireNextImage2KHR, VK_KHR_DEVICE_GROUP_EXTENSION_NAME, VK_API_VERSION_1_1, false) \
|
EP(AcquireNextImage2KHR, VK_KHR_DEVICE_GROUP_EXTENSION_NAME, VK_API_VERSION_1_1, false) \
|
||||||
|
|
|
||||||
|
|
@ -382,3 +382,18 @@ wsi_layer_vkBindImageMemory2(VkDevice device, uint32_t bindInfoCount,
|
||||||
}
|
}
|
||||||
return endpoint_result;
|
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();
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2018-2019 Arm Limited.
|
* Copyright (c) 2018-2019, 2024 Arm Limited.
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*
|
*
|
||||||
|
|
@ -76,3 +76,6 @@ wsi_layer_vkCreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo, c
|
||||||
VWL_VKAPI_CALL(VkResult)
|
VWL_VKAPI_CALL(VkResult)
|
||||||
wsi_layer_vkBindImageMemory2(VkDevice device, uint32_t bindInfoCount,
|
wsi_layer_vkBindImageMemory2(VkDevice device, uint32_t bindInfoCount,
|
||||||
const VkBindImageMemoryInfo *pBindInfos) VWL_API_POST;
|
const VkBindImageMemoryInfo *pBindInfos) VWL_API_POST;
|
||||||
|
|
||||||
|
VWL_VKAPI_CALL(VkResult)
|
||||||
|
wsi_layer_vkGetSwapchainStatusKHR(VkDevice device, VkSwapchainKHR swapchain) VWL_API_POST;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2017-2019, 2021-2023 Arm Limited.
|
* Copyright (c) 2017-2019, 2021-2024 Arm Limited.
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*
|
*
|
||||||
|
|
@ -113,7 +113,12 @@ VkResult surface_properties::get_surface_present_modes(VkPhysicalDevice physical
|
||||||
UNUSED(physical_device);
|
UNUSED(physical_device);
|
||||||
UNUSED(surface);
|
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);
|
return get_surface_present_modes_common(present_mode_count, present_modes, modes);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2017-2022 Arm Limited.
|
* Copyright (c) 2017-2022, 2024 Arm Limited.
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*
|
*
|
||||||
|
|
@ -50,7 +50,9 @@ struct image_data
|
||||||
swapchain::swapchain(layer::device_private_data &dev_data, const VkAllocationCallbacks *pAllocator)
|
swapchain::swapchain(layer::device_private_data &dev_data, const VkAllocationCallbacks *pAllocator)
|
||||||
: wsi::swapchain_base(dev_data, pAllocator)
|
: wsi::swapchain_base(dev_data, pAllocator)
|
||||||
#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN
|
#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN
|
||||||
, m_image_compression_control{}
|
, m_image_compression_control
|
||||||
|
{
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -61,6 +63,21 @@ swapchain::~swapchain()
|
||||||
teardown();
|
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 swapchain::create_and_bind_swapchain_image(VkImageCreateInfo image_create, wsi::swapchain_image &image)
|
||||||
{
|
{
|
||||||
VkResult res = VK_SUCCESS;
|
VkResult res = VK_SUCCESS;
|
||||||
|
|
@ -178,7 +195,6 @@ void swapchain::destroy_image(wsi::swapchain_image &image)
|
||||||
m_allocator.destroy(1, data);
|
m_allocator.destroy(1, data);
|
||||||
image.data = nullptr;
|
image.data = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VkResult swapchain::image_set_present_payload(swapchain_image &image, VkQueue queue, const VkSemaphore *sem_payload,
|
VkResult swapchain::image_set_present_payload(swapchain_image &image, VkQueue queue, const VkSemaphore *sem_payload,
|
||||||
|
|
|
||||||
|
|
@ -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
|
* SPDX-License-Identifier: MIT
|
||||||
*
|
*
|
||||||
|
|
@ -57,11 +57,7 @@ protected:
|
||||||
* @brief Platform specific init
|
* @brief Platform specific init
|
||||||
*/
|
*/
|
||||||
VkResult init_platform(VkDevice device, const VkSwapchainCreateInfoKHR *swapchain_create_info,
|
VkResult init_platform(VkDevice device, const VkSwapchainCreateInfoKHR *swapchain_create_info,
|
||||||
bool &use_presentation_thread) override
|
bool &use_presentation_thread) override;
|
||||||
{
|
|
||||||
use_presentation_thread = true;
|
|
||||||
return VK_SUCCESS;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Creates and binds a new swapchain image.
|
* @brief Creates and binds a new swapchain image.
|
||||||
|
|
@ -109,7 +105,6 @@ protected:
|
||||||
const VkBindImageMemorySwapchainInfoKHR *bind_sc_info) override;
|
const VkBindImageMemorySwapchainInfoKHR *bind_sc_info) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN
|
#if WSI_IMAGE_COMPRESSION_CONTROL_SWAPCHAIN
|
||||||
VkImageCompressionControlEXT m_image_compression_control;
|
VkImageCompressionControlEXT m_image_compression_control;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,29 @@ void swapchain_base::page_flip_thread()
|
||||||
* the variable to be visible to this thread.
|
* the variable to be visible to this thread.
|
||||||
*/
|
*/
|
||||||
while (m_page_flip_thread_run)
|
while (m_page_flip_thread_run)
|
||||||
|
{
|
||||||
|
|
||||||
|
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
|
/* Waiting for the page_flip_semaphore which will be signalled once there is an
|
||||||
* image to display.*/
|
* image to display.*/
|
||||||
|
|
@ -69,17 +92,17 @@ void swapchain_base::page_flip_thread()
|
||||||
/* Image is not ready yet. */
|
/* Image is not ready yet. */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
assert(vk_res == VK_SUCCESS);
|
|
||||||
|
|
||||||
/* We want to present the oldest queued for present image from our present queue,
|
/* 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. */
|
* 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);
|
std::unique_lock<std::recursive_mutex> image_status_lock(m_image_status_mutex);
|
||||||
auto pending_index = m_pending_buffer_pool.pop_front();
|
auto pending_index = m_pending_buffer_pool.pop_front();
|
||||||
assert(pending_index.has_value());
|
assert(pending_index.has_value());
|
||||||
image_status_lock.unlock();
|
image_index = *pending_index;
|
||||||
|
}
|
||||||
|
|
||||||
/* We may need to wait for the payload of the present sync of the oldest pending image to be finished. */
|
/* 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..");
|
WSI_LOG_WARNING("Timeout waiting for image's present fences, retrying..");
|
||||||
}
|
}
|
||||||
|
|
@ -90,7 +113,7 @@ void swapchain_base::page_flip_thread()
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
call_present(*pending_index);
|
call_present(image_index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -157,11 +180,24 @@ void swapchain_base::unpresent_image(uint32_t presented_index)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::recursive_mutex> image_status_lock(m_image_status_mutex);
|
std::unique_lock<std::recursive_mutex> image_status_lock(m_image_status_mutex);
|
||||||
|
|
||||||
|
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;
|
m_swapchain_images[presented_index].status = swapchain_image::FREE;
|
||||||
|
}
|
||||||
|
|
||||||
image_status_lock.unlock();
|
image_status_lock.unlock();
|
||||||
|
|
||||||
|
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();
|
m_free_image_semaphore.post();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
swapchain_base::swapchain_base(layer::device_private_data &dev_data, const VkAllocationCallbacks *callbacks)
|
swapchain_base::swapchain_base(layer::device_private_data &dev_data, const VkAllocationCallbacks *callbacks)
|
||||||
: m_device_data(dev_data)
|
: m_device_data(dev_data)
|
||||||
|
|
@ -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);
|
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)
|
VkResult swapchain_base::notify_presentation_engine(uint32_t image_index)
|
||||||
{
|
{
|
||||||
const std::lock_guard<std::recursive_mutex> lock(m_image_status_mutex);
|
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;
|
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_LOG_CALL(image_set_present_payload(m_swapchain_images[image_index], queue, wait_semaphores, sem_count));
|
||||||
TRY(notify_presentation_engine(image_index));
|
TRY(notify_presentation_engine(image_index));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2017-2022 Arm Limited.
|
* Copyright (c) 2017-2022, 2024 Arm Limited.
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*
|
*
|
||||||
|
|
@ -207,6 +207,13 @@ public:
|
||||||
return m_swapchain_images[image_index].present_semaphore;
|
return m_swapchain_images[image_index].present_semaphore;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the swapchain status.
|
||||||
|
*
|
||||||
|
* @return VK_SUCCESS
|
||||||
|
*/
|
||||||
|
VkResult get_swapchain_status();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
layer::device_private_data &m_device_data;
|
layer::device_private_data &m_device_data;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue