diff --git a/wsi/headless/surface_properties.cpp b/wsi/headless/surface_properties.cpp index 113db07..76f8d1c 100644 --- a/wsi/headless/surface_properties.cpp +++ b/wsi/headless/surface_properties.cpp @@ -87,6 +87,16 @@ VkResult surface_properties::get_surface_capabilities(VkPhysicalDevice physical_ 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); + + auto surface_scaling_capabilities = util::find_extension( + VK_STRUCTURE_TYPE_SURFACE_PRESENT_SCALING_CAPABILITIES_EXT, surface_capabilities); + if (surface_scaling_capabilities != nullptr) + { + get_surface_present_scaling_and_gravity(surface_scaling_capabilities); + surface_scaling_capabilities->minScaledImageExtent = surface_capabilities->surfaceCapabilities.minImageExtent; + surface_scaling_capabilities->maxScaledImageExtent = surface_capabilities->surfaceCapabilities.maxImageExtent; + } + return VK_SUCCESS; } @@ -190,5 +200,13 @@ bool surface_properties::is_surface_extension_enabled(const layer::instance_priv return instance_data.is_instance_extension_enabled(VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME); } +void surface_properties::get_surface_present_scaling_and_gravity( + VkSurfacePresentScalingCapabilitiesEXT *scaling_capabilities) +{ + scaling_capabilities->supportedPresentScaling = 0; + scaling_capabilities->supportedPresentGravityX = 0; + scaling_capabilities->supportedPresentGravityY = 0; +} + } /* namespace headless */ } /* namespace wsi */ diff --git a/wsi/headless/surface_properties.hpp b/wsi/headless/surface_properties.hpp index 4fe158f..53841bb 100644 --- a/wsi/headless/surface_properties.hpp +++ b/wsi/headless/surface_properties.hpp @@ -68,6 +68,8 @@ private: std::array present_mode_compatibilities; void populate_present_mode_compatibilities() override; + + void get_surface_present_scaling_and_gravity(VkSurfacePresentScalingCapabilitiesEXT *scaling_capabilities) override; }; } /* namespace headless */ diff --git a/wsi/surface_properties.hpp b/wsi/surface_properties.hpp index d25723f..16a86b1 100644 --- a/wsi/surface_properties.hpp +++ b/wsi/surface_properties.hpp @@ -115,6 +115,12 @@ public: /* There is no maximum theoretically speaking however we choose 6 for practicality */ static constexpr uint32_t MAX_SWAPCHAIN_IMAGE_COUNT = 6; + /** + * @brief Get the scaling and gravity capabilities of the surface. + */ + virtual void get_surface_present_scaling_and_gravity( + VkSurfacePresentScalingCapabilitiesEXT *scaling_capabilities) = 0; + private: /** * @brief Set which presentation modes are compatible with each other for a particular surface diff --git a/wsi/swapchain_base.cpp b/wsi/swapchain_base.cpp index 1fb7098..d4c2d14 100644 --- a/wsi/swapchain_base.cpp +++ b/wsi/swapchain_base.cpp @@ -45,6 +45,7 @@ #include "util/helpers.hpp" #include "swapchain_base.hpp" +#include "wsi_factory.hpp" namespace wsi { @@ -224,6 +225,34 @@ swapchain_base::swapchain_base(layer::device_private_data &dev_data, const VkAll { } +static VkResult handle_scaling_create_info(VkDevice device, const VkSwapchainCreateInfoKHR *swapchain_create_info, + const VkSurfaceKHR &surface) +{ + + auto present_scaling_create_info = util::find_extension( + VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_SCALING_CREATE_INFO_EXT, swapchain_create_info); + if (present_scaling_create_info != nullptr) + { + auto &device_data = layer::device_private_data::get(device); + auto &instance = device_data.instance_data; + + VkSurfacePresentScalingCapabilitiesEXT scaling_capabilities = {}; + wsi::surface_properties *props = wsi::get_surface_properties(instance, surface); + props->get_surface_present_scaling_and_gravity(&scaling_capabilities); + + if (((present_scaling_create_info->scalingBehavior != 0) && + ((scaling_capabilities.supportedPresentScaling & present_scaling_create_info->scalingBehavior) == 0)) || + ((present_scaling_create_info->presentGravityX != 0) && + ((scaling_capabilities.supportedPresentGravityX & present_scaling_create_info->presentGravityX) == 0)) || + ((present_scaling_create_info->presentGravityY != 0) && + ((scaling_capabilities.supportedPresentGravityY & present_scaling_create_info->presentGravityY) == 0))) + { + return VK_ERROR_INITIALIZATION_FAILED; + } + } + return VK_SUCCESS; +} + VkResult swapchain_base::init(VkDevice device, const VkSwapchainCreateInfoKHR *swapchain_create_info) { assert(device != VK_NULL_HANDLE); @@ -256,6 +285,8 @@ VkResult swapchain_base::init(VkDevice device, const VkSwapchainCreateInfoKHR *s return VK_ERROR_OUT_OF_HOST_MEMORY; } + TRY_LOG_CALL(handle_scaling_create_info(device, swapchain_create_info, m_surface)); + /* We have allocated images, we can call the platform init function if something needs to be done. */ bool use_presentation_thread = true; TRY_LOG_CALL(init_platform(device, swapchain_create_info, use_presentation_thread)); diff --git a/wsi/wayland/surface_properties.cpp b/wsi/wayland/surface_properties.cpp index 9981026..f6fec8a 100644 --- a/wsi/wayland/surface_properties.cpp +++ b/wsi/wayland/surface_properties.cpp @@ -99,6 +99,15 @@ VkResult surface_properties::get_surface_capabilities(VkPhysicalDevice physical_ get_surface_present_mode_compatibility_common(pSurfaceInfo, pSurfaceCapabilities, present_mode_compatibilities); + auto surface_scaling_capabilities = util::find_extension( + VK_STRUCTURE_TYPE_SURFACE_PRESENT_SCALING_CAPABILITIES_EXT, pSurfaceCapabilities); + if (surface_scaling_capabilities != nullptr) + { + get_surface_present_scaling_and_gravity(surface_scaling_capabilities); + surface_scaling_capabilities->minScaledImageExtent = pSurfaceCapabilities->surfaceCapabilities.minImageExtent; + surface_scaling_capabilities->maxScaledImageExtent = pSurfaceCapabilities->surfaceCapabilities.maxImageExtent; + } + return VK_SUCCESS; } @@ -394,5 +403,13 @@ bool surface_properties::is_surface_extension_enabled(const layer::instance_priv return instance_data.is_instance_extension_enabled(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME); } +void surface_properties::get_surface_present_scaling_and_gravity( + VkSurfacePresentScalingCapabilitiesEXT *scaling_capabilities) +{ + scaling_capabilities->supportedPresentScaling = VK_PRESENT_SCALING_ONE_TO_ONE_BIT_EXT; + scaling_capabilities->supportedPresentGravityX = VK_PRESENT_GRAVITY_MIN_BIT_EXT; + scaling_capabilities->supportedPresentGravityY = VK_PRESENT_GRAVITY_MIN_BIT_EXT; +} + } // namespace wayland } // namespace wsi diff --git a/wsi/wayland/surface_properties.hpp b/wsi/wayland/surface_properties.hpp index 7c16b76..27197e2 100644 --- a/wsi/wayland/surface_properties.hpp +++ b/wsi/wayland/surface_properties.hpp @@ -88,6 +88,8 @@ private: std::array present_mode_compatibilities; void populate_present_mode_compatibilities() override; + + void get_surface_present_scaling_and_gravity(VkSurfacePresentScalingCapabilitiesEXT *scaling_capabilities) override; }; } // namespace wayland