Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2d custom vertex attribute not working #14077

Open
jonathandw743 opened this issue Jun 30, 2024 · 2 comments
Open

2d custom vertex attribute not working #14077

jonathandw743 opened this issue Jun 30, 2024 · 2 comments
Labels
A-Rendering Drawing game state to the screen C-Bug An unexpected or incorrect behavior P-Crash A sudden unexpected crash

Comments

@jonathandw743
Copy link

Bevy version

0.14.0-rc.4

The following is a simple program which uses a custom vertex attribute to colour a shape.

use bevy::{
    math::{vec3, vec4, VectorSpace},
    prelude::*,
    render::{
        mesh::{MeshVertexAttribute, PrimitiveTopology},
        render_asset::RenderAssetUsages,
        render_resource::{AsBindGroup, VertexFormat},
    },
    sprite::{Material2d, Material2dPlugin, MaterialMesh2dBundle, Mesh2dHandle},
};

fn main() {
    App::new()
        .add_plugins((DefaultPlugins, MaterialPlugin::<CustomMaterial>::default()))
        .add_systems(Startup, spawn)
        .run();
}

#[derive(Asset, TypePath, AsBindGroup, Debug, Clone)]
struct CustomMaterial {
    #[uniform(0)]
    uniform_value: Vec4,
}

impl Material for CustomMaterial {
    fn fragment_shader() -> bevy::render::render_resource::ShaderRef {
        "custom_vertex_attr.wgsl".into()
    }
    fn vertex_shader() -> bevy::render::render_resource::ShaderRef {
        "custom_vertex_attr.wgsl".into()
    }
    fn specialize(
        _pipeline: &bevy::pbr::MaterialPipeline<Self>,
        descriptor: &mut bevy::render::render_resource::RenderPipelineDescriptor,
        layout: &bevy::render::mesh::MeshVertexBufferLayoutRef,
        _key: bevy::pbr::MaterialPipelineKey<Self>,
    ) -> Result<(), bevy::render::render_resource::SpecializedMeshPipelineError> {
        let vertex_layout = layout.0.get_layout(&[
            Mesh::ATTRIBUTE_POSITION.at_shader_location(0),
            CUSTOM_ATTR.at_shader_location(1),
        ])?;
        descriptor.vertex.buffers = vec![vertex_layout];
        Ok(())
    }
}

const CUSTOM_ATTR: MeshVertexAttribute =
    MeshVertexAttribute::new("CustomAttr", 83457934, VertexFormat::Float32x4);

fn spawn(
    mut commands: Commands,
    mut meshes: ResMut<Assets<Mesh>>,
    mut materials: ResMut<Assets<CustomMaterial>>,
) {
    let mut mesh = Mesh::from(Cuboid::default());
    mesh.insert_attribute(CUSTOM_ATTR, vec![vec4(0.0, 0.0, 0.5, 1.0); 24]);

    commands.spawn(MaterialMeshBundle {
        mesh: meshes.add(mesh),
        material: materials.add(CustomMaterial {
            uniform_value: vec4(0.0, 0.5, 0.0, 1.0),
        }),
        ..default()
    });
    commands.spawn(Camera3dBundle {
        transform: Transform::from_xyz(0.0, 0.0, -5.0).looking_at(Vec3::ZERO, Vec3::Y),
        ..default()
    });
}

However this equivalent in 2D does not work.

use bevy::{
    math::{vec3, vec4},
    prelude::*,
    render::{
        mesh::{MeshVertexAttribute, PrimitiveTopology},
        render_asset::RenderAssetUsages,
        render_resource::{AsBindGroup, VertexFormat},
    },
    sprite::{Material2d, Material2dPlugin, MaterialMesh2dBundle, Mesh2dHandle},
};

fn main() {
    App::new()
        .add_plugins((
            DefaultPlugins,
            Material2dPlugin::<CustomMaterial>::default(),
        ))
        .add_systems(Startup, spawn)
        .run();
}

#[derive(Asset, TypePath, AsBindGroup, Debug, Clone)]
struct CustomMaterial {
    #[uniform(0)]
    uniform_value: Vec4,
}

impl Material2d for CustomMaterial {
    fn fragment_shader() -> bevy::render::render_resource::ShaderRef {
        "custom_vertex_attr.wgsl".into()
    }
    fn vertex_shader() -> bevy::render::render_resource::ShaderRef {
        "custom_vertex_attr.wgsl".into()
    }
    fn specialize(
        descriptor: &mut bevy::render::render_resource::RenderPipelineDescriptor,
        layout: &bevy::render::mesh::MeshVertexBufferLayoutRef,
        _key: bevy::sprite::Material2dKey<Self>,
    ) -> Result<(), bevy::render::render_resource::SpecializedMeshPipelineError> {
        let vertex_layout = layout.0.get_layout(&[
            Mesh::ATTRIBUTE_POSITION.at_shader_location(0),
            CUSTOM_ATTR.at_shader_location(1),
        ])?;
        descriptor.vertex.buffers = vec![vertex_layout];
        Ok(())
    }
}

const CUSTOM_ATTR: MeshVertexAttribute =
    MeshVertexAttribute::new("CustomAttr", 83457934, VertexFormat::Float32x4);

