Skip to contentSkip to conversation

vulkan: Add VK_GOOGLE_display_timing extension (x11+display, anv+radv) [v7]

PATCH New Keith Packard 1 participant 1 message Nov 17, 2018

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 vulkan: Add VK_GOOGLE_display_timing extension (x11+display, anv+radv) [v7]

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.

v4:
Adapt to changes in MESA_query_timestamp extension

v5:
Squash core bits and anv/radv wrappers into a single patch

v6:
Switch from MESA_query_timestamp to EXT_calibrated_timestamps

v7:
Ensure we target frame no earlier than desired. This means rounding the target frame up, rather than selecting the nearest one.

---
 src/amd/vulkan/radv_extensions.py   |   1 +
 src/amd/vulkan/radv_wsi.c           |  33 +++
 src/intel/vulkan/anv_extensions.py  |   1 +
 src/intel/vulkan/anv_wsi.c          |  33 +++
 src/vulkan/wsi/wsi_common.c         | 303 +++++++++++++++++++++++++++-
 src/vulkan/wsi/wsi_common.h         |  32 +++
 src/vulkan/wsi/wsi_common_display.c | 165 ++++++++++++++-
 src/vulkan/wsi/wsi_common_private.h |  35 ++++
 src/vulkan/wsi/wsi_common_x11.c     |  71 ++++++-
 9 files changed, 662 insertions(+), 12 deletions(-)
src/amd/vulkan/radv_extensions.py +1 -0
index 6bdf988d117..76c3ade06f0 100644
@@ -119,6 +119,7 @@ EXTENSIONS = [
     Extension('VK_AMD_shader_trinary_minmax',             1, True),
     Extension('VK_GOOGLE_decorate_string',                1, True),
     Extension('VK_GOOGLE_hlsl_functionality1',            1, True),
+    Extension('VK_GOOGLE_display_timing',                 1, True),
 ]
 
 class VkVersion:
src/amd/vulkan/radv_wsi.c +33 -0
index 346fb43d675..ba24d07edfc 100644
@@ -295,3 +295,36 @@ VkResult radv_GetPhysicalDevicePresentRectanglesKHR(
 						 surface,
 						 pRectCount, pRects);
 }
+
+/* VK_GOOGLE_display_timing */
+VkResult
+radv_GetRefreshCycleDurationGOOGLE(
+	VkDevice _device,
+	VkSwapchainKHR swapchain,
+	VkRefreshCycleDurationGOOGLE *pDisplayTimingProperties)
+{
+	RADV_FROM_HANDLE(radv_device, device, _device);
+	struct radv_physical_device *pdevice = device->physical_device;
+
+	return wsi_common_get_refresh_cycle_duration(&pdevice->wsi_device,
+						     _device,
+						     swapchain,
+						     pDisplayTimingProperties);
+}
+
+VkResult
+radv_GetPastPresentationTimingGOOGLE(VkDevice _device,
+				     VkSwapchainKHR swapchain,
+				     uint32_t *pPresentationTimingCount,
+				     VkPastPresentationTimingGOOGLE
+				     *pPresentationTimings)
+{
+	RADV_FROM_HANDLE(radv_device, device, _device);
+	struct radv_physical_device *pdevice = device->physical_device;
+
+	return wsi_common_get_past_presentation_timing(&pdevice->wsi_device,
+						       _device,
+						       swapchain,
+						       pPresentationTimingCount,
+						       pPresentationTimings);
+}
src/intel/vulkan/anv_extensions.py +1 -0
index e9afe06bb13..8fcc4d1376e 100644
@@ -130,6 +130,7 @@ EXTENSIONS = [
     Extension('VK_EXT_calibrated_timestamps',             1, True),
     Extension('VK_GOOGLE_decorate_string',                1, True),
     Extension('VK_GOOGLE_hlsl_functionality1',            1, True),
+    Extension('VK_GOOGLE_display_timing',                 1, True),
 ]
 
 class VkVersion:
src/intel/vulkan/anv_wsi.c +33 -0
index 024bc1c245d..bfdbcb56c56 100644
@@ -305,3 +305,36 @@ VkResult anv_GetPhysicalDevicePresentRectanglesKHR(
                                             surface,
                                             pRectCount, pRects);
 }
+
+/* VK_GOOGLE_display_timing */
+VkResult
+anv_GetRefreshCycleDurationGOOGLE(VkDevice _device,
+                                  VkSwapchainKHR swapchain,
+                                  VkRefreshCycleDurationGOOGLE
+                                  *pDisplayTimingProperties)
+{
+   ANV_FROM_HANDLE(anv_device, device, _device);
+
+   return wsi_common_get_refresh_cycle_duration(&device->instance->
+                                                physicalDevice.wsi_device,
+                                                _device,
+                                                swapchain,
+                                                pDisplayTimingProperties);
+}
+
+VkResult
+anv_GetPastPresentationTimingGOOGLE(VkDevice _device,
+                                    VkSwapchainKHR swapchain,
+                                    uint32_t *pPresentationTimingCount,
+                                    VkPastPresentationTimingGOOGLE
+                                    *pPresentationTimings)
+{
+   ANV_FROM_HANDLE(anv_device, device, _device);
+
+   return wsi_common_get_past_presentation_timing(&device->instance->
+                                                  physicalDevice.wsi_device,
+                                                  _device,
+                                                  swapchain,
+                                                  pPresentationTimingCount,
+                                                  pPresentationTimings);
+}
src/vulkan/wsi/wsi_common.c +300 -3

397 lines not on this page · raw message

