floooh / sokol

minimal cross-platform standalone C headers
https://floooh.github.io/sokol-html5
zlib License
6.98k stars 490 forks source link

Windows Resize Event Delay #853

Open voidware opened 1 year ago

voidware commented 1 year ago

Currently it appears I dont see the RESIZED event until the main window resize drag is complete.

There's a note in the code here to explain it;

 /* NOTE: resizing the swap-chain during resize leads to a substantial
                   memory spike (hundreds of megabytes for a few seconds).

                if (_sapp_win32_update_dimensions()) {
                    #if defined(SOKOL_D3D11)
                    _sapp_d3d11_resize_default_render_target();
                    #endif
                    _sapp_win32_app_event(SAPP_EVENTTYPE_RESIZED);
                }
                break;
*/

Is this only a problem with D3D11?

I tried putting this code back in and my app now resizes smoothly and I'm not seeing a memory spike (win 10/ -DSOKOL_GLCORE33).

What is the backstory here. Older windows versions? Drivers?

Or is this something that can actually be put back in now?

thanks for any help and info.

floooh commented 1 year ago

I'll need to check what the current behaviour is. IIRC the problem might be that DXGI holds onto (discarded) swapchain surfaces for a couple of frames which then causes massive memory usage spikes when the swapchain surfaces are resized each frame. I could also reproduce this behaviour in official D3D samples, so I doubt I did something wrong there.

But maybe that behaviour had also changed when I added the DXGI_PRESENT_DO_NOT_WAIT flag and everything is fine now (but I would be surprised if I hadn't tested that).

What do you use the RESIZE event for? The intent was to only send that event when the framebuffer size changes - in case your code also needs to resize offscreen render targets to match the new framebuffer size.

It doesn't necessarily mean that the window size has changed (it might probably make sense to split the RESIZE event into two separate events, one for framebuffer size changes, and one for window size changes).

Btw, I'm surprised that GL resizing appears to work, I was pretty sure that the GL context also just scales the window content until the resizing had finished and then only performs a resize of the framebuffer once at the end of the resizing operation (which is essentially how the D3D11 path now behaves with that code block out-commented).

voidware commented 1 year ago

Thanks for all the info.

I'm not actually using the RESIZED event. I have an imgui window which i create "fullscreen" inside the Sokol main window. When I resize the Sokol window, the imgui one remains unchanged until i stop the resize drag, at which point, it resizes correctly to fill.

When i put the resize code back in, it resizes the imgui window at the same time as resizing the Sokol window. This is what i want. It would be fine to choke this back a bit instead of every pixel but without any dynamic resize it looks bad.

Unless there's another way to achieve this perhaps?

floooh commented 1 year ago

Unless there's another way to achieve this perhaps?

Not at the moment. The reason why you see a difference is the _sapp_win32_update_dimensions() call, this updates the values returned by sapp_width()/sapp_height() each frame.

However, those values need to be synced with the actual framebuffer size, otherwise some sokol-gfx backends (like Metal) will throw validation layer errors.

A proper solution would be a better separation of 'window size' and 'framebuffer size' in the sokol-app API. E.g. what Dear ImGui actually needs is the updated window size, the framebuffer size isn't all that important.

This topic is related to https://github.com/floooh/sokol/issues/590 where I want to add some window management functions to the public API, and which would also introduce a clean separation between window size and framebuffer size (this would also add two new function to get the window client area size).

...but let me check first what the current behaviour on D3D11 is when putting that block back in... I'll need to finish my work on the sokol-gfx image/sampler separation first though.

voidware commented 1 year ago

Ok thanks. Right now, it seems I'm ok. Although I'll keep a lookout for this memory spike. Perhaps it's D3D only.