Use SmallVec instead of HashMap in MaterialProperties (#19846)
# Objective - MaterialProperties uses HashMap for some data that is generally going to be really small. This is likely using more memory than necessary ## Solution - Use a SmallVec instead - I used the size a StandardMaterial would need for all the backing arrays ## Testing - Tested the 3d_scene to confirm it still works ## Notes I'm not sure if it made a measurable difference since I'm not sure how to measure this. It's a bit hard to create an artificial workflow where this would be the main bottleneck. This is very in the realm of microoptimization.
This commit is contained in:
parent
fb2bbb043c
commit
37bbbf753d
@ -1300,8 +1300,11 @@ pub struct MaterialProperties {
|
||||
pub reads_view_transmission_texture: bool,
|
||||
pub render_phase_type: RenderPhaseType,
|
||||
pub material_layout: Option<BindGroupLayout>,
|
||||
pub draw_functions: HashMap<InternedDrawFunctionLabel, DrawFunctionId>,
|
||||
pub shaders: HashMap<InternedShaderLabel, Handle<Shader>>,
|
||||
/// Backing array is a size of 4 because the `StandardMaterial` needs 4 draw functions by default
|
||||
pub draw_functions: SmallVec<[(InternedDrawFunctionLabel, DrawFunctionId); 4]>,
|
||||
/// Backing array is a size of 3 because the `StandardMaterial` has 3 custom shaders (`frag`, `prepass_frag`, `deferred_frag`) which is the
|
||||
/// most common use case
|
||||
pub shaders: SmallVec<[(InternedShaderLabel, Handle<Shader>); 3]>,
|
||||
/// Whether this material *actually* uses bindless resources, taking the
|
||||
/// platform support (or lack thereof) of bindless resources into account.
|
||||
pub bindless: bool,
|
||||
@ -1320,27 +1323,31 @@ pub struct MaterialProperties {
|
||||
|
||||
impl MaterialProperties {
|
||||
pub fn get_shader(&self, label: impl ShaderLabel) -> Option<Handle<Shader>> {
|
||||
self.shaders.get(&label.intern()).cloned()
|
||||
self.shaders
|
||||
.iter()
|
||||
.find(|(inner_label, _)| inner_label == &label.intern())
|
||||
.map(|(_, shader)| shader)
|
||||
.cloned()
|
||||
}
|
||||
|
||||
pub fn add_shader(
|
||||
&mut self,
|
||||
label: impl ShaderLabel,
|
||||
shader: Handle<Shader>,
|
||||
) -> Option<Handle<Shader>> {
|
||||
self.shaders.insert(label.intern(), shader)
|
||||
pub fn add_shader(&mut self, label: impl ShaderLabel, shader: Handle<Shader>) {
|
||||
self.shaders.push((label.intern(), shader));
|
||||
}
|
||||
|
||||
pub fn get_draw_function(&self, label: impl DrawFunctionLabel) -> Option<DrawFunctionId> {
|
||||
self.draw_functions.get(&label.intern()).copied()
|
||||
self.draw_functions
|
||||
.iter()
|
||||
.find(|(inner_label, _)| inner_label == &label.intern())
|
||||
.map(|(_, shader)| shader)
|
||||
.cloned()
|
||||
}
|
||||
|
||||
pub fn add_draw_function(
|
||||
&mut self,
|
||||
label: impl DrawFunctionLabel,
|
||||
draw_function: DrawFunctionId,
|
||||
) -> Option<DrawFunctionId> {
|
||||
self.draw_functions.insert(label.intern(), draw_function)
|
||||
) {
|
||||
self.draw_functions.push((label.intern(), draw_function));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1472,19 +1479,19 @@ where
|
||||
_ => None,
|
||||
};
|
||||
|
||||
let mut draw_functions = HashMap::new();
|
||||
draw_functions.insert(MaterialDrawFunction.intern(), draw_function_id);
|
||||
let mut draw_functions = SmallVec::new();
|
||||
draw_functions.push((MaterialDrawFunction.intern(), draw_function_id));
|
||||
if let Some(prepass_draw_function_id) = prepass_draw_function_id {
|
||||
draw_functions.insert(PrepassDrawFunction.intern(), prepass_draw_function_id);
|
||||
draw_functions.push((PrepassDrawFunction.intern(), prepass_draw_function_id));
|
||||
}
|
||||
if let Some(deferred_draw_function_id) = deferred_draw_function_id {
|
||||
draw_functions.insert(DeferredDrawFunction.intern(), deferred_draw_function_id);
|
||||
draw_functions.push((DeferredDrawFunction.intern(), deferred_draw_function_id));
|
||||
}
|
||||
if let Some(shadow_draw_function_id) = shadow_draw_function_id {
|
||||
draw_functions.insert(ShadowsDrawFunction.intern(), shadow_draw_function_id);
|
||||
draw_functions.push((ShadowsDrawFunction.intern(), shadow_draw_function_id));
|
||||
}
|
||||
|
||||
let mut shaders = HashMap::new();
|
||||
let mut shaders = SmallVec::new();
|
||||
let mut add_shader = |label: InternedShaderLabel, shader_ref: ShaderRef| {
|
||||
let mayber_shader = match shader_ref {
|
||||
ShaderRef::Default => None,
|
||||
@ -1492,7 +1499,7 @@ where
|
||||
ShaderRef::Path(path) => Some(asset_server.load(path)),
|
||||
};
|
||||
if let Some(shader) = mayber_shader {
|
||||
shaders.insert(label, shader);
|
||||
shaders.push((label, shader));
|
||||
}
|
||||
};
|
||||
add_shader(MaterialVertexShader.intern(), M::vertex_shader());
|
||||
|
@ -553,27 +553,18 @@ impl PrepassPipelineInternal {
|
||||
|| emulate_unclipped_depth
|
||||
|| (mesh_key.contains(MeshPipelineKey::MAY_DISCARD)
|
||||
&& material_properties
|
||||
.shaders
|
||||
.get(&PrepassFragmentShader.intern())
|
||||
.get_shader(PrepassFragmentShader)
|
||||
.is_some());
|
||||
|
||||
let fragment = fragment_required.then(|| {
|
||||
// Use the fragment shader from the material
|
||||
let frag_shader_handle = if mesh_key.contains(MeshPipelineKey::DEFERRED_PREPASS) {
|
||||
match material_properties
|
||||
.shaders
|
||||
.get(&DeferredFragmentShader.intern())
|
||||
.cloned()
|
||||
{
|
||||
match material_properties.get_shader(DeferredFragmentShader) {
|
||||
Some(frag_shader_handle) => frag_shader_handle,
|
||||
None => self.default_prepass_shader.clone(),
|
||||
}
|
||||
} else {
|
||||
match material_properties
|
||||
.shaders
|
||||
.get(&PrepassFragmentShader.intern())
|
||||
.cloned()
|
||||
{
|
||||
match material_properties.get_shader(PrepassFragmentShader) {
|
||||
Some(frag_shader_handle) => frag_shader_handle,
|
||||
None => self.default_prepass_shader.clone(),
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user