Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5085,7 +5085,7 @@ dependencies = [
"re_format",
"re_log",
"re_log_types",
"re_query",
"re_query2",
"re_renderer",
"re_space_view",
"re_tracing",
Expand Down
14 changes: 14 additions & 0 deletions crates/store/re_chunk_store/src/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,20 @@ impl ChunkStoreConfig {
..Self::DEFAULT
};

/// [`Self::DEFAULT`], but with changelog disabled.
pub const CHANGELOG_DISABLED: Self = Self {
enable_changelog: false,
..Self::DEFAULT
};

/// All features disabled.
pub const ALL_DISABLED: Self = Self {
enable_changelog: false,
chunk_max_bytes: 0,
chunk_max_rows: 0,
chunk_max_rows_if_unsorted: 0,
};

/// Environment variable to configure [`Self::enable_changelog`].
pub const ENV_STORE_ENABLE_CHANGELOG: &'static str = "RERUN_STORE_ENABLE_CHANGELOG";

Expand Down
30 changes: 23 additions & 7 deletions crates/top/rerun/src/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use itertools::{izip, Itertools};

use re_data_source::DataSource;
use re_log_types::{LogMsg, SetStoreInfo};
use re_sdk::log::Chunk;
use re_sdk::{log::Chunk, StoreKind};
use re_smart_channel::{ReceiveSet, Receiver, SmartMessagePayload};

#[cfg(feature = "web_viewer")]
Expand Down Expand Up @@ -661,16 +661,32 @@ fn run_compact(path_to_input_rrd: &Path, path_to_output_rrd: &Path) -> anyhow::R
let mut rrd_out = std::fs::File::create(path_to_output_rrd)
.with_context(|| format!("{path_to_output_rrd:?}"))?;

let messages: Result<Vec<Vec<LogMsg>>, _> = entity_dbs
.into_values()
let messages_rbl: Result<Vec<Vec<LogMsg>>, _> = entity_dbs
.values()
.filter(|entity_db| entity_db.store_kind() == StoreKind::Blueprint)
.map(|entity_db| entity_db.to_messages(None /* time selection */))
.collect();
let messages = messages?;
let messages = messages.iter().flatten();
let messages_rbl = messages_rbl?;
let messages_rbl = messages_rbl.iter().flatten();

let messages_rrd: Result<Vec<Vec<LogMsg>>, _> = entity_dbs
.values()
.filter(|entity_db| entity_db.store_kind() == StoreKind::Recording)
.map(|entity_db| entity_db.to_messages(None /* time selection */))
.collect();
let messages_rrd = messages_rrd?;
let messages_rrd = messages_rrd.iter().flatten();

let encoding_options = re_log_encoding::EncodingOptions::COMPRESSED;
re_log_encoding::encoder::encode(version, encoding_options, messages, &mut rrd_out)
.context("Message encode")?;
re_log_encoding::encoder::encode(
version,
encoding_options,
// NOTE: We want to make sure all blueprints come first, so that the viewer can immediately
// set up the viewport correctly.
messages_rbl.chain(messages_rrd),
&mut rrd_out,
)
.context("Message encode")?;

let rrd_out_size = rrd_out.metadata().ok().map(|md| md.len());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,19 @@ fn transform_at(
}
}

let transform3d = get_parent_from_child_transform(entity_path, entity_db, query);
// If this entity does not contain any `Transform3D`-related data at all, there's no
// point in running actual queries.
let is_potentially_transformed =
crate::transform_component_tracker::TransformComponentTracker::access(
entity_db.store_id(),
|transform_component_tracker| {
transform_component_tracker.is_potentially_transformed(entity_path)
},
)
.unwrap_or(false);
let transform3d = is_potentially_transformed
.then(|| get_parent_from_child_transform(entity_path, entity_db, query))
.flatten();

