mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +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::{
|
||||
mesh::MeshVertexBufferLayoutRef, render_asset::RenderAssets, render_resource::*,
|
||||
};
|
||||
use bitflags::bitflags;
|
||||
|
||||
use crate::deferred::DEFAULT_PBR_DEFERRED_LIGHTING_PASS_ID;
|
||||
use crate::*;
|
||||
|
@ -751,30 +752,56 @@ impl AsBindGroupShaderType<StandardMaterialUniform> for StandardMaterial {
|
|||
}
|
||||
}
|
||||
|
||||
/// The pipeline key for [`StandardMaterial`].
|
||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||
pub struct StandardMaterialKey {
|
||||
normal_map: bool,
|
||||
cull_mode: Option<Face>,
|
||||
depth_bias: i32,
|
||||
relief_mapping: bool,
|
||||
diffuse_transmission: bool,
|
||||
specular_transmission: bool,
|
||||
bitflags! {
|
||||
/// The pipeline key for `StandardMaterial`, packed into 64 bits.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct StandardMaterialKey: u64 {
|
||||
const CULL_FRONT = 0x01;
|
||||
const CULL_BACK = 0x02;
|
||||
const NORMAL_MAP = 0x04;
|
||||
const RELIEF_MAPPING = 0x08;
|
||||
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 {
|
||||
fn from(material: &StandardMaterial) -> Self {
|
||||
StandardMaterialKey {
|
||||
normal_map: material.normal_map_texture.is_some(),
|
||||
cull_mode: material.cull_mode,
|
||||
depth_bias: material.depth_bias as i32,
|
||||
relief_mapping: matches!(
|
||||
let mut key = StandardMaterialKey::empty();
|
||||
key.set(
|
||||
StandardMaterialKey::CULL_FRONT,
|
||||
material.cull_mode == Some(Face::Front),
|
||||
);
|
||||
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,
|
||||
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() {
|
||||
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());
|
||||
}
|
||||
if key.bind_group_data.relief_mapping {
|
||||
if key
|
||||
.bind_group_data
|
||||
.contains(StandardMaterialKey::RELIEF_MAPPING)
|
||||
{
|
||||
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());
|
||||
}
|
||||
|
||||
if key.bind_group_data.specular_transmission {
|
||||
if key
|
||||
.bind_group_data
|
||||
.contains(StandardMaterialKey::SPECULAR_TRANSMISSION)
|
||||
{
|
||||
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());
|
||||
}
|
||||
}
|
||||
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 {
|
||||
*label = format!("pbr_{}", *label).into();
|
||||
}
|
||||
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(())
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue