diff --git a/include/kopper_interface.h b/include/kopper_interface.h index 8852252578d..584214e113a 100644 --- a/include/kopper_interface.h +++ b/include/kopper_interface.h @@ -74,6 +74,7 @@ struct __DRIkopperExtensionRec { void *loaderPrivate, int pixmap); int64_t (*swapBuffers)(__DRIdrawable *draw); + void (*setSwapInterval)(__DRIdrawable *drawable, int interval); }; /** diff --git a/src/gallium/drivers/zink/zink_kopper.c b/src/gallium/drivers/zink/zink_kopper.c index 9a71f5ba3ae..5a9cc4b15bf 100644 --- a/src/gallium/drivers/zink/zink_kopper.c +++ b/src/gallium/drivers/zink/zink_kopper.c @@ -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); +} diff --git a/src/gallium/drivers/zink/zink_kopper.h b/src/gallium/drivers/zink/zink_kopper.h index c427f2067c3..01a3ccabaa1 100644 --- a/src/gallium/drivers/zink/zink_kopper.h +++ b/src/gallium/drivers/zink/zink_kopper.h @@ -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 diff --git a/src/gallium/frontends/dri/kopper.c b/src/gallium/frontends/dri/kopper.c index 2917c3c1650..452daf087ef 100644 --- a/src/gallium/frontends/dri/kopper.c +++ b/src/gallium/frontends/dri/kopper.c @@ -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 = {