Skip to content

Commit

Permalink
Revert to more sensible mesh_bindings.rs
Browse files Browse the repository at this point in the history
  • Loading branch information
nicopap committed Sep 27, 2023
1 parent 5572f8b commit 56e802f
Show file tree
Hide file tree
Showing 6 changed files with 333 additions and 412 deletions.
2 changes: 0 additions & 2 deletions crates/bevy_core_pipeline/src/taa/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,6 @@ pub struct TemporalAntiAliasBundle {
///
/// Cannot be used with [`bevy_render::camera::OrthographicProjection`].
///
/// Currently does not support skinned meshes and morph targets.
/// There will probably be ghosting artifacts if used with them.
/// Does not work well with alpha-blended meshes as it requires depth writing to determine motion.
///
/// It is very important that correct motion vectors are written for everything on screen.
Expand Down
22 changes: 9 additions & 13 deletions crates/bevy_pbr/src/prepass/prepass.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ fn morph_vertex(vertex_in: Vertex) -> Vertex {
fn morph_previous_position(vertex: Vertex) -> vec3<f32> {
var vertex_position = vertex.position;
let weight_count = bevy_pbr::morph::layer_count();
for (var i: u32 = 0u, i < weight_count; i++) {
for (var i: u32 = 0u; i < weight_count; i++) {
let weight = bevy_pbr::morph::previous_weight_at(i);
if weight != 0.0 {
vertex_position += weight * bevy_pbr::morph::morph(vertex.index, bevy_pbr::morph::position_offset, i);
Expand All @@ -96,6 +96,10 @@ fn morph_previous_position(vertex: Vertex) -> vec3<f32> {
fn vertex(vertex_no_morph: Vertex) -> VertexOutput {
var out: VertexOutput;

// Use vertex_no_morph.instance_index instead of vertex.instance_index to work around a wgpu dx12 bug.
// See https://github.com/gfx-rs/naga/issues/2416
let vertex_instance = vertex_no_morph.instance_index;

#ifdef MORPH_TARGETS
var vertex = morph_vertex(vertex_no_morph);
#else
Expand All @@ -105,9 +109,7 @@ fn vertex(vertex_no_morph: Vertex) -> VertexOutput {
#ifdef SKINNED
var model = bevy_pbr::skinning::skin_model(vertex.joint_indices, vertex.joint_weights);
#else // SKINNED
// Use vertex_no_morph.instance_index instead of vertex.instance_index to work around a wgpu dx12 bug.
// See https://github.com/gfx-rs/naga/issues/2416
var model = bevy_pbr::mesh_functions::get_model_matrix(vertex_no_morph.instance_index);
var model = bevy_pbr::mesh_functions::get_model_matrix(vertex_instance);
#endif // SKINNED

out.clip_position = bevy_pbr::mesh_functions::mesh_position_local_to_clip(model, vec4(vertex.position, 1.0));
Expand All @@ -126,19 +128,15 @@ fn vertex(vertex_no_morph: Vertex) -> VertexOutput {
#else // SKINNED
out.world_normal = bevy_pbr::mesh_functions::mesh_normal_local_to_world(
vertex.normal,
// Use vertex_no_morph.instance_index instead of vertex.instance_index to work around a wgpu dx12 bug.
// See https://github.com/gfx-rs/naga/issues/2416
get_instance_index(vertex_no_morph.instance_index)
get_instance_index(vertex_instance)
);
#endif // SKINNED

#ifdef VERTEX_TANGENTS
out.world_tangent = bevy_pbr::mesh_functions::mesh_tangent_local_to_world(
model,
vertex.tangent,
// Use vertex_no_morph.instance_index instead of vertex.instance_index to work around a wgpu dx12 bug.
// See https://github.com/gfx-rs/naga/issues/2416
get_instance_index(vertex_no_morph.instance_index)
get_instance_index(vertex_instance)
);
#endif // VERTEX_TANGENTS
#endif // NORMAL_PREPASS
Expand All @@ -152,11 +150,9 @@ fn vertex(vertex_no_morph: Vertex) -> VertexOutput {
#ifdef SKINNED
var previous_model = bevy_pbr::skinning::previous_skin_model(vertex.joint_indices, vertex.joint_weights);
#else
var previous_model = bevy_pbr::mesh_functions::get_previous_model_matrix(instance_index);
var previous_model = bevy_pbr::mesh_functions::get_previous_model_matrix(vertex_instance);
#endif
out.world_position = bevy_pbr::mesh_functions::mesh_position_local_to_world(model, vec4<f32>(vertex.position, 1.0));
// Use vertex_no_morph.instance_index instead of vertex.instance_index to work around a wgpu dx12 bug.
// See https://github.com/gfx-rs/naga/issues/2416
out.previous_world_position = bevy_pbr::mesh_functions::mesh_position_local_to_world(
previous_model,
vec4<f32>(previous_position, 1.0)
Expand Down
30 changes: 15 additions & 15 deletions crates/bevy_pbr/src/render/double_buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,20 @@ use bevy_render::{
use bytemuck::Pod;

#[derive(Clone, Copy, PartialEq, Eq)]
pub enum Side {
enum Side {
A,
B,
}
impl Side {
fn toggle(&mut self) {
*self = match self {
fn flip(self) -> Self {
match self {
Side::A => Side::B,
Side::B => Side::A,
}
}
fn toggle(&mut self) {
*self = self.flip();
}
}
pub struct DoubleBufferVec<T: Pod> {
a: BufferVec<T>,
Expand All @@ -36,8 +39,8 @@ impl<T: Pod> DoubleBufferVec<T> {
current: Side::A,
}
}
pub(crate) const fn current_buffer(&self) -> &BufferVec<T> {
match self.current {
const fn buffer_side(&self, side: Side) -> &BufferVec<T> {
match side {
Side::A => &self.a,
Side::B => &self.b,
}
Expand All @@ -49,22 +52,19 @@ impl<T: Pod> DoubleBufferVec<T> {
}
}
pub fn current(&self) -> Option<&Buffer> {
self.current_buffer().buffer()
self.buffer_side(self.current).buffer()
}
pub fn previous(&self) -> Option<&Buffer> {
let old_buffer = match self.current {
Side::A => &self.b,
Side::B => &self.a,
};
old_buffer
.buffer()
.or_else(|| self.current_buffer().buffer())
let previous_buffer = self.buffer_side(self.current.flip());
// Workaround a panic in first frame of morph target init.
let current = || self.current();
previous_buffer.buffer().or_else(current)
}
pub fn is_empty(&self) -> bool {
self.current_buffer().is_empty()
self.buffer_side(self.current).is_empty()
}
pub fn len(&self) -> usize {
self.current_buffer().len()
self.buffer_side(self.current).len()
}
pub fn clear(&mut self) {
self.current.toggle();
Expand Down
76 changes: 29 additions & 47 deletions crates/bevy_pbr/src/render/mesh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,14 @@ use bevy_transform::components::GlobalTransform;
use bevy_utils::{tracing::error, EntityHashMap, Hashed};

use crate::render::{
mesh_bindings::MeshBindGroups,
morph::{
extract_morphs, no_automatic_morph_batching, prepare_morphs, MorphIndices, MorphUniform,
},
skin::{extract_skins, no_automatic_skin_batching, prepare_skins, SkinIndices, SkinUniform},
MeshLayouts,
};

use super::mesh_bindings::MeshBindGroups;

#[derive(Default)]
pub struct MeshRenderPlugin;

Expand Down Expand Up @@ -716,24 +715,19 @@ pub fn setup_morph_and_skinning_defs(
shader_defs: &mut Vec<ShaderDefVal>,
vertex_attributes: &mut Vec<VertexAttributeDescriptor>,
) -> BindGroupLayout {
let mut add_skin_data = || {
let mvectors = key.contains(MeshPipelineKey::MOTION_VECTOR_PREPASS);
let morph = key.contains(MeshPipelineKey::MORPH_TARGETS);
let skin = is_skinned(layout);

if skin {
shader_defs.push("SKINNED".into());
vertex_attributes.push(Mesh::ATTRIBUTE_JOINT_INDEX.at_shader_location(offset));
vertex_attributes.push(Mesh::ATTRIBUTE_JOINT_WEIGHT.at_shader_location(offset + 1));
};
let is_mvectors = key.contains(MeshPipelineKey::MOTION_VECTOR_PREPASS);
let is_morphed = key.contains(MeshPipelineKey::MORPH_TARGETS);
let is_skinned = is_skinned(layout);
match (is_skinned, is_morphed) {
(true, false) => add_skin_data(),
(false, true) => shader_defs.push("MORPH_TARGETS".into()),
(false, false) => {}
(true, true) => {
add_skin_data();
shader_defs.push("MORPH_TARGETS".into());
}
};
mesh_layouts.get(is_morphed, is_skinned, is_mvectors)
}
if morph {
shader_defs.push("MORPH_TARGETS".into());
}
mesh_layouts.get(morph, skin, mvectors).clone()
}

impl SpecializedMeshPipeline for MeshPipeline {
Expand Down Expand Up @@ -964,54 +958,42 @@ impl SpecializedMeshPipeline for MeshPipeline {

pub fn prepare_mesh_bind_group(
meshes: Res<RenderAssets<Mesh>>,
groups: ResMut<MeshBindGroups>,
mut groups: ResMut<MeshBindGroups>,
mesh_pipeline: Res<MeshPipeline>,
render_device: Res<RenderDevice>,
mesh_uniforms: Res<GpuArrayBuffer<MeshUniform>>,
skins_uniform: Res<SkinUniform>,
weights_uniform: Res<MorphUniform>,
has_mvectors: Query<(), With<MotionVectorPrepass>>,
) {
let has_mvectors = has_mvectors.iter().len() != 0;
let has_mvectors = |_: &_| has_mvectors;

let device = render_device.into_inner();
let groups = groups.into_inner();
let layouts = &mesh_pipeline.mesh_layouts;

let Some(model) = mesh_uniforms.binding() else {
return;
};
let mut bind_groups = layouts.updater(groups, device, model);
let layouts = &mesh_pipeline.mesh_layouts;
let mut bind_groups = layouts.bind_group_maker(&render_device, model, &mut groups);

// no morph + maybe(skin) * mvectors + no mvectors
let skin = skins_uniform.buffer.current();
let previous_skin = skins_uniform.buffer.previous().filter(has_mvectors);
let previous_skin = skins_uniform.buffer.previous();
bind_groups.add(None, None, None, None);
bind_groups.add(None, skin, None, None);
bind_groups.add(None, skin, None, previous_skin);

let skin = skins_uniform.buffer.buffer();
bind_groups.insert(skin, None, previous_skin, None);
if previous_skin.is_some() {
bind_groups.insert(skin, None, None, None);
}
if skin.is_some() {
bind_groups.insert(None, None, None, None);
}
let Some(weights) = weights_uniform.buffer.current() else {
return;
};
for (id, gpu_mesh) in meshes.iter() {
let previous_weights = weights_uniform.buffer.previous();

let skin = skin.filter(|_| is_skinned(&gpu_mesh.layout));
let previous_skin = previous_skin.filter(|_| is_skinned(&gpu_mesh.layout));

let Some(targets) = gpu_mesh.morph_targets.as_ref() else {
continue;
};
let is_skinned = |_: &_| is_skinned(&gpu_mesh.layout);
let skin = skin.filter(is_skinned);
let previous_skin = skin.filter(is_skinned);
let previous_weights = weights_uniform.buffer.previous().filter(has_mvectors);
let weights = Some((id, weights, targets));

bind_groups.insert(skin, weights, previous_skin, previous_weights);

if previous_weights.is_some() {
bind_groups.insert(skin, weights, previous_skin, None);
}
// morph + maybe(skin) * mvectors + no mvectors
let morph = Some((id, weights, targets));
bind_groups.add(morph, skin, previous_weights, previous_skin);
bind_groups.add(morph, skin, None, previous_skin);
}
}

Expand Down
Loading

0 comments on commit 56e802f

Please sign in to comment.