bevy/crates/bevy_pbr/src/prepass/prepass_bindings.rs
IceSentry 6d0c11a28f
Bind group layout entries (#10224)
# 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
2023-11-28 04:00:49 +00:00

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]
}