bevyengine / bevy

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

shader_material_glsl example crashes if you add a light with shadows_enabled #8138

Open woodroww opened 1 year ago

woodroww commented 1 year ago

Bevy version

0.10.0

[Optional] Relevant system information

cargo 1.68.0 (115f34552 2023-02-26)

the operating system

This crashed on two systems, they are both Intel mac machines, one macos, one linux.

MacOS 13.2.1

2023-03-20T14:24:58.227437Z  INFO bevy_render::renderer: AdapterInfo { name: "AMD Radeon Pro 560", vendor: 0, device: 0, device_type: DiscreteGpu, driver: "", driver_info: "", backend: Metal }
2023-03-20T14:24:58.806900Z  INFO bevy_diagnostic::system_information_diagnostics_plugin::internal: SystemInfo { os: "MacOS 13.2.1", kernel: "22.3.0", cpu: "Intel(R) Core(TM) i5-7500 CPU @ 3.40GHz", core_count: "4", memory: "8.0 GiB" }

Linux 20.04 Ubuntu

2023-03-20T14:31:46.734571Z  INFO bevy_render::renderer: AdapterInfo { name: "Intel(R) Iris(R) Graphics 5100 (HSW GT3)", vendor: 32 902, device: 2606, device_type: IntegratedGpu, driver: "Intel open-source Mesa driver", driver_info: "Mesa 21.2.6", backend: Vulkan }
2023-03-20T14:31:47.526969Z  INFO bevy_diagnostic::system_information_diagnostics_plugin::internal: SystemInfo { os: "Linux 20.04 Ubuntu", kernel: "5.15.0-67-generic", cpu: "Intel(R) Core(TM) i5-4278U CPU @ 2.60GHz", core_count: "2", memory: "7.6 GiB" }

I tried testing the examples of upstream dependency

What you did

I copied the example exactly from: bevy/examples/shader/shader_material_glsl.rs and added a PointLightBundle with shadows_enabled and crash.

It also does not work with DirectionalLightBundle or SpotLightBundle with the shadows_enabled on the inner light.

This is my repository

Crashes:

    commands.spawn(PointLightBundle {
        point_light: PointLight {
            shadows_enabled: true,
            ..default()
        },
        ..default()
    });

Runs:

    commands.spawn(PointLightBundle {
        point_light: PointLight {
            shadows_enabled: false,
            ..default()
        },
        ..default()
    });

What went wrong

App crashes. The fragment shader is None in the specialize function (main.rs line 113).

    descriptor.fragment.as_mut().unwrap().entry_point = "main".into();

Additional information

I searched around issues and doc.rs for a while, but found nothing.

Logs

on MacOS

2023-03-20T14:24:58.227437Z  INFO bevy_render::renderer: AdapterInfo { name: "AMD Radeon Pro 560", vendor: 0, device: 0, device_type: DiscreteGpu, driver: "", driver_info: "", backend: Metal }
2023-03-20T14:24:58.697170Z  INFO bevy_winit::system: Creating new window "Bevy App" (0v0)
2023-03-20T14:24:58.806900Z  INFO bevy_diagnostic::system_information_diagnostics_plugin::internal: SystemInfo { os: "MacOS 13.2.1 ", kernel: "22.3.0", cpu: "Intel(R) Core(TM) i5-7500 CPU @ 3.40GHz", core_count: "4", memory: "8.0 GiB" }
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', src/main.rs:113:38
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
thread 'thread 'Compute Task Pool (0)main' panicked at '' panicked at 'internal error: entered unreachable code: sending into a closed channelA system has panicked so the executor cannot continue.: RecvError', ', /Users/matt /.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_ecs-0.10.0/src/schedule/executor/multi_threaded.rs/Users/matt/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_ecs-0.10.0/src/schedule/executor/multi_threaded.rs::459 194::4560
thread '<unnamed>' panicked at 'called `Option::unwrap()` on a `None` value', /Users/matt/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_tasks-0.10.0/src/task_pool.rs:376:49
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: RecvError', /Users/matt/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_render-0.10.0/src/pipelined_rendering.rs:136:45
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', /Users/matt/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_tasks-0.10.0/src/task_pool.rs:376:49

on Linux

2023-03-20T14:31:46.647954Z  INFO bevy_winit::system: Creating new window "Bevy App" (0v0)
2023-03-20T14:31:46.648298Z  INFO winit::platform_impl::platform::x11::window: Guessed window scale factor: 1    
MESA-INTEL: warning: Haswell Vulkan support is incomplete
2023-03-20T14:31:46.734571Z  INFO bevy_render::renderer: AdapterInfo { name: "Intel(R) Iris(R) Graphics 5100 (HSW GT3)", vendor: 32 902, device: 2606, device_type: IntegratedGpu, driver: "Intel open-source Mesa driver", driver_info: "Mesa 21.2.6", backend: Vulkan }
2023-03-20T14:31:47.526969Z  INFO bevy_diagnostic::system_information_diagnostics_plugin::internal: SystemInfo { os: "Linux 20.04 U buntu", kernel: "5.15.0-67-generic", cpu: "Intel(R) Core(TM) i5-4278U CPU @ 2.60GHz", core_count: "2", memory: "7.6 GiB" }
thread 'Compute Task Pool (0)' panicked at 'called `Option::unwrap()` on a `None` value', src/main.rs:113:38
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
thread 'Compute Task Pool (0)' panicked at 'internal error: entered unreachable code: sending into a closed channel', /home/matt/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_ecs-0.10.0/src/schedule/executor/multi_threaded.rs:459:45
thread 'Compute Task Pool (0)' panicked at 'A system has panicked so the executor cannot continue.: RecvError', /home/matt/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_ecs-0.10.0/src/schedule/executor/multi_threaded.rs:194:60thread '
main' panicked at 'internal error: entered unreachable code: sending into a closed channel', /home/matt/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_ecs-0.10.0/src/schedule/executor/multi_threaded.rs:thread '459Compute Task Pool (1):' panicked at '45internal error: entered unreachable code: sending into a closed channel', /home/matt/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_ecs-0.10.0/src/schedule/executor/multi_threaded.rs:459:45
thread '<unnamed>' panicked at 'called `Option::unwrap()` on a `None` value', /home/matt/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_tasks-0.10.0/src/task_pool.rs:376:49
thread 'main' panicked at 'internal error: entered unreachable code: sending into a closed channel', /home/matt/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_ecs-0.10.0/src/schedule/executor/multi_threaded.rs:459:45
thread 'Compute Task Pool (0)' panicked at 'internal error: entered unreachable code: sending into a closed channel', /home/matt/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_ecs-0.10.0/src/schedule/executor/multi_threaded.rs:459:45
thread 'Compute Task Pool (0)' panicked at 'called `Result::unwrap()` on an `Err` value: RecvError', /home/matt/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_render-0.10.0/src/pipelined_rendering.rs:136:45
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', /home/matt/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_tasks-0.10.0/src/task_pool.rs:376:49
TheoDulka commented 1 year ago

Still occurs on main 97eda02f421ae7f61c1f308a112c09822c3fd2b6 (0.12.0-dev)

The cause for the issue is https://github.com/bevyengine/bevy/blob/97eda02f421ae7f61c1f308a112c09822c3fd2b6/crates/bevy_pbr/src/prepass/mod.rs#L532-L535 in the prepass descriptor.fragment can be None, leading to that panic in CustomMaterial::specialize when the shadows are enabled.


There are 2 pairs of vertex and fragment shaders in Material, the non-prepass and prepass. specialize takes in a RenderPipelineDescriptor which just takes 1 pair. If it's being called in prepass/mod.rs for specifying the prepass shaders, then the functionality overlaps with specifying the non-prepass shaders. Like the comment says at L534, it's a potential issue. In the case that the prepass doesn't use a fragment shader, then specialize breaks.

In most cases the specializing should affect both pairs equally, but perhaps it'd be ideal if there was a way of distinguishing when the call is for the prepass shaders.

Like using

// Might not work for all prepass configurations.
const PREPASS: MeshPipelineKey = MeshPipelineKey::DEPTH_PREPASS
    .union(MeshPipelineKey::NORMAL_PREPASS)
    .union(MeshPipelineKey::MOTION_VECTOR_PREPASS);
let is_prepass = !(key.mesh_key & PREPASS).is_empty();

if !is_prepass {
    descriptor.vertex.entry_point = "main".into();
    descriptor.fragment.as_mut().unwrap().entry_point = "main".into();
}

as this stops the example from panicking for me. Maybe even add PREPASS to MeshPipelineKey