use std::collections::BTreeMap;
use ahash::HashMap;
use nohash_hasher::IntMap;
use rayon::prelude::*;
use re_viewer_context::{
MissingChunkReporter, PerVisualizerTypeInViewClass, SystemExecutionOutput,
ViewContextCollection, ViewContextSystemOncePerFrameResult, ViewId, ViewQuery, ViewState,
ViewStates, ViewSystemExecutionError, ViewSystemIdentifier, ViewSystemState, ViewerContext,
VisualizerCollection, VisualizerExecutionOutput, VisualizerInstructionsPerType,
};
use re_viewport_blueprint::ViewBlueprint;
use crate::view_highlights::highlights_for_view;
fn run_view_systems(
ctx: &ViewerContext<'_>,
view: &ViewBlueprint,
query: &ViewQuery<'_>,
view_state: &dyn ViewState,
context_system_once_per_frame_results: &IntMap<
ViewSystemIdentifier,
ViewContextSystemOncePerFrameResult,
>,
context_systems: &mut ViewContextCollection,
view_systems: &VisualizerCollection,
) -> PerVisualizerTypeInViewClass<Result<VisualizerExecutionOutput, ViewSystemExecutionError>> {
re_tracing::profile_function!(view.class_identifier().as_str());
let view_ctx = view.bundle_context_with_state(ctx, view_state);
{
re_tracing::profile_wait!("ViewContextSystem::execute");
context_systems
.systems
.par_iter_mut()
.for_each(|(name, (view_ctx_system, state))| {
re_tracing::profile_scope!("ViewContextSystem::execute", name.as_str());
let missing_chunk_reporter = MissingChunkReporter::default();
let once_per_frame_result = context_system_once_per_frame_results
.get(name)
.expect("Context system execution result didn't occur");
view_ctx_system.execute(
&view_ctx,
&missing_chunk_reporter,
query,
once_per_frame_result,
);
*state = ViewSystemState {
any_missing_chunks: missing_chunk_reporter.any_missing(),
};
});
};
re_tracing::profile_wait!("VisualizerSystem::execute");
let per_visualizer_type_results = view_systems
.systems
.par_iter()
.map(|(name, vis_system)| {
re_tracing::profile_scope!("VisualizerSystem::execute", name.as_str());
let affinity = vis_system.affinity();
let result = vis_system
.execute(&view_ctx, query, context_systems)
.map(|mut output| {
output.affinity = affinity;
output
});
(*name, result)
})
.collect();
PerVisualizerTypeInViewClass {
view_class_identifier: view.class_identifier(),
per_visualizer: per_visualizer_type_results,
}
}
pub fn new_view_query<'a>(ctx: &'a ViewerContext<'a>, view: &'a ViewBlueprint) -> ViewQuery<'a> {
let highlights = highlights_for_view(ctx, view.id);
let query_result = ctx.lookup_query_result(view.id);
let mut active_visualizer_instructions_per_type = VisualizerInstructionsPerType::default();
{
re_tracing::profile_scope!("active_visualizer_instructions_per_type");
for data_result in query_result.tree.iter_data_results() {
if !data_result.visible {
continue;
}
for instruction in &data_result.visualizer_instructions {
active_visualizer_instructions_per_type
.entry(instruction.visualizer_type)
.or_default()
.push((data_result, instruction));
}
}
}
let current_query = ctx.time_ctrl.current_query();
re_viewer_context::ViewQuery {
view_id: view.id,
space_origin: &view.space_origin,
active_visualizer_instructions_per_type,
timeline: current_query.timeline(),
latest_at: current_query.at(),
highlights,
}
}
pub fn execute_systems_for_view<'a>(
ctx: &'a ViewerContext<'_>,
view: &'a ViewBlueprint,
view_state: &dyn ViewState,
context_system_once_per_frame_results: &IntMap<
ViewSystemIdentifier,
ViewContextSystemOncePerFrameResult,
>,
) -> (ViewQuery<'a>, SystemExecutionOutput) {
re_tracing::profile_function!(view.class_identifier().as_str());
let query = new_view_query(ctx, view);
let mut context_systems = ctx
.view_class_registry()
.new_context_collection(view.class_identifier());
let view_systems = ctx
.view_class_registry()
.new_visualizer_collection(view.class_identifier());
let visualizer_execution_output = run_view_systems(
ctx,
view,
&query,
view_state,
context_system_once_per_frame_results,
&mut context_systems,
&view_systems,
);
(
query,
SystemExecutionOutput {
context_systems,
visualizer_execution_output,
},
)
}
pub fn execute_systems_for_all_views<'a>(
ctx: &'a ViewerContext<'a>,
tree: &egui_tiles::Tree<ViewId>,
views: &'a BTreeMap<ViewId, ViewBlueprint>,
view_states: &mut ViewStates,
) -> HashMap<ViewId, (ViewQuery<'a>, SystemExecutionOutput)> {
re_tracing::profile_wait!("execute_systems");
let store_id = ctx.store_id();
for (view_id, view) in views {
view_states.ensure_state_exists(store_id, *view_id, view.class(ctx.view_class_registry()));
}
let context_system_once_per_frame_results = ctx
.view_class_registry()
.run_once_per_frame_context_systems(
ctx,
views.values().map(|view| view.class_identifier()),
);
tree.active_tiles()
.into_par_iter()
.filter_map(|tile_id| {
let tile = tree.tiles.get(tile_id)?;
match tile {
egui_tiles::Tile::Pane(view_id) => {
let view = views.get(view_id)?;
let Some(view_state) = view_states.get(store_id, *view_id) else {
re_log::debug_panic!("View state for view {view_id:?} not found. That shouldn't be possible since we just ensured they exist above.");
return None;
};
let result = execute_systems_for_view(ctx, view, view_state, &context_system_once_per_frame_results);
Some((*view_id, result))
},
egui_tiles::Tile::Container(_) => None,
}
})
.collect::<HashMap<_, _>>()
}