bevyengine / bevy

A refreshingly simple data-driven game engine built in Rust
https://bevyengine.org
Apache License 2.0
36.12k stars 3.56k forks source link

Crash after app.update() if WgpuPlugin is enabled #3091

Closed Shatur closed 2 years ago

Shatur commented 2 years ago

Bevy version

0.5

Operating system & version

ArchLinux

What you did

The following code crashes the engine:

use bevy::prelude::*;

fn main() {
    let mut app_builder = App::build();
    app_builder.add_plugins(DefaultPlugins);
    app_builder.app.update();
}

But the following works.

use bevy::prelude::*;

fn main() {
    let mut app_builder = App::build();
    app_builder.add_plugins(DefaultPlugins);
    app_builder.run(); // Changed this line from update() to run()
}

What you expected to happen

Exit successfully after single event loop execution.

What actually happened

thread 'main' panicked at 'Window texture node refers to a non-existent window.', /home/gena/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_render-0.5.0/src/render_graph/nodes/window_texture_node.rs:54:14
stack backtrace:
   0: rust_begin_unwind
             at /build/rust/src/rustc-1.56.0-src/library/std/src/panicking.rs:517:5
   1: core::panicking::panic_fmt
             at /build/rust/src/rustc-1.56.0-src/library/core/src/panicking.rs:101:14
   2: core::option::expect_failed
             at /build/rust/src/rustc-1.56.0-src/library/core/src/option.rs:1615:5
   3: core::option::Option<T>::expect
             at /build/rust/src/rustc-1.56.0-src/library/core/src/option.rs:698:21
   4: <bevy_render::render_graph::nodes::window_texture_node::WindowTextureNode as bevy_render::render_graph::node::Node>::update
             at /home/gena/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_render-0.5.0/src/render_graph/nodes/window_texture_node.rs:52:22
   5: bevy_wgpu::renderer::wgpu_render_graph_executor::WgpuRenderGraphExecutor::execute
             at /home/gena/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_wgpu-0.5.0/src/renderer/wgpu_render_graph_executor.rs:75:25
   6: bevy_wgpu::wgpu_renderer::WgpuRenderer::run_graph::{{closure}}
             at /home/gena/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_wgpu-0.5.0/src/wgpu_renderer.rs:115:13
   7: bevy_ecs::world::World::resource_scope
             at /home/gena/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_ecs-0.5.0/src/world/mod.rs:695:22
   8: bevy_wgpu::wgpu_renderer::WgpuRenderer::run_graph
             at /home/gena/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_wgpu-0.5.0/src/wgpu_renderer.rs:104:9
   9: bevy_wgpu::wgpu_renderer::WgpuRenderer::update
             at /home/gena/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_wgpu-0.5.0/src/wgpu_renderer.rs:121:9
  10: bevy_wgpu::get_wgpu_render_system::{{closure}}
             at /home/gena/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_wgpu-0.5.0/src/lib.rs:112:9
  11: <alloc::boxed::Box<F,A> as core::ops::function::FnMut<Args>>::call_mut
             at /build/rust/src/rustc-1.56.0-src/library/alloc/src/boxed.rs:1643:9
  12: <bevy_ecs::system::exclusive_system::ExclusiveSystemFn as bevy_ecs::system::exclusive_system::ExclusiveSystem>::run
             at /home/gena/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_ecs-0.5.0/src/system/exclusive_system.rs:41:9
  13: <bevy_ecs::schedule::stage::SystemStage as bevy_ecs::schedule::stage::Stage>::run
             at /home/gena/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_ecs-0.5.0/src/schedule/stage.rs:812:25
  14: bevy_ecs::schedule::Schedule::run_once
             at /home/gena/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_ecs-0.5.0/src/schedule/mod.rs:201:13
  15: <bevy_ecs::schedule::Schedule as bevy_ecs::schedule::stage::Stage>::run
             at /home/gena/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_ecs-0.5.0/src/schedule/mod.rs:219:21
  16: bevy_app::app::App::update
             at /home/gena/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_app-0.5.0/src/app.rs:58:9
  17: test_bevy_crash::main
             at ./src/main.rs:6:5
  18: core::ops::function::FnOnce::call_once
             at /build/rust/src/rustc-1.56.0-src/library/core/src/ops/function.rs:227:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
