Implement a Render Graph #16

Merged
SeanOMik merged 20 commits from feature/render-graph into main 2024-06-15 22:54:47 +00:00
1 changed files with 12 additions and 20 deletions
Showing only changes of commit d5348ec172 - Show all commits

View File

@ -119,16 +119,8 @@ pub struct RenderGraph {
device: Rc<wgpu::Device>, device: Rc<wgpu::Device>,
queue: Rc<wgpu::Queue>, queue: Rc<wgpu::Queue>,
slots: FxHashMap<RenderGraphLabelValue, ResourcedSlot>, slots: FxHashMap<RenderGraphLabelValue, ResourcedSlot>,
/// HashMap used to lookup the slot id using the label's hash nodes: FxHashMap<RenderGraphLabelValue, PassEntry>,
//slot_label_lookup: FxHashMap<RenderGraphLabelValue, u64>,
passes: FxHashMap<RenderGraphLabelValue, PassEntry>,
// TODO: Use a SlotMap
bind_groups: FxHashMap<RenderGraphLabelValue, BindGroupEntry>, bind_groups: FxHashMap<RenderGraphLabelValue, BindGroupEntry>,
/// HashMap used to lookup the bind group id using the label's hash
//bind_group_names: FxHashMap<RenderGraphLabelValue, u64>,
// TODO: make pipelines a `type` parameter in RenderPasses,
// then the pipelines can be retrieved via TypeId to the pass.
//pipelines: FxHashMap<u64, PipelineResource>,
/// A directed graph describing the execution path of the RenderGraph /// A directed graph describing the execution path of the RenderGraph
execution_graph: petgraph::matrix_graph::DiMatrix<RenderGraphLabelValue, (), Option<()>, usize>, execution_graph: petgraph::matrix_graph::DiMatrix<RenderGraphLabelValue, (), Option<()>, usize>,
} }
@ -139,7 +131,7 @@ impl RenderGraph {
device, device,
queue, queue,
slots: Default::default(), slots: Default::default(),
passes: Default::default(), nodes: Default::default(),
bind_groups: Default::default(), bind_groups: Default::default(),
execution_graph: Default::default(), execution_graph: Default::default(),
} }
@ -213,7 +205,7 @@ impl RenderGraph {
let label: RenderGraphLabelValue = label.into(); let label: RenderGraphLabelValue = label.into();
let index = self.execution_graph.add_node(label.clone()); let index = self.execution_graph.add_node(label.clone());
self.passes.insert( self.nodes.insert(
label, label,
PassEntry { PassEntry {
inner: Arc::new(RefCell::new(pass)), inner: Arc::new(RefCell::new(pass)),
@ -231,7 +223,7 @@ impl RenderGraph {
#[instrument(skip(self, device))] #[instrument(skip(self, device))]
pub fn setup(&mut self, device: &wgpu::Device) { pub fn setup(&mut self, device: &wgpu::Device) {
// For all passes, create their pipelines // For all passes, create their pipelines
for pass in self.passes.values_mut() { for pass in self.nodes.values_mut() {
let desc = (*pass.desc).borrow(); let desc = (*pass.desc).borrow();
if let Some(pipeline_desc) = &desc.pipeline_desc { if let Some(pipeline_desc) = &desc.pipeline_desc {
let pipeline = match desc.ty { let pipeline = match desc.ty {
@ -270,9 +262,9 @@ impl RenderGraph {
let mut buffer_writes = VecDeque::<GraphBufferWrite>::new(); let mut buffer_writes = VecDeque::<GraphBufferWrite>::new();
// reserve some buffer writes. not all nodes write so half the amount of them is probably // reserve some buffer writes. not all nodes write so half the amount of them is probably
// fine. // fine.
buffer_writes.reserve(self.passes.len() / 2); buffer_writes.reserve(self.nodes.len() / 2);
for (label, pass) in &mut self.passes { for (label, pass) in &mut self.nodes {
let mut context = RenderGraphContext::new(&self.device, &self.queue, None, label.clone()); let mut context = RenderGraphContext::new(&self.device, &self.queue, None, label.clone());
let mut inner = pass.inner.borrow_mut(); let mut inner = pass.inner.borrow_mut();
inner.prepare(world, &mut context); inner.prepare(world, &mut context);
@ -311,9 +303,9 @@ impl RenderGraph {
.collect(); .collect();
//debug!("Render graph execution order: {:?}", sorted); //debug!("Render graph execution order: {:?}", sorted);
let mut encoders = Vec::with_capacity(self.passes.len() / 2); let mut encoders = Vec::with_capacity(self.nodes.len() / 2);
while let Some(pass_label) = sorted.pop_front() { while let Some(pass_label) = sorted.pop_front() {
let pass = self.passes.get(&pass_label).unwrap(); let pass = self.nodes.get(&pass_label).unwrap();
let pass_inn = pass.inner.clone(); let pass_inn = pass.inner.clone();
let pass_desc = pass.desc.clone(); let pass_desc = pass.desc.clone();
@ -373,12 +365,12 @@ impl RenderGraph {
} }
pub fn node_desc<L: Into<RenderGraphLabelValue>>(&self, label: L) -> Option<Ref<NodeDesc>> { pub fn node_desc<L: Into<RenderGraphLabelValue>>(&self, label: L) -> Option<Ref<NodeDesc>> {
self.passes.get(&label.into()).map(|s| (*s.desc).borrow()) self.nodes.get(&label.into()).map(|s| (*s.desc).borrow())
} }
#[inline(always)] #[inline(always)]
pub fn pipeline<L: Into<RenderGraphLabelValue>>(&self, label: L) -> Option<Ref<Pipeline>> { pub fn pipeline<L: Into<RenderGraphLabelValue>>(&self, label: L) -> Option<Ref<Pipeline>> {
self.passes.get(&label.into()) self.nodes.get(&label.into())
.and_then(|p| { .and_then(|p| {
let v = p.pipeline.borrow(); let v = p.pipeline.borrow();
@ -416,13 +408,13 @@ impl RenderGraph {
let to = RenderGraphLabelValue::from(to); let to = RenderGraphLabelValue::from(to);
let from_idx = self let from_idx = self
.passes .nodes
.iter() .iter()
.find(|p| *p.0 == from) .find(|p| *p.0 == from)
.map(|p| p.1.graph_index) .map(|p| p.1.graph_index)
.expect("Failed to find from pass"); .expect("Failed to find from pass");
let to_idx = self let to_idx = self
.passes .nodes
.iter() .iter()
.find(|p| *p.0 == to) .find(|p| *p.0 == to)
.map(|p| p.1.graph_index) .map(|p| p.1.graph_index)