vulkan/wsi: Add X11 adaptive sync support based on dri options.
authorBas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
Tue, 16 Apr 2019 23:30:49 +0000 (01:30 +0200)
committerBas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
Tue, 23 Apr 2019 23:49:39 +0000 (23:49 +0000)
The dri options are optional. When the dri options are not provided
the WSI will not  use adaptive sync.

FWIW I think for xf86-video-amdgpu this still requires an X11 config
option, so only people who opt in can get possible regressions from this.

So then the remaining question is: why do this in the WSI?

It has been suggested in another MR that the application sets this.
However, I disagree with that as I don't think we'll ever get a
reasonable set of applications setting it.

The next questions is whether this can be a layer. It definitely
can be as implemented now. However, I think this generally fits
well with the function of the WSI. Furthemore, for e.g. the DISPLAY
WSI this is much harder to do in a layer.

Of course, most of the WSI could almost be a layer, but I think
this still fits best in the WSI.

Acked-by: Jason Ekstrand <jason@jlekstrand.net>
src/amd/vulkan/radv_wsi.c
src/freedreno/vulkan/tu_wsi.c
src/intel/vulkan/anv_wsi.c
src/vulkan/wsi/meson.build
src/vulkan/wsi/wsi_common.c
src/vulkan/wsi/wsi_common.h
src/vulkan/wsi/wsi_common_x11.c

index 346fb43d67541f67628e0fc1417382b65749fcce..1b391f74f98a769123e84ada840ed1ea3690d815 100644 (file)
@@ -42,7 +42,8 @@ radv_init_wsi(struct radv_physical_device *physical_device)
                               radv_physical_device_to_handle(physical_device),
                               radv_wsi_proc_addr,
                               &physical_device->instance->alloc,
-                              physical_device->master_fd);
+                              physical_device->master_fd,
+                              &physical_device->instance->dri_options);
 }
 
 void
index ce06a05d5d5c7514900059affd9af571f7701983..21466108b20e907ff2ed0bb6074ce64b74e2201f 100644 (file)
@@ -40,7 +40,7 @@ tu_wsi_init(struct tu_physical_device *physical_device)
    return wsi_device_init(&physical_device->wsi_device,
                           tu_physical_device_to_handle(physical_device),
                           tu_wsi_proc_addr, &physical_device->instance->alloc,
-                          physical_device->master_fd);
+                          physical_device->master_fd, NULL);
 }
 
 void
index 024bc1c245dac420599557a3c91e99fbb12c6c29..ba07bcef8b38ea7f7877c92e70d7822167cac682 100644 (file)
@@ -49,7 +49,8 @@ anv_init_wsi(struct anv_physical_device *physical_device)
                             anv_physical_device_to_handle(physical_device),
                             anv_wsi_proc_addr,
                             &physical_device->instance->alloc,
-                            physical_device->master_fd);
+                            physical_device->master_fd,
+                            NULL);
    if (result != VK_SUCCESS)
       return result;
 
index 9adc4d47c5a528075d10a32ad72cfc9f271bce61..1f8ada569629ad28be939cc4460f7b4d8a327a71 100644 (file)
@@ -42,6 +42,7 @@ libvulkan_wsi = static_library(
   'vulkan_wsi',
   files_vulkan_wsi,
   include_directories : [inc_common, inc_vulkan_util, inc_include],
+  link_with: [libxmlconfig],
   dependencies : [vulkan_wsi_deps, dep_libdrm],
   c_args : [c_vis_args, vulkan_wsi_args],
   build_by_default : false,
index 66cc4500cb912de1f3548b83a45696af225de43a..d44b9fad542458873a546ff7c15b4cff25d517c7 100644 (file)
@@ -24,6 +24,7 @@
 #include "wsi_common_private.h"
 #include "drm-uapi/drm_fourcc.h"
 #include "util/macros.h"
+#include "util/xmlconfig.h"
 #include "vk_util.h"
 
 #include <time.h>
@@ -37,7 +38,8 @@ wsi_device_init(struct wsi_device *wsi,
                 VkPhysicalDevice pdevice,
                 WSI_FN_GetPhysicalDeviceProcAddr proc_addr,
                 const VkAllocationCallbacks *alloc,
-                int display_fd)
+                int display_fd,
+                const struct driOptionCache *dri_options)
 {
    const char *present_mode;
    VkResult result;
@@ -129,6 +131,12 @@ wsi_device_init(struct wsi_device *wsi,
       }
    }
 
+   if (dri_options) {
+      if (driCheckOption(dri_options, "adaptive_sync", DRI_BOOL))
+         wsi->enable_adaptive_sync = driQueryOptionb(dri_options,
+                                                     "adaptive_sync");
+   }
+
    return VK_SUCCESS;
 
 fail:
index 6446320b95dc8ce3e1ea1a540f48435faf9e7c6b..46e51286e09d880ed47e7280fe9d8ddf549c3875 100644 (file)
@@ -87,6 +87,8 @@ struct wsi_fence {
 
 struct wsi_interface;
 
+struct driOptionCache;
+
 #define VK_ICD_WSI_PLATFORM_MAX (VK_ICD_WSI_PLATFORM_DISPLAY + 1)
 
 struct wsi_device {
@@ -103,6 +105,10 @@ struct wsi_device {
    uint32_t maxImageDimension2D;
    VkPresentModeKHR override_present_mode;
 
+   /* Whether to enable adaptive sync for a swapchain if implemented and
+    * available. Not all window systems might support this. */
+   bool enable_adaptive_sync;
+
    uint64_t (*image_get_modifier)(VkImage image);
 
 #define WSI_CB(cb) PFN_vk##cb cb
@@ -144,7 +150,8 @@ wsi_device_init(struct wsi_device *wsi,
                 VkPhysicalDevice pdevice,
                 WSI_FN_GetPhysicalDeviceProcAddr proc_addr,
                 const VkAllocationCallbacks *alloc,
-                int display_fd);
+                int display_fd,
+                const struct driOptionCache *dri_options);
 
 void
 wsi_device_finish(struct wsi_device *wsi,
index 1782aa525bc04beaef71c23887b06e2e36d16c62..46f1c08b453c281aae0d0a97d3d5eb613b3c1f11 100644 (file)
@@ -1315,6 +1315,33 @@ x11_swapchain_destroy(struct wsi_swapchain *anv_chain,
    return VK_SUCCESS;
 }
 
+static void
+wsi_x11_set_adaptive_sync_property(xcb_connection_t *conn,
+                                   xcb_drawable_t drawable,
+                                   uint32_t state)
+{
+   static char const name[] = "_VARIABLE_REFRESH";
+   xcb_intern_atom_cookie_t cookie;
+   xcb_intern_atom_reply_t* reply;
+   xcb_void_cookie_t check;
+
+   cookie = xcb_intern_atom(conn, 0, strlen(name), name);
+   reply = xcb_intern_atom_reply(conn, cookie, NULL);
+   if (reply == NULL)
+      return;
+
+   if (state)
+      check = xcb_change_property_checked(conn, XCB_PROP_MODE_REPLACE,
+                                          drawable, reply->atom,
+                                          XCB_ATOM_CARDINAL, 32, 1, &state);
+   else
+      check = xcb_delete_property_checked(conn, drawable, reply->atom);
+
+   xcb_discard_reply(conn, check.sequence);
+   free(reply);
+}
+
+
 static VkResult
 x11_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
                              VkDevice device,
@@ -1467,6 +1494,13 @@ x11_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
 
    for (int i = 0; i < ARRAY_SIZE(modifiers); i++)
       vk_free(pAllocator, modifiers[i]);
+
+   /* It is safe to set it here as only one swapchain can be associated with
+    * the window, and swapchain creation does the association. At this point
+    * we know the creation is going to succeed. */
+   wsi_x11_set_adaptive_sync_property(conn, window,
+                                      wsi_device->enable_adaptive_sync);
+
    *swapchain_out = &chain->base;
 
    return VK_SUCCESS;