1// Copyright 2022 The Khronos Group Inc. 2// 3// SPDX-License-Identifier: CC-BY-4.0 4 5= VK_EXT_surface_maintenance1 6:toc: left 7:refpage: https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/ 8:sectnums: 9 10This proposal investigates and addresses a number of practical issues with the 11`VK_KHR_surface` specification. 12 13== Problem Statement 14 15The following is a list of issues considered in this proposal: 16 17 * Min and max image count as reported in `VkSurfaceCapabilitiesKHR` depend on 18 present mode. 19 * The scaling behavior of the surface is undefined when the swapchain and 20 the surface dimensions do not match. 21 * Switching between some present modes technically should not require 22 recreating the swapchain 23 24=== Image Count Query Per Present Mode 25 26The implementation may require a different number of images, as reported in 27`VkSurfaceCapabilitiesKHR::minImageCount` and 28`VkSurfaceCapabilitiesKHR::maxImageCount` depending on the desired present mode. 29However, there is currently no way to specify the present mode when calling 30`vkGetPhysicalDeviceSurfaceCapabilitiesKHR`. 31 32=== Undefined Scaling Behavior 33 34Currently, a few of the surface extensions (such as `VK_KHR_xcb_surface` and 35`VK_KHR_win32_surface`) require the swapchain's extents to match the surface's. 36A mismatch between the swapchain and the surface dimensions, as the window is 37resized, would result in `VK_ERROR_OUT_OF_DATE_KHR`, which can be undesirable 38behavior. 39On other surfaces where scaling happens, it is undefined how the image is 40scaled. 41The image may stretch, scale with fixed aspect ratio, snap to a corner or be 42centered. 43 44=== Switching Present Modes 45 46Certain present modes are compatible, such that a swapchain operating under one 47mode can be easily switched to another. 48In such a case, recreating the swapchain is undesirable. 49 50See the proposal for `VK_EXT_swapchain_maintenance1` for details. 51 52== Solution Space 53 54=== Image Count Query Per Present Mode 55 56This issue can be rectified by providing the desired present mode when querying 57surface capabilities. 58 59=== Undefined Scaling Behavior 60 61This issue can be resolved by the application querying and opting in to a 62specific supported scaling behavior. Potential behaviors are: 63 64 * Stretch the swapchain image to the dimensions of the surface 65 * Stretch the swapchain image while maintaining the aspect ratio to fit 66 within the surface 67 * No scaling applied, and swapchain pixels are mapped one-to-one to the 68 surface 69 70When the resulting image does not cover the entire surface, additional behavior 71can be specified for each of the X and Y axes: 72 73 * Gravitate to left/top 74 * Gravitate to right/bottom 75 * Center 76 77This extension allows the supported behavior to be queried, while 78`VK_EXT_swapchain_maintenance1` would be used to select the desired behavior at 79swapchain creation time. 80 81=== Switching Present Modes 82 83To support the `VK_EXT_swapchain_maintenance1` extension and allow creating 84swapchains that may change present modes, it should be possible to query the 85set of compatible present modes for this purpose. 86 87This can be done by providing one present mode and querying the list of 88compatible present modes from the surface. 89 90== Proposal 91 92Introduced by this API are: 93 94=== Image Count Query Per Present Mode 95 96To query the min and max image counts for a specific present mode, chain the 97following to `VkPhysicalDeviceSurfaceInfo2KHR` when calling 98`vkGetPhysicalDeviceSurfaceCapabilities2KHR`: 99 100[source,c] 101---- 102typedef struct VkSurfacePresentModeEXT { 103 VkStructureType sType; 104 void* pNext; 105 VkPresentModeKHR presentMode; 106} VkSurfacePresentModeEXT; 107---- 108 109The returned values in `VkSurfaceCapabilitiesKHR::minImageCount` and 110`VkSurfaceCapabilitiesKHR::maxImageCount` would then be specific to the given 111present mode. 112 113=== Undefined Scaling Behavior 114 115To query supported scaling behavior, chain `VkSurfacePresentModeEXT` to 116`VkPhysicalDeviceSurfaceInfo2KHR` and chain the following to 117`VkSurfaceCapabilities2KHR`: 118 119[source,c] 120---- 121typedef struct VkSurfacePresentScalingCapabilitiesEXT { 122 VkStructureType sType; 123 void* pNext; 124 VkPresentScalingFlagsEXT supportedPresentScaling; 125 VkPresentGravityFlagsEXT supportedPresentGravityX; 126 VkPresentGravityFlagsEXT supportedPresentGravityY; 127 VkExtent2D minScaledImageExtent; 128 VkExtent2D maxScaledImageExtent; 129} VkSurfacePresentScalingCapabilitiesEXT; 130---- 131 132Where `VkPresentScalingFlagsEXT` is defined as: 133 134[source,c] 135---- 136typedef enum VkPresentScalingFlagBitsEXT { 137 VK_PRESENT_SCALING_ONE_TO_ONE_BIT_EXT = 0x00000001, 138 VK_PRESENT_SCALING_ASPECT_RATIO_STRETCH_BIT_EXT = 0x00000002, 139 VK_PRESENT_SCALING_STRETCH_BIT_EXT = 0x00000004, 140} VkPresentScalingFlagBitsEXT; 141 142typedef VkFlags VkPresentScalingFlagsEXT; 143---- 144 145And `VkPresentGravityFlagsEXT` is defined as: 146 147[source,c] 148---- 149typedef enum VkPresentGravityFlagBitsEXT { 150 VK_PRESENT_GRAVITY_MIN_BIT_EXT = 0x00000001, 151 VK_PRESENT_GRAVITY_MAX_BIT_EXT = 0x00000002, 152 VK_PRESENT_GRAVITY_CENTERED_BIT_EXT = 0x00000004, 153} VkPresentGravityFlagBitsEXT; 154 155typedef VkFlags VkPresentGravityFlagsEXT; 156---- 157 158Note that scaling may not be supported for certain present modes. 159 160The `VK_EXT_swapchain_maintenance1` extension must be used to create a 161swapchain with a supported behavior. 162Swapchains created with scaling enabled, must use image extents that are 163bounded by `minScaledImageExtent` and `maxScaledImageExtent`. 164 165=== Switching Present Modes 166 167To query the list of compatible present modes with a given present mode for the 168purposes of mode switching, chain `VkSurfacePresentModeEXT` to 169`VkPhysicalDeviceSurfaceInfo2KHR` and chain the following to 170`VkSurfaceCapabilities2KHR`: 171 172[source,c] 173---- 174typedef struct VkSurfacePresentModeCompatibilityEXT { 175 VkStructureType sType; 176 void* pNext; 177 uint32_t presentModeCount; 178 VkPresentMode* pPresentModes; 179} VkSurfacePresentModeCompatibilityEXT; 180---- 181 182The implementation will return the count of compatible present modes in 183`presentModeCount`, and if provided, the list of them in `pPresentModes`. 184 185== Issues 186