Skip to content

Commit

Permalink
Progress towards final version.
Browse files Browse the repository at this point in the history
This change captures a lot of the recent feedback we had during
the SI meetings and suggestions from comments in this MR:

- Remove VkSwapchainPresentTimingCreateInfo and move relative
  present timing as per-present parameter.

- Internal results queue size is allocated with a new dedicated
  API: vkSetSwapchainPresentTimingQueueSizeEXT. This allows
  applications to resize it without recreating the swapchain.

- Time domains are associated with a unique identifier to allow
  multiple swapchain-local time domains of the same scope to
  coexist.

- Variable refresh rate boolean flag is now a duration indicating
  the delay in "reaction" of the presentation engine to a new
  image. This is meant to support technologies such as dVRR which
  can quickly adjust their refresh cycles.

- Squash the appendix' revision history.

- Add various details in the proposal document
  • Loading branch information
nvlduc committed May 30, 2024
1 parent d525fc7 commit 116c56d
Show file tree
Hide file tree
Showing 7 changed files with 255 additions and 219 deletions.
20 changes: 4 additions & 16 deletions appendices/VK_EXT_present_timing.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -233,19 +233,7 @@ Split it out into its own extension and define the interaction here.
** Internal revisions.

* Revision 2, 2022-11-30 (Lionel Duc)
** Major rebase.
** Add physical device feature flags.
** Rely on VK_KHR_present_id for present ids.
** Resolve issue (11): remove VK_PRESENT_MODE_FIFO_LATEST_READY_EXT.
** Add per-surface capabilities.

* Revision 3, 2023-01-31 (Lionel Duc)
** Propose resolution to issue (9): let the application provide the queue size for the
pending results.

* Revision 4, 2023-05-03 (Lionel Duc)
** Change target and feedback times to be associated with a well-defined present stage.

* Revision 5, 2024-02-10 (Lionel Duc)
** Move swapchain state into per-present struct, removing the need for vkSetSwapchainTimingEXT
** Add stage-local time domain
** Rebase for public discussions.

* Revision 3, 2024-05-29 (Lionel Duc)
** Public revisions.
94 changes: 44 additions & 50 deletions chapters/VK_EXT_present_timing/PresentTimeInfo.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ include::{generated}/validity/structs/VkPresentTimingsInfoEXT.adoc[]
--


[open,refpage='VkPresentTimingInfoEXT',desc='Specifies per-present per-swapchain timing information',type='structs']
[open,refpage='VkPresentTimingInfoEXT',desc='Specifies per-present timing information',type='structs']
--
The sname:VkPresentTimingInfoEXT structure is defined as:

Expand All @@ -73,27 +73,52 @@ include::{generated}/api/structs/VkPresentTimingInfoEXT.adoc[]
structure.
* pname:time is a sname:VkPresentTimeEXT specifying the target present
time or duration of the presentation request.
* pname:timeDomain is the time domain used to specify the absolute target
present time and the timing results in a subsequent
flink:vkGetPastPresentationTimingEXT call for the current presentation
request.
* pname:timeDomainId is the id of the time domain used to specify the
absolute target present time and the timing results obtained in a
subsequent flink:vkGetPastPresentationTimingEXT call for the current
presentation request.
* pname:presentStageQueries is a valid tlink:VkPresentStageFlagsEXT value
indicating which present stages the presentation engine should collect
timing information for.
* pname:targetPresentStage is zero or a tlink:VkPresentStageFlagsEXT value
specifying which present stage pname:time is targeting.
* pname:presentAtRelativeTime specifies whether pname:time is to be
interpreted as an absolute or a relative time value.
* pname:presentAtNearestRefreshCycle is a flag indicating that the
application would like to complete pname:targetPresentStage at the start
of the refresh cycle that is closest to pname:time. If
pname:presentAtNearestRefreshCycle is ename:VK_TRUE, the presentation
engine may: complete the target present stage earlier than specified in
pname:time.
application would like the presentation engine to complete
pname:targetPresentStage at the start of the refresh cycle that is
closest to pname:time.

If pname:targetPresentStage is not zero, the presentation engine must: not
complete the target present stage before the absolute time specified in
pname:time according to the time domain used, unless
pname:presentAtNearestRefreshCycle is ename:VK_TRUE and pname:time falls
within the first half of a refresh cycle.

[NOTE]
.Note
====
Applications that use pname:targetPresentTime to specify an absolute present
time should: regularly rebase their calculations for their next target time
on the feedback from flink:vkGetPastPresentationTimingEXT to compensate for
accumulated precision errors or potential clock drift. It is recommended
that when targeting the time of a vertical blanking period, applications use
pname:presentAtNearestRefreshCycle to allow the implementation to compensate
for small precision errors that may cause an image to be displayed one
refresh cycle later than intended.
====

.Valid Usage
****
* If pname:presentStageTarget is not zero, it must: specify one and only
one stage.
* pname:presentStageTarget must: not be ename:VK_PRESENT_STAGE_IMAGE_HANDOFF_BIT_EXT
* pname:presentStageTarget must: not be
ename:VK_PRESENT_STAGE_QUEUE_OPERATIONS_END_BIT_EXT
* If pname:targetPresentStage is not zero, pname:presentAtRelativeTime must:
be ename:VK_FALSE.
* If pname:presentAtRelativeTime is ename:VK_TRUE, the
<<features-presentAtRelativeTime, pname:presentAtRelativeTime>> feature
must: be enabled.
****

include::{generated}/validity/structs/VkPresentTimingInfoEXT.adoc[]
Expand All @@ -107,41 +132,14 @@ The sname:VkPresentTimeEXT union is defined as:

include::{generated}/api/structs/VkPresentTimeEXT.adoc[]

* pname:targetPresentTime, if non-zero, specifies the earliest time the
application wants the presentation engine to complete the swapchain's
target present stage. A value of zero specifies that the presentation
engine may: display the image at any time allowed by the current present
mode.
* pname:afterPresentDuration, if non-zero, specifies the minimum duration
in nanoseconds before which the next image presentation request can:
reach the target present stage, relative to the previous presentation
reaching that same stage. A value of zero specifies that the
presentation engine may: display the previous image for any duration
allowed by the current present mode.

The contents of the sname:VkPresentTimeEXT union is interpreted depending on
the associated sname:VkPresentInfoKHR::pname:pSwapchains member creation
values. If
sname:VkSwapchainPresentTimingCreateInfoEXT::pname:presentAtRelativeTime was
ename:VK_FALSE when creating the pname:swapchain, pname:targetPresentTime is
used. Otherwise, pname:afterPresentDuration is used.

pname:targetPresentTime is a time in nanoseconds, according to the
time-domain specified in the associated
slink:VkPresentTimingInfoEXT::pname:timeDomain. The presentation engine
must: not complete the target present stage specified in
slink:VkPresentTimingInfoEXT::pname:targetPresentStage at an earlier time.

[NOTE]
.Note
====
Applications that use pname:targetPresentTime to specify an absolute present
time should: regularly rebase their calculations for their next target time
on the feedback from flink:vkGetPastPresentationTimingEXT to compensate for
accumulated precision errors or potential clock drift. It is recommended
that when targeting the time of a vertical blanking period, applications
subtract a small delta from pname:targetPresentTime as a margin for error.
====
* pname:targetPresentTime, if non-zero, specifies the earliest time in
nanoseconds the application wants the presentation engine to complete a
specified target present stage. A value of zero specifies that the
presentation engine may: display the image at any time allowed by the
current present mode.
* pname:presentDuration specifies the minimum duration in nanoseconds that
must: separate the ename:VK_PRESENT_STAGE_IMAGE_FIRST_PIXEL_VISIBLE_BIT_EXT
present stages of the current and the next presentation requests, if any.

