Skip to content

Commit 7f65740

Browse files
committed
Optimize meshlet material pipeline preparation
1 parent 5330b01 commit 7f65740

File tree

1 file changed

+155
-149
lines changed

1 file changed

+155
-149
lines changed

crates/bevy_pbr/src/meshlet/material_pipeline_prepare.rs

Lines changed: 155 additions & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use bevy_platform::collections::{HashMap, HashSet};
2020
use bevy_render::erased_render_asset::ErasedRenderAssets;
2121
use bevy_render::{camera::TemporalJitter, render_resource::*, view::ExtractedView};
2222
use bevy_utils::default;
23-
use core::any::{Any, TypeId};
23+
use core::any::TypeId;
2424

2525
/// A list of `(Material ID, Pipeline, BindGroup)` for a view for use in [`meshlet_main_opaque_pass`](`super::meshlet_main_opaque_pass`).
2626
#[derive(Component, Deref, DerefMut, Default)]
@@ -165,79 +165,84 @@ pub fn prepare_material_meshlet_meshes_main_opaque_pass(
165165
continue;
166166
}
167167

168-
let erased_key = ErasedMaterialPipelineKey {
169-
mesh_key: ErasedMeshPipelineKey::new(view_key),
170-
material_key: material.properties.material_key.clone(),
171-
type_id: material_id.type_id(),
172-
};
173-
let material_pipeline_specializer = MaterialPipelineSpecializer {
174-
pipeline: material_pipeline.clone(),
175-
properties: material.properties.clone(),
176-
};
177-
let Ok(material_pipeline_descriptor) =
178-
material_pipeline_specializer.specialize(erased_key, fake_vertex_buffer_layout)
179-
else {
180-
continue;
181-
};
182-
let material_fragment = material_pipeline_descriptor.fragment.unwrap();
183-
184-
let mut shader_defs = material_fragment.shader_defs;
185-
shader_defs.push("MESHLET_MESH_MATERIAL_PASS".into());
186-
187-
let layout = mesh_pipeline.get_view_layout(view_key.into());
188-
let layout = vec![
189-
layout.main_layout.clone(),
190-
layout.binding_array_layout.clone(),
191-
resource_manager.material_shade_bind_group_layout.clone(),
192-
material
193-
.properties
194-
.material_layout
195-
.as_ref()
196-
.unwrap()
197-
.clone(),
198-
];
199-
200-
let pipeline_descriptor = RenderPipelineDescriptor {
201-
label: material_pipeline_descriptor.label,
202-
layout,
203-
immediate_size: 0,
204-
vertex: VertexState {
205-
shader: meshlet_pipelines.meshlet_mesh_material.clone(),
206-
shader_defs: shader_defs.clone(),
207-
entry_point: material_pipeline_descriptor.vertex.entry_point,
208-
buffers: Vec::new(),
209-
},
210-
primitive: PrimitiveState::default(),
211-
depth_stencil: Some(DepthStencilState {
212-
format: TextureFormat::Depth16Unorm,
213-
depth_write_enabled: Some(false),
214-
depth_compare: Some(CompareFunction::Equal),
215-
stencil: StencilState::default(),
216-
bias: DepthBiasState::default(),
217-
}),
218-
multisample: MultisampleState::default(),
219-
fragment: Some(FragmentState {
220-
shader: match material.properties.get_shader(MeshletFragmentShader) {
221-
Some(shader) => shader.clone(),
222-
None => meshlet_pipelines.meshlet_mesh_material.clone(),
223-
},
224-
shader_defs,
225-
entry_point: material_fragment.entry_point,
226-
targets: material_fragment.targets,
227-
}),
228-
zero_initialize_workgroup_memory: false,
229-
};
230168
let type_id = material_id.type_id();
231169
let Some(material_bind_group_allocator) = material_bind_group_allocators.get(&type_id)
232170
else {
233171
continue;
234172
};
235-
let material_id = instance_manager.get_material_id(material_id);
236173

237-
let pipeline_id = *cache.entry((view_key, type_id)).or_insert_with(|| {
238-
pipeline_cache.queue_render_pipeline(pipeline_descriptor.clone())
239-
});
174+
let pipeline_id = if let Some(&id) = cache.get(&(view_key, type_id)) {
175+
id
176+
} else {
177+
let erased_key = ErasedMaterialPipelineKey {
178+
mesh_key: ErasedMeshPipelineKey::new(view_key),
179+
material_key: material.properties.material_key.clone(),
180+
type_id,
181+
};
182+
let material_pipeline_specializer = MaterialPipelineSpecializer {
183+
pipeline: material_pipeline.clone(),
184+
properties: material.properties.clone(),
185+
};
186+
let Ok(material_pipeline_descriptor) =
187+
material_pipeline_specializer.specialize(erased_key, fake_vertex_buffer_layout)
188+
else {
189+
continue;
190+
};
191+
let material_fragment = material_pipeline_descriptor.fragment.unwrap();
192+
193+
let mut shader_defs = material_fragment.shader_defs;
194+
shader_defs.push("MESHLET_MESH_MATERIAL_PASS".into());
195+
196+
let layout = mesh_pipeline.get_view_layout(view_key.into());
197+
let layout = vec![
198+
layout.main_layout.clone(),
199+
layout.binding_array_layout.clone(),
200+
resource_manager.material_shade_bind_group_layout.clone(),
201+
material
202+
.properties
203+
.material_layout
204+
.as_ref()
205+
.unwrap()
206+
.clone(),
207+
];
208+
209+
let pipeline_descriptor = RenderPipelineDescriptor {
210+
label: material_pipeline_descriptor.label,
211+
layout,
212+
immediate_size: 0,
213+
vertex: VertexState {
214+
shader: meshlet_pipelines.meshlet_mesh_material.clone(),
215+
shader_defs: shader_defs.clone(),
216+
entry_point: material_pipeline_descriptor.vertex.entry_point,
217+
buffers: Vec::new(),
218+
},
219+
primitive: PrimitiveState::default(),
220+
depth_stencil: Some(DepthStencilState {
221+
format: TextureFormat::Depth16Unorm,
222+
depth_write_enabled: Some(false),
223+
depth_compare: Some(CompareFunction::Equal),
224+
stencil: StencilState::default(),
225+
bias: DepthBiasState::default(),
226+
}),
227+
multisample: MultisampleState::default(),
228+
fragment: Some(FragmentState {
229+
shader: match material.properties.get_shader(MeshletFragmentShader) {
230+
Some(shader) => shader.clone(),
231+
None => meshlet_pipelines.meshlet_mesh_material.clone(),
232+
},
233+
shader_defs,
234+
entry_point: material_fragment.entry_point,
235+
targets: material_fragment.targets,
236+
}),
237+
zero_initialize_workgroup_memory: false,
238+
};
239+
240+
let pipeline_id = pipeline_cache.queue_render_pipeline(pipeline_descriptor);
241+
cache.insert((view_key, type_id), pipeline_id);
242+
pipeline_id
243+
};
240244

245+
let material_id = instance_manager.get_material_id(material_id);
241246
let Some(material_bind_group) =
242247
material_bind_group_allocator.get(material.binding.group)
243248
else {
@@ -318,8 +323,8 @@ pub fn prepare_material_meshlet_meshes_prepass(
318323
let Some(material) = render_materials.get(material_id) else {
319324
continue;
320325
};
321-
let Some(material_bind_group_allocator) =
322-
material_bind_group_allocators.get(&material_id.type_id())
326+
let type_id = material_id.type_id();
327+
let Some(material_bind_group_allocator) = material_bind_group_allocators.get(&type_id)
323328
else {
324329
continue;
325330
};
@@ -340,93 +345,94 @@ pub fn prepare_material_meshlet_meshes_prepass(
340345
continue;
341346
}
342347

343-
let erased_key = ErasedMaterialPipelineKey {
344-
mesh_key: ErasedMeshPipelineKey::new(view_key),
345-
material_key: material.properties.material_key.clone(),
346-
type_id: material_id.type_id(),
347-
};
348-
let material_pipeline_specializer = PrepassPipelineSpecializer {
349-
pipeline: prepass_pipeline.clone(),
350-
properties: material.properties.clone(),
351-
};
352-
let Ok(material_pipeline_descriptor) =
353-
material_pipeline_specializer.specialize(erased_key, fake_vertex_buffer_layout)
354-
else {
355-
continue;
356-
};
357-
let material_fragment = material_pipeline_descriptor.fragment.unwrap();
358-
359-
let mut shader_defs = material_fragment.shader_defs;
360-
shader_defs.push("MESHLET_MESH_MATERIAL_PASS".into());
361-
362-
let view_layout = if view_key.contains(MeshPipelineKey::MOTION_VECTOR_PREPASS) {
363-
prepass_pipeline.view_layout_motion_vectors.clone()
364-
} else {
365-
prepass_pipeline.view_layout_no_motion_vectors.clone()
366-
};
367-
368-
let fragment_shader = if view_key.contains(MeshPipelineKey::DEFERRED_PREPASS) {
369-
material
370-
.properties
371-
.get_shader(MeshletDeferredFragmentShader)
372-
.unwrap_or(meshlet_pipelines.meshlet_mesh_material.clone())
373-
} else {
374-
material
375-
.properties
376-
.get_shader(MeshletPrepassFragmentShader)
377-
.unwrap_or(meshlet_pipelines.meshlet_mesh_material.clone())
378-
};
379-
380-
let entry_point = if fragment_shader == meshlet_pipelines.meshlet_mesh_material {
381-
material_fragment.entry_point.clone()
348+
let pipeline_id = if let Some(&id) = cache.get(&(view_key, type_id)) {
349+
id
382350
} else {
383-
None
384-
};
385-
386-
let pipeline_descriptor = RenderPipelineDescriptor {
387-
label: material_pipeline_descriptor.label,
388-
layout: vec![
389-
view_layout,
390-
prepass_pipeline.empty_layout.clone(),
391-
resource_manager.material_shade_bind_group_layout.clone(),
351+
let erased_key = ErasedMaterialPipelineKey {
352+
mesh_key: ErasedMeshPipelineKey::new(view_key),
353+
material_key: material.properties.material_key.clone(),
354+
type_id,
355+
};
356+
let material_pipeline_specializer = PrepassPipelineSpecializer {
357+
pipeline: prepass_pipeline.clone(),
358+
properties: material.properties.clone(),
359+
};
360+
let Ok(material_pipeline_descriptor) =
361+
material_pipeline_specializer.specialize(erased_key, fake_vertex_buffer_layout)
362+
else {
363+
continue;
364+
};
365+
let material_fragment = material_pipeline_descriptor.fragment.unwrap();
366+
367+
let mut shader_defs = material_fragment.shader_defs;
368+
shader_defs.push("MESHLET_MESH_MATERIAL_PASS".into());
369+
370+
let view_layout = if view_key.contains(MeshPipelineKey::MOTION_VECTOR_PREPASS) {
371+
prepass_pipeline.view_layout_motion_vectors.clone()
372+
} else {
373+
prepass_pipeline.view_layout_no_motion_vectors.clone()
374+
};
375+
376+
let fragment_shader = if view_key.contains(MeshPipelineKey::DEFERRED_PREPASS) {
392377
material
393378
.properties
394-
.material_layout
395-
.as_ref()
396-
.unwrap()
397-
.clone(),
398-
],
399-
vertex: VertexState {
400-
shader: meshlet_pipelines.meshlet_mesh_material.clone(),
401-
shader_defs: shader_defs.clone(),
402-
entry_point: material_pipeline_descriptor.vertex.entry_point,
379+
.get_shader(MeshletDeferredFragmentShader)
380+
.unwrap_or(meshlet_pipelines.meshlet_mesh_material.clone())
381+
} else {
382+
material
383+
.properties
384+
.get_shader(MeshletPrepassFragmentShader)
385+
.unwrap_or(meshlet_pipelines.meshlet_mesh_material.clone())
386+
};
387+
388+
let entry_point = if fragment_shader == meshlet_pipelines.meshlet_mesh_material {
389+
material_fragment.entry_point.clone()
390+
} else {
391+
None
392+
};
393+
394+
let pipeline_descriptor = RenderPipelineDescriptor {
395+
label: material_pipeline_descriptor.label,
396+
layout: vec![
397+
view_layout,
398+
prepass_pipeline.empty_layout.clone(),
399+
resource_manager.material_shade_bind_group_layout.clone(),
400+
material
401+
.properties
402+
.material_layout
403+
.as_ref()
404+
.unwrap()
405+
.clone(),
406+
],
407+
vertex: VertexState {
408+
shader: meshlet_pipelines.meshlet_mesh_material.clone(),
409+
shader_defs: shader_defs.clone(),
410+
entry_point: material_pipeline_descriptor.vertex.entry_point,
411+
..default()
412+
},
413+
primitive: PrimitiveState::default(),
414+
depth_stencil: Some(DepthStencilState {
415+
format: TextureFormat::Depth16Unorm,
416+
depth_write_enabled: Some(false),
417+
depth_compare: Some(CompareFunction::Equal),
418+
stencil: StencilState::default(),
419+
bias: DepthBiasState::default(),
420+
}),
421+
fragment: Some(FragmentState {
422+
shader: fragment_shader,
423+
shader_defs,
424+
entry_point,
425+
targets: material_fragment.targets,
426+
}),
403427
..default()
404-
},
405-
primitive: PrimitiveState::default(),
406-
depth_stencil: Some(DepthStencilState {
407-
format: TextureFormat::Depth16Unorm,
408-
depth_write_enabled: Some(false),
409-
depth_compare: Some(CompareFunction::Equal),
410-
stencil: StencilState::default(),
411-
bias: DepthBiasState::default(),
412-
}),
413-
fragment: Some(FragmentState {
414-
shader: fragment_shader,
415-
shader_defs,
416-
entry_point,
417-
targets: material_fragment.targets,
418-
}),
419-
..default()
428+
};
429+
430+
let pipeline_id = pipeline_cache.queue_render_pipeline(pipeline_descriptor);
431+
cache.insert((view_key, type_id), pipeline_id);
432+
pipeline_id
420433
};
421434

422435
let material_id = instance_manager.get_material_id(material_id);
423-
424-
let pipeline_id = *cache
425-
.entry((view_key, material_id.type_id()))
426-
.or_insert_with(|| {
427-
pipeline_cache.queue_render_pipeline(pipeline_descriptor.clone())
428-
});
429-
430436
let Some(material_bind_group) =
431437
material_bind_group_allocator.get(material.binding.group)
432438
else {

0 commit comments

Comments
 (0)