You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
As discussed a few days ago, resizing the window on Windows is supposed to continue drawing frames during the resize, but doesn't, and instead, the last frame just gets bilinearly scaled to fit the window until the mouse is released.
I've done some investigation, and the reason for the current behaviour is that the default window message handlers aren't leaving the stack until the resize has finished. That means that the resize events just get queued up in a buffer and then all happen in quick succession between frames. That's particularly bad as each of the buffered resize events triggers regeneration of all pipelines, and those new pipelines will go unused except for the final resize, although with #1268 or equivalent, that would stop happening.
If we were to do things by the book, then instead of having the current
while (viewer->advanceToNextFrame())
{
viewer->handleEvents();
viewer->update();
viewer->recordAndSubmit();
viewer->present();
}
main loop, we'd have something more like Win32_Window.cpp's
while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
{
// somehow close all windows
events.emplace_back(vsg::CloseWindowEvent::create(this, event_time));
}
else
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
}
and all the calls to the viewer would be done in response to a WM_PAINT message.
Windows is sending a WM_PAINT message several times during a resize to tell us to draw a new frame, but because the viewer->handleEvents() call hasn't returned, we can't.
For comparison, I checked what the OSG did, and its behaviour was arguably worse - it didn't do the bilinear scaling, but did still stop rendering frames, so you'd end up with this ugly mess:
vsgQt's vsgqtviewer avoids the problem because it basically doesn't use a typical VSG main loop, instead letting Qt have control over the main loop. Qt internally has something relatively similar to a by-the-book Win32 window event pump as its main loop, and fits its own work within it, e.g. interleaving the timer event that triggers a redraw into its event queue.
I'll look into ways to solve this and hope there'll be something that doesn't require the message pump to become the main loop.
The text was updated successfully, but these errors were encountered:
The messages arrive in the thread that created the window. I don't know if we could move loads of stuff to a helper thread so that everything was dealt with by a background thread - that seems complicated and potentially fragile. I did have a look at what glfw does in case it's got a brilliant system to make the problem go away, but at least with how VulkanTutorial uses it, it's got the same problem as we do where new frames aren't drawn during the resize.
I've had a look at the typical approaches for getting rid of this problem with GLFW, and they are:
It's got a callback it fires when the window is resized which applications can use to draw a new frame to fit the new size.
When a resize starts, you can start a second frame loop on another thread and stop it once the resize has finished. Obviously, this needs synchronisation if you're going to respond to events coming from the main thread. I guess it's kind of equivalent to moving all the window stuff to a background thread.
As discussed a few days ago, resizing the window on Windows is supposed to continue drawing frames during the resize, but doesn't, and instead, the last frame just gets bilinearly scaled to fit the window until the mouse is released.
I've done some investigation, and the reason for the current behaviour is that the default window message handlers aren't leaving the stack until the resize has finished. That means that the resize events just get queued up in a buffer and then all happen in quick succession between frames. That's particularly bad as each of the buffered resize events triggers regeneration of all pipelines, and those new pipelines will go unused except for the final resize, although with #1268 or equivalent, that would stop happening.
If we were to do things by the book, then instead of having the current
main loop, we'd have something more like
Win32_Window.cpp
'sand all the calls to the viewer would be done in response to a
WM_PAINT
message.Windows is sending a
WM_PAINT
message several times during a resize to tell us to draw a new frame, but because theviewer->handleEvents()
call hasn't returned, we can't.For comparison, I checked what the OSG did, and its behaviour was arguably worse - it didn't do the bilinear scaling, but did still stop rendering frames, so you'd end up with this ugly mess:
vsgQt's
vsgqtviewer
avoids the problem because it basically doesn't use a typical VSG main loop, instead letting Qt have control over the main loop. Qt internally has something relatively similar to a by-the-book Win32 window event pump as its main loop, and fits its own work within it, e.g. interleaving the timer event that triggers a redraw into its event queue.I'll look into ways to solve this and hope there'll be something that doesn't require the message pump to become the main loop.
The text was updated successfully, but these errors were encountered: