Mesh with vertex joint attributes presumes existence of SkinnedMesh
- Dominant language
- Rust
- Stars
- 48.2k
- Forks
- 4.8k
- Avg merge
- 3d 16h
- Merged PRs (30d)
- 171
Description
When I looked at the Bevy (0.17.3) API for mesh skinning, I interpreted the `SkinnedMesh` component as the main part driving the behavior of drawing the mesh using joint index/weight attributes; that adding it effectively "opts into" it.
However, this doesn't seem to be the case: Rendering panics if I spawn a `Mesh3d` whose asset has `Mesh::ATTRIBUTE_JOINT_WEIGHT` & `_INDEX` and I haven't [yet] added `SkinnedMesh`.
Detailed error output
ERROR wgpu::backend::wgpu_core: Handling wgpu errors as fatal by defaultthread '<unnamed>' (238332) panicked at <crates>/wgpu-26.0.1/src/backend/wgpu_core.rs:2391:18:
wgpu error: Validation ErrorCaused by:
In a CommandEncoder
In a draw command, kind: MultiDrawIndirectCount
The BindGroupLayout with 'mesh_layout' label of current set BindGroup with 'model_only_mesh_bind_group' label at index 2 is not compatible with the corresponding BindGroupLayout with 'skinned_mesh_layout' label of RenderPipeline with 'pbr_prepass_pipeline' label
Expected entry with binding 1 not found in assigned bind group layoutstack backtrace:
0: __rustc::rust_begin_unwind
at /rustc/ded5c06cf21d2b93bffd5d884aa6e96934ee4234/library/std/src/panicking.rs:698:5
1: core::panicking::panic_fmt
at /rustc/ded5c06cf21d2b93bffd5d884aa6e96934ee4234/library/core/src/panicking.rs:80:14
2: wgpu::backend::wgpu_core::default_error_handler
at <crates>/wgpu-26.0.1/src/backend/wgpu_core.rs:659:5
3: wgpu::backend::wgpu_core::ErrorSinkRaw::handle_error
at <crates>/wgpu-26.0.1/src/backend/wgpu_core.rs:643:21
4: wgpu::backend::wgpu_core::ContextWgpuCore::handle_error_inner
at <crates>/wgpu-26.0.1/src/backend/wgpu_core.rs:298:14
5: wgpu::backend::wgpu_core::ContextWgpuCore::handle_error_nolabel
at <crates>/wgpu-26.0.1/src/backend/wgpu_core.rs:323:14
6: <wgpu::backend::wgpu_core::CoreCommandEncoder as wgpu::dispatch::CommandEncoderInterface>::finish
at <crates>/wgpu-26.0.1/src/backend/wgpu_core.rs:2391:18
7: wgpu::api::command_encoder::CommandEncoder::finish
at <crates>/wgpu-26.0.1/src/api/command_encoder.rs:56:33
8: bevy_pbr::render::light::ShadowPassNode::run::{{closure}}
at <crates>/bevy_pbr-0.17.3/src/render/light.rs:2341:37
9: core::ops::function::FnOnce::call_once{{vtable.shim}}
at <rust>/lib/rustlib/src/rust/library/core/src/ops/function.rs:250:5
10: <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once
at <rust>/lib/rustlib/src/rust/library/alloc/src/boxed.rs:2005:9
11: bevy_render::renderer::RenderContext::finish::{{closure}}::{{closure}}
at <crates>/bevy_render-0.17.3/src/renderer/mod.rs:599:41
12: <core::panic::unwind_safe::AssertUnwindSafe<F> as core::future::future::Future>::poll
at <rust>/lib/rustlib/src/rust/library/core/src/panic/unwind_safe.rs:299:9
13: <futures_lite::future::CatchUnwind<F> as core::future::future::Future>::poll::{{closure}}
at <crates>/futures-lite-2.6.1/src/future.rs:653:53
14: <core::panic::unwind_safe::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once
at <rust>/lib/rustlib/src/rust/library/core/src/panic/unwind_safe.rs:274:9
15: std::panicking::catch_unwind::do_call
at <rust>/lib/rustlib/src/rust/library/std/src/panicking.rs:590:40
16: std::panicking::catch_unwind
at <rust>/lib/rustlib/src/rust/library/std/src/panicking.rs:553:19
17: std::panic::catch_unwind
at <rust>/lib/rustlib/src/rust/library/std/src/panic.rs:359:14
18: <futures_lite::future::CatchUnwind<F> as core::future::future::Future>::poll
at <crates>/futures-lite-2.6.1/src/future.rs:653:9
19: <async_executor::AsyncCallOnDrop<Fut,Cleanup> as core::future::future::Future>::poll
at <crates>/async-executor-1.13.3/src/lib.rs:1197:31
20: async_task::raw::RawTask<F,T,S,M>::run::{{closure}}
at <crates>/async-task-4.7.1/src/raw.rs:550:21
21: core::ops::function::FnOnce::call_once
at <rust>/lib/rustlib/src/rust/library/core/src/ops/function.rs:250:5
22: <core::panic::unwind_safe::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once
at <rust>/lib/rustlib/src/rust/library/core/src/panic/unwind_safe.rs:274:9
23: std::panicking::catch_unwind::do_call
at <rust>/lib/rustlib/src/rust/library/std/src/panicking.rs:590:40
24: std::panicking::catch_unwind
at <rust>/lib/rustlib/src/rust/library/std/src/panicking.rs:553:19
25: std::panic::catch_unwind
at <rust>/lib/rustlib/src/rust/library/std/src/panic.rs:359:14
26: async_task::raw::RawTask<F,T,S,M>::run
at <crates>/async-task-4.7.1/src/raw.rs:549:23
27: async_task::runnable::Runnable<M>::run
at <crates>/async-task-4.7.1/src/runnable.rs:781:18
28: async_executor::State::run::{{closure}}::{{closure}}
at <crates>/async-executor-1.13.3/src/lib.rs:751:30
29: <futures_lite::future::Or<F1,F2> as core::future::future::Future>::poll
at <crates>/futures-lite-2.6.1/src/future.rs:454:46
30: async_executor::State::run::{{closure}}
at <crates>/async-executor-1.13.3/src/lib.rs:758:32
31: async_executor::Executor::run::{{closure}}
at <crates>/async-executor-1.13.3/src/lib.rs:344:34
32: <core::panic::unwind_safe::AssertUnwindSafe<F> as core::future::future::Future>::poll
at <rust>/lib/rustlib/src/rust/library/core/src/panic/unwind_safe.rs:299:9
33: <futures_lite::future::CatchUnwind<F> as core::future::future::Future>::poll::{{closure}}
at <crates>/futures-lite-2.6.1/src/future.rs:653:53
34: <core::panic::unwind_safe::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once
at <rust>/lib/rustlib/src/rust/library/core/src/panic/unwind_safe.rs:274:9
35: std::panicking::catch_unwind::do_call
at <rust>/lib/rustlib/src/rust/library/std/src/panicking.rs:590:40
36: std::panicking::catch_unwind
at <rust>/lib/rustlib/src/rust/library/std/src/panicking.rs:553:19
37: std::panic::catch_unwind
at <rust>/lib/rustlib/src/rust/library/std/src/panic.rs:359:14
38: <futures_lite::future::CatchUnwind<F> as core::future::future::Future>::poll
at <crates>/futures-lite-2.6.1/src/future.rs:653:9
39: bevy_tasks::task_pool::TaskPool::execute_global_scope::{{closure}}::{{closure}}
at <crates>/bevy_tasks-0.17.3/src/task_pool.rs:526:22
40: <futures_lite::future::Or<F1,F2> as core::future::future::Future>::poll
at <crates>/futures-lite-2.6.1/src/future.rs:454:46
41: bevy_tasks::task_pool::TaskPool::execute_global_scope::{{closure}}
at <crates>/bevy_tasks-0.17.3/src/task_pool.rs:530:41
42: bevy_tasks::task_pool::TaskPool::scope_with_executor_inner::{{closure}}
at <crates>/bevy_tasks-0.17.3/src/task_pool.rs:457:89
43: async_io::driver::block_on::{{closure}}
at <crates>/async-io-2.6.0/src/driver.rs:204:53
44: std::thread::local::LocalKey<T>::try_with
at <rust>/lib/rustlib/src/rust/library/std/src/thread/local.rs:508:12
45: std::thread::local::LocalKey<T>::with
at <rust>/lib/rustlib/src/rust/library/std/src/thread/local.rs:472:20
46: async_io::driver::block_on
at <crates>/async-io-2.6.0/src/driver.rs:180:11
47: bevy_tasks::task_pool::TaskPool::scope_with_executor_inner
at <crates>/bevy_tasks-0.17.3/src/task_pool.rs:413:13
48: bevy_tasks::task_pool::TaskPool::scope::{{closure}}
at <crates>/bevy_tasks-0.17.3/src/task_pool.rs:316:18
49: std::thread::local::LocalKey<T>::try_with
at <rust>/lib/rustlib/src/rust/library/std/src/thread/local.rs:508:12
50: std::thread::local::LocalKey<T>::with
at <rust>/lib/rustlib/src/rust/library/std/src/thread/local.rs:472:20
51: bevy_tasks::task_pool::TaskPool::scope
at <crates>/bevy_tasks-0.17.3/src/task_pool.rs:315:31
52: bevy_render::renderer::RenderContext::finish
at <crates>/bevy_render-0.17.3/src/renderer/mod.rs:588:52
53: bevy_render::renderer::graph_runner::RenderGraphRunner::run
at <crates>/bevy_render-0.17.3/src/renderer/graph_runner.rs:83:82
54: bevy_render::renderer::render_system
at <crates>/bevy_render-0.17.3/src/renderer/mod.rs:43:15
55: core::ops::function::FnMut::call_mut
at <rust>/lib/rustlib/src/rust/library/core/src/ops/function.rs:166:5
56: core::ops::function::impls::<impl core::ops::function::FnMut<A> for &mut F>::call_mut
at <rust>/lib/rustlib/src/rust/library/core/src/ops/function.rs:298:21
57: <Func as bevy_ecs::system::exclusive_function_system::ExclusiveSystemParamFunction<fn(F0) .> Out>>::run::call_inner
at <crates>/bevy_ecs-0.17.3/src/system/exclusive_function_system.rs:270:21
58: <Func as bevy_ecs::system::exclusive_function_system::ExclusiveSystemParamFunction<fn(F0) .> Out>>::run
at <crates>/bevy_ecs-0.17.3/src/system/exclusive_function_system.rs:273:17
59: <bevy_ecs::system::exclusive_function_system::ExclusiveFunctionSystem<Marker,Out,F> as bevy_ecs::system::system::System>::run_unsafe::{{closure}}
at <crates>/bevy_ecs-0.17.3/src/system/exclusive_function_system.rs:135:33
60: bevy_ecs::world::World::last_change_tick_scope
at <crates>/bevy_ecs-0.17.3/src/world/mod.rs:3009:9
61: <bevy_ecs::system::exclusive_function_system::ExclusiveFunctionSystem<Marker,Out,F> as bevy_ecs::system::system::System>::run_unsafe
at <crates>/bevy_ecs-0.17.3/src/system/exclusive_function_system.rs:113:15
62: bevy_ecs::system::system::System::run_without_applying_deferred
at <crates>/bevy_ecs-0.17.3/src/system/system.rs:139:23
63: bevy_ecs::system::system::System::run
at <crates>/bevy_ecs-0.17.3/src/system/system.rs:119:24
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
The above error repeats a few times, including for the 'pbr_opaque_mesh_pipeline' pipeline label, before ultimately triggering:
Encountered a panic in system `bevy_render::renderer::render_system`!thread '<unnamed>' (238332) panicked at <crates>/wgpu-hal-26.0.6/src/vulkan/instance.rs:194:58:
Trying to destroy a SurfaceAcquireSemaphores that is still in use by a SurfaceTexture
A brief inspection suggests bevy_pbr selects a BindGroupLayoutDescriptor based on the presence of the attributes that is incompatible with the pipeline ultimately used to draw the mesh when there's no `SkinnedMesh`.
It seems to me that those attributes shouldn't be used at all if you don't add `SkinnedMesh`.
It might also be worth checking what happens if you have a `SkinnedMesh` with a `Mesh` that doesn't have the attributes.
---
This isn't actually blocking me, and I mention it more as a UX thing than a bug, since there's no defined behavior documented for this. Though that's not saying much, bevy_mesh::skinning could use more documentation 🙂
Contributor guide
Research direction
Start by reproducing the Mesh3d case with joint attributes but no SkinnedMesh, then inspect the bevy_pbr layout selection and the failing draw path reported in bevy_pbr/src/render/light.rs. Check both combinations mentioned in the issue, including SkinnedMesh without the attributes. Done means the invalid bind-group/pipeline combination no longer panics and the supported behavior is documented in bevy_mesh::skinning.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- computer-graphics, game-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100