mirror of
https://github.com/bevyengine/bevy
synced 2024-11-22 12:43:34 +00:00
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
This commit is contained in:
parent
f0a8994f55
commit
6d0c11a28f
29 changed files with 1142 additions and 1106 deletions
|
@ -1,7 +1,14 @@
|
|||
use bevy_app::{App, Plugin};
|
||||
use bevy_asset::{load_internal_asset, Handle};
|
||||
use bevy_ecs::prelude::*;
|
||||
use bevy_render::{render_resource::*, renderer::RenderDevice, RenderApp};
|
||||
use bevy_render::{
|
||||
render_resource::{
|
||||
binding_types::{sampler, texture_2d},
|
||||
*,
|
||||
},
|
||||
renderer::RenderDevice,
|
||||
RenderApp,
|
||||
};
|
||||
|
||||
use crate::fullscreen_vertex_shader::fullscreen_shader_vertex_state;
|
||||
|
||||
|
@ -36,28 +43,16 @@ impl FromWorld for BlitPipeline {
|
|||
fn from_world(render_world: &mut World) -> Self {
|
||||
let render_device = render_world.resource::<RenderDevice>();
|
||||
|
||||
let texture_bind_group =
|
||||
render_device.create_bind_group_layout(&BindGroupLayoutDescriptor {
|
||||
label: Some("blit_bind_group_layout"),
|
||||
entries: &[
|
||||
BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Texture {
|
||||
sample_type: TextureSampleType::Float { filterable: false },
|
||||
view_dimension: TextureViewDimension::D2,
|
||||
multisampled: false,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
BindGroupLayoutEntry {
|
||||
binding: 1,
|
||||
visibility: ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Sampler(SamplerBindingType::NonFiltering),
|
||||
count: None,
|
||||
},
|
||||
],
|
||||
});
|
||||
let texture_bind_group = render_device.create_bind_group_layout(
|
||||
"blit_bind_group_layout",
|
||||
&BindGroupLayoutEntries::sequential(
|
||||
ShaderStages::FRAGMENT,
|
||||
(
|
||||
texture_2d(TextureSampleType::Float { filterable: false }),
|
||||
sampler(SamplerBindingType::NonFiltering),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
let sampler = render_device.create_sampler(&SamplerDescriptor::default());
|
||||
|
||||
|
|
|
@ -6,7 +6,13 @@ use bevy_ecs::{
|
|||
world::{FromWorld, World},
|
||||
};
|
||||
use bevy_math::Vec4;
|
||||
use bevy_render::{render_resource::*, renderer::RenderDevice};
|
||||
use bevy_render::{
|
||||
render_resource::{
|
||||
binding_types::{sampler, texture_2d, uniform_buffer},
|
||||
*,
|
||||
},
|
||||
renderer::RenderDevice,
|
||||
};
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct BloomDownsamplingPipelineIds {
|
||||
|
@ -41,44 +47,21 @@ impl FromWorld for BloomDownsamplingPipeline {
|
|||
fn from_world(world: &mut World) -> Self {
|
||||
let render_device = world.resource::<RenderDevice>();
|
||||
|
||||
// Input texture binding
|
||||
let texture = BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
ty: BindingType::Texture {
|
||||
sample_type: TextureSampleType::Float { filterable: true },
|
||||
view_dimension: TextureViewDimension::D2,
|
||||
multisampled: false,
|
||||
},
|
||||
visibility: ShaderStages::FRAGMENT,
|
||||
count: None,
|
||||
};
|
||||
|
||||
// Sampler binding
|
||||
let sampler = BindGroupLayoutEntry {
|
||||
binding: 1,
|
||||
ty: BindingType::Sampler(SamplerBindingType::Filtering),
|
||||
visibility: ShaderStages::FRAGMENT,
|
||||
count: None,
|
||||
};
|
||||
|
||||
// Downsampling settings binding
|
||||
let settings = BindGroupLayoutEntry {
|
||||
binding: 2,
|
||||
ty: BindingType::Buffer {
|
||||
ty: BufferBindingType::Uniform,
|
||||
has_dynamic_offset: true,
|
||||
min_binding_size: Some(BloomUniforms::min_size()),
|
||||
},
|
||||
visibility: ShaderStages::FRAGMENT,
|
||||
count: None,
|
||||
};
|
||||
|
||||
// Bind group layout
|
||||
let bind_group_layout =
|
||||
render_device.create_bind_group_layout(&BindGroupLayoutDescriptor {
|
||||
label: Some("bloom_downsampling_bind_group_layout_with_settings"),
|
||||
entries: &[texture, sampler, settings],
|
||||
});
|
||||
let bind_group_layout = render_device.create_bind_group_layout(
|
||||
"bloom_downsampling_bind_group_layout_with_settings",
|
||||
&BindGroupLayoutEntries::sequential(
|
||||
ShaderStages::FRAGMENT,
|
||||
(
|
||||
// Input texture binding
|
||||
texture_2d(TextureSampleType::Float { filterable: true }),
|
||||
// Sampler binding
|
||||
sampler(SamplerBindingType::Filtering),
|
||||
// Downsampling settings binding
|
||||
uniform_buffer::<BloomUniforms>(true),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// Sampler
|
||||
let sampler = render_device.create_sampler(&SamplerDescriptor {
|
||||
|
|
|
@ -8,7 +8,14 @@ use bevy_ecs::{
|
|||
system::{Commands, Query, Res, ResMut, Resource},
|
||||
world::{FromWorld, World},
|
||||
};
|
||||
use bevy_render::{render_resource::*, renderer::RenderDevice, view::ViewTarget};
|
||||
use bevy_render::{
|
||||
render_resource::{
|
||||
binding_types::{sampler, texture_2d, uniform_buffer},
|
||||
*,
|
||||
},
|
||||
renderer::RenderDevice,
|
||||
view::ViewTarget,
|
||||
};
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct UpsamplingPipelineIds {
|
||||
|
@ -31,41 +38,20 @@ impl FromWorld for BloomUpsamplingPipeline {
|
|||
fn from_world(world: &mut World) -> Self {
|
||||
let render_device = world.resource::<RenderDevice>();
|
||||
|
||||
let bind_group_layout =
|
||||
render_device.create_bind_group_layout(&BindGroupLayoutDescriptor {
|
||||
label: Some("bloom_upsampling_bind_group_layout"),
|
||||
entries: &[
|
||||
let bind_group_layout = render_device.create_bind_group_layout(
|
||||
"bloom_upsampling_bind_group_layout",
|
||||
&BindGroupLayoutEntries::sequential(
|
||||
ShaderStages::FRAGMENT,
|
||||
(
|
||||
// Input texture
|
||||
BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
ty: BindingType::Texture {
|
||||
sample_type: TextureSampleType::Float { filterable: true },
|
||||
view_dimension: TextureViewDimension::D2,
|
||||
multisampled: false,
|
||||
},
|
||||
visibility: ShaderStages::FRAGMENT,
|
||||
count: None,
|
||||
},
|
||||
texture_2d(TextureSampleType::Float { filterable: true }),
|
||||
// Sampler
|
||||
BindGroupLayoutEntry {
|
||||
binding: 1,
|
||||
ty: BindingType::Sampler(SamplerBindingType::Filtering),
|
||||
visibility: ShaderStages::FRAGMENT,
|
||||
count: None,
|
||||
},
|
||||
sampler(SamplerBindingType::Filtering),
|
||||
// BloomUniforms
|
||||
BindGroupLayoutEntry {
|
||||
binding: 2,
|
||||
ty: BindingType::Buffer {
|
||||
ty: BufferBindingType::Uniform,
|
||||
has_dynamic_offset: true,
|
||||
min_binding_size: Some(BloomUniforms::min_size()),
|
||||
},
|
||||
visibility: ShaderStages::FRAGMENT,
|
||||
count: None,
|
||||
},
|
||||
],
|
||||
});
|
||||
uniform_buffer::<BloomUniforms>(true),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
BloomUpsamplingPipeline { bind_group_layout }
|
||||
}
|
||||
|
|
|
@ -11,7 +11,10 @@ use bevy_render::{
|
|||
extract_component::{ExtractComponent, ExtractComponentPlugin, UniformComponentPlugin},
|
||||
prelude::Camera,
|
||||
render_graph::RenderGraphApp,
|
||||
render_resource::*,
|
||||
render_resource::{
|
||||
binding_types::{sampler, texture_2d, uniform_buffer},
|
||||
*,
|
||||
},
|
||||
renderer::RenderDevice,
|
||||
texture::BevyDefault,
|
||||
view::{ExtractedView, ViewTarget},
|
||||
|
@ -169,39 +172,18 @@ pub struct CASPipeline {
|
|||
impl FromWorld for CASPipeline {
|
||||
fn from_world(render_world: &mut World) -> Self {
|
||||
let render_device = render_world.resource::<RenderDevice>();
|
||||
let texture_bind_group =
|
||||
render_device.create_bind_group_layout(&BindGroupLayoutDescriptor {
|
||||
label: Some("sharpening_texture_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,
|
||||
},
|
||||
let texture_bind_group = render_device.create_bind_group_layout(
|
||||
"sharpening_texture_bind_group_layout",
|
||||
&BindGroupLayoutEntries::sequential(
|
||||
ShaderStages::FRAGMENT,
|
||||
(
|
||||
texture_2d(TextureSampleType::Float { filterable: true }),
|
||||
sampler(SamplerBindingType::Filtering),
|
||||
// CAS Settings
|
||||
BindGroupLayoutEntry {
|
||||
binding: 2,
|
||||
ty: BindingType::Buffer {
|
||||
ty: BufferBindingType::Uniform,
|
||||
has_dynamic_offset: true,
|
||||
min_binding_size: Some(CASUniform::min_size()),
|
||||
},
|
||||
visibility: ShaderStages::FRAGMENT,
|
||||
count: None,
|
||||
},
|
||||
],
|
||||
});
|
||||
uniform_buffer::<CASUniform>(true),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
let sampler = render_device.create_sampler(&SamplerDescriptor::default());
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ use bevy_ecs::prelude::*;
|
|||
use bevy_math::UVec2;
|
||||
use bevy_render::{
|
||||
camera::ExtractedCamera,
|
||||
render_resource::*,
|
||||
render_resource::{binding_types::texture_2d, *},
|
||||
renderer::RenderDevice,
|
||||
texture::{CachedTexture, TextureCache},
|
||||
view::ViewTarget,
|
||||
|
@ -128,19 +128,13 @@ impl FromWorld for CopyDeferredLightingIdPipeline {
|
|||
fn from_world(world: &mut World) -> Self {
|
||||
let render_device = world.resource::<RenderDevice>();
|
||||
|
||||
let layout = render_device.create_bind_group_layout(&BindGroupLayoutDescriptor {
|
||||
label: Some("copy_deferred_lighting_id_bind_group_layout"),
|
||||
entries: &[BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Texture {
|
||||
sample_type: TextureSampleType::Uint,
|
||||
view_dimension: TextureViewDimension::D2,
|
||||
multisampled: false,
|
||||
},
|
||||
count: None,
|
||||
}],
|
||||
});
|
||||
let layout = render_device.create_bind_group_layout(
|
||||
"copy_deferred_lighting_id_bind_group_layout",
|
||||
&BindGroupLayoutEntries::single(
|
||||
ShaderStages::FRAGMENT,
|
||||
texture_2d(TextureSampleType::Uint),
|
||||
),
|
||||
);
|
||||
|
||||
let pipeline_id =
|
||||
world
|
||||
|
|
|
@ -13,7 +13,10 @@ use bevy_render::{
|
|||
prelude::Camera,
|
||||
render_graph::RenderGraphApp,
|
||||
render_graph::ViewNodeRunner,
|
||||
render_resource::*,
|
||||
render_resource::{
|
||||
binding_types::{sampler, texture_2d},
|
||||
*,
|
||||
},
|
||||
renderer::RenderDevice,
|
||||
texture::BevyDefault,
|
||||
view::{ExtractedView, ViewTarget},
|
||||
|
@ -131,27 +134,16 @@ impl FromWorld for FxaaPipeline {
|
|||
fn from_world(render_world: &mut World) -> Self {
|
||||
let texture_bind_group = render_world
|
||||
.resource::<RenderDevice>()
|
||||
.create_bind_group_layout(&BindGroupLayoutDescriptor {
|
||||
label: Some("fxaa_texture_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,
|
||||
},
|
||||
],
|
||||
});
|
||||
.create_bind_group_layout(
|
||||
"fxaa_texture_bind_group_layout",
|
||||
&BindGroupLayoutEntries::sequential(
|
||||
ShaderStages::FRAGMENT,
|
||||
(
|
||||
texture_2d(TextureSampleType::Float { filterable: true }),
|
||||
sampler(SamplerBindingType::Filtering),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
FxaaPipeline { texture_bind_group }
|
||||
}
|
||||
|
|
|
@ -10,13 +10,13 @@ use bevy_render::{
|
|||
extract_component::{ExtractComponent, ExtractComponentPlugin},
|
||||
render_asset::RenderAssets,
|
||||
render_resource::{
|
||||
BindGroup, BindGroupEntries, BindGroupLayout, BindGroupLayoutDescriptor,
|
||||
BindGroupLayoutEntry, BindingType, BufferBindingType, CachedRenderPipelineId,
|
||||
ColorTargetState, ColorWrites, CompareFunction, DepthBiasState, DepthStencilState,
|
||||
FragmentState, MultisampleState, PipelineCache, PrimitiveState, RenderPipelineDescriptor,
|
||||
SamplerBindingType, Shader, ShaderStages, ShaderType, SpecializedRenderPipeline,
|
||||
SpecializedRenderPipelines, StencilFaceState, StencilState, TextureFormat,
|
||||
TextureSampleType, TextureViewDimension, VertexState,
|
||||
binding_types::{sampler, texture_cube, uniform_buffer},
|
||||
BindGroup, BindGroupEntries, BindGroupLayout, BindGroupLayoutEntries,
|
||||
CachedRenderPipelineId, ColorTargetState, ColorWrites, CompareFunction, DepthBiasState,
|
||||
DepthStencilState, FragmentState, MultisampleState, PipelineCache, PrimitiveState,
|
||||
RenderPipelineDescriptor, SamplerBindingType, Shader, ShaderStages,
|
||||
SpecializedRenderPipeline, SpecializedRenderPipelines, StencilFaceState, StencilState,
|
||||
TextureFormat, TextureSampleType, VertexState,
|
||||
},
|
||||
renderer::RenderDevice,
|
||||
texture::{BevyDefault, Image},
|
||||
|
@ -80,41 +80,19 @@ struct SkyboxPipeline {
|
|||
|
||||
impl SkyboxPipeline {
|
||||
fn new(render_device: &RenderDevice) -> Self {
|
||||
let bind_group_layout_descriptor = BindGroupLayoutDescriptor {
|
||||
label: Some("skybox_bind_group_layout"),
|
||||
entries: &[
|
||||
BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Texture {
|
||||
sample_type: TextureSampleType::Float { filterable: true },
|
||||
view_dimension: TextureViewDimension::Cube,
|
||||
multisampled: false,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
BindGroupLayoutEntry {
|
||||
binding: 1,
|
||||
visibility: ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Sampler(SamplerBindingType::Filtering),
|
||||
count: None,
|
||||
},
|
||||
BindGroupLayoutEntry {
|
||||
binding: 2,
|
||||
visibility: ShaderStages::VERTEX_FRAGMENT,
|
||||
ty: BindingType::Buffer {
|
||||
ty: BufferBindingType::Uniform,
|
||||
has_dynamic_offset: true,
|
||||
min_binding_size: Some(ViewUniform::min_size()),
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
Self {
|
||||
bind_group_layout: render_device
|
||||
.create_bind_group_layout(&bind_group_layout_descriptor),
|
||||
bind_group_layout: render_device.create_bind_group_layout(
|
||||
"skybox_bind_group_layout",
|
||||
&BindGroupLayoutEntries::sequential(
|
||||
ShaderStages::FRAGMENT,
|
||||
(
|
||||
texture_cube(TextureSampleType::Float { filterable: true }),
|
||||
sampler(SamplerBindingType::Filtering),
|
||||
uniform_buffer::<ViewUniform>(true)
|
||||
.visibility(ShaderStages::VERTEX_FRAGMENT),
|
||||
),
|
||||
),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,13 +21,13 @@ use bevy_render::{
|
|||
prelude::{Camera, Projection},
|
||||
render_graph::{NodeRunError, RenderGraphApp, RenderGraphContext, ViewNode, ViewNodeRunner},
|
||||
render_resource::{
|
||||
BindGroupEntries, BindGroupLayout, BindGroupLayoutDescriptor, BindGroupLayoutEntry,
|
||||
BindingType, CachedRenderPipelineId, ColorTargetState, ColorWrites, Extent3d, FilterMode,
|
||||
FragmentState, MultisampleState, Operations, PipelineCache, PrimitiveState,
|
||||
RenderPassColorAttachment, RenderPassDescriptor, RenderPipelineDescriptor, Sampler,
|
||||
SamplerBindingType, SamplerDescriptor, Shader, ShaderStages, SpecializedRenderPipeline,
|
||||
SpecializedRenderPipelines, TextureDescriptor, TextureDimension, TextureFormat,
|
||||
TextureSampleType, TextureUsages, TextureViewDimension,
|
||||
binding_types::{sampler, texture_2d, texture_depth_2d},
|
||||
BindGroupEntries, BindGroupLayout, BindGroupLayoutEntries, CachedRenderPipelineId,
|
||||
ColorTargetState, ColorWrites, Extent3d, FilterMode, FragmentState, MultisampleState,
|
||||
Operations, PipelineCache, PrimitiveState, RenderPassColorAttachment, RenderPassDescriptor,
|
||||
RenderPipelineDescriptor, Sampler, SamplerBindingType, SamplerDescriptor, Shader,
|
||||
ShaderStages, SpecializedRenderPipeline, SpecializedRenderPipelines, TextureDescriptor,
|
||||
TextureDimension, TextureFormat, TextureSampleType, TextureUsages,
|
||||
},
|
||||
renderer::{RenderContext, RenderDevice},
|
||||
texture::{BevyDefault, CachedTexture, TextureCache},
|
||||
|
@ -266,70 +266,26 @@ impl FromWorld for TaaPipeline {
|
|||
..SamplerDescriptor::default()
|
||||
});
|
||||
|
||||
let taa_bind_group_layout =
|
||||
render_device.create_bind_group_layout(&BindGroupLayoutDescriptor {
|
||||
label: Some("taa_bind_group_layout"),
|
||||
entries: &[
|
||||
let taa_bind_group_layout = render_device.create_bind_group_layout(
|
||||
"taa_bind_group_layout",
|
||||
&BindGroupLayoutEntries::sequential(
|
||||
ShaderStages::FRAGMENT,
|
||||
(
|
||||
// View target (read)
|
||||
BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Texture {
|
||||
sample_type: TextureSampleType::Float { filterable: true },
|
||||
view_dimension: TextureViewDimension::D2,
|
||||
multisampled: false,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
texture_2d(TextureSampleType::Float { filterable: true }),
|
||||
// TAA History (read)
|
||||
BindGroupLayoutEntry {
|
||||
binding: 1,
|
||||
visibility: ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Texture {
|
||||
sample_type: TextureSampleType::Float { filterable: true },
|
||||
view_dimension: TextureViewDimension::D2,
|
||||
multisampled: false,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
texture_2d(TextureSampleType::Float { filterable: true }),
|
||||
// Motion Vectors
|
||||
BindGroupLayoutEntry {
|
||||
binding: 2,
|
||||
visibility: ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Texture {
|
||||
sample_type: TextureSampleType::Float { filterable: true },
|
||||
view_dimension: TextureViewDimension::D2,
|
||||
multisampled: false,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
texture_2d(TextureSampleType::Float { filterable: true }),
|
||||
// Depth
|
||||
BindGroupLayoutEntry {
|
||||
binding: 3,
|
||||
visibility: ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Texture {
|
||||
sample_type: TextureSampleType::Depth,
|
||||
view_dimension: TextureViewDimension::D2,
|
||||
multisampled: false,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
texture_depth_2d(),
|
||||
// Nearest sampler
|
||||
BindGroupLayoutEntry {
|
||||
binding: 4,
|
||||
visibility: ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Sampler(SamplerBindingType::NonFiltering),
|
||||
count: None,
|
||||
},
|
||||
sampler(SamplerBindingType::NonFiltering),
|
||||
// Linear sampler
|
||||
BindGroupLayoutEntry {
|
||||
binding: 5,
|
||||
visibility: ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Sampler(SamplerBindingType::Filtering),
|
||||
count: None,
|
||||
},
|
||||
],
|
||||
});
|
||||
sampler(SamplerBindingType::Filtering),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
TaaPipeline {
|
||||
taa_bind_group_layout,
|
||||
|
|
|
@ -7,6 +7,9 @@ use bevy_render::camera::Camera;
|
|||
use bevy_render::extract_component::{ExtractComponent, ExtractComponentPlugin};
|
||||
use bevy_render::extract_resource::{ExtractResource, ExtractResourcePlugin};
|
||||
use bevy_render::render_asset::RenderAssets;
|
||||
use bevy_render::render_resource::binding_types::{
|
||||
sampler, texture_2d, texture_3d, uniform_buffer,
|
||||
};
|
||||
use bevy_render::renderer::RenderDevice;
|
||||
use bevy_render::texture::{CompressedImageFormats, Image, ImageSampler, ImageType};
|
||||
use bevy_render::view::{ViewTarget, ViewUniform};
|
||||
|
@ -248,42 +251,24 @@ impl SpecializedRenderPipeline for TonemappingPipeline {
|
|||
|
||||
impl FromWorld for TonemappingPipeline {
|
||||
fn from_world(render_world: &mut World) -> Self {
|
||||
let mut entries = vec![
|
||||
BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Buffer {
|
||||
ty: BufferBindingType::Uniform,
|
||||
has_dynamic_offset: true,
|
||||
min_binding_size: Some(ViewUniform::min_size()),
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
BindGroupLayoutEntry {
|
||||
binding: 1,
|
||||
visibility: ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Texture {
|
||||
sample_type: TextureSampleType::Float { filterable: false },
|
||||
view_dimension: TextureViewDimension::D2,
|
||||
multisampled: false,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
BindGroupLayoutEntry {
|
||||
binding: 2,
|
||||
visibility: ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Sampler(SamplerBindingType::NonFiltering),
|
||||
count: None,
|
||||
},
|
||||
];
|
||||
entries.extend(get_lut_bind_group_layout_entries([3, 4]));
|
||||
let mut entries = DynamicBindGroupLayoutEntries::new_with_indices(
|
||||
ShaderStages::FRAGMENT,
|
||||
(
|
||||
(0, uniform_buffer::<ViewUniform>(true)),
|
||||
(
|
||||
1,
|
||||
texture_2d(TextureSampleType::Float { filterable: false }),
|
||||
),
|
||||
(2, sampler(SamplerBindingType::NonFiltering)),
|
||||
),
|
||||
);
|
||||
let lut_layout_entries = get_lut_bind_group_layout_entries();
|
||||
entries =
|
||||
entries.extend_with_indices(((3, lut_layout_entries[0]), (4, lut_layout_entries[1])));
|
||||
|
||||
let tonemap_texture_bind_group = render_world
|
||||
.resource::<RenderDevice>()
|
||||
.create_bind_group_layout(&BindGroupLayoutDescriptor {
|
||||
label: Some("tonemapping_hdr_texture_bind_group_layout"),
|
||||
entries: &entries,
|
||||
});
|
||||
.create_bind_group_layout("tonemapping_hdr_texture_bind_group_layout", &entries);
|
||||
|
||||
TonemappingPipeline {
|
||||
texture_bind_group: tonemap_texture_bind_group,
|
||||
|
@ -345,24 +330,10 @@ pub fn get_lut_bindings<'a>(
|
|||
(&lut_image.texture_view, &lut_image.sampler)
|
||||
}
|
||||
|
||||
pub fn get_lut_bind_group_layout_entries(bindings: [u32; 2]) -> [BindGroupLayoutEntry; 2] {
|
||||
pub fn get_lut_bind_group_layout_entries() -> [BindGroupLayoutEntryBuilder; 2] {
|
||||
[
|
||||
BindGroupLayoutEntry {
|
||||
binding: bindings[0],
|
||||
visibility: ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Texture {
|
||||
sample_type: TextureSampleType::Float { filterable: true },
|
||||
view_dimension: TextureViewDimension::D3,
|
||||
multisampled: false,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
BindGroupLayoutEntry {
|
||||
binding: bindings[1],
|
||||
visibility: ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Sampler(SamplerBindingType::Filtering),
|
||||
count: None,
|
||||
},
|
||||
texture_3d(TextureSampleType::Float { filterable: true }),
|
||||
sampler(SamplerBindingType::Filtering),
|
||||
]
|
||||
}
|
||||
|
||||
|
|
|
@ -54,10 +54,9 @@ use bevy_render::{
|
|||
render_asset::{PrepareAssetError, RenderAsset, RenderAssetPlugin, RenderAssets},
|
||||
render_phase::{PhaseItem, RenderCommand, RenderCommandResult, TrackedRenderPass},
|
||||
render_resource::{
|
||||
BindGroup, BindGroupEntries, BindGroupLayout, BindGroupLayoutDescriptor,
|
||||
BindGroupLayoutEntry, BindingType, Buffer, BufferBindingType, BufferInitDescriptor,
|
||||
BufferUsages, Shader, ShaderStages, ShaderType, VertexAttribute, VertexBufferLayout,
|
||||
VertexFormat, VertexStepMode,
|
||||
binding_types::uniform_buffer, BindGroup, BindGroupEntries, BindGroupLayout,
|
||||
BindGroupLayoutEntries, Buffer, BufferInitDescriptor, BufferUsages, Shader, ShaderStages,
|
||||
ShaderType, VertexAttribute, VertexBufferLayout, VertexFormat, VertexStepMode,
|
||||
},
|
||||
renderer::RenderDevice,
|
||||
view::RenderLayers,
|
||||
|
@ -120,19 +119,13 @@ impl Plugin for GizmoPlugin {
|
|||
};
|
||||
|
||||
let render_device = render_app.world.resource::<RenderDevice>();
|
||||
let layout = render_device.create_bind_group_layout(&BindGroupLayoutDescriptor {
|
||||
entries: &[BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: ShaderStages::VERTEX,
|
||||
ty: BindingType::Buffer {
|
||||
ty: BufferBindingType::Uniform,
|
||||
has_dynamic_offset: true,
|
||||
min_binding_size: Some(LineGizmoUniform::min_size()),
|
||||
},
|
||||
count: None,
|
||||
}],
|
||||
label: Some("LineGizmoUniform layout"),
|
||||
});
|
||||
let layout = render_device.create_bind_group_layout(
|
||||
"LineGizmoUniform layout",
|
||||
&BindGroupLayoutEntries::single(
|
||||
ShaderStages::VERTEX,
|
||||
uniform_buffer::<LineGizmoUniform>(true),
|
||||
),
|
||||
);
|
||||
|
||||
render_app.insert_resource(LineGizmoUniformBindgroupLayout { layout });
|
||||
}
|
||||
|
|
|
@ -18,7 +18,9 @@ use bevy_render::{
|
|||
},
|
||||
render_asset::RenderAssets,
|
||||
render_graph::{NodeRunError, RenderGraphContext, ViewNode, ViewNodeRunner},
|
||||
render_resource::{self, Operations, PipelineCache, RenderPassDescriptor},
|
||||
render_resource::{
|
||||
binding_types::uniform_buffer, Operations, PipelineCache, RenderPassDescriptor,
|
||||
},
|
||||
renderer::{RenderContext, RenderDevice},
|
||||
texture::Image,
|
||||
view::{ViewTarget, ViewUniformOffset},
|
||||
|
@ -376,19 +378,13 @@ impl SpecializedRenderPipeline for DeferredLightingLayout {
|
|||
impl FromWorld for DeferredLightingLayout {
|
||||
fn from_world(world: &mut World) -> Self {
|
||||
let render_device = world.resource::<RenderDevice>();
|
||||
let layout = render_device.create_bind_group_layout(&BindGroupLayoutDescriptor {
|
||||
label: Some("deferred_lighting_layout"),
|
||||
entries: &[BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: ShaderStages::VERTEX_FRAGMENT,
|
||||
ty: BindingType::Buffer {
|
||||
ty: render_resource::BufferBindingType::Uniform,
|
||||
has_dynamic_offset: false,
|
||||
min_binding_size: Some(PbrDeferredLightingDepthId::min_size()),
|
||||
},
|
||||
count: None,
|
||||
}],
|
||||
});
|
||||
let layout = render_device.create_bind_group_layout(
|
||||
"deferred_lighting_layout",
|
||||
&BindGroupLayoutEntries::single(
|
||||
ShaderStages::VERTEX_FRAGMENT,
|
||||
uniform_buffer::<PbrDeferredLightingDepthId>(false),
|
||||
),
|
||||
);
|
||||
Self {
|
||||
mesh_pipeline: world.resource::<MeshPipeline>().clone(),
|
||||
bind_group_layout_1: layout,
|
||||
|
|
|
@ -6,7 +6,10 @@ use bevy_reflect::Reflect;
|
|||
use bevy_render::{
|
||||
extract_component::{ExtractComponent, ExtractComponentPlugin},
|
||||
render_asset::RenderAssets,
|
||||
render_resource::*,
|
||||
render_resource::{
|
||||
binding_types::{sampler, texture_cube},
|
||||
*,
|
||||
},
|
||||
texture::{FallbackImageCubemap, Image},
|
||||
};
|
||||
|
||||
|
@ -79,33 +82,10 @@ pub fn get_bindings<'a>(
|
|||
(diffuse_map, specular_map, &fallback_image_cubemap.sampler)
|
||||
}
|
||||
|
||||
pub fn get_bind_group_layout_entries(bindings: [u32; 3]) -> [BindGroupLayoutEntry; 3] {
|
||||
pub fn get_bind_group_layout_entries() -> [BindGroupLayoutEntryBuilder; 3] {
|
||||
[
|
||||
BindGroupLayoutEntry {
|
||||
binding: bindings[0],
|
||||
visibility: ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Texture {
|
||||
sample_type: TextureSampleType::Float { filterable: true },
|
||||
view_dimension: TextureViewDimension::Cube,
|
||||
multisampled: false,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
BindGroupLayoutEntry {
|
||||
binding: bindings[1],
|
||||
visibility: ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Texture {
|
||||
sample_type: TextureSampleType::Float { filterable: true },
|
||||
view_dimension: TextureViewDimension::Cube,
|
||||
multisampled: false,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
BindGroupLayoutEntry {
|
||||
binding: bindings[2],
|
||||
visibility: ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Sampler(SamplerBindingType::Filtering),
|
||||
count: None,
|
||||
},
|
||||
texture_cube(TextureSampleType::Float { filterable: true }),
|
||||
texture_cube(TextureSampleType::Float { filterable: true }),
|
||||
sampler(SamplerBindingType::Filtering),
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
mod prepass_bindings;
|
||||
|
||||
use bevy_render::render_resource::binding_types::uniform_buffer;
|
||||
pub use prepass_bindings::*;
|
||||
|
||||
use bevy_app::{Plugin, PreUpdate};
|
||||
|
@ -229,74 +230,33 @@ impl<M: Material> FromWorld for PrepassPipeline<M> {
|
|||
let render_device = world.resource::<RenderDevice>();
|
||||
let asset_server = world.resource::<AssetServer>();
|
||||
|
||||
let view_layout_motion_vectors =
|
||||
render_device.create_bind_group_layout(&BindGroupLayoutDescriptor {
|
||||
entries: &[
|
||||
let view_layout_motion_vectors = render_device.create_bind_group_layout(
|
||||
"prepass_view_layout_motion_vectors",
|
||||
&BindGroupLayoutEntries::sequential(
|
||||
ShaderStages::VERTEX_FRAGMENT,
|
||||
(
|
||||
// View
|
||||
BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: ShaderStages::VERTEX | ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Buffer {
|
||||
ty: BufferBindingType::Uniform,
|
||||
has_dynamic_offset: true,
|
||||
min_binding_size: Some(ViewUniform::min_size()),
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
uniform_buffer::<ViewUniform>(true),
|
||||
// Globals
|
||||
BindGroupLayoutEntry {
|
||||
binding: 1,
|
||||
visibility: ShaderStages::VERTEX_FRAGMENT,
|
||||
ty: BindingType::Buffer {
|
||||
ty: BufferBindingType::Uniform,
|
||||
has_dynamic_offset: false,
|
||||
min_binding_size: Some(GlobalsUniform::min_size()),
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
uniform_buffer::<GlobalsUniform>(false),
|
||||
// PreviousViewProjection
|
||||
BindGroupLayoutEntry {
|
||||
binding: 2,
|
||||
visibility: ShaderStages::VERTEX | ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Buffer {
|
||||
ty: BufferBindingType::Uniform,
|
||||
has_dynamic_offset: true,
|
||||
min_binding_size: Some(PreviousViewProjection::min_size()),
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
],
|
||||
label: Some("prepass_view_layout_motion_vectors"),
|
||||
});
|
||||
uniform_buffer::<PreviousViewProjection>(true),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
let view_layout_no_motion_vectors =
|
||||
render_device.create_bind_group_layout(&BindGroupLayoutDescriptor {
|
||||
entries: &[
|
||||
let view_layout_no_motion_vectors = render_device.create_bind_group_layout(
|
||||
"prepass_view_layout_no_motion_vectors",
|
||||
&BindGroupLayoutEntries::sequential(
|
||||
ShaderStages::VERTEX_FRAGMENT,
|
||||
(
|
||||
// View
|
||||
BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: ShaderStages::VERTEX | ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Buffer {
|
||||
ty: BufferBindingType::Uniform,
|
||||
has_dynamic_offset: true,
|
||||
min_binding_size: Some(ViewUniform::min_size()),
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
uniform_buffer::<ViewUniform>(true),
|
||||
// Globals
|
||||
BindGroupLayoutEntry {
|
||||
binding: 1,
|
||||
visibility: ShaderStages::VERTEX_FRAGMENT,
|
||||
ty: BindingType::Buffer {
|
||||
ty: BufferBindingType::Uniform,
|
||||
has_dynamic_offset: false,
|
||||
min_binding_size: Some(GlobalsUniform::min_size()),
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
],
|
||||
label: Some("prepass_view_layout_no_motion_vectors"),
|
||||
});
|
||||
uniform_buffer::<GlobalsUniform>(false),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
let mesh_pipeline = world.resource::<MeshPipeline>();
|
||||
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
use bevy_core_pipeline::prepass::ViewPrepassTextures;
|
||||
use bevy_render::render_resource::{
|
||||
BindGroupLayoutEntry, BindingType, ShaderStages, TextureAspect, TextureSampleType, TextureView,
|
||||
TextureViewDescriptor, TextureViewDimension,
|
||||
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;
|
||||
|
@ -9,25 +12,19 @@ use smallvec::SmallVec;
|
|||
use crate::MeshPipelineViewLayoutKey;
|
||||
|
||||
pub fn get_bind_group_layout_entries(
|
||||
bindings: [u32; 4],
|
||||
layout_key: MeshPipelineViewLayoutKey,
|
||||
) -> SmallVec<[BindGroupLayoutEntry; 4]> {
|
||||
let mut result = SmallVec::<[BindGroupLayoutEntry; 4]>::new();
|
||||
) -> 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
|
||||
BindGroupLayoutEntry {
|
||||
binding: bindings[0],
|
||||
visibility: ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Texture {
|
||||
multisampled,
|
||||
sample_type: TextureSampleType::Depth,
|
||||
view_dimension: TextureViewDimension::D2,
|
||||
},
|
||||
count: None,
|
||||
if multisampled {
|
||||
texture_depth_2d_multisampled()
|
||||
} else {
|
||||
texture_depth_2d()
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -35,15 +32,10 @@ pub fn get_bind_group_layout_entries(
|
|||
if layout_key.contains(MeshPipelineViewLayoutKey::NORMAL_PREPASS) {
|
||||
result.push(
|
||||
// Normal texture
|
||||
BindGroupLayoutEntry {
|
||||
binding: bindings[1],
|
||||
visibility: ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Texture {
|
||||
multisampled,
|
||||
sample_type: TextureSampleType::Float { filterable: false },
|
||||
view_dimension: TextureViewDimension::D2,
|
||||
},
|
||||
count: None,
|
||||
if multisampled {
|
||||
texture_2d_multisampled(TextureSampleType::Float { filterable: false })
|
||||
} else {
|
||||
texture_2d(TextureSampleType::Float { filterable: false })
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -51,15 +43,10 @@ pub fn get_bind_group_layout_entries(
|
|||
if layout_key.contains(MeshPipelineViewLayoutKey::MOTION_VECTOR_PREPASS) {
|
||||
result.push(
|
||||
// Motion Vectors texture
|
||||
BindGroupLayoutEntry {
|
||||
binding: bindings[2],
|
||||
visibility: ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Texture {
|
||||
multisampled,
|
||||
sample_type: TextureSampleType::Float { filterable: false },
|
||||
view_dimension: TextureViewDimension::D2,
|
||||
},
|
||||
count: None,
|
||||
if multisampled {
|
||||
texture_2d_multisampled(TextureSampleType::Float { filterable: false })
|
||||
} else {
|
||||
texture_2d(TextureSampleType::Float { filterable: false })
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -67,16 +54,7 @@ pub fn get_bind_group_layout_entries(
|
|||
if layout_key.contains(MeshPipelineViewLayoutKey::DEFERRED_PREPASS) {
|
||||
result.push(
|
||||
// Deferred texture
|
||||
BindGroupLayoutEntry {
|
||||
binding: bindings[3],
|
||||
visibility: ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Texture {
|
||||
multisampled: false,
|
||||
sample_type: TextureSampleType::Uint,
|
||||
view_dimension: TextureViewDimension::D2,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
texture_2d(TextureSampleType::Uint),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,50 +17,28 @@ mod layout_entry {
|
|||
use crate::MeshUniform;
|
||||
use bevy_render::{
|
||||
render_resource::{
|
||||
BindGroupLayoutEntry, BindingType, BufferBindingType, BufferSize, GpuArrayBuffer,
|
||||
ShaderStages, TextureSampleType, TextureViewDimension,
|
||||
binding_types::{texture_3d, uniform_buffer_sized},
|
||||
BindGroupLayoutEntryBuilder, BufferSize, GpuArrayBuffer, ShaderStages,
|
||||
TextureSampleType,
|
||||
},
|
||||
renderer::RenderDevice,
|
||||
};
|
||||
|
||||
fn buffer(binding: u32, size: u64, visibility: ShaderStages) -> BindGroupLayoutEntry {
|
||||
BindGroupLayoutEntry {
|
||||
binding,
|
||||
visibility,
|
||||
count: None,
|
||||
ty: BindingType::Buffer {
|
||||
ty: BufferBindingType::Uniform,
|
||||
has_dynamic_offset: true,
|
||||
min_binding_size: BufferSize::new(size),
|
||||
},
|
||||
pub(super) fn model(render_device: &RenderDevice) -> BindGroupLayoutEntryBuilder {
|
||||
GpuArrayBuffer::<MeshUniform>::binding_layout(render_device)
|
||||
.visibility(ShaderStages::VERTEX_FRAGMENT)
|
||||
}
|
||||
pub(super) fn skinning() -> BindGroupLayoutEntryBuilder {
|
||||
uniform_buffer_sized(true, BufferSize::new(JOINT_BUFFER_SIZE as u64))
|
||||
}
|
||||
pub(super) fn model(render_device: &RenderDevice, binding: u32) -> BindGroupLayoutEntry {
|
||||
GpuArrayBuffer::<MeshUniform>::binding_layout(
|
||||
binding,
|
||||
ShaderStages::VERTEX_FRAGMENT,
|
||||
render_device,
|
||||
)
|
||||
}
|
||||
pub(super) fn skinning(binding: u32) -> BindGroupLayoutEntry {
|
||||
buffer(binding, JOINT_BUFFER_SIZE as u64, ShaderStages::VERTEX)
|
||||
}
|
||||
pub(super) fn weights(binding: u32) -> BindGroupLayoutEntry {
|
||||
buffer(binding, MORPH_BUFFER_SIZE as u64, ShaderStages::VERTEX)
|
||||
}
|
||||
pub(super) fn targets(binding: u32) -> BindGroupLayoutEntry {
|
||||
BindGroupLayoutEntry {
|
||||
binding,
|
||||
visibility: ShaderStages::VERTEX,
|
||||
ty: BindingType::Texture {
|
||||
view_dimension: TextureViewDimension::D3,
|
||||
sample_type: TextureSampleType::Float { filterable: false },
|
||||
multisampled: false,
|
||||
},
|
||||
count: None,
|
||||
pub(super) fn weights() -> BindGroupLayoutEntryBuilder {
|
||||
uniform_buffer_sized(true, BufferSize::new(MORPH_BUFFER_SIZE as u64))
|
||||
}
|
||||
pub(super) fn targets() -> BindGroupLayoutEntryBuilder {
|
||||
texture_3d(TextureSampleType::Float { filterable: false })
|
||||
}
|
||||
}
|
||||
|
||||
/// Individual [`BindGroupEntry`]
|
||||
/// for bind groups.
|
||||
mod entry {
|
||||
|
@ -133,40 +111,52 @@ impl MeshLayouts {
|
|||
// ---------- create individual BindGroupLayouts ----------
|
||||
|
||||
fn model_only_layout(render_device: &RenderDevice) -> BindGroupLayout {
|
||||
render_device.create_bind_group_layout(&BindGroupLayoutDescriptor {
|
||||
entries: &[layout_entry::model(render_device, 0)],
|
||||
label: Some("mesh_layout"),
|
||||
})
|
||||
render_device.create_bind_group_layout(
|
||||
"mesh_layout",
|
||||
&BindGroupLayoutEntries::single(
|
||||
ShaderStages::empty(),
|
||||
layout_entry::model(render_device),
|
||||
),
|
||||
)
|
||||
}
|
||||
fn skinned_layout(render_device: &RenderDevice) -> BindGroupLayout {
|
||||
render_device.create_bind_group_layout(&BindGroupLayoutDescriptor {
|
||||
entries: &[
|
||||
layout_entry::model(render_device, 0),
|
||||
layout_entry::skinning(1),
|
||||
],
|
||||
label: Some("skinned_mesh_layout"),
|
||||
})
|
||||
render_device.create_bind_group_layout(
|
||||
"skinned_mesh_layout",
|
||||
&BindGroupLayoutEntries::with_indices(
|
||||
ShaderStages::VERTEX,
|
||||
(
|
||||
(0, layout_entry::model(render_device)),
|
||||
(1, layout_entry::skinning()),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
fn morphed_layout(render_device: &RenderDevice) -> BindGroupLayout {
|
||||
render_device.create_bind_group_layout(&BindGroupLayoutDescriptor {
|
||||
entries: &[
|
||||
layout_entry::model(render_device, 0),
|
||||
layout_entry::weights(2),
|
||||
layout_entry::targets(3),
|
||||
],
|
||||
label: Some("morphed_mesh_layout"),
|
||||
})
|
||||
render_device.create_bind_group_layout(
|
||||
"morphed_mesh_layout",
|
||||
&BindGroupLayoutEntries::with_indices(
|
||||
ShaderStages::VERTEX,
|
||||
(
|
||||
(0, layout_entry::model(render_device)),
|
||||
(2, layout_entry::weights()),
|
||||
(3, layout_entry::targets()),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
fn morphed_skinned_layout(render_device: &RenderDevice) -> BindGroupLayout {
|
||||
render_device.create_bind_group_layout(&BindGroupLayoutDescriptor {
|
||||
entries: &[
|
||||
layout_entry::model(render_device, 0),
|
||||
layout_entry::skinning(1),
|
||||
layout_entry::weights(2),
|
||||
layout_entry::targets(3),
|
||||
],
|
||||
label: Some("morphed_skinned_mesh_layout"),
|
||||
})
|
||||
render_device.create_bind_group_layout(
|
||||
"morphed_skinned_mesh_layout",
|
||||
&BindGroupLayoutEntries::with_indices(
|
||||
ShaderStages::VERTEX,
|
||||
(
|
||||
(0, layout_entry::model(render_device)),
|
||||
(1, layout_entry::skinning()),
|
||||
(2, layout_entry::weights()),
|
||||
(3, layout_entry::targets()),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
// ---------- BindGroup methods ----------
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use std::array;
|
||||
use std::{array, num::NonZeroU64};
|
||||
|
||||
use bevy_core_pipeline::{
|
||||
core_3d::ViewTransmissionTexture,
|
||||
|
@ -16,15 +16,24 @@ use bevy_render::{
|
|||
globals::{GlobalsBuffer, GlobalsUniform},
|
||||
render_asset::RenderAssets,
|
||||
render_resource::{
|
||||
BindGroup, BindGroupLayout, BindGroupLayoutDescriptor, BindGroupLayoutEntry, BindingType,
|
||||
BufferBindingType, DynamicBindGroupEntries, SamplerBindingType, ShaderStages, ShaderType,
|
||||
TextureFormat, TextureSampleType, TextureViewDimension,
|
||||
binding_types::{
|
||||
sampler, storage_buffer_read_only_sized, storage_buffer_sized, texture_2d,
|
||||
uniform_buffer, uniform_buffer_sized,
|
||||
},
|
||||
BindGroup, BindGroupLayout, BindGroupLayoutEntry, BindGroupLayoutEntryBuilder, BindingType,
|
||||
BufferBindingType, DynamicBindGroupEntries, DynamicBindGroupLayoutEntries,
|
||||
SamplerBindingType, ShaderStages, TextureFormat, TextureSampleType,
|
||||
},
|
||||
renderer::RenderDevice,
|
||||
texture::{BevyDefault, FallbackImageCubemap, FallbackImageMsaa, FallbackImageZero, Image},
|
||||
view::{Msaa, ViewUniform, ViewUniforms},
|
||||
};
|
||||
|
||||
#[cfg(all(feature = "webgl", target_arch = "wasm32"))]
|
||||
use bevy_render::render_resource::binding_types::texture_cube;
|
||||
#[cfg(any(not(feature = "webgl"), not(target_arch = "wasm32")))]
|
||||
use bevy_render::render_resource::binding_types::{texture_2d_array, texture_cube_array};
|
||||
|
||||
use crate::{
|
||||
environment_map, prepass, EnvironmentMapLight, FogMeta, GlobalLightMeta, GpuFog, GpuLights,
|
||||
GpuPointLights, LightMeta, MeshPipeline, MeshPipelineKey, ScreenSpaceAmbientOcclusionTextures,
|
||||
|
@ -144,190 +153,141 @@ impl From<Option<&ViewPrepassTextures>> for MeshPipelineViewLayoutKey {
|
|||
}
|
||||
}
|
||||
|
||||
fn buffer_layout(
|
||||
buffer_binding_type: BufferBindingType,
|
||||
has_dynamic_offset: bool,
|
||||
min_binding_size: Option<NonZeroU64>,
|
||||
) -> BindGroupLayoutEntryBuilder {
|
||||
match buffer_binding_type {
|
||||
BufferBindingType::Uniform => uniform_buffer_sized(has_dynamic_offset, min_binding_size),
|
||||
BufferBindingType::Storage { read_only } => {
|
||||
if read_only {
|
||||
storage_buffer_read_only_sized(has_dynamic_offset, min_binding_size)
|
||||
} else {
|
||||
storage_buffer_sized(has_dynamic_offset, min_binding_size)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the appropriate bind group layout vec based on the parameters
|
||||
fn layout_entries(
|
||||
clustered_forward_buffer_binding_type: BufferBindingType,
|
||||
layout_key: MeshPipelineViewLayoutKey,
|
||||
) -> Vec<BindGroupLayoutEntry> {
|
||||
let mut entries = vec![
|
||||
let mut entries = DynamicBindGroupLayoutEntries::new_with_indices(
|
||||
ShaderStages::FRAGMENT,
|
||||
(
|
||||
// View
|
||||
BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: ShaderStages::VERTEX | ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Buffer {
|
||||
ty: BufferBindingType::Uniform,
|
||||
has_dynamic_offset: true,
|
||||
min_binding_size: Some(ViewUniform::min_size()),
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
(
|
||||
0,
|
||||
uniform_buffer::<ViewUniform>(true).visibility(ShaderStages::VERTEX_FRAGMENT),
|
||||
),
|
||||
// Lights
|
||||
BindGroupLayoutEntry {
|
||||
binding: 1,
|
||||
visibility: ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Buffer {
|
||||
ty: BufferBindingType::Uniform,
|
||||
has_dynamic_offset: true,
|
||||
min_binding_size: Some(GpuLights::min_size()),
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
(1, uniform_buffer::<GpuLights>(true)),
|
||||
// Point Shadow Texture Cube Array
|
||||
BindGroupLayoutEntry {
|
||||
binding: 2,
|
||||
visibility: ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Texture {
|
||||
multisampled: false,
|
||||
sample_type: TextureSampleType::Depth,
|
||||
(
|
||||
2,
|
||||
#[cfg(any(not(feature = "webgl"), not(target_arch = "wasm32")))]
|
||||
view_dimension: TextureViewDimension::CubeArray,
|
||||
texture_cube_array(TextureSampleType::Depth),
|
||||
#[cfg(all(feature = "webgl", target_arch = "wasm32"))]
|
||||
view_dimension: TextureViewDimension::Cube,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
texture_cube(TextureSampleType::Depth),
|
||||
),
|
||||
// Point Shadow Texture Array Sampler
|
||||
BindGroupLayoutEntry {
|
||||
binding: 3,
|
||||
visibility: ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Sampler(SamplerBindingType::Comparison),
|
||||
count: None,
|
||||
},
|
||||
(3, sampler(SamplerBindingType::Comparison)),
|
||||
// Directional Shadow Texture Array
|
||||
BindGroupLayoutEntry {
|
||||
binding: 4,
|
||||
visibility: ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Texture {
|
||||
multisampled: false,
|
||||
sample_type: TextureSampleType::Depth,
|
||||
(
|
||||
4,
|
||||
#[cfg(any(not(feature = "webgl"), not(target_arch = "wasm32")))]
|
||||
view_dimension: TextureViewDimension::D2Array,
|
||||
texture_2d_array(TextureSampleType::Depth),
|
||||
#[cfg(all(feature = "webgl", target_arch = "wasm32"))]
|
||||
view_dimension: TextureViewDimension::D2,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
texture_2d(TextureSampleType::Depth),
|
||||
),
|
||||
// Directional Shadow Texture Array Sampler
|
||||
BindGroupLayoutEntry {
|
||||
binding: 5,
|
||||
visibility: ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Sampler(SamplerBindingType::Comparison),
|
||||
count: None,
|
||||
},
|
||||
(5, sampler(SamplerBindingType::Comparison)),
|
||||
// PointLights
|
||||
BindGroupLayoutEntry {
|
||||
binding: 6,
|
||||
visibility: ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Buffer {
|
||||
ty: clustered_forward_buffer_binding_type,
|
||||
has_dynamic_offset: false,
|
||||
min_binding_size: Some(GpuPointLights::min_size(
|
||||
(
|
||||
6,
|
||||
buffer_layout(
|
||||
clustered_forward_buffer_binding_type,
|
||||
false,
|
||||
Some(GpuPointLights::min_size(
|
||||
clustered_forward_buffer_binding_type,
|
||||
)),
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
),
|
||||
),
|
||||
// ClusteredLightIndexLists
|
||||
BindGroupLayoutEntry {
|
||||
binding: 7,
|
||||
visibility: ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Buffer {
|
||||
ty: clustered_forward_buffer_binding_type,
|
||||
has_dynamic_offset: false,
|
||||
min_binding_size: Some(ViewClusterBindings::min_size_cluster_light_index_lists(
|
||||
(
|
||||
7,
|
||||
buffer_layout(
|
||||
clustered_forward_buffer_binding_type,
|
||||
false,
|
||||
Some(ViewClusterBindings::min_size_cluster_light_index_lists(
|
||||
clustered_forward_buffer_binding_type,
|
||||
)),
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
),
|
||||
),
|
||||
// ClusterOffsetsAndCounts
|
||||
BindGroupLayoutEntry {
|
||||
binding: 8,
|
||||
visibility: ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Buffer {
|
||||
ty: clustered_forward_buffer_binding_type,
|
||||
has_dynamic_offset: false,
|
||||
min_binding_size: Some(ViewClusterBindings::min_size_cluster_offsets_and_counts(
|
||||
(
|
||||
8,
|
||||
buffer_layout(
|
||||
clustered_forward_buffer_binding_type,
|
||||
false,
|
||||
Some(ViewClusterBindings::min_size_cluster_offsets_and_counts(
|
||||
clustered_forward_buffer_binding_type,
|
||||
)),
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
),
|
||||
),
|
||||
// Globals
|
||||
BindGroupLayoutEntry {
|
||||
binding: 9,
|
||||
visibility: ShaderStages::VERTEX_FRAGMENT,
|
||||
ty: BindingType::Buffer {
|
||||
ty: BufferBindingType::Uniform,
|
||||
has_dynamic_offset: false,
|
||||
min_binding_size: Some(GlobalsUniform::min_size()),
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
(9, uniform_buffer::<GlobalsUniform>(false)),
|
||||
// Fog
|
||||
BindGroupLayoutEntry {
|
||||
binding: 10,
|
||||
visibility: ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Buffer {
|
||||
ty: BufferBindingType::Uniform,
|
||||
has_dynamic_offset: true,
|
||||
min_binding_size: Some(GpuFog::min_size()),
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
(10, uniform_buffer::<GpuFog>(true)),
|
||||
// Screen space ambient occlusion texture
|
||||
BindGroupLayoutEntry {
|
||||
binding: 11,
|
||||
visibility: ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Texture {
|
||||
multisampled: false,
|
||||
sample_type: TextureSampleType::Float { filterable: false },
|
||||
view_dimension: TextureViewDimension::D2,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
];
|
||||
(
|
||||
11,
|
||||
texture_2d(TextureSampleType::Float { filterable: false }),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// EnvironmentMapLight
|
||||
let environment_map_entries = environment_map::get_bind_group_layout_entries([12, 13, 14]);
|
||||
entries.extend_from_slice(&environment_map_entries);
|
||||
let environment_map_entries = environment_map::get_bind_group_layout_entries();
|
||||
entries = entries.extend_with_indices((
|
||||
(12, environment_map_entries[0]),
|
||||
(13, environment_map_entries[1]),
|
||||
(14, environment_map_entries[2]),
|
||||
));
|
||||
|
||||
// Tonemapping
|
||||
let tonemapping_lut_entries = get_lut_bind_group_layout_entries([15, 16]);
|
||||
entries.extend_from_slice(&tonemapping_lut_entries);
|
||||
let tonemapping_lut_entries = get_lut_bind_group_layout_entries();
|
||||
entries = entries.extend_with_indices((
|
||||
(15, tonemapping_lut_entries[0]),
|
||||
(16, tonemapping_lut_entries[1]),
|
||||
));
|
||||
|
||||
// Prepass
|
||||
if cfg!(any(not(feature = "webgl"), not(target_arch = "wasm32")))
|
||||
|| (cfg!(all(feature = "webgl", target_arch = "wasm32"))
|
||||
&& !layout_key.contains(MeshPipelineViewLayoutKey::MULTISAMPLED))
|
||||
{
|
||||
entries.extend_from_slice(&prepass::get_bind_group_layout_entries(
|
||||
[17, 18, 19, 20],
|
||||
layout_key,
|
||||
));
|
||||
for (entry, binding) in prepass::get_bind_group_layout_entries(layout_key)
|
||||
.iter()
|
||||
.zip([17, 18, 19, 20])
|
||||
{
|
||||
entries = entries.extend_with_indices(((binding as u32, *entry),));
|
||||
}
|
||||
}
|
||||
|
||||
// View Transmission Texture
|
||||
entries.extend_from_slice(&[
|
||||
BindGroupLayoutEntry {
|
||||
binding: 21,
|
||||
visibility: ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Texture {
|
||||
sample_type: TextureSampleType::Float { filterable: true },
|
||||
multisampled: false,
|
||||
view_dimension: TextureViewDimension::D2,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
BindGroupLayoutEntry {
|
||||
binding: 22,
|
||||
visibility: ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Sampler(SamplerBindingType::Filtering),
|
||||
count: None,
|
||||
},
|
||||
]);
|
||||
entries = entries.extend_with_indices((
|
||||
(
|
||||
21,
|
||||
texture_2d(TextureSampleType::Float { filterable: true }),
|
||||
),
|
||||
(22, sampler(SamplerBindingType::Filtering)),
|
||||
));
|
||||
|
||||
entries
|
||||
entries.to_vec()
|
||||
}
|
||||
|
||||
/// Generates all possible view layouts for the mesh pipeline, based on all combinations of
|
||||
|
@ -347,10 +307,8 @@ pub fn generate_view_layouts(
|
|||
.count();
|
||||
|
||||
MeshPipelineViewLayout {
|
||||
bind_group_layout: render_device.create_bind_group_layout(&BindGroupLayoutDescriptor {
|
||||
label: Some(key.label().as_str()),
|
||||
entries: &entries,
|
||||
}),
|
||||
bind_group_layout: render_device
|
||||
.create_bind_group_layout(key.label().as_str(), &entries),
|
||||
#[cfg(debug_assertions)]
|
||||
texture_count,
|
||||
}
|
||||
|
|
|
@ -20,7 +20,12 @@ use bevy_render::{
|
|||
globals::{GlobalsBuffer, GlobalsUniform},
|
||||
prelude::Camera,
|
||||
render_graph::{NodeRunError, RenderGraphApp, RenderGraphContext, ViewNode, ViewNodeRunner},
|
||||
render_resource::*,
|
||||
render_resource::{
|
||||
binding_types::{
|
||||
sampler, texture_2d, texture_depth_2d, texture_storage_2d, uniform_buffer,
|
||||
},
|
||||
*,
|
||||
},
|
||||
renderer::{RenderAdapter, RenderContext, RenderDevice, RenderQueue},
|
||||
texture::{CachedTexture, TextureCache},
|
||||
view::{Msaa, ViewUniform, ViewUniformOffset, ViewUniforms},
|
||||
|
@ -345,176 +350,58 @@ impl FromWorld for SsaoPipelines {
|
|||
..Default::default()
|
||||
});
|
||||
|
||||
let common_bind_group_layout =
|
||||
render_device.create_bind_group_layout(&BindGroupLayoutDescriptor {
|
||||
label: Some("ssao_common_bind_group_layout"),
|
||||
entries: &[
|
||||
BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: ShaderStages::COMPUTE,
|
||||
ty: BindingType::Sampler(SamplerBindingType::NonFiltering),
|
||||
count: None,
|
||||
},
|
||||
BindGroupLayoutEntry {
|
||||
binding: 1,
|
||||
visibility: ShaderStages::COMPUTE,
|
||||
ty: BindingType::Buffer {
|
||||
ty: BufferBindingType::Uniform,
|
||||
has_dynamic_offset: true,
|
||||
min_binding_size: Some(ViewUniform::min_size()),
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
],
|
||||
});
|
||||
let common_bind_group_layout = render_device.create_bind_group_layout(
|
||||
"ssao_common_bind_group_layout",
|
||||
&BindGroupLayoutEntries::sequential(
|
||||
ShaderStages::COMPUTE,
|
||||
(
|
||||
sampler(SamplerBindingType::NonFiltering),
|
||||
uniform_buffer::<ViewUniform>(true),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
let mip_texture_entry = BindGroupLayoutEntry {
|
||||
binding: 1,
|
||||
visibility: ShaderStages::COMPUTE,
|
||||
ty: BindingType::StorageTexture {
|
||||
access: StorageTextureAccess::WriteOnly,
|
||||
format: TextureFormat::R16Float,
|
||||
view_dimension: TextureViewDimension::D2,
|
||||
},
|
||||
count: None,
|
||||
};
|
||||
let preprocess_depth_bind_group_layout =
|
||||
render_device.create_bind_group_layout(&BindGroupLayoutDescriptor {
|
||||
label: Some("ssao_preprocess_depth_bind_group_layout"),
|
||||
entries: &[
|
||||
BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: ShaderStages::COMPUTE,
|
||||
ty: BindingType::Texture {
|
||||
sample_type: TextureSampleType::Depth,
|
||||
view_dimension: TextureViewDimension::D2,
|
||||
multisampled: false,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
mip_texture_entry,
|
||||
BindGroupLayoutEntry {
|
||||
binding: 2,
|
||||
..mip_texture_entry
|
||||
},
|
||||
BindGroupLayoutEntry {
|
||||
binding: 3,
|
||||
..mip_texture_entry
|
||||
},
|
||||
BindGroupLayoutEntry {
|
||||
binding: 4,
|
||||
..mip_texture_entry
|
||||
},
|
||||
BindGroupLayoutEntry {
|
||||
binding: 5,
|
||||
..mip_texture_entry
|
||||
},
|
||||
],
|
||||
});
|
||||
let preprocess_depth_bind_group_layout = render_device.create_bind_group_layout(
|
||||
"ssao_preprocess_depth_bind_group_layout",
|
||||
&BindGroupLayoutEntries::sequential(
|
||||
ShaderStages::COMPUTE,
|
||||
(
|
||||
texture_depth_2d(),
|
||||
texture_storage_2d(TextureFormat::R16Float, StorageTextureAccess::WriteOnly),
|
||||
texture_storage_2d(TextureFormat::R16Float, StorageTextureAccess::WriteOnly),
|
||||
texture_storage_2d(TextureFormat::R16Float, StorageTextureAccess::WriteOnly),
|
||||
texture_storage_2d(TextureFormat::R16Float, StorageTextureAccess::WriteOnly),
|
||||
texture_storage_2d(TextureFormat::R16Float, StorageTextureAccess::WriteOnly),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
let gtao_bind_group_layout =
|
||||
render_device.create_bind_group_layout(&BindGroupLayoutDescriptor {
|
||||
label: Some("ssao_gtao_bind_group_layout"),
|
||||
entries: &[
|
||||
BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: ShaderStages::COMPUTE,
|
||||
ty: BindingType::Texture {
|
||||
sample_type: TextureSampleType::Float { filterable: false },
|
||||
view_dimension: TextureViewDimension::D2,
|
||||
multisampled: false,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
BindGroupLayoutEntry {
|
||||
binding: 1,
|
||||
visibility: ShaderStages::COMPUTE,
|
||||
ty: BindingType::Texture {
|
||||
sample_type: TextureSampleType::Float { filterable: false },
|
||||
view_dimension: TextureViewDimension::D2,
|
||||
multisampled: false,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
BindGroupLayoutEntry {
|
||||
binding: 2,
|
||||
visibility: ShaderStages::COMPUTE,
|
||||
ty: BindingType::Texture {
|
||||
sample_type: TextureSampleType::Uint,
|
||||
view_dimension: TextureViewDimension::D2,
|
||||
multisampled: false,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
BindGroupLayoutEntry {
|
||||
binding: 3,
|
||||
visibility: ShaderStages::COMPUTE,
|
||||
ty: BindingType::StorageTexture {
|
||||
access: StorageTextureAccess::WriteOnly,
|
||||
format: TextureFormat::R16Float,
|
||||
view_dimension: TextureViewDimension::D2,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
BindGroupLayoutEntry {
|
||||
binding: 4,
|
||||
visibility: ShaderStages::COMPUTE,
|
||||
ty: BindingType::StorageTexture {
|
||||
access: StorageTextureAccess::WriteOnly,
|
||||
format: TextureFormat::R32Uint,
|
||||
view_dimension: TextureViewDimension::D2,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
BindGroupLayoutEntry {
|
||||
binding: 5,
|
||||
visibility: ShaderStages::COMPUTE,
|
||||
ty: BindingType::Buffer {
|
||||
ty: BufferBindingType::Uniform,
|
||||
has_dynamic_offset: false,
|
||||
min_binding_size: Some(GlobalsUniform::min_size()),
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
],
|
||||
});
|
||||
let gtao_bind_group_layout = render_device.create_bind_group_layout(
|
||||
"ssao_gtao_bind_group_layout",
|
||||
&BindGroupLayoutEntries::sequential(
|
||||
ShaderStages::COMPUTE,
|
||||
(
|
||||
texture_2d(TextureSampleType::Float { filterable: false }),
|
||||
texture_2d(TextureSampleType::Float { filterable: false }),
|
||||
texture_2d(TextureSampleType::Uint),
|
||||
texture_storage_2d(TextureFormat::R16Float, StorageTextureAccess::WriteOnly),
|
||||
texture_storage_2d(TextureFormat::R32Uint, StorageTextureAccess::WriteOnly),
|
||||
uniform_buffer::<GlobalsUniform>(false),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
let spatial_denoise_bind_group_layout =
|
||||
render_device.create_bind_group_layout(&BindGroupLayoutDescriptor {
|
||||
label: Some("ssao_spatial_denoise_bind_group_layout"),
|
||||
entries: &[
|
||||
BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: ShaderStages::COMPUTE,
|
||||
ty: BindingType::Texture {
|
||||
sample_type: TextureSampleType::Float { filterable: false },
|
||||
view_dimension: TextureViewDimension::D2,
|
||||
multisampled: false,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
BindGroupLayoutEntry {
|
||||
binding: 1,
|
||||
visibility: ShaderStages::COMPUTE,
|
||||
ty: BindingType::Texture {
|
||||
sample_type: TextureSampleType::Uint,
|
||||
view_dimension: TextureViewDimension::D2,
|
||||
multisampled: false,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
BindGroupLayoutEntry {
|
||||
binding: 2,
|
||||
visibility: ShaderStages::COMPUTE,
|
||||
ty: BindingType::StorageTexture {
|
||||
access: StorageTextureAccess::WriteOnly,
|
||||
format: TextureFormat::R16Float,
|
||||
view_dimension: TextureViewDimension::D2,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
],
|
||||
});
|
||||
let spatial_denoise_bind_group_layout = render_device.create_bind_group_layout(
|
||||
"ssao_spatial_denoise_bind_group_layout",
|
||||
&BindGroupLayoutEntries::sequential(
|
||||
ShaderStages::COMPUTE,
|
||||
(
|
||||
texture_2d(TextureSampleType::Float { filterable: false }),
|
||||
texture_2d(TextureSampleType::Uint),
|
||||
texture_storage_2d(TextureFormat::R16Float, StorageTextureAccess::WriteOnly),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
let preprocess_depth_pipeline =
|
||||
pipeline_cache.queue_compute_pipeline(ComputePipelineDescriptor {
|
||||
|
|
|
@ -10,7 +10,7 @@ pub use bevy_render_macros::AsBindGroup;
|
|||
use bevy_utils::thiserror::Error;
|
||||
use encase::ShaderType;
|
||||
use std::ops::Deref;
|
||||
use wgpu::{BindGroupEntry, BindGroupLayoutDescriptor, BindGroupLayoutEntry, BindingResource};
|
||||
use wgpu::{BindGroupEntry, BindGroupLayoutEntry, BindingResource};
|
||||
|
||||
define_atomic_id!(BindGroupId);
|
||||
render_resource_wrapper!(ErasedBindGroup, wgpu::BindGroup);
|
||||
|
@ -313,10 +313,10 @@ pub trait AsBindGroup {
|
|||
where
|
||||
Self: Sized,
|
||||
{
|
||||
render_device.create_bind_group_layout(&BindGroupLayoutDescriptor {
|
||||
label: Self::label(),
|
||||
entries: &Self::bind_group_layout_entries(render_device),
|
||||
})
|
||||
render_device.create_bind_group_layout(
|
||||
Self::label(),
|
||||
&Self::bind_group_layout_entries(render_device),
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns a vec of bind group layout entries
|
||||
|
|
|
@ -0,0 +1,546 @@
|
|||
use bevy_utils::all_tuples_with_size;
|
||||
use std::num::NonZeroU32;
|
||||
use wgpu::{BindGroupLayoutEntry, BindingType, ShaderStages};
|
||||
|
||||
/// Helper for constructing bind group layouts.
|
||||
///
|
||||
/// Allows constructing the layout's entries as:
|
||||
/// ```ignore
|
||||
/// let layout = render_device.create_bind_group_layout(
|
||||
/// "my_bind_group_layout",
|
||||
/// &BindGroupLayoutEntries::with_indices(
|
||||
/// // The layout entries will only be visible in the fragment stage
|
||||
/// ShaderStages::FRAGMENT,
|
||||
/// (
|
||||
/// // Screen texture
|
||||
/// (2, tepxture_2d(TextureSampleType::Float { filterable: true })),
|
||||
/// // Sampler
|
||||
/// (3, sampler(SamplerBindingType::Filtering)),
|
||||
/// ),
|
||||
/// ),
|
||||
/// );
|
||||
/// ```
|
||||
///
|
||||
/// instead of
|
||||
///
|
||||
/// ```ignore
|
||||
/// let layout = render_device.create_bind_group_layout(
|
||||
/// "my_bind_group_layout",
|
||||
/// &[
|
||||
/// // Screen texture
|
||||
/// BindGroupLayoutEntry {
|
||||
/// binding: 2,
|
||||
/// visibility: ShaderStages::FRAGMENT,
|
||||
/// ty: BindingType::Texture {
|
||||
/// sample_type: TextureSampleType::Float { filterable: true },
|
||||
/// view_dimension: TextureViewDimension::D2,
|
||||
/// multisampled: false,
|
||||
/// },
|
||||
/// count: None,
|
||||
/// },
|
||||
/// // Sampler
|
||||
/// BindGroupLayoutEntry {
|
||||
/// binding: 3,
|
||||
/// visibility: ShaderStages::FRAGMENT,
|
||||
/// ty: BindingType::Sampler(SamplerBindingType::Filtering),
|
||||
/// count: None,
|
||||
/// },
|
||||
/// ],
|
||||
/// );
|
||||
/// ```
|
||||
///
|
||||
/// or
|
||||
///
|
||||
/// ```ignore
|
||||
/// render_device.create_bind_group_layout(
|
||||
/// "my_bind_group_layout",
|
||||
/// &BindGroupLayoutEntries::sequential(
|
||||
/// ShaderStages::FRAGMENT,
|
||||
/// (
|
||||
/// // Screen texture
|
||||
/// texture_2d(TextureSampleType::Float { filterable: true }),
|
||||
/// // Sampler
|
||||
/// sampler(SamplerBindingType::Filtering),
|
||||
/// ),
|
||||
/// ),
|
||||
/// );
|
||||
/// ```
|
||||
///
|
||||
/// instead of
|
||||
///
|
||||
/// ```ignore
|
||||
/// let layout = render_device.create_bind_group_layout(
|
||||
/// "my_bind_group_layout",
|
||||
/// &[
|
||||
/// // Screen texture
|
||||
/// BindGroupLayoutEntry {
|
||||
/// binding: 0,
|
||||
/// visibility: ShaderStages::FRAGMENT,
|
||||
/// ty: BindingType::Texture {
|
||||
/// sample_type: TextureSampleType::Float { filterable: true },
|
||||
/// view_dimension: TextureViewDimension::D2,
|
||||
/// multisampled: false,
|
||||
/// },
|
||||
/// count: None,
|
||||
/// },
|
||||
/// // Sampler
|
||||
/// BindGroupLayoutEntry {
|
||||
/// binding: 1,
|
||||
/// visibility: ShaderStages::FRAGMENT,
|
||||
/// ty: BindingType::Sampler(SamplerBindingType::Filtering),
|
||||
/// count: None,
|
||||
/// },
|
||||
/// ],
|
||||
/// );
|
||||
/// ```
|
||||
///
|
||||
/// or
|
||||
///
|
||||
/// ```ignore
|
||||
/// render_device.create_bind_group_layout(
|
||||
/// "my_bind_group_layout",
|
||||
/// &BindGroupLayoutEntries::single(
|
||||
/// ShaderStages::FRAGMENT,
|
||||
/// texture_2d(TextureSampleType::Float { filterable: true }),
|
||||
/// ),
|
||||
/// );
|
||||
/// ```
|
||||
///
|
||||
/// instead of
|
||||
///
|
||||
/// ```ignore
|
||||
/// let layout = render_device.create_bind_group_layout(
|
||||
/// "my_bind_group_layout",
|
||||
/// &[
|
||||
/// BindGroupLayoutEntry {
|
||||
/// binding: 0,
|
||||
/// visibility: ShaderStages::FRAGMENT,
|
||||
/// ty: BindingType::Texture {
|
||||
/// sample_type: TextureSampleType::Float { filterable: true },
|
||||
/// view_dimension: TextureViewDimension::D2,
|
||||
/// multisampled: false,
|
||||
/// },
|
||||
/// count: None,
|
||||
/// },
|
||||
/// ],
|
||||
/// );
|
||||
/// ```
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct BindGroupLayoutEntryBuilder {
|
||||
ty: BindingType,
|
||||
visibility: Option<ShaderStages>,
|
||||
count: Option<NonZeroU32>,
|
||||
}
|
||||
|
||||
impl BindGroupLayoutEntryBuilder {
|
||||
pub fn visibility(mut self, visibility: ShaderStages) -> Self {
|
||||
self.visibility = Some(visibility);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn count(mut self, count: NonZeroU32) -> Self {
|
||||
self.count = Some(count);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(
|
||||
&self,
|
||||
binding: u32,
|
||||
default_visibility: ShaderStages,
|
||||
) -> wgpu::BindGroupLayoutEntry {
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding,
|
||||
ty: self.ty,
|
||||
visibility: self.visibility.unwrap_or(default_visibility),
|
||||
count: self.count,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BindGroupLayoutEntries<const N: usize> {
|
||||
entries: [wgpu::BindGroupLayoutEntry; N],
|
||||
}
|
||||
|
||||
impl<const N: usize> BindGroupLayoutEntries<N> {
|
||||
#[inline]
|
||||
pub fn sequential(
|
||||
default_visibility: ShaderStages,
|
||||
entries_ext: impl IntoBindGroupLayoutEntryBuilderArray<N>,
|
||||
) -> Self {
|
||||
let mut i = 0;
|
||||
Self {
|
||||
entries: entries_ext.into_array().map(|entry| {
|
||||
let binding = i;
|
||||
i += 1;
|
||||
entry.build(binding, default_visibility)
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn with_indices(
|
||||
default_visibility: ShaderStages,
|
||||
indexed_entries: impl IntoIndexedBindGroupLayoutEntryBuilderArray<N>,
|
||||
) -> Self {
|
||||
Self {
|
||||
entries: indexed_entries
|
||||
.into_array()
|
||||
.map(|(binding, entry)| entry.build(binding, default_visibility)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl BindGroupLayoutEntries<1> {
|
||||
pub fn single(
|
||||
visibility: ShaderStages,
|
||||
resource: impl IntoBindGroupLayoutEntryBuilder,
|
||||
) -> [BindGroupLayoutEntry; 1] {
|
||||
[resource
|
||||
.into_bind_group_layout_entry_builder()
|
||||
.build(0, visibility)]
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> std::ops::Deref for BindGroupLayoutEntries<N> {
|
||||
type Target = [wgpu::BindGroupLayoutEntry];
|
||||
fn deref(&self) -> &[wgpu::BindGroupLayoutEntry] {
|
||||
&self.entries
|
||||
}
|
||||
}
|
||||
|
||||
pub trait IntoBindGroupLayoutEntryBuilder {
|
||||
fn into_bind_group_layout_entry_builder(self) -> BindGroupLayoutEntryBuilder;
|
||||
}
|
||||
|
||||
impl IntoBindGroupLayoutEntryBuilder for BindingType {
|
||||
fn into_bind_group_layout_entry_builder(self) -> BindGroupLayoutEntryBuilder {
|
||||
BindGroupLayoutEntryBuilder {
|
||||
ty: self,
|
||||
visibility: None,
|
||||
count: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoBindGroupLayoutEntryBuilder for wgpu::BindGroupLayoutEntry {
|
||||
fn into_bind_group_layout_entry_builder(self) -> BindGroupLayoutEntryBuilder {
|
||||
if self.binding != u32::MAX {
|
||||
bevy_log::warn!("The BindGroupLayoutEntries api ignores the binding index when converting a raw wgpu::BindGroupLayoutEntry. You can ignore this warning by setting it to u32::MAX.");
|
||||
}
|
||||
BindGroupLayoutEntryBuilder {
|
||||
ty: self.ty,
|
||||
visibility: Some(self.visibility),
|
||||
count: self.count,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoBindGroupLayoutEntryBuilder for BindGroupLayoutEntryBuilder {
|
||||
fn into_bind_group_layout_entry_builder(self) -> BindGroupLayoutEntryBuilder {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
pub trait IntoBindGroupLayoutEntryBuilderArray<const N: usize> {
|
||||
fn into_array(self) -> [BindGroupLayoutEntryBuilder; N];
|
||||
}
|
||||
macro_rules! impl_to_binding_type_slice {
|
||||
($N: expr, $(($T: ident, $I: ident)),*) => {
|
||||
impl<$($T: IntoBindGroupLayoutEntryBuilder),*> IntoBindGroupLayoutEntryBuilderArray<$N> for ($($T,)*) {
|
||||
#[inline]
|
||||
fn into_array(self) -> [BindGroupLayoutEntryBuilder; $N] {
|
||||
let ($($I,)*) = self;
|
||||
[$($I.into_bind_group_layout_entry_builder(), )*]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
all_tuples_with_size!(impl_to_binding_type_slice, 1, 32, T, s);
|
||||
|
||||
pub trait IntoIndexedBindGroupLayoutEntryBuilderArray<const N: usize> {
|
||||
fn into_array(self) -> [(u32, BindGroupLayoutEntryBuilder); N];
|
||||
}
|
||||
macro_rules! impl_to_indexed_binding_type_slice {
|
||||
($N: expr, $(($T: ident, $S: ident, $I: ident)),*) => {
|
||||
impl<$($T: IntoBindGroupLayoutEntryBuilder),*> IntoIndexedBindGroupLayoutEntryBuilderArray<$N> for ($((u32, $T),)*) {
|
||||
#[inline]
|
||||
fn into_array(self) -> [(u32, BindGroupLayoutEntryBuilder); $N] {
|
||||
let ($(($S, $I),)*) = self;
|
||||
[$(($S, $I.into_bind_group_layout_entry_builder())), *]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
all_tuples_with_size!(impl_to_indexed_binding_type_slice, 1, 32, T, n, s);
|
||||
|
||||
impl<const N: usize> IntoBindGroupLayoutEntryBuilderArray<N> for [BindGroupLayoutEntry; N] {
|
||||
fn into_array(self) -> [BindGroupLayoutEntryBuilder; N] {
|
||||
self.map(|x| x.into_bind_group_layout_entry_builder())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DynamicBindGroupLayoutEntries {
|
||||
default_visibility: ShaderStages,
|
||||
entries: Vec<BindGroupLayoutEntry>,
|
||||
}
|
||||
|
||||
impl DynamicBindGroupLayoutEntries {
|
||||
pub fn sequential<const N: usize>(
|
||||
default_visibility: ShaderStages,
|
||||
entries: impl IntoBindGroupLayoutEntryBuilderArray<N>,
|
||||
) -> Self {
|
||||
Self {
|
||||
default_visibility,
|
||||
entries: entries
|
||||
.into_array()
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map(|(ix, resource)| resource.build(ix as u32, default_visibility))
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn extend_sequential<const N: usize>(
|
||||
mut self,
|
||||
entries: impl IntoBindGroupLayoutEntryBuilderArray<N>,
|
||||
) -> Self {
|
||||
let start = self.entries.last().unwrap().binding + 1;
|
||||
self.entries.extend(
|
||||
entries
|
||||
.into_array()
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map(|(ix, resource)| resource.build(start + ix as u32, self.default_visibility)),
|
||||
);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn new_with_indices<const N: usize>(
|
||||
default_visibility: ShaderStages,
|
||||
entries: impl IntoIndexedBindGroupLayoutEntryBuilderArray<N>,
|
||||
) -> Self {
|
||||
Self {
|
||||
default_visibility,
|
||||
entries: entries
|
||||
.into_array()
|
||||
.into_iter()
|
||||
.map(|(binding, resource)| resource.build(binding, default_visibility))
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn extend_with_indices<const N: usize>(
|
||||
mut self,
|
||||
entries: impl IntoIndexedBindGroupLayoutEntryBuilderArray<N>,
|
||||
) -> Self {
|
||||
self.entries.extend(
|
||||
entries
|
||||
.into_array()
|
||||
.into_iter()
|
||||
.map(|(binding, resource)| resource.build(binding, self.default_visibility)),
|
||||
);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Deref for DynamicBindGroupLayoutEntries {
|
||||
type Target = [BindGroupLayoutEntry];
|
||||
|
||||
fn deref(&self) -> &[BindGroupLayoutEntry] {
|
||||
&self.entries
|
||||
}
|
||||
}
|
||||
|
||||
pub mod binding_types {
|
||||
use crate::render_resource::{
|
||||
BufferBindingType, SamplerBindingType, TextureSampleType, TextureViewDimension,
|
||||
};
|
||||
use encase::ShaderType;
|
||||
use std::num::NonZeroU64;
|
||||
use wgpu::{BindingType, StorageTextureAccess, TextureFormat};
|
||||
|
||||
use super::*;
|
||||
|
||||
pub fn storage_buffer<T: ShaderType>(has_dynamic_offset: bool) -> BindGroupLayoutEntryBuilder {
|
||||
storage_buffer_sized(has_dynamic_offset, Some(T::min_size()))
|
||||
}
|
||||
|
||||
pub fn storage_buffer_sized(
|
||||
has_dynamic_offset: bool,
|
||||
min_binding_size: Option<NonZeroU64>,
|
||||
) -> BindGroupLayoutEntryBuilder {
|
||||
BindingType::Buffer {
|
||||
ty: BufferBindingType::Storage { read_only: false },
|
||||
has_dynamic_offset,
|
||||
min_binding_size,
|
||||
}
|
||||
.into_bind_group_layout_entry_builder()
|
||||
}
|
||||
|
||||
pub fn storage_buffer_read_only<T: ShaderType>(
|
||||
has_dynamic_offset: bool,
|
||||
) -> BindGroupLayoutEntryBuilder {
|
||||
storage_buffer_read_only_sized(has_dynamic_offset, Some(T::min_size()))
|
||||
}
|
||||
|
||||
pub fn storage_buffer_read_only_sized(
|
||||
has_dynamic_offset: bool,
|
||||
min_binding_size: Option<NonZeroU64>,
|
||||
) -> BindGroupLayoutEntryBuilder {
|
||||
BindingType::Buffer {
|
||||
ty: BufferBindingType::Storage { read_only: true },
|
||||
has_dynamic_offset,
|
||||
min_binding_size,
|
||||
}
|
||||
.into_bind_group_layout_entry_builder()
|
||||
}
|
||||
|
||||
pub fn uniform_buffer<T: ShaderType>(has_dynamic_offset: bool) -> BindGroupLayoutEntryBuilder {
|
||||
uniform_buffer_sized(has_dynamic_offset, Some(T::min_size()))
|
||||
}
|
||||
|
||||
pub fn uniform_buffer_sized(
|
||||
has_dynamic_offset: bool,
|
||||
min_binding_size: Option<NonZeroU64>,
|
||||
) -> BindGroupLayoutEntryBuilder {
|
||||
BindingType::Buffer {
|
||||
ty: BufferBindingType::Uniform,
|
||||
has_dynamic_offset,
|
||||
min_binding_size,
|
||||
}
|
||||
.into_bind_group_layout_entry_builder()
|
||||
}
|
||||
|
||||
pub fn texture_2d(sample_type: TextureSampleType) -> BindGroupLayoutEntryBuilder {
|
||||
BindingType::Texture {
|
||||
sample_type,
|
||||
view_dimension: TextureViewDimension::D2,
|
||||
multisampled: false,
|
||||
}
|
||||
.into_bind_group_layout_entry_builder()
|
||||
}
|
||||
|
||||
pub fn texture_2d_multisampled(sample_type: TextureSampleType) -> BindGroupLayoutEntryBuilder {
|
||||
BindingType::Texture {
|
||||
sample_type,
|
||||
view_dimension: TextureViewDimension::D2,
|
||||
multisampled: true,
|
||||
}
|
||||
.into_bind_group_layout_entry_builder()
|
||||
}
|
||||
|
||||
pub fn texture_2d_array(sample_type: TextureSampleType) -> BindGroupLayoutEntryBuilder {
|
||||
BindingType::Texture {
|
||||
sample_type,
|
||||
view_dimension: TextureViewDimension::D2Array,
|
||||
multisampled: false,
|
||||
}
|
||||
.into_bind_group_layout_entry_builder()
|
||||
}
|
||||
|
||||
pub fn texture_2d_array_multisampled(
|
||||
sample_type: TextureSampleType,
|
||||
) -> BindGroupLayoutEntryBuilder {
|
||||
BindingType::Texture {
|
||||
sample_type,
|
||||
view_dimension: TextureViewDimension::D2Array,
|
||||
multisampled: true,
|
||||
}
|
||||
.into_bind_group_layout_entry_builder()
|
||||
}
|
||||
|
||||
pub fn texture_depth_2d() -> BindGroupLayoutEntryBuilder {
|
||||
texture_2d(TextureSampleType::Depth).into_bind_group_layout_entry_builder()
|
||||
}
|
||||
|
||||
pub fn texture_depth_2d_multisampled() -> BindGroupLayoutEntryBuilder {
|
||||
texture_2d_multisampled(TextureSampleType::Depth).into_bind_group_layout_entry_builder()
|
||||
}
|
||||
|
||||
pub fn texture_cube(sample_type: TextureSampleType) -> BindGroupLayoutEntryBuilder {
|
||||
BindingType::Texture {
|
||||
sample_type,
|
||||
view_dimension: TextureViewDimension::Cube,
|
||||
multisampled: false,
|
||||
}
|
||||
.into_bind_group_layout_entry_builder()
|
||||
}
|
||||
|
||||
pub fn texture_cube_multisampled(
|
||||
sample_type: TextureSampleType,
|
||||
) -> BindGroupLayoutEntryBuilder {
|
||||
BindingType::Texture {
|
||||
sample_type,
|
||||
view_dimension: TextureViewDimension::Cube,
|
||||
multisampled: true,
|
||||
}
|
||||
.into_bind_group_layout_entry_builder()
|
||||
}
|
||||
|
||||
pub fn texture_cube_array(sample_type: TextureSampleType) -> BindGroupLayoutEntryBuilder {
|
||||
BindingType::Texture {
|
||||
sample_type,
|
||||
view_dimension: TextureViewDimension::CubeArray,
|
||||
multisampled: false,
|
||||
}
|
||||
.into_bind_group_layout_entry_builder()
|
||||
}
|
||||
|
||||
pub fn texture_cube_array_multisampled(
|
||||
sample_type: TextureSampleType,
|
||||
) -> BindGroupLayoutEntryBuilder {
|
||||
BindingType::Texture {
|
||||
sample_type,
|
||||
view_dimension: TextureViewDimension::CubeArray,
|
||||
multisampled: true,
|
||||
}
|
||||
.into_bind_group_layout_entry_builder()
|
||||
}
|
||||
|
||||
pub fn texture_3d(sample_type: TextureSampleType) -> BindGroupLayoutEntryBuilder {
|
||||
BindingType::Texture {
|
||||
sample_type,
|
||||
view_dimension: TextureViewDimension::D3,
|
||||
multisampled: false,
|
||||
}
|
||||
.into_bind_group_layout_entry_builder()
|
||||
}
|
||||
|
||||
pub fn texture_3d_multisampled(sample_type: TextureSampleType) -> BindGroupLayoutEntryBuilder {
|
||||
BindingType::Texture {
|
||||
sample_type,
|
||||
view_dimension: TextureViewDimension::D3,
|
||||
multisampled: true,
|
||||
}
|
||||
.into_bind_group_layout_entry_builder()
|
||||
}
|
||||
|
||||
pub fn sampler(sampler_binding_type: SamplerBindingType) -> BindGroupLayoutEntryBuilder {
|
||||
BindingType::Sampler(sampler_binding_type).into_bind_group_layout_entry_builder()
|
||||
}
|
||||
|
||||
pub fn texture_storage_2d(
|
||||
format: TextureFormat,
|
||||
access: StorageTextureAccess,
|
||||
) -> BindGroupLayoutEntryBuilder {
|
||||
BindingType::StorageTexture {
|
||||
access,
|
||||
format,
|
||||
view_dimension: TextureViewDimension::D2,
|
||||
}
|
||||
.into_bind_group_layout_entry_builder()
|
||||
}
|
||||
|
||||
pub fn texture_storage_2d_array(
|
||||
format: TextureFormat,
|
||||
access: StorageTextureAccess,
|
||||
) -> BindGroupLayoutEntryBuilder {
|
||||
BindingType::StorageTexture {
|
||||
access,
|
||||
format,
|
||||
view_dimension: TextureViewDimension::D2Array,
|
||||
}
|
||||
.into_bind_group_layout_entry_builder()
|
||||
}
|
||||
}
|
|
@ -1,4 +1,7 @@
|
|||
use super::StorageBuffer;
|
||||
use super::{
|
||||
binding_types::{storage_buffer_read_only, uniform_buffer_sized},
|
||||
BindGroupLayoutEntryBuilder, StorageBuffer,
|
||||
};
|
||||
use crate::{
|
||||
render_resource::batched_uniform_buffer::BatchedUniformBuffer,
|
||||
renderer::{RenderDevice, RenderQueue},
|
||||
|
@ -7,7 +10,7 @@ use bevy_ecs::{prelude::Component, system::Resource};
|
|||
use bevy_utils::nonmax::NonMaxU32;
|
||||
use encase::{private::WriteInto, ShaderSize, ShaderType};
|
||||
use std::{marker::PhantomData, mem};
|
||||
use wgpu::{BindGroupLayoutEntry, BindingResource, BindingType, BufferBindingType, ShaderStages};
|
||||
use wgpu::BindingResource;
|
||||
|
||||
/// Trait for types able to go in a [`GpuArrayBuffer`].
|
||||
pub trait GpuArrayBufferable: ShaderType + ShaderSize + WriteInto + Clone {}
|
||||
|
@ -74,30 +77,16 @@ impl<T: GpuArrayBufferable> GpuArrayBuffer<T> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn binding_layout(
|
||||
binding: u32,
|
||||
visibility: ShaderStages,
|
||||
device: &RenderDevice,
|
||||
) -> BindGroupLayoutEntry {
|
||||
BindGroupLayoutEntry {
|
||||
binding,
|
||||
visibility,
|
||||
ty: if device.limits().max_storage_buffers_per_shader_stage == 0 {
|
||||
BindingType::Buffer {
|
||||
ty: BufferBindingType::Uniform,
|
||||
has_dynamic_offset: true,
|
||||
pub fn binding_layout(device: &RenderDevice) -> BindGroupLayoutEntryBuilder {
|
||||
if device.limits().max_storage_buffers_per_shader_stage == 0 {
|
||||
uniform_buffer_sized(
|
||||
true,
|
||||
// BatchedUniformBuffer uses a MaxCapacityArray that is runtime-sized, so we use
|
||||
// None here and let wgpu figure out the size.
|
||||
min_binding_size: None,
|
||||
}
|
||||
None,
|
||||
)
|
||||
} else {
|
||||
BindingType::Buffer {
|
||||
ty: BufferBindingType::Storage { read_only: true },
|
||||
has_dynamic_offset: false,
|
||||
min_binding_size: Some(T::min_size()),
|
||||
}
|
||||
},
|
||||
count: None,
|
||||
storage_buffer_read_only::<T>(false)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ mod batched_uniform_buffer;
|
|||
mod bind_group;
|
||||
mod bind_group_entries;
|
||||
mod bind_group_layout;
|
||||
mod bind_group_layout_entries;
|
||||
mod buffer;
|
||||
mod buffer_vec;
|
||||
mod gpu_array_buffer;
|
||||
|
@ -17,6 +18,7 @@ mod uniform_buffer;
|
|||
pub use bind_group::*;
|
||||
pub use bind_group_entries::*;
|
||||
pub use bind_group_layout::*;
|
||||
pub use bind_group_layout_entries::*;
|
||||
pub use buffer::*;
|
||||
pub use buffer_vec::*;
|
||||
pub use gpu_array_buffer::*;
|
||||
|
|
|
@ -4,7 +4,8 @@ use crate::render_resource::{
|
|||
};
|
||||
use bevy_ecs::system::Resource;
|
||||
use wgpu::{
|
||||
util::DeviceExt, BindGroupDescriptor, BindGroupEntry, BufferAsyncError, BufferBindingType,
|
||||
util::DeviceExt, BindGroupDescriptor, BindGroupEntry, BindGroupLayoutDescriptor,
|
||||
BindGroupLayoutEntry, BufferAsyncError, BufferBindingType,
|
||||
};
|
||||
|
||||
use super::RenderQueue;
|
||||
|
@ -100,11 +101,18 @@ impl RenderDevice {
|
|||
|
||||
/// Creates a [`BindGroupLayout`](wgpu::BindGroupLayout).
|
||||
#[inline]
|
||||
pub fn create_bind_group_layout(
|
||||
pub fn create_bind_group_layout<'a>(
|
||||
&self,
|
||||
desc: &wgpu::BindGroupLayoutDescriptor,
|
||||
label: impl Into<wgpu::Label<'a>>,
|
||||
entries: &'a [BindGroupLayoutEntry],
|
||||
) -> BindGroupLayout {
|
||||
BindGroupLayout::from(self.device.create_bind_group_layout(desc))
|
||||
BindGroupLayout::from(
|
||||
self.device
|
||||
.create_bind_group_layout(&BindGroupLayoutDescriptor {
|
||||
label: label.into(),
|
||||
entries,
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
/// Creates a [`PipelineLayout`](wgpu::PipelineLayout).
|
||||
|
|
|
@ -15,9 +15,9 @@ use wgpu::{
|
|||
use crate::{
|
||||
prelude::{Image, Shader},
|
||||
render_resource::{
|
||||
BindGroup, BindGroupLayout, Buffer, CachedRenderPipelineId, FragmentState, PipelineCache,
|
||||
RenderPipelineDescriptor, SpecializedRenderPipeline, SpecializedRenderPipelines, Texture,
|
||||
VertexState,
|
||||
binding_types::texture_2d, BindGroup, BindGroupLayout, BindGroupLayoutEntries, Buffer,
|
||||
CachedRenderPipelineId, FragmentState, PipelineCache, RenderPipelineDescriptor,
|
||||
SpecializedRenderPipeline, SpecializedRenderPipelines, Texture, VertexState,
|
||||
},
|
||||
renderer::RenderDevice,
|
||||
texture::TextureFormatPixelInfo,
|
||||
|
@ -201,19 +201,13 @@ impl FromWorld for ScreenshotToScreenPipeline {
|
|||
fn from_world(render_world: &mut World) -> Self {
|
||||
let device = render_world.resource::<RenderDevice>();
|
||||
|
||||
let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
label: Some("screenshot-to-screen-bgl"),
|
||||
entries: &[wgpu::BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStages::FRAGMENT,
|
||||
ty: wgpu::BindingType::Texture {
|
||||
sample_type: wgpu::TextureSampleType::Float { filterable: false },
|
||||
view_dimension: wgpu::TextureViewDimension::D2,
|
||||
multisampled: false,
|
||||
},
|
||||
count: None,
|
||||
}],
|
||||
});
|
||||
let bind_group_layout = device.create_bind_group_layout(
|
||||
"screenshot-to-screen-bgl",
|
||||
&BindGroupLayoutEntries::single(
|
||||
wgpu::ShaderStages::FRAGMENT,
|
||||
texture_2d(wgpu::TextureSampleType::Float { filterable: false }),
|
||||
),
|
||||
);
|
||||
|
||||
Self { bind_group_layout }
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ use bevy_render::{
|
|||
mesh::{GpuBufferInfo, Mesh, MeshVertexBufferLayout},
|
||||
render_asset::RenderAssets,
|
||||
render_phase::{PhaseItem, RenderCommand, RenderCommandResult, TrackedRenderPass},
|
||||
render_resource::*,
|
||||
render_resource::{binding_types::uniform_buffer, *},
|
||||
renderer::{RenderDevice, RenderQueue},
|
||||
texture::{
|
||||
BevyDefault, DefaultImageSampler, GpuImage, Image, ImageSampler, TextureFormatPixelInfo,
|
||||
|
@ -256,41 +256,25 @@ impl FromWorld for Mesh2dPipeline {
|
|||
)> = SystemState::new(world);
|
||||
let (render_device, render_queue, default_sampler) = system_state.get_mut(world);
|
||||
let render_device = render_device.into_inner();
|
||||
let view_layout = render_device.create_bind_group_layout(&BindGroupLayoutDescriptor {
|
||||
entries: &[
|
||||
// View
|
||||
BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: ShaderStages::VERTEX | ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Buffer {
|
||||
ty: BufferBindingType::Uniform,
|
||||
has_dynamic_offset: true,
|
||||
min_binding_size: Some(ViewUniform::min_size()),
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
BindGroupLayoutEntry {
|
||||
binding: 1,
|
||||
visibility: ShaderStages::VERTEX_FRAGMENT,
|
||||
ty: BindingType::Buffer {
|
||||
ty: BufferBindingType::Uniform,
|
||||
has_dynamic_offset: false,
|
||||
min_binding_size: Some(GlobalsUniform::min_size()),
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
],
|
||||
label: Some("mesh2d_view_layout"),
|
||||
});
|
||||
|
||||
let mesh_layout = render_device.create_bind_group_layout(&BindGroupLayoutDescriptor {
|
||||
entries: &[GpuArrayBuffer::<Mesh2dUniform>::binding_layout(
|
||||
0,
|
||||
let view_layout = render_device.create_bind_group_layout(
|
||||
"mesh2d_view_layout",
|
||||
&BindGroupLayoutEntries::sequential(
|
||||
ShaderStages::VERTEX_FRAGMENT,
|
||||
render_device,
|
||||
)],
|
||||
label: Some("mesh2d_layout"),
|
||||
});
|
||||
(
|
||||
// View
|
||||
uniform_buffer::<ViewUniform>(true),
|
||||
uniform_buffer::<GlobalsUniform>(false),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
let mesh_layout = render_device.create_bind_group_layout(
|
||||
"mesh2d_layout",
|
||||
&BindGroupLayoutEntries::single(
|
||||
ShaderStages::VERTEX_FRAGMENT,
|
||||
GpuArrayBuffer::<Mesh2dUniform>::binding_layout(render_device),
|
||||
),
|
||||
);
|
||||
// A 1x1x1 'all 1.0' texture to use as a dummy texture to use in place of optional StandardMaterial textures
|
||||
let dummy_white_gpu_image = {
|
||||
let image = Image::default();
|
||||
|
|
|
@ -21,7 +21,10 @@ use bevy_render::{
|
|||
DrawFunctions, PhaseItem, RenderCommand, RenderCommandResult, RenderPhase, SetItemPipeline,
|
||||
TrackedRenderPass,
|
||||
},
|
||||
render_resource::{BindGroupEntries, *},
|
||||
render_resource::{
|
||||
binding_types::{sampler, texture_2d, uniform_buffer},
|
||||
BindGroupEntries, *,
|
||||
},
|
||||
renderer::{RenderDevice, RenderQueue},
|
||||
texture::{
|
||||
BevyDefault, DefaultImageSampler, GpuImage, Image, ImageSampler, TextureFormatPixelInfo,
|
||||
|
@ -53,41 +56,24 @@ impl FromWorld for SpritePipeline {
|
|||
)> = SystemState::new(world);
|
||||
let (render_device, default_sampler, render_queue) = system_state.get_mut(world);
|
||||
|
||||
let view_layout = render_device.create_bind_group_layout(&BindGroupLayoutDescriptor {
|
||||
entries: &[BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: ShaderStages::VERTEX | ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Buffer {
|
||||
ty: BufferBindingType::Uniform,
|
||||
has_dynamic_offset: true,
|
||||
min_binding_size: Some(ViewUniform::min_size()),
|
||||
},
|
||||
count: None,
|
||||
}],
|
||||
label: Some("sprite_view_layout"),
|
||||
});
|
||||
let view_layout = render_device.create_bind_group_layout(
|
||||
"sprite_view_layout",
|
||||
&BindGroupLayoutEntries::single(
|
||||
ShaderStages::VERTEX_FRAGMENT,
|
||||
uniform_buffer::<ViewUniform>(true),
|
||||
),
|
||||
);
|
||||
|
||||
let material_layout = render_device.create_bind_group_layout(&BindGroupLayoutDescriptor {
|
||||
entries: &[
|
||||
BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Texture {
|
||||
multisampled: false,
|
||||
sample_type: TextureSampleType::Float { filterable: true },
|
||||
view_dimension: TextureViewDimension::D2,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
BindGroupLayoutEntry {
|
||||
binding: 1,
|
||||
visibility: ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Sampler(SamplerBindingType::Filtering),
|
||||
count: None,
|
||||
},
|
||||
],
|
||||
label: Some("sprite_material_layout"),
|
||||
});
|
||||
let material_layout = render_device.create_bind_group_layout(
|
||||
"sprite_material_layout",
|
||||
&BindGroupLayoutEntries::sequential(
|
||||
ShaderStages::FRAGMENT,
|
||||
(
|
||||
texture_2d(TextureSampleType::Float { filterable: true }),
|
||||
sampler(SamplerBindingType::Filtering),
|
||||
),
|
||||
),
|
||||
);
|
||||
let dummy_white_gpu_image = {
|
||||
let image = Image::default();
|
||||
let texture = render_device.create_texture(&image.texture_descriptor);
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
use bevy_ecs::prelude::*;
|
||||
use bevy_render::{
|
||||
render_resource::*,
|
||||
render_resource::{
|
||||
binding_types::{sampler, texture_2d, uniform_buffer},
|
||||
*,
|
||||
},
|
||||
renderer::RenderDevice,
|
||||
texture::BevyDefault,
|
||||
view::{ViewTarget, ViewUniform},
|
||||
|
@ -16,41 +19,24 @@ impl FromWorld for UiPipeline {
|
|||
fn from_world(world: &mut World) -> Self {
|
||||
let render_device = world.resource::<RenderDevice>();
|
||||
|
||||
let view_layout = render_device.create_bind_group_layout(&BindGroupLayoutDescriptor {
|
||||
entries: &[BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: ShaderStages::VERTEX | ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Buffer {
|
||||
ty: BufferBindingType::Uniform,
|
||||
has_dynamic_offset: true,
|
||||
min_binding_size: Some(ViewUniform::min_size()),
|
||||
},
|
||||
count: None,
|
||||
}],
|
||||
label: Some("ui_view_layout"),
|
||||
});
|
||||
let view_layout = render_device.create_bind_group_layout(
|
||||
"ui_view_layout",
|
||||
&BindGroupLayoutEntries::single(
|
||||
ShaderStages::VERTEX_FRAGMENT,
|
||||
uniform_buffer::<ViewUniform>(true),
|
||||
),
|
||||
);
|
||||
|
||||
let image_layout = render_device.create_bind_group_layout(&BindGroupLayoutDescriptor {
|
||||
entries: &[
|
||||
BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Texture {
|
||||
multisampled: false,
|
||||
sample_type: TextureSampleType::Float { filterable: true },
|
||||
view_dimension: TextureViewDimension::D2,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
BindGroupLayoutEntry {
|
||||
binding: 1,
|
||||
visibility: ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Sampler(SamplerBindingType::Filtering),
|
||||
count: None,
|
||||
},
|
||||
],
|
||||
label: Some("ui_image_layout"),
|
||||
});
|
||||
let image_layout = render_device.create_bind_group_layout(
|
||||
"ui_image_layout",
|
||||
&BindGroupLayoutEntries::sequential(
|
||||
ShaderStages::FRAGMENT,
|
||||
(
|
||||
texture_2d(TextureSampleType::Float { filterable: true }),
|
||||
sampler(SamplerBindingType::Filtering),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
UiPipeline {
|
||||
view_layout,
|
||||
|
|
|
@ -17,7 +17,7 @@ use bevy_render::{
|
|||
extract_component::ExtractComponentPlugin,
|
||||
render_asset::RenderAssets,
|
||||
render_phase::*,
|
||||
render_resource::*,
|
||||
render_resource::{binding_types::uniform_buffer, *},
|
||||
renderer::{RenderDevice, RenderQueue},
|
||||
texture::{BevyDefault, FallbackImage, Image},
|
||||
view::*,
|
||||
|
@ -223,19 +223,13 @@ impl<M: UiMaterial> FromWorld for UiMaterialPipeline<M> {
|
|||
let render_device = world.resource::<RenderDevice>();
|
||||
let ui_layout = M::bind_group_layout(render_device);
|
||||
|
||||
let view_layout = render_device.create_bind_group_layout(&BindGroupLayoutDescriptor {
|
||||
entries: &[BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: ShaderStages::VERTEX | ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Buffer {
|
||||
ty: BufferBindingType::Uniform,
|
||||
has_dynamic_offset: true,
|
||||
min_binding_size: Some(ViewUniform::min_size()),
|
||||
},
|
||||
count: None,
|
||||
}],
|
||||
label: Some("ui_view_layout"),
|
||||
});
|
||||
let view_layout = render_device.create_bind_group_layout(
|
||||
"ui_view_layout",
|
||||
&BindGroupLayoutEntries::single(
|
||||
ShaderStages::VERTEX_FRAGMENT,
|
||||
uniform_buffer::<ViewUniform>(true),
|
||||
),
|
||||
);
|
||||
UiMaterialPipeline {
|
||||
ui_layout,
|
||||
view_layout,
|
||||
|
|
|
@ -9,7 +9,7 @@ use bevy::{
|
|||
extract_resource::{ExtractResource, ExtractResourcePlugin},
|
||||
render_asset::RenderAssets,
|
||||
render_graph::{self, RenderGraph},
|
||||
render_resource::*,
|
||||
render_resource::{binding_types::texture_storage_2d, *},
|
||||
renderer::{RenderContext, RenderDevice},
|
||||
Render, RenderApp, RenderSet,
|
||||
},
|
||||
|
@ -124,22 +124,13 @@ pub struct GameOfLifePipeline {
|
|||
|
||||
impl FromWorld for GameOfLifePipeline {
|
||||
fn from_world(world: &mut World) -> Self {
|
||||
let texture_bind_group_layout =
|
||||
world
|
||||
.resource::<RenderDevice>()
|
||||
.create_bind_group_layout(&BindGroupLayoutDescriptor {
|
||||
label: None,
|
||||
entries: &[BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: ShaderStages::COMPUTE,
|
||||
ty: BindingType::StorageTexture {
|
||||
access: StorageTextureAccess::ReadWrite,
|
||||
format: TextureFormat::Rgba8Unorm,
|
||||
view_dimension: TextureViewDimension::D2,
|
||||
},
|
||||
count: None,
|
||||
}],
|
||||
});
|
||||
let texture_bind_group_layout = world.resource::<RenderDevice>().create_bind_group_layout(
|
||||
None,
|
||||
&BindGroupLayoutEntries::single(
|
||||
ShaderStages::COMPUTE,
|
||||
texture_storage_2d(TextureFormat::Rgba8Unorm, StorageTextureAccess::ReadWrite),
|
||||
),
|
||||
);
|
||||
let shader = world
|
||||
.resource::<AssetServer>()
|
||||
.load("shaders/game_of_life.wgsl");
|
||||
|
|
|
@ -17,12 +17,8 @@ use bevy::{
|
|||
NodeRunError, RenderGraphApp, RenderGraphContext, ViewNode, ViewNodeRunner,
|
||||
},
|
||||
render_resource::{
|
||||
BindGroupEntries, BindGroupLayout, BindGroupLayoutDescriptor, BindGroupLayoutEntry,
|
||||
BindingType, CachedRenderPipelineId, ColorTargetState, ColorWrites, FragmentState,
|
||||
MultisampleState, Operations, PipelineCache, PrimitiveState, RenderPassColorAttachment,
|
||||
RenderPassDescriptor, RenderPipelineDescriptor, Sampler, SamplerBindingType,
|
||||
SamplerDescriptor, ShaderStages, ShaderType, TextureFormat, TextureSampleType,
|
||||
TextureViewDimension,
|
||||
binding_types::{sampler, texture_2d, uniform_buffer},
|
||||
*,
|
||||
},
|
||||
renderer::{RenderContext, RenderDevice},
|
||||
texture::BevyDefault,
|
||||
|
@ -227,40 +223,21 @@ impl FromWorld for PostProcessPipeline {
|
|||
let render_device = world.resource::<RenderDevice>();
|
||||
|
||||
// We need to define the bind group layout used for our pipeline
|
||||
let layout = render_device.create_bind_group_layout(&BindGroupLayoutDescriptor {
|
||||
label: Some("post_process_bind_group_layout"),
|
||||
entries: &[
|
||||
let layout = render_device.create_bind_group_layout(
|
||||
"post_process_bind_group_layout",
|
||||
&BindGroupLayoutEntries::sequential(
|
||||
// The layout entries will only be visible in the fragment stage
|
||||
ShaderStages::FRAGMENT,
|
||||
(
|
||||
// The screen texture
|
||||
BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Texture {
|
||||
sample_type: TextureSampleType::Float { filterable: true },
|
||||
view_dimension: TextureViewDimension::D2,
|
||||
multisampled: false,
|
||||
},
|
||||
count: None,
|
||||
},
|
||||
texture_2d(TextureSampleType::Float { filterable: true }),
|
||||
// The sampler that will be used to sample the screen texture
|
||||
BindGroupLayoutEntry {
|
||||
binding: 1,
|
||||
visibility: ShaderStages::FRAGMENT,
|
||||
ty: BindingType::Sampler(SamplerBindingType::Filtering),
|
||||
count: None,
|
||||
},
|
||||
sampler(SamplerBindingType::Filtering),
|
||||
// The settings uniform that will control the effect
|
||||
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,
|
||||
},
|
||||
],
|
||||
});
|
||||
uniform_buffer::<PostProcessSettings>(false),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// We can create the sampler here since it won't change at runtime and doesn't depend on the view
|
||||
let sampler = render_device.create_sampler(&SamplerDescriptor::default());
|
||||
|
|
Loading…
Reference in a new issue