Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix motion vector computation after #17688. #17717

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 2 additions & 8 deletions crates/bevy_pbr/src/meshlet/instance_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,14 +118,8 @@ impl InstanceManager {
.cloned()
.unwrap_or_default();

let mesh_uniform = MeshUniform::new(
&transforms,
0,
mesh_material_binding_id.slot,
None,
None,
None,
);
let mesh_uniform =
MeshUniform::new(&transforms, 0, mesh_material_binding_id.slot, None, None);

// Append instance data
self.instances.push((
Expand Down
23 changes: 12 additions & 11 deletions crates/bevy_pbr/src/render/gpu_preprocess.rs
Original file line number Diff line number Diff line change
Expand Up @@ -626,12 +626,10 @@ impl Node for EarlyGpuPreprocessNode {
continue;
};

// If we're drawing indirectly, make sure the mesh preprocessing
// shader has access to the view info it needs to do culling.
let mut dynamic_offsets: SmallVec<[u32; 1]> = smallvec![];
if !no_indirect_drawing {
dynamic_offsets.push(view_uniform_offset.offset);
}
// Make sure the mesh preprocessing shader has access to the
// view info it needs to do culling and motion vector
// computation.
let dynamic_offsets = [view_uniform_offset.offset];

// Are we drawing directly or indirectly?
match *phase_bind_groups {
Expand Down Expand Up @@ -1317,6 +1315,11 @@ fn preprocess_direct_bind_group_layout_entries() -> DynamicBindGroupLayoutEntrie
DynamicBindGroupLayoutEntries::new_with_indices(
ShaderStages::COMPUTE,
(
// `view`
(
0,
uniform_buffer::<ViewUniform>(/* has_dynamic_offset= */ true),
),
// `current_input`
(3, storage_buffer_read_only::<MeshInputUniform>(false)),
// `previous_input`
Expand Down Expand Up @@ -1361,11 +1364,6 @@ fn gpu_culling_bind_group_layout_entries() -> DynamicBindGroupLayoutEntries {
8,
storage_buffer_read_only::<MeshCullingData>(/* has_dynamic_offset= */ false),
),
// `view`
(
0,
uniform_buffer::<ViewUniform>(/* has_dynamic_offset= */ true),
),
))
}

Expand Down Expand Up @@ -1802,11 +1800,14 @@ impl<'a> PreprocessBindGroupBuilder<'a> {
)
.ok();

let view_uniforms_binding = self.view_uniforms.uniforms.binding()?;

Some(PhasePreprocessBindGroups::Direct(
self.render_device.create_bind_group(
"preprocess_direct_bind_group",
&self.pipelines.direct_preprocess.bind_group_layout,
&BindGroupEntries::with_indices((
(0, view_uniforms_binding),
(3, self.current_input_buffer.as_entire_binding()),
(4, self.previous_input_buffer.as_entire_binding()),
(
Expand Down
47 changes: 18 additions & 29 deletions crates/bevy_pbr/src/render/mesh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -478,13 +478,13 @@ pub struct MeshUniform {
pub first_vertex_index: u32,
/// The current skin index, or `u32::MAX` if there's no skin.
pub current_skin_index: u32,
/// The previous skin index, or `u32::MAX` if there's no previous skin.
pub previous_skin_index: u32,
/// The material and lightmap indices, packed into 32 bits.
///
/// Low 16 bits: index of the material inside the bind group data.
/// High 16 bits: index of the lightmap in the binding array.
pub material_and_lightmap_bind_group_slot: u32,
/// Padding.
pub pad: u32,
}

/// Information that has to be transferred from CPU to GPU in order to produce
Expand Down Expand Up @@ -515,6 +515,11 @@ pub struct MeshInputUniform {
///
/// This is used for TAA. If not present, this will be `u32::MAX`.
pub previous_input_index: u32,
/// The frame number of the previous frame.
///
/// The shader compared this field to the current frame number in order to
/// determine whether [`Self::previous_input_index`] is valid.
pub previous_input_frame_number: u32,
/// The index of this mesh's first vertex in the vertex buffer.
///
/// Multiple meshes can be packed into a single vertex buffer (see
Expand All @@ -534,8 +539,6 @@ pub struct MeshInputUniform {
pub index_count: u32,
/// The current skin index, or `u32::MAX` if there's no skin.
pub current_skin_index: u32,
/// The previous skin index, or `u32::MAX` if there's no previous skin.
pub previous_skin_index: u32,
/// The material and lightmap indices, packed into 32 bits.
///
/// Low 16 bits: index of the material inside the bind group data.
Expand Down Expand Up @@ -577,7 +580,6 @@ impl MeshUniform {
material_bind_group_slot: MaterialBindGroupSlot,
maybe_lightmap: Option<(LightmapSlotIndex, Rect)>,
current_skin_index: Option<u32>,
previous_skin_index: Option<u32>,
) -> Self {
let (local_from_world_transpose_a, local_from_world_transpose_b) =
mesh_transforms.world_from_local.inverse_transpose_3x3();
Expand All @@ -595,9 +597,9 @@ impl MeshUniform {
flags: mesh_transforms.flags,
first_vertex_index,
current_skin_index: current_skin_index.unwrap_or(u32::MAX),
previous_skin_index: previous_skin_index.unwrap_or(u32::MAX),
material_and_lightmap_bind_group_slot: u32::from(material_bind_group_slot)
| ((lightmap_bind_group_slot as u32) << 16),
pad: 0,
}
}
}
Expand Down Expand Up @@ -1115,11 +1117,7 @@ impl RenderMeshInstanceGpuBuilder {
None => (false, 0, 0),
};

let current_skin_index = match skin_indices.current.get(&entity) {
Some(skin_indices) => skin_indices.index(),
None => u32::MAX,
};
let previous_skin_index = match skin_indices.prev.get(&entity) {
let current_skin_index = match skin_indices.get(&entity) {
Some(skin_indices) => skin_indices.index(),
None => u32::MAX,
};
Expand Down Expand Up @@ -1148,6 +1146,7 @@ impl RenderMeshInstanceGpuBuilder {
lightmap_uv_rect: self.lightmap_uv_rect,
flags: self.mesh_flags.bits(),
previous_input_index: u32::MAX,
previous_input_frame_number: u32::MAX,
first_vertex_index,
first_index_index,
index_count: if mesh_is_indexed {
Expand All @@ -1156,7 +1155,6 @@ impl RenderMeshInstanceGpuBuilder {
vertex_count
},
current_skin_index,
previous_skin_index,
material_and_lightmap_bind_group_slot: u32::from(
self.shared.material_bindings_index.slot,
) | ((lightmap_slot as u32) << 16),
Expand Down Expand Up @@ -1557,7 +1555,7 @@ fn set_mesh_motion_vector_flags(
skin_indices: Res<SkinIndices>,
morph_indices: Res<MorphIndices>,
) {
for &entity in skin_indices.prev.keys() {
for &entity in skin_indices.keys() {
render_mesh_instances
.insert_mesh_instance_flags(entity, RenderMeshInstanceFlags::HAS_PREVIOUS_SKIN);
}
Expand Down Expand Up @@ -1827,9 +1825,7 @@ impl GetBatchData for MeshPipeline {
};
let maybe_lightmap = lightmaps.render_lightmaps.get(&main_entity);

let current_skin_index = skin_indices.current.get(&main_entity).map(SkinIndex::index);
let previous_skin_index = skin_indices.prev.get(&main_entity).map(SkinIndex::index);

let current_skin_index = skin_indices.get(&main_entity).map(SkinIndex::index);
let material_bind_group_index = mesh_instance.material_bindings_index;

Some((
Expand All @@ -1839,7 +1835,6 @@ impl GetBatchData for MeshPipeline {
material_bind_group_index.slot,
maybe_lightmap.map(|lightmap| (lightmap.slot_index, lightmap.uv_rect)),
current_skin_index,
previous_skin_index,
),
mesh_instance.should_batch().then_some((
material_bind_group_index.group,
Expand Down Expand Up @@ -1897,16 +1892,14 @@ impl GetFullBatchData for MeshPipeline {
};
let maybe_lightmap = lightmaps.render_lightmaps.get(&main_entity);

let current_skin_index = skin_indices.current.get(&main_entity).map(SkinIndex::index);
let previous_skin_index = skin_indices.prev.get(&main_entity).map(SkinIndex::index);
let current_skin_index = skin_indices.get(&main_entity).map(SkinIndex::index);

Some(MeshUniform::new(
&mesh_instance.transforms,
first_vertex_index,
mesh_instance.material_bindings_index.slot,
maybe_lightmap.map(|lightmap| (lightmap.slot_index, lightmap.uv_rect)),
current_skin_index,
previous_skin_index,
))
}

Expand Down Expand Up @@ -2793,8 +2786,7 @@ impl<P: PhaseItem, const I: usize> RenderCommand<P> for SetMeshBindGroup<I> {
return RenderCommandResult::Success;
};

let current_skin_index = skin_indices.current.get(entity);
let prev_skin_index = skin_indices.prev.get(entity);
let current_skin_index = skin_indices.get(entity);
let current_morph_index = morph_indices.current.get(entity);
let prev_morph_index = morph_indices.prev.get(entity);

Expand Down Expand Up @@ -2841,14 +2833,11 @@ impl<P: PhaseItem, const I: usize> RenderCommand<P> for SetMeshBindGroup<I> {
if has_motion_vector_prepass {
// Attach the previous skin index for motion vector computation. If
// there isn't one, just use zero as the shader will ignore it.
if current_skin_index.is_some() && skin::skins_use_uniform_buffers(&render_device) {
match prev_skin_index {
Some(prev_skin_index) => {
dynamic_offsets[offset_count] = prev_skin_index.byte_offset;
}
None => dynamic_offsets[offset_count] = 0,
if skin::skins_use_uniform_buffers(&render_device) {
if let Some(current_skin_index) = current_skin_index {
dynamic_offsets[offset_count] = current_skin_index.byte_offset;
offset_count += 1;
}
offset_count += 1;
}

// Attach the previous morph index for motion vector computation. If
Expand Down
9 changes: 5 additions & 4 deletions crates/bevy_pbr/src/render/mesh_preprocess.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -193,13 +193,15 @@ fn main(@builtin(global_invocation_id) global_invocation_id: vec3<u32>) {
#endif

// Look up the previous model matrix.
let previous_input_frame_number = current_input[input_index].previous_input_frame_number;
let previous_input_index = current_input[input_index].previous_input_index;
let previous_input_is_valid = previous_input_frame_number + 1 == view.frame_number;
var previous_world_from_local_affine_transpose: mat3x4<f32>;
if (previous_input_index == 0xffffffff) {
previous_world_from_local_affine_transpose = world_from_local_affine_transpose;
} else {
if (previous_input_is_valid && previous_input_index != 0xffffffffu) {
previous_world_from_local_affine_transpose =
previous_input[previous_input_index].world_from_local;
} else {
previous_world_from_local_affine_transpose = world_from_local_affine_transpose;
}
let previous_world_from_local =
maths::affine3_to_square(previous_world_from_local_affine_transpose);
Expand Down Expand Up @@ -342,7 +344,6 @@ fn main(@builtin(global_invocation_id) global_invocation_id: vec3<u32>) {
output[mesh_output_index].lightmap_uv_rect = current_input[input_index].lightmap_uv_rect;
output[mesh_output_index].first_vertex_index = current_input[input_index].first_vertex_index;
output[mesh_output_index].current_skin_index = current_input[input_index].current_skin_index;
output[mesh_output_index].previous_skin_index = current_input[input_index].previous_skin_index;
output[mesh_output_index].material_and_lightmap_bind_group_slot =
current_input[input_index].material_and_lightmap_bind_group_slot;
}
2 changes: 1 addition & 1 deletion crates/bevy_pbr/src/render/mesh_types.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ struct Mesh {
// The index of the mesh's first vertex in the vertex buffer.
first_vertex_index: u32,
current_skin_index: u32,
previous_skin_index: u32,
// Low 16 bits: index of the material inside the bind group data.
// High 16 bits: index of the lightmap in the binding array.
material_and_lightmap_bind_group_slot: u32,
pad: u32,
};

#ifdef SKINNED
Expand Down
Loading