render: rename RenderGraph::add_pass to add_node

This commit is contained in:
SeanOMik 2024-06-21 21:58:40 -04:00
parent 5fc1a0f134
commit f17bf40c77
Signed by: SeanOMik
GPG Key ID: FEC9E2FC15235964
3 changed files with 107 additions and 99 deletions

View File

@ -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<u8>,
}
#[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<wgpu::CommandEncoder>,
/// The gpu device that is being used.
pub device: &'a wgpu::Device,
pub queue: &'a wgpu::Queue,
pub(crate) buffer_writes: VecDeque<GraphBufferWrite>,
renderpass_desc: Vec<wgpu::RenderPassDescriptor<'a, 'a>>,
/// 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<wgpu::CommandEncoder>, 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::<T>()))]
pub fn queue_buffer_write_with<T: bytemuck::NoUninit>(
&mut self,
target_slot: impl RenderGraphLabel,
offset: u64,
bytes: T,
) {
self.queue_buffer_write(target_slot, offset, bytemuck::bytes_of(&bytes));
}
}

View File

@ -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<RenderGraphLabelValue, ResourcedSlot>,
nodes: FxHashMap<RenderGraphLabelValue, PassEntry>,
bind_groups: FxHashMap<RenderGraphLabelValue, BindGroupEntry>,
/// A directed graph describing the execution path of the RenderGraph
execution_graph: petgraph::matrix_graph::DiMatrix<RenderGraphLabelValue, (), Option<()>, usize>,
/// A directed graph used to determine dependencies of nodes.
node_graph: petgraph::matrix_graph::DiMatrix<RenderGraphLabelValue, (), Option<()>, 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<P: Node>(&mut self, label: impl RenderGraphLabel, mut pass: P) {
pub fn add_node<P: 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<RenderGraphLabelValue> = petgraph::algo::toposort(&self.execution_graph, None)
let mut sorted: VecDeque<RenderGraphLabelValue> = 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.
@ -463,87 +466,3 @@ impl RenderGraph {
}
}
}
/// 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<u8>,
}
#[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<wgpu::CommandEncoder>,
/// The gpu device that is being used.
pub device: &'a wgpu::Device,
pub queue: &'a wgpu::Queue,
pub(crate) buffer_writes: VecDeque<GraphBufferWrite>,
renderpass_desc: Vec<wgpu::RenderPassDescriptor<'a, 'a>>,
/// 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<wgpu::CommandEncoder>, 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::<T>()))]
pub fn queue_buffer_write_with<T: bytemuck::NoUninit>(
&mut self,
target_slot: impl RenderGraphLabel,
offset: u64,
bytes: T,
) {
self.queue_buffer_write(target_slot, offset, bytemuck::bytes_of(&bytes));
}
}

View File

@ -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);