bevy
bevy copied to clipboard
webgl2: Mesh without triangles panics
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.
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.
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.
Is this a regression? Should it block 0.15?
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.