diff --git a/chapters/VK_EXT_present_timing/queries.adoc b/chapters/VK_EXT_present_timing/queries.adoc index 0e426646f0..bf796c499b 100644 --- a/chapters/VK_EXT_present_timing/queries.adoc +++ b/chapters/VK_EXT_present_timing/queries.adoc @@ -81,11 +81,11 @@ include::{generated}/api/protos/vkGetSwapchainTimingPropertiesEXT.adoc[] * pname:device is the device associated with pname:swapchain. * pname:swapchain is the swapchain to obtain timing properties for. - * pname:pSwapchainTimingProperties is a pointer to an instance of the - slink:VkSwapchainTimingPropertiesEXT structure. * pname:pSwapchainTimingPropertiesCounter is `NULL` or a pointer to a 64-bit unsigned integer set by the implementation to the current value of the swapchain's internal timing properties counter. + * pname:pSwapchainTimingProperties is a pointer to an instance of the + slink:VkSwapchainTimingPropertiesEXT structure. include::{generated}/validity/protos/vkGetSwapchainTimingPropertiesEXT.adoc[] -- @@ -103,12 +103,11 @@ include::{generated}/api/structs/VkSwapchainTimingPropertiesEXT.adoc[] * pname:refreshDuration is zero or an indication of the duration of a refresh cycle. If the presentation engine is operating as an FRR display, this is the - number of nanoseconds from the start of one refresh cycle to the - start of the next refresh cycle. - If the presentation engine is operating as a VRR display - (i.e. refresh cycles may: have variable length), this is the - minimum number of nanoseconds from the start of one refresh cycle - to the start of the next refresh cycle. + number of nanoseconds from the start of one refresh cycle to the start of + the next refresh cycle. + If the presentation engine is operating as a VRR display (i.e. refresh + cycles may: have variable length), this is the minimum number of nanoseconds + from the start of one refresh cycle to the start of the next refresh cycle. * pname:variableRefreshDelay is undefined: if pname:refreshDuration is zero; otherwise it is a duration in nanoseconds indicating the maximum theoretical delay for the presentation engine to start a new refresh @@ -170,42 +169,34 @@ feedback of slink:VkPastPresentationTimingEXT values indicates that the target IPD can be durably achieved. ==== -[open,refpage='vkGetSwapchainTimeDomainsEXT',desc='Obtain the time domains supported by the PE for the swapchain',type='protos'] +[open,refpage='vkGetSwapchainTimeDomainPropertiesEXT',desc='Obtain the time domains supported by the PE for the swapchain',type='protos'] -- +The implementation maintains an internal monotonically increasing counter which +updates when the presentation engine's list of supported time domains for a +swapchain is modified. -To query the time domain used by the presentation engine for a given swapchain, +To query the time domains supported by the presentation engine for a given swapchain, call: -include::{generated}/api/protos/vkGetSwapchainTimeDomainsEXT.adoc[] +include::{generated}/api/protos/vkGetSwapchainTimeDomainPropertiesEXT.adoc[] * pname:device is the device associated with pname:swapchain. - * pname:swapchain is the swapchain to obtain timing properties for. - * pname:pSwapchainTimeDomainCount is a pointer to an integer related to the - number of time domains available or queried, as described below. - * pname:pSwapchainTimeDomains is either `NULL` or a pointer to an array of - slink:VkSwapchainTimeDomainPropertiesEXT structs, indicating the supported time - domains of the presentation engine for the swapchain. - -If pname:pSwapchainTimeDomains is `NULL`, then the number of time domains -supported for the given pname:swapchain is returned in -pname:pSwapchainTimeDomainCount (if this value is zero, pname:swapchain -does not currently support display timing). -Otherwise, pname:pSwapchainTimeDomainCount must: point to a variable set by the user -to the number of elements in the pname:pSwapchainTimeDomains array, and on return -the variable is overwritten with the number of values actually written to -pname:pSwapchainTimeDomains. -If the value of pname:pSwapchainTimeDomainCount is less than the number of -time domains supported, at most pname:pSwapchainTimeDomainCount values will be -written. -If pname:pSwapchainTimeDomainCount is smaller than the number of time domains -supported for the given pname:swapchain, ename:VK_INCOMPLETE will be returned -instead of ename:VK_SUCCESS to indicate that not all the available values -were returned. - -include::{generated}/validity/protos/vkGetSwapchainTimeDomainsEXT.adoc[] + * pname:swapchain is the swapchain to obtain time domain properties for. + * pname:pTimeDomainsCounter is `NULL` or a pointer to a 64-bit unsigned + integer set by the implementation to the current value of the + swapchain's internal time domain properties counter. + * pname:pSwapchainTimeDomainProperties is a pointer to an instance of the + slink:VkSwapchainTimeDomainPropertiesEXT structure. + +If upon return slink:VkSwapchainTimeDomainPropertiesEXT::pname:timeDomainCount +is smaller than the number of time domains supported for the given +pname:swapchain, ename:VK_INCOMPLETE will be returned instead of +ename:VK_SUCCESS to indicate that not all the available values were returned. + +include::{generated}/validity/protos/vkGetSwapchainTimeDomainPropertiesEXT.adoc[] -- -[open,refpage='VkSwapchainTimeDomainPropertiesEXT',desc='An available time domain for a swapchain',type='structs'] +[open,refpage='VkSwapchainTimeDomainPropertiesEXT',desc='List of available time domains for a swapchain',type='structs'] -- The sname:VkSwapchainTimeDomainPropertiesEXT structure is defined as: @@ -215,20 +206,30 @@ include::{generated}/api/structs/VkSwapchainTimeDomainPropertiesEXT.adoc[] * pname:sType is a elink:VkStructureType value identifying this structure. * pname:pNext is `NULL` or a pointer to a structure extending this structure. - * pname:timeDomain is a elink:VkTimeDomainEXT value representing a time - domain that is available for the swapchain. - * pname:timeDomainId is a unique identifier for this time domain within a - swapchain's namespace. + * pname:timeDomainCount is an integer related to the number of time domains + available or queried, as described below. + * pname:pTimeDomains is a pointer to an array of elink:VkTimeDomainEXT values + representing time domains that are available for the swapchain. + * pname:pTimeDomainIds is a pointer to an array of unique identifiers for each + time domain. + +When calling flink:vkGetSwapchainTimeDomainPropertiesEXT, if pname:pTimeDomains +is `NULL` and pname:pTimeDomainIds is `NULL`, then the number of time domains +supported for the given pname:swapchain is returned in +pname:timeDomainCount. Otherwise, pname:timeDomainCount must: specify the number +of elements in the pname:pTimeDomains, pname:pTimeDomainIds, or both arrays, and +on return the variable is overwritten with the number of values actually written +to either array. [NOTE] .Note ==== Due to the dynamic nature of their underlying sname:VkSurfaceKHR properties, -swapchains may need to expose multiple swapchain-local opaque time domains -using the same elink:VkTimeDomainEXT value, for example when a surface is -moved from one display hardware to another. Arbitrary identifiers, provided -in pname:timeDomainId, are used by the implementation to differentiate opaque -time domains of identical scopes. +swapchains may need to expose multiple swapchain-local opaque time domains using +the same elink:VkTimeDomainEXT value over time, for example when a surface is +moved from one display hardware to another. Arbitrary identifiers, provided in +pname:timeDomainIds, are used by the implementation to differentiate opaque time +domains of identical scopes. ==== include::{generated}/validity/structs/VkSwapchainTimeDomainPropertiesEXT.adoc[] @@ -238,8 +239,8 @@ include::{generated}/validity/structs/VkSwapchainTimeDomainPropertiesEXT.adoc[] -- Because of the asynchronous nature of the presentation engine, the timing -information for a given flink:vkQueuePresentKHR command only becomes -available some time later. +information for a given flink:vkQueuePresentKHR command may: only becomes +available some time after the presentation has occured. These time values should: be asynchronously queried, and are returned if available. All time values are in nanoseconds, according to the time-domain being used. @@ -250,32 +251,86 @@ information about one or more previous presents to a given swapchain, call: include::{generated}/api/protos/vkGetPastPresentationTimingEXT.adoc[] * pname:device is the device associated with pname:swapchain. + * pname:pPastPresentationTimingInfo is a pointer to an instance of + the slink:VkPastPresentationTimingInfoEXT structure. + * pname:pPastPresentationTimingProperties is a pointer to an instance + of the slink:VkPastPresentationTimingPropertiesEXT structure. + +If upon return the value of +sname:VkPastPresentationTimingPropertiesEXT::pname:presentationTimingCount is +less than the number of available timing records for the given +sname:VkPastPresentationTimingInfoEXT::pname:swapchain, ename:VK_INCOMPLETE is +returned instead of ename:VK_SUCCESS to indicate that not all the available +values were returned. + +Timing information may: become available out of order with regards to their +associated presentation request submission order. + +Upon return, zero or more slots of the pname:swapchain internal timing results +queue, equal to the number of entries written to +sname:VkPastPresentationTimingPropertiesEXT::pname:pPresentationTimings for +which pname:reportComplete is ename:VK_TRUE, are made available for future +fname:vkQueuePresentKHR calls. Elements of pname:pPresentationTimings are +arranged in ascending order of present ids. + +There is no requirement for any precise timing relationship between the +completion of a present stage and the availability of any associated timing +information. However, results must: be made available in finite time. + +As an exception to the normal rules for objects which are externally +synchronized, pname:swapchain may: be +simultaneously used by other threads in calls to functions other than +flink:vkDestroySwapchainKHR and flink:vkCreateSwapchainKHR with pname:swapchain +used as an pname:oldSwapchain. Access to the swapchain timing information must: +be atomic within the implementation. + +include::{generated}/validity/protos/vkGetPastPresentationTimingEXT.adoc[] +-- + +[open,refpage='VkPastPresentationTimingInfoEXT',desc='Structure specifying swapchain present timing query parameters',type='structs'] +-- + +The sname:VkPastPresentationTimingInfoEXT structure is defined as: + +include::{generated}/api/structs/VkPastPresentationTimingInfoEXT.adoc[] + + * pname:sType is a elink:VkStructureType value identifying this structure. + * pname:pNext is `NULL` or a pointer to a structure extending this + structure. * pname:swapchain is the swapchain to obtain presentation timing - information duration for. - * pname:pPresentationTimingCount is a pointer to an integer related to the - number of slink:VkPastPresentationTimingEXT structures to query, as + information for. + +include::{generated}/validity/structs/VkPastPresentationTimingInfoEXT.adoc[] +-- + +[open,refpage='VkPastPresentationTimingPropertiesEXT',desc='Structure containing details about a swapchain past presentation activity',type='structs'] +-- + +The sname:VkPastPresentationTimingPropertiesEXT structure is defined as: + +include::{generated}/api/structs/VkPastPresentationTimingPropertiesEXT.adoc[] + + * pname:sType is a elink:VkStructureType value identifying this structure. + * pname:pNext is `NULL` or a pointer to a structure extending this + structure. + * pname:timingPropertiesCounter is a 64-bit unsigned integer set by the + implementation to the current value of the swapchain's internal timing + properties counter. + * pname:timeDomainsCounter is a 64-bit unsigned integer set by the + implementation to the current value of the swapchain's internal time + domains list counter. + * pname:presentationTimingCount is an integer related to the number of number + of slink:VkPastPresentationTimingEXT structures available or queried, as described below. - * pname:pPresentationTimings is `NULL` or a pointer to an an array + * pname:pPresentationTimings is `NULL` or a pointer to an array of slink:VkPastPresentationTimingEXT structures. - * pname:pSwapchainTimingPropertiesCounter is `NULL` or a pointer to a - 64-bit unsigned integer set by the implementation to the current value of - the swapchain's internal timing properties counter. - * pname:pTimeDomainsChanged is `NULL` or a pointer to a boolean value - indicating if the list of supported time domains supported by the - pname:swapchain has changed since the last call to this function. - -If pname:pPresentationTimings is `NULL`, then the number of available -timing records for the given pname:swapchain is returned in -pname:pPresentationTimingCount. -Otherwise, pname:pPresentationTimingCount must: point to a variable set by -the user to the number of elements in the pname:pPresentationTimings array, -and on return the variable is overwritten with the number of structures -actually written to pname:pPresentationTimings. -If the value of pname:pPresentationTimingCount is less than the number of -newly-available timing records for the given pname:swapchain, at most -pname:pPresentationTimingCount structures are written, and -ename:VK_INCOMPLETE is returned instead of ename:VK_SUCCESS to indicate that -not all the available values were returned. + +When calling flink:vkGetPastPresentationTimingEXT, if pname:pPresentationTimings +is `NULL`, then the number of available timing records for the given +pname:swapchain is returned in pname:presentationTimingCount. Otherwise, +pname:presentationTimingCount must: specify the number of elements in the +pname:pPresentationTimings array, and on return the variable is overwritten with +the number of structures actually written to pname:pPresentationTimings. fname:vkGetPastPresentationTimingEXT may: return incomplete results, containing only information for a subset of the requested present @@ -288,30 +343,7 @@ every flink:vkQueuePresentKHR referencing pname:swapchain where a non-zero slink:VkPresentTimingInfoEXT::pname:presentStageQueries was specified and at least one present stage has available results. -If pname:pTimeDomainsChanged is ename:VK_TRUE, applications should: query -the new list of available time domains with flink:vkGetSwapchainTimeDomainsEXT. - -Timing information may: become available out of order with regards to their -associated presentation request submission order. - -Upon return, zero or more slots of the pname:swapchain internal timing -results queue, equal to the number of entries written to -pname:pPresentationTimings for which pname:reportComplete is ename:VK_TRUE, -are made available for future fname:vkQueuePresentKHR calls. Elements of -pname:pPresentationTimings are arranged in ascending order of present ids. - -There is no requirement for any precise timing relationship between the -completion of a present stage and the availability of any associated timing -information. - -As an exception to the normal rules for objects which are externally -synchronized, pname:swapchain may: be simultaneously used by other threads -in calls to functions other than flink:vkDestroySwapchainKHR and -flink:vkCreateSwapchainKHR with pname:swapchain used as an -pname:oldSwapchain. Access to the swapchain timing information must: be -atomic within the implementation. - -include::{generated}/validity/protos/vkGetPastPresentationTimingEXT.adoc[] +include::{generated}/validity/structs/VkPastPresentationTimingPropertiesEXT.adoc[] -- [open,refpage='VkPastPresentationTimingEXT',desc='Structure containing timing information about a previously-presented image',type='structs'] @@ -332,8 +364,9 @@ include::{generated}/api/structs/VkPastPresentationTimingEXT.adoc[] * pname:pPresentStages a pointer to an array of slink:VkPresentStageTimeEXT providing timing information for the presentation request associated with pname:presentId. - * pname:timeDomainId is the id of the time domain used by the presentation + * pname:timeDomain is the time domain used by the presentation engine to report times in pname:pPresentStages. + * pname:timeDomainId is the id associated with pname:timeDomain. * pname:reportComplete is ename:VK_TRUE if the presentation engine has reported all the requested results in pname:pPresentStages. @@ -351,15 +384,15 @@ For systems with multiple entities operating within the presentation engine, such as multiple displays, pname:pPresentStages will return timing results for at least one entity which has been affected by the presentation. -pname:timeDomain may: be different than the time domain that was specified -in slink:VkPresentTimingInfoEXT::pname:timeDomain if the requirements for -using this time domain could not be met at the time the presentation engine -processed the presentation request. In such a case, the presentation engine -may: pick a time domain to fall back to and report results in that domain. -Applications can: continue to use this fallback time domain in future +pname:timeDomain may: be different than the time domain that was specified in +slink:VkPresentTimingInfoEXT::pname:timeDomain if the requirements for using +this time domain could not be met at the time the presentation engine processed +the presentation request. In such a case, the presentation engine may: pick a +time domain to fall back to, if one is available, and report results in that +domain. Applications can: continue to use this fallback time domain in future flink:vkQueuePresentKHR calls, or they can: call -flink:vkGetSwapchainTimeDomainsEXT to choose from the currently supported -time domains. +flink:vkGetSwapchainTimeDomainPropertiesEXT to choose from the currently +supported time domains. include::{generated}/validity/structs/VkPastPresentationTimingEXT.adoc[] @@ -408,7 +441,7 @@ full-screen, the timing properties may: be VRR. The available time domains for a swapchain may: change for similar or identical reasons. Therefore, it is possible that the same event will cause both -pname:timingPropertiesChanged to become ename:VK_TRUE and and +pname:timingPropertiesChanged to become ename:VK_TRUE and pname:timeDomain to be different than the time domain requested in slink:VkPresentTimingInfoEXT. ==== diff --git a/chapters/synchronization.adoc b/chapters/synchronization.adoc index 713a79afa5..f1bdcbe353 100644 --- a/chapters/synchronization.adoc +++ b/chapters/synchronization.adoc @@ -7801,7 +7801,7 @@ include::{generated}/api/structs/VkSwapchainCalibratedTimestampInfoEXT.adoc[] * pname:timeDomainId is the id for the opaque time domain being calibrated. pname:timeDomainId must: be an id previously reported by -flink:vkGetSwapchainTimeDomainsEXT for pname:swapchain. If the +flink:vkGetSwapchainTimeDomainPropertiesEXT for pname:swapchain. If the pname:timeDomainId is no longer supported by the pname:swapchain, implementations may: report zero as the calibrated timestamp value. diff --git a/proposals/VK_EXT_present_timing.adoc b/proposals/VK_EXT_present_timing.adoc index a50139db40..dbe84afde8 100644 --- a/proposals/VK_EXT_present_timing.adoc +++ b/proposals/VK_EXT_present_timing.adoc @@ -86,7 +86,7 @@ typedef enum VkPresentStageFlagBitsEXT { When queueing a presentation request for a swapchain, a set of present stages is specified to inform the implementation that timing for all those stages is desired. See <>. -Similarly, when using `presentAtAbsoluteTime` feature to schedule presents at specific times, a present stage must be specified as a target. +Similarly, when using `presentAtAbsoluteTime` feature to schedule presents at specific times, a present stage must be specified as a target. See <>. * `VK_PRESENT_STAGE_QUEUE_OPERATIONS_END_BIT_EXT` marks the end of the set of queue operations enqueued by `vkQueuePresentKHR` on the provided `VkQueue`. These queue operations are implementation-specific; the usual example is a blit to a system-specific internal surface suited for presentation. * `VK_PRESENT_STAGE_IMAGE_LATCHED_BIT_EXT` is the step after which the image associated with the presentation request has been latched by the presentation engine to create the presentation of a future refresh cycle. For example, in a flip-model scenario, this is the time the presentation request's image has been selected for the next refresh cycle. @@ -115,6 +115,8 @@ Calling `vkQueuePresentKHR` with non-zero stage queries allocates a slot in that === Swapchain Timing Information +==== Timing Properties + For timing to be meaningful, the application needs to be aware of various properties. Basic properties are exposed in a new structure, `VkSwapchainTimingPropertiesEXT`, which can be retrieved with: [source,c] @@ -122,14 +124,12 @@ For timing to be meaningful, the application needs to be aware of various proper VkResult vkGetSwapchainTimingPropertiesEXT( VkDevice device, VkSwapchainKHR swapchain, - VkSwapchainTimingPropertiesEXT* pSwapchainTimingProperties, - uint64_t* pSwapchainTimingPropertiesCounter); + uint64_t* pSwapchainTimingPropertiesCounter, + VkSwapchainTimingPropertiesEXT* pSwapchainTimingProperties); ---- - -Swapchain timing properties may change dynamically at any time. To allow applications to detect changes in those properties, a monotonically increasing counter is used by the implementation to identify the current state. This counter increases every time the swapchain properties are modified. `pSwapchainTimingPropertiesCounter` is a pointer to a `uint64_t` set by the implementation to the value of the current timing properties counter. +Swapchain timing properties may change dynamically at any time without prior notification. For example, enabling power-saving mode on a device may cause it to lower the display panel's refresh rate. To allow applications to detect changes in those properties, a monotonically increasing counter is used by the implementation to identify the current state. This counter increases every time the swapchain properties are modified. `pSwapchainTimingPropertiesCounter` is a pointer to a `uint64_t` set by the implementation to the value of the current timing properties counter. Further updates to those properties are communicated back to the application when querying presentation timings via `vkGetPastPresentationTimingEXT`. The `VkSwapchainTimingPropertiesEXT` structure is defined as: - [source,c] ---- typedef struct VkSwapchainTimingPropertiesEXT { @@ -139,36 +139,42 @@ typedef struct VkSwapchainTimingPropertiesEXT { uint64_t variableRefreshDelay; } VkSwapchainTimingPropertiesEXT; ---- - * `refreshDuration` is the duration in nanoseconds of the refresh cycle the presentation engine is operating at. * `variableRefreshDelay` is a duration in nanoseconds indicating the maximum theoretical delay for the presentation engine to start a new refresh cycle upon receiving a presentation request. If this value is the same as `refreshDuration`, the presentation engine is operating in FRR mode. -Those properties may change at any time during an application's runtime without prior notification, in order to satisfy various system constraints or user input. For example, enabling power-saving mode on a device may cause it to lower the display panel's refresh rate. Such changes are communicated back to the application when querying presentation timings via `vkGetSwapchainTimingPropertiesEXT`. - When the presentation engine is operating in VRR mode, `refreshDuration` is the minimum refresh duration. `refreshDuration` may be zero, because some platforms may not provide timing properties until after at least one image has been presented to the swapchain. If timing properties of the swapchain change, updated results may again only be provided until after at least one additional image has been presented. +==== Time Domains + Applications also need to query available time domains using: [source,c] ---- -VkResult vkGetSwapchainTimeDomainsEXT( +VkResult vkGetSwapchainTimeDomainPropertiesEXT( VkDevice device, VkSwapchainKHR swapchain, - uint32_t* pSwapchainTimeDomainCount, - VkSwapchainTimeDomainPropertiesEXT* pSwapchainTimeDomains); + uint64_t* pTimeDomainsCounter, + VkSwapchainTimeDomainPropertiesEXT* pSwapchainTimeDomainProperties); +---- +Similar to <>, supported time domains may change dynamically. `pTimeDomainsCounter` identifies the current list of available time domains, and further internal changes to this list are notified to the application when calling `vkGetPastPresentationTimingEXT`. +The `VkSwapchainTimeDomainPropertiesEXT` structure is defined as: +[source,c] +---- typedef struct VkSwapchainTimeDomainPropertiesEXT { VkStructureType sType; void* pNext; - VkTimeDomainEXT timeDomain; - uint64_t timeDomainId; + uint32_t timeDomainCount; + VkTimeDomainEXT *pTimeDomains; + uint64_t *pTimeDomainIds; } VkSwapchainTimeDomainPropertiesEXT; ---- +* `timeDomainCount` is an input specifying the size of the `pTimeDomains` and `pTimeDomainIds` arrays. If it is 0, it is set by the implementation upon return of `vkGetSwapchainTimeDomainPropertiesEXT` to the number of available time domains. Otherwise, it is set to the number of elements written in `pTimeDomains` and `pTimeDomainIds`. +* `pTimeDomains` is an array of `VkTimeDomainEXT` currently supported by the swapchain. +* `pTimeDomainIds` is an array of unique identifiers for each supported time domain. This is used to differentiate between multiple swapchain-local time domains that have the same `VkTimeDomainEXT` scope. -* `timeDomainId` is a unique identifier for this time domain in a swapchain-local namespace. This is used to differentiate between multiple swapchain-local time domains that have the same `VkTimeDomainEXT` scope. - -Swapchain-local time domains are added in this proposal as two new `VkTimeDomainEXT` values: +Two new swapchain-local time domains are added in this proposal as `VkTimeDomainEXT` values: [source,c] ---- typedef enum VkTimeDomainEXT { @@ -177,7 +183,6 @@ typedef enum VkTimeDomainEXT { VK_TIME_DOMAIN_SWAPCHAIN_LOCAL_EXT = 1000208001, } VkTimeDomainEXT; ---- - * `VK_TIME_DOMAIN_PRESENT_STAGE_LOCAL_EXT` is a stage-local and swapchain-local time domain. It allows platforms where different presentation stages are handled by independent hardware to report timings in their own time domain. It is required to be supported. * `VK_TIME_DOMAIN_SWAPCHAIN_LOCAL_EXT` is a swapchain-local time domain, shared by all present stages. @@ -194,8 +199,8 @@ typedef struct VkSwapchainCalibratedTimestampInfoEXT { uint64_t timeDomainId; } VkSwapchainCalibratedTimestampInfoEXT; ---- - -A single present stage can be specified in `presentStage` to calibrate a `VK_TIME_DOMAIN_PRESENT_STAGE_LOCAL_EXT` timestamp from that stage. +* `presentStage` is zero to calibrate a `VK_TIME_DOMAIN_SWAPCHAIN_LOCAL_EXT` time domain, or a single `VkPresentStageFlagsEXT` bit to calibrate a `VK_TIME_DOMAIN_PRESENT_STAGE_LOCAL_EXT` from that stage. +* `timeDomainId` is the identifier of the swapchain-local time domain returned by `vkGetSwapchainTimeDomainPropertiesEXT` or `vkGetPastPresentationTimingEXT`. === Presentation timings feedback [[statistics]] @@ -204,21 +209,37 @@ Applications can obtain timing information about previous presents using: [source,c] ---- VkResult vkGetPastPresentationTimingEXT( - VkDevice device, - VkSwapchainKHR swapchain, - uint32_t* pPresentationTimingCount, - VkPastPresentationTimingEXT* pPresentationTimings, - uint64_t* pSwapchainTimingPropertiesCounter, - VkBool32* pTimeDomainsChanged); + VkDevice device, + const VkPastPresentationTimingInfoEXT* pPastPresentationTimingInfo, + VkPastPresentationTimingPropertiesEXT* pPastPresentationTimingProperties); +---- +`VkPastPresentationTimingInfoEXT` is a simple input structure referencing the `swapchain` to target, allowing for potential future extensions to hook into the `pNext` chain: +[source,c] +---- +typedef struct VkPastPresentationTimingInfoEXT { + VkStructureType sType; + const void* pNext; + VkSwapchainKHR swapchain; +}; ---- -If the value of `pPresentationTimingCount` is 0, the implementation sets it to the number of pending results available in the swapchain's internal queue. Otherwise, it contains the number of entries written to `pPresentationTimings` upon return. If the implementation is not able to write all the available results in the provided `pPresentationTimings` array, `VK_INCOMPLETE` is returned. - -Results for presentation requests whose entries in `pPresentationTimings` are marked as complete with `VkPastPresentationTimingEXT::reportComplete` will not be returned anymore. For each of those, a slot in the internal swapchain present timing queue is released. Incomplete results for presentation requests will keep being reported by `vkGetPastPresentationTimingEXT` until complete. - -If `pSwapchainTimingPropertiesCounter` is not `NULL`, the implementation sets it to the current internal counter of the swapchain's timing properties. If its value is different than the last known counter value (from a previous call to `vkGetPastPresentationTimingEXT` or `vkGetSwapchainTimingPropertiesEXT`), applications should query those properties again using `vkGetSwapchainTimingPropertiesEXT`. +The `VkPastPresentationTimingPropertiesEXT` structure is defined as: +[source,c] +---- +typedef struct VkPastPresentationTimingPropertiesEXT { + VkStructureType sType; + const void* pNext; + uint64_t timingPropertiesCounter; + uint64_t timeDomainsCounter; + uint32_t presentationTimingCount; + VkPastPresentationTimingEXT* pPresentationTimings; +}; +---- +* `timingPropertiesCounter` is set to the current internal counter of the swapchain's timing properties. +* `timeDomainsCounter` is set to the current internal counter of the swapchain's supported time domain list. +* If the input value of `presentationTimingCount` is 0, the implementation sets it to the number of pending results available in the swapchain's internal queue. Otherwise, it contains the number of entries written to `pPresentationTimings` upon return. If the implementation is not able to write all the available results in the provided `pPresentationTimings` array, `VK_INCOMPLETE` is returned. -`pTimeDomainsChanged` is `VK_TRUE` if the swapchain's list of supported time domains has changed since the last call to `vkGetPastPresentationTimingEXT`. +Results for presentation requests whose entries in `pPresentationTimings` are marked as complete with `VkPastPresentationTimingEXT::reportComplete` will not be returned anymore. For each of those, a slot in the swapchain's internal results queue is released. Incomplete results for presentation requests will keep being reported in further `vkGetPastPresentationTimingEXT` calls until complete. `VkPastPresentationTimingEXT` is defined as: [source, c] @@ -234,14 +255,15 @@ typedef struct VkPastPresentationTimingEXT { uint64_t presentId; uint32_t presentStageCount; VkPresentStageTimeEXT* pPresentStages; + VkTimeDomainEXT timeDomain; uint64_t timeDomainId; VkBool32 reportComplete; } VkPastPresentationTimingEXT; ---- * `presentId` is a present id provided to `vkQueuePresentKHR` by adding a `VkPresentIdKHR` to the `VkPresentInfoKHR` pNext chain. Timing results can be correlated to specific presents using this value. -* `presentStageCount` and `pPresentStages` contain the timing information for the present stages that were specified in the `VkPresentTimeTargetInfoEXT` passed to the corresponding `vkQueuePresentKHR`. -* `timeDomainId` is the id of the time domain used for `pPresentStages` result times. It may be different than the time domain specified for the associated `vkQueuePresentKHR` if that time domain was unavailable when the presentation request was processed. In this case, `timeDomainId` refers to the time domain the presentation engine used as a preferred fallback. +* `presentStageCount` and `pPresentStages` contain the timing information for the present stages that were specified in the `VkPresentTimeTargetInfoEXT` passed to the corresponding `vkQueuePresentKHR` call. +* `timeDomain` and `timeDomainId` define the time domain used for `pPresentStages` result times. It may be different than the time domain specified for the associated `vkQueuePresentKHR` call if that time domain was unavailable when the presentation request was processed. * `reportComplete` indicates whether results for all present stages have been reported. `presentStageCount` only reports the number of stages which contain definitive results. However, time values in completed `pPresentStages` can still be 0 for multiple reasons. Most notably, it is possible for a presentation request to never reach some present stages, for example if using a present mode that allows images to be replaced in the queue, such as `VK_PRESENT_MODE_MAILBOX_KHR`. Platform-specific events can also cause results for some present stages to be unavailable for a specific presentation request. @@ -287,8 +309,8 @@ typedef struct VkPresentTimingsInfoEXT { const VkPresentTimingInfoEXT* pTimingInfos; } VkPresentTimingsInfoEXT; ---- - For each swapchain referenced in `VkPresentInfoKHR`, a `VkPresentTimingInfoEXT` is specified: + * `time` is the absolute or relative time used to schedule this presentation request. * `timeDomainId` is the id of the time domain used to specify `time` and to query timing results. * `presentStageQueries` is a bitmask specifying all the present stages the application would like timings for. @@ -297,6 +319,7 @@ For each swapchain referenced in `VkPresentInfoKHR`, a `VkPresentTimingInfoEXT` * `presentAtNearestRefreshCycle` specifies that the application would like to present at the refresh cycle that is nearest to the target present time. `VkPresentTimeEXT` is interpreted according to the `VkPresentTimingInfoEXT::presentAtRelativeTime` flag: + * `targetPresentTime` specifies the earliest time in nanoseconds the presentation engine can complete the swapchain's target present stage. * `presentDuration` specifies the minimum duration in nanoseconds the application would like the image to be visible. @@ -352,20 +375,27 @@ To maintain a constant IPD, applications should use timing information collected }; uint64_t currentTimingPropertiesCounter = 0; - result = vkGetSwapchainTimingPropertiesEXT(device, swapchain, &swapchainTimingProperties, ¤tTimingPropertiesCounter); + result = vkGetSwapchainTimingPropertiesEXT(device, swapchain, ¤tTimingPropertiesCounter, &swapchainTimingProperties); - uint32_t timeDomainCount = 0; - VkSwapchainTimeDomainPropertiesEXT *timeDomains; + uint64_t currentTimeDomainsCounter = 0; + VkSwapchainTimeDomainPropertiesEXT timeDomains = { + .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_TIME_DOMAIN_PROPERTIES_EXT, + .pNext = NULL, + .timeDomainCount = 0, + .pTimeDomains = NULL, + .pTimeDomainIds = NULL + }; - result = vkGetSwapchainTimeDomainsEXT(device, swapchain, &timeDomainCount, NULL); - timeDomains = (VkSwapchainTimeDomainPropertiesEXT *) malloc(timeDomainCount * sizeof(VkSwapchainTimeDomainPropertiesEXT)); - result = vkGetSwapchainTimeDomainsEXT(device, swapchain, &timeDomainCount, timeDomains); + result = vkGetSwapchainTimeDomainPropertiesEXT(device, swapchain, NULL, &timeDomains); + timeDomains.pTimeDomains = (VkTimeDomainEXT *) malloc(timeDomains.timeDomainCount * sizeof(VkTimeDomainEXT)); + timeDomains.pTimeDomainIds = (uint64_t *) malloc(timeDomains.timeDomainCount * sizeof(uint64_t)); + result = vkGetSwapchainTimeDomainPropertiesEXT(device, swapchain, ¤tTimeDomainsCounter, &timeDomains); // Find the ID of the current VK_TIME_DOMAIN_SWAPCHAIN_LOCAL_EXT time domain - uint64_t currentTimeDomainId = FindTimeDomain(timeDomains, timeDomainCount, VK_TIME_DOMAIN_SWAPCHAIN_LOCAL_EXT); + uint64_t swapchainLocalTimeDomainId = FindTimeDomain(&timeDomains, VK_TIME_DOMAIN_SWAPCHAIN_LOCAL_EXT); // Allocate internal queue to collect present timing results - const uint32_t maxTimingCount = GetMaxTimingCount(); // e.g. swapchainImageCount * 2 + const uint32_t maxTimingCount = GetMaxTimingCount(); // Default to sane value, e.g. swapchainImageCount * 2 result = vkSetSwapchainPresentTimingQueueSizeEXT(device, swapchain, maxTimingCount); // (Start presenting...) @@ -377,36 +407,50 @@ To maintain a constant IPD, applications should use timing information collected ---- uint32_t maxPresentStageCount = 4; uint64_t currentPresentId = 1; - VkPastPresentationTimingEXT *timings = NULL; + VkPastPresentationTimingEXT *pTimings = (VkPastPresentationTimingEXT *) malloc(maxTimingCount * sizeof(VkPastPresentationTimingEXT)); + VkPastPresentationTimingInfoEXT pastPresentationTimingInfo = { + .sType = VK_STRUCTURE_TYPE_PAST_PRESENTATION_TIMING_INFO_EXT, + .pNext = NULL, + .swapchain = swapchain + }; + VkPastPresentationTimingPropertiesEXT pastPresentationTimingProperties = { + .sType = VK_STRUCTURE_TYPE_PAST_PRESENTATION_TIMING_PROPERTIES_EXT, + .pNext = NULL, + .pPresentationTimings = pTimings + }; VkPresentStageFlagBitsEXT targetPresentStage = VK_PRESENT_STAGE_IMAGE_LATCHED_BIT_EXT; - timings = (VkPastPresentationTimingEXT *) malloc(maxTimingCount * sizeof(VkPastPresentationTimingEXT)); for (uint32_t i = 0; i < maxTimingCount; ++i) { - timings[i].pPresentStages = (VkPresentStageTimeEXT *) malloc(maxPresentStageCount * sizeof(VkPastPresentationTimingEXT)); + pTimings[i].pPresentStages = (VkPresentStageTimeEXT *) malloc(maxPresentStageCount * sizeof(VkPresentStageTimeEXT)); } while (!done) { - uint32_t timingCount = maxTimingCount; - uint64_t newTimingPropertiesCounter = 0; + pastPresentationTimingProperties.presentationTimingCount = maxTimingCount; - result = vkGetPastPresentationTimingEXT(device, swapchain, &timingCount, &timings, &newTimingPropertiesCounter); + result = vkGetPastPresentationTimingEXT(device, &pastPresentationTimingInfo, &pastPresentationTimingProperties); - if (newTimingPropertiesCounter != currentTimingPropertiesCounter) { - result = vkGetSwapchainTimingPropertiesEXT(device, swapchain, &swapchainTimingProperties, ¤tTimingPropertiesCounter); - currentTimingPropertiesCounter = newTimingPropertiesCounter; + if (pastPresentationTimingProperties.timingPropertiesCounter != currentTimingPropertiesCounter) { + result = vkGetSwapchainTimingPropertiesEXT(device, swapchain, ¤tTimingPropertiesCounter, &swapchainTimingProperties); + currentTimingPropertiesCounter = pastPresentationTimingProperties.timingPropertiesCounter; } for (uint32_t i = 0; i < timingCount; ++i) { - if (timings[i].reportComplete) { - if (timings[i].timeDomain == currentTimeDomain) { - // Build a presentation history - pastPresentationTimings[timings[i].presentId % maxPresentHistory] = ParseResult(timings[i]); - } else { - // Handle time domain change. A more sophisticated approach can be - // taken with calibrated timestamps to correlate both time domains. - currentTimeDomain = SelectAvailableTimeDomain(swapchain); - InvalidatePastPresentationTimings(); - } + if (timings[i].reportComplete && timings[i].timeDomainId == swapchainLocalTimeDomainId) { + // Build the presentation history for reports that use the expected time domain only. + // This could be handled in a more sophisticated way by calibrating timestamps across + // different time domains if desired. + pastPresentationTimings[timings[i].presentId % maxPresentHistory] = ParseResult(timings[i]); + } + } + + // Re-query time domains if necessary. If our current time domain is not available anymore, start + // over with a new history. + if (pastPresentationTimingProperties.timeDomainsCounter != currentTimeDomainsCounter) { + currentTimeDomainsCounter = UpdateTimeDomains(swapchain, &timeDomains); + uint64_t newSwapchainLocalTimeDomainId = FindTimeDomain(&timeDomains, VK_TIME_DOMAIN_SWAPCHAIN_LOCAL_EXT); + if (newSwapchainLocalTimeDomainId != swapchainLocalTimeDomainId) { + swapchainLocalTimeDomainId = newSwapchainLocalTimeDomainId; + InvalidatePresentationTimingHistory(); } } @@ -417,7 +461,7 @@ To maintain a constant IPD, applications should use timing information collected uint64_t targetPresentTime = pastPresentationTimings[mostRecentResultsIndex].latchTime + (currentPresentId - pastPresentationTimings[mostRecentResultsIndex].presentId) * targetIPD. - // Position scene geometry / camera for `targetPresentTime' + // Position scene geometry for `targetPresentTime' // (...) result = vkAcquireNextImageKHR(...); @@ -431,7 +475,7 @@ To maintain a constant IPD, applications should use timing information collected .sType = VK_STRUCTURE_TYPE_PRESENT_TIME_TARGET_INFO_EXT, .pNext = NULL, .time = targetPresentTime, - .timeDomainId = currentTimeDomain, + .timeDomainId = swapchainLocalTimeDomainId, .presentStageQueries = allStageQueries, .targetPresentStage = VK_PRESENT_STAGE_IMAGE_LATCHED, .presentAtNearestRefreshCycle = VK_TRUE diff --git a/xml/vk.xml b/xml/vk.xml index 0b891447e0..fcc6f15725 100755 --- a/xml/vk.xml +++ b/xml/vk.xml @@ -3210,27 +3210,42 @@ typedef void* MTLSharedEvent_id; VkStructureType sType - void* pNext + void* pNext uint64_t refreshDurationNumber of nanoseconds from the start of one refresh cycle to the next uint64_t variableRefreshDelayNumber of nanoseconds for variable refresh displays to react to IPD changes VkStructureType sType - void* pNext - VkTimeDomainEXT timeDomainAvailable time domain to use with the swapchain - uint64_t timeDomainIdUnique identifier for this time domain + void* pNext + uint32_t timeDomainCount + VkTimeDomainEXT* pTimeDomainsAvailable time domains to use with the swapchain + uint64_t* pTimeDomainIdsUnique identifier for a time domain VkPresentStageFlagsEXT stage uint64_t timeTime in nanoseconds of the associated stage + + VkStructureType sType + const void* pNext + VkSwapchainKHR swapchain + + + VkStructureType sType + void* pNext + uint64_t timingPropertiesCounter + uint64_t timeDomainsCounter + uint32_t presentationTimingCount + VkPastPresentationTimingEXT* pPresentationTimings + VkStructureType sType void* pNext uint64_t presentIdApplication-provided identifier, previously given to vkQueuePresentKHR uint32_t presentStageCountNumber of present stages results available in pPresentStages VkPresentStageTimeEXT* pPresentStagesReported timings for each present stage - uint64_t timeDomainIdTime domain of the present stages + VkTimeDomainEXT timeDomainTime domain of the present stages + uint64_t timeDomainIdTime domain id of the present stages VkBool32 reportCompleteVK_TRUE if all the present stages have been reported @@ -3253,7 +3268,7 @@ typedef void* MTLSharedEvent_id; uint64_t targetPresentTime uint64_t presentDuration - + VkStructureType sType const void* pNext VkSwapchainKHR swapchain @@ -13199,15 +13214,6 @@ typedef void* MTLSharedEvent_id; uint32_t set const void* pData - - VkResult vkGetPastPresentationTimingEXT - VkDevice device - VkSwapchainKHR swapchain - uint32_t* pPresentationTimingCount - VkPastPresentationTimingEXT* pPresentationTimings - uint64_t* pSwapchainTimingPropertiesCounter - VkBool32* pTimeDomainsChanged - void vkSetHdrMetadataEXT VkDevice device @@ -15368,15 +15374,21 @@ typedef void* MTLSharedEvent_id; VkResult vkGetSwapchainTimingPropertiesEXT VkDevice device VkSwapchainKHR swapchain - VkSwapchainTimingPropertiesEXT* pSwapchainTimingProperties uint64_t* pSwapchainTimingPropertiesCounter + VkSwapchainTimingPropertiesEXT* pSwapchainTimingProperties - VkResult vkGetSwapchainTimeDomainsEXT + VkResult vkGetSwapchainTimeDomainPropertiesEXT VkDevice device VkSwapchainKHR swapchain - uint32_t* pSwapchainTimeDomainCount - VkSwapchainTimeDomainPropertiesEXT* pSwapchainTimeDomains + uint64_t* pTimeDomainsCounter + VkSwapchainTimeDomainPropertiesEXT* pSwapchainTimeDomainProperties + + + VkResult vkGetPastPresentationTimingEXT + VkDevice device + const VkPastPresentationTimingInfoEXT* pPastPresentationTimingInfo + VkPastPresentationTimingPropertiesEXT* pPastPresentationTimingProperties VkResult vkGetScreenBufferPropertiesQNX @@ -20062,6 +20074,8 @@ typedef void* MTLSharedEvent_id; + + @@ -20071,7 +20085,7 @@ typedef void* MTLSharedEvent_id; - +