# Objective
- Follow up to #9694
## Solution
- Same api as #9694 but adapted for `BindGroupLayoutEntry`
- Use the same `ShaderStages` visibilty for all entries by default
- Add `BindingType` helper function that mirror the wgsl equivalent and
that make writing layouts much simpler.
Before:
```rust
let layout = render_device.create_bind_group_layout(&BindGroupLayoutDescriptor {
label: Some("post_process_bind_group_layout"),
entries: &[
BindGroupLayoutEntry {
binding: 0,
visibility: ShaderStages::FRAGMENT,
ty: BindingType::Texture {
sample_type: TextureSampleType::Float { filterable: true },
view_dimension: TextureViewDimension::D2,
multisampled: false,
},
count: None,
},
BindGroupLayoutEntry {
binding: 1,
visibility: ShaderStages::FRAGMENT,
ty: BindingType::Sampler(SamplerBindingType::Filtering),
count: None,
},
BindGroupLayoutEntry {
binding: 2,
visibility: ShaderStages::FRAGMENT,
ty: BindingType::Buffer {
ty: bevy::render::render_resource::BufferBindingType::Uniform,
has_dynamic_offset: false,
min_binding_size: Some(PostProcessSettings::min_size()),
},
count: None,
},
],
});
```
After:
```rust
let layout = render_device.create_bind_group_layout(
"post_process_bind_group_layout"),
&BindGroupLayoutEntries::sequential(
ShaderStages::FRAGMENT,
(
texture_2d_f32(),
sampler(SamplerBindingType::Filtering),
uniform_buffer(false, Some(PostProcessSettings::min_size())),
),
),
);
```
Here's a more extreme example in bevy_solari:
86dab7f5da
---
## Changelog
- Added `BindGroupLayoutEntries` and all `BindingType` helper functions.
## Migration Guide
`RenderDevice::create_bind_group_layout()` doesn't take a
`BindGroupLayoutDescriptor` anymore. You need to provide the parameters
separately
```rust
// 0.12
let layout = render_device.create_bind_group_layout(&BindGroupLayoutDescriptor {
label: Some("post_process_bind_group_layout"),
entries: &[
BindGroupLayoutEntry {
// ...
},
],
});
// 0.13
let layout = render_device.create_bind_group_layout(
"post_process_bind_group_layout",
&[
BindGroupLayoutEntry {
// ...
},
],
);
```
## TODO
- [x] implement a `Dynamic` variant
- [x] update the `RenderDevice::create_bind_group_layout()` api to match
the one from `RenderDevice::creat_bind_group()`
- [x] docs
88 lines
2.8 KiB
Rust
88 lines
2.8 KiB
Rust
use bevy_core_pipeline::prepass::ViewPrepassTextures;
|
|
use bevy_render::render_resource::{
|
|
binding_types::{
|
|
texture_2d, texture_2d_multisampled, texture_depth_2d, texture_depth_2d_multisampled,
|
|
},
|
|
BindGroupLayoutEntryBuilder, TextureAspect, TextureSampleType, TextureView,
|
|
TextureViewDescriptor,
|
|
};
|
|
use bevy_utils::default;
|
|
use smallvec::SmallVec;
|
|
|
|
use crate::MeshPipelineViewLayoutKey;
|
|
|
|
pub fn get_bind_group_layout_entries(
|
|
layout_key: MeshPipelineViewLayoutKey,
|
|
) -> SmallVec<[BindGroupLayoutEntryBuilder; 4]> {
|
|
let mut result = SmallVec::<[BindGroupLayoutEntryBuilder; 4]>::new();
|
|
|
|
let multisampled = layout_key.contains(MeshPipelineViewLayoutKey::MULTISAMPLED);
|
|
|
|
if layout_key.contains(MeshPipelineViewLayoutKey::DEPTH_PREPASS) {
|
|
result.push(
|
|
// Depth texture
|
|
if multisampled {
|
|
texture_depth_2d_multisampled()
|
|
} else {
|
|
texture_depth_2d()
|
|
},
|
|
);
|
|
}
|
|
|
|
if layout_key.contains(MeshPipelineViewLayoutKey::NORMAL_PREPASS) {
|
|
result.push(
|
|
// Normal texture
|
|
if multisampled {
|
|
texture_2d_multisampled(TextureSampleType::Float { filterable: false })
|
|
} else {
|
|
texture_2d(TextureSampleType::Float { filterable: false })
|
|
},
|
|
);
|
|
}
|
|
|
|
if layout_key.contains(MeshPipelineViewLayoutKey::MOTION_VECTOR_PREPASS) {
|
|
result.push(
|
|
// Motion Vectors texture
|
|
if multisampled {
|
|
texture_2d_multisampled(TextureSampleType::Float { filterable: false })
|
|
} else {
|
|
texture_2d(TextureSampleType::Float { filterable: false })
|
|
},
|
|
);
|
|
}
|
|
|
|
if layout_key.contains(MeshPipelineViewLayoutKey::DEFERRED_PREPASS) {
|
|
result.push(
|
|
// Deferred texture
|
|
texture_2d(TextureSampleType::Uint),
|
|
);
|
|
}
|
|
|
|
result
|
|
}
|
|
|
|
pub fn get_bindings(prepass_textures: Option<&ViewPrepassTextures>) -> [Option<TextureView>; 4] {
|
|
let depth_desc = TextureViewDescriptor {
|
|
label: Some("prepass_depth"),
|
|
aspect: TextureAspect::DepthOnly,
|
|
..default()
|
|
};
|
|
let depth_view = prepass_textures
|
|
.and_then(|x| x.depth.as_ref())
|
|
.map(|texture| texture.texture.create_view(&depth_desc));
|
|
|
|
let normal_view = prepass_textures
|
|
.and_then(|x| x.normal.as_ref())
|
|
.map(|texture| texture.default_view.clone());
|
|
|
|
let motion_vectors_view = prepass_textures
|
|
.and_then(|x| x.motion_vectors.as_ref())
|
|
.map(|texture| texture.default_view.clone());
|
|
|
|
let deferred_view = prepass_textures
|
|
.and_then(|x| x.deferred.as_ref())
|
|
.map(|texture| texture.default_view.clone());
|
|
|
|
[depth_view, normal_view, motion_vectors_view, deferred_view]
|
|
}
|