src/vulkan/wsi/wsi_common.h +32 -0
index f6ca013c2a8..f07cf3a5880 100644
@@ -96,6 +96,7 @@ struct wsi_device {
    VkPhysicalDevice pdevice;
    VkPhysicalDeviceMemoryProperties memory_props;
    uint32_t queue_family_count;
+   float timestamp_period;
 
    VkPhysicalDevicePCIBusInfoPropertiesEXT pci_bus_info;
 
@@ -109,14 +110,18 @@ struct wsi_device {
    WSI_CB(BindImageMemory);
    WSI_CB(BeginCommandBuffer);
    WSI_CB(CmdCopyImageToBuffer);
+   WSI_CB(CmdResetQueryPool);
+   WSI_CB(CmdWriteTimestamp);
    WSI_CB(CreateBuffer);
    WSI_CB(CreateCommandPool);
    WSI_CB(CreateFence);
    WSI_CB(CreateImage);
+   WSI_CB(CreateQueryPool);
    WSI_CB(DestroyBuffer);
    WSI_CB(DestroyCommandPool);
    WSI_CB(DestroyFence);
    WSI_CB(DestroyImage);
+   WSI_CB(DestroyQueryPool);
    WSI_CB(EndCommandBuffer);
    WSI_CB(FreeMemory);
    WSI_CB(FreeCommandBuffers);
@@ -124,10 +129,14 @@ struct wsi_device {
    WSI_CB(GetImageMemoryRequirements);
    WSI_CB(GetImageSubresourceLayout);
    WSI_CB(GetMemoryFdKHR);
+   WSI_CB(GetPhysicalDeviceProperties);
    WSI_CB(GetPhysicalDeviceFormatProperties);
    WSI_CB(GetPhysicalDeviceFormatProperties2KHR);
+   WSI_CB(GetPhysicalDeviceQueueFamilyProperties);
+   WSI_CB(GetQueryPoolResults);
    WSI_CB(ResetFences);
    WSI_CB(QueueSubmit);
+   WSI_CB(GetCalibratedTimestampsEXT);
    WSI_CB(WaitForFences);
 #undef WSI_CB
 
@@ -241,4 +250,27 @@ wsi_common_queue_present(const struct wsi_device *wsi,
                          int queue_family_index,
                          const VkPresentInfoKHR *pPresentInfo);
 
+VkResult
+wsi_common_convert_timestamp(const struct wsi_device *wsi,
+                             VkDevice device_h,
+                             VkSurfaceKHR surface_h,
+                             uint64_t monotonic_timestamp,
+                             uint64_t *surface_timestamp);
+
+/* VK_GOOGLE_display_timing */
+VkResult
+wsi_common_get_refresh_cycle_duration(const struct wsi_device *wsi,
+                                      VkDevice device_h,
+                                      VkSwapchainKHR swapchain,
+                                      VkRefreshCycleDurationGOOGLE
+                                      *pDisplayTimingProperties);
+
+VkResult
+wsi_common_get_past_presentation_timing(const struct wsi_device *wsi,
+                                        VkDevice device_h,
+                                        VkSwapchainKHR swapchain,
+                                        uint32_t *pPresentationTimingCount,
+                                        VkPastPresentationTimingGOOGLE
+                                        *pPresentationTimings);
+
 #endif
src/vulkan/wsi/wsi_common_display.c +159 -6

295 lines not on this page · raw message

src/vulkan/wsi/wsi_common_private.h +35 -0
index 50a78acacb0..a0c97942954 100644
@@ -25,6 +25,13 @@
 
 #include "wsi_common.h"
 
+struct wsi_timing {
+   bool complete;
+   bool consumed;
+   uint64_t target_msc;
+   VkPastPresentationTimingGOOGLE timing;
+};
+
 struct wsi_image {
    VkImage image;
    VkDeviceMemory memory;
@@ -41,8 +48,16 @@ struct wsi_image {
    uint32_t offsets[4];
    uint32_t row_pitches[4];
    int fds[4];
+
+   VkQueryPool query_pool;
+
+   VkCommandBuffer timestamp_buffer;
+
+   struct wsi_timing *timing;
 };
 
+#define WSI_TIMING_HISTORY      16
+
 struct wsi_swapchain {
    const struct wsi_device *wsi;
 
@@ -54,6 +69,16 @@ struct wsi_swapchain {
 
    bool use_prime_blit;
 
+   uint32_t timing_insert;
+   uint32_t timing_count;
+
+   struct wsi_timing timing[WSI_TIMING_HISTORY];
+
+   uint64_t frame_msc;
+   uint64_t frame_ust;
+
+   float timestamp_period;
+
    /* Command pools, one per queue family */
    VkCommandPool *cmd_pools;
 
@@ -67,6 +92,10 @@ struct wsi_swapchain {
    VkResult (*queue_present)(struct wsi_swapchain *swap_chain,
                              uint32_t image_index,
                              const VkPresentRegionKHR *damage);
+   VkResult (*get_refresh_cycle_duration)(struct wsi_swapchain *swap_chain,
+                                          VkRefreshCycleDurationGOOGLE
+                                          *pDisplayTimingProperties);
+
 };
 
 bool
@@ -100,6 +129,12 @@ wsi_destroy_image(const struct wsi_swapchain *chain,
                   struct wsi_image *image);
 
 
+void
+wsi_mark_timing(struct wsi_swapchain *swapchain,
+                struct wsi_image *image,
+                uint64_t ust,
+                uint64_t msc);
+
 struct wsi_interface {
    VkResult (*get_support)(VkIcdSurfaceBase *surface,
                            struct wsi_device *wsi_device,
src/vulkan/wsi/wsi_common_x11.c +68 -3

136 lines not on this page · raw message

Signature · 7 lines
2.19.1


_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel