render: create a node for sub render graphs, create a graph init node
This commit is contained in:
parent
9d3de88c50
commit
f755a4c53b
|
@ -123,6 +123,7 @@ pub struct RenderGraph {
|
||||||
queue: Rc<wgpu::Queue>,
|
queue: Rc<wgpu::Queue>,
|
||||||
slots: FxHashMap<RenderGraphLabelValue, ResourcedSlot>,
|
slots: FxHashMap<RenderGraphLabelValue, ResourcedSlot>,
|
||||||
nodes: FxHashMap<RenderGraphLabelValue, PassEntry>,
|
nodes: FxHashMap<RenderGraphLabelValue, PassEntry>,
|
||||||
|
sub_graphs: FxHashMap<RenderGraphLabelValue, RenderGraph>,
|
||||||
bind_groups: FxHashMap<RenderGraphLabelValue, BindGroupEntry>,
|
bind_groups: FxHashMap<RenderGraphLabelValue, BindGroupEntry>,
|
||||||
/// A directed graph used to determine dependencies of nodes.
|
/// A directed graph used to determine dependencies of nodes.
|
||||||
node_graph: petgraph::matrix_graph::DiMatrix<RenderGraphLabelValue, (), Option<()>, usize>,
|
node_graph: petgraph::matrix_graph::DiMatrix<RenderGraphLabelValue, (), Option<()>, usize>,
|
||||||
|
@ -135,6 +136,7 @@ impl RenderGraph {
|
||||||
queue,
|
queue,
|
||||||
slots: Default::default(),
|
slots: Default::default(),
|
||||||
nodes: Default::default(),
|
nodes: Default::default(),
|
||||||
|
sub_graphs: Default::default(),
|
||||||
bind_groups: Default::default(),
|
bind_groups: Default::default(),
|
||||||
node_graph: Default::default(),
|
node_graph: Default::default(),
|
||||||
}
|
}
|
||||||
|
@ -261,16 +263,27 @@ impl RenderGraph {
|
||||||
|
|
||||||
#[instrument(skip(self, world))]
|
#[instrument(skip(self, world))]
|
||||||
pub fn prepare(&mut self, world: &mut World) {
|
pub fn prepare(&mut self, world: &mut World) {
|
||||||
// prepare all passes
|
|
||||||
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.nodes.len() / 2);
|
buffer_writes.reserve(self.nodes.len() / 2);
|
||||||
|
|
||||||
for (label, pass) in &mut self.nodes {
|
let mut sorted: VecDeque<RenderGraphLabelValue> = petgraph::algo::toposort(&self.node_graph, None)
|
||||||
let mut context = RenderGraphContext::new(&self.device, &self.queue, None, label.clone());
|
.expect("RenderGraph had cycled!")
|
||||||
let mut inner = pass.inner.borrow_mut();
|
.iter()
|
||||||
inner.prepare(world, &mut context);
|
.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);
|
buffer_writes.append(&mut context.buffer_writes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -465,24 +478,33 @@ impl RenderGraph {
|
||||||
pass.set_bind_group(*index, bg, &[]);
|
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 {
|
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![])
|
NodeDesc::new(NodeType::Graph, None, vec![])
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prepare(&mut self, world: &mut World, _: &mut RenderGraphContext) {
|
fn prepare(&mut self, graph: &mut RenderGraph, world: &mut World, _: &mut RenderGraphContext) {
|
||||||
self.prepare(world);
|
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(
|
fn execute(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: &mut RenderGraph,
|
graph: &mut RenderGraph,
|
||||||
_: &NodeDesc,
|
_: &NodeDesc,
|
||||||
_: &mut RenderGraphContext,
|
_: &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();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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
|
/// This phase runs before `execute` and is meant to be used to collect data from the World
|
||||||
/// and write to GPU buffers.
|
/// 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.
|
/// Execute the node.
|
||||||
///
|
///
|
||||||
|
|
|
@ -9,8 +9,7 @@ use crate::{
|
||||||
render::{
|
render::{
|
||||||
camera::{CameraUniform, RenderCamera},
|
camera::{CameraUniform, RenderCamera},
|
||||||
graph::{
|
graph::{
|
||||||
RenderGraphContext, Node, NodeDesc, NodeSlot,
|
Node, NodeDesc, NodeSlot, NodeType, RenderGraph, RenderGraphContext, RenderTarget, SlotAttribute, SlotType, SlotValue
|
||||||
NodeType, RenderTarget, SlotAttribute, SlotType, SlotValue,
|
|
||||||
},
|
},
|
||||||
render_buffer::BufferWrapper, texture::RenderTexture,
|
render_buffer::BufferWrapper, texture::RenderTexture,
|
||||||
},
|
},
|
||||||
|
@ -147,7 +146,7 @@ impl Node for BasePass {
|
||||||
desc
|
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() {
|
if let Some(camera) = world.view_iter::<&mut CameraComponent>().next() {
|
||||||
let mut render_cam =
|
let mut render_cam =
|
||||||
RenderCamera::new(PhysicalSize::new(self.screen_size.x, self.screen_size.y));
|
RenderCamera::new(PhysicalSize::new(self.screen_size.x, self.screen_size.y));
|
||||||
|
|
|
@ -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,
|
||||||
|
) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,8 +2,7 @@ use lyra_game_derive::RenderGraphLabel;
|
||||||
|
|
||||||
use crate::render::{
|
use crate::render::{
|
||||||
graph::{
|
graph::{
|
||||||
RenderGraphContext, Node, NodeDesc, NodeType, SlotAttribute,
|
Node, NodeDesc, NodeType, RenderGraph, RenderGraphContext, SlotAttribute, SlotValue
|
||||||
SlotValue,
|
|
||||||
},
|
},
|
||||||
light::LightUniformBuffers,
|
light::LightUniformBuffers,
|
||||||
};
|
};
|
||||||
|
@ -58,7 +57,7 @@ impl Node for LightBasePass {
|
||||||
desc
|
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 tick = world.current_tick();
|
||||||
let lights = self.light_buffers.as_mut().unwrap();
|
let lights = self.light_buffers.as_mut().unwrap();
|
||||||
lights.update_lights(context.queue, tick, world);
|
lights.update_lights(context.queue, tick, world);
|
||||||
|
|
|
@ -7,7 +7,7 @@ use wgpu::util::DeviceExt;
|
||||||
|
|
||||||
use crate::render::{
|
use crate::render::{
|
||||||
graph::{
|
graph::{
|
||||||
Node, NodeDesc, NodeType, RenderGraphContext, SlotAttribute, SlotValue
|
Node, NodeDesc, NodeType, RenderGraph, RenderGraphContext, SlotAttribute, SlotValue
|
||||||
}, renderer::ScreenSize, resource::{ComputePipelineDescriptor, PipelineDescriptor, Shader}
|
}, renderer::ScreenSize, resource::{ComputePipelineDescriptor, PipelineDescriptor, Shader}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -215,7 +215,7 @@ impl Node for LightCullComputePass {
|
||||||
desc
|
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);
|
context.queue_buffer_write_with(LightCullComputePassSlots::IndexCounterBuffer, 0, 0);
|
||||||
|
|
||||||
let screen_size = world.get_resource::<ScreenSize>();
|
let screen_size = world.get_resource::<ScreenSize>();
|
||||||
|
|
|
@ -15,8 +15,7 @@ use wgpu::util::DeviceExt;
|
||||||
use crate::{
|
use crate::{
|
||||||
render::{
|
render::{
|
||||||
desc_buf_lay::DescVertexBufferLayout, graph::{
|
desc_buf_lay::DescVertexBufferLayout, graph::{
|
||||||
RenderGraphContext, Node, NodeDesc,
|
Node, NodeDesc, NodeType, RenderGraph, RenderGraphContext
|
||||||
NodeType,
|
|
||||||
}, 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
|
}, 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,
|
DeltaTime,
|
||||||
|
@ -297,8 +296,8 @@ impl Node for MeshPass {
|
||||||
desc
|
desc
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(skip(self, world, context))]
|
#[instrument(skip(self, _graph, world, context))]
|
||||||
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 device = context.device;
|
let device = context.device;
|
||||||
let queue = context.queue;
|
let queue = context.queue;
|
||||||
let render_limits = device.limits();
|
let render_limits = device.limits();
|
||||||
|
|
|
@ -12,3 +12,6 @@ pub use light_base::*;
|
||||||
|
|
||||||
mod present_pass;
|
mod present_pass;
|
||||||
pub use present_pass::*;
|
pub use present_pass::*;
|
||||||
|
|
||||||
|
mod init;
|
||||||
|
pub use init::*;
|
|
@ -2,7 +2,7 @@ use std::hash::Hash;
|
||||||
|
|
||||||
use lyra_game_derive::RenderGraphLabel;
|
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)]
|
#[derive(Debug, Clone, Hash, PartialEq, RenderGraphLabel)]
|
||||||
pub struct PresentPassLabel(RenderGraphLabelValue);
|
pub struct PresentPassLabel(RenderGraphLabelValue);
|
||||||
|
@ -50,7 +50,7 @@ impl Node for PresentPass {
|
||||||
desc
|
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) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue