Bug 466454 - Vulkan and OpenGL windows not being created properly with fraction scale factors
Summary: Vulkan and OpenGL windows not being created properly with fraction scale factors
Status: RESOLVED FIXED
Alias: None
Product: kwin
Classification: Plasma
Component: wayland-generic (show other bugs)
Version: 5.27.1
Platform: openSUSE Linux
: HI major
Target Milestone: ---
Assignee: KWin default assignee
URL:
Keywords:
: 469818 (view as bug list)
Depends on:
Blocks:
 
Reported: 2023-02-26 07:47 UTC by Mark Richardson
Modified: 2023-06-01 11:26 UTC (History)
7 users (show)

See Also:
Latest Commit:
Version Fixed In:
Sentry Crash Report:


Attachments
example image (1.85 MB, image/png)
2023-02-26 07:47 UTC, Mark Richardson
Details
xwayland_swapchain_kwin_150scale (473.02 KB, image/png)
2023-04-17 14:30 UTC, Mark Richardson
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Mark Richardson 2023-02-26 07:47:45 UTC
Created attachment 156749 [details]
example image

Trying to create a window of a given size(ex. 1280x720) results in being given a surface one exaclty 1 pixel too tall (1280x721).
Happens only on wayland with amdgpu, on the radeon mesa opengl driver, and both RADV and lavapipe drivers, with fractional scaling factors such as 150%.

Does not happen on kwin_x11 nor on wayland with integer scale factors.

Was happening on plasma 5.26 before the new fractional scaling protocol merge.
Comment 1 Zamundaaa 2023-03-02 16:37:27 UTC
Can confirm for X11 windows, but not for native Wayland ones.
Do keep in mind though that your program needs to handle such a situation either way, you can't expect the requested size to always be honored.
Comment 2 Oleg 2023-03-02 21:33:16 UTC
Can confirm
OpenGL and Vulkan applications won't start with 110% scaling, but start just fine with 125% scaling.
Comment 3 Mark Richardson 2023-03-27 00:36:59 UTC
After even more testing this appears to only happen with XWayland windows and a scale set to 150%, or 250%, no other fractional scale factors trigger the disconnect between the window size, and the vulkan surface extent.

Just to be clear what's happening, with XWayland windows on kwin_wayland and scale values of 150% or 250%, vkGetPhysicalDeviceSurfaceCapabilitiesKHR returns a min and max extent of (1280,721) on a window of size (1280,720). This breaks most Vulkan apps, including almost every Steam/Proton game.

The solution can not be to create the swapchain based on either the min/max extent instead of the window size, because with SDL2's native Wayland backend, the min/max reported extants are always (1,1),(16384,16384).

This still happens on the latest KDE(opensuse tumbleweed), with the stock amdgpu kernel driver with RADV, and started on Plasma 5.26, before the new fractional scaling protocol.

