quick save
This commit is contained in:
		
							parent
							
								
									3deca28391
								
							
						
					
					
						commit
						146ffa654f
					
				|  | @ -2,7 +2,7 @@ | ||||||
| 
 | 
 | ||||||
| use std::{ | use std::{ | ||||||
|     collections::{BTreeMap, BTreeSet}, |     collections::{BTreeMap, BTreeSet}, | ||||||
|     fmt::Debug, |     fmt::{Debug, Display}, | ||||||
|     sync::Arc, |     sync::Arc, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | @ -75,7 +75,7 @@ impl RenderContext<'_> { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Debug, Clone, Copy, Default)] | #[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord)] | ||||||
| pub struct Access { | pub struct Access { | ||||||
|     pub stage: vk::PipelineStageFlags2, |     pub stage: vk::PipelineStageFlags2, | ||||||
|     pub mask: vk::AccessFlags2, |     pub mask: vk::AccessFlags2, | ||||||
|  | @ -95,7 +95,72 @@ impl core::ops::BitOr for Access { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord)] | ||||||
|  | pub struct AccessMask { | ||||||
|  |     pub stage: vk::PipelineStageFlags2, | ||||||
|  |     pub mask: vk::AccessFlags2, | ||||||
|  | } | ||||||
|  | impl AccessMask { | ||||||
|  |     fn undefined() -> Self { | ||||||
|  |         Self { | ||||||
|  |             stage: vk::PipelineStageFlags2::NONE, | ||||||
|  |             mask: vk::AccessFlags2::empty(), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     fn is_empty(&self) -> bool { | ||||||
|  |         self.stage.is_empty() && self.mask.is_empty() | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | impl core::ops::BitOr for AccessMask { | ||||||
|  |     type Output = Self; | ||||||
|  | 
 | ||||||
|  |     fn bitor(self, rhs: Self) -> Self::Output { | ||||||
|  |         Self { | ||||||
|  |             stage: self.stage | rhs.stage, | ||||||
|  |             mask: self.mask | rhs.mask, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | impl core::ops::Not for AccessMask { | ||||||
|  |     type Output = Self; | ||||||
|  | 
 | ||||||
|  |     fn not(self) -> Self::Output { | ||||||
|  |         Self { | ||||||
|  |             stage: !self.stage, | ||||||
|  |             mask: !self.mask, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl core::ops::BitAnd for AccessMask { | ||||||
|  |     type Output = Self; | ||||||
|  | 
 | ||||||
|  |     fn bitand(self, rhs: Self) -> Self::Output { | ||||||
|  |         Self { | ||||||
|  |             stage: self.stage & rhs.stage, | ||||||
|  |             mask: self.mask & rhs.mask, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl core::ops::BitXor for AccessMask { | ||||||
|  |     type Output = Self; | ||||||
|  | 
 | ||||||
|  |     fn bitxor(self, rhs: Self) -> Self::Output { | ||||||
|  |         Self { | ||||||
|  |             stage: self.stage ^ rhs.stage, | ||||||
|  |             mask: self.mask ^ rhs.mask, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| impl Access { | impl Access { | ||||||
|  |     pub fn into_access_mask(&self) -> AccessMask { | ||||||
|  |         AccessMask { | ||||||
|  |             stage: self.stage, | ||||||
|  |             mask: self.mask, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|     pub fn undefined() -> Self { |     pub fn undefined() -> Self { | ||||||
|         Self { |         Self { | ||||||
|             stage: vk::PipelineStageFlags2::NONE, |             stage: vk::PipelineStageFlags2::NONE, | ||||||
|  | @ -103,6 +168,22 @@ impl Access { | ||||||
|             layout: Some(vk::ImageLayout::UNDEFINED), |             layout: Some(vk::ImageLayout::UNDEFINED), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |     /// Only use this for `Ord`!
 | ||||||
|  |     pub fn min() -> Self { | ||||||
|  |         Self { | ||||||
|  |             stage: vk::PipelineStageFlags2::from_raw(u64::MAX), | ||||||
|  |             mask: vk::AccessFlags2::from_raw(u64::MAX), | ||||||
|  |             layout: None, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     /// Only use this for `Ord`!
 | ||||||
|  |     pub fn max() -> Self { | ||||||
|  |         Self { | ||||||
|  |             stage: vk::PipelineStageFlags2::from_raw(u64::MAX), | ||||||
|  |             mask: vk::AccessFlags2::from_raw(u64::MAX), | ||||||
|  |             layout: Some(vk::ImageLayout::from_raw(i32::MAX)), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|     pub fn general() -> Self { |     pub fn general() -> Self { | ||||||
|         Self { |         Self { | ||||||
|             stage: vk::PipelineStageFlags2::NONE, |             stage: vk::PipelineStageFlags2::NONE, | ||||||
|  | @ -304,13 +385,414 @@ impl RenderGraph { | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         #[derive(Debug, Clone, Copy)] |         #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] | ||||||
|         enum PassNode { |         enum PassNode { | ||||||
|             First, |             First, | ||||||
|             Pass(usize), |             Pass(usize), | ||||||
|             Last, |             Last, | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         impl PassNode { | ||||||
|  |             fn into_u32(&self) -> u32 { | ||||||
|  |                 match self { | ||||||
|  |                     PassNode::First => 0, | ||||||
|  |                     PassNode::Last => 1, | ||||||
|  |                     PassNode::Pass(i) => 2 + *i as u32, | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] | ||||||
|  |         enum RefAccess { | ||||||
|  |             __Min, | ||||||
|  |             None, | ||||||
|  |             Read(Access), | ||||||
|  |             Write(Access), | ||||||
|  |             __Max, | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] | ||||||
|  |         struct GraphRef { | ||||||
|  |             pass: PassNode, | ||||||
|  |             resource: GraphResourceId, | ||||||
|  |             access: RefAccess, | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // gather references to resources.
 | ||||||
|  |         let (references, intervals) = { | ||||||
|  |             let mut references = BTreeSet::<GraphRef>::new(); | ||||||
|  | 
 | ||||||
|  |             // interval for each resource from (first pass referencing, last pass referencing)
 | ||||||
|  |             let mut intervals = BTreeMap::<GraphResourceId, (PassNode, PassNode)>::new(); | ||||||
|  | 
 | ||||||
|  |             // the root node creates and transitions resources added to the
 | ||||||
|  |             // graph. don't want to create any resources which are never used
 | ||||||
|  |             // after `First`. a newly created resource has no layout and no
 | ||||||
|  |             // writes to make-available.
 | ||||||
|  |             for rid in self.resource_descs.keys() { | ||||||
|  |                 references.insert(GraphRef { | ||||||
|  |                     pass: PassNode::First, | ||||||
|  |                     resource: *rid, | ||||||
|  |                     access: RefAccess::Write(Access::undefined()), | ||||||
|  |                 }); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             for (i, pass) in self.pass_descs.iter().enumerate() { | ||||||
|  |                 let mut reads = BTreeMap::new(); | ||||||
|  |                 for (rid, access) in &pass.reads { | ||||||
|  |                     reads | ||||||
|  |                         .entry(*rid) | ||||||
|  |                         .and_modify(|entry| { | ||||||
|  |                             *entry = *entry | *access; | ||||||
|  |                         }) | ||||||
|  |                         .or_insert(*access); | ||||||
|  | 
 | ||||||
|  |                     intervals | ||||||
|  |                         .entry(*rid) | ||||||
|  |                         .and_modify(|entry| { | ||||||
|  |                             entry.1 = PassNode::Pass(i); | ||||||
|  |                         }) | ||||||
|  |                         .or_insert((PassNode::Pass(i), PassNode::Pass(i))); | ||||||
|  |                 } | ||||||
|  |                 references.extend(reads.into_iter().map(|(resource, access)| GraphRef { | ||||||
|  |                     pass: PassNode::Pass(i), | ||||||
|  |                     resource, | ||||||
|  |                     access: RefAccess::Read(access), | ||||||
|  |                 })); | ||||||
|  | 
 | ||||||
|  |                 let mut writes = BTreeMap::new(); | ||||||
|  |                 for (rid, access) in &pass.writes { | ||||||
|  |                     writes | ||||||
|  |                         .entry(*rid) | ||||||
|  |                         .and_modify(|entry| { | ||||||
|  |                             *entry = *entry | *access; | ||||||
|  |                         }) | ||||||
|  |                         .or_insert(*access); | ||||||
|  | 
 | ||||||
|  |                     intervals | ||||||
|  |                         .entry(*rid) | ||||||
|  |                         .and_modify(|entry| { | ||||||
|  |                             entry.1 = PassNode::Pass(i); | ||||||
|  |                         }) | ||||||
|  |                         .or_insert((PassNode::Pass(i), PassNode::Pass(i))); | ||||||
|  |                 } | ||||||
|  |                 references.extend(writes.into_iter().map(|(resource, access)| GraphRef { | ||||||
|  |                     pass: PassNode::Pass(i), | ||||||
|  |                     resource, | ||||||
|  |                     access: RefAccess::Write(access), | ||||||
|  |                 })); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             // any resource marked as output should be created and returned even
 | ||||||
|  |             // if it isn't referenced by any pass.
 | ||||||
|  |             for rid in &self.outputs { | ||||||
|  |                 references.insert(GraphRef { | ||||||
|  |                     pass: PassNode::Last, | ||||||
|  |                     resource: *rid, | ||||||
|  |                     access: RefAccess::None, | ||||||
|  |                 }); | ||||||
|  | 
 | ||||||
|  |                 intervals | ||||||
|  |                     .entry(*rid) | ||||||
|  |                     .and_modify(|entry| { | ||||||
|  |                         entry.1 = PassNode::Last; | ||||||
|  |                     }) | ||||||
|  |                     .or_insert((PassNode::Last, PassNode::Last)); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             (references, intervals) | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         #[derive(Debug)] | ||||||
|  |         enum Barrier { | ||||||
|  |             Logical, | ||||||
|  |             Execution { | ||||||
|  |                 src: vk::PipelineStageFlags2, | ||||||
|  |                 dst: vk::PipelineStageFlags2, | ||||||
|  |             }, | ||||||
|  |             LayoutTransition { | ||||||
|  |                 src: (vk::PipelineStageFlags2, vk::ImageLayout), | ||||||
|  |                 dst: (vk::PipelineStageFlags2, vk::ImageLayout), | ||||||
|  |             }, | ||||||
|  | 
 | ||||||
|  |             MakeAvailable { | ||||||
|  |                 src: (vk::PipelineStageFlags2, vk::AccessFlags2), | ||||||
|  |                 dst: vk::PipelineStageFlags2, | ||||||
|  |             }, | ||||||
|  |             MakeVisible { | ||||||
|  |                 src: vk::PipelineStageFlags2, | ||||||
|  |                 dst: (vk::PipelineStageFlags2, vk::AccessFlags2), | ||||||
|  |             }, | ||||||
|  |             MemoryBarrier { | ||||||
|  |                 src: (vk::PipelineStageFlags2, vk::AccessFlags2), | ||||||
|  |                 dst: (vk::PipelineStageFlags2, vk::AccessFlags2), | ||||||
|  |             }, | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         impl Display for Barrier { | ||||||
|  |             fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||||
|  |                 match self { | ||||||
|  |                     Barrier::Logical => write!(f, "Logical"), | ||||||
|  |                     Barrier::Execution { .. } => write!(f, "Execution"), | ||||||
|  |                     Barrier::LayoutTransition { .. } => write!(f, "Layout"), | ||||||
|  |                     Barrier::MakeAvailable { .. } => write!(f, "MakeAvailable"), | ||||||
|  |                     Barrier::MakeVisible { .. } => write!(f, "MakeVisible"), | ||||||
|  |                     Barrier::MemoryBarrier { .. } => write!(f, "MemoryBarrier"), | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // build graph from references.
 | ||||||
|  |         { | ||||||
|  |             let mut edges = Vec::new(); | ||||||
|  | 
 | ||||||
|  |             intervals.iter().for_each(|(&rid, &(from, to))| { | ||||||
|  |                 #[derive(Clone, Copy, Debug)] | ||||||
|  |                 enum PreviousRef { | ||||||
|  |                     Write(PassNode, Access), | ||||||
|  |                     Read(PassNode, Access), | ||||||
|  |                 } | ||||||
|  |                 impl PreviousRef { | ||||||
|  |                     fn node(&self) -> PassNode { | ||||||
|  |                         match self { | ||||||
|  |                             PreviousRef::Write(pass_node, _) => *pass_node, | ||||||
|  |                             PreviousRef::Read(pass_node, _) => *pass_node, | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                     fn access(&self) -> Access { | ||||||
|  |                         match self { | ||||||
|  |                             PreviousRef::Write(_, access) => *access, | ||||||
|  |                             PreviousRef::Read(_, access) => *access, | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 // writes not yet made available
 | ||||||
|  |                 let mut to_make_available = AccessMask::undefined(); | ||||||
|  |                 // writes already made-visible
 | ||||||
|  |                 let mut made_visible = AccessMask::undefined(); | ||||||
|  |                 let mut last_read = PreviousRef::Write(PassNode::First, Access::undefined()); | ||||||
|  |                 let mut last_write = PreviousRef::Write(PassNode::First, Access::undefined()); | ||||||
|  |                 let mut last_ref = PreviousRef::Write(PassNode::First, Access::undefined()); | ||||||
|  | 
 | ||||||
|  |                 references | ||||||
|  |                     .range( | ||||||
|  |                         GraphRef { | ||||||
|  |                             pass: from, | ||||||
|  |                             resource: rid, | ||||||
|  |                             access: RefAccess::__Min, | ||||||
|  |                         }..GraphRef { | ||||||
|  |                             pass: to, | ||||||
|  |                             resource: rid, | ||||||
|  |                             access: RefAccess::__Max, | ||||||
|  |                         }, | ||||||
|  |                     ) | ||||||
|  |                     .for_each(|a| { | ||||||
|  |                         // TODO: VkEvents can make this more
 | ||||||
|  |                         // fine-grained but also probably have zero
 | ||||||
|  |                         // real-world benefit :<
 | ||||||
|  | 
 | ||||||
|  |                         last_ref = match a.access { | ||||||
|  |                             RefAccess::None => { | ||||||
|  |                                 // make-available previous writes
 | ||||||
|  |                                 // no-op edge between previous reference and a.pass
 | ||||||
|  | 
 | ||||||
|  |                                 edges.push(((last_ref.node(), a.pass), (rid, Barrier::Logical))); | ||||||
|  |                                 // because this is the last node, setting last_ref isn't required.
 | ||||||
|  |                                 PreviousRef::Read(a.pass, Access::undefined()) | ||||||
|  |                             } | ||||||
|  |                             RefAccess::Read(access) => { | ||||||
|  |                                 // - if read: no writes pending, check for
 | ||||||
|  |                                 // layout transition, otherwise an edge to
 | ||||||
|  |                                 // previous write. make sure it is only executed
 | ||||||
|  |                                 // once.
 | ||||||
|  |                                 // - if write: make-available writes + make-visible for reads
 | ||||||
|  |                                 let make_visible_mask = access.into_access_mask() & !made_visible; | ||||||
|  |                                 made_visible = made_visible | make_visible_mask; | ||||||
|  | 
 | ||||||
|  |                                 match last_ref { | ||||||
|  |                                     PreviousRef::Read(pass_node, before) => { | ||||||
|  |                                         if !make_visible_mask.is_empty() { | ||||||
|  |                                             // make-visible reads.
 | ||||||
|  |                                             edges.push(( | ||||||
|  |                                                 (last_write.node(), a.pass), | ||||||
|  |                                                 ( | ||||||
|  |                                                     rid, | ||||||
|  |                                                     Barrier::MakeVisible { | ||||||
|  |                                                         src: last_write.access().stage, | ||||||
|  |                                                         dst: ( | ||||||
|  |                                                             make_visible_mask.stage, | ||||||
|  |                                                             make_visible_mask.mask, | ||||||
|  |                                                         ), | ||||||
|  |                                                     }, | ||||||
|  |                                                 ), | ||||||
|  |                                             )); | ||||||
|  |                                         } else { | ||||||
|  |                                             // still require a after b
 | ||||||
|  |                                             edges.push(( | ||||||
|  |                                                 (last_write.node(), a.pass), | ||||||
|  |                                                 ( | ||||||
|  |                                                     rid, | ||||||
|  |                                                     Barrier::Execution { | ||||||
|  |                                                         src: last_write.access().stage, | ||||||
|  |                                                         dst: access.stage, | ||||||
|  |                                                     }, | ||||||
|  |                                                 ), | ||||||
|  |                                             )); | ||||||
|  |                                         } | ||||||
|  | 
 | ||||||
|  |                                         if before.layout != access.layout { | ||||||
|  |                                             edges.push(( | ||||||
|  |                                                 (pass_node, a.pass), | ||||||
|  |                                                 ( | ||||||
|  |                                                     rid, | ||||||
|  |                                                     Barrier::LayoutTransition { | ||||||
|  |                                                         src: (before.stage, before.layout.unwrap()), | ||||||
|  |                                                         dst: (access.stage, access.layout.unwrap()), | ||||||
|  |                                                     }, | ||||||
|  |                                                 ), | ||||||
|  |                                             )); | ||||||
|  |                                         } | ||||||
|  |                                     } | ||||||
|  |                                     PreviousRef::Write(..) => { | ||||||
|  |                                         // make writes visible
 | ||||||
|  |                                         if make_visible_mask.is_empty() { | ||||||
|  |                                             edges.push(( | ||||||
|  |                                                 (last_write.node(), a.pass), | ||||||
|  |                                                 ( | ||||||
|  |                                                     rid, | ||||||
|  |                                                     Barrier::MakeVisible { | ||||||
|  |                                                         src: last_write.access().stage, | ||||||
|  |                                                         dst: ( | ||||||
|  |                                                             make_visible_mask.stage, | ||||||
|  |                                                             make_visible_mask.mask, | ||||||
|  |                                                         ), | ||||||
|  |                                                     }, | ||||||
|  |                                                 ), | ||||||
|  |                                             )); | ||||||
|  |                                         } | ||||||
|  |                                         // make all writes available
 | ||||||
|  |                                         if !to_make_available.is_empty() { | ||||||
|  |                                             edges.push(( | ||||||
|  |                                                 (last_write.node(), a.pass), | ||||||
|  |                                                 ( | ||||||
|  |                                                     rid, | ||||||
|  |                                                     Barrier::MakeAvailable { | ||||||
|  |                                                         src: ( | ||||||
|  |                                                             to_make_available.stage, | ||||||
|  |                                                             to_make_available.mask, | ||||||
|  |                                                         ), | ||||||
|  |                                                         dst: access.stage, | ||||||
|  |                                                     }, | ||||||
|  |                                                 ), | ||||||
|  |                                             )); | ||||||
|  |                                             // mark that we've made all pending writes available
 | ||||||
|  |                                             to_make_available = AccessMask::undefined(); | ||||||
|  |                                         } | ||||||
|  | 
 | ||||||
|  |                                         if make_visible_mask.is_empty() | ||||||
|  |                                             && to_make_available.is_empty() | ||||||
|  |                                         { | ||||||
|  |                                             // still require a after b
 | ||||||
|  |                                             edges.push(( | ||||||
|  |                                                 (last_write.node(), a.pass), | ||||||
|  |                                                 ( | ||||||
|  |                                                     rid, | ||||||
|  |                                                     Barrier::Execution { | ||||||
|  |                                                         src: last_write.access().stage, | ||||||
|  |                                                         dst: access.stage, | ||||||
|  |                                                     }, | ||||||
|  |                                                 ), | ||||||
|  |                                             )); | ||||||
|  |                                         } | ||||||
|  |                                     } | ||||||
|  |                                 } | ||||||
|  |                                 last_read = PreviousRef::Read(a.pass, access); | ||||||
|  |                                 last_write | ||||||
|  |                             } | ||||||
|  |                             RefAccess::Write(access) => { | ||||||
|  |                                 // - if read: execution barrier against write-after-read
 | ||||||
|  |                                 // - if write: check for layout transition, otherwise a no-op edge.
 | ||||||
|  |                                 to_make_available = to_make_available | access.into_access_mask(); | ||||||
|  | 
 | ||||||
|  |                                 match last_ref { | ||||||
|  |                                     PreviousRef::Read(pass_node, before) => { | ||||||
|  |                                         // execution barrier to ward against write-after-read
 | ||||||
|  |                                         edges.push(( | ||||||
|  |                                             (pass_node, a.pass), | ||||||
|  |                                             ( | ||||||
|  |                                                 rid, | ||||||
|  |                                                 Barrier::Execution { | ||||||
|  |                                                     src: before.stage, | ||||||
|  |                                                     dst: access.stage, | ||||||
|  |                                                 }, | ||||||
|  |                                             ), | ||||||
|  |                                         )); | ||||||
|  |                                     } | ||||||
|  |                                     PreviousRef::Write(pass_node, before) => { | ||||||
|  |                                         if before.layout != access.layout { | ||||||
|  |                                             // as far as I understand the spec,
 | ||||||
|  |                                             // this already makes-available
 | ||||||
|  |                                             edges.push(( | ||||||
|  |                                                 (pass_node, a.pass), | ||||||
|  |                                                 ( | ||||||
|  |                                                     rid, | ||||||
|  |                                                     Barrier::LayoutTransition { | ||||||
|  |                                                         src: (before.stage, before.layout.unwrap()), | ||||||
|  |                                                         dst: (access.stage, access.layout.unwrap()), | ||||||
|  |                                                     }, | ||||||
|  |                                                 ), | ||||||
|  |                                             )); | ||||||
|  |                                         } else { | ||||||
|  |                                             // write_no_sync: pass tells us that
 | ||||||
|  |                                             // writes do not interleave.
 | ||||||
|  |                                             edges.push(( | ||||||
|  |                                                 (last_read.node(), a.pass), | ||||||
|  |                                                 (rid, Barrier::Logical), | ||||||
|  |                                             )); | ||||||
|  |                                         } | ||||||
|  |                                     } | ||||||
|  |                                 } | ||||||
|  |                                 last_write = PreviousRef::Write(a.pass, access); | ||||||
|  |                                 last_write | ||||||
|  |                             } | ||||||
|  |                             _ => unreachable!(), | ||||||
|  |                         }; | ||||||
|  |                     }); | ||||||
|  |             }); | ||||||
|  | 
 | ||||||
|  |             let mut dag = petgraph::graph::DiGraph::new(); | ||||||
|  |             dag.add_node(PassNode::First); | ||||||
|  |             for i in 0..self.pass_descs.len() { | ||||||
|  |                 dag.add_node(PassNode::Pass(i)); | ||||||
|  |             } | ||||||
|  |             dag.add_node(PassNode::Last); | ||||||
|  | 
 | ||||||
|  |             for ((from, to), weight) in edges { | ||||||
|  |                 dag.add_edge(from.into_u32().into(), to.into_u32().into(), weight); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             #[cfg(any(debug_assertions, test))] | ||||||
|  |             std::fs::write( | ||||||
|  |                 "render_graph2.dot", | ||||||
|  |                 &format!( | ||||||
|  |                     "{:?}", | ||||||
|  |                     petgraph::dot::Dot::with_attr_getters( | ||||||
|  |                         &dag, | ||||||
|  |                         &[], | ||||||
|  |                         &|_graph, edgeref| { | ||||||
|  |                             format!( | ||||||
|  |                                 "label = \"{},{}\"", | ||||||
|  |                                 edgeref.weight().0.as_u32(), | ||||||
|  |                                 edgeref.weight().1, | ||||||
|  |                             ) | ||||||
|  |                         }, | ||||||
|  |                         &|_graph, noderef| { format!("label = \"Pass({:?})\"", noderef.weight()) } | ||||||
|  |                     ) | ||||||
|  |                 ), | ||||||
|  |             ) | ||||||
|  |             .expect("writing render_graph repr"); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         let now = std::time::Instant::now(); |         let now = std::time::Instant::now(); | ||||||
|         let mut dag = petgraph::stable_graph::StableDiGraph::new(); |         let mut dag = petgraph::stable_graph::StableDiGraph::new(); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue