Add simple API sample for VK_EXT_present_timing.#1535
Add simple API sample for VK_EXT_present_timing.#1535nvlduc wants to merge 1 commit intoKhronosGroup:mainfrom
Conversation
asuessenbach
left a comment
There was a problem hiding this comment.
That's an interesting sample!
Unfortunately, it doesn't run on my environment (Win11, NVIDIA RTX A3000 Laptop GPU). It gets a VK_ERROR_SURFACE_LOST_KHR on vkQueuePresentKHR after vkGetPastPresentationTimingEXT got more than 0 (1, to be precise) past_presentation_properties.presentationTimingCount for the first time.
Any idea what that might mean?
Besides that, I have a couple of questions...
| == Extension Features | ||
|
|
||
| VK_EXT_present_timing exposes 3 features at the physical device level: | ||
| * `presentTiming` is required for the extension to be exposed, and allows the application to query past presentation timings. |
There was a problem hiding this comment.
You probably want an empty line before this one.
| === Timing Properties | ||
|
|
||
| `VkSwapchainTimingPropertiesEXT` exposes a `refreshDuration` and a `refreshInterval` value. These two fields put together describe the behavior of the presentation engine: | ||
| * If both values are equal, the presentation engine is operating in a fixed refresh rate mode (FRR), and the value indicates the length of a refresh cycle in nanoseconds. |
There was a problem hiding this comment.
Probably an empty line before this one, again?
|
|
||
| === Time Domains | ||
|
|
||
| The time values are all expressed in a time domain chosen by the application among a list of candidates exposed by the swapchain. `VK_EXT_present_timing` introduces new opaque times domains that are local to a given swapchain: `VK_TIME_DOMAIN_PRESENT_STAGE_LOCAL_EXT`, which all implementations must support, and `VK_TIME_DOMAIN_SWAPCHAIN_LOCAL_EXT`. |
There was a problem hiding this comment.
times domains -> time domains ?
| } | ||
|
|
||
| // Do triple-buffering when possible. This is clamped to the min and max image count limits. | ||
| desired_swapchain_images = std::max(surface_capabilities.surfaceCapabilities.minImageCount, 3u); |
There was a problem hiding this comment.
On desired_swapchain_image: maybe something with "count" in its name?
| } | ||
|
|
||
| // Find a supported composite type. | ||
| composite = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; |
There was a problem hiding this comment.
What if (surface_capabilities.surfaceCapabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR) is false?
| { | ||
| can_use_present_timing = false; | ||
| } | ||
| } |
There was a problem hiding this comment.
Maybe just
can_use_present_timing = display_present_stage &&
(present_timing_capabilities.presentAtRelativeTimeSupported ||
present_timing_capabilities.presentAtAbsoluteTimeSupported);
| past_presentation_properties.pPresentationTimings = past_presentation_timings.data(); | ||
| past_presentation_properties.presentationTimingCount = past_presentation_timings.size(); | ||
|
|
||
| VK_CHECK(vkGetPastPresentationTimingEXT(get_device_handle(), &past_presentation_info, &past_presentation_properties)); |
There was a problem hiding this comment.
Isn't vkGetPastPresentationTimingEXT an enumeration call?
First call to determine the number of VkPastPresentationTimingEXT to get, and second call to actually get them?
past_presentation_timings could be a std::vector, then.
| { | ||
| query_swapchain_timing_properties(); | ||
| select_target_present_duration(); | ||
| timing_properties_counter = past_presentation_properties.timingPropertiesCounter; |
There was a problem hiding this comment.
timing_properties_counter has already been set in query_swapchain_timing_properties() by calling vkGetSwapchainTimingPropertiesEXT.
Is that supposed to be identical to what you get with vkGetPastPresentationTimingEXT?
| invalidate_timing_history(); | ||
| } | ||
|
|
||
| time_domains_counter = past_presentation_properties.timeDomainsCounter; |
There was a problem hiding this comment.
Similar to the above, now with time_domains_counter, select_swapchain_time_domain(), and vkGetSwapchainTimeDomainPropertiesEXT
| std::array<VkPastPresentationTimingEXT, history_buffer_size> past_presentation_timings; | ||
|
|
||
| /// Frame timing history. This is not directly used and is meant as an example. | ||
| std::array<FrameTimingData, history_buffer_size> timing_history; |
There was a problem hiding this comment.
Do you need past_presentation_timings and timing_history to be the same size, or can they be sized differently?
Description
This change adds a new "API" sample demonstrating usage of the VK_EXT_present_timing API. I chose this type of sample as opposed to a more complex demo to focus on the API design of this particular extension, rather than exploring the problem space of frame pacing and swapchain best practices which require interactions with other unrelated extensions.
The simple rendering (a circle moving across the display) is a decent test to verify the quality of a VK_EXT_present_timing implementation.
I unfortunately do not have equipment to build this on macOS or Android.
This sample was tested using latest NVIDIA beta developer drivers on Windows 11 (596.10) and Linux (595.44.05) with an NVIDIA RTX 4080.
General Checklist:
Please ensure the following points are checked:
Note: The Samples CI runs a number of checks including:
If this PR contains framework changes:
batchcommand line argument to make sure all samples still work properlySample Checklist
If your PR contains a new or modified sample, these further checks must be carried out in addition to the General Checklist: