Skip to content

Commit

Permalink
Insert NoAutomaticBatching onto skinned main world entities
Browse files Browse the repository at this point in the history
  • Loading branch information
superdump committed Sep 26, 2023
1 parent 29ae71f commit 18802e5
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 25 deletions.
23 changes: 14 additions & 9 deletions crates/bevy_pbr/src/render/mesh.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
use crate::{
environment_map, prepass, render::morph::MorphIndices, EnvironmentMapLight, FogMeta,
GlobalLightMeta, GpuFog, GpuLights, GpuPointLights, LightMeta, MaterialBindGroupId,
NotShadowCaster, NotShadowReceiver, PreviousGlobalTransform,
environment_map, prepass,
render::{
morph::{no_automatic_morph_batching, MorphIndices},
skin::no_automatic_skin_batching,
},
EnvironmentMapLight, FogMeta, GlobalLightMeta, GpuFog, GpuLights, GpuPointLights, LightMeta,
MaterialBindGroupId, NotShadowCaster, NotShadowReceiver, PreviousGlobalTransform,
ScreenSpaceAmbientOcclusionTextures, Shadow, ShadowSamplers, ViewClusterBindings,
ViewFogUniformOffset, ViewLightsUniformOffset, ViewShadowBindings,
CLUSTERED_FORWARD_STORAGE_BUFFER_COUNT, MAX_CASCADES_PER_LIGHT, MAX_DIRECTIONAL_LIGHTS,
};
use bevy_app::Plugin;
use bevy_app::{Plugin, PostUpdate};
use bevy_asset::{load_internal_asset, AssetId, Handle};
use bevy_core_pipeline::{
core_3d::{AlphaMask3d, Opaque3d, Transparent3d},
Expand Down Expand Up @@ -109,6 +113,11 @@ impl Plugin for MeshRenderPlugin {
load_internal_asset!(app, SKINNING_HANDLE, "skinning.wgsl", Shader::from_wgsl);
load_internal_asset!(app, MORPH_HANDLE, "morph.wgsl", Shader::from_wgsl);

app.add_systems(
PostUpdate,
(no_automatic_skin_batching, no_automatic_morph_batching),
);

if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
render_app
.init_resource::<RenderMeshInstances>()
Expand All @@ -119,11 +128,7 @@ impl Plugin for MeshRenderPlugin {
.init_resource::<MorphIndices>()
.add_systems(
ExtractSchedule,
(
extract_meshes,
extract_skins.after(extract_meshes),
extract_morphs.after(extract_meshes),
),
(extract_meshes, extract_skins, extract_morphs),
)
.add_systems(
Render,
Expand Down
20 changes: 12 additions & 8 deletions crates/bevy_pbr/src/render/morph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::{iter, mem};
use bevy_derive::{Deref, DerefMut};
use bevy_ecs::prelude::*;
use bevy_render::{
batching::NoAutomaticBatching,
mesh::morph::{MeshMorphWeights, MAX_MORPH_WEIGHTS},
render_resource::{BufferUsages, BufferVec},
renderer::{RenderDevice, RenderQueue},
Expand All @@ -12,8 +13,6 @@ use bevy_render::{
use bevy_utils::PassHashMap;
use bytemuck::Pod;

use crate::RenderMeshInstances;

#[derive(Component)]
pub struct MorphIndex {
pub(super) index: u32,
Expand Down Expand Up @@ -83,7 +82,6 @@ fn add_to_alignment<T: Pod + Default>(buffer: &mut BufferVec<T>) {
pub fn extract_morphs(
mut morph_indices: ResMut<MorphIndices>,
mut uniform: ResMut<MorphUniform>,
mut mesh_instances: ResMut<RenderMeshInstances>,
query: Extract<Query<(Entity, &ViewVisibility, &MeshMorphWeights)>>,
) {
morph_indices.clear();
Expand All @@ -101,10 +99,16 @@ pub fn extract_morphs(

let index = (start * mem::size_of::<f32>()) as u32;
morph_indices.insert(entity, MorphIndex { index });
// NOTE: Because morph targets require per-morph target texture bindings, they cannot
// currently be batched.
mesh_instances
.get_mut(&entity)
.map(|mesh_instance| mesh_instance.automatic_batching = false);
}
}

// NOTE: Because morph targets require per-morph target texture bindings, they cannot
// currently be batched.
pub fn no_automatic_morph_batching(
mut commands: Commands,
query: Query<Entity, (With<MeshMorphWeights>, Without<NoAutomaticBatching>)>,
) {
for entity in &query {
commands.entity(entity).insert(NoAutomaticBatching);
}
}
20 changes: 12 additions & 8 deletions crates/bevy_pbr/src/render/skin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use bevy_derive::{Deref, DerefMut};
use bevy_ecs::prelude::*;
use bevy_math::Mat4;
use bevy_render::{
batching::NoAutomaticBatching,
mesh::skinning::{SkinnedMesh, SkinnedMeshInverseBindposes},
render_resource::{BufferUsages, BufferVec},
renderer::{RenderDevice, RenderQueue},
Expand All @@ -12,8 +13,6 @@ use bevy_render::{
use bevy_transform::prelude::GlobalTransform;
use bevy_utils::PassHashMap;

use crate::RenderMeshInstances;

/// Maximum number of joints supported for skinned meshes.
pub const MAX_JOINTS: usize = 256;

Expand Down Expand Up @@ -91,7 +90,6 @@ pub fn prepare_skins(
pub fn extract_skins(
mut skin_indices: ResMut<SkinIndices>,
mut uniform: ResMut<SkinUniform>,
mut mesh_instances: ResMut<RenderMeshInstances>,
query: Extract<Query<(Entity, &ViewVisibility, &SkinnedMesh)>>,
inverse_bindposes: Extract<Res<Assets<SkinnedMeshInverseBindposes>>>,
joints: Extract<Query<&GlobalTransform>>,
Expand Down Expand Up @@ -132,15 +130,21 @@ pub fn extract_skins(
}

skin_indices.insert(entity, SkinIndex::new(start));
// NOTE: The skinned joints uniform buffer has to be bound at a dynamic offset per
// entity and so cannot currently be batched.
mesh_instances
.get_mut(&entity)
.map(|mesh_instance| mesh_instance.automatic_batching = false);
}

// Pad out the buffer to ensure that there's enough space for bindings
while uniform.buffer.len() - last_start < MAX_JOINTS {
uniform.buffer.push(Mat4::ZERO);
}
}

// NOTE: The skinned joints uniform buffer has to be bound at a dynamic offset per
// entity and so cannot currently be batched.
pub fn no_automatic_skin_batching(
mut commands: Commands,
query: Query<Entity, (With<SkinnedMesh>, Without<NoAutomaticBatching>)>,
) {
for entity in &query {
commands.entity(entity).insert(NoAutomaticBatching);
}
}

0 comments on commit 18802e5

Please sign in to comment.