-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Variable MeshPipeline
View Bind Group Layout
#10156
Changes from 5 commits
2c44195
f46e7f6
19ca341
8db3082
6949f8a
392c3ca
06dd7b0
d884622
6909e70
d8741c5
ba17d90
0f43c7c
b6923e4
f20672a
0b76720
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
doc-valid-idents = ["sRGB", "NaN", "iOS", "glTF", "GitHub", "WebGPU", "GilRs"] | ||
doc-valid-idents = ["sRGB", "NaN", "iOS", "glTF", "GitHub", "WebGL", "WebGPU", "GilRs"] |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,11 +37,10 @@ use bevy_render::{ | |
FragmentState, FrontFace, MultisampleState, PipelineCache, PolygonMode, PrimitiveState, | ||
PushConstantRange, RenderPipelineDescriptor, Shader, ShaderRef, ShaderStages, ShaderType, | ||
SpecializedMeshPipeline, SpecializedMeshPipelineError, SpecializedMeshPipelines, | ||
StencilFaceState, StencilState, TextureAspect, TextureFormat, TextureSampleType, | ||
TextureView, TextureViewDescriptor, TextureViewDimension, VertexState, | ||
StencilFaceState, StencilState, TextureAspect, TextureSampleType, TextureView, | ||
TextureViewDescriptor, TextureViewDimension, VertexState, | ||
}, | ||
renderer::{RenderDevice, RenderQueue}, | ||
texture::{BevyDefault, FallbackImageMsaa}, | ||
view::{ExtractedView, Msaa, ViewUniform, ViewUniformOffset, ViewUniforms, VisibleEntities}, | ||
Extract, ExtractSchedule, Render, RenderApp, RenderSet, | ||
}; | ||
|
@@ -52,8 +51,8 @@ use bevy_utils::tracing::error; | |
use crate::{ | ||
prepare_materials, setup_morph_and_skinning_defs, AlphaMode, DrawMesh, Material, | ||
MaterialPipeline, MaterialPipelineKey, MeshLayouts, MeshPipeline, MeshPipelineKey, | ||
OpaqueRendererMethod, RenderMaterialInstances, RenderMaterials, RenderMeshInstances, | ||
SetMaterialBindGroup, SetMeshBindGroup, | ||
MeshPipelineViewLayoutKey, OpaqueRendererMethod, RenderMaterialInstances, RenderMaterials, | ||
RenderMeshInstances, SetMaterialBindGroup, SetMeshBindGroup, | ||
}; | ||
|
||
use std::{hash::Hash, marker::PhantomData}; | ||
|
@@ -636,127 +635,151 @@ where | |
|
||
pub fn get_bind_group_layout_entries( | ||
bindings: [u32; 4], | ||
multisampled: bool, | ||
) -> [BindGroupLayoutEntry; 4] { | ||
[ | ||
// Depth texture | ||
BindGroupLayoutEntry { | ||
binding: bindings[0], | ||
visibility: ShaderStages::FRAGMENT, | ||
ty: BindingType::Texture { | ||
multisampled, | ||
sample_type: TextureSampleType::Depth, | ||
view_dimension: TextureViewDimension::D2, | ||
layout_key: MeshPipelineViewLayoutKey, | ||
) -> Vec<BindGroupLayoutEntry> { | ||
let mut result = vec![]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not a big deal considering this is run only once, but we should use an ArrayVec here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like we don't depend on that crate, probably not worth it to add it just for this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm pretty sure we have a small array crate somewhere in tree, maybe not in bevy_pbr though but if it's already in tree in another crate it's probably fine to add it. Although, if it's only for this place it's probably not necessary There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I use |
||
|
||
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, | ||
}, | ||
count: None, | ||
}, | ||
// Normal texture | ||
BindGroupLayoutEntry { | ||
binding: bindings[1], | ||
visibility: ShaderStages::FRAGMENT, | ||
ty: BindingType::Texture { | ||
multisampled, | ||
sample_type: TextureSampleType::Float { filterable: false }, | ||
view_dimension: TextureViewDimension::D2, | ||
); | ||
} | ||
|
||
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, | ||
}, | ||
count: None, | ||
}, | ||
// Motion Vectors texture | ||
BindGroupLayoutEntry { | ||
binding: bindings[2], | ||
visibility: ShaderStages::FRAGMENT, | ||
ty: BindingType::Texture { | ||
multisampled, | ||
sample_type: TextureSampleType::Float { filterable: false }, | ||
view_dimension: TextureViewDimension::D2, | ||
); | ||
} | ||
|
||
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, | ||
}, | ||
count: None, | ||
}, | ||
// Deferred texture | ||
BindGroupLayoutEntry { | ||
binding: bindings[3], | ||
visibility: ShaderStages::FRAGMENT, | ||
ty: BindingType::Texture { | ||
multisampled: false, | ||
sample_type: TextureSampleType::Uint, | ||
view_dimension: TextureViewDimension::D2, | ||
); | ||
} | ||
|
||
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, | ||
}, | ||
count: None, | ||
}, | ||
] | ||
); | ||
} | ||
|
||
result | ||
} | ||
|
||
// Needed so the texture views can live long enough. | ||
pub struct PrepassBindingsSet([TextureView; 4]); | ||
pub struct PrepassBindingsSet { | ||
depth_view: Option<TextureView>, | ||
normal_view: Option<TextureView>, | ||
motion_vectors_view: Option<TextureView>, | ||
deferred_view: Option<TextureView>, | ||
} | ||
|
||
impl PrepassBindingsSet { | ||
pub fn get_entries(&self, bindings: [u32; 4]) -> [BindGroupEntry; 4] { | ||
[ | ||
BindGroupEntry { | ||
pub fn get_entries(&self, bindings: [u32; 4]) -> Vec<BindGroupEntry> { | ||
let mut result: Vec<BindGroupEntry> = vec![]; | ||
|
||
if let Some(ref depth_view) = self.depth_view { | ||
result.push(BindGroupEntry { | ||
binding: bindings[0], | ||
resource: BindingResource::TextureView(&self.0[0]), | ||
}, | ||
BindGroupEntry { | ||
resource: BindingResource::TextureView(depth_view), | ||
}); | ||
} | ||
|
||
if let Some(ref normal_view) = self.normal_view { | ||
result.push(BindGroupEntry { | ||
binding: bindings[1], | ||
resource: BindingResource::TextureView(&self.0[1]), | ||
}, | ||
BindGroupEntry { | ||
resource: BindingResource::TextureView(normal_view), | ||
}); | ||
} | ||
|
||
if let Some(ref motion_vectors_view) = self.motion_vectors_view { | ||
result.push(BindGroupEntry { | ||
binding: bindings[2], | ||
resource: BindingResource::TextureView(&self.0[2]), | ||
}, | ||
BindGroupEntry { | ||
resource: BindingResource::TextureView(motion_vectors_view), | ||
}); | ||
} | ||
|
||
if let Some(ref deferred_view) = self.deferred_view { | ||
result.push(BindGroupEntry { | ||
binding: bindings[3], | ||
resource: BindingResource::TextureView(&self.0[3]), | ||
}, | ||
] | ||
resource: BindingResource::TextureView(deferred_view), | ||
}); | ||
} | ||
|
||
result | ||
} | ||
} | ||
|
||
pub fn get_bindings( | ||
prepass_textures: Option<&ViewPrepassTextures>, | ||
fallback_images: &mut FallbackImageMsaa, | ||
msaa: &Msaa, | ||
) -> PrepassBindingsSet { | ||
pub fn get_bindings(prepass_textures: Option<&ViewPrepassTextures>) -> PrepassBindingsSet { | ||
let depth_desc = TextureViewDescriptor { | ||
label: Some("prepass_depth"), | ||
aspect: TextureAspect::DepthOnly, | ||
..default() | ||
}; | ||
let depth_view = match prepass_textures.and_then(|x| x.depth.as_ref()) { | ||
Some(texture) => texture.texture.create_view(&depth_desc), | ||
None => fallback_images | ||
.image_for_samplecount(msaa.samples(), CORE_3D_DEPTH_FORMAT) | ||
.texture | ||
.create_view(&depth_desc), | ||
}; | ||
|
||
let normal_motion_vectors_fallback = &fallback_images | ||
.image_for_samplecount(msaa.samples(), TextureFormat::bevy_default()) | ||
.texture_view; | ||
|
||
let normal_view = match prepass_textures.and_then(|x| x.normal.as_ref()) { | ||
Some(texture) => &texture.default_view, | ||
None => normal_motion_vectors_fallback, | ||
let depth_view = prepass_textures | ||
.and_then(|x| x.depth.as_ref()) | ||
.map(|texture| texture.texture.create_view(&depth_desc)); | ||
|
||
let normal_view = prepass_textures | ||
.and_then(|x| x.normal.as_ref()) | ||
.map(|texture| texture.default_view.clone()); | ||
|
||
let motion_vectors_view = prepass_textures | ||
.and_then(|x| x.motion_vectors.as_ref()) | ||
.map(|texture| texture.default_view.clone()); | ||
|
||
let deferred_view = prepass_textures | ||
.and_then(|x| x.deferred.as_ref()) | ||
.map(|texture| texture.default_view.clone()); | ||
|
||
PrepassBindingsSet { | ||
depth_view, | ||
normal_view, | ||
motion_vectors_view, | ||
deferred_view, | ||
} | ||
.clone(); | ||
|
||
let motion_vectors_view = match prepass_textures.and_then(|x| x.motion_vectors.as_ref()) { | ||
Some(texture) => &texture.default_view, | ||
None => normal_motion_vectors_fallback, | ||
} | ||
.clone(); | ||
|
||
let deferred_fallback = &fallback_images | ||
.image_for_samplecount(1, TextureFormat::Rgba32Uint) | ||
.texture_view; | ||
|
||
let deferred_view = match prepass_textures.and_then(|x| x.deferred.as_ref()) { | ||
Some(texture) => &texture.default_view, | ||
None => deferred_fallback, | ||
} | ||
.clone(); | ||
|
||
PrepassBindingsSet([depth_view, normal_view, motion_vectors_view, deferred_view]) | ||
} | ||
|
||
// Extract the render phases for the prepass | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could the bind group creation code be moved to its own file? I think we should avoid large files like
render/mesh.rs
. And it would neatly reflectmesh_bindings.rs
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extracted it. Also moved the
mesh.rs
view binding creation code to the newly createdmesh_view_bindings.rs
.