Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Persistent Render World #14252

Closed
Closed
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
12 changes: 11 additions & 1 deletion crates/bevy_core_pipeline/src/core_3d/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ use bevy_ecs::{entity::EntityHashSet, prelude::*};
use bevy_math::FloatOrd;
use bevy_render::{
camera::{Camera, ExtractedCamera},
extract_component::ExtractComponentPlugin,
extract_component::{ExtractComponentPlugin, MainToRenderEntityMap},
prelude::Msaa,
render_graph::{EmptyNode, RenderGraphApp, ViewNodeRunner},
render_phase::{
Expand Down Expand Up @@ -504,6 +504,7 @@ impl CachedRenderPipelinePhaseItem for Transparent3d {

pub fn extract_core_3d_camera_phases(
mut commands: Commands,
mut map: ResMut<MainToRenderEntityMap>,
mut opaque_3d_phases: ResMut<ViewBinnedRenderPhases<Opaque3d>>,
mut alpha_mask_3d_phases: ResMut<ViewBinnedRenderPhases<AlphaMask3d>>,
mut transmissive_3d_phases: ResMut<ViewSortedRenderPhases<Transmissive3d>>,
Expand All @@ -518,6 +519,15 @@ pub fn extract_core_3d_camera_phases(
continue;
}

let render_entity: Entity;
if map.0.contains_key(&entity) {
render_entity = *map.0.get(&entity).unwrap();
} else {
render_entity = commands.spawn_empty().id();
map.0.insert(entity, render_entity);
}
let entity = render_entity;

commands.get_or_spawn(entity);

opaque_3d_phases.insert_or_clear(entity);
Expand Down
19 changes: 13 additions & 6 deletions crates/bevy_pbr/src/cluster/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,15 @@ use bevy_ecs::{
reflect::ReflectComponent,
system::{Commands, Query, Res, Resource},
world::{FromWorld, World},
prelude::ResMut,
};
use bevy_math::{AspectRatio, UVec2, UVec3, UVec4, Vec3Swizzles as _, Vec4};
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
use bevy_render::{
camera::Camera,
render_resource::{
camera::Camera, extract_component::MainToRenderEntityMap, render_resource::{
BindingResource, BufferBindingType, ShaderSize as _, ShaderType, StorageBuffer,
UniformBuffer,
},
renderer::{RenderDevice, RenderQueue},
Extract,
}, renderer::{RenderDevice, RenderQueue}, Extract
};
use bevy_utils::{hashbrown::HashSet, tracing::warn};

Expand Down Expand Up @@ -511,6 +509,7 @@ pub(crate) fn clusterable_object_order(
/// Extracts clusters from the main world from the render world.
pub fn extract_clusters(
mut commands: Commands,
mut map: ResMut<MainToRenderEntityMap>,
views: Extract<Query<(Entity, &Clusters, &Camera)>>,
) {
for (entity, clusters, camera) in &views {
Expand All @@ -536,7 +535,15 @@ pub fn extract_clusters(
}
}

commands.get_or_spawn(entity).insert((
let render_entity: Entity;
if map.0.contains_key(&entity) {
render_entity = *map.0.get(&entity).unwrap();
} else {
render_entity = commands.spawn_empty().id();
map.0.insert(entity, render_entity);
}

commands.entity(render_entity).insert((
ExtractedClusterableObjects { data },
ExtractedClusterConfig {
near: clusters.near,
Expand Down
4 changes: 4 additions & 0 deletions crates/bevy_pbr/src/render/light.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use bevy_render::{
texture::*,
view::{ExtractedView, RenderLayers, ViewVisibility, VisibleEntities, WithMesh},
Extract,
extract_component::Mayfly,
};
use bevy_transform::{components::GlobalTransform, prelude::Transform};
#[cfg(feature = "trace")]
Expand Down Expand Up @@ -922,6 +923,7 @@ pub fn prepare_lights(
light_entity,
face_index,
},
Mayfly {},
))
.id();
view_lights.push(view_light_entity);
Expand Down Expand Up @@ -980,6 +982,7 @@ pub fn prepare_lights(
},
*spot_light_frustum.unwrap(),
LightEntity::Spot { light_entity },
Mayfly {},
))
.id();

Expand Down Expand Up @@ -1079,6 +1082,7 @@ pub fn prepare_lights(
light_entity,
cascade_index,
},
Mayfly {},
))
.id();
view_lights.push(view_light_entity);
Expand Down
13 changes: 11 additions & 2 deletions crates/bevy_render/src/camera/camera.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use crate::{
ColorGrading, ExtractedView, ExtractedWindows, GpuCulling, RenderLayers, VisibleEntities,
},
Extract,
extract_component::{MainToRenderEntityMap, Mayfly},
};
use bevy_asset::{AssetEvent, AssetId, Assets, Handle};
use bevy_derive::{Deref, DerefMut};
Expand All @@ -22,7 +23,7 @@ use bevy_ecs::{
prelude::With,
query::Has,
reflect::ReflectComponent,
system::{Commands, Query, Res, ResMut, Resource},
system::{EntityCommands, Commands, Query, Res, ResMut, Resource},
};
use bevy_math::{vec2, Dir3, Mat4, Ray3d, Rect, URect, UVec2, UVec4, Vec2, Vec3};
use bevy_reflect::prelude::*;
Expand Down Expand Up @@ -844,6 +845,7 @@ pub fn extract_cameras(
Has<GpuCulling>,
)>,
>,
map: Res<MainToRenderEntityMap>,
primary_window: Extract<Query<Entity, With<PrimaryWindow>>>,
gpu_preprocessing_support: Res<GpuPreprocessingSupport>,
) {
Expand Down Expand Up @@ -885,7 +887,13 @@ pub fn extract_cameras(
continue;
}

let mut commands = commands.get_or_spawn(entity);
let entity_commands: EntityCommands;
if map.0.contains_key(&entity) {
entity_commands = commands.entity(*map.0.get(&entity).unwrap());
} else {
entity_commands = commands.spawn_empty();
}
let mut commands = entity_commands;

commands.insert((
ExtractedCamera {
Expand Down Expand Up @@ -920,6 +928,7 @@ pub fn extract_cameras(
},
visible_entities.clone(),
*frustum,
Mayfly{},
));

if let Some(temporal_jitter) = temporal_jitter {
Expand Down
38 changes: 26 additions & 12 deletions crates/bevy_render/src/extract_component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use bevy_ecs::{
use std::{marker::PhantomData, ops::Deref};

pub use bevy_render_macros::ExtractComponent;
pub use bevy_utils::EntityHashMap;

/// Stores the index of a uniform inside of [`ComponentUniforms`].
#[derive(Component)]
Expand Down Expand Up @@ -155,6 +156,9 @@ fn prepare_uniform_components<C>(
commands.insert_or_spawn_batch(entities);
}

#[derive(Resource)]
pub struct MainToRenderEntityMap(pub EntityHashMap<Entity, Entity>);

/// This plugin extracts the components into the "render world".
///
/// Therefore it sets up the [`ExtractSchedule`] step
Expand Down Expand Up @@ -185,6 +189,7 @@ impl<C, F> ExtractComponentPlugin<C, F> {
impl<C: ExtractComponent> Plugin for ExtractComponentPlugin<C> {
fn build(&self, app: &mut App) {
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
render_app.insert_resource(MainToRenderEntityMap(EntityHashMap::default()));
if self.only_extract_visible {
render_app.add_systems(ExtractSchedule, extract_visible_components::<C>);
} else {
Expand All @@ -205,36 +210,45 @@ impl<T: Asset> ExtractComponent for Handle<T> {
}
}

#[derive(Component)]
pub struct Mayfly;

/// This system extracts all components of the corresponding [`ExtractComponent`] type.
fn extract_components<C: ExtractComponent>(
mut commands: Commands,
mut previous_len: Local<usize>,
mut map: ResMut<MainToRenderEntityMap>,
query: Extract<Query<(Entity, C::QueryData), C::QueryFilter>>,
) {
let mut values = Vec::with_capacity(*previous_len);
for (entity, query_item) in &query {
if let Some(component) = C::extract_component(query_item) {
values.push((entity, component));
if map.0.contains_key(&entity) {
let render_entity = map.0.get(&entity).unwrap();
commands.insert_or_spawn_batch([(*render_entity, component)]);
} else {
let id = commands.spawn((component, Mayfly{})).id();
map.0.insert(entity, id);
}
}
}
*previous_len = values.len();
commands.insert_or_spawn_batch(values);
}

/// This system extracts all visible components of the corresponding [`ExtractComponent`] type.
fn extract_visible_components<C: ExtractComponent>(
mut commands: Commands,
mut previous_len: Local<usize>,
mut map: ResMut<MainToRenderEntityMap>,
query: Extract<Query<(Entity, &ViewVisibility, C::QueryData), C::QueryFilter>>,
) {
let mut values = Vec::with_capacity(*previous_len);
for (entity, view_visibility, query_item) in &query {
if view_visibility.get() {
if let Some(component) = C::extract_component(query_item) {
values.push((entity, component));
if let Some(component) = C::extract_component(query_item) {
if view_visibility.get() {
if map.0.contains_key(&entity) {
let render_entity = map.0.get(&entity).unwrap();
commands.insert_or_spawn_batch([(*render_entity, component)]);
} else {
let id = commands.spawn((component, Mayfly)).id();
map.0.insert(entity, id);
}
}
}
}
*previous_len = values.len();
commands.insert_or_spawn_batch(values);
}
41 changes: 39 additions & 2 deletions crates/bevy_render/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ pub mod prelude {
use batching::gpu_preprocessing::BatchingPlugin;
use bevy_ecs::schedule::ScheduleBuildSettings;
use bevy_utils::prelude::default;
use extract_component::MainToRenderEntityMap;
pub use extract_param::Extract;

use bevy_hierarchy::ValidParentCheckPlugin;
Expand All @@ -73,6 +74,7 @@ use crate::{
render_resource::{PipelineCache, Shader, ShaderLoader},
renderer::{render_system, RenderInstance},
settings::RenderCreation,
extract_component::Mayfly,
view::{ViewPlugin, WindowRenderPlugin},
};
use bevy_app::{App, AppLabel, Plugin, SubApp};
Expand Down Expand Up @@ -430,6 +432,34 @@ fn extract(main_world: &mut World, render_world: &mut World) {
main_world.insert_resource(ScratchMainWorld(scratch_world));
}

fn print_entities(render_world: &World) {
let entity_count = render_world.entities().total_count();
println!("Entities: {:?}", entity_count);

if entity_count < 20 {
for entity in render_world.iter_entities() {
print!("[");
for component_info in render_world.inspect_entity(entity.id()) {
print!("{:?}, ", component_info.name());
}
print!("] \n");
}
}
}

fn clear_map(mut map: ResMut<MainToRenderEntityMap>) {
map.0.clear();
}

fn despawn_mayflies(
mut commands: Commands,
query: Query<Entity, With<Mayfly>>,
) {
for entity in query.iter() {
commands.entity(entity).despawn();
}
}

/// SAFETY: this function must be called from the main thread.
unsafe fn initialize_render_app(app: &mut App) {
app.init_resource::<ScratchMainWorld>();
Expand Down Expand Up @@ -461,9 +491,15 @@ unsafe fn initialize_render_app(app: &mut App) {
(
PipelineCache::process_pipeline_queue_system.before(render_system),
render_system,
print_entities.after(render_system),
)
.in_set(RenderSet::Render),
World::clear_entities.in_set(RenderSet::Cleanup),
(
//World::clear_entities,
clear_map,
despawn_mayflies
)
.in_set(RenderSet::Cleanup),
),
);

Expand All @@ -479,7 +515,7 @@ unsafe fn initialize_render_app(app: &mut App) {
// reserve all existing main world entities for use in render_app
// they can only be spawned using `get_or_spawn()`
let total_count = main_world.entities().total_count();

/*
assert_eq!(
render_world.entities().len(),
0,
Expand All @@ -492,6 +528,7 @@ unsafe fn initialize_render_app(app: &mut App) {
.entities_mut()
.flush_and_reserve_invalid_assuming_no_entities(total_count);
}
*/
}

// run extract schedule
Expand Down
5 changes: 3 additions & 2 deletions crates/bevy_ui/src/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ use bevy_render::{
texture::Image,
view::{ExtractedView, ViewUniforms},
Extract, RenderApp, RenderSet,
extract_component::Mayfly,
};
use bevy_sprite::TextureAtlasLayout;
#[cfg(feature = "bevy_text")]
Expand Down Expand Up @@ -759,7 +760,7 @@ pub fn extract_default_ui_camera_view(
UI_CAMERA_FAR,
);
let default_camera_view = commands
.spawn(ExtractedView {
.spawn((ExtractedView {
clip_from_view: projection_matrix,
world_from_view: GlobalTransform::from_xyz(
0.0,
Expand All @@ -775,7 +776,7 @@ pub fn extract_default_ui_camera_view(
physical_size.y,
),
color_grading: Default::default(),
})
}, Mayfly{}))
.id();
commands
.get_or_spawn(entity)
Expand Down
Loading