kopper: Grow a swap interval API
authorAdam Jackson <ajax@redhat.com>
Thu, 28 Apr 2022 21:03:23 +0000 (17:03 -0400)
committerMarge Bot <emma+marge@anholt.net>
Wed, 4 May 2022 15:06:51 +0000 (15:06 +0000)
We take a slight liberty here by allowing 0 to mean either MAILBOX or
IMMEDIATE, since Wayland (at least) doesn't have a true IMMEDIATE mode
at least MAILBOX won't throttle to vblank.

This only correctly handles intervals of 0 or 1 at the moment.

Reviewed-By: Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/15800>

include/kopper_interface.h
src/gallium/drivers/zink/zink_kopper.c
src/gallium/drivers/zink/zink_kopper.h
src/gallium/frontends/dri/kopper.c

index 8852252..584214e 100644 (file)
@@ -74,6 +74,7 @@ struct __DRIkopperExtensionRec {
                                         void *loaderPrivate,
                                         int pixmap);
     int64_t (*swapBuffers)(__DRIdrawable *draw);
+    void (*setSwapInterval)(__DRIdrawable *drawable, int interval);
 };
 
 /**
index 9a71f5b..5a9cc4b 100644 (file)
@@ -54,6 +54,13 @@ init_dt_type(struct kopper_displaytarget *cdt)
     default:
        unreachable("unsupported!");
     }
+#ifdef WIN32
+    // not hooked up yet so let's not sabotage benchmarks
+    cdt->present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR;
+#else
+    // Matches the EGL and GLX_SGI_swap_interval default
+    cdt->present_mode = VK_PRESENT_MODE_FIFO_KHR;
+#endif
 }
 
 static VkSurfaceKHR
@@ -212,10 +219,9 @@ kopper_CreateSwapchain(struct zink_screen *screen, struct kopper_displaytarget *
       cswap->scci.queueFamilyIndexCount = 0;
       cswap->scci.pQueueFamilyIndices = NULL;
       cswap->scci.compositeAlpha = has_alpha ? VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR : VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
-      // TODO: This is where you'd hook up GLX_EXT_swap_interval and friends
-      cswap->scci.presentMode = cdt->type == KOPPER_WAYLAND ? VK_PRESENT_MODE_FIFO_KHR : VK_PRESENT_MODE_IMMEDIATE_KHR;
       cswap->scci.clipped = VK_TRUE;
    }
+   cswap->scci.presentMode = cdt->present_mode;
    cswap->scci.minImageCount = cdt->caps.minImageCount;
    cswap->scci.preTransform = cdt->caps.currentTransform;
    if (cdt->formats[1])
@@ -807,3 +813,27 @@ zink_kopper_check(struct pipe_resource *pres)
    struct kopper_displaytarget *cdt = kopper_displaytarget(res->obj->dt);
    return !cdt->is_kill;
 }
+
+void
+zink_kopper_set_swap_interval(struct pipe_screen *pscreen, struct pipe_resource *pres, int interval)
+{
+   struct zink_resource *res = zink_resource(pres);
+   struct zink_screen *screen = zink_screen(pscreen);
+   assert(res->obj->dt);
+   struct kopper_displaytarget *cdt = kopper_displaytarget(res->obj->dt);
+   VkPresentModeKHR old_present_mode = cdt->present_mode;
+
+   assert(interval >= 0); /* TODO: VK_PRESENT_MODE_FIFO_RELAXED_KHR */
+   if (interval == 0) {
+      if (cdt->present_modes & BITFIELD_BIT(VK_PRESENT_MODE_IMMEDIATE_KHR))
+         cdt->present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR;
+      else
+         cdt->present_mode = VK_PRESENT_MODE_MAILBOX_KHR;
+   } else if (interval > 0) {
+      cdt->present_mode = VK_PRESENT_MODE_FIFO_KHR;
+   }
+   assert(cdt->present_modes & BITFIELD_BIT(cdt->present_mode));
+
+   if (old_present_mode != cdt->present_mode)
+      update_swapchain(screen, cdt, cdt->caps.currentExtent.width, cdt->caps.currentExtent.height);
+}
index c427f20..01a3cca 100644 (file)
@@ -70,6 +70,7 @@ struct kopper_displaytarget
    VkImageFormatListCreateInfoKHR format_list;
    enum kopper_type type;
    bool is_kill;
+   VkPresentModeKHR present_mode;
 };
 
 struct zink_context;
@@ -119,4 +120,6 @@ void
 zink_kopper_fixup_depth_buffer(struct zink_context *ctx);
 bool
 zink_kopper_check(struct pipe_resource *pres);
+void
+zink_kopper_set_swap_interval(struct pipe_screen *pscreen, struct pipe_resource *pres, int interval);
 #endif
index 2917c3c..452daf0 100644 (file)
@@ -31,6 +31,7 @@
 #include "state_tracker/st_context.h"
 #include "os/os_process.h"
 #include "zink/zink_public.h"
+#include "zink/zink_instance.h"
 #include "zink/zink_kopper.h"
 #include "driver_trace/tr_screen.h"
 
@@ -98,6 +99,8 @@ static const __DRIrobustnessExtension dri2Robustness = {
    .base = { __DRI2_ROBUSTNESS, 1 }
 };
 
+const __DRIkopperExtension driKopperExtension;
+
 static const __DRIextension *drivk_screen_extensions[] = {
    &driTexBufferExtension.base,
    &dri2RendererQueryExtension.base,
@@ -107,6 +110,7 @@ static const __DRIextension *drivk_screen_extensions[] = {
    &driVkImageExtension.base,
    &dri2FlushControlExtension.base,
    &driVkFlushExtension.base,
+   &driKopperExtension.base,
    NULL
 };
 
@@ -965,11 +969,28 @@ kopperCreateNewDrawable(__DRIscreen *screen,
     return pdraw;
 }
 
+static void
+kopperSetSwapInterval(__DRIdrawable *dPriv, int interval)
+{
+   struct dri_drawable *drawable = dri_drawable(dPriv);
+   struct dri_screen *screen = dri_screen(drawable->sPriv);
+   struct kopper_screen *kscreen = (struct kopper_screen *)screen;
+   struct pipe_screen *pscreen = kscreen->screen;
+   struct pipe_resource *ptex = drawable->textures[ST_ATTACHMENT_BACK_LEFT] ?
+                                drawable->textures[ST_ATTACHMENT_BACK_LEFT] :
+                                drawable->textures[ST_ATTACHMENT_FRONT_LEFT];
+
+   // the conditional is because we can be called before buffer allocation, though
+   // this is almost certainly not the right fix.
+   if (ptex)
+      zink_kopper_set_swap_interval(pscreen, ptex, interval);
+}
 
 const __DRIkopperExtension driKopperExtension = {
    .base = { __DRI_KOPPER, 1 },
    .createNewDrawable          = kopperCreateNewDrawable,
    .swapBuffers                = kopperSwapBuffers,
+   .setSwapInterval            = kopperSetSwapInterval,
 };
 
 const struct __DriverAPIRec galliumvk_driver_api = {