fn spawn(
    mut commands: Commands,
    mut meshes: ResMut<Assets<Mesh>>,
    mut materials: ResMut<Assets<CustomMaterial>>,
) {
    let mut mesh = Mesh::new(PrimitiveTopology::TriangleList, RenderAssetUsages::all());
    mesh.insert_attribute(
        Mesh::ATTRIBUTE_POSITION,
        vec![
            vec3(0.0, 0.0, 0.0),
            vec3(100.0, 0.0, 0.0),
            vec3(0.0, 100.0, 0.0),
        ],
    );
    mesh.insert_attribute(CUSTOM_ATTR, vec![vec4(0.5, 0.0, 0.0, 1.0); 3]);

    commands.spawn(MaterialMesh2dBundle {
        mesh: Mesh2dHandle::from(meshes.add(mesh)),
        material: materials.add(CustomMaterial {
            uniform_value: vec4(0.0, 0.5, 0.0, 1.0),
        }),
        ..default()
    });
    commands.spawn(Camera2dBundle { ..default() });
}

This error is shown, followed by a series of panics and the program crashing:

2024-06-30T15:15:49.531042Z ERROR wgpu_core::device::global: Device::create_render_pipeline error: Error matching ShaderStages(VERTEX) shader requirements against the pipeline    
2024-06-30T15:15:49.531192Z ERROR wgpu::backend::wgpu_core: Handling wgpu errors as fatal by default    
thread 'Async Compute Task Pool (0)' panicked at /home/.../.cargo/registry/src/index.crates.io-6f17d22bba15001f/wgpu-0.20.1/src/backend/wgpu_core.rs:2996:5:
wgpu error: Validation Error

Caused by:
    In Device::create_render_pipeline
      note: label = `transparent_mesh2d_pipeline`
    Error matching ShaderStages(VERTEX) shader requirements against the pipeline
    Shader global ResourceBinding { group: 1, binding: 0 } is not available in the pipeline layout
    Buffer structure size 144, added to one element of an unbound array, if it's the last field, ended up greater than the given `min_binding_size`

The following shader is used in both examples:

#import bevy_pbr::mesh_functions::{get_world_from_local, mesh_position_local_to_clip}

struct CustomMaterial {
    uniform_value: vec4<f32>,
}
@group(2) @binding(0)
var<uniform> material: CustomMaterial;

struct Vertex {
    @builtin(instance_index) instance_index: u32,
    @location(0) position: vec3<f32>,
    @location(1) custom_attr: vec4<f32>,
};

struct VertexOutput {
    @builtin(position) clip_position: vec4<f32>,
    @location(0) custom_attr: vec4<f32>,
};

@vertex
fn vertex(vertex: Vertex) -> VertexOutput {
    var out: VertexOutput;
    out.clip_position = mesh_position_local_to_clip(
        get_world_from_local(vertex.instance_index),
        vec4<f32>(vertex.position, 1.0),
    );
    out.custom_attr = vertex.custom_attr;
    return out;
}

struct FragmentInput {
    @location(0) custom_attr: vec4<f32>,
};

@fragment
fn fragment(in: FragmentInput) -> @location(0) vec4<f32> {
    return in.custom_attr;
}
@jonathandw743 jonathandw743 added C-Bug An unexpected or incorrect behavior S-Needs-Triage This issue needs to be labelled labels Jun 30, 2024
@janhohenheim
Copy link
Member

Do you know if this worked in 0.13?

@janhohenheim janhohenheim added A-Rendering Drawing game state to the screen P-Crash A sudden unexpected crash and removed S-Needs-Triage This issue needs to be labelled labels Jul 1, 2024
@jonathandw743
Copy link
Author

Do you know if this worked in 0.13?

it did not.
In 0.13.2, the same code with very minor changes gives the same output:

2024-07-01T21:18:02.604417Z ERROR log: Device::create_render_pipeline error: Error matching ShaderStages(VERTEX) shader requirements against the pipeline    
2024-07-01T21:18:02.604511Z ERROR log: Handling wgpu errors as fatal by default    
thread 'Async Compute Task Pool (0)' panicked at /home/.../.cargo/registry/src/index.crates.io-6f17d22bba15001f/wgpu-0.19.4/src/backend/wgpu_core.rs:3006:5:
wgpu error: Validation Error

Caused by:
    In Device::create_render_pipeline
      note: label = `transparent_mesh2d_pipeline`
    Error matching ShaderStages(VERTEX) shader requirements against the pipeline
    Shader global ResourceBinding { group: 1, binding: 0 } is not available in the pipeline layout
    Buffer structure size 160, added to one element of an unbound array, if it's the last field, ended up greater than the given `min_binding_size`


note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Encountered a panic in system `bevy_render::render_resource::pipeline_cache::PipelineCache::process_pipeline_queue_system`!
thread 'Compute Task Pool (0)' panicked at /home/.../.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_render-0.13.2/src/pipelined_rendering.rs:49:67:
called `Result::unwrap()` on an `Err` value: RecvError

This is the same as the 0.14 error, just with a bit less spam.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Rendering Drawing game state to the screen C-Bug An unexpected or incorrect behavior P-Crash A sudden unexpected crash
Projects
None yet
Development

No branches or pull requests

2 participants