Panic / segfault when trying to create a custom bindless material with storage buffers.
- Dominant language
- Rust
- Stars
- 48.2k
- Forks
- 4.8k
- Avg merge
- 3d 16h
- Merged PRs (30d)
- 171
Description
## Bevy version
Bevy 0.16.0-rc.5
## \[Optional\] Relevant system information
Asahi Linux, Apple M1 Pro
```
2025-04-15T14:42:33.261113Z INFO bevy_render::renderer: AdapterInfo { name: "Apple M1 Pro (G13S C0)", vendor: 65541, device: 0, device_type: IntegratedGpu, driver: "Honeykrisp", driver_info: "Mesa 25.1.0-asahi20250221", backend: Vulkan }
2025-04-15T14:42:33.398102Z INFO bevy_render::batching::gpu_preprocessing: GPU preprocessing is fully supported on this device.
```
## What you did
I tried to create my own bindless material, learning from the docs, the examples, and the StandardMaterial source code.
Here is my material:
```rust
#[derive(AsBindGroup, Clone, Asset, TypePath)]
#[data(0, TerrainMaterialUniform, binding_array(10))]
#[bindless]
pub struct TerrainMaterial {
mask_index: u32,
#[storage(1, read_only)]
mat_props: Handle,
#[storage(2, read_only)]
tex_props: Handle,
#[texture(3, dimension = "2d_array")]
#[sampler(4)]
texmasks: Handle,
#[texture(5, dimension = "2d_array")]
#[sampler(6)]
propmasks: Handle,
#[texture(7, dimension = "2d_array")]
#[sampler(8)]
textures_color: Handle,
#[texture(9, dimension = "2d_array")]
#[sampler(10)]
textures_normal: Handle,
}
impl Material for TerrainMaterial {
fn fragment_shader() -> ShaderRef {
"shaders/terrain.wgsl".into()
}
}
#[derive(ShaderType, Clone, Copy)]
struct TerrainMaterialUniform {
mask_index: u32,
}
impl From<&TerrainMaterial> for TerrainMaterialUniform {
fn from(value: &TerrainMaterial) -> Self {
Self {
mask_index: value.mask_index,
}
}
}
```
As you can see, I have the following:
- Some textures and samplers
- Global uniform data (like StandardMaterial does)
- Some custom storage buffers
I have not really written my shader code yet. I just made a simple dummy shader to test if bindless works:
```wgsl
#import bevy_pbr::forward_io::VertexOutput;
@fragment
fn fragment(input: VertexOutput) -> @location(0) vec4 {
#ifdef BINDLESS
return vec4(1.0, 0.0, 0.0, 1.0);
#else
return vec4(0.0, 0.0, 1.0, 1.0);
#endif
}
```
I spawned a simple plane mesh with my custom material to test. I expected to see it either solid red or solid blue, depending on the state of the BINDLESS shader def. Instead, I got a crash.
## What went wrong
The code compiles (no error from the `AsBindGroup` derive), but crashes at runtime with the following:
```
2025-04-15T14:42:36.203590Z ERROR bevy_pbr::material_bind_groups: Binding array wasn't present for buffer at index BindlessIndex(1)
thread 'Compute Task Pool (5)' panicked at c/bevy/crates/bevy_pbr/src/material_bind_groups.rs:825:13:
An allocation into an empty slab should always succeed
stack backtrace:
0: __rustc::rust_begin_unwind
at /rustc/092a284ba0421695f2032c947765429fd7095796/library/std/src/panicking.rs:697:5
1: core::panicking::panic_fmt
at /rustc/092a284ba0421695f2032c947765429fd7095796/library/core/src/panicking.rs:75:14
2: bevy_pbr::material_bind_groups::MaterialBindGroupBindlessAllocator::allocate_unprepared
3: as bevy_render::render_asset::RenderAsset>::prepare_asset
4: bevy_render::render_asset::prepare_assets
5: as bevy_ecs::system::system::System>::run_unsafe
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
Encountered a panic in system `bevy_render::render_asset::prepare_assets>`!
thread 'Compute Task Pool (3)' panicked at c/crates/bevy_pbr/src/material_bind_groups.rs:707:18:
Bindings buffer must exist
stack backtrace:
0: __rustc::rust_begin_unwind
at /rustc/092a284ba0421695f2032c947765429fd7095796/library/std/src/panicking.rs:697:5
1: core::panicking::panic_fmt
at /rustc/092a284ba0421695f2032c947765429fd7095796/library/core/src/panicking.rs:75:14
2: core::panicking::panic_display
at /rustc/092a284ba0421695f2032c947765429fd7095796/library/core/src/panicking.rs:261:5
3: core::option::expect_failed
at /rustc/092a284ba0421695f2032c947765429fd7095796/library/core/src/option.rs:2024:5
4: alloc::vec::Vec::extend_trusted
5: as alloc::vec::spec_from_iter_nested::SpecFromIterNested>::from_iter
6: bevy_pbr::material_bind_groups::MaterialBindlessSlab::prepare_bind_group
7: bevy_pbr::material_bind_groups::MaterialBindlessSlab::prepare
8: as bevy_ecs::system::system::System>::run_unsafe
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
Encountered a panic in system `bevy_pbr::material::prepare_material_bind_groups`!
[1] 479258 segmentation fault (core dumped) cargo run
```
## Additional information
If I comment out the storage buffer bindings (but leave everything else as is: the textures, samplers, global data uniform), everything works. The game runs and I get the mesh rendered solid red, indicating that bindless is enabled.
Contributor guide
Research direction
The failure is in crates/bevy_pbr/src/material_bind_groups.rs, at the reported allocator and bind-group preparation paths; start by reproducing the custom TerrainMaterial with its two storage bindings and run cargo run. Done means the material no longer panics or segfaults and the dummy shader renders with storage buffers enabled.
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