Skip to content

Commit

Permalink
HACK: Split batches for skinning or morph targets
Browse files Browse the repository at this point in the history
  • Loading branch information
superdump committed Sep 4, 2023
1 parent 5468edc commit 950abd7
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 9 deletions.
21 changes: 15 additions & 6 deletions crates/bevy_pbr/src/material.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{
render, AlphaMode, DrawMesh, DrawPrepass, EnvironmentMapLight, MeshPipeline, MeshPipelineKey,
MeshTransforms, PrepassPipelinePlugin, PrepassPlugin, ScreenSpaceAmbientOcclusionSettings,
SetMeshBindGroup, SetMeshViewBindGroup, Shadow,
is_skinned, render, AlphaMode, DrawMesh, DrawPrepass, EnvironmentMapLight, MeshFlags,
MeshPipeline, MeshPipelineKey, MeshTransforms, PrepassPipelinePlugin, PrepassPlugin,
ScreenSpaceAmbientOcclusionSettings, SetMeshBindGroup, SetMeshViewBindGroup, Shadow,
};
use bevy_app::{App, Plugin};
use bevy_asset::{AddAsset, AssetEvent, AssetServer, Assets, Handle};
Expand Down Expand Up @@ -409,7 +409,7 @@ pub fn queue_material_meshes<M: Material>(
&Handle<M>,
&mut MaterialBindGroupId,
&Handle<Mesh>,
&MeshTransforms,
&mut MeshTransforms,
)>,
images: Res<RenderAssets<Image>>,
mut views: Query<(
Expand Down Expand Up @@ -494,8 +494,12 @@ pub fn queue_material_meshes<M: Material>(

let rangefinder = view.rangefinder3d();
for visible_entity in &visible_entities.entities {
if let Ok((material_handle, mut material_bind_group_id, mesh_handle, mesh_transforms)) =
material_meshes.get_mut(*visible_entity)
if let Ok((
material_handle,
mut material_bind_group_id,
mesh_handle,
mut mesh_transforms,
)) = material_meshes.get_mut(*visible_entity)
{
if let (Some(mesh), Some(material)) = (
render_meshes.get(mesh_handle),
Expand All @@ -504,8 +508,13 @@ pub fn queue_material_meshes<M: Material>(
let mut mesh_key =
MeshPipelineKey::from_primitive_topology(mesh.primitive_topology)
| view_key;

if is_skinned(&mesh.layout) {
mesh_transforms.flags |= MeshFlags::SKINNED.bits();
}
if mesh.morph_targets.is_some() {
mesh_key |= MeshPipelineKey::MORPH_TARGETS;
mesh_transforms.flags |= MeshFlags::MORPH_TARGETS.bits();
}
match material.properties.alpha_mode {
AlphaMode::Blend => {
Expand Down
9 changes: 7 additions & 2 deletions crates/bevy_pbr/src/render/mesh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,8 +247,10 @@ impl From<&MeshTransforms> for MeshUniform {
// NOTE: These must match the bit flags in bevy_pbr/src/render/mesh_types.wgsl!
bitflags::bitflags! {
#[repr(transparent)]
struct MeshFlags: u32 {
pub struct MeshFlags: u32 {
const SHADOW_RECEIVER = (1 << 0);
const SKINNED = (1 << 1);
const MORPH_TARGETS = (1 << 2);
// Indicates the sign of the determinant of the 3x3 model matrix. If the sign is positive,
// then the flag should be set, else it should not be set.
const SIGN_DETERMINANT_MODEL_3X3 = (1 << 31);
Expand Down Expand Up @@ -413,6 +415,7 @@ struct BatchMeta<'mat, 'mesh> {
/// dynamic offsets.
material_binding_meta: Option<&'mat MaterialBindGroupId>,
mesh_handle: Option<&'mesh Handle<Mesh>>,
mesh_flags: u32,
dynamic_offset: Option<NonMaxU32>,
}

Expand All @@ -422,6 +425,7 @@ impl<'mat, 'mesh> BatchMeta<'mat, 'mesh> {
self.pipeline_id == other.pipeline_id
&& self.draw_function_id == other.draw_function_id
&& self.mesh_handle == other.mesh_handle
&& (self.mesh_flags & (MeshFlags::SKINNED | MeshFlags::MORPH_TARGETS).bits()) == 0
&& self.dynamic_offset == other.dynamic_offset
&& (!consider_material || self.material_binding_meta == other.material_binding_meta)
}
Expand Down Expand Up @@ -470,6 +474,7 @@ fn process_phase<I: CachedRenderPipelinePhaseItem>(
draw_function_id: Some(item.draw_function()),
material_binding_meta,
mesh_handle: Some(mesh_handle),
mesh_flags: mesh_transforms.flags,
dynamic_offset: gpu_array_buffer_index.dynamic_offset,
};
if !batch_meta.matches(&batch.meta, consider_material) {
Expand Down Expand Up @@ -939,7 +944,7 @@ impl MeshPipelineKey {
}
}

fn is_skinned(layout: &Hashed<InnerMeshVertexBufferLayout>) -> bool {
pub fn is_skinned(layout: &Hashed<InnerMeshVertexBufferLayout>) -> bool {
layout.contains(Mesh::ATTRIBUTE_JOINT_INDEX) && layout.contains(Mesh::ATTRIBUTE_JOINT_WEIGHT)
}
pub fn setup_morph_and_skinning_defs(
Expand Down
4 changes: 3 additions & 1 deletion crates/bevy_pbr/src/render/mesh_types.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ struct MorphWeights {
};
#endif

const MESH_FLAGS_SHADOW_RECEIVER_BIT: u32 = 1u;
const MESH_FLAGS_SHADOW_RECEIVER_BIT: u32 = 1u;
const MESH_FLAGS_SKINNED_BIT: u32 = 2u;
const MESH_FLAGS_MORPH_TARGETS_BIT: u32 = 4u;
// 2^31 - if the flag is set, the sign is positive, else it is negative
const MESH_FLAGS_SIGN_DETERMINANT_MODEL_3X3_BIT: u32 = 2147483648u;

0 comments on commit 950abd7

Please sign in to comment.