From f17bf40c77ed8346dc9021523fd4ef305978583f Mon Sep 17 00:00:00 2001 From: SeanOMik Date: Fri, 21 Jun 2024 21:58:40 -0400 Subject: [PATCH] render: rename RenderGraph::add_pass to add_node --- lyra-game/src/render/graph/context.rs | 89 ++++++++++++++++++++++ lyra-game/src/render/graph/mod.rs | 105 +++----------------------- lyra-game/src/render/renderer.rs | 12 +-- 3 files changed, 107 insertions(+), 99 deletions(-) create mode 100644 lyra-game/src/render/graph/context.rs diff --git a/lyra-game/src/render/graph/context.rs b/lyra-game/src/render/graph/context.rs new file mode 100644 index 0000000..fea0dc0 --- /dev/null +++ b/lyra-game/src/render/graph/context.rs @@ -0,0 +1,89 @@ +use std::collections::VecDeque; + +use tracing::instrument; + +use super::{RenderGraphLabel, RenderGraphLabelValue}; + +/// A queued write to a GPU buffer targeting a graph slot. +pub(crate) struct GraphBufferWrite { + /// The name of the slot that has the resource that will be written + pub(crate) target_slot: RenderGraphLabelValue, + pub(crate) offset: u64, + pub(crate) bytes: Vec, +} + +#[allow(dead_code)] +pub struct RenderGraphContext<'a> { + /// The [`wgpu::CommandEncoder`] used to encode GPU operations. + /// + /// This is `None` during the `prepare` stage. + pub encoder: Option, + /// The gpu device that is being used. + pub device: &'a wgpu::Device, + pub queue: &'a wgpu::Queue, + pub(crate) buffer_writes: VecDeque, + renderpass_desc: Vec>, + /// The label of this Node. + pub label: RenderGraphLabelValue, +} + +impl<'a> RenderGraphContext<'a> { + pub(crate) fn new(device: &'a wgpu::Device, queue: &'a wgpu::Queue, encoder: Option, label: RenderGraphLabelValue) -> Self { + Self { + encoder, + device, + queue, + buffer_writes: Default::default(), + renderpass_desc: vec![], + label, + } + } + + pub fn begin_render_pass( + &'a mut self, + desc: wgpu::RenderPassDescriptor<'a, 'a>, + ) -> wgpu::RenderPass { + self.encoder + .as_mut() + .expect( + "RenderGraphContext is missing a command encoder. This is likely \ + because you are trying to run render commands in the prepare stage.", + ) + .begin_render_pass(&desc) + } + + pub fn begin_compute_pass(&mut self, desc: &wgpu::ComputePassDescriptor) -> wgpu::ComputePass { + self.encoder + .as_mut() + .expect( + "RenderGraphContext is missing a command encoder. This is likely \ + because you are trying to run render commands in the prepare stage.", + ) + .begin_compute_pass(desc) + } + + /// Queue a data write to a buffer at that is contained in `target_slot`. + /// + /// This does not submit the data to the GPU immediately, or add it to the `wgpu::Queue`. The + /// data will be submitted to the GPU queue right after the prepare stage for all passes + /// is ran. + #[instrument(skip(self, bytes), level="trace", fields(size = bytes.len()))] + pub fn queue_buffer_write(&mut self, target_slot: impl RenderGraphLabel, offset: u64, bytes: &[u8]) { + self.buffer_writes.push_back(GraphBufferWrite { + target_slot: target_slot.into(), + offset, + bytes: bytes.to_vec(), + }) + } + + /// Queue a data write of a type that to a buffer at that is contained in `target_slot`. + #[instrument(skip(self, bytes), level="trace", fields(size = std::mem::size_of::()))] + pub fn queue_buffer_write_with( + &mut self, + target_slot: impl RenderGraphLabel, + offset: u64, + bytes: T, + ) { + self.queue_buffer_write(target_slot, offset, bytemuck::bytes_of(&bytes)); + } +} diff --git a/lyra-game/src/render/graph/mod.rs b/lyra-game/src/render/graph/mod.rs index d2d568b..0e754b9 100644 --- a/lyra-game/src/render/graph/mod.rs +++ b/lyra-game/src/render/graph/mod.rs @@ -12,6 +12,9 @@ pub use passes::*; mod slot_desc; pub use slot_desc::*; +mod context; +pub use context::*; + use rustc_hash::FxHashMap; use tracing::{debug_span, instrument, trace, warn}; use wgpu::ComputePass; @@ -121,8 +124,8 @@ pub struct RenderGraph { slots: FxHashMap, nodes: FxHashMap, bind_groups: FxHashMap, - /// A directed graph describing the execution path of the RenderGraph - execution_graph: petgraph::matrix_graph::DiMatrix, usize>, + /// A directed graph used to determine dependencies of nodes. + node_graph: petgraph::matrix_graph::DiMatrix, usize>, } impl RenderGraph { @@ -133,7 +136,7 @@ impl RenderGraph { slots: Default::default(), nodes: Default::default(), bind_groups: Default::default(), - execution_graph: Default::default(), + node_graph: Default::default(), } } @@ -152,7 +155,7 @@ impl RenderGraph { /// not change. The IDs of output slots do stay the same. /// 3. Ensuring that no two slots share the same ID when the names do not match. #[instrument(skip(self, pass), level = "debug")] - pub fn add_pass(&mut self, label: impl RenderGraphLabel, mut pass: P) { + pub fn add_node(&mut self, label: impl RenderGraphLabel, mut pass: P) { let mut desc = pass.desc(self); // collect all the slots of the pass @@ -203,7 +206,7 @@ impl RenderGraph { } let label: RenderGraphLabelValue = label.into(); - let index = self.execution_graph.add_node(label.clone()); + let index = self.node_graph.add_node(label.clone()); self.nodes.insert( label, @@ -296,10 +299,10 @@ impl RenderGraph { #[instrument(skip(self))] pub fn render(&mut self) { - let mut sorted: VecDeque = petgraph::algo::toposort(&self.execution_graph, None) + let mut sorted: VecDeque = petgraph::algo::toposort(&self.node_graph, None) .expect("RenderGraph had cycled!") .iter() - .map(|i| self.execution_graph[i.clone()].clone()) + .map(|i| self.node_graph[i.clone()].clone()) .collect(); //debug!("Render graph execution order: {:?}", sorted); @@ -422,7 +425,7 @@ impl RenderGraph { debug_assert_ne!(from_idx, to_idx, "cannot add edges between the same node"); - self.execution_graph.add_edge(from_idx, to_idx, ()); + self.node_graph.add_edge(from_idx, to_idx, ()); } /// Utility method for setting the bind groups for a pass. @@ -462,88 +465,4 @@ impl RenderGraph { pass.set_bind_group(*index, bg, &[]); } } -} - -/// A queued write to a GPU buffer targeting a graph slot. -pub(crate) struct GraphBufferWrite { - /// The name of the slot that has the resource that will be written - target_slot: RenderGraphLabelValue, - offset: u64, - bytes: Vec, -} - -#[allow(dead_code)] -pub struct RenderGraphContext<'a> { - /// The [`wgpu::CommandEncoder`] used to encode GPU operations. - /// - /// This is `None` during the `prepare` stage. - pub encoder: Option, - /// The gpu device that is being used. - pub device: &'a wgpu::Device, - pub queue: &'a wgpu::Queue, - pub(crate) buffer_writes: VecDeque, - renderpass_desc: Vec>, - /// The label of this Node. - pub label: RenderGraphLabelValue, -} - -impl<'a> RenderGraphContext<'a> { - pub(crate) fn new(device: &'a wgpu::Device, queue: &'a wgpu::Queue, encoder: Option, label: RenderGraphLabelValue) -> Self { - Self { - encoder, - device, - queue, - buffer_writes: Default::default(), - renderpass_desc: vec![], - label, - } - } - - pub fn begin_render_pass( - &'a mut self, - desc: wgpu::RenderPassDescriptor<'a, 'a>, - ) -> wgpu::RenderPass { - self.encoder - .as_mut() - .expect( - "RenderGraphContext is missing a command encoder. This is likely \ - because you are trying to run render commands in the prepare stage.", - ) - .begin_render_pass(&desc) - } - - pub fn begin_compute_pass(&mut self, desc: &wgpu::ComputePassDescriptor) -> wgpu::ComputePass { - self.encoder - .as_mut() - .expect( - "RenderGraphContext is missing a command encoder. This is likely \ - because you are trying to run render commands in the prepare stage.", - ) - .begin_compute_pass(desc) - } - - /// Queue a data write to a buffer at that is contained in `target_slot`. - /// - /// This does not submit the data to the GPU immediately, or add it to the `wgpu::Queue`. The - /// data will be submitted to the GPU queue right after the prepare stage for all passes - /// is ran. - #[instrument(skip(self, bytes), level="trace", fields(size = bytes.len()))] - pub fn queue_buffer_write(&mut self, target_slot: impl RenderGraphLabel, offset: u64, bytes: &[u8]) { - self.buffer_writes.push_back(GraphBufferWrite { - target_slot: target_slot.into(), - offset, - bytes: bytes.to_vec(), - }) - } - - /// Queue a data write of a type that to a buffer at that is contained in `target_slot`. - #[instrument(skip(self, bytes), level="trace", fields(size = std::mem::size_of::()))] - pub fn queue_buffer_write_with( - &mut self, - target_slot: impl RenderGraphLabel, - offset: u64, - bytes: T, - ) { - self.queue_buffer_write(target_slot, offset, bytemuck::bytes_of(&bytes)); - } -} +} \ No newline at end of file diff --git a/lyra-game/src/render/renderer.rs b/lyra-game/src/render/renderer.rs index b73a0b9..b2fda3f 100755 --- a/lyra-game/src/render/renderer.rs +++ b/lyra-game/src/render/renderer.rs @@ -125,20 +125,20 @@ impl BasicRenderer { let mut g = RenderGraph::new(device.clone(), queue.clone()); debug!("Adding base pass"); - g.add_pass(BasePassLabel, BasePass::new(surface, config)); + g.add_node(BasePassLabel, BasePass::new(surface, config)); debug!("Adding light base pass"); - g.add_pass(LightBasePassLabel, LightBasePass::new()); + g.add_node(LightBasePassLabel, LightBasePass::new()); debug!("Adding light cull compute pass"); - g.add_pass(LightCullComputePassLabel, LightCullComputePass::new(size)); + g.add_node(LightCullComputePassLabel, LightCullComputePass::new(size)); //debug!("Adding triangle pass"); - //g.add_pass(TrianglePass::new()); + //g.add_node(TrianglePass::new()); debug!("Adding mesh pass"); - g.add_pass(MeshesPassLabel, MeshPass::new()); + g.add_node(MeshesPassLabel, MeshPass::new()); debug!("Adding present pass"); let p = PresentPass::new(BasePassSlots::MainRenderTarget); - g.add_pass(p.label.clone(), p); + g.add_node(p.label.clone(), p); g.add_edge(BasePassLabel, LightBasePassLabel); g.add_edge(LightBasePassLabel, LightCullComputePassLabel);