 36c6f29832
			
		
	
	
		36c6f29832
		
			
		
	
	
	
	
		
			
			# Objective - After #13894, I noticed the performance of `many_lights `dropped from 120+ to 60+. I reviewed the PR but couldn't identify any mistakes. After profiling, I discovered that `Hashmap::Clone `was very slow when its not empty, causing `extract_light` to increase from 3ms to 8ms. - Lighting only checks visibility for 3D Meshes. We don't need to maintain a TypeIdMap for this, as it not only impacts performance negatively but also reduces ergonomics. ## Solution - use VisibleMeshEntities for lighint visibility checking. ## Performance cargo run --release --example many_lights --features bevy/trace_tracy name="bevy_pbr::light::check_point_light_mesh_visibility"}  system{name="bevy_pbr::render::light::extract_lights"}  ## Migration Guide > now `SpotLightBundle` , `CascadesVisibleEntities `and `CubemapVisibleEntities `use VisibleMeshEntities instead of `VisibleEntities` --------- Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
		
			
				
	
	
		
			141 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			141 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
| use crate::{
 | |
|     CascadeShadowConfig, Cascades, DirectionalLight, Material, PointLight, SpotLight,
 | |
|     StandardMaterial,
 | |
| };
 | |
| use bevy_asset::Handle;
 | |
| use bevy_derive::{Deref, DerefMut};
 | |
| use bevy_ecs::entity::{Entity, EntityHashMap};
 | |
| use bevy_ecs::{bundle::Bundle, component::Component, reflect::ReflectComponent};
 | |
| use bevy_reflect::Reflect;
 | |
| use bevy_render::{
 | |
|     mesh::Mesh,
 | |
|     primitives::{CascadesFrusta, CubemapFrusta, Frustum},
 | |
|     view::{InheritedVisibility, ViewVisibility, Visibility},
 | |
| };
 | |
| use bevy_transform::components::{GlobalTransform, Transform};
 | |
| 
 | |
| /// A component bundle for PBR entities with a [`Mesh`] and a [`StandardMaterial`].
 | |
| pub type PbrBundle = MaterialMeshBundle<StandardMaterial>;
 | |
| 
 | |
| /// A component bundle for entities with a [`Mesh`] and a [`Material`].
 | |
| #[derive(Bundle, Clone)]
 | |
| pub struct MaterialMeshBundle<M: Material> {
 | |
|     pub mesh: Handle<Mesh>,
 | |
|     pub material: Handle<M>,
 | |
|     pub transform: Transform,
 | |
|     pub global_transform: GlobalTransform,
 | |
|     /// User indication of whether an entity is visible
 | |
|     pub visibility: Visibility,
 | |
|     /// Inherited visibility of an entity.
 | |
|     pub inherited_visibility: InheritedVisibility,
 | |
|     /// Algorithmically-computed indication of whether an entity is visible and should be extracted for rendering
 | |
|     pub view_visibility: ViewVisibility,
 | |
| }
 | |
| 
 | |
