Move non-generic parts of the PrepassPipeline to internal field (#18322)
# Objective - The prepass pipeline has a generic bound on the specialize function but 95% of it doesn't need it ## Solution - Move most of the fields to an internal struct and use a separate specialize function for those fields ## Testing - Ran the 3d_scene and it worked like before --- ## Migration Guide If you were using a field of the `PrepassPipeline`, most of them have now been move to `PrepassPipeline::internal`. ## Notes Here's the cargo bloat size comparison (from this tool https://github.com/bevyengine/bevy/discussions/14864): ``` before: ( "<bevy_pbr::prepass::PrepassPipeline<M> as bevy_render::render_resource::pipeline_specializer::SpecializedMeshPipeline>::specialize", 25416, 0.05582993, ), after: ( "<bevy_pbr::prepass::PrepassPipeline<M> as bevy_render::render_resource::pipeline_specializer::SpecializedMeshPipeline>::specialize", 2496, 0.005490916, ), ( "bevy_pbr::prepass::PrepassPipelineInternal::specialize", 11444, 0.025175499, ), ``` The size for the specialize function that is generic is now much smaller, so users won't need to recompile it for every material.
This commit is contained in:
parent
a021ed1ce8
commit
af9fd4e939
@ -336,9 +336,12 @@ pub fn prepare_material_meshlet_meshes_prepass<M: Material>(
|
|||||||
shader_defs.push("MESHLET_MESH_MATERIAL_PASS".into());
|
shader_defs.push("MESHLET_MESH_MATERIAL_PASS".into());
|
||||||
|
|
||||||
let view_layout = if view_key.contains(MeshPipelineKey::MOTION_VECTOR_PREPASS) {
|
let view_layout = if view_key.contains(MeshPipelineKey::MOTION_VECTOR_PREPASS) {
|
||||||
prepass_pipeline.view_layout_motion_vectors.clone()
|
prepass_pipeline.internal.view_layout_motion_vectors.clone()
|
||||||
} else {
|
} else {
|
||||||
prepass_pipeline.view_layout_no_motion_vectors.clone()
|
prepass_pipeline
|
||||||
|
.internal
|
||||||
|
.view_layout_no_motion_vectors
|
||||||
|
.clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
let fragment_shader = if view_key.contains(MeshPipelineKey::DEFERRED_PREPASS) {
|
let fragment_shader = if view_key.contains(MeshPipelineKey::DEFERRED_PREPASS) {
|
||||||
@ -357,7 +360,7 @@ pub fn prepare_material_meshlet_meshes_prepass<M: Material>(
|
|||||||
layout: vec![
|
layout: vec![
|
||||||
view_layout,
|
view_layout,
|
||||||
resource_manager.material_shade_bind_group_layout.clone(),
|
resource_manager.material_shade_bind_group_layout.clone(),
|
||||||
prepass_pipeline.material_layout.clone(),
|
prepass_pipeline.internal.material_layout.clone(),
|
||||||
],
|
],
|
||||||
push_constant_ranges: vec![],
|
push_constant_ranges: vec![],
|
||||||
vertex: VertexState {
|
vertex: VertexState {
|
||||||
|
@ -287,6 +287,13 @@ pub fn update_mesh_previous_global_transforms(
|
|||||||
|
|
||||||
#[derive(Resource)]
|
#[derive(Resource)]
|
||||||
pub struct PrepassPipeline<M: Material> {
|
pub struct PrepassPipeline<M: Material> {
|
||||||
|
pub internal: PrepassPipelineInternal,
|
||||||
|
pub material_pipeline: MaterialPipeline<M>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Internal fields of the `PrepassPipeline` that don't need the generic bound
|
||||||
|
/// This is done as an optimization to not recompile the same code multiple time
|
||||||
|
pub struct PrepassPipelineInternal {
|
||||||
pub view_layout_motion_vectors: BindGroupLayout,
|
pub view_layout_motion_vectors: BindGroupLayout,
|
||||||
pub view_layout_no_motion_vectors: BindGroupLayout,
|
pub view_layout_no_motion_vectors: BindGroupLayout,
|
||||||
pub mesh_layouts: MeshLayouts,
|
pub mesh_layouts: MeshLayouts,
|
||||||
@ -295,7 +302,6 @@ pub struct PrepassPipeline<M: Material> {
|
|||||||
pub prepass_material_fragment_shader: Option<Handle<Shader>>,
|
pub prepass_material_fragment_shader: Option<Handle<Shader>>,
|
||||||
pub deferred_material_vertex_shader: Option<Handle<Shader>>,
|
pub deferred_material_vertex_shader: Option<Handle<Shader>>,
|
||||||
pub deferred_material_fragment_shader: Option<Handle<Shader>>,
|
pub deferred_material_fragment_shader: Option<Handle<Shader>>,
|
||||||
pub material_pipeline: MaterialPipeline<M>,
|
|
||||||
|
|
||||||
/// Whether skins will use uniform buffers on account of storage buffers
|
/// Whether skins will use uniform buffers on account of storage buffers
|
||||||
/// being unavailable on this platform.
|
/// being unavailable on this platform.
|
||||||
@ -306,8 +312,6 @@ pub struct PrepassPipeline<M: Material> {
|
|||||||
/// Whether binding arrays (a.k.a. bindless textures) are usable on the
|
/// Whether binding arrays (a.k.a. bindless textures) are usable on the
|
||||||
/// current render device.
|
/// current render device.
|
||||||
pub binding_arrays_are_usable: bool,
|
pub binding_arrays_are_usable: bool,
|
||||||
|
|
||||||
_marker: PhantomData<M>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<M: Material> FromWorld for PrepassPipeline<M> {
|
impl<M: Material> FromWorld for PrepassPipeline<M> {
|
||||||
@ -372,8 +376,7 @@ impl<M: Material> FromWorld for PrepassPipeline<M> {
|
|||||||
let depth_clip_control_supported = render_device
|
let depth_clip_control_supported = render_device
|
||||||
.features()
|
.features()
|
||||||
.contains(WgpuFeatures::DEPTH_CLIP_CONTROL);
|
.contains(WgpuFeatures::DEPTH_CLIP_CONTROL);
|
||||||
|
let internal = PrepassPipelineInternal {
|
||||||
PrepassPipeline {
|
|
||||||
view_layout_motion_vectors,
|
view_layout_motion_vectors,
|
||||||
view_layout_no_motion_vectors,
|
view_layout_no_motion_vectors,
|
||||||
mesh_layouts: mesh_pipeline.mesh_layouts.clone(),
|
mesh_layouts: mesh_pipeline.mesh_layouts.clone(),
|
||||||
@ -398,11 +401,13 @@ impl<M: Material> FromWorld for PrepassPipeline<M> {
|
|||||||
ShaderRef::Path(path) => Some(asset_server.load(path)),
|
ShaderRef::Path(path) => Some(asset_server.load(path)),
|
||||||
},
|
},
|
||||||
material_layout: M::bind_group_layout(render_device),
|
material_layout: M::bind_group_layout(render_device),
|
||||||
material_pipeline: world.resource::<MaterialPipeline<M>>().clone(),
|
|
||||||
skins_use_uniform_buffers: skin::skins_use_uniform_buffers(render_device),
|
skins_use_uniform_buffers: skin::skins_use_uniform_buffers(render_device),
|
||||||
depth_clip_control_supported,
|
depth_clip_control_supported,
|
||||||
binding_arrays_are_usable: binding_arrays_are_usable(render_device, render_adapter),
|
binding_arrays_are_usable: binding_arrays_are_usable(render_device, render_adapter),
|
||||||
_marker: PhantomData,
|
};
|
||||||
|
PrepassPipeline {
|
||||||
|
internal,
|
||||||
|
material_pipeline: world.resource::<MaterialPipeline<M>>().clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -418,15 +423,38 @@ where
|
|||||||
key: Self::Key,
|
key: Self::Key,
|
||||||
layout: &MeshVertexBufferLayoutRef,
|
layout: &MeshVertexBufferLayoutRef,
|
||||||
) -> Result<RenderPipelineDescriptor, SpecializedMeshPipelineError> {
|
) -> Result<RenderPipelineDescriptor, SpecializedMeshPipelineError> {
|
||||||
let mut bind_group_layouts = vec![if key
|
let mut shader_defs = Vec::new();
|
||||||
.mesh_key
|
if self.material_pipeline.bindless {
|
||||||
|
shader_defs.push("BINDLESS".into());
|
||||||
|
}
|
||||||
|
let mut descriptor = self
|
||||||
|
.internal
|
||||||
|
.specialize(key.mesh_key, shader_defs, layout)?;
|
||||||
|
|
||||||
|
// This is a bit risky because it's possible to change something that would
|
||||||
|
// break the prepass but be fine in the main pass.
|
||||||
|
// Since this api is pretty low-level it doesn't matter that much, but it is a potential issue.
|
||||||
|
M::specialize(&self.material_pipeline, &mut descriptor, layout, key)?;
|
||||||
|
|
||||||
|
Ok(descriptor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PrepassPipelineInternal {
|
||||||
|
fn specialize(
|
||||||
|
&self,
|
||||||
|
mesh_key: MeshPipelineKey,
|
||||||
|
shader_defs: Vec<ShaderDefVal>,
|
||||||
|
layout: &MeshVertexBufferLayoutRef,
|
||||||
|
) -> Result<RenderPipelineDescriptor, SpecializedMeshPipelineError> {
|
||||||
|
let mut shader_defs = shader_defs;
|
||||||
|
let mut bind_group_layouts = vec![if mesh_key
|
||||||
.contains(MeshPipelineKey::MOTION_VECTOR_PREPASS)
|
.contains(MeshPipelineKey::MOTION_VECTOR_PREPASS)
|
||||||
{
|
{
|
||||||
self.view_layout_motion_vectors.clone()
|
self.view_layout_motion_vectors.clone()
|
||||||
} else {
|
} else {
|
||||||
self.view_layout_no_motion_vectors.clone()
|
self.view_layout_no_motion_vectors.clone()
|
||||||
}];
|
}];
|
||||||
let mut shader_defs = Vec::new();
|
|
||||||
let mut vertex_attributes = Vec::new();
|
let mut vertex_attributes = Vec::new();
|
||||||
|
|
||||||
// Let the shader code know that it's running in a prepass pipeline.
|
// Let the shader code know that it's running in a prepass pipeline.
|
||||||
@ -437,40 +465,29 @@ where
|
|||||||
// NOTE: Eventually, it would be nice to only add this when the shaders are overloaded by the Material.
|
// NOTE: Eventually, it would be nice to only add this when the shaders are overloaded by the Material.
|
||||||
// The main limitation right now is that bind group order is hardcoded in shaders.
|
// The main limitation right now is that bind group order is hardcoded in shaders.
|
||||||
bind_group_layouts.push(self.material_layout.clone());
|
bind_group_layouts.push(self.material_layout.clone());
|
||||||
|
|
||||||
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
|
#[cfg(all(feature = "webgl", target_arch = "wasm32", not(feature = "webgpu")))]
|
||||||
shader_defs.push("WEBGL2".into());
|
shader_defs.push("WEBGL2".into());
|
||||||
|
|
||||||
shader_defs.push("VERTEX_OUTPUT_INSTANCE_INDEX".into());
|
shader_defs.push("VERTEX_OUTPUT_INSTANCE_INDEX".into());
|
||||||
|
if mesh_key.contains(MeshPipelineKey::DEPTH_PREPASS) {
|
||||||
if key.mesh_key.contains(MeshPipelineKey::DEPTH_PREPASS) {
|
|
||||||
shader_defs.push("DEPTH_PREPASS".into());
|
shader_defs.push("DEPTH_PREPASS".into());
|
||||||
}
|
}
|
||||||
|
if mesh_key.contains(MeshPipelineKey::MAY_DISCARD) {
|
||||||
if key.mesh_key.contains(MeshPipelineKey::MAY_DISCARD) {
|
|
||||||
shader_defs.push("MAY_DISCARD".into());
|
shader_defs.push("MAY_DISCARD".into());
|
||||||
}
|
}
|
||||||
|
let blend_key = mesh_key.intersection(MeshPipelineKey::BLEND_RESERVED_BITS);
|
||||||
let blend_key = key
|
|
||||||
.mesh_key
|
|
||||||
.intersection(MeshPipelineKey::BLEND_RESERVED_BITS);
|
|
||||||
if blend_key == MeshPipelineKey::BLEND_PREMULTIPLIED_ALPHA {
|
if blend_key == MeshPipelineKey::BLEND_PREMULTIPLIED_ALPHA {
|
||||||
shader_defs.push("BLEND_PREMULTIPLIED_ALPHA".into());
|
shader_defs.push("BLEND_PREMULTIPLIED_ALPHA".into());
|
||||||
}
|
}
|
||||||
if blend_key == MeshPipelineKey::BLEND_ALPHA {
|
if blend_key == MeshPipelineKey::BLEND_ALPHA {
|
||||||
shader_defs.push("BLEND_ALPHA".into());
|
shader_defs.push("BLEND_ALPHA".into());
|
||||||
}
|
}
|
||||||
|
|
||||||
if layout.0.contains(Mesh::ATTRIBUTE_POSITION) {
|
if layout.0.contains(Mesh::ATTRIBUTE_POSITION) {
|
||||||
shader_defs.push("VERTEX_POSITIONS".into());
|
shader_defs.push("VERTEX_POSITIONS".into());
|
||||||
vertex_attributes.push(Mesh::ATTRIBUTE_POSITION.at_shader_location(0));
|
vertex_attributes.push(Mesh::ATTRIBUTE_POSITION.at_shader_location(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
// For directional light shadow map views, use unclipped depth via either the native GPU feature,
|
// For directional light shadow map views, use unclipped depth via either the native GPU feature,
|
||||||
// or emulated by setting depth in the fragment shader for GPUs that don't support it natively.
|
// or emulated by setting depth in the fragment shader for GPUs that don't support it natively.
|
||||||
let emulate_unclipped_depth = key
|
let emulate_unclipped_depth = mesh_key.contains(MeshPipelineKey::UNCLIPPED_DEPTH_ORTHO)
|
||||||
.mesh_key
|
|
||||||
.contains(MeshPipelineKey::UNCLIPPED_DEPTH_ORTHO)
|
|
||||||
&& !self.depth_clip_control_supported;
|
&& !self.depth_clip_control_supported;
|
||||||
if emulate_unclipped_depth {
|
if emulate_unclipped_depth {
|
||||||
shader_defs.push("UNCLIPPED_DEPTH_ORTHO_EMULATION".into());
|
shader_defs.push("UNCLIPPED_DEPTH_ORTHO_EMULATION".into());
|
||||||
@ -482,36 +499,28 @@ where
|
|||||||
// https://github.com/bevyengine/bevy/pull/8877
|
// https://github.com/bevyengine/bevy/pull/8877
|
||||||
shader_defs.push("PREPASS_FRAGMENT".into());
|
shader_defs.push("PREPASS_FRAGMENT".into());
|
||||||
}
|
}
|
||||||
let unclipped_depth = key
|
let unclipped_depth = mesh_key.contains(MeshPipelineKey::UNCLIPPED_DEPTH_ORTHO)
|
||||||
.mesh_key
|
|
||||||
.contains(MeshPipelineKey::UNCLIPPED_DEPTH_ORTHO)
|
|
||||||
&& self.depth_clip_control_supported;
|
&& self.depth_clip_control_supported;
|
||||||
|
|
||||||
if layout.0.contains(Mesh::ATTRIBUTE_UV_0) {
|
if layout.0.contains(Mesh::ATTRIBUTE_UV_0) {
|
||||||
shader_defs.push("VERTEX_UVS".into());
|
shader_defs.push("VERTEX_UVS".into());
|
||||||
shader_defs.push("VERTEX_UVS_A".into());
|
shader_defs.push("VERTEX_UVS_A".into());
|
||||||
vertex_attributes.push(Mesh::ATTRIBUTE_UV_0.at_shader_location(1));
|
vertex_attributes.push(Mesh::ATTRIBUTE_UV_0.at_shader_location(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
if layout.0.contains(Mesh::ATTRIBUTE_UV_1) {
|
if layout.0.contains(Mesh::ATTRIBUTE_UV_1) {
|
||||||
shader_defs.push("VERTEX_UVS".into());
|
shader_defs.push("VERTEX_UVS".into());
|
||||||
shader_defs.push("VERTEX_UVS_B".into());
|
shader_defs.push("VERTEX_UVS_B".into());
|
||||||
vertex_attributes.push(Mesh::ATTRIBUTE_UV_1.at_shader_location(2));
|
vertex_attributes.push(Mesh::ATTRIBUTE_UV_1.at_shader_location(2));
|
||||||
}
|
}
|
||||||
|
if mesh_key.contains(MeshPipelineKey::NORMAL_PREPASS) {
|
||||||
if key.mesh_key.contains(MeshPipelineKey::NORMAL_PREPASS) {
|
|
||||||
shader_defs.push("NORMAL_PREPASS".into());
|
shader_defs.push("NORMAL_PREPASS".into());
|
||||||
}
|
}
|
||||||
|
if mesh_key.intersects(MeshPipelineKey::NORMAL_PREPASS | MeshPipelineKey::DEFERRED_PREPASS)
|
||||||
if key
|
|
||||||
.mesh_key
|
|
||||||
.intersects(MeshPipelineKey::NORMAL_PREPASS | MeshPipelineKey::DEFERRED_PREPASS)
|
|
||||||
{
|
{
|
||||||
shader_defs.push("NORMAL_PREPASS_OR_DEFERRED_PREPASS".into());
|
shader_defs.push("NORMAL_PREPASS_OR_DEFERRED_PREPASS".into());
|
||||||
if layout.0.contains(Mesh::ATTRIBUTE_NORMAL) {
|
if layout.0.contains(Mesh::ATTRIBUTE_NORMAL) {
|
||||||
shader_defs.push("VERTEX_NORMALS".into());
|
shader_defs.push("VERTEX_NORMALS".into());
|
||||||
vertex_attributes.push(Mesh::ATTRIBUTE_NORMAL.at_shader_location(3));
|
vertex_attributes.push(Mesh::ATTRIBUTE_NORMAL.at_shader_location(3));
|
||||||
} else if key.mesh_key.contains(MeshPipelineKey::NORMAL_PREPASS) {
|
} else if mesh_key.contains(MeshPipelineKey::NORMAL_PREPASS) {
|
||||||
warn!(
|
warn!(
|
||||||
"The default normal prepass expects the mesh to have vertex normal attributes."
|
"The default normal prepass expects the mesh to have vertex normal attributes."
|
||||||
);
|
);
|
||||||
@ -521,91 +530,62 @@ where
|
|||||||
vertex_attributes.push(Mesh::ATTRIBUTE_TANGENT.at_shader_location(4));
|
vertex_attributes.push(Mesh::ATTRIBUTE_TANGENT.at_shader_location(4));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if mesh_key
|
||||||
if key
|
|
||||||
.mesh_key
|
|
||||||
.intersects(MeshPipelineKey::MOTION_VECTOR_PREPASS | MeshPipelineKey::DEFERRED_PREPASS)
|
.intersects(MeshPipelineKey::MOTION_VECTOR_PREPASS | MeshPipelineKey::DEFERRED_PREPASS)
|
||||||
{
|
{
|
||||||
shader_defs.push("MOTION_VECTOR_PREPASS_OR_DEFERRED_PREPASS".into());
|
shader_defs.push("MOTION_VECTOR_PREPASS_OR_DEFERRED_PREPASS".into());
|
||||||
}
|
}
|
||||||
|
if mesh_key.contains(MeshPipelineKey::DEFERRED_PREPASS) {
|
||||||
if key.mesh_key.contains(MeshPipelineKey::DEFERRED_PREPASS) {
|
|
||||||
shader_defs.push("DEFERRED_PREPASS".into());
|
shader_defs.push("DEFERRED_PREPASS".into());
|
||||||
}
|
}
|
||||||
|
if mesh_key.contains(MeshPipelineKey::LIGHTMAPPED) {
|
||||||
if key.mesh_key.contains(MeshPipelineKey::LIGHTMAPPED) {
|
|
||||||
shader_defs.push("LIGHTMAP".into());
|
shader_defs.push("LIGHTMAP".into());
|
||||||
}
|
}
|
||||||
if key
|
if mesh_key.contains(MeshPipelineKey::LIGHTMAP_BICUBIC_SAMPLING) {
|
||||||
.mesh_key
|
|
||||||
.contains(MeshPipelineKey::LIGHTMAP_BICUBIC_SAMPLING)
|
|
||||||
{
|
|
||||||
shader_defs.push("LIGHTMAP_BICUBIC_SAMPLING".into());
|
shader_defs.push("LIGHTMAP_BICUBIC_SAMPLING".into());
|
||||||
}
|
}
|
||||||
|
|
||||||
if layout.0.contains(Mesh::ATTRIBUTE_COLOR) {
|
if layout.0.contains(Mesh::ATTRIBUTE_COLOR) {
|
||||||
shader_defs.push("VERTEX_COLORS".into());
|
shader_defs.push("VERTEX_COLORS".into());
|
||||||
vertex_attributes.push(Mesh::ATTRIBUTE_COLOR.at_shader_location(7));
|
vertex_attributes.push(Mesh::ATTRIBUTE_COLOR.at_shader_location(7));
|
||||||
}
|
}
|
||||||
|
if mesh_key.contains(MeshPipelineKey::MOTION_VECTOR_PREPASS) {
|
||||||
if key
|
|
||||||
.mesh_key
|
|
||||||
.contains(MeshPipelineKey::MOTION_VECTOR_PREPASS)
|
|
||||||
{
|
|
||||||
shader_defs.push("MOTION_VECTOR_PREPASS".into());
|
shader_defs.push("MOTION_VECTOR_PREPASS".into());
|
||||||
}
|
}
|
||||||
|
if mesh_key.contains(MeshPipelineKey::HAS_PREVIOUS_SKIN) {
|
||||||
if key.mesh_key.contains(MeshPipelineKey::HAS_PREVIOUS_SKIN) {
|
|
||||||
shader_defs.push("HAS_PREVIOUS_SKIN".into());
|
shader_defs.push("HAS_PREVIOUS_SKIN".into());
|
||||||
}
|
}
|
||||||
|
if mesh_key.contains(MeshPipelineKey::HAS_PREVIOUS_MORPH) {
|
||||||
if key.mesh_key.contains(MeshPipelineKey::HAS_PREVIOUS_MORPH) {
|
|
||||||
shader_defs.push("HAS_PREVIOUS_MORPH".into());
|
shader_defs.push("HAS_PREVIOUS_MORPH".into());
|
||||||
}
|
}
|
||||||
|
|
||||||
// If bindless mode is on, add a `BINDLESS` define.
|
|
||||||
if self.material_pipeline.bindless {
|
|
||||||
shader_defs.push("BINDLESS".into());
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.binding_arrays_are_usable {
|
if self.binding_arrays_are_usable {
|
||||||
shader_defs.push("MULTIPLE_LIGHTMAPS_IN_ARRAY".into());
|
shader_defs.push("MULTIPLE_LIGHTMAPS_IN_ARRAY".into());
|
||||||
}
|
}
|
||||||
|
if mesh_key.contains(MeshPipelineKey::VISIBILITY_RANGE_DITHER) {
|
||||||
if key
|
|
||||||
.mesh_key
|
|
||||||
.contains(MeshPipelineKey::VISIBILITY_RANGE_DITHER)
|
|
||||||
{
|
|
||||||
shader_defs.push("VISIBILITY_RANGE_DITHER".into());
|
shader_defs.push("VISIBILITY_RANGE_DITHER".into());
|
||||||
}
|
}
|
||||||
|
if mesh_key.intersects(
|
||||||
if key.mesh_key.intersects(
|
|
||||||
MeshPipelineKey::NORMAL_PREPASS
|
MeshPipelineKey::NORMAL_PREPASS
|
||||||
| MeshPipelineKey::MOTION_VECTOR_PREPASS
|
| MeshPipelineKey::MOTION_VECTOR_PREPASS
|
||||||
| MeshPipelineKey::DEFERRED_PREPASS,
|
| MeshPipelineKey::DEFERRED_PREPASS,
|
||||||
) {
|
) {
|
||||||
shader_defs.push("PREPASS_FRAGMENT".into());
|
shader_defs.push("PREPASS_FRAGMENT".into());
|
||||||
}
|
}
|
||||||
|
|
||||||
let bind_group = setup_morph_and_skinning_defs(
|
let bind_group = setup_morph_and_skinning_defs(
|
||||||
&self.mesh_layouts,
|
&self.mesh_layouts,
|
||||||
layout,
|
layout,
|
||||||
5,
|
5,
|
||||||
&key.mesh_key,
|
&mesh_key,
|
||||||
&mut shader_defs,
|
&mut shader_defs,
|
||||||
&mut vertex_attributes,
|
&mut vertex_attributes,
|
||||||
self.skins_use_uniform_buffers,
|
self.skins_use_uniform_buffers,
|
||||||
);
|
);
|
||||||
bind_group_layouts.insert(1, bind_group);
|
bind_group_layouts.insert(1, bind_group);
|
||||||
|
|
||||||
let vertex_buffer_layout = layout.0.get_layout(&vertex_attributes)?;
|
let vertex_buffer_layout = layout.0.get_layout(&vertex_attributes)?;
|
||||||
|
|
||||||
// Setup prepass fragment targets - normals in slot 0 (or None if not needed), motion vectors in slot 1
|
// Setup prepass fragment targets - normals in slot 0 (or None if not needed), motion vectors in slot 1
|
||||||
let mut targets = prepass_target_descriptors(
|
let mut targets = prepass_target_descriptors(
|
||||||
key.mesh_key.contains(MeshPipelineKey::NORMAL_PREPASS),
|
mesh_key.contains(MeshPipelineKey::NORMAL_PREPASS),
|
||||||
key.mesh_key
|
mesh_key.contains(MeshPipelineKey::MOTION_VECTOR_PREPASS),
|
||||||
.contains(MeshPipelineKey::MOTION_VECTOR_PREPASS),
|
mesh_key.contains(MeshPipelineKey::DEFERRED_PREPASS),
|
||||||
key.mesh_key.contains(MeshPipelineKey::DEFERRED_PREPASS),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if targets.iter().all(Option::is_none) {
|
if targets.iter().all(Option::is_none) {
|
||||||
@ -619,12 +599,12 @@ where
|
|||||||
// prepass shader, or we are emulating unclipped depth in the fragment shader.
|
// prepass shader, or we are emulating unclipped depth in the fragment shader.
|
||||||
let fragment_required = !targets.is_empty()
|
let fragment_required = !targets.is_empty()
|
||||||
|| emulate_unclipped_depth
|
|| emulate_unclipped_depth
|
||||||
|| (key.mesh_key.contains(MeshPipelineKey::MAY_DISCARD)
|
|| (mesh_key.contains(MeshPipelineKey::MAY_DISCARD)
|
||||||
&& self.prepass_material_fragment_shader.is_some());
|
&& self.prepass_material_fragment_shader.is_some());
|
||||||
|
|
||||||
let fragment = fragment_required.then(|| {
|
let fragment = fragment_required.then(|| {
|
||||||
// Use the fragment shader from the material
|
// Use the fragment shader from the material
|
||||||
let frag_shader_handle = if key.mesh_key.contains(MeshPipelineKey::DEFERRED_PREPASS) {
|
let frag_shader_handle = if mesh_key.contains(MeshPipelineKey::DEFERRED_PREPASS) {
|
||||||
match self.deferred_material_fragment_shader.clone() {
|
match self.deferred_material_fragment_shader.clone() {
|
||||||
Some(frag_shader_handle) => frag_shader_handle,
|
Some(frag_shader_handle) => frag_shader_handle,
|
||||||
_ => PREPASS_SHADER_HANDLE,
|
_ => PREPASS_SHADER_HANDLE,
|
||||||
@ -645,7 +625,7 @@ where
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Use the vertex shader from the material if present
|
// Use the vertex shader from the material if present
|
||||||
let vert_shader_handle = if key.mesh_key.contains(MeshPipelineKey::DEFERRED_PREPASS) {
|
let vert_shader_handle = if mesh_key.contains(MeshPipelineKey::DEFERRED_PREPASS) {
|
||||||
if let Some(handle) = &self.deferred_material_vertex_shader {
|
if let Some(handle) = &self.deferred_material_vertex_shader {
|
||||||
handle.clone()
|
handle.clone()
|
||||||
} else {
|
} else {
|
||||||
@ -656,8 +636,7 @@ where
|
|||||||
} else {
|
} else {
|
||||||
PREPASS_SHADER_HANDLE
|
PREPASS_SHADER_HANDLE
|
||||||
};
|
};
|
||||||
|
let descriptor = RenderPipelineDescriptor {
|
||||||
let mut descriptor = RenderPipelineDescriptor {
|
|
||||||
vertex: VertexState {
|
vertex: VertexState {
|
||||||
shader: vert_shader_handle,
|
shader: vert_shader_handle,
|
||||||
entry_point: "vertex".into(),
|
entry_point: "vertex".into(),
|
||||||
@ -667,7 +646,7 @@ where
|
|||||||
fragment,
|
fragment,
|
||||||
layout: bind_group_layouts,
|
layout: bind_group_layouts,
|
||||||
primitive: PrimitiveState {
|
primitive: PrimitiveState {
|
||||||
topology: key.mesh_key.primitive_topology(),
|
topology: mesh_key.primitive_topology(),
|
||||||
strip_index_format: None,
|
strip_index_format: None,
|
||||||
front_face: FrontFace::Ccw,
|
front_face: FrontFace::Ccw,
|
||||||
cull_mode: None,
|
cull_mode: None,
|
||||||
@ -692,7 +671,7 @@ where
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
multisample: MultisampleState {
|
multisample: MultisampleState {
|
||||||
count: key.mesh_key.msaa_samples(),
|
count: mesh_key.msaa_samples(),
|
||||||
mask: !0,
|
mask: !0,
|
||||||
alpha_to_coverage_enabled: false,
|
alpha_to_coverage_enabled: false,
|
||||||
},
|
},
|
||||||
@ -700,12 +679,6 @@ where
|
|||||||
label: Some("prepass_pipeline".into()),
|
label: Some("prepass_pipeline".into()),
|
||||||
zero_initialize_workgroup_memory: false,
|
zero_initialize_workgroup_memory: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
// This is a bit risky because it's possible to change something that would
|
|
||||||
// break the prepass but be fine in the main pass.
|
|
||||||
// Since this api is pretty low-level it doesn't matter that much, but it is a potential issue.
|
|
||||||
M::specialize(&self.material_pipeline, &mut descriptor, layout, key)?;
|
|
||||||
|
|
||||||
Ok(descriptor)
|
Ok(descriptor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -790,7 +763,7 @@ pub fn prepare_prepass_view_bind_group<M: Material>(
|
|||||||
) {
|
) {
|
||||||
prepass_view_bind_group.no_motion_vectors = Some(render_device.create_bind_group(
|
prepass_view_bind_group.no_motion_vectors = Some(render_device.create_bind_group(
|
||||||
"prepass_view_no_motion_vectors_bind_group",
|
"prepass_view_no_motion_vectors_bind_group",
|
||||||
&prepass_pipeline.view_layout_no_motion_vectors,
|
&prepass_pipeline.internal.view_layout_no_motion_vectors,
|
||||||
&BindGroupEntries::with_indices((
|
&BindGroupEntries::with_indices((
|
||||||
(0, view_binding.clone()),
|
(0, view_binding.clone()),
|
||||||
(1, globals_binding.clone()),
|
(1, globals_binding.clone()),
|
||||||
@ -801,7 +774,7 @@ pub fn prepare_prepass_view_bind_group<M: Material>(
|
|||||||
if let Some(previous_view_uniforms_binding) = previous_view_uniforms.uniforms.binding() {
|
if let Some(previous_view_uniforms_binding) = previous_view_uniforms.uniforms.binding() {
|
||||||
prepass_view_bind_group.motion_vectors = Some(render_device.create_bind_group(
|
prepass_view_bind_group.motion_vectors = Some(render_device.create_bind_group(
|
||||||
"prepass_view_motion_vectors_bind_group",
|
"prepass_view_motion_vectors_bind_group",
|
||||||
&prepass_pipeline.view_layout_motion_vectors,
|
&prepass_pipeline.internal.view_layout_motion_vectors,
|
||||||
&BindGroupEntries::with_indices((
|
&BindGroupEntries::with_indices((
|
||||||
(0, view_binding),
|
(0, view_binding),
|
||||||
(1, globals_binding),
|
(1, globals_binding),
|
||||||
|
Loading…
Reference in New Issue
Block a user