Skip to content

Commit

Permalink
refactor: optimize, rename structs
Browse files Browse the repository at this point in the history
  • Loading branch information
simbleau committed Feb 19, 2025
1 parent 4eec5e3 commit 236a7c1
Show file tree
Hide file tree
Showing 10 changed files with 208 additions and 148 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ This release supports Bevy version 0.14 and has an [MSRV][] of 1.80.
### Added

- Added `VelloView` marker component used for identifying cameras rendering vello content.
- Added `VelloDiagnosticsPlugin` which can be used to introspect rendering data at runtime. See the `diagnostics` example.
- Added `VelloEntityCountDiagnosticsPlugin` which can be used to provide vello entity type data at runtime. See the `diagnostics` example.
- Added `VelloFrameProfileDiagnosticsPlugin` which can be used to provide vello frame profile data at runtime. See the `diagnostics` example.

### Changed

Expand Down
35 changes: 25 additions & 10 deletions examples/diagnostics/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
use bevy::{diagnostic::DiagnosticsStore, prelude::*};
use bevy_vello::{prelude::*, VelloDiagnosticsPlugin, VelloPlugin};
use bevy_vello::{
diagnostics::VelloEntityCountDiagnosticsPlugin,
diagnostics::VelloFrameProfileDiagnosticsPlugin, prelude::*, VelloPlugin,
};

const SCENE_COUNT: usize = 5;

fn main() {
let mut app = App::new();
app.add_plugins(DefaultPlugins)
.add_plugins(VelloPlugin::default())
.add_plugins(VelloDiagnosticsPlugin)
.add_plugins(VelloEntityCountDiagnosticsPlugin)
.add_plugins(VelloFrameProfileDiagnosticsPlugin)
.add_systems(Startup, setup)
.add_systems(Update, simple_animation)
.add_systems(Update, update_scene_count_ui);
Expand Down Expand Up @@ -72,13 +76,24 @@ fn simple_animation(mut query: Query<(&mut Transform, &mut VelloScene)>, time: R

fn update_scene_count_ui(
diagnostics: Res<DiagnosticsStore>,
mut query: Query<&mut Text, With<SceneCounterText>>,
mut text: Single<&mut Text, With<SceneCounterText>>,
) {
if let Some(diagnostic) = diagnostics.get(&VelloDiagnosticsPlugin::PATH_SEGMENTS_COUNT) {
if let Some(scene_count) = diagnostic.measurement() {
for mut text in query.iter_mut() {
text.0 = format!("Total segments: {}", scene_count.value);
}
}
}
let Some(scenes) = diagnostics.get(&VelloEntityCountDiagnosticsPlugin::SCENE_COUNT) else {
return;
};
let Some(scene_count) = scenes.measurement() else {
return;
};
let Some(path_segs) = diagnostics.get(&VelloFrameProfileDiagnosticsPlugin::PATH_SEGMENTS_COUNT)
else {
return;
};
let Some(path_segs_count) = path_segs.measurement() else {
return;
};

text.0 = format!(
"Total scenes: {}\nTotal segments: {}",
scene_count.value, path_segs_count.value
);
}
40 changes: 28 additions & 12 deletions src/diagnostics.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
use crate::render::VelloFrameData;
use crate::render::{VelloEntityCountData, VelloFrameProfileData};
use bevy::{
diagnostic::{Diagnostic, DiagnosticPath, Diagnostics, RegisterDiagnostic},
prelude::*,
};

/// Adds vello diagnostics to an App, specifically asset counting and profiling.
/// Adds Vello entity counting diagnostics to an App.
#[derive(Default)]
pub struct VelloDiagnosticsPlugin;
pub struct VelloEntityCountDiagnosticsPlugin;

impl Plugin for VelloDiagnosticsPlugin {
impl Plugin for VelloEntityCountDiagnosticsPlugin {
fn build(&self, app: &mut App) {
app.register_diagnostic(Diagnostic::new(Self::SCENE_COUNT).with_suffix(" scenes"))
.register_diagnostic(Diagnostic::new(Self::TEXT_COUNT).with_suffix(" texts"))
.register_diagnostic(
Diagnostic::new(Self::PATH_SEGMENTS_COUNT).with_suffix(" path segments"),
)
.add_systems(Update, Self::diagnostic_system);

#[cfg(feature = "svg")]
Expand All @@ -24,18 +21,15 @@ impl Plugin for VelloDiagnosticsPlugin {
}
}

impl VelloDiagnosticsPlugin {
pub const PATH_SEGMENTS_COUNT: DiagnosticPath =
DiagnosticPath::const_new("vello_path_segments");
impl VelloEntityCountDiagnosticsPlugin {
pub const SCENE_COUNT: DiagnosticPath = DiagnosticPath::const_new("vello_scenes");
pub const TEXT_COUNT: DiagnosticPath = DiagnosticPath::const_new("vello_texts");
#[cfg(feature = "svg")]
pub const SVG_COUNT: DiagnosticPath = DiagnosticPath::const_new("vello_svgs");
#[cfg(feature = "lottie")]
pub const LOTTIE_COUNT: DiagnosticPath = DiagnosticPath::const_new("vello_lotties");

fn diagnostic_system(mut diagnostics: Diagnostics, data: Res<VelloFrameData>) {
diagnostics.add_measurement(&Self::PATH_SEGMENTS_COUNT, || data.n_path_segs as f64);
fn diagnostic_system(mut diagnostics: Diagnostics, data: Res<VelloEntityCountData>) {
diagnostics.add_measurement(&Self::SCENE_COUNT, || data.n_scenes as f64);
diagnostics.add_measurement(&Self::TEXT_COUNT, || data.n_texts as f64);
#[cfg(feature = "svg")]
Expand All @@ -44,3 +38,25 @@ impl VelloDiagnosticsPlugin {
diagnostics.add_measurement(&Self::LOTTIE_COUNT, || data.n_lotties as f64);
}
}

/// Adds Vello frame profile diagnostics to an App.
#[derive(Default)]
pub struct VelloFrameProfileDiagnosticsPlugin;

impl Plugin for VelloFrameProfileDiagnosticsPlugin {
fn build(&self, app: &mut App) {
app.register_diagnostic(
Diagnostic::new(Self::PATH_SEGMENTS_COUNT).with_suffix(" path segments"),
)
.add_systems(Update, Self::diagnostic_system);
}
}

impl VelloFrameProfileDiagnosticsPlugin {
pub const PATH_SEGMENTS_COUNT: DiagnosticPath =
DiagnosticPath::const_new("vello_path_segments");

fn diagnostic_system(mut diagnostics: Diagnostics, data: Res<VelloFrameProfileData>) {
diagnostics.add_measurement(&Self::PATH_SEGMENTS_COUNT, || data.n_path_segs as f64);
}
}
63 changes: 33 additions & 30 deletions src/integrations/lottie/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use super::{
use crate::{
render::{
prepare::{PrepareRenderInstance, PreparedAffine, PreparedTransform},
VelloFrameData, VelloView,
VelloEntityCountData, VelloView,
},
CoordinateSpace, SkipEncoding,
};
Expand Down Expand Up @@ -56,17 +56,16 @@ pub fn extract_lottie_assets(
>,
>,
assets: Extract<Res<Assets<VelloLottie>>>,
mut frame_data: ResMut<VelloFrameData>,
mut frame_data: ResMut<VelloEntityCountData>,
) {
let mut n_lotties = 0;

// Respect camera ordering
let mut views: Vec<(&ExtractedCamera, Option<&RenderLayers>)> =
query_views.into_iter().collect();
views.sort_by(|(camera_a, _), (camera_b, _)| camera_a.order.cmp(&camera_b.order));
// Sort cameras by rendering order
let mut views: Vec<_> = query_views.iter().collect();
views.sort_unstable_by_key(|(camera, _)| camera.order);

for (
asset,
asset_handle,
asset_anchor,
coord_space,
transform,
Expand All @@ -78,29 +77,33 @@ pub fn extract_lottie_assets(
inherited_visibility,
) in query_vectors.iter()
{
if let Some(asset) = assets.get(asset.id()) {
if view_visibility.get() && inherited_visibility.get() {
let svg_render_layers = render_layers.unwrap_or_default();
for (_, camera_render_layers) in views.iter() {
if svg_render_layers.intersects(camera_render_layers.unwrap_or_default()) {
let playhead = playhead.frame();
commands
.spawn(ExtractedLottieAsset {
asset: asset.to_owned(),
transform: *transform,
asset_anchor: *asset_anchor,
theme: theme.cloned(),
render_mode: *coord_space,
playhead,
alpha: asset.alpha,
ui_node: ui_node.cloned(),
})
.insert(TemporaryRenderEntity);
n_lotties += 1;
break;
}
}
}
// Skip if visibility conditions are not met
if !view_visibility.get() || !inherited_visibility.get() {
continue;
}
// Skip if asset isn't loaded.
let Some(asset) = assets.get(asset_handle.id()) else {
continue;
};

// Check if any camera renders this asset
let asset_render_layers = render_layers.unwrap_or_default();
if views.iter().any(|(_, camera_layers)| {
asset_render_layers.intersects(camera_layers.unwrap_or_default())
}) {
commands
.spawn(ExtractedLottieAsset {
asset: asset.clone(),
transform: *transform,
asset_anchor: *asset_anchor,
theme: theme.cloned(),
render_mode: *coord_space,
playhead: playhead.frame(),
alpha: asset.alpha,
ui_node: ui_node.cloned(),
})
.insert(TemporaryRenderEntity);
n_lotties += 1;
}
}

Expand Down
58 changes: 31 additions & 27 deletions src/integrations/svg/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{
prelude::*,
render::{
prepare::{PrepareRenderInstance, PreparedAffine, PreparedTransform},
VelloFrameData,
VelloEntityCountData,
},
};
use bevy::{
Expand Down Expand Up @@ -52,17 +52,16 @@ pub fn extract_svg_assets(
>,
>,
assets: Extract<Res<Assets<VelloSvg>>>,
mut frame_data: ResMut<VelloFrameData>,
mut frame_data: ResMut<VelloEntityCountData>,
) {
let mut n_svgs = 0;

// Respect camera ordering
let mut views: Vec<(&ExtractedCamera, Option<&RenderLayers>)> =
query_views.into_iter().collect();
views.sort_by(|(camera_a, _), (camera_b, _)| camera_a.order.cmp(&camera_b.order));
// Sort cameras by rendering order
let mut views: Vec<_> = query_views.iter().collect();
views.sort_unstable_by_key(|(camera, _)| camera.order);

for (
asset,
asset_handle,
asset_anchor,
coord_space,
transform,
Expand All @@ -72,26 +71,31 @@ pub fn extract_svg_assets(
inherited_visibility,
) in query_vectors.iter()
{
if let Some(asset) = assets.get(asset.id()) {
if view_visibility.get() && inherited_visibility.get() {
let svg_render_layers = render_layers.unwrap_or_default();
for (_, camera_render_layers) in views.iter() {
if svg_render_layers.intersects(camera_render_layers.unwrap_or_default()) {
commands
.spawn(ExtractedVelloSvg {
asset: asset.to_owned(),
transform: *transform,
asset_anchor: *asset_anchor,
render_mode: *coord_space,
ui_node: ui_node.cloned(),
alpha: asset.alpha,
})
.insert(TemporaryRenderEntity);
n_svgs += 1;
break;
}
}
}
// Skip if visibility conditions are not met
if !view_visibility.get() || !inherited_visibility.get() {
continue;
}
// Skip if asset isn't loaded.
let Some(asset) = assets.get(asset_handle.id()) else {
continue;
};

// Check if any camera renders this asset
let asset_render_layers = render_layers.unwrap_or_default();
if views.iter().any(|(_, camera_layers)| {
asset_render_layers.intersects(camera_layers.unwrap_or_default())
}) {
commands
.spawn(ExtractedVelloSvg {
asset: asset.to_owned(),
transform: *transform,
asset_anchor: *asset_anchor,
render_mode: *coord_space,
ui_node: ui_node.cloned(),
alpha: asset.alpha,
})
.insert(TemporaryRenderEntity);
n_svgs += 1;
}
}

Expand Down
8 changes: 3 additions & 5 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,8 @@ use bevy::prelude::*;
mod plugin;
pub use plugin::VelloPlugin;

mod diagnostics;
pub use diagnostics::VelloDiagnosticsPlugin;

pub mod debug;
pub mod diagnostics;
pub mod integrations;
pub mod render;
pub mod text;
Expand Down Expand Up @@ -82,7 +80,7 @@ pub struct VelloTextBundle {
/// A simple newtype component wrapper for [`vello::Scene`] for rendering.
#[derive(Component, Default, Clone, Deref, DerefMut)]
#[require(CoordinateSpace, Transform, Visibility)]
pub struct VelloScene(Box<vello::Scene>);
pub struct VelloScene(vello::Scene);

impl VelloScene {
pub fn new() -> Self {
Expand All @@ -92,6 +90,6 @@ impl VelloScene {

impl From<vello::Scene> for VelloScene {
fn from(scene: vello::Scene) -> Self {
Self(Box::new(scene))
Self(scene)
}
}
Loading

0 comments on commit 236a7c1

Please sign in to comment.