Refactor compatible present mode functionality

Refactor the compatible present mode functionality into a new class
compatible_present_modes.

Change-Id: I801f41ba16d9c5693f1aaa1e95e9eb2c9c4f5b59
Signed-off-by: Dennis Tsiang <dennis.tsiang@arm.com>
Signed-off-by: Fufu Fang <fufu.fang@arm.com>
This commit is contained in:
Dennis Tsiang 2024-05-13 12:20:49 +01:00 committed by Fufu Fang
parent 05e98f4d17
commit 7f428885e1
6 changed files with 169 additions and 117 deletions

View file

@ -0,0 +1,145 @@
/*
* Copyright (c) 2024 Arm Limited.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/**
* @file compatible_present_modes.hpp
*
* @brief Contains functions for handling compatibility between different presentation modes
*/
#pragma once
#include <vulkan/vulkan.h>
#include <array>
#include <util/log.hpp>
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;
};
template <std::size_t SIZE>
class compatible_present_modes
{
public:
compatible_present_modes()
{
}
compatible_present_modes(std::array<present_mode_compatibility, SIZE> present_mode_compatibilites)
: m_present_mode_compatibilites(present_mode_compatibilites)
{
}
/**
* @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.
*
*/
void get_surface_present_mode_compatibility_common(const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
VkSurfaceCapabilities2KHR *pSurfaceCapabilities)
{
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(m_present_mode_compatibilites.begin(), m_present_mode_compatibilites.end(),
[present_mode](present_mode_compatibility p) { return p.present_mode == present_mode; });
if (it == m_present_mode_compatibilites.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);
}
/**
* @brief Common function for handling checking whether a present mode is compatible with another.
*
* @param present_mode_a First present mode.
* @param present_mode_b Second present mode to compare against.
*
* @return true if compatible, false otherwise.
*/
bool is_compatible_present_modes(VkPresentModeKHR present_mode_a, VkPresentModeKHR present_mode_b)
{
auto it =
std::find_if(m_present_mode_compatibilites.begin(), m_present_mode_compatibilites.end(),
[present_mode_a](present_mode_compatibility p) { return p.present_mode == present_mode_a; });
if (it == m_present_mode_compatibilites.end())
{
WSI_LOG_ERROR("Querying compatible presentation mode support for a presentation mode that is not supported.");
return false;
}
const present_mode_compatibility &present_mode_comp = *it;
auto present_mode_it =
std::find_if(present_mode_comp.compatible_present_modes.begin(),
present_mode_comp.compatible_present_modes.begin() + present_mode_comp.present_mode_count,
[present_mode_b](VkPresentModeKHR p) { return p == present_mode_b; });
return present_mode_it != present_mode_comp.compatible_present_modes.end();
}
private:
std::array<present_mode_compatibility, SIZE> m_present_mode_compatibilites;
};
} // namespace wsi

View file

