render graph 2: schedulers + window nodes
This commit is contained in:
		
							parent
							
								
									210a50e781
								
							
						
					
					
						commit
						5fec31b63c
					
				| @ -41,7 +41,7 @@ use self::{ | |||||||
|     render_resource::{ |     render_resource::{ | ||||||
|         entity_render_resource_assignments_system, |         entity_render_resource_assignments_system, | ||||||
|         resource_providers::{ |         resource_providers::{ | ||||||
|             Camera2dResourceProvider, CameraResourceProvider, LightResourceProvider, |             LightResourceProvider, | ||||||
|             UniformResourceProvider, |             UniformResourceProvider, | ||||||
|         }, |         }, | ||||||
|         AssetBatchers, EntityRenderResourceAssignments, RenderResourceAssignments, |         AssetBatchers, EntityRenderResourceAssignments, RenderResourceAssignments, | ||||||
| @ -50,12 +50,11 @@ use self::{ | |||||||
|     texture::Texture, |     texture::Texture, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| use bevy_app::{stage, AppBuilder, AppPlugin, GetEventReader}; | use bevy_app::{stage, AppBuilder, AppPlugin}; | ||||||
| use bevy_asset::AssetStorage; | use bevy_asset::AssetStorage; | ||||||
| use bevy_transform::prelude::LocalToWorld; | use bevy_transform::prelude::LocalToWorld; | ||||||
| use bevy_window::WindowResized; | use render_resource::resource_providers::{mesh_resource_provider_system}; | ||||||
| use render_resource::resource_providers::{CameraNode, mesh_resource_provider_system}; | use render_graph_2::{nodes::{Camera2dNode, CameraNode}, RenderGraph2}; | ||||||
| use render_graph_2::RenderGraph2; |  | ||||||
| 
 | 
 | ||||||
| pub static RENDER_RESOURCE_STAGE: &str = "render_resource"; | pub static RENDER_RESOURCE_STAGE: &str = "render_resource"; | ||||||
| pub static RENDER_STAGE: &str = "render"; | pub static RENDER_STAGE: &str = "render"; | ||||||
| @ -78,9 +77,6 @@ impl RenderPlugin { | |||||||
|             .add_draw_target(AssignedBatchesDrawTarget::default()) |             .add_draw_target(AssignedBatchesDrawTarget::default()) | ||||||
|             .add_draw_target(AssignedMeshesDrawTarget::default()) |             .add_draw_target(AssignedMeshesDrawTarget::default()) | ||||||
|             .add_draw_target(UiDrawTarget::default()) |             .add_draw_target(UiDrawTarget::default()) | ||||||
|             .add_resource_provider(Camera2dResourceProvider::new( |  | ||||||
|                 resources.get_event_reader::<WindowResized>(), |  | ||||||
|             )) |  | ||||||
|             .add_resource_provider(LightResourceProvider::new(10)) |             .add_resource_provider(LightResourceProvider::new(10)) | ||||||
|             .add_resource_provider(UniformResourceProvider::<StandardMaterial>::new(true)) |             .add_resource_provider(UniformResourceProvider::<StandardMaterial>::new(true)) | ||||||
|             .add_resource_provider(UniformResourceProvider::<LocalToWorld>::new(true)) |             .add_resource_provider(UniformResourceProvider::<LocalToWorld>::new(true)) | ||||||
| @ -93,6 +89,7 @@ impl AppPlugin for RenderPlugin { | |||||||
|     fn build(&self, app: &mut AppBuilder) { |     fn build(&self, app: &mut AppBuilder) { | ||||||
|         let mut render_graph = RenderGraph2::default(); |         let mut render_graph = RenderGraph2::default(); | ||||||
|         render_graph.add_system_node(CameraNode::default(), app.resources_mut()); |         render_graph.add_system_node(CameraNode::default(), app.resources_mut()); | ||||||
|  |         render_graph.add_system_node(Camera2dNode::default(), app.resources_mut()); | ||||||
|         let mut asset_batchers = AssetBatchers::default(); |         let mut asset_batchers = AssetBatchers::default(); | ||||||
|         asset_batchers.batch_types2::<Mesh, StandardMaterial>(); |         asset_batchers.batch_types2::<Mesh, StandardMaterial>(); | ||||||
|         app.add_stage_after(stage::POST_UPDATE, RENDER_RESOURCE_STAGE) |         app.add_stage_after(stage::POST_UPDATE, RENDER_RESOURCE_STAGE) | ||||||
|  | |||||||
| @ -1,3 +1,5 @@ | |||||||
|  | pub mod nodes; | ||||||
|  | 
 | ||||||
| use crate::{ | use crate::{ | ||||||
|     render_resource::{RenderResource, ResourceInfo}, |     render_resource::{RenderResource, ResourceInfo}, | ||||||
|     renderer_2::RenderContext, |     renderer_2::RenderContext, | ||||||
| @ -76,37 +78,124 @@ impl NodeId { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | pub struct ResourceBinding { | ||||||
|  |     pub resource: Option<RenderResource>, | ||||||
|  |     pub slot: ResourceSlot, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Default)] | ||||||
|  | pub struct ResourceBindings { | ||||||
|  |     bindings: Vec<ResourceBinding>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl ResourceBindings { | ||||||
|  |     pub fn set(&mut self, index: usize, resource: RenderResource) { | ||||||
|  |         self.bindings[index].resource = Some(resource); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn set_named(&mut self, name: &str, resource: RenderResource) { | ||||||
|  |         let binding = self | ||||||
|  |             .bindings | ||||||
|  |             .iter_mut() | ||||||
|  |             .find(|b| b.slot.name == name) | ||||||
|  |             .expect("Name not found"); | ||||||
|  |         binding.resource = Some(resource); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn get(&self, index: usize) -> Option<RenderResource> { | ||||||
|  |         self.bindings | ||||||
|  |             .get(index) | ||||||
|  |             .and_then(|binding| binding.resource) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn get_named(&self, name: &str) -> Option<RenderResource> { | ||||||
|  |         self.bindings | ||||||
|  |             .iter() | ||||||
|  |             .find(|b| b.slot.name == name) | ||||||
|  |             .and_then(|binding| binding.resource) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl From<&ResourceSlot> for ResourceBinding { | ||||||
|  |     fn from(slot: &ResourceSlot) -> Self { | ||||||
|  |         ResourceBinding { | ||||||
|  |             resource: None, | ||||||
|  |             slot: slot.clone(), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl From<&[ResourceSlot]> for ResourceBindings { | ||||||
|  |     fn from(slots: &[ResourceSlot]) -> Self { | ||||||
|  |         ResourceBindings { | ||||||
|  |             bindings: slots | ||||||
|  |                 .iter() | ||||||
|  |                 .map(|s| s.into()) | ||||||
|  |                 .collect::<Vec<ResourceBinding>>(), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Clone)] | ||||||
| pub struct ResourceSlot { | pub struct ResourceSlot { | ||||||
|     name: Option<String>, |     name: &'static str, | ||||||
|     resource_type: ResourceInfo, |     resource_type: ResourceInfo, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub struct ResourceSlotBinding { | impl ResourceSlot { | ||||||
|     resource: RenderResource, |     pub const fn new(name: &'static str, resource_type: ResourceInfo) -> Self { | ||||||
| } |         ResourceSlot { | ||||||
| 
 |             name, | ||||||
| pub struct NodeDescriptor { |             resource_type, | ||||||
|     pub inputs: Vec<ResourceSlot>, |         } | ||||||
|     pub outputs: Vec<ResourceSlot>, |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub trait Node: Send + Sync + 'static { | pub trait Node: Send + Sync + 'static { | ||||||
|     fn descriptor(&self) -> &NodeDescriptor; |     fn input(&self) -> &[ResourceSlot] { | ||||||
|  |         &[] | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn output(&self) -> &[ResourceSlot] { | ||||||
|  |         &[] | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     fn update( |     fn update( | ||||||
|         &mut self, |         &mut self, | ||||||
|         world: &World, |         world: &World, | ||||||
|         resources: &Resources, |         resources: &Resources, | ||||||
|         render_context: &mut dyn RenderContext, |         render_context: &mut dyn RenderContext, | ||||||
|  |         input: &ResourceBindings, | ||||||
|  |         output: &mut ResourceBindings, | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | pub struct NodeState { | ||||||
|  |     pub node: Box<dyn Node>, | ||||||
|  |     pub input: ResourceBindings, | ||||||
|  |     pub output: ResourceBindings, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl NodeState { | ||||||
|  |     pub fn new<T>(node: T) -> Self | ||||||
|  |     where | ||||||
|  |         T: Node, | ||||||
|  |     { | ||||||
|  |         NodeState { | ||||||
|  |             input: ResourceBindings::from(node.input()), | ||||||
|  |             output: ResourceBindings::from(node.output()), | ||||||
|  |             node: Box::new(node), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| pub trait SystemNode: Node { | pub trait SystemNode: Node { | ||||||
|     fn get_system(&self, resources: &mut Resources) -> Box<dyn Schedulable>; |     fn get_system(&self, resources: &mut Resources) -> Box<dyn Schedulable>; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Default)] | #[derive(Default)] | ||||||
| pub struct RenderGraph2 { | pub struct RenderGraph2 { | ||||||
|     nodes: HashMap<NodeId, Box<dyn Node>>, |     nodes: HashMap<NodeId, NodeState>, | ||||||
|     new_systems: Vec<Box<dyn Schedulable>>, |     new_systems: Vec<Box<dyn Schedulable>>, | ||||||
|     system_executor: Option<Executor>, |     system_executor: Option<Executor>, | ||||||
| } | } | ||||||
| @ -117,7 +206,7 @@ impl RenderGraph2 { | |||||||
|         T: Node + 'static, |         T: Node + 'static, | ||||||
|     { |     { | ||||||
|         let id = NodeId::new(); |         let id = NodeId::new(); | ||||||
|         self.nodes.insert(id, Box::new(node)); |         self.nodes.insert(id, NodeState::new(node)); | ||||||
|         id |         id | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -127,14 +216,10 @@ impl RenderGraph2 { | |||||||
|     { |     { | ||||||
|         let id = NodeId::new(); |         let id = NodeId::new(); | ||||||
|         self.new_systems.push(node.get_system(resources)); |         self.new_systems.push(node.get_system(resources)); | ||||||
|         self.nodes.insert(id, Box::new(node)); |         self.nodes.insert(id, NodeState::new(node)); | ||||||
|         id |         id | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn get_schedule(&mut self) -> impl Iterator<Item = &mut Box<dyn Node>> { |  | ||||||
|         self.nodes.values_mut() |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     pub fn take_executor(&mut self) -> Option<Executor> { |     pub fn take_executor(&mut self) -> Option<Executor> { | ||||||
|         // rebuild executor if there are new systems
 |         // rebuild executor if there are new systems
 | ||||||
|         if self.new_systems.len() > 0 { |         if self.new_systems.len() > 0 { | ||||||
| @ -157,3 +242,54 @@ impl RenderGraph2 { | |||||||
|         self.system_executor = Some(executor); |         self.system_executor = Some(executor); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | #[derive(Default)] | ||||||
|  | pub struct Stage<'a> { | ||||||
|  |     ordered_jobs: Vec<OrderedJob<'a>>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl<'a> Stage<'a> { | ||||||
|  |     pub fn add(&mut self, job: OrderedJob<'a>) { | ||||||
|  |         self.ordered_jobs.push(job); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn iter_mut(&mut self) -> impl Iterator<Item=&mut OrderedJob<'a>> { | ||||||
|  |         self.ordered_jobs.iter_mut() | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Default)] | ||||||
|  | pub struct OrderedJob<'a> { | ||||||
|  |     node_states: Vec<&'a mut NodeState>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl<'a> OrderedJob<'a> { | ||||||
|  |     pub fn add(&mut self, node_state: &'a mut NodeState) { | ||||||
|  |         self.node_states.push(node_state); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn iter_mut(&mut self) -> impl Iterator<Item=&mut &'a mut NodeState> { | ||||||
|  |         self.node_states.iter_mut() | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | pub trait RenderGraphScheduler { | ||||||
|  |     fn get_stages<'a>(&mut self, render_graph: &'a mut RenderGraph2) -> Vec<Stage<'a>>; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Default)] | ||||||
|  | pub struct LinearScheduler; | ||||||
|  | 
 | ||||||
|  | impl RenderGraphScheduler for LinearScheduler { | ||||||
|  |     fn get_stages<'a>(&mut self, render_graph: &'a mut RenderGraph2) -> Vec<Stage<'a>> { | ||||||
|  |         let mut stage = Stage::default(); | ||||||
|  |         let mut job = OrderedJob::default(); | ||||||
|  |         for node_state in render_graph.nodes.values_mut() { | ||||||
|  |             job.add(node_state);        
 | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         stage.ordered_jobs.push(job); | ||||||
|  | 
 | ||||||
|  |         vec![stage] | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										100
									
								
								bevy_render/src/render_graph_2/nodes/camera2d_node.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								bevy_render/src/render_graph_2/nodes/camera2d_node.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,100 @@ | |||||||
|  | use bevy_app::{Events, GetEventReader}; | ||||||
|  | use bevy_window::WindowResized; | ||||||
|  | 
 | ||||||
|  | use crate::{ | ||||||
|  |     camera::{ActiveCamera2d, Camera}, | ||||||
|  |     render_graph_2::{CommandQueue, Node, SystemNode, ResourceBindings}, | ||||||
|  |     render_resource::{resource_name, BufferInfo, BufferUsage, RenderResourceAssignments}, | ||||||
|  |     renderer_2::{GlobalRenderResourceContext, RenderContext}, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | use bevy_transform::components::LocalToWorld; | ||||||
|  | use legion::prelude::*; | ||||||
|  | use zerocopy::AsBytes; | ||||||
|  | 
 | ||||||
|  | #[derive(Default)] | ||||||
|  | pub struct Camera2dNode { | ||||||
|  |     command_queue: CommandQueue, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl Node for Camera2dNode { | ||||||
|  |     fn update( | ||||||
|  |         &mut self, | ||||||
|  |         _world: &World, | ||||||
|  |         _resources: &Resources, | ||||||
|  |         render_context: &mut dyn RenderContext, | ||||||
|  |         _input: &ResourceBindings, | ||||||
|  |         _output: &mut ResourceBindings, | ||||||
|  |     ) { | ||||||
|  |         self.command_queue.execute(render_context); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl SystemNode for Camera2dNode { | ||||||
|  |     fn get_system(&self, resources: &mut Resources) -> Box<dyn Schedulable> { | ||||||
|  |         let mut camera_buffer = None; | ||||||
|  |         let mut tmp_buffer = None; | ||||||
|  |         let mut window_resized_event_reader = resources.get_event_reader::<WindowResized>(); | ||||||
|  |         let mut command_queue = self.command_queue.clone(); | ||||||
|  |         SystemBuilder::new("camera_resource_provider") | ||||||
|  |             .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>() | ||||||
|  |             .read_resource::<Events<WindowResized>>() | ||||||
|  |             .with_query(<(Read<Camera>, Read<LocalToWorld>, Read<ActiveCamera2d>)>::query()) | ||||||
|  |             .build( | ||||||
|  |                 move |_, | ||||||
|  |                       world, | ||||||
|  |                       ( | ||||||
|  |                     render_resource_context, | ||||||
|  |                     ref mut render_resource_assignments, | ||||||
|  |                     window_resized_events, | ||||||
|  |                 ), | ||||||
|  |                       query| { | ||||||
|  |                     let render_resources = &render_resource_context.context; | ||||||
|  |                     if camera_buffer.is_none() { | ||||||
|  |                         let buffer = render_resources.create_buffer(BufferInfo { | ||||||
|  |                             size: std::mem::size_of::<[[f32; 4]; 4]>(), | ||||||
|  |                             buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM, | ||||||
|  |                             ..Default::default() | ||||||
|  |                         }); | ||||||
|  |                         render_resource_assignments.set(resource_name::uniform::CAMERA2D, buffer); | ||||||
|  |                         camera_buffer = Some(buffer); | ||||||
|  |                     } | ||||||
|  | 
 | ||||||
|  |                     let primary_window_resized_event = window_resized_events | ||||||
|  |                         .find_latest(&mut window_resized_event_reader, |event| event.is_primary); | ||||||
|  |                     if let Some(_) = primary_window_resized_event { | ||||||
|  |                         let matrix_size = std::mem::size_of::<[[f32; 4]; 4]>(); | ||||||
|  |                         for (camera, local_to_world, _) in query.iter(world) { | ||||||
|  |                             let camera_matrix: [[f32; 4]; 4] = | ||||||
|  |                                 (camera.view_matrix * local_to_world.0).to_cols_array_2d(); | ||||||
|  | 
 | ||||||
|  |                             if let Some(old_tmp_buffer) = tmp_buffer { | ||||||
|  |                                 render_resources.remove_buffer(old_tmp_buffer); | ||||||
|  |                             } | ||||||
|  | 
 | ||||||
|  |                             tmp_buffer = Some(render_resources.create_buffer_mapped( | ||||||
|  |                                 BufferInfo { | ||||||
|  |                                     size: matrix_size, | ||||||
|  |                                     buffer_usage: BufferUsage::COPY_SRC, | ||||||
|  |                                     ..Default::default() | ||||||
|  |                                 }, | ||||||
|  |                                 &mut |data, _renderer| { | ||||||
|  |                                     data[0..matrix_size].copy_from_slice(camera_matrix.as_bytes()); | ||||||
|  |                                 }, | ||||||
|  |                             )); | ||||||
|  | 
 | ||||||
|  |                             command_queue.copy_buffer_to_buffer( | ||||||
|  |                                 tmp_buffer.unwrap(), | ||||||
|  |                                 0, | ||||||
|  |                                 camera_buffer.unwrap(), | ||||||
|  |                                 0, | ||||||
|  |                                 matrix_size as u64, | ||||||
|  |                             ); | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 }, | ||||||
|  |             ) | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -1,7 +1,5 @@ | |||||||
| use bevy_window::WindowResized; |  | ||||||
| 
 |  | ||||||
| use crate::{ | use crate::{ | ||||||
|     render_graph_2::{CommandQueue, Node, NodeDescriptor, SystemNode}, |     render_graph_2::{CommandQueue, Node, SystemNode, ResourceBindings}, | ||||||
|     render_resource::{resource_name, BufferInfo, BufferUsage, RenderResourceAssignments}, |     render_resource::{resource_name, BufferInfo, BufferUsage, RenderResourceAssignments}, | ||||||
|     renderer_2::{GlobalRenderResourceContext, RenderContext}, |     renderer_2::{GlobalRenderResourceContext, RenderContext}, | ||||||
|     ActiveCamera, Camera, |     ActiveCamera, Camera, | ||||||
| @ -10,8 +8,8 @@ use crate::{ | |||||||
| use bevy_app::{Events, GetEventReader}; | use bevy_app::{Events, GetEventReader}; | ||||||
| use bevy_transform::prelude::*; | use bevy_transform::prelude::*; | ||||||
| use legion::prelude::*; | use legion::prelude::*; | ||||||
| use once_cell::sync::Lazy; |  | ||||||
| use zerocopy::AsBytes; | use zerocopy::AsBytes; | ||||||
|  | use bevy_window::WindowResized; | ||||||
| 
 | 
 | ||||||
| #[derive(Default)] | #[derive(Default)] | ||||||
| pub struct CameraNode { | pub struct CameraNode { | ||||||
| @ -19,19 +17,13 @@ pub struct CameraNode { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Node for CameraNode { | impl Node for CameraNode { | ||||||
|     fn descriptor(&self) -> &NodeDescriptor { |  | ||||||
|         static DESCRIPTOR: Lazy<NodeDescriptor> = Lazy::new(|| NodeDescriptor { |  | ||||||
|             inputs: Vec::new(), |  | ||||||
|             outputs: Vec::new(), |  | ||||||
|         }); |  | ||||||
|         &DESCRIPTOR |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     fn update( |     fn update( | ||||||
|         &mut self, |         &mut self, | ||||||
|         _world: &World, |         _world: &World, | ||||||
|         _resources: &Resources, |         _resources: &Resources, | ||||||
|         render_context: &mut dyn RenderContext, |         render_context: &mut dyn RenderContext, | ||||||
|  |         _input: &ResourceBindings, | ||||||
|  |         _output: &mut ResourceBindings, | ||||||
|     ) { |     ) { | ||||||
|         self.command_queue.execute(render_context); |         self.command_queue.execute(render_context); | ||||||
|     } |     } | ||||||
| @ -104,4 +96,4 @@ impl SystemNode for CameraNode { | |||||||
|                 }, |                 }, | ||||||
|             ) |             ) | ||||||
|     } |     } | ||||||
| } | } | ||||||
							
								
								
									
										9
									
								
								bevy_render/src/render_graph_2/nodes/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								bevy_render/src/render_graph_2/nodes/mod.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | |||||||
|  | mod camera_node; | ||||||
|  | mod camera2d_node; | ||||||
|  | mod window_texture_node; | ||||||
|  | mod window_swapchain_node; | ||||||
|  | 
 | ||||||
|  | pub use camera_node::*; | ||||||
|  | pub use camera2d_node::*; | ||||||
|  | pub use window_texture_node::*; | ||||||
|  | pub use window_swapchain_node::*; | ||||||
| @ -0,0 +1,70 @@ | |||||||
|  | use crate::{ | ||||||
|  |     render_graph_2::{Node, ResourceBindings, ResourceSlot}, | ||||||
|  |     render_resource::{RenderResource, ResourceInfo}, | ||||||
|  |     renderer_2::RenderContext, | ||||||
|  |     texture::TextureDescriptor, | ||||||
|  | }; | ||||||
|  | use bevy_app::{EventReader, Events}; | ||||||
|  | use bevy_window::{WindowCreated, WindowId, WindowResized, Windows}; | ||||||
|  | use legion::prelude::*; | ||||||
|  | 
 | ||||||
|  | pub struct WindowSwapChainNode { | ||||||
|  |     window_id: WindowId, | ||||||
|  |     use_primary_window: bool, | ||||||
|  |     window_resized_event_reader: EventReader<WindowResized>, | ||||||
|  |     window_created_event_reader: EventReader<WindowCreated>, | ||||||
|  |     swap_chain_resource: Option<RenderResource>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl Node for WindowSwapChainNode { | ||||||
|  |     fn output(&self) -> &[ResourceSlot] { | ||||||
|  |         static OUTPUT: &[ResourceSlot] = &[ResourceSlot::new( | ||||||
|  |             "swapchain_texture", | ||||||
|  |             ResourceInfo::Texture, | ||||||
|  |         )]; | ||||||
|  |         OUTPUT | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn update( | ||||||
|  |         &mut self, | ||||||
|  |         _world: &World, | ||||||
|  |         resources: &Resources, | ||||||
|  |         render_context: &mut dyn RenderContext, | ||||||
|  |         _input: &ResourceBindings, | ||||||
|  |         output: &mut ResourceBindings, | ||||||
|  |     ) { | ||||||
|  |         const WINDOW_TEXTURE: usize = 0; | ||||||
|  |         let window_created_events = resources.get::<Events<WindowCreated>>().unwrap(); | ||||||
|  |         let window_resized_events = resources.get::<Events<WindowResized>>().unwrap(); | ||||||
|  |         let windows = resources.get::<Windows>().unwrap(); | ||||||
|  | 
 | ||||||
|  |         let render_resources = render_context.resources_mut(); | ||||||
|  |         let window = if self.use_primary_window { | ||||||
|  |             windows.get_primary().expect("No primary window exists") | ||||||
|  |         } else { | ||||||
|  |             windows | ||||||
|  |             .get(self.window_id) | ||||||
|  |             .expect("Received window resized event for non-existent window") | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         // create window swapchain
 | ||||||
|  |         if let Some(_) = window_created_events | ||||||
|  |             .find_latest(&mut self.window_created_event_reader, |e| { | ||||||
|  |                 e.id == window.id | ||||||
|  |             }) | ||||||
|  |         { | ||||||
|  |             render_resources.create_swap_chain(window); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // resize window swapchain
 | ||||||
|  |         if let Some(_) = window_resized_events | ||||||
|  |             .find_latest(&mut self.window_resized_event_reader, |e| { | ||||||
|  |                 e.id == window.id | ||||||
|  |             }) | ||||||
|  |         { | ||||||
|  |             render_resources.create_swap_chain(window); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         output.set(WINDOW_TEXTURE, self.swap_chain_resource.unwrap()); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										45
									
								
								bevy_render/src/render_graph_2/nodes/window_texture_node.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								bevy_render/src/render_graph_2/nodes/window_texture_node.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,45 @@ | |||||||
|  | use crate::{ | ||||||
|  |     render_graph_2::{Node, ResourceBindings, ResourceSlot}, | ||||||
|  |     render_resource::ResourceInfo, | ||||||
|  |     renderer_2::RenderContext, | ||||||
|  |     texture::TextureDescriptor, | ||||||
|  | }; | ||||||
|  | use bevy_app::{EventReader, Events}; | ||||||
|  | use bevy_window::WindowResized; | ||||||
|  | use legion::prelude::*; | ||||||
|  | 
 | ||||||
|  | pub struct WindowTextureNode { | ||||||
|  |     pub descriptor: TextureDescriptor, | ||||||
|  |     window_resized_event_reader: EventReader<WindowResized>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl Node for WindowTextureNode { | ||||||
|  |     fn output(&self) -> &[ResourceSlot] { | ||||||
|  |         static OUTPUT: &[ResourceSlot] = | ||||||
|  |             &[ResourceSlot::new("window_texture", ResourceInfo::Texture)]; | ||||||
|  |         OUTPUT | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn update( | ||||||
|  |         &mut self, | ||||||
|  |         _world: &World, | ||||||
|  |         resources: &Resources, | ||||||
|  |         render_context: &mut dyn RenderContext, | ||||||
|  |         _input: &ResourceBindings, | ||||||
|  |         output: &mut ResourceBindings, | ||||||
|  |     ) { | ||||||
|  |         const WINDOW_TEXTURE: usize = 0; | ||||||
|  |         let window_resized_events = resources.get::<Events<WindowResized>>().unwrap(); | ||||||
|  |         if let Some(event) = window_resized_events.latest(&mut self.window_resized_event_reader) { | ||||||
|  |             let render_resources = render_context.resources_mut(); | ||||||
|  |             if let Some(old_texture) = output.get(WINDOW_TEXTURE) { | ||||||
|  |                 render_resources.remove_texture(old_texture); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             self.descriptor.size.width = event.width; | ||||||
|  |             self.descriptor.size.height = event.height; | ||||||
|  |             let texture_resource = render_resources.create_texture(&self.descriptor); | ||||||
|  |             output.set(WINDOW_TEXTURE, texture_resource); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -1,91 +0,0 @@ | |||||||
| use bevy_app::{EventReader, Events}; |  | ||||||
| use bevy_window::WindowResized; |  | ||||||
| 
 |  | ||||||
| use crate::{ |  | ||||||
|     camera::{ActiveCamera2d, Camera}, |  | ||||||
|     render_resource::{ |  | ||||||
|         resource_name, BufferInfo, BufferUsage, RenderResource, RenderResourceAssignments, |  | ||||||
|         ResourceProvider, |  | ||||||
|     }, |  | ||||||
|     renderer_2::RenderContext, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| use legion::prelude::*; |  | ||||||
| use zerocopy::AsBytes; |  | ||||||
| 
 |  | ||||||
| pub struct Camera2dResourceProvider { |  | ||||||
|     pub camera_buffer: Option<RenderResource>, |  | ||||||
|     pub tmp_buffer: Option<RenderResource>, |  | ||||||
|     pub window_resized_event_reader: EventReader<WindowResized>, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl Camera2dResourceProvider { |  | ||||||
|     pub fn new(window_resized_event_reader: EventReader<WindowResized>) -> Self { |  | ||||||
|         Camera2dResourceProvider { |  | ||||||
|             camera_buffer: None, |  | ||||||
|             tmp_buffer: None, |  | ||||||
|             window_resized_event_reader, |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl ResourceProvider for Camera2dResourceProvider { |  | ||||||
|     fn initialize( |  | ||||||
|         &mut self, |  | ||||||
|         render_context: &mut dyn RenderContext, |  | ||||||
|         _world: &mut World, |  | ||||||
|         resources: &Resources, |  | ||||||
|     ) { |  | ||||||
|         let buffer = render_context.resources_mut().create_buffer(BufferInfo { |  | ||||||
|             size: std::mem::size_of::<[[f32; 4]; 4]>(), |  | ||||||
|             buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM, |  | ||||||
|             ..Default::default() |  | ||||||
|         }); |  | ||||||
| 
 |  | ||||||
|         let mut render_resource_assignments = |  | ||||||
|             resources.get_mut::<RenderResourceAssignments>().unwrap(); |  | ||||||
|         render_resource_assignments.set(resource_name::uniform::CAMERA2D, buffer); |  | ||||||
|         self.camera_buffer = Some(buffer); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     fn update( |  | ||||||
|         &mut self, |  | ||||||
|         render_context: &mut dyn RenderContext, |  | ||||||
|         world: &World, |  | ||||||
|         resources: &Resources, |  | ||||||
|     ) { |  | ||||||
|         let window_resized_events = resources.get::<Events<WindowResized>>().unwrap(); |  | ||||||
|         let primary_window_resized_event = window_resized_events |  | ||||||
|             .find_latest(&mut self.window_resized_event_reader, |event| event.is_primary); |  | ||||||
| 
 |  | ||||||
|         if let Some(_) = primary_window_resized_event { |  | ||||||
|             let matrix_size = std::mem::size_of::<[[f32; 4]; 4]>(); |  | ||||||
|             for (camera, _) in <(Read<Camera>, Read<ActiveCamera2d>)>::query().iter(world) { |  | ||||||
|                 let camera_matrix: [[f32; 4]; 4] = camera.view_matrix.to_cols_array_2d(); |  | ||||||
| 
 |  | ||||||
|                 if let Some(old_tmp_buffer) = self.tmp_buffer { |  | ||||||
|                     render_context.resources_mut().remove_buffer(old_tmp_buffer); |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 self.tmp_buffer = Some(render_context.resources_mut().create_buffer_mapped( |  | ||||||
|                     BufferInfo { |  | ||||||
|                         size: matrix_size, |  | ||||||
|                         buffer_usage: BufferUsage::COPY_SRC, |  | ||||||
|                         ..Default::default() |  | ||||||
|                     }, |  | ||||||
|                     &mut |data, _renderer| { |  | ||||||
|                         data[0..matrix_size].copy_from_slice(camera_matrix.as_bytes()); |  | ||||||
|                     }, |  | ||||||
|                 )); |  | ||||||
| 
 |  | ||||||
|                 render_context.copy_buffer_to_buffer( |  | ||||||
|                     self.tmp_buffer.unwrap(), |  | ||||||
|                     0, |  | ||||||
|                     self.camera_buffer.unwrap(), |  | ||||||
|                     0, |  | ||||||
|                     matrix_size as u64, |  | ||||||
|                 ); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,11 +1,50 @@ | |||||||
| use crate::{ | use crate::{ | ||||||
|     render_resource::{RenderResourceAssignments, ResourceProvider}, |     render_graph_2::{Node, ResourceBindings, ResourceSlot}, | ||||||
|  |     render_resource::{RenderResourceAssignments, ResourceInfo, ResourceProvider}, | ||||||
|     renderer_2::RenderContext, |     renderer_2::RenderContext, | ||||||
|     texture::TextureDescriptor, |     texture::TextureDescriptor, | ||||||
| }; | }; | ||||||
| use bevy_window::Windows; | use bevy_app::{EventReader, Events}; | ||||||
|  | use bevy_window::{WindowResized, Windows}; | ||||||
| use legion::prelude::*; | use legion::prelude::*; | ||||||
| 
 | 
 | ||||||
|  | pub struct WindowTextureNode { | ||||||
|  |     pub name: String, | ||||||
|  |     pub descriptor: TextureDescriptor, | ||||||
|  |     pub window_resized_event_reader: EventReader<WindowResized>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl Node for WindowTextureNode { | ||||||
|  |     fn output(&self) -> &[ResourceSlot] { | ||||||
|  |         static OUTPUT: &[ResourceSlot] = | ||||||
|  |             &[ResourceSlot::new("window_texture", ResourceInfo::Texture)]; | ||||||
|  |         OUTPUT | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn update( | ||||||
|  |         &mut self, | ||||||
|  |         _world: &World, | ||||||
|  |         resources: &Resources, | ||||||
|  |         render_context: &mut dyn RenderContext, | ||||||
|  |         _input: &ResourceBindings, | ||||||
|  |         output: &mut ResourceBindings, | ||||||
|  |     ) { | ||||||
|  |         const WINDOW_TEXTURE: usize = 0; | ||||||
|  |         let window_resized_events = resources.get::<Events<WindowResized>>().unwrap(); | ||||||
|  |         if let Some(event) = window_resized_events.latest(&mut self.window_resized_event_reader) { | ||||||
|  |             let render_resources = render_context.resources_mut(); | ||||||
|  |             if let Some(old_texture) = output.get(WINDOW_TEXTURE) { | ||||||
|  |                 render_resources.remove_texture(old_texture); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             self.descriptor.size.width = event.width; | ||||||
|  |             self.descriptor.size.height = event.height; | ||||||
|  |             let texture_resource = render_resources.create_texture(&self.descriptor); | ||||||
|  |             output.set(WINDOW_TEXTURE, texture_resource); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| pub struct FrameTextureResourceProvider { | pub struct FrameTextureResourceProvider { | ||||||
|     pub name: String, |     pub name: String, | ||||||
|     pub descriptor: TextureDescriptor, |     pub descriptor: TextureDescriptor, | ||||||
|  | |||||||
| @ -1,12 +1,8 @@ | |||||||
| mod camera2d_resource_provider; |  | ||||||
| mod camera_resource_provider; |  | ||||||
| mod frame_texture_resource_provider; | mod frame_texture_resource_provider; | ||||||
| mod light_resource_provider; | mod light_resource_provider; | ||||||
| mod mesh_resource_provider; | mod mesh_resource_provider; | ||||||
| mod uniform_resource_provider; | mod uniform_resource_provider; | ||||||
| 
 | 
 | ||||||
| pub use camera2d_resource_provider::*; |  | ||||||
| pub use camera_resource_provider::*; |  | ||||||
| pub use frame_texture_resource_provider::*; | pub use frame_texture_resource_provider::*; | ||||||
| pub use light_resource_provider::*; | pub use light_resource_provider::*; | ||||||
| pub use mesh_resource_provider::*; | pub use mesh_resource_provider::*; | ||||||
|  | |||||||
| @ -1,46 +1,46 @@ | |||||||
| #![feature(test)] | // #![feature(test)]
 | ||||||
| 
 | 
 | ||||||
| extern crate test; | // extern crate test;
 | ||||||
| 
 | 
 | ||||||
| use legion::prelude::*; | // use legion::prelude::*;
 | ||||||
| use legion_transform::{local_to_world_system, prelude::*}; | // use bevy_transform::{local_to_world_system, prelude::*};
 | ||||||
| use test::Bencher; | // use test::Bencher;
 | ||||||
| 
 | 
 | ||||||
| #[bench] | // #[bench]
 | ||||||
| fn local_to_world_update_without_change(b: &mut Bencher) { | // fn local_to_world_update_without_change(b: &mut Bencher) {
 | ||||||
|     let _ = env_logger::builder().is_test(true).try_init(); | //     let _ = env_logger::builder().is_test(true).try_init();
 | ||||||
| 
 | 
 | ||||||
|     let mut world = Universe::new().create_world(); | //     let mut world = Universe::new().create_world();
 | ||||||
|     let system = local_to_world_system::build(&mut world); | //     let system = local_to_world_system::build(&mut world);
 | ||||||
| 
 | 
 | ||||||
|     let ltw = LocalToWorld::identity(); | //     let ltw = LocalToWorld::identity();
 | ||||||
|     let t = Translation::new(1.0, 2.0, 3.0); | //     let t = Translation::new(1.0, 2.0, 3.0);
 | ||||||
|     let r = Rotation::from_euler_angles(1.0, 2.0, 3.0); | //     let r = Rotation::from_euler_angles(1.0, 2.0, 3.0);
 | ||||||
|     let s = Scale(2.0); | //     let s = Scale(2.0);
 | ||||||
|     let nus = NonUniformScale::new(1.0, 2.0, 3.0); | //     let nus = NonUniformScale::new(1.0, 2.0, 3.0);
 | ||||||
| 
 | 
 | ||||||
|     // Add N of every combination of transform types.
 | //     // Add N of every combination of transform types.
 | ||||||
|     let n = 1000; | //     let n = 1000;
 | ||||||
|     let _translation = *world.insert((), vec![(ltw, t); n]).first().unwrap(); | //     let _translation = *world.insert((), vec![(ltw, t); n]).first().unwrap();
 | ||||||
|     let _rotation = *world.insert((), vec![(ltw, r); n]).first().unwrap(); | //     let _rotation = *world.insert((), vec![(ltw, r); n]).first().unwrap();
 | ||||||
|     let _scale = *world.insert((), vec![(ltw, s); n]).first().unwrap(); | //     let _scale = *world.insert((), vec![(ltw, s); n]).first().unwrap();
 | ||||||
|     let _non_uniform_scale = *world.insert((), vec![(ltw, nus); n]).first().unwrap(); | //     let _non_uniform_scale = *world.insert((), vec![(ltw, nus); n]).first().unwrap();
 | ||||||
|     let _translation_and_rotation = *world.insert((), vec![(ltw, t, r); n]).first().unwrap(); | //     let _translation_and_rotation = *world.insert((), vec![(ltw, t, r); n]).first().unwrap();
 | ||||||
|     let _translation_and_scale = *world.insert((), vec![(ltw, t, s); n]).first().unwrap(); | //     let _translation_and_scale = *world.insert((), vec![(ltw, t, s); n]).first().unwrap();
 | ||||||
|     let _translation_and_nus = *world.insert((), vec![(ltw, t, nus); n]).first().unwrap(); | //     let _translation_and_nus = *world.insert((), vec![(ltw, t, nus); n]).first().unwrap();
 | ||||||
|     let _rotation_scale = *world.insert((), vec![(ltw, r, s); n]).first().unwrap(); | //     let _rotation_scale = *world.insert((), vec![(ltw, r, s); n]).first().unwrap();
 | ||||||
|     let _rotation_nus = *world.insert((), vec![(ltw, r, nus); n]).first().unwrap(); | //     let _rotation_nus = *world.insert((), vec![(ltw, r, nus); n]).first().unwrap();
 | ||||||
|     let _translation_rotation_scale = *world.insert((), vec![(ltw, t, r, s); n]).first().unwrap(); | //     let _translation_rotation_scale = *world.insert((), vec![(ltw, t, r, s); n]).first().unwrap();
 | ||||||
|     let _translation_rotation_nus = *world.insert((), vec![(ltw, t, r, nus); n]).first().unwrap(); | //     let _translation_rotation_nus = *world.insert((), vec![(ltw, t, r, nus); n]).first().unwrap();
 | ||||||
| 
 | 
 | ||||||
|     // Run the system once outside the test (which should compute everything and it shouldn't be
 | //     // Run the system once outside the test (which should compute everything and it shouldn't be
 | ||||||
|     // touched again).
 | //     // touched again).
 | ||||||
|     system.run(&mut world); | //     system.run(&mut world);
 | ||||||
|     system.command_buffer_mut().write(&mut world); | //     system.command_buffer_mut().write(&mut world);
 | ||||||
| 
 | 
 | ||||||
|     // Then time the already-computed updates.
 | //     // Then time the already-computed updates.
 | ||||||
|     b.iter(|| { | //     b.iter(|| {
 | ||||||
|         system.run(&mut world); | //         system.run(&mut world);
 | ||||||
|         system.command_buffer_mut().write(&mut world); | //         system.command_buffer_mut().write(&mut world);
 | ||||||
|     }); | //     });
 | ||||||
| } | // }
 | ||||||
|  | |||||||
| @ -6,7 +6,7 @@ use bevy_asset::AssetStorage; | |||||||
| use bevy_render::{ | use bevy_render::{ | ||||||
|     pipeline::{update_shader_assignments, PipelineCompiler, PipelineDescriptor}, |     pipeline::{update_shader_assignments, PipelineCompiler, PipelineDescriptor}, | ||||||
|     render_graph::RenderGraph, |     render_graph::RenderGraph, | ||||||
|     render_graph_2::RenderGraph2, |     render_graph_2::{LinearScheduler, RenderGraph2, RenderGraphScheduler}, | ||||||
|     render_resource::RenderResourceAssignments, |     render_resource::RenderResourceAssignments, | ||||||
|     renderer_2::{GlobalRenderResourceContext, RenderContext, RenderResourceContext}, |     renderer_2::{GlobalRenderResourceContext, RenderContext, RenderResourceContext}, | ||||||
| }; | }; | ||||||
| @ -245,10 +245,15 @@ impl WgpuRenderer { | |||||||
|             .context |             .context | ||||||
|             .downcast_mut::<WgpuRenderResourceContext>() |             .downcast_mut::<WgpuRenderResourceContext>() | ||||||
|             .unwrap(); |             .unwrap(); | ||||||
|  |         let mut linear_scheduler = LinearScheduler::default(); | ||||||
|         let mut render_context = |         let mut render_context = | ||||||
|             WgpuRenderContext::new(self.device.clone(), render_resource_context.clone()); |             WgpuRenderContext::new(self.device.clone(), render_resource_context.clone()); | ||||||
|         for node in render_graph.get_schedule() { |         for mut stage in linear_scheduler.get_stages(&mut render_graph) { | ||||||
|             node.update(world, resources, &mut render_context); |             for job in stage.iter_mut() { | ||||||
|  |                 for node_state in job.iter_mut() { | ||||||
|  |                     node_state.node.update(world, resources, &mut render_context, &node_state.input, &mut node_state.output); | ||||||
|  |                 } 
 | ||||||
|  |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         let command_buffer = render_context.finish(); |         let command_buffer = render_context.finish(); | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Carter Anderson
						Carter Anderson