| impl<M: Material> Default for MaterialMeshBundle<M> {
 | |
|     fn default() -> Self {
 | |
|         Self {
 | |
|             mesh: Default::default(),
 | |
|             material: Default::default(),
 | |
|             transform: Default::default(),
 | |
|             global_transform: Default::default(),
 | |
|             visibility: Default::default(),
 | |
|             inherited_visibility: Default::default(),
 | |
|             view_visibility: Default::default(),
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| /// Collection of mesh entities visible for 3D lighting.
 | |
| /// This component contains all mesh entities visible from the current light view.
 | |
| /// The collection is updated automatically by [`crate::SimulationLightSystems`].
 | |
| #[derive(Component, Clone, Debug, Default, Reflect, Deref, DerefMut)]
 | |
| #[reflect(Component)]
 | |
| pub struct VisibleMeshEntities {
 | |
|     #[reflect(ignore)]
 | |
|     pub entities: Vec<Entity>,
 | |
| }
 | |
| 
 | |
| #[derive(Component, Clone, Debug, Default, Reflect)]
 | |
| #[reflect(Component)]
 | |
| pub struct CubemapVisibleEntities {
 | |
|     #[reflect(ignore)]
 | |
|     data: [VisibleMeshEntities; 6],
 | |
| }
 | |
| 
 | |
| impl CubemapVisibleEntities {
 | |
|     pub fn get(&self, i: usize) -> &VisibleMeshEntities {
 | |
|         &self.data[i]
 | |
|     }
 | |
| 
 | |
|     pub fn get_mut(&mut self, i: usize) -> &mut VisibleMeshEntities {
 | |
|         &mut self.data[i]
 | |
|     }
 | |
| 
 | |
|     pub fn iter(&self) -> impl DoubleEndedIterator<Item = &VisibleMeshEntities> {
 | |
|         self.data.iter()
 | |
|     }
 | |
| 
 | |
|     pub fn iter_mut(&mut self) -> impl DoubleEndedIterator<Item = &mut VisibleMeshEntities> {
 | |
|         self.data.iter_mut()
 | |
|     }
 | |
| }
 | |
| 
 | |
| #[derive(Component, Clone, Debug, Default, Reflect)]
 | |
| #[reflect(Component)]
 | |
| pub struct CascadesVisibleEntities {
 | |
|     /// Map of view entity to the visible entities for each cascade frustum.
 | |
|     #[reflect(ignore)]
 | |
|     pub entities: EntityHashMap<Vec<VisibleMeshEntities>>,
 | |
| }
 | |
| 
 | |
| /// A component bundle for [`PointLight`] entities.
 | |
| #[derive(Debug, Bundle, Default, Clone)]
 | |
| pub struct PointLightBundle {
 | |
|     pub point_light: PointLight,
 | |
|     pub cubemap_visible_entities: CubemapVisibleEntities,
 | |
|     pub cubemap_frusta: CubemapFrusta,
 | |
|     pub transform: Transform,
 | |
|     pub global_transform: GlobalTransform,
 | |
|     /// Enables or disables the light
 | |
|     pub visibility: Visibility,
 | |
|     /// Inherited visibility of an entity.
 | |
|     pub inherited_visibility: InheritedVisibility,
 | |
|     /// Algorithmically-computed indication of whether an entity is visible and should be extracted for rendering
 | |
|     pub view_visibility: ViewVisibility,
 | |
| }
 | |
| 
 | |
| /// A component bundle for spot light entities
 | |
| #[derive(Debug, Bundle, Default, Clone)]
 | |
| pub struct SpotLightBundle {
 | |
|     pub spot_light: SpotLight,
 | |
|     pub visible_entities: VisibleMeshEntities,
 | |
|     pub frustum: Frustum,
 | |
|     pub transform: Transform,
 | |
|     pub global_transform: GlobalTransform,
 | |
|     /// Enables or disables the light
 | |
|     pub visibility: Visibility,
 | |
|     /// Inherited visibility of an entity.
 | |
|     pub inherited_visibility: InheritedVisibility,
 | |
|     /// Algorithmically-computed indication of whether an entity is visible and should be extracted for rendering
 | |
|     pub view_visibility: ViewVisibility,
 | |
| }
 | |
| 
 | |
| /// A component bundle for [`DirectionalLight`] entities.
 | |
| #[derive(Debug, Bundle, Default, Clone)]
 | |
| pub struct DirectionalLightBundle {
 | |
|     pub directional_light: DirectionalLight,
 | |
|     pub frusta: CascadesFrusta,
 | |
|     pub cascades: Cascades,
 | |
|     pub cascade_shadow_config: CascadeShadowConfig,
 | |
|     pub visible_entities: CascadesVisibleEntities,
 | |
|     pub transform: Transform,
 | |
|     pub global_transform: GlobalTransform,
 | |
|     /// Enables or disables the light
 | |
|     pub visibility: Visibility,
 | |
|     /// Inherited visibility of an entity.
 | |
|     pub inherited_visibility: InheritedVisibility,
 | |
|     /// Algorithmically-computed indication of whether an entity is visible and should be extracted for rendering
 | |
|     pub view_visibility: ViewVisibility,
 | |
| }
 |