Skip to content

Commit 92928f1

Browse files
re0312Patrick Walton
andauthored
Cleanup extract_meshes (#13026)
# Objective - clean up extract_mesh_(gpu/cpu)_building ## Solution - gpu_building no need to hold `prev_render_mesh_instances` - using `insert_unique_unchecked` instead of simple insert as we know all entities are unique - direcly get `previous_input_index ` in par_loop ## Performance this should also bring a slight performance win. cargo run --release --example many_cubes --features bevy/trace_tracy -- --no-frustum-culling `extract_meshes_for_gpu_building` ![image](https://github.com/bevyengine/bevy/assets/45868716/a5425e8a-258b-482d-afda-170363ee6479) --------- Co-authored-by: Patrick Walton <pcwalton@mimiga.net>
1 parent 91a393a commit 92928f1

1 file changed

Lines changed: 56 additions & 102 deletions

File tree

‎crates/bevy_pbr/src/render/mesh.rs‎

Lines changed: 56 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use bevy_ecs::{
1212
query::ROQueryItem,
1313
system::{lifetimeless::*, SystemParamItem, SystemState},
1414
};
15-
use bevy_math::{Affine3, Rect, UVec2, Vec3, Vec4};
15+
use bevy_math::{vec3, Affine3, Rect, UVec2, Vec3, Vec4};
1616
use bevy_render::{
1717
batching::{
1818
gpu_preprocessing, no_gpu_preprocessing, GetBatchData, GetFullBatchData,
@@ -403,32 +403,6 @@ pub struct RenderMeshInstanceShared {
403403
pub flags: RenderMeshInstanceFlags,
404404
}
405405

406-
/// Information that is gathered during the parallel portion of mesh extraction
407-
/// when GPU mesh uniform building is enabled.
408-
///
409-
/// From this, the [`MeshInputUniform`] and [`RenderMeshInstanceGpu`] are
410-
/// prepared.
411-
pub struct RenderMeshInstanceGpuBuilder {
412-
/// Data that will be placed on the [`RenderMeshInstanceGpu`].
413-
pub shared: RenderMeshInstanceShared,
414-
/// The current transform.
415-
pub transform: Affine3,
416-
/// Four 16-bit unsigned normalized UV values packed into a [`UVec2`]:
417-
///
418-
/// ```text
419-
/// <--- MSB LSB --->
420-
/// +---- min v ----+ +---- min u ----+
421-
/// lightmap_uv_rect.x: vvvvvvvv vvvvvvvv uuuuuuuu uuuuuuuu,
422-
/// +---- max v ----+ +---- max u ----+
423-
/// lightmap_uv_rect.y: VVVVVVVV VVVVVVVV UUUUUUUU UUUUUUUU,
424-
///
425-
/// (MSB: most significant bit; LSB: least significant bit.)
426-
/// ```
427-
pub lightmap_uv_rect: UVec2,
428-
/// Various flags.
429-
pub mesh_flags: MeshFlags,
430-
}
431-
432406
impl RenderMeshInstanceShared {
433407
fn from_components(
434408
previous_transform: Option<&PreviousGlobalTransform>,
@@ -457,6 +431,7 @@ impl RenderMeshInstanceShared {
457431

458432
/// Returns true if this entity is eligible to participate in automatic
459433
/// batching.
434+
#[inline]
460435
pub fn should_batch(&self) -> bool {
461436
self.flags
462437
.contains(RenderMeshInstanceFlags::AUTOMATIC_BATCHING)
@@ -650,7 +625,9 @@ pub fn extract_meshes_for_cpu_building(
650625

651626
render_mesh_instances.clear();
652627
for queue in render_mesh_instance_queues.iter_mut() {
653-
render_mesh_instances.extend(queue.drain(..));
628+
for (k, v) in queue.drain(..) {
629+
render_mesh_instances.insert_unique_unchecked(k, v);
630+
}
654631
}
655632
}
656633

@@ -664,8 +641,9 @@ pub fn extract_meshes_for_gpu_building(
664641
mut batched_instance_buffers: ResMut<
665642
gpu_preprocessing::BatchedInstanceBuffers<MeshUniform, MeshInputUniform>,
666643
>,
667-
mut render_mesh_instance_queues: Local<Parallel<Vec<(Entity, RenderMeshInstanceGpuBuilder)>>>,
668-
mut prev_render_mesh_instances: Local<RenderMeshInstancesGpu>,
644+
mut render_mesh_instance_queues: Local<
645+
Parallel<Vec<(Entity, RenderMeshInstanceShared, MeshInputUniform)>>,
646+
>,
669647
meshes_query: Extract<
670648
Query<(
671649
Entity,
@@ -681,6 +659,24 @@ pub fn extract_meshes_for_gpu_building(
681659
)>,
682660
>,
683661
) {
662+
// Collect render mesh instances. Build up the uniform buffer.
663+
let RenderMeshInstances::GpuBuilding(ref mut render_mesh_instances) = *render_mesh_instances
664+
else {
665+
panic!(
666+
"`collect_render_mesh_instances_for_gpu_building` should only be called if we're \
667+
using GPU `MeshUniform` building"
668+
);
669+
};
670+
671+
let gpu_preprocessing::BatchedInstanceBuffers {
672+
ref mut current_input_buffer,
673+
ref mut previous_input_buffer,
674+
..
675+
} = *batched_instance_buffers;
676+
677+
// Swap buffers.
678+
mem::swap(current_input_buffer, previous_input_buffer);
679+
684680
meshes_query.par_iter().for_each_init(
685681
|| render_mesh_instance_queues.borrow_local_mut(),
686682
|queue,
@@ -710,94 +706,52 @@ pub fn extract_meshes_for_gpu_building(
710706
no_automatic_batching,
711707
);
712708

709+
let previous_input_index = shared
710+
.flags
711+
.contains(RenderMeshInstanceFlags::HAVE_PREVIOUS_TRANSFORM)
712+
.then(|| {
713+
render_mesh_instances
714+
.get(&entity)
715+
.map(|render_mesh_instance| {
716+
render_mesh_instance.current_uniform_index.into()
717+
})
718+
.unwrap_or(u32::MAX)
719+
})
720+
.unwrap_or(u32::MAX);
721+
713722
let lightmap_uv_rect =
714723
lightmap::pack_lightmap_uv_rect(lightmap.map(|lightmap| lightmap.uv_rect));
724+
let affine3: Affine3 = (&transform.affine()).into();
715725

716726
queue.push((
717727
entity,
718-
RenderMeshInstanceGpuBuilder {
719-
shared,
720-
transform: (&transform.affine()).into(),
728+
shared,
729+
MeshInputUniform {
730+
flags: mesh_flags.bits(),
721731
lightmap_uv_rect,
722-
mesh_flags,
732+
transform: affine3.to_transpose(),
733+
previous_input_index,
723734
},
724735
));
725736
},
726737
);
727738

728-
collect_meshes_for_gpu_building(
729-
&mut render_mesh_instances,
730-
&mut batched_instance_buffers,
731-
&mut render_mesh_instance_queues,
732-
&mut prev_render_mesh_instances,
733-
);
734-
}
735-
736-
/// Creates the [`RenderMeshInstanceGpu`]s and [`MeshInputUniform`]s when GPU
737-
/// mesh uniforms are built.
738-
fn collect_meshes_for_gpu_building(
739-
render_mesh_instances: &mut RenderMeshInstances,
740-
batched_instance_buffers: &mut gpu_preprocessing::BatchedInstanceBuffers<
741-
MeshUniform,
742-
MeshInputUniform,
743-
>,
744-
render_mesh_instance_queues: &mut Parallel<Vec<(Entity, RenderMeshInstanceGpuBuilder)>>,
745-
prev_render_mesh_instances: &mut RenderMeshInstancesGpu,
746-
) {
747-
// Collect render mesh instances. Build up the uniform buffer.
748-
let RenderMeshInstances::GpuBuilding(ref mut render_mesh_instances) = *render_mesh_instances
749-
else {
750-
panic!(
751-
"`collect_render_mesh_instances_for_gpu_building` should only be called if we're \
752-
using GPU `MeshUniform` building"
753-
);
754-
};
755-
756-
let gpu_preprocessing::BatchedInstanceBuffers {
757-
ref mut current_input_buffer,
758-
ref mut previous_input_buffer,
759-
..
760-
} = batched_instance_buffers;
761-
762-
// Swap buffers.
763-
mem::swap(current_input_buffer, previous_input_buffer);
764-
mem::swap(render_mesh_instances, prev_render_mesh_instances);
765-
766739
// Build the [`RenderMeshInstance`]s and [`MeshInputUniform`]s.
767740
render_mesh_instances.clear();
768741
for queue in render_mesh_instance_queues.iter_mut() {
769-
for (entity, builder) in queue.drain(..) {
770-
let previous_input_index = if builder
771-
.shared
772-
.flags
773-
.contains(RenderMeshInstanceFlags::HAVE_PREVIOUS_TRANSFORM)
774-
{
775-
prev_render_mesh_instances
776-
.get(&entity)
777-
.map(|render_mesh_instance| render_mesh_instance.current_uniform_index)
778-
} else {
779-
None
780-
};
781-
782-
// Push the mesh input uniform.
783-
let current_uniform_index = current_input_buffer.push(MeshInputUniform {
784-
transform: builder.transform.to_transpose(),
785-
lightmap_uv_rect: builder.lightmap_uv_rect,
786-
flags: builder.mesh_flags.bits(),
787-
previous_input_index: match previous_input_index {
788-
Some(previous_input_index) => previous_input_index.into(),
789-
None => u32::MAX,
790-
},
791-
}) as u32;
792-
793-
// Record the [`RenderMeshInstance`].
794-
render_mesh_instances.insert(
742+
for (entity, shared, mesh_uniform) in queue.drain(..) {
743+
let buffer_index = current_input_buffer.push(mesh_uniform);
744+
let translation = vec3(
745+
mesh_uniform.transform[0].w,
746+
mesh_uniform.transform[1].w,
747+
mesh_uniform.transform[2].w,
748+
);
749+
render_mesh_instances.insert_unique_unchecked(
795750
entity,
796751
RenderMeshInstanceGpu {
797-
translation: builder.transform.translation,
798-
shared: builder.shared,
799-
current_uniform_index: NonMaxU32::try_from(current_uniform_index)
800-
.unwrap_or_default(),
752+
shared,
753+
translation,
754+
current_uniform_index: NonMaxU32::new(buffer_index as u32).unwrap_or_default(),
801755
},
802756
);
803757
}

0 commit comments

Comments
 (0)