From 4ab6d7e7534b6848231e1a2b8bc1a05531ab54bc Mon Sep 17 00:00:00 2001 From: Hans-Kristian Arntzen Date: Fri, 12 Jan 2024 15:13:59 +0100 Subject: [PATCH] wsi/x11: Add drirc option to ignore SUBOPTIMAL. Talos Principle and related games on that engine fail to handle SUBOPTIMAL properly. Adds an option to ignore SUBOPTIMAL and pretend it's SUCCESS. Signed-off-by: Hans-Kristian Arntzen Reviewed-by: Danylo Piliaiev Part-of: --- src/amd/vulkan/radv_instance.c | 1 + src/freedreno/vulkan/tu_device.cc | 1 + src/intel/vulkan/anv_device.c | 1 + src/intel/vulkan_hasvk/anv_device.c | 1 + src/nouveau/vulkan/nvk_instance.c | 5 +++++ src/util/00-mesa-defaults.conf | 6 +++++ src/util/driconf.h | 4 ++++ src/vulkan/wsi/wsi_common.h | 4 ++++ src/vulkan/wsi/wsi_common_x11.c | 34 ++++++++++++++++++++++------- 9 files changed, 49 insertions(+), 8 deletions(-) diff --git a/src/amd/vulkan/radv_instance.c b/src/amd/vulkan/radv_instance.c index 4279bc4af3d..f5f273aacc8 100644 --- a/src/amd/vulkan/radv_instance.c +++ b/src/amd/vulkan/radv_instance.c @@ -137,6 +137,7 @@ static const driOptionDescription radv_dri_options[] = { DRI_CONF_OVERRIDE_VRAM_SIZE() DRI_CONF_VK_WSI_FORCE_BGRA8_UNORM_FIRST(false) DRI_CONF_VK_WSI_FORCE_SWAPCHAIN_TO_CURRENT_EXTENT(false) + DRI_CONF_VK_X11_IGNORE_SUBOPTIMAL(false) DRI_CONF_VK_REQUIRE_ETC2(false) DRI_CONF_VK_REQUIRE_ASTC(false) DRI_CONF_RADV_ZERO_VRAM(false) diff --git a/src/freedreno/vulkan/tu_device.cc b/src/freedreno/vulkan/tu_device.cc index 96af807661f..430cf3c1642 100644 --- a/src/freedreno/vulkan/tu_device.cc +++ b/src/freedreno/vulkan/tu_device.cc @@ -762,6 +762,7 @@ static const driOptionDescription tu_dri_options[] = { DRI_CONF_SECTION_DEBUG DRI_CONF_VK_WSI_FORCE_BGRA8_UNORM_FIRST(false) DRI_CONF_VK_WSI_FORCE_SWAPCHAIN_TO_CURRENT_EXTENT(false) + DRI_CONF_VK_X11_IGNORE_SUBOPTIMAL(false) DRI_CONF_VK_DONT_CARE_AS_LOAD(false) DRI_CONF_SECTION_END diff --git a/src/intel/vulkan/anv_device.c b/src/intel/vulkan/anv_device.c index 612caa5c553..5e1f22c052d 100644 --- a/src/intel/vulkan/anv_device.c +++ b/src/intel/vulkan/anv_device.c @@ -96,6 +96,7 @@ static const driOptionDescription anv_dri_options[] = { DRI_CONF_ALWAYS_FLUSH_CACHE(false) DRI_CONF_VK_WSI_FORCE_BGRA8_UNORM_FIRST(false) DRI_CONF_VK_WSI_FORCE_SWAPCHAIN_TO_CURRENT_EXTENT(false) + DRI_CONF_VK_X11_IGNORE_SUBOPTIMAL(false) DRI_CONF_LIMIT_TRIG_INPUT_RANGE(false) DRI_CONF_ANV_MESH_CONV_PRIM_ATTRS_TO_VERT_ATTRS(-2) DRI_CONF_FORCE_VK_VENDOR(0) diff --git a/src/intel/vulkan_hasvk/anv_device.c b/src/intel/vulkan_hasvk/anv_device.c index 2819dd634b2..a7fb141b461 100644 --- a/src/intel/vulkan_hasvk/anv_device.c +++ b/src/intel/vulkan_hasvk/anv_device.c @@ -77,6 +77,7 @@ static const driOptionDescription anv_dri_options[] = { DRI_CONF_ALWAYS_FLUSH_CACHE(false) DRI_CONF_VK_WSI_FORCE_BGRA8_UNORM_FIRST(false) DRI_CONF_VK_WSI_FORCE_SWAPCHAIN_TO_CURRENT_EXTENT(false) + DRI_CONF_VK_X11_IGNORE_SUBOPTIMAL(false) DRI_CONF_LIMIT_TRIG_INPUT_RANGE(false) DRI_CONF_SECTION_END diff --git a/src/nouveau/vulkan/nvk_instance.c b/src/nouveau/vulkan/nvk_instance.c index 5340b1b6837..76e89a5ad58 100644 --- a/src/nouveau/vulkan/nvk_instance.c +++ b/src/nouveau/vulkan/nvk_instance.c @@ -71,6 +71,11 @@ static const driOptionDescription nvk_dri_options[] = { DRI_CONF_VK_KHR_PRESENT_WAIT(false) DRI_CONF_VK_XWAYLAND_WAIT_READY(true) DRI_CONF_SECTION_END + + DRI_CONF_SECTION_DEBUG + DRI_CONF_VK_WSI_FORCE_SWAPCHAIN_TO_CURRENT_EXTENT(false) + DRI_CONF_VK_X11_IGNORE_SUBOPTIMAL(false) + DRI_CONF_SECTION_END }; static void diff --git a/src/util/00-mesa-defaults.conf b/src/util/00-mesa-defaults.conf index 051b6ee4b52..7e7f33c07ef 100644 --- a/src/util/00-mesa-defaults.conf +++ b/src/util/00-mesa-defaults.conf @@ -597,24 +597,30 @@ TODO: document the other workarounds. diff --git a/src/util/driconf.h b/src/util/driconf.h index 32ccf87a5e1..04bf560f8bf 100644 --- a/src/util/driconf.h +++ b/src/util/driconf.h @@ -422,6 +422,10 @@ DRI_CONF_OPT_B(vk_x11_ensure_min_image_count, def, \ "Force the X11 WSI to create at least the number of image specified by the driver in VkSurfaceCapabilitiesKHR::minImageCount") +#define DRI_CONF_VK_X11_IGNORE_SUBOPTIMAL(def) \ + DRI_CONF_OPT_B(vk_x11_ignore_suboptimal, def, \ + "Force the X11 WSI to never report VK_SUBOPTIMAL_KHR") + #define DRI_CONF_VK_KHR_PRESENT_WAIT(def) \ DRI_CONF_OPT_B(vk_khr_present_wait, def, \ "Expose VK_KHR_present_wait and id extensions despite them not being implemented for all supported surface types") diff --git a/src/vulkan/wsi/wsi_common.h b/src/vulkan/wsi/wsi_common.h index b6b803c52ef..8d136869040 100644 --- a/src/vulkan/wsi/wsi_common.h +++ b/src/vulkan/wsi/wsi_common.h @@ -160,6 +160,10 @@ struct wsi_device { /* adds an extra minImageCount when running under xwayland */ bool extra_xwayland_image; + + /* Never report VK_SUBOPTIMAL_KHR. Used to workaround + * games that cannot handle SUBOPTIMAL correctly. */ + bool ignore_suboptimal; } x11; struct { diff --git a/src/vulkan/wsi/wsi_common_x11.c b/src/vulkan/wsi/wsi_common_x11.c index 46733c932c8..0ac83108252 100644 --- a/src/vulkan/wsi/wsi_common_x11.c +++ b/src/vulkan/wsi/wsi_common_x11.c @@ -1241,9 +1241,12 @@ x11_handle_dri3_present_event(struct x11_swapchain *chain, if (config->pixmap_flags & PresentWindowDestroyed) return VK_ERROR_SURFACE_LOST_KHR; - if (config->width != chain->extent.width || - config->height != chain->extent.height) - return VK_SUBOPTIMAL_KHR; + struct wsi_device *wsi_device = (struct wsi_device *)chain->base.wsi; + if (!wsi_device->x11.ignore_suboptimal) { + if (config->width != chain->extent.width || + config->height != chain->extent.height) + return VK_SUBOPTIMAL_KHR; + } break; } @@ -1280,6 +1283,11 @@ x11_handle_dri3_present_event(struct x11_swapchain *chain, } VkResult result = VK_SUCCESS; + + struct wsi_device *wsi_device = (struct wsi_device *)chain->base.wsi; + if (wsi_device->x11.ignore_suboptimal) + return result; + switch (complete->mode) { case XCB_PRESENT_COMPLETE_MODE_COPY: if (chain->copy_is_suboptimal) @@ -1824,9 +1832,12 @@ x11_acquire_next_image(struct wsi_swapchain *anv_chain, xcb_get_geometry_reply_t *geom = xcb_get_geometry_reply(chain->conn, geom_cookie, &err); VkResult result = VK_SUCCESS; if (geom) { - if (chain->extent.width != geom->width || - chain->extent.height != geom->height) - result = VK_SUBOPTIMAL_KHR; + struct wsi_device *wsi_device = (struct wsi_device *)chain->base.wsi; + if (!wsi_device->x11.ignore_suboptimal) { + if (chain->extent.width != geom->width || + chain->extent.height != geom->height) + result = VK_SUBOPTIMAL_KHR; + } } else { result = VK_ERROR_SURFACE_LOST_KHR; } @@ -2823,8 +2834,10 @@ x11_surface_create_swapchain(VkIcdSurfaceBase *icd_surface, * happen by flip, only by copy. So this is a suboptimal copy, because if the client would change * the chain extents X may be able to flip */ - if (chain->extent.width != cur_width || chain->extent.height != cur_height) - chain->status = VK_SUBOPTIMAL_KHR; + if (!wsi_device->x11.ignore_suboptimal) { + if (chain->extent.width != cur_width || chain->extent.height != cur_height) + chain->status = VK_SUBOPTIMAL_KHR; + } /* On a new swapchain this helper variable is set to false. Once we present it will have an * impact once we ever do at least one flip and go back to copying afterwards. It is presumed @@ -3020,6 +3033,11 @@ wsi_x11_init_wsi(struct wsi_device *wsi_device, wsi_device->x11.xwaylandWaitReady = driQueryOptionb(dri_options, "vk_xwayland_wait_ready"); } + + if (driCheckOption(dri_options, "vk_x11_ignore_suboptimal", DRI_BOOL)) { + wsi_device->x11.ignore_suboptimal = + driQueryOptionb(dri_options, "vk_x11_ignore_suboptimal"); + } } wsi->base.get_support = x11_surface_get_support;