Search code examples
cvulkanxcb

XCB window geometry/surface dimensions appear to be stale despite reconfigure


I was working with Vulkan on an XCB-provided window surface under my own windowing abstraction but encountered a rather strange behaviour when recreating the swapchain on recieving a window reconfigure event (XCB_CONFIGURE_NOTIFY).

The values returned by xcb_get_geometry appear to stay as the initial values for the window. i.e. if I created a window of extent 640x480 at (0,0), drag it elsewhere on the screen and resize it - the values returned by xcb_get_geometry will still be 640x480 at (0,0). I tried explicitly flushing and reconfiguring the window to some other value to see whether it was just a case of the events being delivered erroneously - but even though I could see the window visually resizing, xcb_get_geometry still remained the same.

The reason this was highlighted was that Validation Layers (Actual message attached below) notified me the extent I had specified to vkCreateSwapchain was outside the range of acceptable values according to vkGetPhysicalDeviceSurfaceCapabilitiesKHR - also 640x480 despite the window visually being resized and a resize event having been delivered. This too persisted even if I explicitly reconfigured the window before recreating the swapchain.

I feel like I may be missing some sort of surface-resize proc I should be calling, or maybe I have to wait a frame before resizing but I am not sure.

There is a lot of code but I can point out some relevant parts - it's all under this repo.

genstone/genfx/genuwin.c:361 Event polling code - configuration requests are buffered into separate position and window events delivered on the two subsequent calls to the one where the event is actually processed.

genstone/genfx/gengfx.c:902 Swapchain recreation code - shouldn't be problematic as far as I can see and the issue does appear to be on the side of my XCB abstraction but probably better to share as much info as possible.

sandbox/sample/main.c:240 Handling of wrapped Genuwin event and dispatching call to gen_internal_vk_create_swapchain.

The validation error which signalled this (Without Validation Layers submitting VkQueue results in failure):

Fatal: Validation Error: Validation Error: [ VUID-VkSwapchainCreateInfoKHR-imageExtent-01274 ] Object 0: handle = 0x62d000168450, type = VK_OBJECT_TYPE_DEVICE; | MessageID = 0x7cd0911d | vkCreateSwapchainKHR() called with imageExtent = (792,605), which is outside the bounds returned by vkGetPhysicalDeviceSurfaceCapabilitiesKHR(): currentExtent = (640,480), minImageExtent = (640,480), maxImageExtent = (640,480). 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 (https://www.khronos.org/registry/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-VkSwapchainCreateInfoKHR-imageExtent-01274)
Trace: frame #0: 0x0x7f4c9a0afa00 gen_internal_vk_debug_callback() genstone/genfx/gengfx.c
Trace: frame #1: 0x0x7f4c9a0b33e0 gen_internal_vk_create_swapchain() genstone/genfx/gengfx.c
Trace: frame #2: 0x0x7f4c9a0baaa0 gen_gfx_targetable_geometry_update() genstone/genfx/gengfx.c
Trace: frame #3: 0x0x563b13ebcbc0 main() sandbox/sample/main.c

The backtrace is missing any code not tooled by me but you get the idea.

I am using XCB 1.15-1 (according to pacman), and I have submoduled all the Vulkan "stuff" I use (Validation Layers, headers, loader) so they're all up to date with their trunks (at the time I'm posting).


Solution

  • Found it. You are indeed making your window non-resizable by selecting XCB_EVENT_MASK_RESIZE_REDIRECT on the window here: https://github.com/Th3T3chn0G1t/Genstone/blob/c8759b6687bb83045b8fe58b03c2575276940ca7/genstone/genfx/genuwin.c#L741-L743

    Thanks to this, you only get ResizeRequest events instead of actually being resized, see: https://www.x.org/releases/X11R7.6/doc/xproto/x11protocol.html#events:ResizeRequest

    That whole event mask looks like "this seriously needs some line breaks for readability", but also "I am just selecting every event there is". I suggest to just ask for the events that you are really interested in. Just selecting an event already has side-effects and ResizeRedirect is not the only such event mask.

    I found https://github.com/Th3T3chn0G1t/Genstone/blob/c8759b6687bb83045b8fe58b03c2575276940ca7/genstone/genfx/genuwin.c#L394-L722 and it looks like you are only interested in few of the events. You can find which event mask you need for which event on https://www.x.org/releases/X11R7.6/doc/xproto/x11protocol.html.