@ -48,21 +48,23 @@ constexpr int max_core_1_0_formats = VK_FORMAT_ASTC_12x12_SRGB_BLOCK + 1;
void surface_properties::populate_present_mode_compatibilities() void surface_properties::populate_present_mode_compatibilities()
{ {
present_mode_compatibilities = { std::array compatible_present_modes_list = {
present_mode_compatibility{ present_mode_compatibility{
VK_PRESENT_MODE_FIFO_KHR, 1, { VK_PRESENT_MODE_FIFO_KHR, VK_PRESENT_MODE_FIFO_RELAXED_KHR } }, VK_PRESENT_MODE_FIFO_KHR, 2, { VK_PRESENT_MODE_FIFO_KHR, VK_PRESENT_MODE_FIFO_RELAXED_KHR } },
present_mode_compatibility{ present_mode_compatibility{
VK_PRESENT_MODE_FIFO_RELAXED_KHR, 1, { VK_PRESENT_MODE_FIFO_RELAXED_KHR, VK_PRESENT_MODE_FIFO_KHR } }, VK_PRESENT_MODE_FIFO_RELAXED_KHR, 2, { VK_PRESENT_MODE_FIFO_RELAXED_KHR, VK_PRESENT_MODE_FIFO_KHR } },
present_mode_compatibility{ present_mode_compatibility{
VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR, 1, { VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR } }, VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR, 1, { VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR } },
present_mode_compatibility{ present_mode_compatibility{
VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR, 1, { VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR } }, VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR, 1, { VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR } },
}; };
m_compatible_present_modes =
compatible_present_modes<compatible_present_modes_list.size()>(compatible_present_modes_list);
} }
surface_properties::surface_properties() surface_properties::surface_properties()
: supported_modes({ VK_PRESENT_MODE_FIFO_KHR, VK_PRESENT_MODE_FIFO_RELAXED_KHR, : m_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 }) VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR, VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR })
{ {
populate_present_mode_compatibilities(); populate_present_mode_compatibilities();
} }
@ -84,9 +86,9 @@ VkResult surface_properties::get_surface_capabilities(VkPhysicalDevice physical_
const VkPhysicalDeviceSurfaceInfo2KHR *surface_info, const VkPhysicalDeviceSurfaceInfo2KHR *surface_info,
VkSurfaceCapabilities2KHR *surface_capabilities) VkSurfaceCapabilities2KHR *surface_capabilities)
{ {
TRY(check_surface_present_mode_query_is_supported(surface_info, supported_modes)); TRY(check_surface_present_mode_query_is_supported(surface_info, m_supported_modes));
get_surface_capabilities_common(physical_device, &surface_capabilities->surfaceCapabilities); get_surface_capabilities_common(physical_device, &surface_capabilities->surfaceCapabilities);
get_surface_present_mode_compatibility_common(surface_info, surface_capabilities, present_mode_compatibilities); m_compatible_present_modes.get_surface_present_mode_compatibility_common(surface_info, surface_capabilities);
auto surface_scaling_capabilities = util::find_extension<VkSurfacePresentScalingCapabilitiesEXT>( auto surface_scaling_capabilities = util::find_extension<VkSurfacePresentScalingCapabilitiesEXT>(
VK_STRUCTURE_TYPE_SURFACE_PRESENT_SCALING_CAPABILITIES_EXT, surface_capabilities); VK_STRUCTURE_TYPE_SURFACE_PRESENT_SCALING_CAPABILITIES_EXT, surface_capabilities);
@ -150,7 +152,7 @@ VkResult surface_properties::get_surface_present_modes(VkPhysicalDevice physical
{ {
UNUSED(physical_device); UNUSED(physical_device);
UNUSED(surface); UNUSED(surface);
return get_surface_present_modes_common(present_mode_count, present_modes, supported_modes); return get_surface_present_modes_common(present_mode_count, present_modes, m_supported_modes);
} }
VWL_VKAPI_CALL(VkResult) VWL_VKAPI_CALL(VkResult)
@ -210,7 +212,7 @@ void surface_properties::get_surface_present_scaling_and_gravity(
bool surface_properties::is_compatible_present_modes(VkPresentModeKHR present_mode_a, VkPresentModeKHR present_mode_b) bool surface_properties::is_compatible_present_modes(VkPresentModeKHR present_mode_a, VkPresentModeKHR present_mode_b)
{ {
return is_compatible_present_modes_common(present_mode_a, present_mode_b, present_mode_compatibilities); return m_compatible_present_modes.is_compatible_present_modes(present_mode_a, present_mode_b);
} }
} /* namespace headless */ } /* namespace headless */

View file

@ -27,7 +27,7 @@
#include <vulkan/vk_icd.h> #include <vulkan/vk_icd.h>
#include <vulkan/vulkan.h> #include <vulkan/vulkan.h>
#include <wsi/surface_properties.hpp> #include <wsi/surface_properties.hpp>
#include <wsi/compatible_present_modes.hpp>
namespace wsi namespace wsi
{ {
namespace headless namespace headless
@ -64,10 +64,10 @@ public:
private: private:
/* List of supported presentation modes */ /* List of supported presentation modes */
std::array<VkPresentModeKHR, 4> supported_modes; std::array<VkPresentModeKHR, 4> m_supported_modes;
/* Stores compatible presentation modes */ /* Stores compatible presentation modes */
std::array<present_mode_compatibility, 4> present_mode_compatibilities; compatible_present_modes<4> m_compatible_present_modes;
void populate_present_mode_compatibilities() override; void populate_present_mode_compatibilities() override;

View file

@ -41,19 +41,6 @@
namespace wsi 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. * @brief The base surface property query interface.
*/ */
@ -319,88 +306,4 @@ VkResult get_surface_present_modes_common(uint32_t *present_mode_count, VkPresen
return res; 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);
}
/**
* @brief Common function for handling checking whether a present mode is compatible with another.
*
* @param present_mode_a First present mode.
* @param present_mode_b Second present mode to compare against.
* @param present_mode_compatibilities A table containing a mapping of presentation modes and what other modes they are compatible with.
*
* @return true if compatible, false otherwise.
*/
template <std::size_t SIZE>
bool is_compatible_present_modes_common(
VkPresentModeKHR present_mode_a, VkPresentModeKHR present_mode_b,
const std::array<present_mode_compatibility, SIZE> &present_mode_compatibilities)
{
auto it = std::find_if(present_mode_compatibilities.begin(), present_mode_compatibilities.end(),
[present_mode_a](present_mode_compatibility p) { return p.present_mode == present_mode_a; });
if (it == present_mode_compatibilities.end())
{
WSI_LOG_ERROR("Querying compatible presentation mode support for a presentation mode that is not supported.");
return false;
}
const present_mode_compatibility &present_mode_comp = *it;
auto present_mode_it =
std::find_if(present_mode_comp.compatible_present_modes.begin(), present_mode_comp.compatible_present_modes.end(),
[present_mode_b](VkPresentModeKHR p) { return p == present_mode_b; });
if (present_mode_it == present_mode_comp.compatible_present_modes.end())
{
return false;
}
return true;
}
} /* namespace wsi */ } /* namespace wsi */

View file

@ -49,16 +49,17 @@ namespace wayland
void surface_properties::populate_present_mode_compatibilities() void surface_properties::populate_present_mode_compatibilities()
{ {
present_mode_compatibilities = { std::array<present_mode_compatibility, 2> compatible_present_modes_list = {
present_mode_compatibility{ VK_PRESENT_MODE_FIFO_KHR, 1, { VK_PRESENT_MODE_FIFO_KHR } }, 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 } } present_mode_compatibility{ VK_PRESENT_MODE_MAILBOX_KHR, 1, { VK_PRESENT_MODE_MAILBOX_KHR } }
}; };
m_compatible_present_modes = compatible_present_modes<2>(compatible_present_modes_list);
} }
surface_properties::surface_properties(surface *wsi_surface, const util::allocator &allocator) surface_properties::surface_properties(surface *wsi_surface, const util::allocator &allocator)
: specific_surface(wsi_surface) : specific_surface(wsi_surface)
, supported_formats(allocator) , supported_formats(allocator)
, supported_modes({ VK_PRESENT_MODE_FIFO_KHR, VK_PRESENT_MODE_MAILBOX_KHR }) , m_supported_modes({ VK_PRESENT_MODE_FIFO_KHR, VK_PRESENT_MODE_MAILBOX_KHR })
{ {
populate_present_mode_compatibilities(); populate_present_mode_compatibilities();
} }
@ -92,12 +93,12 @@ VkResult surface_properties::get_surface_capabilities(VkPhysicalDevice physical_
const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo, const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
VkSurfaceCapabilities2KHR *pSurfaceCapabilities) VkSurfaceCapabilities2KHR *pSurfaceCapabilities)
{ {
TRY(check_surface_present_mode_query_is_supported(pSurfaceInfo, supported_modes)); TRY(check_surface_present_mode_query_is_supported(pSurfaceInfo, m_supported_modes));
/* Image count limits */ /* Image count limits */
get_surface_capabilities(physical_device, &pSurfaceCapabilities->surfaceCapabilities); get_surface_capabilities(physical_device, &pSurfaceCapabilities->surfaceCapabilities);
get_surface_present_mode_compatibility_common(pSurfaceInfo, pSurfaceCapabilities, present_mode_compatibilities); m_compatible_present_modes.get_surface_present_mode_compatibility_common(pSurfaceInfo, pSurfaceCapabilities);
auto surface_scaling_capabilities = util::find_extension<VkSurfacePresentScalingCapabilitiesEXT>( auto surface_scaling_capabilities = util::find_extension<VkSurfacePresentScalingCapabilitiesEXT>(
VK_STRUCTURE_TYPE_SURFACE_PRESENT_SCALING_CAPABILITIES_EXT, pSurfaceCapabilities); VK_STRUCTURE_TYPE_SURFACE_PRESENT_SCALING_CAPABILITIES_EXT, pSurfaceCapabilities);
@ -245,7 +246,7 @@ VkResult surface_properties::get_surface_formats(VkPhysicalDevice physical_devic
VkResult surface_properties::get_surface_present_modes(VkPhysicalDevice physical_device, VkSurfaceKHR surface, VkResult surface_properties::get_surface_present_modes(VkPhysicalDevice physical_device, VkSurfaceKHR surface,
uint32_t *pPresentModeCount, VkPresentModeKHR *pPresentModes) uint32_t *pPresentModeCount, VkPresentModeKHR *pPresentModes)
{ {
return get_surface_present_modes_common(pPresentModeCount, pPresentModes, supported_modes); return get_surface_present_modes_common(pPresentModeCount, pPresentModes, m_supported_modes);
} }
VkResult surface_properties::get_required_device_extensions(util::extension_list &extension_list) VkResult surface_properties::get_required_device_extensions(util::extension_list &extension_list)
@ -413,7 +414,7 @@ void surface_properties::get_surface_present_scaling_and_gravity(
bool surface_properties::is_compatible_present_modes(VkPresentModeKHR present_mode_a, VkPresentModeKHR present_mode_b) bool surface_properties::is_compatible_present_modes(VkPresentModeKHR present_mode_a, VkPresentModeKHR present_mode_b)
{ {
return is_compatible_present_modes_common(present_mode_a, present_mode_b, present_mode_compatibilities); return m_compatible_present_modes.is_compatible_present_modes(present_mode_a, present_mode_b);
} }
} // namespace wayland } // namespace wayland

View file

@ -26,6 +26,7 @@
#include "wsi/surface_properties.hpp" #include "wsi/surface_properties.hpp"
#include "util/unordered_set.hpp" #include "util/unordered_set.hpp"
#include "wsi/compatible_present_modes.hpp"
namespace wsi namespace wsi
{ {
@ -84,10 +85,10 @@ private:
surface_format_properties_map supported_formats; surface_format_properties_map supported_formats;
/* List of supported presentation modes */ /* List of supported presentation modes */
std::array<VkPresentModeKHR, 2> supported_modes; std::array<VkPresentModeKHR, 2> m_supported_modes;
/* Stores compatible presentation modes */ /* Stores compatible presentation modes */
std::array<present_mode_compatibility, 2> present_mode_compatibilities; compatible_present_modes<2> m_compatible_present_modes;
void populate_present_mode_compatibilities() override; void populate_present_mode_compatibilities() override;