bevyengine / bevyengine/bevy

ShaderStorageBuffer changes only sync if Material is mutably accessed

Open
#20,378 1 comment 8 reactions 0 assignees View on GitHub
A-Assets A-Rendering C-Bug S-Needs-Investigation
Dominant language
Rust
Stars
48.2k
Forks
4.8k
Avg merge
3d 22h
Merged PRs (30d)
161

Description

## Bevy version

0.16.1

## What you did

I have a material
```rust
#[derive(Asset, TypePath, AsBindGroup, Debug, Clone)]
pub struct SbMaterial {
#[storage(0, read_only)]
sb: Handle,
}
```

and the material is initialized from a central resource that initializes one global shader storage buffer:

```rust
#[derive(Resource)]
pub struct SbResource {
pub buffer: Handle,
}
```

In a `setup` system, the `SbResource` and its `ShaderStorageBuffer` gets initialized.
Some other setup systems generate entities with `SbMaterial`, pointing to the same `Handle`.

An `update` system changes the `ShaderStorageBuffer` using the reference from `SbResource`:

```rust
fn update(
mut this: ResMut,
...,
mut materials: ResMut>,
) {
let Some(buffer) = buffers.get_mut(&this.buffer) else {
panic!("Buffer not found");
};
buffer.set_data(...);

// Workaround: We need to mutate the material to trigger a rebind of the shader storage buffer.
for (_, _material) in materials.iter_mut() {}
}
```

## What went wrong

This works, but only with the "Workaround" line above. If I remove the loop mutably accessing all materials, then the change to the shader storage buffer does not get applied and the old value keeps being used in rendering.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.