None of this happens on the lavapipe vulkan driver, min/max extant always matches the window size exactly on Xorg and XWayland, and always returns min of (1,1) and max of (16384,16384) on wayland
Comment 4 Mark Richardson 2023-03-27 00:41:33 UTC
(In reply to Mark Richardson from comment #3)

> None of this happens on the lavapipe vulkan driver, min/max extant always
> matches the window size exactly on Xorg and XWayland, and always returns min
> of (1,1) and max of (16384,16384) on wayland

actually, I had the scale set wrong when I tested lvp, the problem happens with xWayland windows on lvp with 150% and 250% scaling just like with RADV.
Comment 5 Juan 2023-03-29 16:03:10 UTC
Hi, I think I'm experiencing the same error. If I run a steam game on xwayland with proton, the game window doesn't appear (but I hear the background music)

The game shows the window if my monitor has scale (tested from 100% to 160%):

110%, 120%, 125%, 130%, 160%

Doesn't show on scale:

105%, 115%, 135%, 140%, 145%, 150%, 155%

The resolution is: 2560x1440
Comment 6 Fushan Wen 2023-04-03 15:08:02 UTC
See also https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/5783
Comment 7 Mark Richardson 2023-04-13 15:45:09 UTC
Still happens on Plasma 5.27.4, is anyone looking into this? I would like to continue using Linux and KDE, and am more than willing to help test images and builds as long as this bug isn't going to rot or be closed as WONTFIX.

This seems like the kind of bug that is going to get written off and ignored as a edge case, until a seemingly unrelated DRM/wayland change happens, followed by a panicked and embarrasing rush to haphazardly fix the issue as half the userbase can't see any of thier windows in a future release.
Comment 8 Mark Richardson 2023-04-13 17:33:05 UTC
Just tested ubuntu 23.04 beta, absolutely no problems with any scaling factors on gnome/whatever they are using. This is solely a Kwin problem.
Comment 9 Mark Richardson 2023-04-15 16:37:51 UTC
testing with the latest tumbleweed under virtualbox shows the same problem with both llvmpipe and SVGA3D GL drivers.
Comment 10 David Edmundson 2023-04-16 11:41:45 UTC
Can you confirm that "X applications scale themselves" setting is currently checked, and that unchecking it avoids the problem?
Comment 11 David Edmundson 2023-04-16 14:12:14 UTC
Relevant mesa code:
wsi_common_x11.c: 659


```
x11_surface_get_capabilities(VkIcdSurfaceBase *icd_surface,
                             struct wsi_device *wsi_device,
                             VkSurfaceCapabilitiesKHR *caps)
{
   xcb_connection_t *conn = x11_surface_get_connection(icd_surface);
   xcb_window_t window = x11_surface_get_window(icd_surface);
   xcb_get_geometry_cookie_t geom_cookie;
   xcb_generic_error_t *err;
   xcb_get_geometry_reply_t *geom;
   unsigned visual_depth;

   geom_cookie = xcb_get_geometry(conn, window);

   /* This does a round-trip.  This is why we do get_geometry first and
    * wait to read the reply until after we have a visual.
    */
   xcb_visualtype_t *visual =
      get_visualtype_for_window(conn, window, &visual_depth);

   if (!visual)
      return VK_ERROR_SURFACE_LOST_KHR;

   geom = xcb_get_geometry_reply(conn, geom_cookie, &err);
   if (geom) {
      VkExtent2D extent = { geom->width, geom->height };
      caps->currentExtent = extent;
      caps->minImageExtent = extent;
      caps->maxImageExtent = extent;
   }
```

it's just using the regular window geometry, so that can't really be wrong. 

I strongly suspect our window is configured to the 1280x721size; at which point it's partly client side problems for not handling that correctly. Turning a harmless though non-ideal quirk into a user-breakage.

We could aim for a mesa fix there to use the similar min and max that wayland would use.

As for why kwin is configuring a window differently to requested, I'll expand our relevant unit test and try to hit it. It'll probably be the annoying resize increments. If you can `xprop` a window that's known to be annoying that would help me.
Comment 12 Mark Richardson 2023-04-16 14:34:30 UTC
(In reply to David Edmundson from comment #10)
> Can you confirm that "X applications scale themselves" setting is currently
> checked, and that unchecking it avoids the problem?

makes no difference
Comment 13 Mark Richardson 2023-04-16 15:34:26 UTC
(In reply to David Edmundson from comment #11)

> I strongly suspect our window is configured to the 1280x721size; at which
> point it's partly client side problems for not handling that correctly.
> Turning a harmless though non-ideal quirk into a user-breakage.

What can/should an app do about being lied to about the window size? And only under certain circumstances? All An app can do is request a window of a given size and try to create a swapchain of that size. For native wayland windows, the min/max is always 1-16k, so its fine, and under xwayland it should be the same, or match exactly like it usually does, otherwise there's nothing you can do without writing platform specific code.
Comment 14 David Edmundson 2023-04-16 16:44:36 UTC
I don't think the app is being lied to. 
It's being resized. 

The vulkan code above is reading the current size the window is.
Comment 15 Zamundaaa 2023-04-16 16:52:20 UTC
(In reply to Mark Richardson from comment #13)
> What can/should an app do about being lied to about the window size?
You need to query the surface capabilities with vkGetPhysicalDeviceSurfaceCapabilitiesKHR, and choose a swapchain size that's bigger than or equal to the minimum, and smaller than or equal to the maximum swapchain extends. See https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkSurfaceCapabilitiesKHR.html for details

(In reply to Juan from comment #5)
> Hi, I think I'm experiencing the same error. If I run a steam game on
> xwayland with proton, the game window doesn't appear (but I hear the
> background music)

What specific game and Proton version did you use? This is not happening for me and afaict from the dxvk code, it's handling the min/max surface extends correctly.
Comment 16 Mark Richardson 2023-04-16 18:51:16 UTC
(In reply to Zamundaaa from comment #15)
> (In reply to Mark Richardson from comment #13)
> > What can/should an app do about being lied to about the window size?
> You need to query the surface capabilities with
> vkGetPhysicalDeviceSurfaceCapabilitiesKHR, and choose a swapchain size
> that's bigger than or equal to the minimum, and smaller than or equal to the
> maximum swapchain extends.

on wayland, that could be anything from 1-16k, on xwayland its a specific size, that sometimes doesn't match the window size depending on the scaling setting for kwin. I don't see a cross platform way to set the swapchain size, unless kwin gives a surface of either 1px-16384px like it does on wayland, or exactly matching the window size like on xwayland with no scaling active.
Comment 17 Mark Richardson 2023-04-16 19:47:19 UTC
(In reply to Zamundaaa from comment #15)

> 
> What specific game and Proton version did you use? This is not happening for
> me and afaict from the dxvk code, it's handling the min/max surface extends
> correctly.

I can reproduce this issue with thedarkmod, a linux native opengl game, under virtualbox with both SVGA3D and llvmpipe gl drivers
Comment 18 David Edmundson 2023-04-17 08:38:01 UTC
> I don't see a cross platform way to set the swapchain size, unless kwin gives a surface of either 1px-16384px like it does on wayland, or exactly matching the window size like on xwayland with no scaling active.

We've got a few crossed paths:

 - kwin isn't setting this surface capabilities sizes, this all comes from mesa and this 721px values is based on the current window size
we can change mesa.

 - from the output it strongly suggests kwin is resizing the window (which is a silly rounding bug we need to fix) but that would be the same if the user resized things by dragging a corner and resized a window

The crossplatform way to do things is to make sure clients build your swapchain size is also based on the *current* window size, watching for the window being resized as external factors can resize things.
Comment 19 Mark Richardson 2023-04-17 14:30:12 UTC
(In reply to David Edmundson from comment #18)
> > I don't see a cross platform way to set the swapchain size, unless kwin gives a surface of either 1px-16384px like it does on wayland, or exactly matching the window size like on xwayland with no scaling active.
> 
> We've got a few crossed paths:
> 
>  - kwin isn't setting this surface capabilities sizes, this all comes from
> mesa and this 721px values is based on the current window size
> we can change mesa.
> 
>  - from the output it strongly suggests kwin is resizing the window (which
> is a silly rounding bug we need to fix) but that would be the same if the
> user resized things by dragging a corner and resized a window
> 
> The crossplatform way to do things is to make sure clients build your
> swapchain size is also based on the *current* window size, watching for the
> window being resized as external factors can resize things.

All SDL window queries say the window size is 1280x720 with a min/max swapchain extant of 1280x721 to 1280x721.
        SDL_GetWindowSize();
        SDL_GetWindowSizeInPixels();
        SDL_Vulkan_GetDrawableSize();

However on native wayland, the max extant is always 16k. not what I would call optimal usage.
Comment 20 Mark Richardson 2023-04-17 14:30:52 UTC
Created attachment 158165 [details]
xwayland_swapchain_kwin_150scale
Comment 21 Zamundaaa 2023-04-17 16:02:00 UTC
> However on native wayland, the max extant is always 16k. not what I would call optimal usage
I thought this was obvious but maybe I didn't describe it well: When picking a swapchain size, Vulkan requires you to do
> extends = min(maxExtends, max(desiredSize, minExtends))
which will handle this and any other situations with restricted size options correctly.
Comment 22 Mark Richardson 2023-04-17 17:04:36 UTC
(In reply to Zamundaaa from comment #21)
> > However on native wayland, the max extant is always 16k. not what I would call optimal usage
> I thought this was obvious but maybe I didn't describe it well: When picking
> a swapchain size, Vulkan requires you to do
> > extends = min(maxExtends, max(desiredSize, minExtends))
> which will handle this and any other situations with restricted size options
> correctly.

Ah, thats makes sense now.

Now there is only the little matter of every single other 3D game not working.
I know the usual attitude of Wayland developers when considering changing protocol/compositor behaviour vs. every single application being written wrong is to usually stick to thier guns, But I think kwin would really benefit from being able to display the windows of the tens of thousands of games already out there, and I belive the best ssolution for the users of kwin is for it to not return different swapchain extants depending on the scaling factor.
Comment 23 Bug Janitor Service 2023-04-18 16:27:54 UTC
A possibly relevant merge request was started @ https://invent.kde.org/plasma/kwin/-/merge_requests/3990
Comment 24 David Edmundson 2023-04-20 11:15:51 UTC
The darkmod case seems to be different.

With the fractional scaling xserver ends up being told a logical size like 2133. X will then use that as a screen size, but set a mode size of 2128 (rounded down to the nearest 8). We then continue to use a window size of 2133, larger than the monitor.

This can be reproduced without scaling. Just by running kwin_wayland nested with a resizable window and dragging the window about. Sometimes "thedarkmod" will start, sometimes not.
Comment 25 David Edmundson 2023-04-21 11:48:30 UTC
filed at: https://gitlab.freedesktop.org/xorg/xserver/-/issues/1540
Comment 26 David Edmundson 2023-04-24 20:01:14 UTC
X developers were super fast.

https://gitlab.freedesktop.org/xorg/xserver/-/issues/1540

This fixes the issues with "thedarkmod" for me. If you can confirm that, it would be great.
Comment 27 Zamundaaa 2023-05-16 15:06:14 UTC
*** Bug 469818 has been marked as a duplicate of this bug. ***
Comment 28 Mark Richardson 2023-05-27 22:06:39 UTC
What's the blocker to getting this fixed? Plasma 6 is going wayland by default, and with qt6's native fractional scaling support being advertised, I see a lot of angry and confused users unable to play any games in the near future.
Comment 29 David Edmundson 2023-06-01 11:26:40 UTC
The xwayland patch is merged pending release which fixes thedarkmod for me.

Another patch to do with handling of native X geometry landed in 5.27.6 hopefully that address some of the others. Lets investigate once those two are both released if other issues remain