bevyengine / bevy

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

Wgpu validation error with light and custom material #9980

Open louis-le-cam opened 1 year ago

louis-le-cam commented 1 year ago

Bevy version

0.11.3

Relevant system information

AdapterInfo { name: "NVIDIA GeForce GTX 1050 Ti", vendor: 4318, device: 7298, device_type: DiscreteGpu, driver: "NVIDIA", driver_info: "537.34", backend: Vulkan }

What you did

Create a project with a custom material (vertex and fragment shaders) and a light

What went wrong

The application crashed with a wgpu validation error

Additional information

The shader_material_screenspace_texture works fine and have point Light and custom material (only fragment shader)

Other dependencies:

Shader:

#import bevy_pbr::mesh_bindings              mesh
#import bevy_pbr::mesh_functions             mesh_position_local_to_clip
#import bevy_pbr::mesh_view_bindings         globals
#import bevy_shader_utils::simplex_noise_2d  simplex_noise_2d

struct VertexIn {
    @location(0) position: vec3<f32>,
}

struct VertexOut {
    @builtin(position) position: vec4<f32>,
    @location(0) height: f32,
}

@vertex
fn vertex(in: VertexIn) -> VertexOut {
    var out: VertexOut;

    out.height = height(in.position.xz);

    out.position = mesh_position_local_to_clip(
        mesh.model,
        vec4<f32>(
            in.position.x,
            in.position.y + out.height,
            in.position.z,
            1.0
        )
    );

    return out;
}

struct FragmentIn {
    @location(0) height: f32,
}

@fragment
fn fragment(in: FragmentIn) -> @location(0) vec4<f32> {
    return mix(
        vec4<f32>(129.0 / 255.0, 192.0 / 255.0, 240.0 / 255.0, 1.0),
        vec4<f32>(26.0 / 255.0, 146.0 / 255.0, 237.0 / 255.0, 1.0),
        in.height
    );
}

fn height(position: vec2<f32>) -> f32 {
    return simplex_noise_2d(
        position + vec2<f32>(globals.time, globals.time) * 0.3
    );
}

Material:

#[derive(AsBindGroup, TypePath, TypeUuid, Clone)]
#[uuid = "dd271efa-de36-45ae-a742-915b00b01e55"]
struct WaterMaterial {}
impl Material for WaterMaterial {
    fn vertex_shader() -> ShaderRef {
        "shaders/water.wgsl".into()
    }

    fn fragment_shader() -> ShaderRef {
        "shaders/water.wgsl".into()
    }

    fn alpha_mode(&self) -> AlphaMode {
        AlphaMode::Blend
    }

    fn specialize(
        _pipeline: &MaterialPipeline<Self>,
        descriptor: &mut RenderPipelineDescriptor,
        layout: &MeshVertexBufferLayout,
        _key: MaterialPipelineKey<Self>,
    ) -> Result<(), SpecializedMeshPipelineError> {
        let vertex_layout = layout.get_layout(&[Mesh::ATTRIBUTE_POSITION.at_shader_location(0)])?;
        descriptor.vertex.buffers = vec![vertex_layout];
        Ok(())
    }
}

MeshMaterial:

 commands.spawn(MaterialMeshBundle {
        mesh: meshes.add(
            shape::Plane {
                size: 100.0,
                subdivisions: 10,
            }
            .into(),
        ),
        material: materials.add(WaterMaterial {}),
        transform: Transform::from_xyz(0.0, 0.0, 0.0),
        ..Default::default()
    });

PointLight:

    commands.spawn(PointLightBundle {
        point_light: PointLight {
            color: Color::WHITE,
            intensity: 1000.0,
            range: 30.0,
            radius: 0.5,
            shadows_enabled: true,
            ..Default::default()
        },
        transform: Transform::from_xyz(0.0, 10.0, 0.0),
        ..Default::default()
    });

Logs:

