bevyengine / bevyengine/bevy

Specialized Material Bind Group Layout

Open
#14,057 2 comments 1 reaction 0 assignees View on GitHub
A-Rendering C-Feature D-Modest
Dominant language
Rust
Stars
48.2k
Forks
4.8k
Avg merge
3d 22h
Merged PRs (30d)
161

Description

## What problem does this solve or what need does it fill?

Currently Bevy's Materials (which use the AsBindGroup trait/derive) assume a "static" bind group layout. For most of Bevy's life, this has been acceptable. But StandardMaterial has expanded to the point that it uses too many bind groups, risking overflowing on some platforms and blocking the addition of new features.

We've started to work around this by adding compile-time flags to enable/disable material features (#14048). But this is something that should be done automatically _at runtime_ to allow people to use whatever feature combinations they want.

## What solution would you like?

We should support "specializing" material bind group layouts. One approach is, rather than reuse existing material specialization keys (which may not encapsulate the required information, and may be much bigger than necessary), we can just "imply" a bitflag key:

```rust
#[derive(AsBindGroup)]
struct StandardMaterial {
pub base_color: Color,
// This is the first optional binding, it is bit 0
#[texture(1)]
#[sampler(2)]
pub base_color_texture: Option>,

// This is the second optional binding, it is bit 1
#[texture(3)]
#[sampler(4)]
pub emissive_texture: Option>,
}
```

The AsBindGroup trait would then have:

```rust
fn get_key(&self) -> u64 {
let mut key = 0;
if self.base_color_texture.is_some() {
key |= 1;
}
if self.emissive_texture.is_some() {
key |= 2;
}
key
}
```

And then bind_group_layout_entries could be:

```rust
fn bind_group_layout_entries(render_device: &RenderDevice, key: u64) -> Vec {
/ * field by field */
if key & 1 == 1 {
// add base_color_texture binding
}

if key & 2 == 2 {
// add emissive_texture binding
}
}
```

## Some Considerations

* We should decide whether this should be a default behavior or if it should be opt-in.
* It would be nice if we didn't pay unnecessary specialization costs for materials that don't need it.
* This adds another vector for fracturing pipelines / preventing batching. I'm guessing we probably don't want to do it for _every_ material that has an `Option`.
* This key _is_ pipeline specialization information, meaning it needs to be a part of the "top level" specialization key. If we don't pack it into an existing key, it will increase the per-entity hashing costs to look up the specialized pipeline.

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.