RenderGraph2: Lights node
This commit is contained in:
		
							parent
							
								
									c124cbe22f
								
							
						
					
					
						commit
						06b6ade902
					
				| @ -39,8 +39,7 @@ use self::{ | |||||||
|     }, |     }, | ||||||
|     render_graph::RenderGraph, |     render_graph::RenderGraph, | ||||||
|     render_resource::{ |     render_resource::{ | ||||||
|         entity_render_resource_assignments_system, |         entity_render_resource_assignments_system, resource_providers::UniformResourceProvider, | ||||||
|         resource_providers::{LightResourceProvider, UniformResourceProvider}, |  | ||||||
|         AssetBatchers, EntityRenderResourceAssignments, RenderResourceAssignments, |         AssetBatchers, EntityRenderResourceAssignments, RenderResourceAssignments, | ||||||
|     }, |     }, | ||||||
|     shader::{uniforms::StandardMaterial, Shader}, |     shader::{uniforms::StandardMaterial, Shader}, | ||||||
| @ -54,7 +53,10 @@ use bevy_window::{WindowCreated, WindowReference, WindowResized}; | |||||||
| use pass::PassDescriptor; | use pass::PassDescriptor; | ||||||
| use pipeline::pipelines::build_forward_pipeline; | use pipeline::pipelines::build_forward_pipeline; | ||||||
| use render_graph_2::{ | use render_graph_2::{ | ||||||
|     nodes::{Camera2dNode, CameraNode, PassNode, WindowSwapChainNode, WindowTextureNode, UniformNode}, |     nodes::{ | ||||||
|  |         Camera2dNode, CameraNode, LightsNode, PassNode, UniformNode, WindowSwapChainNode, | ||||||
|  |         WindowTextureNode, | ||||||
|  |     }, | ||||||
|     RenderGraph2, |     RenderGraph2, | ||||||
| }; | }; | ||||||
| use render_resource::resource_providers::mesh_resource_provider_system; | use render_resource::resource_providers::mesh_resource_provider_system; | ||||||
| @ -77,7 +79,6 @@ impl RenderPlugin { | |||||||
|         let mut render_graph = resources.get_mut::<RenderGraph>().unwrap(); |         let mut render_graph = resources.get_mut::<RenderGraph>().unwrap(); | ||||||
|         render_graph |         render_graph | ||||||
|             .build(&mut pipelines, &mut shaders) |             .build(&mut pipelines, &mut shaders) | ||||||
|             .add_resource_provider(LightResourceProvider::new(10)) |  | ||||||
|             .add_resource_provider(UniformResourceProvider::<LocalToWorld>::new(true)); |             .add_resource_provider(UniformResourceProvider::<LocalToWorld>::new(true)); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @ -123,7 +124,12 @@ impl AppPlugin for RenderPlugin { | |||||||
|             let resources = app.resources_mut(); |             let resources = app.resources_mut(); | ||||||
|             render_graph.add_system_node_named("camera", CameraNode::default(), resources); |             render_graph.add_system_node_named("camera", CameraNode::default(), resources); | ||||||
|             render_graph.add_system_node_named("camera2d", Camera2dNode::default(), resources); |             render_graph.add_system_node_named("camera2d", Camera2dNode::default(), resources); | ||||||
|             render_graph.add_system_node_named("standard_material", UniformNode::<StandardMaterial>::new(true), resources); |             render_graph.add_system_node_named( | ||||||
|  |                 "standard_material", | ||||||
|  |                 UniformNode::<StandardMaterial>::new(true), | ||||||
|  |                 resources, | ||||||
|  |             ); | ||||||
|  |             render_graph.add_system_node_named("lights", LightsNode::new(10), resources); | ||||||
|             render_graph.add_node_named( |             render_graph.add_node_named( | ||||||
|                 "swapchain", |                 "swapchain", | ||||||
|                 WindowSwapChainNode::new( |                 WindowSwapChainNode::new( | ||||||
| @ -185,7 +191,10 @@ impl AppPlugin for RenderPlugin { | |||||||
|             // TODO: replace these with "autowire" groups
 |             // TODO: replace these with "autowire" groups
 | ||||||
|             render_graph.add_node_edge("camera", "main_pass").unwrap(); |             render_graph.add_node_edge("camera", "main_pass").unwrap(); | ||||||
|             render_graph.add_node_edge("camera2d", "main_pass").unwrap(); |             render_graph.add_node_edge("camera2d", "main_pass").unwrap(); | ||||||
|             render_graph.add_node_edge("standard_material", "main_pass").unwrap(); |             render_graph | ||||||
|  |                 .add_node_edge("standard_material", "main_pass") | ||||||
|  |                 .unwrap(); | ||||||
|  |             render_graph.add_node_edge("lights", "main_pass").unwrap(); | ||||||
|             render_graph |             render_graph | ||||||
|                 .add_slot_edge( |                 .add_slot_edge( | ||||||
|                     "swapchain", |                     "swapchain", | ||||||
|  | |||||||
| @ -4,6 +4,7 @@ mod window_texture_node; | |||||||
| mod window_swapchain_node; | mod window_swapchain_node; | ||||||
| mod pass_node; | mod pass_node; | ||||||
| mod uniform_node; | mod uniform_node; | ||||||
|  | mod lights_node; | ||||||
| 
 | 
 | ||||||
| pub use camera_node::*; | pub use camera_node::*; | ||||||
| pub use camera2d_node::*; | pub use camera2d_node::*; | ||||||
| @ -11,3 +12,4 @@ pub use window_texture_node::*; | |||||||
| pub use window_swapchain_node::*; | pub use window_swapchain_node::*; | ||||||
| pub use pass_node::*; | pub use pass_node::*; | ||||||
| pub use uniform_node::*; | pub use uniform_node::*; | ||||||
|  | pub use lights_node::*; | ||||||
							
								
								
									
										150
									
								
								bevy_render/src/render_graph_2/nodes/lights_node.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										150
									
								
								bevy_render/src/render_graph_2/nodes/lights_node.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,150 @@ | |||||||
|  | use crate::{ | ||||||
|  |     render_graph_2::{CommandQueue, Node, ResourceSlots, SystemNode}, | ||||||
|  |     render_resource::{resource_name, BufferInfo, BufferUsage, RenderResourceAssignments}, | ||||||
|  |     renderer_2::{GlobalRenderResourceContext, RenderContext}, | ||||||
|  |     Light, LightRaw, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | use bevy_transform::prelude::*; | ||||||
|  | use legion::prelude::*; | ||||||
|  | use zerocopy::AsBytes; | ||||||
|  | 
 | ||||||
|  | #[derive(Default)] | ||||||
|  | pub struct LightsNode { | ||||||
|  |     command_queue: CommandQueue, | ||||||
|  |     max_lights: usize, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl LightsNode { | ||||||
|  |     pub fn new(max_lights: usize) -> Self { | ||||||
|  |         LightsNode { | ||||||
|  |             max_lights, | ||||||
|  |             command_queue: CommandQueue::default(), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl Node for LightsNode { | ||||||
|  |     fn update( | ||||||
|  |         &mut self, | ||||||
|  |         _world: &World, | ||||||
|  |         _resources: &Resources, | ||||||
|  |         render_context: &mut dyn RenderContext, | ||||||
|  |         _input: &ResourceSlots, | ||||||
|  |         _output: &mut ResourceSlots, | ||||||
|  |     ) { | ||||||
|  |         self.command_queue.execute(render_context); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[repr(C)] | ||||||
|  | #[derive(Clone, Copy, AsBytes)] | ||||||
|  | pub struct LightCount { | ||||||
|  |     pub num_lights: [u32; 4], | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl SystemNode for LightsNode { | ||||||
|  |     fn get_system(&self, resources: &mut Resources) -> Box<dyn Schedulable> { | ||||||
|  |         let mut light_buffer = None; | ||||||
|  |         let mut lights_are_dirty = true; | ||||||
|  |         // TODO: merge these
 | ||||||
|  |         let mut tmp_count_buffer = None; | ||||||
|  |         let mut tmp_light_buffer = None; | ||||||
|  |         let mut command_queue = self.command_queue.clone(); | ||||||
|  |         let max_lights = self.max_lights; | ||||||
|  |         SystemBuilder::new("light_node") | ||||||
|  |             .read_resource::<GlobalRenderResourceContext>() | ||||||
|  |             // TODO: this write on RenderResourceAssignments will prevent this system from running in parallel with other systems that do the same
 | ||||||
|  |             .write_resource::<RenderResourceAssignments>() | ||||||
|  |             .with_query(<(Read<Light>, Read<LocalToWorld>, Read<Translation>)>::query()) | ||||||
|  |             .build( | ||||||
|  |                 move |_, | ||||||
|  |                       world, | ||||||
|  |                       (render_resource_context, ref mut render_resource_assignments), | ||||||
|  |                       query| { | ||||||
|  |                     if !lights_are_dirty { | ||||||
|  |                         return; | ||||||
|  |                     } | ||||||
|  | 
 | ||||||
|  |                     let render_resources = &render_resource_context.context; | ||||||
|  |                     if light_buffer.is_none() { | ||||||
|  |                         let light_uniform_size = std::mem::size_of::<LightCount>() | ||||||
|  |                             + max_lights * std::mem::size_of::<LightRaw>(); | ||||||
|  | 
 | ||||||
|  |                         let buffer = render_resources.create_buffer(BufferInfo { | ||||||
|  |                             size: light_uniform_size, | ||||||
|  |                             buffer_usage: BufferUsage::UNIFORM | ||||||
|  |                                 | BufferUsage::COPY_SRC | ||||||
|  |                                 | BufferUsage::COPY_DST, | ||||||
|  |                             ..Default::default() | ||||||
|  |                         }); | ||||||
|  |                         render_resource_assignments.set(resource_name::uniform::LIGHTS, buffer); | ||||||
|  |                         light_buffer = Some(buffer); | ||||||
|  |                     } | ||||||
|  | 
 | ||||||
|  |                     let light_count = query.iter(world).count(); | ||||||
|  | 
 | ||||||
|  |                     if light_count == 0 { | ||||||
|  |                         return; | ||||||
|  |                     } | ||||||
|  | 
 | ||||||
|  |                     lights_are_dirty = false; | ||||||
|  |                     let size = std::mem::size_of::<LightRaw>(); | ||||||
|  |                     let total_size = size * light_count; | ||||||
|  |                     let light_count_size = std::mem::size_of::<LightCount>(); | ||||||
|  | 
 | ||||||
|  |                     if let Some(old_tmp_light_buffer) = tmp_light_buffer { | ||||||
|  |                         render_resources.remove_buffer(old_tmp_light_buffer); | ||||||
|  |                     } | ||||||
|  | 
 | ||||||
|  |                     if let Some(old_tmp_count_buffer) = tmp_count_buffer { | ||||||
|  |                         render_resources.remove_buffer(old_tmp_count_buffer); | ||||||
|  |                     } | ||||||
|  | 
 | ||||||
|  |                     tmp_light_buffer = Some(render_resources.create_buffer_mapped( | ||||||
|  |                         BufferInfo { | ||||||
|  |                             size: total_size, | ||||||
|  |                             buffer_usage: BufferUsage::COPY_SRC, | ||||||
|  |                             ..Default::default() | ||||||
|  |                         }, | ||||||
|  |                         &mut |data, _renderer| { | ||||||
|  |                             for ((light, local_to_world, translation), slot) in | ||||||
|  |                                 query.iter(world).zip(data.chunks_exact_mut(size)) | ||||||
|  |                             { | ||||||
|  |                                 slot.copy_from_slice( | ||||||
|  |                                     LightRaw::from(&light, &local_to_world.0, &translation) | ||||||
|  |                                         .as_bytes(), | ||||||
|  |                                 ); | ||||||
|  |                             } | ||||||
|  |                         }, | ||||||
|  |                     )); | ||||||
|  |                     tmp_count_buffer = Some(render_resources.create_buffer_mapped( | ||||||
|  |                         BufferInfo { | ||||||
|  |                             size: light_count_size, | ||||||
|  |                             buffer_usage: BufferUsage::COPY_SRC, | ||||||
|  |                             ..Default::default() | ||||||
|  |                         }, | ||||||
|  |                         &mut |data, _renderer| { | ||||||
|  |                             data.copy_from_slice([light_count as u32, 0, 0, 0].as_bytes()); | ||||||
|  |                         }, | ||||||
|  |                     )); | ||||||
|  | 
 | ||||||
|  |                     command_queue.copy_buffer_to_buffer( | ||||||
|  |                         tmp_count_buffer.unwrap(), | ||||||
|  |                         0, | ||||||
|  |                         light_buffer.unwrap(), | ||||||
|  |                         0, | ||||||
|  |                         light_count_size as u64, | ||||||
|  |                     ); | ||||||
|  | 
 | ||||||
|  |                     command_queue.copy_buffer_to_buffer( | ||||||
|  |                         tmp_light_buffer.unwrap(), | ||||||
|  |                         0, | ||||||
|  |                         light_buffer.unwrap(), | ||||||
|  |                         light_count_size as u64, | ||||||
|  |                         total_size as u64, | ||||||
|  |                     ); | ||||||
|  |                 }, | ||||||
|  |             ) | ||||||
|  |     } | ||||||
|  | } | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Carter Anderson
						Carter Anderson