We are currently migrating Bugzilla to GitHub issues.
Any changes made to the bug tracker now will be lost, so please do not post new bugs or make changes to them.
When we're done, all bug URLs will redirect to their equivalent location on the new bug tracker.

Bug 4671 - SDL_Vulkan_GetDrawableSize() off while drag-resizing window
Summary: SDL_Vulkan_GetDrawableSize() off while drag-resizing window
Status: ASSIGNED
Alias: None
Product: SDL
Classification: Unclassified
Component: video (show other bugs)
Version: 2.0.9
Hardware: x86_64 Linux
: P2 normal
Assignee: Ryan C. Gordon
QA Contact: Sam Lantinga
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2019-06-17 22:44 UTC by colaeuphoria
Modified: 2019-06-26 04:35 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description colaeuphoria 2019-06-17 22:44:46 UTC
When creating a swapchain I use SDL_Vulkan_GetDrawableSize() to get information for the extent immediately before calling vkCreateSwapchainKHR(). This works fine until I drag-resize the window. When I drag-resize the window I tear down my swapchain and build it again calling SDL_Vulkan_GetDrawableSize() many times as I drag, but the validation layers start giving out messages like these:

>vkCreateSwapchainKHR() called with imageExtent = (1194,720), which is outside the bounds returned by vkGetPhysicalDeviceSurfaceCapabilitiesKHR(): currentExtent = (1102,720), minImageExtent = (1102,720), maxImageExtent = (1102,720). The Vulkan spec states: imageExtent must be between minImageExtent and maxImageExtent, inclusive, where minImageExtent and maxImageExtent are members of the VkSurfaceCapabilitiesKHR structure returned by vkGetPhysicalDeviceSurfaceCapabilitiesKHR for the surface

The original window width was 1280 and I was in the middle of dragging it down.

I'm currently working around this by manually clamping the results returned by SDL_Vulkan_GetDrawableSize() to the min and max extents in the VkSurfaceCapabilitiesKHR struct and the validation errors go away. My code is as follows:

	int width, height;
	SDL_Vulkan_GetDrawableSize(win, &width, &height);
	width = CLAMP(width, sc.capabilities.minImageExtent.width, sc.capabilities.maxImageExtent.width);
	height = CLAMP(height, sc.capabilities.minImageExtent.height, sc.capabilities.maxImageExtent.height);
	swapchainExtent.width = width;
	swapchainExtent.height = height;
	const VkSwapchainCreateInfoKHR createInfo = ...;
	vkCreateSwapchainKHR(...);

I'm using GNOME with proprietary NVIDIA drivers, but IIRC the same thing happens on Intel Integrated with Mesa.
Comment 1 Ryan C. Gordon 2019-06-20 23:42:13 UTC
I assume this is X11 and not Wayland, right? For X11, SDL_Vulkan_GetDrawableSize() is literally just SDL_GetWindowSize().

I would say clamping to the min/maxImageExtent is the correct approach and not a workaround, unless you never get a resize event that puts you at the correct dimensions when dragging completes.

Something worth trying: use an SDL event filter to catch resize events as X11 sends them. Otherwise they're going into a separate queue and when you get the event from SDL from SDL_PollEvents, it's possible the X server has moved on and resized the window further and you don't have that information yet.

Also worth trying, first: make note of resizes, but don't actually create a swapchain until the event queue is empty (SDL_PollEvent() returns 0). This is a better idea in any case: if a big pile of resize events have queued up, you only want to do this once per frame.

These are just ideas, though. Let me know what you find.

--ryan.
Comment 2 colaeuphoria 2019-06-22 07:12:38 UTC
(In reply to Ryan C. Gordon from comment #1)
> I assume this is X11 and not Wayland, right? For X11,
> SDL_Vulkan_GetDrawableSize() is literally just SDL_GetWindowSize().
> 
> I would say clamping to the min/maxImageExtent is the correct approach and
> not a workaround, unless you never get a resize event that puts you at the
> correct dimensions when dragging completes.
> 
> Something worth trying: use an SDL event filter to catch resize events as
> X11 sends them. Otherwise they're going into a separate queue and when you
> get the event from SDL from SDL_PollEvents, it's possible the X server has
> moved on and resized the window further and you don't have that information
> yet.
> 
> Also worth trying, first: make note of resizes, but don't actually create a
> swapchain until the event queue is empty (SDL_PollEvent() returns 0). This
> is a better idea in any case: if a big pile of resize events have queued up,
> you only want to do this once per frame.
> 
> These are just ideas, though. Let me know what you find.
> 
> --ryan.

Yes this is X, not Wayland. I always loop my events until SDL_PollEvent() returns 0, but I suspect there's a race condition where the event queue starts filling up again by the time it recreates the swapchain.

I've tried each possibility. I've recreated the swapchain when vkAcquireNextImageKHR() returns OUT_OF_DATE or SUBOPTIMAL. I've filtered (emptied the entire queue of) events for SDL_WINDOWEVENT_RESIZED and passed the event-given coordinates (data1 and data2) but I suspect a race condition between emptying the queue and recreating the swapchain where the "new" coordinates given by the resize event are already outdated.

I do see that the canonical solution is to simply CLAMP() the given coordinates between min and max image extents, in which case the "bug-fix" would just be adding a note of this in the header comments of SDL_Vulkan_GetDrawableSize().

"This function may return spurious or out-of-date results if the window is in the middle of being resized. The `width` and `height` should be clamped between their respective `minImageExtent` and `maxImageExtent` of their `VkSurfaceCapabilitiesKHR` structure returned by `vkGetPhysicalDeviceSurfaceCapabilitiesKHR()`."
Comment 3 colaeuphoria 2019-06-22 08:33:38 UTC
Although I wonder why one should use SDL_Vulkan_GetDrawableSize() over currentExtent in the first place.
Comment 4 Ryan C. Gordon 2019-06-22 17:52:39 UTC
(In reply to colaeuphoria from comment #3)
> Although I wonder why one should use SDL_Vulkan_GetDrawableSize() over
> currentExtent in the first place.

I imagine the thinking is to match SDL_GL_GetDrawableSize(), which takes into account DPI scaling, but I'm not super-familiar with this piece of SDL yet.

--ryan.