mirror of
https://github.com/bevyengine/bevy
synced 2024-11-24 21:53:07 +00:00
Pack the StandardMaterialKey
into a single scalar instead of a structure. (#12783)
This commit changes the `StandardMaterialKey` to be based on a set of bitflags instead of a structure. We hash it every frame for every mesh, and `#[derive(Hash)]` doesn't generate particularly efficient code for large structures full of small types. Packing it into a single `u64` therefore results in a roughly 10% speedup in `queue_material_meshes` on `many_cubes --no-frustum-culling`. ![Screenshot 2024-03-29 075124](https://github.com/bevyengine/bevy/assets/157897/78afcab6-b616-489b-8243-da9a117f606c)
This commit is contained in:
parent
fee824413f
commit
5b746d2b19
1 changed files with 78 additions and 25 deletions
|
@ -5,6 +5,7 @@ use bevy_reflect::{std_traits::ReflectDefault, Reflect};
|
||||||
use bevy_render::{
|
use bevy_render::{
|
||||||
mesh::MeshVertexBufferLayoutRef, render_asset::RenderAssets, render_resource::*,
|
mesh::MeshVertexBufferLayoutRef, render_asset::RenderAssets, render_resource::*,
|
||||||
};
|
};
|
||||||
|
use bitflags::bitflags;
|
||||||
|
|
||||||
use crate::deferred::DEFAULT_PBR_DEFERRED_LIGHTING_PASS_ID;
|
use crate::deferred::DEFAULT_PBR_DEFERRED_LIGHTING_PASS_ID;
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
@ -751,30 +752,56 @@ impl AsBindGroupShaderType<StandardMaterialUniform> for StandardMaterial {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The pipeline key for [`StandardMaterial`].
|
bitflags! {
|
||||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
/// The pipeline key for `StandardMaterial`, packed into 64 bits.
|
||||||
pub struct StandardMaterialKey {
|
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
normal_map: bool,
|
pub struct StandardMaterialKey: u64 {
|
||||||
cull_mode: Option<Face>,
|
const CULL_FRONT = 0x01;
|
||||||
depth_bias: i32,
|
const CULL_BACK = 0x02;
|
||||||
relief_mapping: bool,
|
const NORMAL_MAP = 0x04;
|
||||||
diffuse_transmission: bool,
|
const RELIEF_MAPPING = 0x08;
|
||||||
specular_transmission: bool,
|
const DIFFUSE_TRANSMISSION = 0x10;
|
||||||
|
const SPECULAR_TRANSMISSION = 0x20;
|
||||||
|
const DEPTH_BIAS = 0xffffffff_00000000;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const STANDARD_MATERIAL_KEY_DEPTH_BIAS_SHIFT: u64 = 32;
|
||||||
|
|
||||||
impl From<&StandardMaterial> for StandardMaterialKey {
|
impl From<&StandardMaterial> for StandardMaterialKey {
|
||||||
fn from(material: &StandardMaterial) -> Self {
|
fn from(material: &StandardMaterial) -> Self {
|
||||||
StandardMaterialKey {
|
let mut key = StandardMaterialKey::empty();
|
||||||
normal_map: material.normal_map_texture.is_some(),
|
key.set(
|
||||||
cull_mode: material.cull_mode,
|
StandardMaterialKey::CULL_FRONT,
|
||||||
depth_bias: material.depth_bias as i32,
|
material.cull_mode == Some(Face::Front),
|
||||||
relief_mapping: matches!(
|
);
|
||||||
|
key.set(
|
||||||
|
StandardMaterialKey::CULL_BACK,
|
||||||
|
material.cull_mode == Some(Face::Back),
|
||||||
|
);
|
||||||
|
key.set(
|
||||||
|
StandardMaterialKey::NORMAL_MAP,
|
||||||
|
material.normal_map_texture.is_some(),
|
||||||
|
);
|
||||||
|
key.set(
|
||||||
|
StandardMaterialKey::RELIEF_MAPPING,
|
||||||
|
matches!(
|
||||||
material.parallax_mapping_method,
|
material.parallax_mapping_method,
|
||||||
ParallaxMappingMethod::Relief { .. }
|
ParallaxMappingMethod::Relief { .. }
|
||||||
),
|
),
|
||||||
diffuse_transmission: material.diffuse_transmission > 0.0,
|
);
|
||||||
specular_transmission: material.specular_transmission > 0.0,
|
key.set(
|
||||||
}
|
StandardMaterialKey::DIFFUSE_TRANSMISSION,
|
||||||
|
material.diffuse_transmission > 0.0,
|
||||||
|
);
|
||||||
|
key.set(
|
||||||
|
StandardMaterialKey::SPECULAR_TRANSMISSION,
|
||||||
|
material.specular_transmission > 0.0,
|
||||||
|
);
|
||||||
|
key.insert(StandardMaterialKey::from_bits_retain(
|
||||||
|
(material.depth_bias as u64) << STANDARD_MATERIAL_KEY_DEPTH_BIAS_SHIFT,
|
||||||
|
));
|
||||||
|
key
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -847,32 +874,58 @@ impl Material for StandardMaterial {
|
||||||
if let Some(fragment) = descriptor.fragment.as_mut() {
|
if let Some(fragment) = descriptor.fragment.as_mut() {
|
||||||
let shader_defs = &mut fragment.shader_defs;
|
let shader_defs = &mut fragment.shader_defs;
|
||||||
|
|
||||||
if key.bind_group_data.normal_map {
|
if key
|
||||||
|
.bind_group_data
|
||||||
|
.contains(StandardMaterialKey::NORMAL_MAP)
|
||||||
|
{
|
||||||
shader_defs.push("STANDARD_MATERIAL_NORMAL_MAP".into());
|
shader_defs.push("STANDARD_MATERIAL_NORMAL_MAP".into());
|
||||||
}
|
}
|
||||||
if key.bind_group_data.relief_mapping {
|
if key
|
||||||
|
.bind_group_data
|
||||||
|
.contains(StandardMaterialKey::RELIEF_MAPPING)
|
||||||
|
{
|
||||||
shader_defs.push("RELIEF_MAPPING".into());
|
shader_defs.push("RELIEF_MAPPING".into());
|
||||||
}
|
}
|
||||||
|
|
||||||
if key.bind_group_data.diffuse_transmission {
|
if key
|
||||||
|
.bind_group_data
|
||||||
|
.contains(StandardMaterialKey::DIFFUSE_TRANSMISSION)
|
||||||
|
{
|
||||||
shader_defs.push("STANDARD_MATERIAL_DIFFUSE_TRANSMISSION".into());
|
shader_defs.push("STANDARD_MATERIAL_DIFFUSE_TRANSMISSION".into());
|
||||||
}
|
}
|
||||||
|
|
||||||
if key.bind_group_data.specular_transmission {
|
if key
|
||||||
|
.bind_group_data
|
||||||
|
.contains(StandardMaterialKey::SPECULAR_TRANSMISSION)
|
||||||
|
{
|
||||||
shader_defs.push("STANDARD_MATERIAL_SPECULAR_TRANSMISSION".into());
|
shader_defs.push("STANDARD_MATERIAL_SPECULAR_TRANSMISSION".into());
|
||||||
}
|
}
|
||||||
|
|
||||||
if key.bind_group_data.diffuse_transmission || key.bind_group_data.specular_transmission
|
if key.bind_group_data.intersects(
|
||||||
{
|
StandardMaterialKey::DIFFUSE_TRANSMISSION
|
||||||
|
| StandardMaterialKey::SPECULAR_TRANSMISSION,
|
||||||
|
) {
|
||||||
shader_defs.push("STANDARD_MATERIAL_SPECULAR_OR_DIFFUSE_TRANSMISSION".into());
|
shader_defs.push("STANDARD_MATERIAL_SPECULAR_OR_DIFFUSE_TRANSMISSION".into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
descriptor.primitive.cull_mode = key.bind_group_data.cull_mode;
|
|
||||||
|
descriptor.primitive.cull_mode = if key
|
||||||
|
.bind_group_data
|
||||||
|
.contains(StandardMaterialKey::CULL_FRONT)
|
||||||
|
{
|
||||||
|
Some(Face::Front)
|
||||||
|
} else if key.bind_group_data.contains(StandardMaterialKey::CULL_BACK) {
|
||||||
|
Some(Face::Back)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
if let Some(label) = &mut descriptor.label {
|
if let Some(label) = &mut descriptor.label {
|
||||||
*label = format!("pbr_{}", *label).into();
|
*label = format!("pbr_{}", *label).into();
|
||||||
}
|
}
|
||||||
if let Some(depth_stencil) = descriptor.depth_stencil.as_mut() {
|
if let Some(depth_stencil) = descriptor.depth_stencil.as_mut() {
|
||||||
depth_stencil.bias.constant = key.bind_group_data.depth_bias;
|
depth_stencil.bias.constant =
|
||||||
|
(key.bind_group_data.bits() >> STANDARD_MATERIAL_KEY_DEPTH_BIAS_SHIFT) as i32;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue