bevy icon indicating copy to clipboard operation
bevy copied to clipboard

webgl2: Mesh without triangles panics

Open rparrett opened this issue 1 year ago • 4 comments

Bevy version

0.15.0-rc.3

Relevant system information

AdapterInfo { name: "ANGLE (Apple, ANGLE Metal Renderer: Apple M1 Max, Unspecified Version)", vendor: 4203, device: 0, device_type: IntegratedGpu, driver: "", driver_info: "WebGL 2.0 (OpenGL ES 3.0 Chromium)", backend: Gl }

What you did

I experienced this panic in the wild while migrating an app that uses a lot of Mesh2d by way of bevy_prototype_lyon. It seems that the root cause is creating a Line with zero length in that plugin.

Minimal repro for Bevy 0.15
use bevy::{asset::RenderAssetUsages, prelude::*, render::mesh::PrimitiveTopology};

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_systems(Startup, setup)
        .run();
}

fn setup(
    mut commands: Commands,
    mut meshes: ResMut<Assets<Mesh>>,
    mut materials: ResMut<Assets<ColorMaterial>>,
) {
    commands.spawn(Camera2d);

    let mesh = Mesh::new(
        PrimitiveTopology::TriangleList,
        RenderAssetUsages::default(),
    );

    commands.spawn((
        Mesh2d(meshes.add(mesh)),
        MeshMaterial2d(materials.add(Color::hsl(180.0, 0.95, 0.7))),
    ));
}
Bevy 0.14 code tested
use bevy::{
    prelude::*,
    render::{mesh::PrimitiveTopology, render_asset::RenderAssetUsages},
    sprite::{MaterialMesh2dBundle, Mesh2dHandle},
};

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_systems(Startup, setup)
        .run();
}

fn setup(
    mut commands: Commands,
    mut meshes: ResMut<Assets<Mesh>>,
    mut materials: ResMut<Assets<ColorMaterial>>,
) {
    commands.spawn(Camera2dBundle::default());

    let mesh = Mesh::new(
        PrimitiveTopology::TriangleList,
        RenderAssetUsages::default(),
    );

    let color = Color::hsl(180., 0.95, 0.7);

    commands.spawn(MaterialMesh2dBundle {
        mesh: Mesh2dHandle(meshes.add(mesh)),
        material: materials.add(color),
        ..default()
    });
}

The exact type of mesh generated by a zero-length line w/ bevy_prototype_lyon (same panic)
let mesh = Mesh::new(
    PrimitiveTopology::TriangleList,
    RenderAssetUsages::default(),
)
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, Vec::<[f32; 3]>::new())
.with_inserted_attribute(Mesh::ATTRIBUTE_COLOR, Vec::<[f32; 4]>::new())
.with_inserted_indices(Indices::U32(vec![]));
cargo run -p build-wasm-example -- --api webgl2 empty_mesh
basic-http-server examples/wasm/

What went wrong

wasm_example.js:1951 panicked at /Users/me/.cargo/registry/src/index.crates.io-6f17d22bba15001f/wgpu-23.0.1/src/api/buffer.rs:684:9:
slice offset 0 is out of range for buffer of size 0

Stack:

Error
    at imports.wbg.__wbg_new_abda76e883ba8a5f (http://127.0.0.1:4000/target/wasm_example.js:1935:21)
    at sprite-e09298d3df91ece6.wasm.__wbg_new_abda76e883ba8a5f externref shim (http://127.0.0.1:4000/target/wasm_example_bg.wasm:wasm-function[87386]:0x22b19ec)
    at sprite-e09298d3df91ece6.wasm.console_error_panic_hook::hook::ha8c6c1fd53fdbabe (http://127.0.0.1:4000/target/wasm_example_bg.wasm:wasm-function[16852]:0x1840f09)
    at sprite-e09298d3df91ece6.wasm.core::ops::function::Fn::call::h4a1d224ff1d85143 (http://127.0.0.1:4000/target/wasm_example_bg.wasm:wasm-function[135054]:0x23915f6)
    at sprite-e09298d3df91ece6.wasm.std::panicking::rust_panic_with_hook::he5c089ac7305193e (http://127.0.0.1:4000/target/wasm_example_bg.wasm:wasm-function[35603]:0x1ee83b4)
    at sprite-e09298d3df91ece6.wasm.std::panicking::begin_panic_handler::{{closure}}::h010c94f3a1c5c766 (http://127.0.0.1:4000/target/wasm_example_bg.wasm:wasm-function[41310]:0x2000557)
    at sprite-e09298d3df91ece6.wasm.std::sys::backtrace::__rust_end_short_backtrace::hbe714695da4edadc (http://127.0.0.1:4000/target/wasm_example_bg.wasm:wasm-function[131865]:0x238a269)
    at sprite-e09298d3df91ece6.wasm.rust_begin_unwind (http://127.0.0.1:4000/target/wasm_example_bg.wasm:wasm-function[52617]:0x21540ee)
    at sprite-e09298d3df91ece6.wasm.core::panicking::panic_fmt::hdc8d2d914c0710e4 (http://127.0.0.1:4000/target/wasm_example_bg.wasm:wasm-function[54160]:0x2173e57)
    at sprite-e09298d3df91ece6.wasm.wgpu::api::buffer::check_buffer_bounds::h3364e293f2fdb994 (http://127.0.0.1:4000/target/wasm_example_bg.wasm:wasm-function[30214]:0x1d84ec2)

Additional information

This is a silly thing to be trying to do, but it did not panic in Bevy 0.14.

Possibly related to https://github.com/gfx-rs/wgpu/issues/3170#issuecomment-2491549161

webgpu and native on m1 mac seem to work okay.

rparrett avatar Nov 27 '24 03:11 rparrett

I ran your code on my Windows computer and a panic also occurred. However, it was due to another reason, which is as follows.

thread 'Compute Task Pool (7)' panicked at C:\Users\decli\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bevy_render-0.15.0-rc.3\src\mesh\allocator.rs:656:48:
attempt to divide by zero
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Encountered a panic in system `bevy_render::mesh::allocator::allocate_and_free_meshes`!

Besides, this panic only occurs in version 0.15.0-rc.3.

yshngg avatar Nov 27 '24 14:11 yshngg

This new mesh allocator panic seems to be from me minimizing the repro excessively. The initial panic I experienced happens when there are some vertex attributes/indices, but they are empty vecs. This new panic happens when there are no vertex attributes or indices at all.

I did some additional testing of both scenarios on mac and windows, and edited the PR description with both code snippets I'm using to create the meshes.

platform mesh attributes result
win/nvidia/webgl2/chrome No Panic (bevy mesh allocator)
win/nvidia/webgl2/chrome Yes OK
win/nvidia/native No Panic (bevy mesh allocator)
win/nvidia/native Yes OK
m1/webgl2/chrome No Panic (wgpu buffer)
m1/webgl2/chrome Yes Panic (wgpu buffer)
m1/native No Panic (bevy mesh allocator)
m1/native Yes OK

Both of these scenarios did not panic in 0.14.2.

rparrett avatar Nov 27 '24 16:11 rparrett

Is this a regression? Should it block 0.15?

BenjaminBrienen avatar Nov 28 '24 16:11 BenjaminBrienen

This is a regression and I don't think we should panic in either case.

Some considerations:

  • I could see real situations where generating a mesh with attributes that are empty vecs would could be more convenient than removing a mesh.
  • The panics are likely to be pretty mysterious to users
  • But this is borderline user-error, and can be worked around by not spawning / generating these invalid meshes.

IMO, this shouldn't block 0.15.

rparrett avatar Nov 28 '24 16:11 rparrett