[Mesa-dev] [PATCH] vulkan: Add VK_GOOGLE_display_timing extension (x11+display, anv+radv) [v6]
Michel Dänzer
michel at daenzer.net
Fri Nov 16 09:39:04 UTC 2018
On 2018-11-15 7:06 p.m., Keith Packard wrote:
> This adds support for the VK_GOOGLE_display timing extension, which
> provides two things:
>
> 1) Detailed information about when frames are displayed, including
> slack time between GPU execution and display frame.
>
> 2) Absolute time control over swapchain queue processing. This allows
> the application to request frames be displayed at specific
> absolute times, using the same timebase as that provided in vblank
> events.
>
> Support for this extension has been implemented for the x11 and
> display backends; adding support to other backends should be
> reasonable straightforward for one familiar with those systems and
> should not require any additional device-specific code.
>
> v2:
> Adjust GOOGLE_display_timing earliest value. The
> earliestPresentTime for an image cannot be before the previous
> image was displayed, or even a frame later (in FIFO mode).
>
> Make GOOGLE_display_timing use render completed time. Switch
> from VK_PIPELINE_TOP_OF_PIPE_BIT to
> VK_PIPELINE_STAGE_ALL_COMMANDS_BIT so that the time reported
> to applications as the end of rendering reflects the latest
> possible value to ensure that applications don't underestimate
> the amount of work done in the frame.
>
> v3:
> Adopt Jason Ekstrand's coding conventions. Declare variables
> at first use, eliminate extra whitespace between types and
> names. Wrap lines to 80 columns.
>
> Suggested-by: Jason Ekstrand <jason.ekstrand at intel.com>
>
> v4:
> Adapt to changes in MESA_query_timestamp extension
>
> v5:
> Squash core bits and anv/radv wrappers into a single patch
>
> Suggested-by: Jason Ekstrand <jason.ekstrand at intel.com>
>
> v6:
> Switch from MESA_query_timestamp to EXT_calibrated_timestamps
>
> Signed-off-by: Keith Packard <keithp at keithp.com>
>
> [...]
>
> @@ -979,9 +1187,49 @@ wsi_common_queue_present(const struct wsi_device *wsi,
> */
> struct wsi_image *image =
> swapchain->get_wsi_image(swapchain, pPresentInfo->pImageIndices[i]);
> - submit_info.commandBufferCount = 1;
> - submit_info.pCommandBuffers =
> - &image->prime.blit_cmd_buffers[queue_family_index];
> + submit_buffers[submit_info.commandBufferCount++] =
> + image->prime.blit_cmd_buffers[queue_family_index];
> + }
> +
> + /* Set up GOOGLE_display_timing bits */
> + if (present_times_info &&
> + present_times_info->pTimes != NULL &&
> + i < present_times_info->swapchainCount)
> + {
> + const VkPresentTimeGOOGLE *present_time =
> + &present_times_info->pTimes[i];
> +
> + struct wsi_image *image =
> + swapchain->get_wsi_image(swapchain, pPresentInfo->pImageIndices[i]);
> +
> + timing = wsi_next_timing(swapchain, pPresentInfo->pImageIndices[i]);
> + timing->timing.presentID = present_time->presentID;
> + timing->timing.desiredPresentTime = present_time->desiredPresentTime;
> + timing->target_msc = 0;
> + image->timing = timing;
> +
> + if (present_time->desiredPresentTime != 0)
> + {
> + int64_t delta_nsec = (int64_t) (present_time->desiredPresentTime -
> + swapchain->frame_ust);
> +
> + /* Set the target msc only if it's no more than two seconds from
> + * now, and not stale
> + */
> + if (0 <= delta_nsec && delta_nsec <= 2000000000ul) {
> + VkRefreshCycleDurationGOOGLE refresh_timing;
> +
> + swapchain->get_refresh_cycle_duration(swapchain,
> + &refresh_timing);
> +
> + int64_t refresh = (int64_t) refresh_timing.refreshDuration;
> + int64_t frames = (delta_nsec + refresh/2) / refresh;
desiredPresentTime has "no sooner than" semantics, so I think this should be
int64_t frames = (delta_nsec + refresh-1) / refresh;
> + timing->target_msc = swapchain->frame_msc + frames;
> + }
> + }
Note that MSC based timing won't work well with variable refresh rate.
In the long term, support for PresentOptionUST should be implemented and
used.
> @@ -1691,6 +1760,66 @@ wsi_display_queue_present(struct wsi_swapchain *drv_chain,
>
> pthread_mutex_lock(&wsi->wait_mutex);
>
> + if (image->base.timing && image->base.timing->target_msc != 0) {
> + VkIcdSurfaceDisplay *surface = chain->surface;
> + wsi_display_mode *display_mode =
> + wsi_display_mode_from_handle(surface->displayMode);
> + wsi_display_connector *connector = display_mode->connector;
> +
> + wsi_display_debug("delta frame %ld\n",
> + image->base.timing->target_msc - connector->last_frame);
> + if (image->base.timing->target_msc > connector->last_frame) {
> + uint64_t frame_queued;
> + VkDisplayKHR display = wsi_display_connector_to_handle(connector);
> +
> + wsi_display_debug_code(uint64_t current_frame, current_nsec;
> + drmCrtcGetSequence(wsi->fd, connector->crtc_id,
> + ¤t_frame,
> + ¤t_nsec);
> + wsi_display_debug("from current: %ld\n",
> + image->base.timing->target_msc
> + - current_frame));
> +
> + image->fence = wsi_display_fence_alloc(chain->base.device,
> + chain->base.wsi,
> + display, &chain->base.alloc);
> +
> + if (!image->fence) {
> + result = VK_ERROR_OUT_OF_HOST_MEMORY;
> + goto bail_unlock;
> + }
> +
> + result = wsi_register_vblank_event(image->fence,
> + chain->base.wsi,
> + display,
> + 0,
> + image->base.timing->target_msc - 1,
> + &frame_queued);
> +
> + if (result != VK_SUCCESS)
> + goto bail_unlock;
> +
> + /* Check and make sure we are queued for the right frame, otherwise
> + * just go queue an image
> + */
> + if (frame_queued <= image->base.timing->target_msc - 1) {
> + image->state = WSI_IMAGE_WAITING;
> +
> + /*
> + * Don't set the image member until we're going to wait for the
> + * event to arrive before flipping to the image. That way, if the
> + * register_vblank_event call happens to process the event, it
> + * won't actually do anything
> + */
> + image->fence->image = image;
> + wsi_display_start_wait_thread(wsi);
> + result = VK_SUCCESS;
> + goto bail_unlock;
> + }
> +
> + }
> + }
What is this code for? At least with X11 Present, shouldn't it be
sufficient to simply pass the target MSC value to x11_present_to_x11?
--
Earthling Michel Dänzer | http://www.amd.com
Libre software enthusiast | Mesa and X developer
More information about the dri-devel
mailing list