-
-
Couldn't load subscription status.
- Fork 4.2k
Open
Labels
A-RenderingDrawing game state to the screenDrawing game state to the screenC-BugAn unexpected or incorrect behaviorAn unexpected or incorrect behaviorO-DX12Specific to the DX12 render APISpecific to the DX12 render APIP-CrashA sudden unexpected crashA sudden unexpected crashS-Needs-InvestigationThis issue requires detective work to figure out what's going wrongThis issue requires detective work to figure out what's going wrong
Description
Bevy version and features
- Bevy version:
0.17(and up)
Relevant system information
- OS: Windows 10, Windows 11
- WGPU backend: DX12
- Rust version:
cargo 1.90.0 (840b83a10 2025-07-30) - Adapter info:
AdapterInfo { name: "NVIDIA GeForce RTX 3070 Ti", vendor: 4318, device: 9346, device_type: DiscreteGpu, driver: "32.0.15.8142", driver_info: "", backend: Dx12 }What you did
Attach identical material handles to different meshes while using Dx12 backend.
Reproduction steps
- Start with
generate_custom_meshexample - Replace
setupwith the following:
fn setup(
mut commands: Commands,
asset_server: Res<AssetServer>,
mut materials: ResMut<Assets<StandardMaterial>>,
mut meshes: ResMut<Assets<Mesh>>,
) {
// Import the custom texture.
let mesh_material = MeshMaterial3d(materials.add(StandardMaterial {
base_color_texture: Some(asset_server.load("textures/array_texture.png")),
..default()
}));
// Case 1: Use unique meshes from vec
// call create_cube_mesh in a loop 10 times and store them in a vec
let ten_meshes = (0..10)
.map(|_| meshes.add(create_cube_mesh()))
.collect::<Vec<_>>();
for i in 0..ten_meshes.len() {
// Case 1: Use unique meshes from vec
let mesh_handle = ten_meshes[i].clone();
commands.spawn((
Mesh3d(mesh_handle),
mesh_material.clone(),
Transform::from_xyz(i as f32, 0.0, 0.0),
CustomUV,
));
}
// Transform for the camera and lighting, looking at (0,0,0) (the position of the mesh).
let camera_and_light_transform =
Transform::from_xyz(1.8, 1.8, 1.8).looking_at(Vec3::ZERO, Vec3::Y);
// Camera in 3D space.
commands.spawn((Camera3d::default(), camera_and_light_transform));
// Light up the scene.
commands.spawn((PointLight::default(), camera_and_light_transform));
// Text to describe the controls.
commands.spawn((
Text::new("Controls:\nSpace: Change UVs\nX/Y/Z: Rotate\nR: Reset orientation"),
Node {
position_type: PositionType::Absolute,
top: px(12),
left: px(12),
..default()
},
));
}- Run
generate_custom_meshexample withWGPU_BACKEND=dx12.
What went wrong
This results in the following panic:
thread 'Compute Task Pool (4)' panicked at ~\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\wgpu-core-26.0.1\src\command\render.rs:2760:17:
assertion `left == right` failed
left: 32
right: 20
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Encountered a panic in system `bevy_render::renderer::render_system`!
Correct results can be seen when running with Vulkan WGPU backend.
Additional information
- Ensuring all mesh handles are identical as well as the material handles avoids the issue:
up(
mut commands: Commands,
asset_server: Res<AssetServer>,
mut materials: ResMut<Assets<StandardMaterial>>,
mut meshes: ResMut<Assets<Mesh>>,
) {
// Import the custom texture.
let mesh_material = MeshMaterial3d(materials.add(StandardMaterial {
base_color_texture: Some(asset_server.load("textures/array_texture.png")),
..default()
}));
// Case 2: Use instances of cloned mesh from vec
// call create_cube_mesh once, clone the handle 10 times, and store them in a vec
let cube_mesh_handle: Handle<Mesh> = meshes.add(create_cube_mesh());
let ten_mesh_clones = (0..10)
.map(|_| cube_mesh_handle.clone())
.collect::<Vec<_>>();
for i in 0..ten_mesh_clones.len() {
// Case 2: Use instances of cloned mesh from vec
let mesh_handle = ten_mesh_clones[i].clone();
commands.spawn((
Mesh3d(mesh_handle),
mesh_material.clone(),
Transform::from_xyz(i as f32, 0.0, 0.0),
CustomUV,
));
}
// Transform for the camera and lighting, looking at (0,0,0) (the position of the mesh).
let camera_and_light_transform =
Transform::from_xyz(1.8, 1.8, 1.8).looking_at(Vec3::ZERO, Vec3::Y);
// Camera in 3D space.
commands.spawn((Camera3d::default(), camera_and_light_transform));
// Light up the scene.
commands.spawn((PointLight::default(), camera_and_light_transform));
// Text to describe the controls.
commands.spawn((
Text::new("Controls:\nSpace: Change UVs\nX/Y/Z: Rotate\nR: Reset orientation"),
Node {
position_type: PositionType::Absolute,
top: px(12),
left: px(12),
..default()
},
));
}- As does ensuring mesh handle and material handle pairings are unique:
fn setup(
mut commands: Commands,
asset_server: Res<AssetServer>,
mut materials: ResMut<Assets<StandardMaterial>>,
mut meshes: ResMut<Assets<Mesh>>,
) {
// Case 3: Use unique meshes and materials
// call create_cube_mesh in a loop 10 times and store them in a vec
let ten_meshes = (0..10)
.map(|_| meshes.add(create_cube_mesh()))
.collect::<Vec<_>>();
for i in 0..ten_meshes.len() {
// Case 3: Use unique meshes and materials
let mesh_handle = ten_meshes[i].clone();
commands.spawn((
Mesh3d(mesh_handle),
MeshMaterial3d(materials.add(StandardMaterial {
base_color_texture: Some(asset_server.load("textures/array_texture.png")),
..default()
})),
Transform::from_xyz(i as f32, 0.0, 0.0),
CustomUV,
));
}
// Transform for the camera and lighting, looking at (0,0,0) (the position of the mesh).
let camera_and_light_transform =
Transform::from_xyz(1.8, 1.8, 1.8).looking_at(Vec3::ZERO, Vec3::Y);
// Camera in 3D space.
commands.spawn((Camera3d::default(), camera_and_light_transform));
// Light up the scene.
commands.spawn((PointLight::default(), camera_and_light_transform));
// Text to describe the controls.
commands.spawn((
Text::new("Controls:\nSpace: Change UVs\nX/Y/Z: Rotate\nR: Reset orientation"),
Node {
position_type: PositionType::Absolute,
top: px(12),
left: px(12),
..default()
},
));
}- This only happens with DX12 backend, not with Metal or Vulkan. I suspect this is because DX12 is stricter about byte alignment and layout.
- This panic only occurs after Bevy version 0.17. Could not reproduce issue on Bevy 0.16.
- Based on avoiding this issue involving how mesh and material handles are paired, my immediate hunch is that this has something to do with how Bevy is handling auto-instancing.
Full backtrace
thread 'Compute Task Pool (2)' panicked at ~\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\wgpu-core-26.0.1\src\command\render.rs:2760:17:
assertion `left == right` failed
left: 32
right: 20
stack backtrace:
0: std::panicking::begin_panic_handler
at /rustc/1159e78c4747b02ef996e55082b704c09b970588/library\std\src\panicking.rs:697
1: core::panicking::panic_fmt
at /rustc/1159e78c4747b02ef996e55082b704c09b970588/library\core\src\panicking.rs:75
2: core::panicking::assert_failed_inner
at /rustc/1159e78c4747b02ef996e55082b704c09b970588/library\core\src\panicking.rs:443
3: core::panicking::assert_failed
at /rustc/1159e78c4747b02ef996e55082b704c09b970588/library\core\src\panicking.rs:403
4: wgpu_core::command::render::multi_draw_indirect
at ~\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\wgpu-core-26.0.1\src\command\render.rs:2760
5: wgpu_core::command::render::impl$22::render_pass_end::closure$0
at ~\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\wgpu-core-26.0.1\src\command\render.rs:2064
6: wgpu_core::command::RecordingGuard::record
at ~\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\wgpu-core-26.0.1\src\command\mod.rs:324
7: enum2$::unlock_and_record
at ~\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\wgpu-core-26.0.1\src\command\mod.rs:245
8: wgpu_core::global::Global::render_pass_end
at ~\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\wgpu-core-26.0.1\src\command\render.rs:1835
9: wgpu::backend::wgpu_core::impl$50::end
at ~\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\wgpu-26.0.1\src\backend\wgpu_core.rs:3366
10: wgpu::backend::wgpu_core::impl$51::drop
at ~\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\wgpu-26.0.1\src\backend\wgpu_core.rs:3379
11: core::ptr::drop_in_place
at ~\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\ptr\mod.rs:804
12: core::ptr::drop_in_place >
at ~\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\ptr\mod.rs:804
13: core::ptr::drop_in_place
at ~\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\ptr\mod.rs:804
14: core::ptr::drop_in_place
at ~\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\ptr\mod.rs:804
15: core::mem::drop
at ~\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\mem\mod.rs:961
16: bevy_core_pipeline::core_3d::main_opaque_pass_3d_node::impl$0::run::closure$0
at .\crates\bevy_core_pipeline\src\core_3d\main_opaque_pass_3d_node.rs:136
17: core::ops::function::FnOnce::call_once >
at ~\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\ops\function.rs:253
18: alloc::boxed::impl$28::call_once,dyn$,assoc$ >,core::marker::
at ~\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\alloc\src\boxed.rs:1971
19: bevy_render::renderer::impl$0::finish::closure$0::async_block$0
at .\crates\bevy_render\src\renderer\mod.rs:599
20: core::panic::unwind_safe::impl$28::poll >
at ~\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\panic\unwind_safe.rs:297
21: futures_lite::future::impl$11::poll::closure$0 > >
at ~\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\futures-lite-2.6.1\src\future.rs:653
22: core::panic::unwind_safe::impl$25::call_once > >,futures_lite::future::impl$11::poll::closure_env$0 > > >
at ~\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\std\src\panicking.rs:589
24: std::panic::catch_unwind > > >,enum2$ > >
at ~\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\futures-lite-2.6.1\src\future.rs:653
28: async_executor::impl$21::poll > >,async_executor::impl$5::spawn_inner::closure_env$0 > >,async_executor::impl$5::spa
at ~\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\async-task-4.7.1\src\raw.rs:550
30: core::ops::function::FnOnce::call_once,alloc::boxed::Box,alloc::alloc::Global> > > > >,async_task
at ~\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\panic\unwind_safe.rs:272
32: std::panicking::catch_unwind::do_call > >,async_executor::impl$5::spawn_inner::closu
at ~\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\async-task-4.7.1\src\raw.rs:549
37: async_task::runnable::Runnable >::run >
at ~\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\async-task-4.7.1\src\runnable.rs:781
38: async_executor::impl$13::run::async_fn$0::async_block$0,async_channel::RecvError> >,futures_lite::future::Or,async_channel::RecvError> >,futures_lite::future::Or,async_channel::R
at ~\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\futures-lite-2.6.1\src\future.rs:454
40: async_executor::impl$13::run::async_fn$0,async_channel::RecvError> >,futures_lite::future::Or,async_chan
at ~\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\async-executor-1.13.3\src\lib.rs:758
41: async_executor::impl$5::run::async_fn$0,async_channel::RecvError> >,futures_lite::future::Or,async_chann
at ~\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\async-executor-1.13.3\src\lib.rs:344
42: futures_lite::future::block_on::closure$0,async_channel::RecvError> >,enum2$,async_channel::RecvError> >,futures_lite::future::Or > >::try_with >,futures_lite::future::block_on::closure_env$0 > >::with >,futures_lite::future::block_on::closure_env$0,async_channel::RecvError> >,enum2$,async_channel::RecvError> >,futures_lite::future::Or,async_channel::RecvError> > >
at ~\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\std\src\panicking.rs:589
48: std::panic::catch_unwind,async_channel::RecvError> > >
49: std::panicking::catch_unwind
at ~\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\std\src\panicking.rs:552
50: std::panic::catch_unwind,async_channel::RecvError> > >
at ~\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\std\src\panic.rs:359
51: bevy_tasks::task_pool::impl$2::new_internal::closure$0::closure$0::closure$0
at .\crates\bevy_tasks\src\task_pool.rs:197
52: std::thread::local::LocalKey::try_with >
at ~\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\std\src\thread\local.rs:315
53: std::thread::local::LocalKey::with >
at ~\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\std\src\thread\local.rs:279
54: bevy_tasks::task_pool::impl$2::new_internal::closure$0::closure$0
at .\crates\bevy_tasks\src\task_pool.rs:190
55: core::hint::black_box
at ~\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\hint.rs:482
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
Encountered a panic in system `bevy_render::renderer::render_system`!
Metadata
Metadata
Assignees
Labels
A-RenderingDrawing game state to the screenDrawing game state to the screenC-BugAn unexpected or incorrect behaviorAn unexpected or incorrect behaviorO-DX12Specific to the DX12 render APISpecific to the DX12 render APIP-CrashA sudden unexpected crashA sudden unexpected crashS-Needs-InvestigationThis issue requires detective work to figure out what's going wrongThis issue requires detective work to figure out what's going wrong