@@ -4,7 +4,6 @@ use core::any::TypeId;
4
4
5
5
use bevy_app:: { App , Plugin } ;
6
6
use bevy_ecs:: {
7
- entity:: { hash_map:: EntityHashMap , Entity } ,
8
7
query:: { Has , With } ,
9
8
resource:: Resource ,
10
9
schedule:: IntoSystemConfigs as _,
@@ -13,7 +12,7 @@ use bevy_ecs::{
13
12
} ;
14
13
use bevy_encase_derive:: ShaderType ;
15
14
use bevy_math:: UVec4 ;
16
- use bevy_platform_support:: collections:: hash_map:: Entry ;
15
+ use bevy_platform_support:: collections:: { hash_map:: Entry , HashMap , HashSet } ;
17
16
use bevy_utils:: { default, TypeIdMap } ;
18
17
use bytemuck:: { Pod , Zeroable } ;
19
18
use nonmax:: NonMaxU32 ;
@@ -30,7 +29,7 @@ use crate::{
30
29
} ,
31
30
render_resource:: { Buffer , BufferVec , GpuArrayBufferable , RawBufferVec , UninitBufferVec } ,
32
31
renderer:: { RenderAdapter , RenderDevice , RenderQueue } ,
33
- view:: { ExtractedView , NoIndirectDrawing } ,
32
+ view:: { ExtractedView , NoIndirectDrawing , RetainedViewEntity } ,
34
33
Render , RenderApp , RenderSet ,
35
34
} ;
36
35
@@ -157,7 +156,7 @@ where
157
156
/// corresponds to each instance.
158
157
///
159
158
/// This is keyed off each view. Each view has a separate buffer.
160
- pub work_item_buffers : EntityHashMap < TypeIdMap < PreprocessWorkItemBuffers > > ,
159
+ pub work_item_buffers : HashMap < RetainedViewEntity , TypeIdMap < PreprocessWorkItemBuffers > > ,
161
160
162
161
/// The uniform data inputs for the current frame.
163
162
///
@@ -409,8 +408,8 @@ impl Default for LatePreprocessWorkItemIndirectParameters {
409
408
/// You may need to call this function if you're implementing your own custom
410
409
/// render phases. See the `specialized_mesh_pipeline` example.
411
410
pub fn get_or_create_work_item_buffer < ' a , I > (
412
- work_item_buffers : & ' a mut EntityHashMap < TypeIdMap < PreprocessWorkItemBuffers > > ,
413
- view : Entity ,
411
+ work_item_buffers : & ' a mut HashMap < RetainedViewEntity , TypeIdMap < PreprocessWorkItemBuffers > > ,
412
+ view : RetainedViewEntity ,
414
413
no_indirect_drawing : bool ,
415
414
gpu_occlusion_culling : bool ,
416
415
late_indexed_indirect_parameters_buffer : & ' _ mut RawBufferVec <
@@ -493,6 +492,28 @@ impl PreprocessWorkItemBuffers {
493
492
}
494
493
}
495
494
}
495
+
496
+ /// Clears out the GPU work item buffers in preparation for a new frame.
497
+ pub fn clear ( & mut self ) {
498
+ match * self {
499
+ PreprocessWorkItemBuffers :: Direct ( ref mut buffer) => {
500
+ buffer. clear ( ) ;
501
+ }
502
+ PreprocessWorkItemBuffers :: Indirect {
503
+ indexed : ref mut indexed_buffer,
504
+ non_indexed : ref mut non_indexed_buffer,
505
+ ref mut gpu_occlusion_culling,
506
+ } => {
507
+ indexed_buffer. clear ( ) ;
508
+ non_indexed_buffer. clear ( ) ;
509
+
510
+ if let Some ( ref mut gpu_occlusion_culling) = * gpu_occlusion_culling {
511
+ gpu_occlusion_culling. late_indexed . clear ( ) ;
512
+ gpu_occlusion_culling. late_non_indexed . clear ( ) ;
513
+ }
514
+ }
515
+ }
516
+ }
496
517
}
497
518
498
519
/// One invocation of the preprocessing shader: i.e. one mesh instance in a
@@ -942,7 +963,7 @@ where
942
963
pub fn new ( ) -> Self {
943
964
BatchedInstanceBuffers {
944
965
data_buffer : UninitBufferVec :: new ( BufferUsages :: STORAGE ) ,
945
- work_item_buffers : EntityHashMap :: default ( ) ,
966
+ work_item_buffers : HashMap :: default ( ) ,
946
967
current_input_buffer : InstanceInputUniformBuffer :: new ( ) ,
947
968
previous_input_buffer : InstanceInputUniformBuffer :: new ( ) ,
948
969
late_indexed_indirect_parameters_buffer : RawBufferVec :: new (
@@ -968,7 +989,14 @@ where
968
989
self . data_buffer . clear ( ) ;
969
990
self . late_indexed_indirect_parameters_buffer . clear ( ) ;
970
991
self . late_non_indexed_indirect_parameters_buffer . clear ( ) ;
971
- self . work_item_buffers . clear ( ) ;
992
+
993
+ // Clear each individual set of buffers, but don't depopulate the hash
994
+ // table. We want to avoid reallocating these vectors every frame.
995
+ for view_work_item_buffers in self . work_item_buffers . values_mut ( ) {
996
+ for phase_work_item_buffers in view_work_item_buffers. values_mut ( ) {
997
+ phase_work_item_buffers. clear ( ) ;
998
+ }
999
+ }
972
1000
}
973
1001
}
974
1002
@@ -1074,13 +1102,17 @@ pub fn delete_old_work_item_buffers<GFBD>(
1074
1102
mut gpu_batched_instance_buffers : ResMut <
1075
1103
BatchedInstanceBuffers < GFBD :: BufferData , GFBD :: BufferInputData > ,
1076
1104
> ,
1077
- extracted_views : Query < Entity , With < ExtractedView > > ,
1105
+ extracted_views : Query < & ExtractedView > ,
1078
1106
) where
1079
1107
GFBD : GetFullBatchData ,
1080
1108
{
1109
+ let retained_view_entities: HashSet < _ > = extracted_views
1110
+ . iter ( )
1111
+ . map ( |extracted_view| extracted_view. retained_view_entity )
1112
+ . collect ( ) ;
1081
1113
gpu_batched_instance_buffers
1082
1114
. work_item_buffers
1083
- . retain ( |entity , _| extracted_views . contains ( * entity ) ) ;
1115
+ . retain ( |retained_view_entity , _| retained_view_entities . contains ( retained_view_entity ) ) ;
1084
1116
}
1085
1117
1086
1118
/// Batch the items in a sorted render phase, when GPU instance buffer building
@@ -1091,7 +1123,6 @@ pub fn batch_and_prepare_sorted_render_phase<I, GFBD>(
1091
1123
mut indirect_parameters_buffers : ResMut < IndirectParametersBuffers > ,
1092
1124
mut sorted_render_phases : ResMut < ViewSortedRenderPhases < I > > ,
1093
1125
mut views : Query < (
1094
- Entity ,
1095
1126
& ExtractedView ,
1096
1127
Has < NoIndirectDrawing > ,
1097
1128
Has < OcclusionCulling > ,
@@ -1110,15 +1141,15 @@ pub fn batch_and_prepare_sorted_render_phase<I, GFBD>(
1110
1141
..
1111
1142
} = gpu_array_buffer. into_inner ( ) ;
1112
1143
1113
- for ( view , extracted_view, no_indirect_drawing, gpu_occlusion_culling) in & mut views {
1144
+ for ( extracted_view, no_indirect_drawing, gpu_occlusion_culling) in & mut views {
1114
1145
let Some ( phase) = sorted_render_phases. get_mut ( & extracted_view. retained_view_entity ) else {
1115
1146
continue ;
1116
1147
} ;
1117
1148
1118
1149
// Create the work item buffer if necessary.
1119
1150
let work_item_buffer = get_or_create_work_item_buffer :: < I > (
1120
1151
work_item_buffers,
1121
- view ,
1152
+ extracted_view . retained_view_entity ,
1122
1153
no_indirect_drawing,
1123
1154
gpu_occlusion_culling,
1124
1155
late_indexed_indirect_parameters_buffer,
@@ -1248,7 +1279,6 @@ pub fn batch_and_prepare_binned_render_phase<BPI, GFBD>(
1248
1279
mut binned_render_phases : ResMut < ViewBinnedRenderPhases < BPI > > ,
1249
1280
mut views : Query <
1250
1281
(
1251
- Entity ,
1252
1282
& ExtractedView ,
1253
1283
Has < NoIndirectDrawing > ,
1254
1284
Has < OcclusionCulling > ,
@@ -1270,7 +1300,7 @@ pub fn batch_and_prepare_binned_render_phase<BPI, GFBD>(
1270
1300
..
1271
1301
} = gpu_array_buffer. into_inner ( ) ;
1272
1302
1273
- for ( view , extracted_view, no_indirect_drawing, gpu_occlusion_culling) in & mut views {
1303
+ for ( extracted_view, no_indirect_drawing, gpu_occlusion_culling) in & mut views {
1274
1304
let Some ( phase) = binned_render_phases. get_mut ( & extracted_view. retained_view_entity ) else {
1275
1305
continue ;
1276
1306
} ;
@@ -1279,7 +1309,7 @@ pub fn batch_and_prepare_binned_render_phase<BPI, GFBD>(
1279
1309
// used this frame.
1280
1310
let work_item_buffer = get_or_create_work_item_buffer :: < BPI > (
1281
1311
work_item_buffers,
1282
- view ,
1312
+ extracted_view . retained_view_entity ,
1283
1313
no_indirect_drawing,
1284
1314
gpu_occlusion_culling,
1285
1315
late_indexed_indirect_parameters_buffer,
0 commit comments