@@ -71,6 +71,10 @@ pub struct ScheduleData {
7171 pub conflicts : Vec < SystemConflict > ,
7272}
7373
74+ /// A newtype for the index of a component.
75+ #[ derive( Serialize , Deserialize , PartialEq , Eq , Debug , Clone , Copy , PartialOrd , Ord , Hash ) ]
76+ pub struct ComponentIndex ( pub u32 ) ;
77+
7478/// Data about a component type.
7579#[ derive( Serialize , Deserialize , PartialEq , Eq , Debug , Clone ) ]
7680pub struct ComponentData {
@@ -89,7 +93,65 @@ pub struct SystemData {
8993 pub exclusive : bool ,
9094 /// Whether this system has deferred buffers to apply.
9195 pub deferred : bool ,
92- // TODO: Store the conditions specific to this system.
96+
97+ /// Combined access for the system
98+ pub combined_access : AccessData ,
99+ /// Filtered accesses for the system
100+ pub filtered_accesses : Vec < FilteredAccessData > ,
101+ }
102+
103+ /// Access wrapper
104+ #[ derive( Serialize , Deserialize , PartialEq , Eq , Debug , Clone , Default ) ]
105+ pub struct AccessData {
106+ read_and_writes : Vec < u32 > ,
107+ writes : Vec < u32 > ,
108+ read_and_writes_inverted : bool ,
109+ writes_inverted : bool ,
110+ archetypal : Vec < u32 > ,
111+ }
112+
113+ impl AccessData {
114+ fn new ( value : & bevy_ecs:: query:: Access , trace : & mut ComponentTrace ) -> Self {
115+ Self {
116+ read_and_writes : trace. get_indexes ( value. read_and_writes ( ) . iter ( ) ) ,
117+ writes : trace. get_indexes ( value. writes ( ) . iter ( ) ) ,
118+ read_and_writes_inverted : value. read_and_writes_inverted ( ) ,
119+ writes_inverted : value. writes_inverted ( ) ,
120+ archetypal : trace. get_indexes ( value. archetypal ( ) . iter ( ) ) ,
121+ }
122+ }
123+ }
124+
125+ /// `AccessFilters` wrapper
126+ #[ derive( Serialize , Deserialize , PartialEq , Eq , Debug , Clone , Default ) ]
127+ pub struct AccessFiltersData {
128+ with : Vec < u32 > ,
129+ without : Vec < u32 > ,
130+ }
131+
132+ /// `FilteredAccess` wrapper
133+ #[ derive( Serialize , Deserialize , PartialEq , Eq , Debug , Clone , Default ) ]
134+ pub struct FilteredAccessData {
135+ access : AccessData ,
136+ required : Vec < u32 > ,
137+ filter_sets : Vec < AccessFiltersData > ,
138+ }
139+
140+ impl FilteredAccessData {
141+ fn new ( value : & bevy_ecs:: query:: FilteredAccess , trace : & mut ComponentTrace ) -> Self {
142+ Self {
143+ access : AccessData :: new ( value. access ( ) , trace) ,
144+ required : trace. get_indexes ( value. required ( ) . iter ( ) ) ,
145+ filter_sets : value
146+ . filter_sets ( )
147+ . iter ( )
148+ . map ( |f| AccessFiltersData {
149+ with : trace. get_indexes ( f. with ( ) . iter ( ) ) ,
150+ without : trace. get_indexes ( f. without ( ) . iter ( ) ) ,
151+ } )
152+ . collect ( ) ,
153+ }
154+ }
93155}
94156
95157/// Data about a particular system set.
@@ -145,6 +207,49 @@ pub enum AccessConflict {
145207#[ derive( Serialize , Deserialize , PartialEq , Eq , Debug , Clone , Copy , PartialOrd , Ord ) ]
146208pub struct SystemSetIndex ( pub u32 ) ;
147209
210+ // Helper to build the components used by systems in this schedule
211+ struct ComponentTrace < ' a > {
212+ world_components : & ' a Components ,
213+ component_id_to_index : HashMap < ComponentId , usize > ,
214+ components : Vec < ComponentData > ,
215+ }
216+
217+ impl < ' a > ComponentTrace < ' a > {
218+ fn with_world_components ( world_components : & ' a Components ) -> Self {
219+ Self {
220+ world_components,
221+ component_id_to_index : HashMap :: new ( ) ,
222+ components : vec ! [ ] ,
223+ }
224+ }
225+
226+ fn get_index ( & mut self , id : ComponentId ) -> u32 {
227+ match self . component_id_to_index . entry ( id) {
228+ Entry :: Occupied ( entry) => * entry. get ( ) as _ ,
229+ Entry :: Vacant ( entry) => {
230+ let component = self
231+ . world_components
232+ . get_info ( id)
233+ . expect ( "the component has already been registered by the system" ) ;
234+
235+ self . components . push ( ComponentData {
236+ name : format ! ( "{}" , component. name( ) ) ,
237+ } ) ;
238+
239+ * entry. insert ( self . components . len ( ) - 1 ) as _
240+ }
241+ }
242+ }
243+
244+ fn get_indexes ( & mut self , ids : impl Iterator < Item = ComponentId > ) -> Vec < u32 > {
245+ ids. map ( |id| self . get_index ( id) ) . collect ( )
246+ }
247+
248+ fn get_indexes3 < ' b > ( & mut self , ids : impl Iterator < Item = & ' b ComponentId > ) -> Vec < u32 > {
249+ ids. map ( |id| self . get_index ( * id) ) . collect ( )
250+ }
251+ }
252+
148253impl ScheduleData {
149254 /// Creates the data from the underlying [`Schedule`].
150255 ///
@@ -154,6 +259,8 @@ impl ScheduleData {
154259 world_components : & Components ,
155260 build_metadata : Option < & ScheduleBuildMetadata > ,
156261 ) -> Result < Self , ExtractAppDataError > {
262+ let mut component_trace = ComponentTrace :: with_world_components ( world_components) ;
263+
157264 let graph = schedule. graph ( ) ;
158265
159266 let mut system_key_to_index = HashMap :: new ( ) ;
@@ -169,14 +276,20 @@ impl ScheduleData {
169276 }
170277
171278 let systems = schedule
172- . systems ( )
279+ . systems_with_access ( )
173280 . map_err ( |_| {
174281 ExtractAppDataError :: ScheduleNotInitialized ( format ! ( "{:?}" , schedule. label( ) ) )
175282 } ) ?
176283 . enumerate ( )
177- . map ( |( index, ( key, system ) ) | {
284+ . map ( |( index, ( key, system_with_access ) ) | {
178285 system_key_to_index. insert ( key, index) ;
179286
287+ let system = system_with_access. system ( ) ;
288+ let access = system_with_access. access ( ) ;
289+
290+ let combined_access = access. combined_access ( ) ;
291+ let filtered_accesses = access. filtered_accesses ( ) ;
292+
180293 let flags = system. flags ( ) ;
181294
182295 SystemData {
@@ -185,6 +298,11 @@ impl ScheduleData {
185298 == core:: any:: TypeId :: of :: < ApplyDeferred > ( ) ,
186299 exclusive : flags. contains ( SystemStateFlags :: EXCLUSIVE ) ,
187300 deferred : flags. contains ( SystemStateFlags :: DEFERRED ) ,
301+ combined_access : AccessData :: new ( combined_access, & mut component_trace) ,
302+ filtered_accesses : filtered_accesses
303+ . iter ( )
304+ . map ( |fa| FilteredAccessData :: new ( fa, & mut component_trace) )
305+ . collect ( ) ,
188306 }
189307 } )
190308 . collect ( ) ;
@@ -258,9 +376,6 @@ impl ScheduleData {
258376 ) ;
259377 }
260378
261- let mut component_id_to_index = HashMap :: < ComponentId , usize > :: new ( ) ;
262- let mut components = vec ! [ ] ;
263-
264379 let conflicts = graph
265380 . conflicting_systems ( )
266381 . iter ( )
@@ -279,29 +394,14 @@ impl ScheduleData {
279394 // The systems conflict on the world if there's no particular component IDs.
280395 AccessConflict :: World
281396 } else {
282- AccessConflict :: Components (
283- conflicts
284- . iter ( )
285- . map ( |id| match component_id_to_index. entry ( * id) {
286- Entry :: Occupied ( entry) => * entry. get ( ) as _ ,
287- Entry :: Vacant ( entry) => {
288- let component = world_components. get_info ( * id) . expect (
289- "the component has already been registered by the system" ,
290- ) ;
291-
292- components. push ( ComponentData {
293- name : format ! ( "{}" , component. name( ) ) ,
294- } ) ;
295- * entry. insert ( components. len ( ) - 1 ) as _
296- }
297- } )
298- . collect ( ) ,
299- )
397+ AccessConflict :: Components ( component_trace. get_indexes3 ( conflicts. iter ( ) ) )
300398 } ,
301399 }
302400 } )
303401 . collect ( ) ;
304402
403+ let components = component_trace. components ;
404+
305405 Ok ( Self {
306406 name : format ! ( "{:?}" , schedule. label( ) ) ,
307407 components,
@@ -337,8 +437,9 @@ pub mod tests {
337437 use bevy_platform:: collections:: HashMap ;
338438
339439 use crate :: schedule_data:: serde:: {
340- AccessConflict , AppData , ComponentData , ExtractAppDataError , ScheduleData , ScheduleIndex ,
341- SystemConflict , SystemData , SystemSetData , SystemSetIndex ,
440+ AccessConflict , AccessData , AppData , ComponentData , ExtractAppDataError ,
441+ FilteredAccessData , ScheduleData , ScheduleIndex , SystemConflict , SystemData , SystemSetData ,
442+ SystemSetIndex ,
342443 } ;
343444
344445 fn app_data_from_app ( app : & mut App ) -> Result < AppData , ExtractAppDataError > {
@@ -517,6 +618,8 @@ pub mod tests {
517618 apply_deferred : false ,
518619 exclusive : false ,
519620 deferred : false ,
621+ combined_access : AccessData :: default ( ) ,
622+ filtered_accesses : vec ! [ ] ,
520623 }
521624 }
522625
@@ -704,18 +807,24 @@ pub mod tests {
704807 apply_deferred: false ,
705808 exclusive: false ,
706809 deferred: true ,
810+ combined_access: AccessData :: default ( ) ,
811+ filtered_accesses: vec![ ] ,
707812 } ,
708813 SystemData {
709814 name: "a1" . into( ) ,
710815 apply_deferred: false ,
711816 exclusive: false ,
712817 deferred: true ,
818+ combined_access: AccessData :: default ( ) ,
819+ filtered_accesses: vec![ ] ,
713820 } ,
714821 SystemData {
715822 name: "apply_deferred" . into( ) ,
716823 apply_deferred: true ,
717824 exclusive: true ,
718825 deferred: false ,
826+ combined_access: AccessData :: default ( ) ,
827+ filtered_accesses: vec![ ] ,
719828 } ,
720829 simple_system( "b0" ) ,
721830 simple_system( "b1" ) ,
0 commit comments