render: rename RenderGraph::add_pass to add_node
This commit is contained in:
parent
5fc1a0f134
commit
f17bf40c77
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,6 +12,9 @@ pub use passes::*;
|
||||||
mod slot_desc;
|
mod slot_desc;
|
||||||
pub use slot_desc::*;
|
pub use slot_desc::*;
|
||||||
|
|
||||||
|
mod context;
|
||||||
|
pub use context::*;
|
||||||
|
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use tracing::{debug_span, instrument, trace, warn};
|
use tracing::{debug_span, instrument, trace, warn};
|
||||||
use wgpu::ComputePass;
|
use wgpu::ComputePass;
|
||||||
|
@ -121,8 +124,8 @@ pub struct RenderGraph {
|
||||||
slots: FxHashMap<RenderGraphLabelValue, ResourcedSlot>,
|
slots: FxHashMap<RenderGraphLabelValue, ResourcedSlot>,
|
||||||
nodes: FxHashMap<RenderGraphLabelValue, PassEntry>,
|
nodes: FxHashMap<RenderGraphLabelValue, PassEntry>,
|
||||||
bind_groups: FxHashMap<RenderGraphLabelValue, BindGroupEntry>,
|
bind_groups: FxHashMap<RenderGraphLabelValue, BindGroupEntry>,
|
||||||
/// A directed graph describing the execution path of the RenderGraph
|
/// A directed graph used to determine dependencies of nodes.
|
||||||
execution_graph: petgraph::matrix_graph::DiMatrix<RenderGraphLabelValue, (), Option<()>, usize>,
|
node_graph: petgraph::matrix_graph::DiMatrix<RenderGraphLabelValue, (), Option<()>, usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RenderGraph {
|
impl RenderGraph {
|
||||||
|
@ -133,7 +136,7 @@ impl RenderGraph {
|
||||||
slots: Default::default(),
|
slots: Default::default(),
|
||||||
nodes: Default::default(),
|
nodes: Default::default(),
|
||||||
bind_groups: 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.
|
/// 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.
|
/// 3. Ensuring that no two slots share the same ID when the names do not match.
|
||||||
#[instrument(skip(self, pass), level = "debug")]
|
#[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);
|
let mut desc = pass.desc(self);
|
||||||
|
|
||||||
// collect all the slots of the pass
|
// collect all the slots of the pass
|
||||||
|
@ -203,7 +206,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.node_graph.add_node(label.clone());
|
||||||
|
|
||||||
self.nodes.insert(
|
self.nodes.insert(
|
||||||
label,
|
label,
|
||||||
|
@ -296,10 +299,10 @@ impl RenderGraph {
|
||||||
|
|
||||||
#[instrument(skip(self))]
|
#[instrument(skip(self))]
|
||||||
pub fn render(&mut 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!")
|
.expect("RenderGraph had cycled!")
|
||||||
.iter()
|
.iter()
|
||||||
.map(|i| self.execution_graph[i.clone()].clone())
|
.map(|i| self.node_graph[i.clone()].clone())
|
||||||
.collect();
|
.collect();
|
||||||
//debug!("Render graph execution order: {:?}", sorted);
|
//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");
|
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.
|
/// Utility method for setting the bind groups for a pass.
|
||||||
|
@ -462,88 +465,4 @@ impl RenderGraph {
|
||||||
pass.set_bind_group(*index, bg, &[]);
|
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<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));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -125,20 +125,20 @@ impl BasicRenderer {
|
||||||
let mut g = RenderGraph::new(device.clone(), queue.clone());
|
let mut g = RenderGraph::new(device.clone(), queue.clone());
|
||||||
|
|
||||||
debug!("Adding base pass");
|
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");
|
debug!("Adding light base pass");
|
||||||
g.add_pass(LightBasePassLabel, LightBasePass::new());
|
g.add_node(LightBasePassLabel, LightBasePass::new());
|
||||||
debug!("Adding light cull compute pass");
|
debug!("Adding light cull compute pass");
|
||||||
g.add_pass(LightCullComputePassLabel, LightCullComputePass::new(size));
|
g.add_node(LightCullComputePassLabel, LightCullComputePass::new(size));
|
||||||
//debug!("Adding triangle pass");
|
//debug!("Adding triangle pass");
|
||||||
//g.add_pass(TrianglePass::new());
|
//g.add_node(TrianglePass::new());
|
||||||
|
|
||||||
debug!("Adding mesh pass");
|
debug!("Adding mesh pass");
|
||||||
g.add_pass(MeshesPassLabel, MeshPass::new());
|
g.add_node(MeshesPassLabel, MeshPass::new());
|
||||||
|
|
||||||
debug!("Adding present pass");
|
debug!("Adding present pass");
|
||||||
let p = PresentPass::new(BasePassSlots::MainRenderTarget);
|
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(BasePassLabel, LightBasePassLabel);
|
||||||
g.add_edge(LightBasePassLabel, LightCullComputePassLabel);
|
g.add_edge(LightBasePassLabel, LightCullComputePassLabel);
|
||||||
|
|
Loading…
Reference in New Issue