From 260275d69484365edd8c430f7a421e33c75d7403 Mon Sep 17 00:00:00 2001 From: Janis Date: Sun, 5 Jan 2025 16:10:30 +0100 Subject: [PATCH] rendergraph: barriers against write-after-read --- crates/renderer/src/render_graph.rs | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/crates/renderer/src/render_graph.rs b/crates/renderer/src/render_graph.rs index 583da85..d7d17f0 100644 --- a/crates/renderer/src/render_graph.rs +++ b/crates/renderer/src/render_graph.rs @@ -305,8 +305,6 @@ impl RenderGraph { } } - let mut dag = petgraph::stable_graph::StableDiGraph::new(); - #[derive(Debug, Clone, Copy)] enum PassNode { First, @@ -314,13 +312,23 @@ impl RenderGraph { Last, } + let mut dag = petgraph::stable_graph::StableDiGraph::new(); + let root = dag.add_node(PassNode::First); - let mut last_write = self + let mut last_write: BTreeMap = self .resources .keys() .filter_map(|id| self.accesses.get(id).map(|access| (*id, (root, *access)))) .collect::>(); + let mut last_read: BTreeMap = BTreeMap::new(); + + // TODO: rewrite finding edges properly. + // finding out if this graph is cyclical is actually non-trivial + // some pass might require both a read of a resource 1, and a read of a resource 2, where 2 is the product of another pass writing to resource 1. + // this could be resolved by copying resource 1 before the write pass. + // tl;dr: write-after-read makes this all more complicated + // insert edges between write->read edges of 2 passes for (i, pass) in self.pass_descs.iter().enumerate() { let node = dag.add_node(PassNode::Pass(i)); @@ -341,6 +349,7 @@ impl RenderGraph { tracing::trace!("adding edge between {other:?} and {node:?} for {rid:?} with ({before:?} -> {after:?})"); dag.add_edge(other, node, (rid, (before, after))); } + last_read.insert(rid, (node, after)); } let mut write_accesses = BTreeMap::new(); @@ -356,6 +365,12 @@ impl RenderGraph { for (rid, after) in write_accesses { last_write.insert(rid, (node, after)); + if let Some(&(other, read)) = last_read.get(&rid) + && other != node + { + tracing::trace!("adding edge between {other:?} and {node:?} for {rid:?} with ({read:?} -> {after:?}) (WaR)"); + dag.add_edge(other, node, (rid, (read, after))); + } } }