re_viewport/
system_execution.rs

1use std::collections::BTreeMap;
2
3use ahash::HashMap;
4use nohash_hasher::IntMap;
5use rayon::prelude::*;
6
7use re_viewer_context::{
8    PerSystemDataResults, SystemExecutionOutput, ViewContextCollection,
9    ViewContextSystemStaticExecResult, ViewId, ViewQuery, ViewState, ViewStates,
10    ViewSystemIdentifier, ViewerContext, VisualizerCollection,
11};
12
13use crate::view_highlights::highlights_for_view;
14use re_viewport_blueprint::ViewBlueprint;
15
16fn run_view_systems(
17    ctx: &ViewerContext<'_>,
18    view: &ViewBlueprint,
19    query: &ViewQuery<'_>,
20    view_state: &dyn ViewState,
21    context_system_static_exec_results: &IntMap<
22        ViewSystemIdentifier,
23        ViewContextSystemStaticExecResult,
24    >,
25    context_systems: &mut ViewContextCollection,
26    view_systems: &mut VisualizerCollection,
27) -> Vec<re_renderer::QueueableDrawData> {
28    re_tracing::profile_function!(view.class_identifier().as_str());
29
30    let view_ctx = view.bundle_context_with_state(ctx, view_state);
31
32    {
33        re_tracing::profile_wait!("ViewContextSystem::execute");
34        context_systems
35            .systems
36            .par_iter_mut()
37            .for_each(|(name, system)| {
38                re_tracing::profile_scope!("ViewContextSystem::execute", name.as_str());
39                let static_execution_result = context_system_static_exec_results
40                    .get(name)
41                    .expect("Context system execution result didn't occur");
42                system.execute(&view_ctx, query, static_execution_result);
43            });
44    };
45
46    re_tracing::profile_wait!("VisualizerSystem::execute");
47    view_systems
48        .systems
49        .par_iter_mut()
50        .map(|(name, part)| {
51            re_tracing::profile_scope!("VisualizerSystem::execute", name.as_str());
52            match part.execute(&view_ctx, query, context_systems) {
53                Ok(part_draw_data) => part_draw_data,
54                Err(err) => {
55                    re_log::error_once!("Error executing visualizer {name:?}: {err}");
56                    Vec::new()
57                }
58            }
59        })
60        .flatten()
61        .collect()
62}
63
64pub fn execute_systems_for_view<'a>(
65    ctx: &'a ViewerContext<'_>,
66    view: &'a ViewBlueprint,
67    view_state: &dyn ViewState,
68    context_system_static_exec_results: &IntMap<
69        ViewSystemIdentifier,
70        ViewContextSystemStaticExecResult,
71    >,
72) -> (ViewQuery<'a>, SystemExecutionOutput) {
73    re_tracing::profile_function!(view.class_identifier().as_str());
74
75    let highlights = highlights_for_view(ctx, view.id);
76
77    let query_result = ctx.lookup_query_result(view.id);
78
79    let mut per_visualizer_data_results = PerSystemDataResults::default();
80    {
81        re_tracing::profile_scope!("per_system_data_results");
82
83        query_result.tree.visit(&mut |node| {
84            for system in &node.data_result.visualizers {
85                per_visualizer_data_results
86                    .entry(*system)
87                    .or_default()
88                    .push(&node.data_result);
89            }
90            true
91        });
92    }
93
94    let current_query = ctx.time_ctrl.current_query();
95    let query = re_viewer_context::ViewQuery {
96        view_id: view.id,
97        space_origin: &view.space_origin,
98        per_visualizer_data_results,
99        timeline: current_query.timeline(),
100        latest_at: current_query.at(),
101        highlights,
102    };
103
104    let mut context_systems = ctx
105        .view_class_registry()
106        .new_context_collection(view.class_identifier());
107    let mut view_systems = ctx
108        .view_class_registry()
109        .new_visualizer_collection(view.class_identifier());
110
111    let draw_data = run_view_systems(
112        ctx,
113        view,
114        &query,
115        view_state,
116        context_system_static_exec_results,
117        &mut context_systems,
118        &mut view_systems,
119    );
120
121    (
122        query,
123        SystemExecutionOutput {
124            view_systems,
125            context_systems,
126            draw_data,
127        },
128    )
129}
130
131pub fn execute_systems_for_all_views<'a>(
132    ctx: &'a ViewerContext<'a>,
133    tree: &egui_tiles::Tree<ViewId>,
134    views: &'a BTreeMap<ViewId, ViewBlueprint>,
135    view_states: &mut ViewStates,
136) -> HashMap<ViewId, (ViewQuery<'a>, SystemExecutionOutput)> {
137    re_tracing::profile_wait!("execute_systems");
138
139    // During system execution we only have read access to the view states, so we need to ensure they exist ahead of time.
140    for (view_id, view) in views {
141        view_states.ensure_state_exists(*view_id, view.class(ctx.view_class_registry()));
142    }
143
144    // Static context system execution.
145    // The same context system class may be used by several view classes, so we have to do this before
146    // running anything per-view.
147    let context_system_static_exec_results = ctx
148        .view_class_registry()
149        .run_static_context_systems_for_views(
150            ctx,
151            views.values().map(|view| view.class_identifier()),
152        );
153
154    tree.active_tiles()
155        .into_par_iter()
156        .filter_map(|tile_id| {
157            let tile = tree.tiles.get(tile_id)?;
158            match tile {
159                egui_tiles::Tile::Pane(view_id) => {
160                    let view = views.get(view_id)?;
161                    let Some(view_state) = view_states.get(*view_id) else {
162                        debug_assert!(false, "View state for view {view_id:?} not found. That shouldn't be possible since we just ensured they exist above.");
163                        return None;
164                    };
165
166                    let result = execute_systems_for_view(ctx, view, view_state, &context_system_static_exec_results);
167                    Some((*view_id, result))
168                },
169                egui_tiles::Tile::Container(_) => None,
170            }
171        })
172        .collect::<HashMap<_, _>>()
173}