let pinhole = pinhole.map(|(image_from_camera, camera_xyz)| {
// Everything under a pinhole camera is a 2D projection, thus doesn't actually have a proper 3D representation.
Expand Down
1 change: 1 addition & 0 deletions crates/viewer/re_space_view_spatial/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ mod proc_mesh;
mod scene_bounding_boxes;
mod space_camera_3d;
mod spatial_topology;
mod transform_component_tracker;
mod ui;
mod ui_2d;
mod ui_3d;
Expand Down
117 changes: 117 additions & 0 deletions crates/viewer/re_space_view_spatial/src/transform_component_tracker.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
use ahash::HashMap;
use once_cell::sync::OnceCell;

use nohash_hasher::IntSet;
use re_chunk_store::{
ChunkStore, ChunkStoreDiffKind, ChunkStoreEvent, ChunkStoreSubscriber,
ChunkStoreSubscriberHandle,
};
use re_log_types::{EntityPath, StoreId};
use re_types::ComponentName;

// ---

/// Keeps track of which entities have had any `Transform3D`-related data on any timeline at any
/// point in time.
///
/// This is used to optimize queries in the `TransformContext`, so that we don't unnecessarily pay
/// for the fixed overhead of all the query layers when we know for a fact that there won't be any
/// data there.
/// This is a huge performance improvement in practice, especially in recordings with many entities.
#[derive(Default)]
pub struct TransformComponentTracker {
/// Which entities have had any of these components at any point in time.
entities: IntSet<EntityPath>,
}

impl TransformComponentTracker {
/// Accesses the spatial topology for a given store.
#[inline]
pub fn access<T>(store_id: &StoreId, f: impl FnOnce(&Self) -> T) -> Option<T> {
ChunkStore::with_subscriber_once(
TransformComponentTrackerStoreSubscriber::subscription_handle(),
move |susbcriber: &TransformComponentTrackerStoreSubscriber| {
susbcriber.per_store.get(store_id).map(f)
},
)
.flatten()
}

#[inline]
pub fn is_potentially_transformed(&self, entity_path: &EntityPath) -> bool {
self.entities.contains(entity_path)
}
}

// ---

pub struct TransformComponentTrackerStoreSubscriber {
/// The components of interest.
components: IntSet<ComponentName>,

per_store: HashMap<StoreId, TransformComponentTracker>,
}

impl Default for TransformComponentTrackerStoreSubscriber {
#[inline]
fn default() -> Self {
use re_types::Archetype as _;
let components = re_types::archetypes::Transform3D::all_components()
.iter()
.copied()
.collect();

Self {
components,
per_store: Default::default(),
}
}
}

impl TransformComponentTrackerStoreSubscriber {
/// Accesses the global store subscriber.
///
/// Lazily registers the subscriber if it hasn't been registered yet.
pub fn subscription_handle() -> ChunkStoreSubscriberHandle {
static SUBSCRIPTION: OnceCell<ChunkStoreSubscriberHandle> = OnceCell::new();
*SUBSCRIPTION.get_or_init(|| ChunkStore::register_subscriber(Box::<Self>::default()))
}
}

impl ChunkStoreSubscriber for TransformComponentTrackerStoreSubscriber {
#[inline]
fn name(&self) -> String {
"rerun.store_subscriber.TransformComponentTracker".into()
}

#[inline]
fn as_any(&self) -> &dyn std::any::Any {
self
}

#[inline]
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
self
}

fn on_events(&mut self, events: &[ChunkStoreEvent]) {
re_tracing::profile_function!();

for event in events
.iter()
// This is only additive, don't care about removals.
.filter(|e| e.kind == ChunkStoreDiffKind::Addition)
{
let transform_component_tracker =
self.per_store.entry(event.store_id.clone()).or_default();

for component_name in event.chunk.component_names() {
if self.components.contains(&component_name) {
transform_component_tracker
.entities
.insert(event.chunk.entity_path().clone());
}
}
}
}
}
1 change: 1 addition & 0 deletions crates/viewer/re_space_view_spatial/src/view_2d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ impl SpaceViewClass for SpatialSpaceView2D {
) -> Result<(), SpaceViewClassRegistryError> {
// Ensure spatial topology & max image dimension is registered.
crate::spatial_topology::SpatialTopologyStoreSubscriber::subscription_handle();
crate::transform_component_tracker::TransformComponentTrackerStoreSubscriber::subscription_handle();
crate::max_image_dimension_subscriber::MaxImageDimensionSubscriber::subscription_handle();

register_spatial_contexts(system_registry)?;
Expand Down
1 change: 1 addition & 0 deletions crates/viewer/re_space_view_spatial/src/view_3d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ impl SpaceViewClass for SpatialSpaceView3D {
) -> Result<(), SpaceViewClassRegistryError> {
// Ensure spatial topology is registered.
crate::spatial_topology::SpatialTopologyStoreSubscriber::subscription_handle();
crate::transform_component_tracker::TransformComponentTrackerStoreSubscriber::subscription_handle();

register_spatial_contexts(system_registry)?;
register_3d_spatial_visualizers(system_registry)?;
Expand Down
2 changes: 1 addition & 1 deletion crates/viewer/re_space_view_time_series/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ re_chunk_store.workspace = true
re_format.workspace = true
re_log.workspace = true
re_log_types.workspace = true
re_query.workspace = true
re_query2.workspace = true
re_renderer.workspace = true
re_space_view.workspace = true
re_tracing.workspace = true
Expand Down
Loading