Nov 09 17:17:00.778 ERROR gpu_alloc::block: Memory block wasn't deallocated
Nov 09 17:17:00.779 ERROR gpu_alloc::block: Memory block wasn't deallocated
fish: Job 1, 'RUST_BACKTRACE=1 cargo run' terminated by signal SIGSEGV (Address boundary error)

Additional information

It looks like the issue caused by WgpuPlugin. app.update() is convenient for use inside tests. And some systems need a render to work (like egui, to create UI tests).

Shatur commented 2 years ago

I dug deeper and it looks like the problem is caused by WgpuPlugin, which is needed by most other plugins. Without it, for example, I cannot do UI tests.

bjorn3 commented 2 years ago

What is the full output?

Shatur commented 2 years ago

What is the full output?

Sorry for a stupid question, but how can I provide it? I already used RUST_BACKTRACE=1, it shows only Memory block wasn't deallocated messages.

bjorn3 commented 2 years ago

I thought you only copied the last couple of lines. My bad. Can you try using a debugger to find where it crashes? You will probably need to directly run the executable instead of using cargo run or cargo test as I suspect you are doing right now. You can find it somewhere inside the target dir depending on how you wrote test or you can pass -v to cargo to let it tell you which programs it runs.

Shatur commented 2 years ago

Here is stacktrace:

running 1 test
thread 'test' panicked at 'Window swapchain node refers to a non-existent window.', /home/gena/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_render-0.5.0/src/render_graph/nodes/window_swapchain_node.rs:51:14
stack backtrace:
   0: rust_begin_unwind
             at /build/rust/src/rustc-1.56.0-src/library/std/src/panicking.rs:517:5
   1: core::panicking::panic_fmt
             at /build/rust/src/rustc-1.56.0-src/library/core/src/panicking.rs:101:14
   2: core::option::expect_failed
             at /build/rust/src/rustc-1.56.0-src/library/core/src/option.rs:1615:5
   3: core::option::Option<T>::expect
             at /build/rust/src/rustc-1.56.0-src/library/core/src/option.rs:698:21
   4: <bevy_render::render_graph::nodes::window_swapchain_node::WindowSwapChainNode as bevy_render::render_graph::node::Node>::update
             at /home/gena/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_render-0.5.0/src/render_graph/nodes/window_swapchain_node.rs:49:22
   5: bevy_wgpu::renderer::wgpu_render_graph_executor::WgpuRenderGraphExecutor::execute
             at /home/gena/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_wgpu-0.5.0/src/renderer/wgpu_render_graph_executor.rs:75:25
   6: bevy_wgpu::wgpu_renderer::WgpuRenderer::run_graph::{{closure}}
             at /home/gena/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_wgpu-0.5.0/src/wgpu_renderer.rs:115:13
   7: bevy_ecs::world::World::resource_scope
             at /home/gena/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_ecs-0.5.0/src/world/mod.rs:695:22
   8: bevy_wgpu::wgpu_renderer::WgpuRenderer::run_graph
             at /home/gena/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_wgpu-0.5.0/src/wgpu_renderer.rs:104:9
   9: bevy_wgpu::wgpu_renderer::WgpuRenderer::update
             at /home/gena/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_wgpu-0.5.0/src/wgpu_renderer.rs:121:9
  10: bevy_wgpu::get_wgpu_render_system::{{closure}}
             at /home/gena/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_wgpu-0.5.0/src/lib.rs:112:9
  11: <alloc::boxed::Box<F,A> as core::ops::function::FnMut<Args>>::call_mut
             at /build/rust/src/rustc-1.56.0-src/library/alloc/src/boxed.rs:1643:9
  12: <bevy_ecs::system::exclusive_system::ExclusiveSystemFn as bevy_ecs::system::exclusive_system::ExclusiveSystem>::run
             at /home/gena/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_ecs-0.5.0/src/system/exclusive_system.rs:41:9
  13: <bevy_ecs::schedule::stage::SystemStage as bevy_ecs::schedule::stage::Stage>::run
             at /home/gena/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_ecs-0.5.0/src/schedule/stage.rs:812:25
  14: bevy_ecs::schedule::Schedule::run_once
             at /home/gena/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_ecs-0.5.0/src/schedule/mod.rs:201:13
  15: <bevy_ecs::schedule::Schedule as bevy_ecs::schedule::stage::Stage>::run
             at /home/gena/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_ecs-0.5.0/src/schedule/mod.rs:219:21
  16: bevy_app::app::App::update
             at /home/gena/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_app-0.5.0/src/app.rs:58:9
  17: test::test
             at ./tests/test.rs:35:5
  18: test::test::{{closure}}
             at ./tests/test.rs:4:1
  19: core::ops::function::FnOnce::call_once
             at /build/rust/src/rustc-1.56.0-src/library/core/src/ops/function.rs:227:5
  20: core::ops::function::FnOnce::call_once
             at /build/rust/src/rustc-1.56.0-src/library/core/src/ops/function.rs:227:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
