vulkano-rs / vulkano

Safe and rich Rust wrapper around the Vulkan API
Apache License 2.0
4.51k stars 435 forks source link

Programs hang on Swapchain recreation when window is resized #959

Open ishanjain28 opened 6 years ago

ishanjain28 commented 6 years ago

Hi, I am running into a problem with running vulkano programs on Windows.

My code and the code in examples compiles and starts just fine but when I do anything that'll need a recreation of swapchain, For example, Resizing a window. The window just hangs forever.

The code in examples does not works as it's supposed to on Windows and Linux.

Specifically, This code.

let mut previous_frame_end = Box::new(now(device.clone())) as Box<GpuFuture>;
loop {
    ...
let future = previous_frame_end.join(acquire_future)
        .then_execute(queue.clone(), command_buffer).unwrap()
        .then_swapchain_present(queue.clone(), swapchain.clone(), image_num)
        .then_signal_fence_and_flush().unwrap();
    previous_frame_end = Box::new(future) as Box<_>;
}

When the window is resized, The then_signal_fence_and_flush method returns a FlushError::OutOfDate error. Unwrapping the result directly crashes the program upon window resize. I tried to make it work with the following code.

loop {
let prev_frame_end = now(device.clone());
match prev_frame_end.join(acquire_future)
    .then_execute(queue.clone(), command_buffer).unwrap()
    .then_swapchain_present(queue.clone(), swapchain.clone(), image_num)
    .then_signal_fence_and_flush() {
        Ok(v) => (),
        Err(FlushError::OutOfDate) => {
            recreate_swapchain = true;
        }
        Err(e) => panic!("{:?}", e);
        };
}

Since, match takes ownership of prev_frame_end, I have to create it on each iteration. This code seems to be working perfectly fine on Linux with no issues whatsoever but on windows this code causes the window to hang forever. The program doesn't starts consuming more ram and there is no increase in CPU Usage(It stays about the same even when the window is hung). I just couldn't figure out any way to create prev_frame_end only one time and checking for error returned by then_signal_fence_and_flush without taking ownership of prev_frame_end, So I figured creating an issue on repo might be a good idea.

More information, I was using discrete GPUs(gtx 960M) to run the programs. Output of vulkaninfo on Windows: https://hastebin.com/dezofezuda.sql Window version: WIndows 10 Home 1703 Nvidia Driver version 397.31

My full modified program: https://hastebin.com/acurayevax.php

ishanjain28 commented 6 years ago

Okay, So, I just found the updated examples in examples folder, Let me try that code and hopefully that fixes the problem.

ishanjain28 commented 6 years ago

The new examples don't fix the problem. The window still hangs just like it did before.

paulhilbert commented 6 years ago

I can confirm this error on two different systems - both Arch Linux under i3. The repository triangle example (or in fact any example with a window) fails with repository HEAD as well as crates.io vulkano directly after window generation.

Since tiling WMs resize immediately after window creation I introduced an exception for the example window leading to the example crashing on manual window resize and/or move.

Here is the stack trace (by breaking on rust_begin_unwind in gdb):

0 rust_begin_unwind () at libstd/panicking.rs:326

1 0x0000555555a5932c in core::panicking::panic_fmt () at libcore/panicking.rs:77

2 0x000055555593d4d2 in core::result::unwrap_failed (msg="called Result::unwrap() on an Err value", error=vulkano::OutOfHostMemory) at libcore/macros.rs:26

3 0x000055555559e8d0 in <core::result::Result<T, E>>::unwrap (self=Err = {...}) at libcore/result.rs:808

4 0x00005555556793c8 in vulkano::sync::future::fence_signal::then_signal_fence (

future=PresentFuture<vulkano::command_buffer::traits::CommandBufferExecFuture<vulkano::sync::future::join::JoinFuture<alloc::boxed::Box, vulkano::swapchain::swapchain::SwapchainAcquireFuture>, vulkano::command_buffer::auto::AutoCommandBuffer>, winit::Window> = {...}, Python Exception <class 'gdb.error'> Cannot convert value to long.: behavior=...) at /home/user/source/rust/vulkano-examples/vulkano/vulkano/src/sync/future/fence_signal.rs:40

5 0x0000555555581de3 in vulkano::sync::future::GpuFuture::then_signal_fence (self=...) at /home/user/source/rust/vulkano-examples/vulkano/vulkano/src/sync/future/mod.rs:217

6 0x0000555555581e32 in vulkano::sync::future::GpuFuture::then_signal_fence_and_flush (self=...) at /home/user/source/rust/vulkano-examples/vulkano/vulkano/src/sync/future/mod.rs:227

7 0x0000555555670b1f in triangle::main () at src/bin/triangle.rs:270

The changes tested by ishanjain28 (new future per loop iteration) indeed run without any problems on both systems.