mirror of
https://gitlab.freedesktop.org/mesa/vulkan-wsi-layer.git
synced 2026-05-08 17:18:48 +02:00
Add support for present mode compatibility
This commit adds support for querying a surface's compatible presentation modes via VkSurfacePresentModeEXT and VkSurfacePresentModeCompatibilityEXT, as part of the VK_EXT_surface_maintenance1 extension. A new struct present_mode_compatibility has been created to capture this new functionality. Our headless implementation supports compability between FIFO and FIFO_RELAXED. On Wayland, we do not allow compatibility between FIFO and MAILBOX presentation. Change-Id: I53659cb2f2aa0ac41e37975cc34aee3ce8317a73 Signed-off-by: Dennis Tsiang <dennis.tsiang@arm.com> Signed-off-by: Fufu Fang <fufu.fang@arm.com>
This commit is contained in:
parent
8f2722de92
commit
8e02a7ffe3
7 changed files with 200 additions and 33 deletions
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2017, 2019, 2021-2022 Arm Limited.
|
||||
* Copyright (c) 2016-2017, 2019, 2021-2022, 2024 Arm Limited.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
|
|
@ -70,12 +70,7 @@ wsi_layer_vkGetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice physicalDe
|
|||
shared_present_surface_cap_struct->sharedPresentSupportedUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Any of the extensions that extend pSurfaceInfo are not supported by the
|
||||
* swapchain implementation so it is safe to ignore pNext here, even if
|
||||
* the extensions are supported by the ICD.
|
||||
*/
|
||||
return props->get_surface_capabilities(physicalDevice, &pSurfaceCapabilities->surfaceCapabilities);
|
||||
return props->get_surface_capabilities(physicalDevice, pSurfaceInfo, pSurfaceCapabilities);
|
||||
}
|
||||
|
||||
return instance.disp.GetPhysicalDeviceSurfaceCapabilities2KHR(physicalDevice, pSurfaceInfo, pSurfaceCapabilities);
|
||||
|
|
|
|||
|
|
@ -46,6 +46,27 @@ namespace headless
|
|||
|
||||
constexpr int max_core_1_0_formats = VK_FORMAT_ASTC_12x12_SRGB_BLOCK + 1;
|
||||
|
||||
void surface_properties::populate_present_mode_compatibilities()
|
||||
{
|
||||
present_mode_compatibilities = {
|
||||
present_mode_compatibility{
|
||||
VK_PRESENT_MODE_FIFO_KHR, 1, { VK_PRESENT_MODE_FIFO_KHR, VK_PRESENT_MODE_FIFO_RELAXED_KHR } },
|
||||
present_mode_compatibility{
|
||||
VK_PRESENT_MODE_FIFO_RELAXED_KHR, 1, { VK_PRESENT_MODE_FIFO_RELAXED_KHR, VK_PRESENT_MODE_FIFO_KHR } },
|
||||
present_mode_compatibility{
|
||||
VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR, 1, { VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR } },
|
||||
present_mode_compatibility{
|
||||
VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR, 1, { VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR } },
|
||||
};
|
||||
}
|
||||
|
||||
surface_properties::surface_properties()
|
||||
: supported_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 })
|
||||
{
|
||||
populate_present_mode_compatibilities();
|
||||
}
|
||||
|
||||
surface_properties &surface_properties::get_instance()
|
||||
{
|
||||
static surface_properties instance;
|
||||
|
|
@ -56,7 +77,16 @@ VkResult surface_properties::get_surface_capabilities(VkPhysicalDevice physical_
|
|||
VkSurfaceCapabilitiesKHR *surface_capabilities)
|
||||
{
|
||||
get_surface_capabilities_common(physical_device, surface_capabilities);
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult surface_properties::get_surface_capabilities(VkPhysicalDevice physical_device,
|
||||
const VkPhysicalDeviceSurfaceInfo2KHR *surface_info,
|
||||
VkSurfaceCapabilities2KHR *surface_capabilities)
|
||||
{
|
||||
TRY(check_surface_present_mode_query_is_supported(surface_info, supported_modes));
|
||||
get_surface_capabilities_common(physical_device, &surface_capabilities->surfaceCapabilities);
|
||||
get_surface_present_mode_compatibility_common(surface_info, surface_capabilities, present_mode_compatibilities);
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
@ -110,15 +140,7 @@ VkResult surface_properties::get_surface_present_modes(VkPhysicalDevice physical
|
|||
{
|
||||
UNUSED(physical_device);
|
||||
UNUSED(surface);
|
||||
|
||||
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, supported_modes);
|
||||
}
|
||||
|
||||
VWL_VKAPI_CALL(VkResult)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2019, 2022-2023 Arm Limited.
|
||||
* Copyright (c) 2017-2019, 2022-2024 Arm Limited.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
|
|
@ -36,9 +36,15 @@ namespace headless
|
|||
class surface_properties : public wsi::surface_properties
|
||||
{
|
||||
public:
|
||||
surface_properties();
|
||||
|
||||
VkResult get_surface_capabilities(VkPhysicalDevice physical_device,
|
||||
VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) override;
|
||||
|
||||
VkResult get_surface_capabilities(VkPhysicalDevice physical_device,
|
||||
const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
|
||||
VkSurfaceCapabilities2KHR *pSurfaceCapabilities) override;
|
||||
|
||||
VkResult get_surface_formats(VkPhysicalDevice physical_device, uint32_t *surfaceFormatCount,
|
||||
VkSurfaceFormatKHR *surfaceFormats,
|
||||
VkSurfaceFormat2KHR *extended_surface_formats) override;
|
||||
|
|
@ -53,6 +59,15 @@ public:
|
|||
bool is_surface_extension_enabled(const layer::instance_private_data &instance_data) override;
|
||||
|
||||
static surface_properties &get_instance();
|
||||
|
||||
private:
|
||||
/* List of supported presentation modes */
|
||||
std::array<VkPresentModeKHR, 4> supported_modes;
|
||||
|
||||
/* Stores compatible presentation modes */
|
||||
std::array<present_mode_compatibility, 4> present_mode_compatibilities;
|
||||
|
||||
void populate_present_mode_compatibilities() override;
|
||||
};
|
||||
|
||||
} /* namespace headless */
|
||||
|
|
|
|||
|
|
@ -41,6 +41,19 @@
|
|||
namespace wsi
|
||||
{
|
||||
|
||||
static constexpr uint32_t MAX_PRESENT_MODES = 6;
|
||||
struct present_mode_compatibility
|
||||
{
|
||||
/* Presentation mode */
|
||||
VkPresentModeKHR present_mode;
|
||||
|
||||
/* Number of presentation modes compatible */
|
||||
uint32_t present_mode_count;
|
||||
|
||||
/* Stores the compatible presentation modes */
|
||||
std::array<VkPresentModeKHR, MAX_PRESENT_MODES> compatible_present_modes;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The base surface property query interface.
|
||||
*/
|
||||
|
|
@ -53,6 +66,13 @@ public:
|
|||
virtual VkResult get_surface_capabilities(VkPhysicalDevice physical_device,
|
||||
VkSurfaceCapabilitiesKHR *surface_capabilities) = 0;
|
||||
|
||||
/**
|
||||
* @brief Implementation of vkGetPhysicalDeviceSurfaceCapabilities2KHR for the specific VkSurface type.
|
||||
*/
|
||||
virtual VkResult get_surface_capabilities(VkPhysicalDevice physical_device,
|
||||
const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
|
||||
VkSurfaceCapabilities2KHR *surface_capabilities) = 0;
|
||||
|
||||
/**
|
||||
* @brief Implementation of vkGetPhysicalDeviceSurfaceFormatsKHR for the specific VkSurface type.
|
||||
*/
|
||||
|
|
@ -94,6 +114,12 @@ public:
|
|||
|
||||
/* There is no maximum theoretically speaking however we choose 6 for practicality */
|
||||
static constexpr uint32_t MAX_SWAPCHAIN_IMAGE_COUNT = 6;
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Set which presentation modes are compatible with each other for a particular surface
|
||||
*/
|
||||
virtual void populate_present_mode_compatibilities() = 0;
|
||||
};
|
||||
|
||||
class surface_format_properties
|
||||
|
|
@ -204,6 +230,36 @@ VkResult surface_properties_formats_helper(It begin, It end, uint32_t *surface_f
|
|||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Common function for handling VkSurfacePresentModeEXT.
|
||||
*
|
||||
* If VkSurfacePresentModeEXT is present in the pNext chain of VkPhysicalDeviceSurfaceInfo2KHR, then
|
||||
* the presentation mode specified in the VkSurfacePresentModeEXT struct is checked to see if it is
|
||||
* supported by the surface.
|
||||
*
|
||||
* @param surface_info Pointer to Vulkan surface info struct.
|
||||
* @param modes Array of presentation modes supported by the surface.
|
||||
*
|
||||
* @return VK_SUCCESS on success, VK_ERROR_OUT_OF_HOST_MEMORY otherwise.
|
||||
*/
|
||||
template <std::size_t SIZE>
|
||||
VkResult check_surface_present_mode_query_is_supported(const VkPhysicalDeviceSurfaceInfo2KHR *surface_info,
|
||||
const std::array<VkPresentModeKHR, SIZE> &modes)
|
||||
{
|
||||
auto surface_present_mode =
|
||||
util::find_extension<VkSurfacePresentModeEXT>(VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_EXT, surface_info);
|
||||
if (surface_present_mode != nullptr)
|
||||
{
|
||||
VkPresentModeKHR present_mode = surface_present_mode->presentMode;
|
||||
if (std::find(modes.begin(), modes.end(), present_mode) == modes.end())
|
||||
{
|
||||
WSI_LOG_ERROR("Querying surface capability support for a present mode that is not supported by the surface");
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
}
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Common function for the get_surface_capabilities.
|
||||
*
|
||||
|
|
@ -255,4 +311,55 @@ VkResult get_surface_present_modes_common(uint32_t *present_mode_count, VkPresen
|
|||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Common function for handling VkSurfacePresentModeCompatibilityEXT if it exists in the pNext chain of VkSurfaceCapabilities2KHR.
|
||||
*
|
||||
* If pSurfaceInfo contains a VkSurfacePresentModeEXT struct in its pNext chain, and pSurfaceCapabilities contains a VkSurfacePresentModeCompatibilityEXT struct
|
||||
* then this function fills the VkSurfacePresentModeCompatibilityEXT struct with the presentation modes that are compatible with the presentation mode specified
|
||||
* in the VkSurfacePresentModeEXT struct.
|
||||
*
|
||||
* @param pSurfaceInfo Pointer to surface info that may or may not contain a VkSurfacePresentModeEXT.
|
||||
* @param pSurfaceCapabilities Pointer to surface capabilities that may or may not contain a VkSurfacePresentModeCompatibilityEXT struct.
|
||||
* @param present_mode_compatibilities A table containing a mapping of presentation modes and what other modes they are compatible with.
|
||||
*
|
||||
*/
|
||||
template <std::size_t SIZE>
|
||||
void get_surface_present_mode_compatibility_common(
|
||||
const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo, VkSurfaceCapabilities2KHR *pSurfaceCapabilities,
|
||||
const std::array<present_mode_compatibility, SIZE> &present_mode_compatibilities)
|
||||
{
|
||||
auto surface_present_mode =
|
||||
util::find_extension<VkSurfacePresentModeEXT>(VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_EXT, pSurfaceInfo);
|
||||
auto surface_present_mode_compatibility = util::find_extension<VkSurfacePresentModeCompatibilityEXT>(
|
||||
VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_COMPATIBILITY_EXT, pSurfaceCapabilities);
|
||||
|
||||
if (surface_present_mode == nullptr || surface_present_mode_compatibility == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
VkPresentModeKHR present_mode = surface_present_mode->presentMode;
|
||||
auto it = std::find_if(present_mode_compatibilities.begin(), present_mode_compatibilities.end(),
|
||||
[present_mode](present_mode_compatibility p) { return p.present_mode == present_mode; });
|
||||
if (it == present_mode_compatibilities.end())
|
||||
{
|
||||
WSI_LOG_ERROR("Querying compatible presentation mode support for a presentation mode that is not supported.");
|
||||
return;
|
||||
}
|
||||
const present_mode_compatibility &surface_supported_compatibility = *it;
|
||||
|
||||
if (surface_present_mode_compatibility->pPresentModes == nullptr)
|
||||
{
|
||||
surface_present_mode_compatibility->presentModeCount = surface_supported_compatibility.present_mode_count;
|
||||
return;
|
||||
}
|
||||
|
||||
surface_present_mode_compatibility->presentModeCount = std::min(surface_present_mode_compatibility->presentModeCount,
|
||||
surface_supported_compatibility.present_mode_count);
|
||||
std::copy(surface_supported_compatibility.compatible_present_modes.begin(),
|
||||
surface_supported_compatibility.compatible_present_modes.begin() +
|
||||
surface_present_mode_compatibility->presentModeCount,
|
||||
surface_present_mode_compatibility->pPresentModes);
|
||||
}
|
||||
|
||||
} /* namespace wsi */
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ surface::surface(const init_parameters ¶ms)
|
|||
, wayland_display(params.display)
|
||||
, wayland_surface(params.surf)
|
||||
, supported_formats(params.allocator)
|
||||
, properties(*this, params.allocator)
|
||||
, properties(this, params.allocator)
|
||||
, surface_queue(nullptr)
|
||||
, last_frame_callback(nullptr)
|
||||
, present_pending(false)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2019, 2021-2023 Arm Limited.
|
||||
* Copyright (c) 2017-2019, 2021-2024 Arm Limited.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
|
|
@ -47,15 +47,24 @@ namespace wsi
|
|||
namespace wayland
|
||||
{
|
||||
|
||||
surface_properties::surface_properties(surface &wsi_surface, const util::allocator &allocator)
|
||||
: specific_surface(&wsi_surface)
|
||||
, supported_formats(allocator)
|
||||
void surface_properties::populate_present_mode_compatibilities()
|
||||
{
|
||||
present_mode_compatibilities = {
|
||||
present_mode_compatibility{ VK_PRESENT_MODE_FIFO_KHR, 1, { VK_PRESENT_MODE_FIFO_KHR } },
|
||||
present_mode_compatibility{ VK_PRESENT_MODE_MAILBOX_KHR, 1, { VK_PRESENT_MODE_MAILBOX_KHR } }
|
||||
};
|
||||
}
|
||||
|
||||
surface_properties::surface_properties(surface *wsi_surface, const util::allocator &allocator)
|
||||
: specific_surface(wsi_surface)
|
||||
, supported_formats(allocator)
|
||||
, supported_modes({ VK_PRESENT_MODE_FIFO_KHR, VK_PRESENT_MODE_MAILBOX_KHR })
|
||||
{
|
||||
populate_present_mode_compatibilities();
|
||||
}
|
||||
|
||||
surface_properties::surface_properties()
|
||||
: specific_surface(nullptr)
|
||||
, supported_formats(util::allocator::get_generic())
|
||||
: surface_properties(nullptr, util::allocator::get_generic())
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -68,6 +77,7 @@ surface_properties &surface_properties::get_instance()
|
|||
VkResult surface_properties::get_surface_capabilities(VkPhysicalDevice physical_device,
|
||||
VkSurfaceCapabilitiesKHR *pSurfaceCapabilities)
|
||||
{
|
||||
|
||||
/* Image count limits */
|
||||
get_surface_capabilities_common(physical_device, pSurfaceCapabilities);
|
||||
pSurfaceCapabilities->minImageCount = 2;
|
||||
|
|
@ -75,6 +85,19 @@ VkResult surface_properties::get_surface_capabilities(VkPhysicalDevice physical_
|
|||
/* Composite alpha */
|
||||
pSurfaceCapabilities->supportedCompositeAlpha = static_cast<VkCompositeAlphaFlagBitsKHR>(
|
||||
VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR | VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR);
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VkResult surface_properties::get_surface_capabilities(VkPhysicalDevice physical_device,
|
||||
const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
|
||||
VkSurfaceCapabilities2KHR *pSurfaceCapabilities)
|
||||
{
|
||||
TRY(check_surface_present_mode_query_is_supported(pSurfaceInfo, supported_modes));
|
||||
|
||||
/* Image count limits */
|
||||
get_surface_capabilities(physical_device, &pSurfaceCapabilities->surfaceCapabilities);
|
||||
|
||||
get_surface_present_mode_compatibility_common(pSurfaceInfo, pSurfaceCapabilities, present_mode_compatibilities);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
|
@ -213,13 +236,7 @@ VkResult surface_properties::get_surface_formats(VkPhysicalDevice physical_devic
|
|||
VkResult surface_properties::get_surface_present_modes(VkPhysicalDevice physical_device, VkSurfaceKHR surface,
|
||||
uint32_t *pPresentModeCount, VkPresentModeKHR *pPresentModes)
|
||||
{
|
||||
|
||||
static const std::array<VkPresentModeKHR, 2> modes = {
|
||||
VK_PRESENT_MODE_FIFO_KHR,
|
||||
VK_PRESENT_MODE_MAILBOX_KHR,
|
||||
};
|
||||
|
||||
return get_surface_present_modes_common(pPresentModeCount, pPresentModes, modes);
|
||||
return get_surface_present_modes_common(pPresentModeCount, pPresentModes, supported_modes);
|
||||
}
|
||||
|
||||
VkResult surface_properties::get_required_device_extensions(util::extension_list &extension_list)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2019, 2021-2023 Arm Limited.
|
||||
* Copyright (c) 2017-2019, 2021-2024 Arm Limited.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
|
|
@ -48,12 +48,15 @@ class surface;
|
|||
class surface_properties : public wsi::surface_properties
|
||||
{
|
||||
public:
|
||||
surface_properties(surface &wsi_surface, const util::allocator &alloc);
|
||||
surface_properties(surface *wsi_surface, const util::allocator &alloc);
|
||||
|
||||
static surface_properties &get_instance();
|
||||
|
||||
VkResult get_surface_capabilities(VkPhysicalDevice physical_device,
|
||||
VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) override;
|
||||
VkResult get_surface_capabilities(VkPhysicalDevice physical_device,
|
||||
const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
|
||||
VkSurfaceCapabilities2KHR *pSurfaceCapabilities) override;
|
||||
VkResult get_surface_formats(VkPhysicalDevice physical_device, uint32_t *surfaceFormatCount,
|
||||
VkSurfaceFormatKHR *surfaceFormats,
|
||||
VkSurfaceFormat2KHR *extended_surface_formats) override;
|
||||
|
|
@ -77,6 +80,14 @@ private:
|
|||
surface *specific_surface;
|
||||
/** Set of supported Vulkan formats by the @ref specific_surface. */
|
||||
surface_format_properties_map supported_formats;
|
||||
|
||||
/* List of supported presentation modes */
|
||||
std::array<VkPresentModeKHR, 2> supported_modes;
|
||||
|
||||
/* Stores compatible presentation modes */
|
||||
std::array<present_mode_compatibility, 2> present_mode_compatibilities;
|
||||
|
||||
void populate_present_mode_compatibilities() override;
|
||||
};
|
||||
|
||||
} // namespace wayland
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue