RenderGraph2: Finish graph executor, fix window textures
This commit is contained in:
		
							parent
							
								
									8326a1a3c2
								
							
						
					
					
						commit
						5780bf4025
					
				| @ -50,14 +50,15 @@ use self::{ | ||||
| use bevy_app::{stage, AppBuilder, AppPlugin, GetEventReader}; | ||||
| use bevy_asset::AssetStorage; | ||||
| use bevy_transform::prelude::LocalToWorld; | ||||
| use bevy_window::{WindowCreated, WindowResized}; | ||||
| use bevy_window::{WindowCreated, WindowReference, WindowResized}; | ||||
| use pass::PassDescriptor; | ||||
| use pipeline::pipelines::build_forward_pipeline; | ||||
| use render_graph_2::{ | ||||
|     nodes::{Camera2dNode, CameraNode, PassNode, SwapChainWindowSource, WindowSwapChainNode}, | ||||
|     nodes::{Camera2dNode, CameraNode, PassNode, WindowSwapChainNode, WindowTextureNode}, | ||||
|     RenderGraph2, | ||||
| }; | ||||
| use render_resource::resource_providers::mesh_resource_provider_system; | ||||
| use texture::{Extent3d, TextureDescriptor, TextureDimension, TextureFormat, TextureUsage}; | ||||
| 
 | ||||
| pub static RENDER_RESOURCE_STAGE: &str = "render_resource"; | ||||
| pub static RENDER_STAGE: &str = "render"; | ||||
| @ -126,7 +127,28 @@ impl AppPlugin for RenderPlugin { | ||||
|             render_graph.add_node_named( | ||||
|                 "swapchain", | ||||
|                 WindowSwapChainNode::new( | ||||
|                     SwapChainWindowSource::Primary, | ||||
|                     WindowReference::Primary, | ||||
|                     resources.get_event_reader::<WindowCreated>(), | ||||
|                     resources.get_event_reader::<WindowResized>(), | ||||
|                 ), | ||||
|             ); | ||||
|             render_graph.add_node_named( | ||||
|                 "main_pass_depth_texture", | ||||
|                 WindowTextureNode::new( | ||||
|                     WindowReference::Primary, | ||||
|                     TextureDescriptor { | ||||
|                         size: Extent3d { | ||||
|                             depth: 1, | ||||
|                             width: 1, | ||||
|                             height: 1, | ||||
|                         }, | ||||
|                         array_layer_count: 1, | ||||
|                         mip_level_count: 1, | ||||
|                         sample_count: 1, | ||||
|                         dimension: TextureDimension::D2, | ||||
|                         format: TextureFormat::Depth32Float, // PERF: vulkan recommends using 24 bit depth for better performance
 | ||||
|                         usage: TextureUsage::OUTPUT_ATTACHMENT, | ||||
|                     }, | ||||
|                     resources.get_event_reader::<WindowCreated>(), | ||||
|                     resources.get_event_reader::<WindowResized>(), | ||||
|                 ), | ||||
| @ -164,7 +186,20 @@ impl AppPlugin for RenderPlugin { | ||||
|             render_graph.add_node_edge("camera", "main_pass").unwrap(); | ||||
|             render_graph.add_node_edge("camera2d", "main_pass").unwrap(); | ||||
|             render_graph | ||||
|                 .add_slot_edge("swapchain", WindowSwapChainNode::OUT_TEXTURE, "main_pass", "color") | ||||
|                 .add_slot_edge( | ||||
|                     "swapchain", | ||||
|                     WindowSwapChainNode::OUT_TEXTURE, | ||||
|                     "main_pass", | ||||
|                     "color", | ||||
|                 ) | ||||
|                 .unwrap(); | ||||
|             render_graph | ||||
|                 .add_slot_edge( | ||||
|                     "main_pass_depth_texture", | ||||
|                     WindowTextureNode::OUT_TEXTURE, | ||||
|                     "main_pass", | ||||
|                     "depth", | ||||
|                 ) | ||||
|                 .unwrap(); | ||||
|         } | ||||
|         app.add_resource(render_graph); | ||||
|  | ||||
| @ -131,10 +131,10 @@ impl RenderGraph2 { | ||||
| 
 | ||||
|         { | ||||
|             let output_node = self.get_node_state_mut(output_node_id)?; | ||||
|             output_node.add_output_edge(edge.clone())?; | ||||
|             output_node.edges.add_output_edge(edge.clone())?; | ||||
|         } | ||||
|         let input_node = self.get_node_state_mut(input_node_id)?; | ||||
|         input_node.add_input_edge(edge)?; | ||||
|         input_node.edges.add_input_edge(edge)?; | ||||
| 
 | ||||
|         Ok(()) | ||||
|     } | ||||
| @ -156,10 +156,10 @@ impl RenderGraph2 { | ||||
| 
 | ||||
|         { | ||||
|             let output_node = self.get_node_state_mut(output_node_id)?; | ||||
|             output_node.add_output_edge(edge.clone())?; | ||||
|             output_node.edges.add_output_edge(edge.clone())?; | ||||
|         } | ||||
|         let input_node = self.get_node_state_mut(input_node_id)?; | ||||
|         input_node.add_input_edge(edge)?; | ||||
|         input_node.edges.add_input_edge(edge)?; | ||||
| 
 | ||||
|         Ok(()) | ||||
|     } | ||||
| @ -185,7 +185,7 @@ impl RenderGraph2 { | ||||
|                 if let Some(Edge::SlotEdge { | ||||
|                     output_node: current_output_node, | ||||
|                     .. | ||||
|                 }) = input_node_state.input_edges.iter().find(|e| { | ||||
|                 }) = input_node_state.edges.input_edges.iter().find(|e| { | ||||
|                     if let Edge::SlotEdge { | ||||
|                         input_index: current_input_index, | ||||
|                         .. | ||||
| @ -222,9 +222,9 @@ impl RenderGraph2 { | ||||
|         let output_node_state = self.get_node_state(edge.get_output_node()); | ||||
|         let input_node_state = self.get_node_state(edge.get_input_node()); | ||||
|         if let Ok(output_node_state) = output_node_state { | ||||
|             if output_node_state.output_edges.contains(edge) { | ||||
|             if output_node_state.edges.output_edges.contains(edge) { | ||||
|                 if let Ok(input_node_state) = input_node_state { | ||||
|                     if input_node_state.input_edges.contains(edge) { | ||||
|                     if input_node_state.edges.input_edges.contains(edge) { | ||||
|                         return true; | ||||
|                     } | ||||
|                 } | ||||
| @ -270,6 +270,7 @@ impl RenderGraph2 { | ||||
|     ) -> Result<impl Iterator<Item = (&Edge, &NodeState)>, RenderGraphError> { | ||||
|         let node = self.get_node_state(label)?; | ||||
|         Ok(node | ||||
|             .edges | ||||
|             .input_edges | ||||
|             .iter() | ||||
|             .map(|edge| (edge, edge.get_output_node())) | ||||
| @ -284,6 +285,7 @@ impl RenderGraph2 { | ||||
|     ) -> Result<impl Iterator<Item = (&Edge, &NodeState)>, RenderGraphError> { | ||||
|         let node = self.get_node_state(label)?; | ||||
|         Ok(node | ||||
|             .edges | ||||
|             .output_edges | ||||
|             .iter() | ||||
|             .map(|edge| (edge, edge.get_input_node())) | ||||
|  | ||||
| @ -39,56 +39,13 @@ pub trait SystemNode: Node { | ||||
|     fn get_system(&self, resources: &mut Resources) -> Box<dyn Schedulable>; | ||||
| } | ||||
| 
 | ||||
| pub struct NodeState { | ||||
| pub struct Edges { | ||||
|     pub id: NodeId, | ||||
|     pub name: Option<Cow<'static, str>>, | ||||
|     pub node: Box<dyn Node>, | ||||
|     pub input_slots: ResourceSlots, | ||||
|     pub output_slots: ResourceSlots, | ||||
|     pub input_edges: Vec<Edge>, | ||||
|     pub output_edges: Vec<Edge>, | ||||
| } | ||||
| 
 | ||||
| impl Debug for NodeState { | ||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||
|         writeln!(f, "{:?} ({:?})", self.id, self.name) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl NodeState { | ||||
|     pub fn new<T>(id: NodeId, node: T) -> Self | ||||
|     where | ||||
|         T: Node, | ||||
|     { | ||||
|         NodeState { | ||||
|             id, | ||||
|             name: None, | ||||
|             input_slots: ResourceSlots::from(node.input()), | ||||
|             output_slots: ResourceSlots::from(node.output()), | ||||
|             node: Box::new(node), | ||||
|             input_edges: Vec::new(), | ||||
|             output_edges: Vec::new(), | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn node<T>(&self) -> Result<&T, RenderGraphError> | ||||
|     where | ||||
|         T: Node, | ||||
|     { | ||||
|         self.node | ||||
|             .downcast_ref::<T>() | ||||
|             .ok_or_else(|| RenderGraphError::WrongNodeType) | ||||
|     } | ||||
| 
 | ||||
|     pub fn node_mut<T>(&mut self) -> Result<&mut T, RenderGraphError> | ||||
|     where | ||||
|         T: Node, | ||||
|     { | ||||
|         self.node | ||||
|             .downcast_mut::<T>() | ||||
|             .ok_or_else(|| RenderGraphError::WrongNodeType) | ||||
|     } | ||||
| 
 | ||||
| impl Edges { | ||||
|     pub(crate) fn add_input_edge(&mut self, edge: Edge) -> Result<(), RenderGraphError> { | ||||
|         if self.has_input_edge(&edge) { | ||||
|             return Err(RenderGraphError::EdgeAlreadyExists(edge.clone())); | ||||
| @ -144,10 +101,64 @@ impl NodeState { | ||||
|                 node: self.id, | ||||
|             }) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| pub struct NodeState { | ||||
|     pub id: NodeId, | ||||
|     pub name: Option<Cow<'static, str>>, | ||||
|     pub node: Box<dyn Node>, | ||||
|     pub input_slots: ResourceSlots, | ||||
|     pub output_slots: ResourceSlots, | ||||
|     pub edges: Edges, | ||||
| } | ||||
| 
 | ||||
| impl Debug for NodeState { | ||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||
|         writeln!(f, "{:?} ({:?})", self.id, self.name) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl NodeState { | ||||
|     pub fn new<T>(id: NodeId, node: T) -> Self | ||||
|     where | ||||
|         T: Node, | ||||
|     { | ||||
|         NodeState { | ||||
|             id, | ||||
|             name: None, | ||||
|             input_slots: ResourceSlots::from(node.input()), | ||||
|             output_slots: ResourceSlots::from(node.output()), | ||||
|             node: Box::new(node), | ||||
|             edges: Edges { | ||||
|                 id, | ||||
|                 input_edges: Vec::new(), | ||||
|                 output_edges: Vec::new(), | ||||
|             }, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn node<T>(&self) -> Result<&T, RenderGraphError> | ||||
|     where | ||||
|         T: Node, | ||||
|     { | ||||
|         self.node | ||||
|             .downcast_ref::<T>() | ||||
|             .ok_or_else(|| RenderGraphError::WrongNodeType) | ||||
|     } | ||||
| 
 | ||||
|     pub fn node_mut<T>(&mut self) -> Result<&mut T, RenderGraphError> | ||||
|     where | ||||
|         T: Node, | ||||
|     { | ||||
|         self.node | ||||
|             .downcast_mut::<T>() | ||||
|             .ok_or_else(|| RenderGraphError::WrongNodeType) | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     pub fn validate_output_slots(&self) -> Result<(), RenderGraphError> { | ||||
|         for i in 0..self.output_slots.len() { | ||||
|             self.get_output_slot_edge(i)?; | ||||
|             self.edges.get_output_slot_edge(i)?; | ||||
|         } | ||||
| 
 | ||||
|         Ok(()) | ||||
| @ -155,7 +166,7 @@ impl NodeState { | ||||
| 
 | ||||
|     pub fn validate_input_slots(&self) -> Result<(), RenderGraphError> { | ||||
|         for i in 0..self.input_slots.len() { | ||||
|             self.get_input_slot_edge(i)?; | ||||
|             self.edges.get_input_slot_edge(i)?; | ||||
|         } | ||||
| 
 | ||||
|         Ok(()) | ||||
|  | ||||
| @ -2,13 +2,13 @@ use super::RenderGraphError; | ||||
| use crate::render_resource::{RenderResource, ResourceInfo}; | ||||
| use std::borrow::Cow; | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| #[derive(Debug, Clone)] | ||||
| pub struct ResourceSlot { | ||||
|     pub resource: Option<RenderResource>, | ||||
|     pub info: ResourceSlotInfo, | ||||
| } | ||||
| 
 | ||||
| #[derive(Default, Debug)] | ||||
| #[derive(Default, Debug, Clone)] | ||||
| pub struct ResourceSlots { | ||||
|     slots: Vec<ResourceSlot>, | ||||
| } | ||||
| @ -93,6 +93,10 @@ impl ResourceSlots { | ||||
|         self.slots.iter() | ||||
|     } | ||||
| 
 | ||||
|     pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut ResourceSlot> { | ||||
|         self.slots.iter_mut() | ||||
|     } | ||||
| 
 | ||||
|     pub fn len(&self) -> usize { | ||||
|         self.slots.len() | ||||
|     } | ||||
|  | ||||
| @ -23,7 +23,7 @@ impl PassNode { | ||||
|         for color_attachment in descriptor.color_attachments.iter() { | ||||
|             if let TextureAttachment::Input(ref name) = color_attachment.attachment { | ||||
|                 inputs.push(ResourceSlotInfo::new(name.to_string(), ResourceInfo::Texture)); | ||||
|                 color_attachment_input_indices.push(Some(inputs.len())); | ||||
|                 color_attachment_input_indices.push(Some(inputs.len() - 1)); | ||||
|             } else { | ||||
|                 color_attachment_input_indices.push(None); | ||||
|             } | ||||
| @ -33,7 +33,7 @@ impl PassNode { | ||||
|         if let Some(ref depth_stencil_attachment)= descriptor.depth_stencil_attachment { | ||||
|             if let TextureAttachment::Input(ref name) = depth_stencil_attachment.attachment { | ||||
|                 inputs.push(ResourceSlotInfo::new(name.to_string(), ResourceInfo::Texture)); | ||||
|                 depth_stencil_attachment_input_index = Some(inputs.len()); | ||||
|                 depth_stencil_attachment_input_index = Some(inputs.len() - 1); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|  | ||||
| @ -4,23 +4,12 @@ use crate::{ | ||||
|     renderer_2::RenderContext, | ||||
| }; | ||||
| use bevy_app::{EventReader, Events}; | ||||
| use bevy_window::{WindowCreated, WindowId, WindowResized, Windows}; | ||||
| use bevy_window::{WindowCreated, WindowResized, Windows, WindowReference}; | ||||
| use legion::prelude::*; | ||||
| use std::borrow::Cow; | ||||
| 
 | ||||
| pub enum SwapChainWindowSource { | ||||
|     Primary, | ||||
|     Id(WindowId), | ||||
| } | ||||
| 
 | ||||
| impl Default for SwapChainWindowSource { | ||||
|     fn default() -> Self { | ||||
|         SwapChainWindowSource::Primary | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| pub struct WindowSwapChainNode { | ||||
|     source_window: SwapChainWindowSource, | ||||
|     window_reference: WindowReference, | ||||
|     window_created_event_reader: EventReader<WindowCreated>, | ||||
|     window_resized_event_reader: EventReader<WindowResized>, | ||||
| } | ||||
| @ -28,12 +17,12 @@ pub struct WindowSwapChainNode { | ||||
| impl WindowSwapChainNode { | ||||
|     pub const OUT_TEXTURE: &'static str = "texture"; | ||||
|     pub fn new( | ||||
|         source_window: SwapChainWindowSource, | ||||
|         window_reference: WindowReference, | ||||
|         window_created_event_reader: EventReader<WindowCreated>, | ||||
|         window_resized_event_reader: EventReader<WindowResized>, | ||||
|     ) -> Self { | ||||
|         WindowSwapChainNode { | ||||
|             source_window, | ||||
|             window_reference, | ||||
|             window_created_event_reader, | ||||
|             window_resized_event_reader, | ||||
|         } | ||||
| @ -62,26 +51,22 @@ impl Node for WindowSwapChainNode { | ||||
|         let window_resized_events = resources.get::<Events<WindowResized>>().unwrap(); | ||||
|         let windows = resources.get::<Windows>().unwrap(); | ||||
| 
 | ||||
|         let render_resources = render_context.resources_mut(); | ||||
|         let window = match self.source_window { | ||||
|             SwapChainWindowSource::Primary => { | ||||
|         let window = match self.window_reference { | ||||
|             WindowReference::Primary => { | ||||
|                 windows.get_primary().expect("No primary window exists") | ||||
|             } | ||||
|             SwapChainWindowSource::Id(id) => windows | ||||
|             WindowReference::Id(id) => windows | ||||
|                 .get(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); | ||||
|         } | ||||
|         let render_resources = render_context.resources_mut(); | ||||
| 
 | ||||
|         // resize window swapchain
 | ||||
|         if let Some(_) = window_resized_events | ||||
|             .find_latest(&mut self.window_resized_event_reader, |e| e.id == window.id) | ||||
|         // create window swapchain when window is resized or created
 | ||||
|         if window_created_events | ||||
|             .find_latest(&mut self.window_created_event_reader, |e| e.id == window.id).is_some() || | ||||
|             window_resized_events | ||||
|             .find_latest(&mut self.window_resized_event_reader, |e| e.id == window.id).is_some() | ||||
|         { | ||||
|             render_resources.create_swap_chain(window); | ||||
|         } | ||||
|  | ||||
| @ -1,23 +1,42 @@ | ||||
| use crate::{ | ||||
|     render_graph_2::{Node, ResourceSlots, ResourceSlotInfo}, | ||||
|     render_graph_2::{Node, ResourceSlotInfo, ResourceSlots}, | ||||
|     render_resource::ResourceInfo, | ||||
|     renderer_2::RenderContext, | ||||
|     texture::TextureDescriptor, | ||||
| }; | ||||
| use bevy_app::{EventReader, Events}; | ||||
| use bevy_window::WindowResized; | ||||
| use bevy_window::{WindowCreated, WindowReference, WindowResized, Windows}; | ||||
| use legion::prelude::*; | ||||
| use std::borrow::Cow; | ||||
| 
 | ||||
| pub struct WindowTextureNode { | ||||
|     pub descriptor: TextureDescriptor, | ||||
|     window_reference: WindowReference, | ||||
|     descriptor: TextureDescriptor, | ||||
|     window_created_event_reader: EventReader<WindowCreated>, | ||||
|     window_resized_event_reader: EventReader<WindowResized>, | ||||
| } | ||||
| 
 | ||||
| impl WindowTextureNode { | ||||
|     pub const OUT_TEXTURE: &'static str = "texture"; | ||||
|     pub fn new( | ||||
|         window_reference: WindowReference, | ||||
|         descriptor: TextureDescriptor, | ||||
|         window_created_event_reader: EventReader<WindowCreated>, | ||||
|         window_resized_event_reader: EventReader<WindowResized>, | ||||
|     ) -> Self { | ||||
|         WindowTextureNode { | ||||
|             window_reference, | ||||
|             descriptor, | ||||
|             window_created_event_reader, | ||||
|             window_resized_event_reader, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Node for WindowTextureNode { | ||||
|     fn output(&self) -> &[ResourceSlotInfo] { | ||||
|         static OUTPUT: &[ResourceSlotInfo] = &[ResourceSlotInfo { | ||||
|             name: Cow::Borrowed("texture"), | ||||
|             name: Cow::Borrowed(WindowTextureNode::OUT_TEXTURE), | ||||
|             resource_type: ResourceInfo::Texture, | ||||
|         }]; | ||||
|         OUTPUT | ||||
| @ -32,15 +51,29 @@ impl Node for WindowTextureNode { | ||||
|         output: &mut ResourceSlots, | ||||
|     ) { | ||||
|         const WINDOW_TEXTURE: usize = 0; | ||||
|         let window_created_events = resources.get::<Events<WindowCreated>>().unwrap(); | ||||
|         let window_resized_events = resources.get::<Events<WindowResized>>().unwrap(); | ||||
|         if let Some(event) = window_resized_events.latest(&mut self.window_resized_event_reader) { | ||||
|         let windows = resources.get::<Windows>().unwrap(); | ||||
| 
 | ||||
|         let window = match self.window_reference { | ||||
|             WindowReference::Primary => windows.get_primary().expect("No primary window exists"), | ||||
|             WindowReference::Id(id) => windows | ||||
|                 .get(id) | ||||
|                 .expect("Received window resized event for non-existent window"), | ||||
|         }; | ||||
| 
 | ||||
|         if window_created_events | ||||
|             .find_latest(&mut self.window_created_event_reader, |e| e.id == window.id).is_some() || | ||||
|             window_resized_events | ||||
|             .find_latest(&mut self.window_resized_event_reader, |e| e.id == window.id).is_some() | ||||
|         { | ||||
|             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; | ||||
|             self.descriptor.size.width = window.width; | ||||
|             self.descriptor.size.height = window.height; | ||||
|             let texture_resource = render_resources.create_texture(&self.descriptor); | ||||
|             output.set(WINDOW_TEXTURE, texture_resource); | ||||
|         } | ||||
|  | ||||
| @ -187,6 +187,7 @@ fn stage_node( | ||||
|     // don't re-visit nodes or visit them before all of their parents have been visited
 | ||||
|     if node_stages_and_jobs.contains_key(&node.id) | ||||
|         || node | ||||
|             .edges | ||||
|             .input_edges | ||||
|             .iter() | ||||
|             .find(|e| !node_stages_and_jobs.contains_key(&e.get_output_node())) | ||||
| @ -204,6 +205,7 @@ fn stage_node( | ||||
| 
 | ||||
|     // check to see if the current node has a parent. if so, grab the parent with the highest stage
 | ||||
|     if let Some((max_parent_stage, max_parent_job)) = node | ||||
|         .edges | ||||
|         .input_edges | ||||
|         .iter() | ||||
|         .map(|e| { | ||||
| @ -215,6 +217,7 @@ fn stage_node( | ||||
|     { | ||||
|         // count the number of parents that are in the highest stage
 | ||||
|         let max_stage_parent_count = node | ||||
|             .edges | ||||
|             .input_edges | ||||
|             .iter() | ||||
|             .filter(|e| { | ||||
|  | ||||
| @ -11,7 +11,7 @@ use bevy_render::{ | ||||
|     }, | ||||
|     pipeline::{BindGroupDescriptor, BindType, PipelineDescriptor}, | ||||
|     render_resource::{ | ||||
|         resource_name, RenderResource, RenderResourceAssignments, RenderResourceSetId, ResourceInfo, | ||||
|         RenderResource, RenderResourceAssignments, RenderResourceSetId, ResourceInfo, | ||||
|     }, | ||||
|     renderer_2::{RenderContext, RenderResourceContext}, | ||||
|     shader::Shader, | ||||
| @ -475,26 +475,13 @@ fn get_texture_view<'a>( | ||||
|     attachment: &TextureAttachment, | ||||
| ) -> &'a wgpu::TextureView { | ||||
|     match attachment { | ||||
|         TextureAttachment::Name(name) => match name.as_str() { | ||||
|             resource_name::texture::SWAP_CHAIN => { | ||||
|                 if let Some(primary_swap_chain) = refs.swap_chain_outputs.values().next() { | ||||
|                     &primary_swap_chain.view | ||||
|                 } else { | ||||
|                     panic!("No primary swap chain found for color attachment"); | ||||
|                 } | ||||
|         TextureAttachment::Name(name) => match global_render_resource_assignments.get(&name) { | ||||
|             Some(resource) => refs.textures.get(&resource).unwrap(), | ||||
|             None => { | ||||
|                 panic!("Color attachment {} does not exist", name); | ||||
|             } | ||||
|             _ => match global_render_resource_assignments.get(&name) { | ||||
|                 Some(resource) => refs.textures.get(&resource).unwrap(), | ||||
|                 None => { | ||||
|                     // if let Some(swap_chain_output) = swap_chain_outputs.get(name) {
 | ||||
|                     //     &swap_chain_output.view
 | ||||
|                     // } else {
 | ||||
|                     panic!("Color attachment {} does not exist", name); | ||||
|                     // }
 | ||||
|                 } | ||||
|             }, | ||||
|         }, | ||||
|         TextureAttachment::RenderResource(render_resource) => refs.textures.get(&render_resource).unwrap(), | ||||
|         TextureAttachment::RenderResource(render_resource) => refs.textures.get(&render_resource).unwrap_or_else(|| &refs.swap_chain_outputs.get(&render_resource).unwrap().view), | ||||
|         TextureAttachment::Input(_) => panic!("Encountered unset TextureAttachment::Input. The RenderGraph executor should always set TextureAttachment::Inputs to TextureAttachment::RenderResource before running. This is a bug"), | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -1,7 +1,10 @@ | ||||
| use super::{WgpuRenderContext, WgpuRenderResourceContext}; | ||||
| use bevy_render::{render_graph_2::StageBorrow, renderer_2::GlobalRenderResourceContext}; | ||||
| use bevy_render::{ | ||||
|     render_graph_2::{Edge, NodeId, ResourceSlots, StageBorrow}, | ||||
|     renderer_2::GlobalRenderResourceContext, | ||||
| }; | ||||
| use legion::prelude::{Resources, World}; | ||||
| use std::sync::Arc; | ||||
| use std::{collections::HashMap, sync::Arc}; | ||||
| 
 | ||||
| pub struct WgpuRenderGraphExecutor { | ||||
|     pub max_thread_count: usize, | ||||
| @ -21,6 +24,7 @@ impl WgpuRenderGraphExecutor { | ||||
|             .context | ||||
|             .downcast_mut::<WgpuRenderResourceContext>() | ||||
|             .unwrap(); | ||||
|         let mut node_outputs: HashMap<NodeId, ResourceSlots> = HashMap::new(); | ||||
|         for stage in stages.iter_mut() { | ||||
|             // TODO: sort jobs and slice by "amount of work" / weights
 | ||||
|             // stage.jobs.sort_by_key(|j| j.node_states.len());
 | ||||
| @ -29,6 +33,7 @@ impl WgpuRenderGraphExecutor { | ||||
|             let chunk_size = (stage.jobs.len() + self.max_thread_count - 1) / self.max_thread_count; // divide ints rounding remainder up
 | ||||
|             let mut actual_thread_count = 0; | ||||
|             crossbeam_utils::thread::scope(|s| { | ||||
|                 let node_outputs = &node_outputs; | ||||
|                 for jobs_chunk in stage.jobs.chunks_mut(chunk_size) { | ||||
|                     let sender = sender.clone(); | ||||
|                     let world = &*world; | ||||
| @ -38,8 +43,37 @@ impl WgpuRenderGraphExecutor { | ||||
|                     s.spawn(move |_| { | ||||
|                         let mut render_context = | ||||
|                             WgpuRenderContext::new(device, render_resource_context); | ||||
|                         let mut local_node_outputs = HashMap::new(); | ||||
|                         for job in jobs_chunk.iter_mut() { | ||||
|                             for node_state in job.node_states.iter_mut() { | ||||
|                                 // bind inputs from connected node outputs
 | ||||
|                                 for (i, mut input_slot) in node_state.input_slots.iter_mut().enumerate() | ||||
|                                 { | ||||
|                                     if let Edge::SlotEdge { | ||||
|                                         output_node, | ||||
|                                         output_index, | ||||
|                                         .. | ||||
|                                     } = node_state.edges.get_input_slot_edge(i).unwrap() | ||||
|                                     { | ||||
|                                         let outputs = | ||||
|                                             if let Some(outputs) = node_outputs.get(output_node) { | ||||
|                                                 outputs | ||||
|                                             } else if let Some(outputs) = | ||||
|                                                 local_node_outputs.get(output_node) | ||||
|                                             { | ||||
|                                                 outputs | ||||
|                                             } else { | ||||
|                                                 panic!("node inputs not set") | ||||
|                                             }; | ||||
| 
 | ||||
|                                         let output_resource = outputs | ||||
|                                             .get(*output_index) | ||||
|                                             .expect("output should be set"); | ||||
|                                         input_slot.resource = Some(output_resource); | ||||
|                                     } else { | ||||
|                                         panic!("no edge connected to input") | ||||
|                                     } | ||||
|                                 } | ||||
|                                 node_state.node.update( | ||||
|                                     world, | ||||
|                                     resources, | ||||
| @ -47,9 +81,14 @@ impl WgpuRenderGraphExecutor { | ||||
|                                     &node_state.input_slots, | ||||
|                                     &mut node_state.output_slots, | ||||
|                                 ); | ||||
| 
 | ||||
|                                 local_node_outputs | ||||
|                                     .insert(node_state.id, node_state.output_slots.clone()); | ||||
|                             } | ||||
|                         } | ||||
|                         sender.send(render_context.finish()).unwrap(); | ||||
|                         sender | ||||
|                             .send((render_context.finish(), local_node_outputs)) | ||||
|                             .unwrap(); | ||||
|                     }); | ||||
|                 } | ||||
|             }) | ||||
| @ -57,10 +96,12 @@ impl WgpuRenderGraphExecutor { | ||||
| 
 | ||||
|             let mut command_buffers = Vec::new(); | ||||
|             for _i in 0..actual_thread_count { | ||||
|                 let command_buffer = receiver.recv().unwrap(); | ||||
|                 let (command_buffer, mut local_node_outputs) = receiver.recv().unwrap(); | ||||
|                 if let Some(command_buffer) = command_buffer { | ||||
|                     command_buffers.push(command_buffer); | ||||
|                 } | ||||
| 
 | ||||
|                 node_outputs.extend(local_node_outputs.drain()); | ||||
|             } | ||||
| 
 | ||||
|             queue.submit(&command_buffers); | ||||
|  | ||||
| @ -1,5 +1,10 @@ | ||||
| use uuid::Uuid; | ||||
| 
 | ||||
| pub enum WindowReference { | ||||
|     Primary, | ||||
|     Id(WindowId), | ||||
| } | ||||
| 
 | ||||
| #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] | ||||
| pub struct WindowId(Uuid); | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Carter Anderson
						Carter Anderson