include::{generated}/validity/structs/VkPresentTimeEXT.adoc[]
--
Expand Down Expand Up @@ -174,10 +172,6 @@ The set of queue operations delimited by
ename:VK_PRESENT_STAGE_QUEUE_OPERATIONS_END_BIT_EXT includes the wait for
the semaphores specified in slink:VkPresentInfoKHR::pname:pWaitSemaphores,
if any, and any work implicitly enqueued by the implementation.
On some platforms, when the present mode allows for it, presentation engines
may: proactively latch an image before this set of queue operations has
completed.
====
--

Expand Down
107 changes: 57 additions & 50 deletions chapters/VK_EXT_present_timing/queries.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -39,39 +39,33 @@ displayed to the user on a periodic basis. This period may: be fixed (Fixed
Refresh Rate, FRR) or variable (Variable Refresh Rate, VRR).

ifdef::VK_EXT_present_timing[]
[open,refpage='VkSwapchainPresentTimingCreateInfoEXT',desc='Specify present timing properties to initialize a swapchain with',type='structs']
[open,refpage='vkSetSwapchainPresentTimingQueueSizeEXT',desc='Allocate memory for the swapchain-internal timing results queue',type='protos']
--
To enable present timing for a swapchain, add a
sname:VkSwapchainPresentTimingCreateInfoEXT structure to the pname:pNext
chain of slink:VkSwapchainCreateInfoKHR.
In order to collect timing information about presentation, a swapchain needs
an internal queue to store asynchronously updated results until applications
collect them.

The sname:VkSwapchainPresentTimingCreateInfoEXT structure is defined as:
To allocate the swapchain's internal timing results queue, call:

include::{generated}/api/structs/VkSwapchainPresentTimingCreateInfoEXT.adoc[]
include::{generated}/api/protos/vkSetSwapchainPresentTimingQueueSizeEXT.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:presentTimingQueueSize is the size of the swapchain's internal
storage holding presentation timing results.
* pname:presentAtRelativeTime specifies whether target present times are
to be interpreted as relative times.
* pname:device is the device associated with pname:swapchain.
* pname:swapchain is the swapchain to allocate a results queue for.
* pname:size is the requested number of slots in the internal results queue.

When timing collection is enabled via the <<features-presentTiming,
pname:presentTiming>> feature, resources may: be allocated by the
implementation for an internal queue to collect results. The size of that
queue is specified by pname:presentTimingQueueSize.
If this function is called multiple times, the internal queue is reallocated
to fit the new pname:size. If the new pname:size is less than the current
number of outstanding results, ename:VK_NOT_READY is returned and no allocation
is performed.

.Valid Usage
****
* If the <<features-presentTiming, pname:presentTiming>> feature is not
enabled, pname:presentTimingQueueSize must: be zero
* If the <<features-presentAtRelativeTime, pname:presentAtRelativeTime>>
feature is not enabled, pname:presentAtRelativeTime must: be
ename:VK_FALSE
* pname:swapchain must: have been created with
sname:VkSwapchainCreateInfoKHR::pname:flags containing
ename:VK_SWAPCHAIN_CREATE_PRESENT_TIMING_BIT_EXT
****

include::{generated}/validity/structs/VkSwapchainPresentTimingCreateInfoEXT.adoc[]
include::{generated}/validity/protos/vkSetSwapchainPresentTimingQueueSizeEXT.adoc[]
--

[open,refpage='vkGetSwapchainTimingPropertiesEXT',desc='Obtain the display timing properties of the PE\'s display',type='protos']
Expand All @@ -88,18 +82,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
sname:VkSwapchainTimingPropertiesEXT structure.
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.

.Valid Usage
****
* pname:swapchain must: have been created with a
slink:VkSwapchainPresentTimingCreateInfoEXT specified in the
slink:VkSwapchainCreateInfoKHR::pname:pNext chain.
****

include::{generated}/validity/protos/vkGetSwapchainTimingPropertiesEXT.adoc[]
--