Nov 09 13:23:50.653 ERROR gpu_alloc::block: Memory block wasn't deallocated
Nov 09 13:23:50.653 ERROR gpu_alloc::block: Memory block wasn't deallocated
fish: Job 1, 'RUST_BACKTRACE=1 /mnt/Files/Git…' terminated by signal SIGSEGV (Address boundary error)

I guess the problem is initializing the render in headless mode, because I am running the project as a test.

bjorn3 commented 2 years ago

If you want to run it headless, you can try using xvfb-run from the xvfb package. This is what bevy's CI uses: https://github.com/bevyengine/bevy/blob/f4cfcc0e44b91446beb49a1dbe9965cb7bcde059/.github/workflows/ci.yml#L251 You may also need to use swiftshader for software rendering if no gpu is available.

Shatur commented 2 years ago

If you want to run it headless, you can try using xvfb-run from the xvfb package. This is what bevy's CI uses:

Trying it this way. I downloaded swiftshader.zip, unpacked it, replaced PATH_TO_CHANGE with full path to .so and used the following command:

VK_ICD_FILENAMES=/mnt/Files/Git/test_bevy_crash/vk_swiftshader_icd.json DRI_PRIME=0 xvfb-run cargo test

But I have the same error.

Then I decided to try to run the same code normally, not as a part of a test:

use bevy::prelude::*;

fn main() {
    let mut app_builder = App::build();
    app_builder.add_plugins(DefaultPlugins);
    app_builder.app.update();
}

And it also crashes. However, the following works, I see the window:

use bevy::prelude::*;

fn main() {
    let mut app_builder = App::build();
    app_builder.add_plugins(DefaultPlugins);
    app_builder.run(); // Changed this line from update() to run()
}

So the issue in the code! What am I doing wrong? I know that for game I need to use run(), but for tests I need to run event loop once. update() works for me when I don not have WgpuPlugin initialized.

bjorn3 commented 2 years ago

Right, bevy_winit requires it's own runner to be used as it is responsible for creating the actual winit winfow. Bevy's CI uses the winit runner and then stops the test after a fixed amount of time. See https://github.com/bevyengine/bevy/pull/1826 for how it was implemented.

Shatur commented 2 years ago

Got it. Should I keep the issue open? It would be nice to have a better solution.

bjorn3 commented 2 years ago

I think it is fine to keep it open. Maybe edit the issue title though.

Shatur commented 2 years ago

Thanks, updated the issue.

Shatur commented 2 years ago

No longer an issue with the latest master. I tested and it works.