4

I'm experimenting with some rust code that is a slight re-structuring of the code shown in the Learn WGPU tutorial, including the addition of a uniform transform to draw objects at fixed (pixel) locations and sizes.

I notice that when I resize my window, that my boxes stretch, squash, and jitter drastically.

resize jitter

The stretching/warping follows the magnitude and direction of the delta, and once the resize is completed the boxes always settle at their correct position and size

enter image description here

GifCam's frame diff view shows the extent of the stretching during the move

enter image description here

To rule out any of my changes to the tutorial code, I cloned the repository, built and ran "tutorial6-uniforms", and it shows the same behavior with resizes stretching and squashing the shape as they occur.

enter image description here

Adding println's to my resize and render functions (and disabling redraws on MainEventsCleared) shows even pairs of resize events and redraws

redraw called PhysicalSize { width: 800, height: 600 } // initial draw
resize called PhysicalSize { width: 799, height: 600 } // resize begins
redraw called PhysicalSize { width: 799, height: 600 }
resize called PhysicalSize { width: 774, height: 589 }
redraw called PhysicalSize { width: 774, height: 589 }

This all makes me believe that there is something going on behind the scenes, where perhaps the frame is stretched first to match the window's new size before the redraw is completed? Is there a way to prevent this? When there are a lot of elements on the screen, especially text, this effect becomes pretty jarring. Not to mention most application's do not suffer from this, so it looks unprofessional and ugly.

Here is my event loop, I've omitted other code to keep my post size down but will add more if it helps troubleshoot the issue, or refer to the code here from the tutorial.

event_loop.run(move |event, _, control_flow| {
    match event {
        Event::WindowEvent {
            ref event,
            window_id,
        } if window_id  == window.id() => {
            match event {
                // ...
                WindowEvent::Resized(physical_size) => {
                    renderer.resize(*physical_size);
                },
                _ => {}
            }
        },
        Event::RedrawRequested(_) => {
            match renderer.render() {
                Ok(_) => {},
                Err(e) => eprintln!("{:?}", e),
            }
        },
        // no change in observed resizing behavior with or without
        /*Event::MainEventsCleared => {
            window.request_redraw();
        },*/
        // ...
        _ => {}
    }
})
plast1k
  • 793
  • 8
  • 15

2 Answers2

2

I believe this is a winit issue, where it both sets the view to be automatically resized and also not giving the app chance to redraw before OS redraws the resized window. I haven't found a good workaround, so I guess the only path is for someone to dive in to winit code.

scoopr
  • 903
  • 8
  • 14
  • Interesting that most of the wgpu / winit issues seem to be first reported on macOS but I'm on Win10. Either way, everyone seems to have a similar assumption that the resize event is allowing for some sort of redraw at the old size before allowing the application code to respond. Thanks for the lead. – plast1k Mar 18 '21 at 19:31
1

Changing the surface's presentation mode from Fifo to Immediate prevents distortion while resizing (on Windows 10).

// surface: wgpu::Surface, device: wgpu::Device

let config = wgpu::SurfaceConfiguration {
    ...
    present_mode: wgpu::PresentMode::Immediate,
    ...
};

surface.configure(&device, &config);
zeyonaut
  • 11
  • 1
  • 3