@@ -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 } ;
1616use 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-
432406impl 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