Expand All @@ -113,7 +100,7 @@ include::{generated}/api/structs/VkSwapchainTimingPropertiesEXT.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:refreshDuration is zero; or is an indication of the duration
* 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
Expand All @@ -122,10 +109,13 @@ include::{generated}/api/structs/VkSwapchainTimingPropertiesEXT.adoc[]
(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:variableRefresh is undefined: if pname:refreshDuration is
zero; otherwise it is ename:VK_FALSE if the presentation engine is
operating as a FRR display, or ename:VK_TRUE if the presentation
engine is operating as a VRR display.
* 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
cycle upon processing a presentation request.

If pname:variableRefreshDelay is the same as pname:refreshDuration, the
presentation engine is operating as an FRR display.

Some platforms may: not provide timing properties until after at least one
image has been presented to the pname:swapchain. If timing properties
Expand Down Expand Up @@ -180,7 +170,7 @@ feedback of slink:VkPastPresentationTimingEXT values indicates that the
target IPD can be durably achieved.
====

[open,refpage='vkGetSwapchainTimeDomainsEXT',desc='Obtain the time domain used by the PE for the swapchain',type='protos']
[open,refpage='vkGetSwapchainTimeDomainsEXT',desc='Obtain the time domains supported by the PE for the swapchain',type='protos']
--

To query the time domain used by the presentation engine for a given swapchain,
Expand Down Expand Up @@ -227,17 +217,26 @@ include::{generated}/api/structs/VkSwapchainTimeDomainPropertiesEXT.adoc[]
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.

[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.
====

include::{generated}/validity/structs/VkSwapchainTimeDomainPropertiesEXT.adoc[]
--

[open,refpage='vkGetPastPresentationTimingEXT',desc='Obtain timing of a previously-presented image',type='protos']
[open,refpage='vkGetPastPresentationTimingEXT',desc='Obtain timing of previously-presented images',type='protos']
--

The implementation maintains a limited amount of history of timing
information about previous presents, specified by
slink:VkSwapchainPresentTimingCreateInfoEXT::pname:presentTimingQueueSize
when creating a swapchain.
Because of the asynchronous nature of the presentation engine, the timing
information for a given flink:vkQueuePresentKHR command only becomes
available some time later.
Expand All @@ -254,13 +253,16 @@ include::{generated}/api/protos/vkGetPastPresentationTimingEXT.adoc[]
* 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 sname:VkPastPresentationTimingEXT structures to query, as
number of slink:VkPastPresentationTimingEXT structures to query, as
described below.
* pname:pPresentationTimings is `NULL` or a pointer to an an array
of sname:VkPastPresentationTimingEXT structures.
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
Expand All @@ -281,16 +283,19 @@ stages. Further calls to fname:vkGetPastPresentationTimingEXT will keep
providing all available results for a previously incomplete entry until it
is complete.

The implementation must: return a sname:VkPastPresentationTimingEXT for
The implementation must: return a slink:VkPastPresentationTimingEXT for
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
collection queue, equal to the number of entries written to
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.
Expand All @@ -301,8 +306,10 @@ 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. Access to the
swapchain timing information must: be atomic within the implementation.
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[]
--
Expand All @@ -325,7 +332,7 @@ 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:timeDomain is the ename:VkTimeDomainEXT used by the presentation
* pname:timeDomainId is the id of the time domain used by the presentation
engine to report times in pname:pPresentStages.
* pname:reportComplete is ename:VK_TRUE if the presentation engine
has reported all the requested results in pname:pPresentStages.
Expand Down Expand Up @@ -403,7 +410,7 @@ identical reasons.
Therefore, it is possible that the same event will cause both
pname:timingPropertiesChanged to become ename:VK_TRUE and and
pname:timeDomain to be different than the time domain requested in
sname:VkPresentTimingInfoEXT.
slink:VkPresentTimingInfoEXT.
====
--

Expand Down
Loading

0 comments on commit 116c56d

Please sign in to comment.