bevyengine / bevy

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

depth prepass not supported even when msaa is disabled #13680

Closed bananaturtlesandwich closed 5 months ago

bananaturtlesandwich commented 5 months ago

Bevy version

0.13.2

AdapterInfo { name: "Radeon RX550/550 Series", vendor: 4098, device: 27039, device_type: DiscreteGpu, driver: "AMD proprietary driver", driver_info: "24.3.1 (AMD proprietary shader compiler)", backend: Vulkan }

What you did

i essentially just tried to run a simplified version of the shader prepass example (just the plane and quad with no settings) to try and figure out a bug i was having using depth prepass (the one i'm reporting now) main.rs

use bevy::{
    core_pipeline::prepass::DepthPrepass,
    pbr::{NotShadowCaster, PbrPlugin},
    prelude::*,
    reflect::TypePath,
    render::render_resource::{AsBindGroup, ShaderRef},
};

fn main() {
    App::new()
        .add_plugins((
            DefaultPlugins.set(PbrPlugin {
                // The prepass is enabled by default on the StandardMaterial,
                // but you can disable it if you need to.
                //
                // prepass_enabled: false,
                ..default()
            }),
            MaterialPlugin::<PrepassOutputMaterial> {
                // This material only needs to read the prepass textures,
                // but the meshes using it should not contribute to the prepass render, so we can disable it.
                prepass_enabled: false,
                ..default()
            },
        ))
        .add_systems(Startup, setup)
        // Disabling MSAA for maximum compatibility. Shader prepass with MSAA needs GPU capability MULTISAMPLED_SHADING
        .insert_resource(Msaa::Off)
        .run();
}

/// set up a simple 3D scene
fn setup(
    mut commands: Commands,
    mut meshes: ResMut<Assets<Mesh>>,
    mut std_materials: ResMut<Assets<StandardMaterial>>,
    mut depth_materials: ResMut<Assets<PrepassOutputMaterial>>,
) {
    commands.spawn((
        Camera3dBundle {
            transform: Transform::from_xyz(-2.0, 3., 5.0).looking_at(Vec3::ZERO, Vec3::Y),
            ..default()
        },
        DepthPrepass,
    ));
    commands.spawn(PbrBundle {
        mesh: meshes.add(Plane3d::default().mesh().size(5.0, 5.0)),
        material: std_materials.add(Color::rgb(0.3, 0.5, 0.3)),
        ..default()
    });
    // quad to filter stuff through
    commands.spawn((
        MaterialMeshBundle {
            mesh: meshes.add(Rectangle::new(20.0, 20.0)),
            material: depth_materials.add(PrepassOutputMaterial {}),
            transform: Transform::from_xyz(-0.75, 1.25, 3.0)
                .looking_at(Vec3::new(2.0, -2.5, -5.0), Vec3::Y),
            ..default()
        },
        NotShadowCaster,
    ));
}

// This shader simply loads the prepass texture and outputs it directly
#[derive(Asset, TypePath, AsBindGroup, Debug, Clone)]
struct PrepassOutputMaterial {}

impl Material for PrepassOutputMaterial {
    fn fragment_shader() -> ShaderRef {
        "shaders/show_prepass.wgsl".into()
    }

    // This needs to be transparent in order to show the scene behind the mesh
    fn alpha_mode(&self) -> AlphaMode {
        AlphaMode::Blend
    }
}

show_prepass.wgsl

#import bevy_pbr::mesh_types
#import bevy_pbr::mesh_view_bindings
#import bevy_pbr::prepass_utils

@fragment
fn fragment(
    @builtin(position) frag_coord: vec4<f32>,
    @builtin(sample_index) sample_index: u32,
    #import bevy_pbr::mesh_vertex_output
) -> @location(0) vec4<f32> {
    let depth = prepass_depth(frag_coord, sample_index);
    return vec4(depth, depth, depth, 1.0);
}

What went wrong

when compiling the shader this error is printed to the console

2024-06-02T17:26:27.944953Z ERROR bevy_render::render_resource::pipeline_cache: failed to process shader:
error: no definition in scope for identifier: 'prepass_depth'
   ┌─ shaders/shader_prepass.wgsl:11:17
   │
11 │     let depth = prepass_depth(frag_coord, sample_index);
   │                 ^^^^^^^^^^^^^ unknown identifier
   │
   = no definition in scope for identifier: 'prepass_depth'

and so no depth colouring was applied

Additional information

This is on Windows 10 trying to get depth prepass working to make a material which displays differently through walls and dithers when close to the camera i posted a discussion here at #13657 about this to see if i was being dumb but @IceSentry wasn't sure what could be wrong

the first time i compiled i wasn't using all default features like the example but the same results occur for me compiling with default features too the error isn't from any change in the example code on master which i copied it from since the only commits to it have been to change text size in the ui

bugsweeper commented 5 months ago

@bananaturtlesandwich If you look in ssr.wgsl, there is prepass_utils imported from bevy_pbr like in your example, and in other place prepass_utils::prepass_depth is used instead of just prepass_depth in your example. Can you try import bevy_pbr::prepass_utils::prepass_depth or use prepass_utils::prepass_depth?

bananaturtlesandwich commented 5 months ago

oh yeah that's on me although it's now showing a different error

2024-06-05T09:43:06.371985Z ERROR bevy_render::render_resource::pipeline_cache: failed to process shader:
error: failed to build a valid final module: Entry point fragment at Fragment is invalid
 = Argument 1 varying error
 = Capability Capabilities(MULTISAMPLED_SHADING) is not supported
bananaturtlesandwich commented 5 months ago

should this be happening even if Msaa is disabled like it is?

bananaturtlesandwich commented 5 months ago

nevermind i'm an idiot sample index is 0 if not supported

bananaturtlesandwich commented 5 months ago

didn't click that sample index meant multisampling

IceSentry commented 5 months ago

@bugsweeper nice catch on that one, I completely missed the import being incorrect 😅.

@bananaturtlesandwich I think the multisampled_shading feature will be enabled by default in 0.14, but yeah, just use 0 instead of sample_index for now.