1// Copyright (c) 2016-2018 Google LLC. 2// 3// SPDX-License-Identifier: CC-BY-4.0 4 5== Display Timing Queries 6 7Traditional game and real-time-animation applications frequently use 8ename:VK_PRESENT_MODE_FIFO_KHR so that presentable images are updated during 9the vertical blanking period of a given refresh cycle (RC) of the 10presentation engine's display. 11This avoids the visual anomaly known as tearing. 12 13However, synchronizing the presentation of images with the RC does not 14prevent all forms of visual anomalies. 15Stuttering occurs when the geometry for each presentable image is not 16accurately positioned for when that image will be displayed. 17The geometry may appear to move too little some RCs, and too much for 18others. 19Sometimes the animation appears to freeze, when the same image is used for 20more than one RC. 21 22In order to minimize stuttering, an application needs to correctly position 23their geometry for when the presentable image will be displayed to the user. 24To accomplish this, applications need various timing information about the 25presentation engine's display. 26They need to know when presentable images were actually presented, and when 27they could have been presented. 28Applications also need to tell the presentation engine to display an image 29no sooner than a given time. 30This can allow the application's animation to look smooth to the user, with 31no stuttering. 32The `VK_GOOGLE_display_timing` extension allows an application to satisfy 33these needs. 34 35The presentation engine's display typically refreshes the pixels that are 36displayed to the user on a periodic basis. 37The period may be fixed or variable. 38In many cases, the presentation engine is associated with fixed refresh rate 39(FRR) display technology, with a fixed refresh rate (RR, e.g. 60Hz). 40In some cases, the presentation engine is associated with variable refresh 41rate (VRR) display technology, where each refresh cycle (RC) can vary in 42length. 43This extension treats VRR displays as if they are FRR. 44 45[open,refpage='vkGetRefreshCycleDurationGOOGLE',desc='Obtain the RC duration of the PE\'s display',type='protos'] 46-- 47To query the duration of a refresh cycle (RC) for the presentation engine's 48display, call: 49 50include::{generated}/api/protos/vkGetRefreshCycleDurationGOOGLE.txt[] 51 52 * pname:device is the device associated with pname:swapchain. 53 * pname:swapchain is the swapchain to obtain the refresh duration for. 54 * pname:pDisplayTimingProperties is a pointer to a 55 sname:VkRefreshCycleDurationGOOGLE structure. 56 57include::{generated}/validity/protos/vkGetRefreshCycleDurationGOOGLE.txt[] 58-- 59 60[open,refpage='VkRefreshCycleDurationGOOGLE',desc='Structure containing the RC duration of a display',type='structs'] 61-- 62The sname:VkRefreshCycleDurationGOOGLE structure is defined as: 63 64include::{generated}/api/structs/VkRefreshCycleDurationGOOGLE.txt[] 65 66 * pname:refreshDuration is the number of nanoseconds from the start of one 67 refresh cycle to the next. 68 69include::{generated}/validity/structs/VkRefreshCycleDurationGOOGLE.txt[] 70-- 71 72[NOTE] 73.Note 74==== 75The rate at which an application renders and presents new images is known as 76the image present rate (IPR, aka frame rate). 77The inverse of IPR, or the duration between each image present, is the image 78present duration (IPD). 79In order to provide a smooth, stutter-free animation, an application will 80want its IPD to be a multiple of pname:refreshDuration. 81For example, if a display has a 60Hz refresh rate, pname:refreshDuration 82will be a value in nanoseconds that is approximately equal to 16.67ms. 83In such a case, an application will want an IPD of 16.67ms (1X multiplier of 84pname:refreshDuration), or 33.33ms (2X multiplier of pname:refreshDuration), 85or 50.0ms (3X multiplier of pname:refreshDuration), etc. 86 87In order to determine a target IPD for a display (i.e. a multiple of 88pname:refreshDuration), an application needs to determine when its images 89are actually displayed. 90Suppose an application has an initial target IPD of 16.67ms (1X multiplier 91of pname:refreshDuration). 92It will therefore position the geometry of a new image 16.67ms later than 93the previous image. 94But suppose this application is running on slower hardware, so that it 95actually takes 20ms to render each new image. 96This will create visual anomalies, because the images will not be displayed 97to the user every 16.67ms, nor every 20ms. 98In this case, it is better for the application to adjust its target IPD to 9933.33ms (i.e. a 2X multiplier of pname:refreshDuration), and tell the 100presentation engine to not present images any sooner than every 33.33ms. 101This will allow the geometry to be correctly positioned for each presentable 102image. 103 104Adjustments to an application's IPD may be needed because different views of 105an application's geometry can take different amounts of time to render. 106For example, looking at the sky may take less time to render than looking at 107multiple, complex items in a room. 108In general, it is good to not frequently change IPD, as that can cause 109visual anomalies. 110Adjustments to a larger IPD because of late images should happen quickly, 111but adjustments to a smaller IPD should only happen if the 112pname:actualPresentTime and pname:earliestPresentTime members of the 113slink:VkPastPresentationTimingGOOGLE structure are consistently different, 114and if pname:presentMargin is consistently large, over multiple images. 115==== 116 117[open,refpage='vkGetPastPresentationTimingGOOGLE',desc='Obtain timing of a previously-presented image',type='protos'] 118-- 119The implementation will maintain a limited amount of history of timing 120information about previous presents. 121Because of the asynchronous nature of the presentation engine, the timing 122information for a given flink:vkQueuePresentKHR command will become 123available some time later. 124These time values can be asynchronously queried, and will be returned if 125available. 126All time values are in nanoseconds, relative to a monotonically-increasing 127clock (e.g. `CLOCK_MONOTONIC` (see clock_gettime(2)) on Android and Linux). 128 129To asynchronously query the presentation engine, for newly-available timing 130information about one or more previous presents to a given swapchain, call: 131 132include::{generated}/api/protos/vkGetPastPresentationTimingGOOGLE.txt[] 133 134 * pname:device is the device associated with pname:swapchain. 135 * pname:swapchain is the swapchain to obtain presentation timing 136 information duration for. 137 * pname:pPresentationTimingCount is a pointer to an integer related to the 138 number of sname:VkPastPresentationTimingGOOGLE structures to query, as 139 described below. 140 * pname:pPresentationTimings is either `NULL` or a pointer to an array of 141 sname:VkPastPresentationTimingGOOGLE structures. 142 143If pname:pPresentationTimings is `NULL`, then the number of newly-available 144timing records for the given pname:swapchain is returned in 145pname:pPresentationTimingCount. 146Otherwise, pname:pPresentationTimingCount must: point to a variable set by 147the user to the number of elements in the pname:pPresentationTimings array, 148and on return the variable is overwritten with the number of structures 149actually written to pname:pPresentationTimings. 150If the value of pname:pPresentationTimingCount is less than the number of 151newly-available timing records, at most pname:pPresentationTimingCount 152structures will be written, and ename:VK_INCOMPLETE will be returned instead 153of ename:VK_SUCCESS, to indicate that not all the available timing records 154were returned. 155 156include::{generated}/validity/protos/vkGetPastPresentationTimingGOOGLE.txt[] 157-- 158 159[open,refpage='VkPastPresentationTimingGOOGLE',desc='Structure containing timing information about a previously-presented image',type='structs'] 160-- 161The sname:VkPastPresentationTimingGOOGLE structure is defined as: 162 163include::{generated}/api/structs/VkPastPresentationTimingGOOGLE.txt[] 164 165 * pname:presentID is an application-provided value that was given to a 166 previous fname:vkQueuePresentKHR command via 167 slink:VkPresentTimeGOOGLE::pname:presentID (see below). 168 It can: be used to uniquely identify a previous present with the 169 flink:vkQueuePresentKHR command. 170 * pname:desiredPresentTime is an application-provided value that was given 171 to a previous flink:vkQueuePresentKHR command via 172 slink:VkPresentTimeGOOGLE::pname:desiredPresentTime. 173 If non-zero, it was used by the application to indicate that an image 174 not be presented any sooner than pname:desiredPresentTime. 175 * pname:actualPresentTime is the time when the image of the 176 pname:swapchain was actually displayed. 177 * pname:earliestPresentTime is the time when the image of the 178 pname:swapchain could have been displayed. 179 This may: differ from pname:actualPresentTime if the application 180 requested that the image be presented no sooner than 181 slink:VkPresentTimeGOOGLE::pname:desiredPresentTime. 182 * pname:presentMargin is an indication of how early the 183 fname:vkQueuePresentKHR command was processed compared to how soon it 184 needed to be processed, and still be presented at 185 pname:earliestPresentTime. 186 187The results for a given pname:swapchain and pname:presentID are only 188returned once from fname:vkGetPastPresentationTimingGOOGLE. 189 190The application can: use the sname:VkPastPresentationTimingGOOGLE values to 191occasionally adjust its timing. 192For example, if pname:actualPresentTime is later than expected (e.g. one 193pname:refreshDuration late), the application may increase its target IPD to 194a higher multiple of pname:refreshDuration (e.g. decrease its frame rate 195from 60Hz to 30Hz). 196If pname:actualPresentTime and pname:earliestPresentTime are consistently 197different, and if pname:presentMargin is consistently large enough, the 198application may decrease its target IPD to a smaller multiple of 199pname:refreshDuration (e.g. increase its frame rate from 30Hz to 60Hz). 200If pname:actualPresentTime and pname:earliestPresentTime are same, and if 201pname:presentMargin is consistently high, the application may delay the 202start of its input-render-present loop in order to decrease the latency 203between user input and the corresponding present (always leaving some margin 204in case a new image takes longer to render than the previous image). 205An application that desires its target IPD to always be the same as 206pname:refreshDuration, can also adjust features until 207pname:actualPresentTime is never late and pname:presentMargin is 208satisfactory. 209-- 210 211The full `apiext:VK_GOOGLE_display_timing` extension semantics are described 212for swapchains created with ename:VK_PRESENT_MODE_FIFO_KHR. 213For example, non-zero values of 214sname:VkPresentTimeGOOGLE::pname:desiredPresentTime must: be honored, and 215fname:vkGetPastPresentationTimingGOOGLE should: return a 216sname:VkPastPresentationTimingGOOGLE structure with valid values for all 217images presented with fname:vkQueuePresentKHR. 218The semantics for other present modes are as follows: 219 220 * ename:VK_PRESENT_MODE_IMMEDIATE_KHR. 221 The presentation engine may: ignore non-zero values of 222 sname:VkPresentTimeGOOGLE::pname:desiredPresentTime in favor of 223 presenting immediately. 224 The value of 225 sname:VkPastPresentationTimingGOOGLE::pname:earliestPresentTime must: be 226 the same as 227 sname:VkPastPresentationTimingGOOGLE::pname:actualPresentTime, which 228 should: be when the presentation engine displayed the image. 229 * ename:VK_PRESENT_MODE_MAILBOX_KHR. 230 The intention of using this present mode with this extension is to 231 handle cases where an image is presented late, and the next image is 232 presented soon enough to replace it at the next vertical blanking 233 period. 234 For images that are displayed to the user, the value of 235 sname:VkPastPresentationTimingGOOGLE::pname:actualPresentTime must: be 236 when the image was displayed. 237 For images that are not displayed to the user, 238 fname:vkGetPastPresentationTimingGOOGLE may: not return a 239 sname:VkPastPresentationTimingGOOGLE structure, or it may: return a 240 sname:VkPastPresentationTimingGOOGLE structure with the value of zero 241 for both sname:VkPastPresentationTimingGOOGLE::pname:actualPresentTime 242 and sname:VkPastPresentationTimingGOOGLE::pname:earliestPresentTime. 243 It is possible that an application can: submit images with 244 sname:VkPresentTimeGOOGLE::pname:desiredPresentTime values such that new 245 images may: not be displayed. 246 For example, if sname:VkPresentTimeGOOGLE::pname:desiredPresentTime is 247 far enough in the future that an image is not presented before 248 fname:vkQueuePresentKHR is called to present another image, the first 249 image will not be displayed to the user. 250 If the application continues to do that, the presentation may: not 251 display new images. 252 * ename:VK_PRESENT_MODE_FIFO_RELAXED_KHR. 253 For images that are presented in time to be displayed at the next 254 vertical blanking period, the semantics are identical as for 255 ename:VK_PRESENT_MODE_FIFO_RELAXED_KHR. 256 For images that are presented late, and are displayed after the start of 257 the vertical blanking period (i.e. with tearing), the values of 258 sname:VkPastPresentationTimingGOOGLE may: be treated as if the image was 259 displayed at the start of the vertical blanking period, or may: be 260 treated the same as for ename:VK_PRESENT_MODE_IMMEDIATE_KHR. 261