2023-09-30T16:59:37.230068Z  INFO bevy_winit::system: Creating new window "App" (0v0)
2023-09-30T16:59:37.648091Z  INFO bevy_render::renderer: AdapterInfo { name: "NVIDIA GeForce GTX 1050 Ti", vendor: 4318, device: 7298, device_type: DiscreteGpu, driver: "NVIDIA", driver_info: "537.34", backend: Vulkan }
2023-09-30T16:59:37.726248Z  INFO bevy_editor_pls_default_windows::cameras: Spawning editor cameras
2023-09-30T16:59:37.729229Z  INFO bevy_input::gamepad: Gamepad { id: 0 } Connected
2023-09-30T16:59:38.962692Z ERROR wgpu::backend::direct: Handling wgpu errors as fatal by default
The application panicked (crashed).
Message:  wgpu error: Validation Error

Caused by:
    In Device::create_render_pipeline
      note: label = `prepass_pipeline`
    Error matching ShaderStages(VERTEX) shader requirements against the pipeline
    Location[1] Float32x2 interpolated as Some(Perspective) with sampling Some(Center) is not provided by the previous stage outputs
    Input is not provided by the earlier stage in the pipeline

Location: D:\Dev\Tools\Rust\cargo\registry\src\index.crates.io-6f17d22bba15001f\wgpu-0.16.3\src\backend\direct.rs:3019

Backtrace omitted.

Run with RUST_BACKTRACE=1 environment variable to display it.
Run with RUST_BACKTRACE=full to include source snippets.
Encountered a panic in system `bevy_render::render_resource::pipeline_cache::PipelineCache::process_pipeline_queue_system`!
The application panicked (crashed).
Message:  called `Result::unwrap()` on an `Err` value: RecvError
Location: D:\Dev\Tools\Rust\cargo\registry\src\index.crates.io-6f17d22bba15001f\bevy_render-0.11.3\src\pipelined_rendering.rs:143

Backtrace omitted.

Run with RUST_BACKTRACE=1 environment variable to display it.
Run with RUST_BACKTRACE=full to include source snippets.
error: process didn't exit successfully: `target\debug\bevy_template.exe` (exit code: 101)`
superdump commented 1 year ago

I think this is a problem with the default prepass shaders not matching the vertex buffer layout that you set. @IceSentry perhaps you can debug this quicker than me :)

IceSentry commented 1 year ago

Yeah, changing the vertex layout in specialize is most likely the issue.

There's a few solution

The reason this happens even if you don't actually use the prepass is because the shadows reuse the depth prepass shaders.

louis-le-cam commented 1 year ago

I tried to set the prepass vertex shader with the vertex shader and it shows another error:

wgpu error: Validation Error

Caused by:
    In Device::create_render_pipeline
      note: label = `prepass_pipeline`
    Error matching ShaderStages(VERTEX) shader requirements against the pipeline
    Shader global ResourceBinding { group: 0, binding: 9 } is not available in the layout pipeline layout
    Binding is missing from the pipeline layout

(I don't know how to implement the first solution proposition)

Theses errors are not clear, I think they should be handled.

Why custom_vertex_attribute example work with light ?

By the way what is a prepass shader ?

IceSentry commented 1 year ago

Theses errors are not clear, I think they should be handled.

They come from wgpu so we don't have control over them

Why custom_vertex_attribute example work with light?

The issue seems to be with bind group not matching. That example doesn't do anything with bind groups so it doesn't cause any issues.

By the way what is a prepass shader?

A prepass is a render phase that runs before the main pass. It generates a depth texture that can be used in the main pass. We also use the prepass for the shadow system which is why you are getting this error despite not actually having a prepass enabled.

As to how to fix it. Do you have a full reproduction in a repo I could clone and run? I have a very vague idea of what might be the issue but I'm not sure so I'd need to run the code.

louis-le-cam commented 1 year ago

I uploaded my project at louis-le-cam/topdown_game

The material definition: src/water/mod.rs

The shader: assets/shaders/water.wgsl

Thank you for your help

Kuerbiskakteen commented 1 month ago

I have the same problem as @louis-le-cam after he fixed the first one. But I am using bevy 0.14.2. A simple project to reproduce the problem is here: https://github.com/Kuerbiskakteen/bevy-test-time/tree/main

IceSentry commented 4 weeks ago

@Kuerbiskakteen that's an unrelated error, the reason your shader doesn't work is that you are importing Globals from bevy_pbr but you are using a 2d material. bevy_pbr is for 3d, for 2d you should use bevy_sprite