render: create a node for sub render graphs, create a graph init node

This commit is contained in:
SeanOMik 2024-06-22 17:00:32 -04:00
parent 9d3de88c50
commit f755a4c53b
Signed by: SeanOMik
GPG Key ID: FEC9E2FC15235964
9 changed files with 83 additions and 28 deletions

View File

@ -123,6 +123,7 @@ pub struct RenderGraph {
queue: Rc<wgpu::Queue>,
slots: FxHashMap<RenderGraphLabelValue, ResourcedSlot>,
nodes: FxHashMap<RenderGraphLabelValue, PassEntry>,
sub_graphs: FxHashMap<RenderGraphLabelValue, RenderGraph>,
bind_groups: FxHashMap<RenderGraphLabelValue, BindGroupEntry>,
/// A directed graph used to determine dependencies of nodes.
node_graph: petgraph::matrix_graph::DiMatrix<RenderGraphLabelValue, (), Option<()>, usize>,
@ -135,6 +136,7 @@ impl RenderGraph {
queue,
slots: Default::default(),
nodes: Default::default(),
sub_graphs: Default::default(),
bind_groups: Default::default(),
node_graph: Default::default(),
}
@ -261,16 +263,27 @@ impl RenderGraph {
#[instrument(skip(self, world))]
pub fn prepare(&mut self, world: &mut World) {
// prepare all passes
let mut buffer_writes = VecDeque::<GraphBufferWrite>::new();
// reserve some buffer writes. not all nodes write so half the amount of them is probably
// fine.
buffer_writes.reserve(self.nodes.len() / 2);
for (label, pass) in &mut self.nodes {
let mut context = RenderGraphContext::new(&self.device, &self.queue, None, label.clone());
let mut inner = pass.inner.borrow_mut();
inner.prepare(world, &mut context);
let mut sorted: VecDeque<RenderGraphLabelValue> = petgraph::algo::toposort(&self.node_graph, None)
.expect("RenderGraph had cycled!")
.iter()
.map(|i| self.node_graph[i.clone()].clone())
.collect();
while let Some(pass_label) = sorted.pop_front() {
let pass = self.nodes.get(&pass_label).unwrap();
let device = self.device.clone();
let queue = self.queue.clone();
let inner = pass.inner.clone();
let mut inner = inner.borrow_mut();
let mut context = RenderGraphContext::new(&device, &queue, None, pass_label.clone());
inner.prepare(self, world, &mut context);
buffer_writes.append(&mut context.buffer_writes);
}
@ -465,24 +478,33 @@ impl RenderGraph {
pass.set_bind_group(*index, bg, &[]);
}
}
pub fn sub_graph_mut<L: Into<RenderGraphLabelValue>>(&mut self, label: L) -> Option<&mut RenderGraph> {
self.sub_graphs.get_mut(&label.into())
}
}
impl Node for RenderGraph {
pub struct SubGraphNode(RenderGraphLabelValue);
impl Node for SubGraphNode {
fn desc<'a, 'b>(&'a mut self, _: &'b mut RenderGraph) -> NodeDesc {
// TODO: how would bind groups be shared between sub-graphs?
NodeDesc::new(NodeType::Graph, None, vec![])
}
fn prepare(&mut self, world: &mut World, _: &mut RenderGraphContext) {
self.prepare(world);
fn prepare(&mut self, graph: &mut RenderGraph, world: &mut World, _: &mut RenderGraphContext) {
let sg = graph.sub_graph_mut(self.0.clone())
.unwrap_or_else(|| panic!("failed to find sub graph for SubGraphNode: {:?}", self.0));
sg.prepare(world);
}
fn execute(
&mut self,
_: &mut RenderGraph,
graph: &mut RenderGraph,
_: &NodeDesc,
_: &mut RenderGraphContext,
) {
self.render();
let sg = graph.sub_graph_mut(self.0.clone())
.unwrap_or_else(|| panic!("failed to find sub graph for SubGraphNode: {:?}", self.0));
sg.render();
}
}
}

View File

@ -351,7 +351,7 @@ pub trait Node: 'static {
///
/// This phase runs before `execute` and is meant to be used to collect data from the World
/// and write to GPU buffers.
fn prepare(&mut self, world: &mut World, context: &mut RenderGraphContext);
fn prepare(&mut self, graph: &mut RenderGraph, world: &mut World, context: &mut RenderGraphContext);
/// Execute the node.
///

View File

@ -9,8 +9,7 @@ use crate::{
render::{
camera::{CameraUniform, RenderCamera},
graph::{
RenderGraphContext, Node, NodeDesc, NodeSlot,
NodeType, RenderTarget, SlotAttribute, SlotType, SlotValue,
Node, NodeDesc, NodeSlot, NodeType, RenderGraph, RenderGraphContext, RenderTarget, SlotAttribute, SlotType, SlotValue
},
render_buffer::BufferWrapper, texture::RenderTexture,
},
@ -147,7 +146,7 @@ impl Node for BasePass {
desc
}
fn prepare(&mut self, world: &mut lyra_ecs::World, context: &mut RenderGraphContext) {
fn prepare(&mut self, _graph: &mut RenderGraph, world: &mut lyra_ecs::World, context: &mut RenderGraphContext) {
if let Some(camera) = world.view_iter::<&mut CameraComponent>().next() {
let mut render_cam =
RenderCamera::new(PhysicalSize::new(self.screen_size.x, self.screen_size.y));

View File

@ -0,0 +1,33 @@
use lyra_game_derive::RenderGraphLabel;
use crate::render::graph::{Node, NodeDesc, NodeSlot, NodeType};
#[derive(Debug, Default, Clone, Copy, Hash, RenderGraphLabel)]
pub struct InitNodeLabel;
pub struct InitNode {
slots: Vec<NodeSlot>,
}
impl Node for InitNode {
fn desc<'a, 'b>(&'a mut self, _: &'b mut crate::render::graph::RenderGraph) -> crate::render::graph::NodeDesc {
let mut desc = NodeDesc::new(NodeType::Node, None, vec![]);
// the slots can just be cloned since the slot attribute doesn't really matter much.
desc.slots = self.slots.clone();
desc
}
fn prepare(&mut self, _: &mut crate::render::graph::RenderGraph, _: &mut lyra_ecs::World, _: &mut crate::render::graph::RenderGraphContext) {
}
fn execute(
&mut self,
_: &mut crate::render::graph::RenderGraph,
_: &crate::render::graph::NodeDesc,
_: &mut crate::render::graph::RenderGraphContext,
) {
}
}

View File

@ -2,8 +2,7 @@ use lyra_game_derive::RenderGraphLabel;
use crate::render::{
graph::{
RenderGraphContext, Node, NodeDesc, NodeType, SlotAttribute,
SlotValue,
Node, NodeDesc, NodeType, RenderGraph, RenderGraphContext, SlotAttribute, SlotValue
},
light::LightUniformBuffers,
};
@ -58,7 +57,7 @@ impl Node for LightBasePass {
desc
}
fn prepare(&mut self, world: &mut lyra_ecs::World, context: &mut RenderGraphContext) {
fn prepare(&mut self, _graph: &mut RenderGraph, world: &mut lyra_ecs::World, context: &mut RenderGraphContext) {
let tick = world.current_tick();
let lights = self.light_buffers.as_mut().unwrap();
lights.update_lights(context.queue, tick, world);

View File

@ -7,7 +7,7 @@ use wgpu::util::DeviceExt;
use crate::render::{
graph::{
Node, NodeDesc, NodeType, RenderGraphContext, SlotAttribute, SlotValue
Node, NodeDesc, NodeType, RenderGraph, RenderGraphContext, SlotAttribute, SlotValue
}, renderer::ScreenSize, resource::{ComputePipelineDescriptor, PipelineDescriptor, Shader}
};
@ -215,7 +215,7 @@ impl Node for LightCullComputePass {
desc
}
fn prepare(&mut self, world: &mut World, context: &mut RenderGraphContext) {
fn prepare(&mut self, _graph: &mut RenderGraph, world: &mut World, context: &mut RenderGraphContext) {
context.queue_buffer_write_with(LightCullComputePassSlots::IndexCounterBuffer, 0, 0);
let screen_size = world.get_resource::<ScreenSize>();

View File

@ -15,8 +15,7 @@ use wgpu::util::DeviceExt;
use crate::{
render::{
desc_buf_lay::DescVertexBufferLayout, graph::{
RenderGraphContext, Node, NodeDesc,
NodeType,
Node, NodeDesc, NodeType, RenderGraph, RenderGraphContext
}, material::{Material, MaterialUniform}, render_buffer::{BufferStorage, BufferWrapper}, render_job::RenderJob, resource::{FragmentState, PipelineDescriptor, RenderPipelineDescriptor, Shader, VertexState}, texture::RenderTexture, transform_buffer_storage::{TransformBuffers, TransformGroup}, vertex::Vertex
},
DeltaTime,
@ -297,8 +296,8 @@ impl Node for MeshPass {
desc
}
#[instrument(skip(self, world, context))]
fn prepare(&mut self, world: &mut lyra_ecs::World, context: &mut RenderGraphContext) {
#[instrument(skip(self, _graph, world, context))]
fn prepare(&mut self, _graph: &mut RenderGraph, world: &mut lyra_ecs::World, context: &mut RenderGraphContext) {
let device = context.device;
let queue = context.queue;
let render_limits = device.limits();

View File

@ -11,4 +11,7 @@ mod light_base;
pub use light_base::*;
mod present_pass;
pub use present_pass::*;
pub use present_pass::*;
mod init;
pub use init::*;

View File

@ -2,7 +2,7 @@ use std::hash::Hash;
use lyra_game_derive::RenderGraphLabel;
use crate::render::graph::{RenderGraphContext, RenderGraphLabel, RenderGraphLabelValue, Node, NodeDesc, NodeSlot, NodeType, SlotAttribute, SlotType};
use crate::render::graph::{Node, NodeDesc, NodeSlot, NodeType, RenderGraph, RenderGraphContext, RenderGraphLabel, RenderGraphLabelValue, SlotAttribute, SlotType};
#[derive(Debug, Clone, Hash, PartialEq, RenderGraphLabel)]
pub struct PresentPassLabel(RenderGraphLabelValue);
@ -50,7 +50,7 @@ impl Node for PresentPass {
desc
}
fn prepare(&mut self, _world: &mut lyra_ecs::World, _context: &mut RenderGraphContext) {
fn prepare(&mut self, _graph: &mut RenderGraph, _world: &mut lyra_ecs::World, _context: &mut RenderGraphContext) {
}