From 28b9604189024115e1cd3319710db8c127b0fcb2 Mon Sep 17 00:00:00 2001 From: SeanOMik Date: Thu, 6 Jun 2024 19:37:25 -0400 Subject: [PATCH] render: rename RenderGraphPass to Node to better represent what it actually is in the RenderGraph A node wont always render or compute, so it wouldn't actually be a pass. Calling it a node is a better representation of what it actually is --- Cargo.lock | 7 + lyra-game/Cargo.toml | 1 + lyra-game/src/render/graph/mod.rs | 49 +++-- .../src/render/graph/{pass.rs => node.rs} | 170 ++++++++++++------ lyra-game/src/render/graph/passes/base.rs | 16 +- .../src/render/graph/passes/depth_prepass.rs | 94 ---------- .../src/render/graph/passes/light_base.rs | 12 +- .../render/graph/passes/light_cull_compute.rs | 12 +- lyra-game/src/render/graph/passes/meshes.rs | 20 ++- .../src/render/graph/passes/present_pass.rs | 14 +- 10 files changed, 191 insertions(+), 204 deletions(-) rename lyra-game/src/render/graph/{pass.rs => node.rs} (57%) delete mode 100644 lyra-game/src/render/graph/passes/depth_prepass.rs diff --git a/Cargo.lock b/Cargo.lock index a2362f3..b5960e5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -384,6 +384,12 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +[[package]] +name = "bind_match" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "171f0236f66c7be99f32060539c2bade94033ded356ecf4c9dc9b1e6198326cd" + [[package]] name = "bit-set" version = "0.5.3" @@ -1859,6 +1865,7 @@ dependencies = [ "anyhow", "async-std", "async-trait", + "bind_match", "bytemuck", "cfg-if", "gilrs-core", diff --git a/lyra-game/Cargo.toml b/lyra-game/Cargo.toml index efba477..bc28133 100644 --- a/lyra-game/Cargo.toml +++ b/lyra-game/Cargo.toml @@ -37,6 +37,7 @@ thiserror = "1.0.56" unique = "0.9.1" rustc-hash = "1.1.0" petgraph = { version = "0.6.5", features = ["matrix_graph"] } +bind_match = "0.1.2" [features] tracy = ["dep:tracing-tracy"] diff --git a/lyra-game/src/render/graph/mod.rs b/lyra-game/src/render/graph/mod.rs index 27b71c4..9e99897 100644 --- a/lyra-game/src/render/graph/mod.rs +++ b/lyra-game/src/render/graph/mod.rs @@ -1,11 +1,11 @@ -mod pass; +mod node; use std::{ cell::RefCell, collections::{HashMap, VecDeque}, fmt::Debug, hash::Hash, rc::Rc, sync::Arc }; use itertools::Itertools; use lyra_ecs::World; -pub use pass::*; +pub use node::*; mod passes; pub use passes::*; @@ -76,8 +76,8 @@ impl PartialEq for RenderGraphLabelValue { impl Eq for RenderGraphLabelValue {} struct PassEntry { - inner: Arc>, - desc: Arc, + inner: Arc>, + desc: Arc, /// The index of the pass in the execution graph graph_index: petgraph::matrix_graph::NodeIndex, } @@ -165,8 +165,18 @@ impl RenderGraph { self.slot_label_lookup.get(&label.rc_clone().into()).cloned() } + /// Add a [`Node`] to the RenderGraph. + /// + /// When the node is added, its [`Node::desc`] method will be executed. + /// + /// Additionally, all [`Slot`](node::NodeSlot)s of the node will be iterated, + /// 1. Ensuring that there are no two slots of the same name, with different value types + /// 2. Changing the id of insert slots to match the id of the output slot of the same name. + /// * This means that the id of insert slots **ARE NOT STABLE**. **DO NOT** rely on them to + /// 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, mut pass: P) { + pub fn add_pass(&mut self, mut pass: P) { let mut desc = pass.desc(self); // collect all the slots of the pass @@ -234,25 +244,28 @@ impl RenderGraph { } /// Creates all buffers required for the passes, also creates an internal execution path. + /// + /// This only needs to be ran when the [`Node`]s in the graph change, or they are removed or + /// added. #[instrument(skip(self, device))] pub fn setup(&mut self, device: &wgpu::Device) { // For all passes, create their pipelines for pass in self.passes.values() { if let Some(pipeline_desc) = &pass.desc.pipeline_desc { - let pipeline = match pass.desc.pass_type { - RenderPassType::Render => Pipeline::Render(RenderPipeline::create( + let pipeline = match pass.desc.ty { + NodeType::Render => Pipeline::Render(RenderPipeline::create( device, pipeline_desc .as_render_pipeline_descriptor() .expect("got compute pipeline descriptor in a render pass"), )), - RenderPassType::Compute => Pipeline::Compute(ComputePipeline::create( + NodeType::Compute => Pipeline::Compute(ComputePipeline::create( device, pipeline_desc .as_compute_pipeline_descriptor() .expect("got render pipeline descriptor in a compute pass"), )), - RenderPassType::Presenter | RenderPassType::Node => { + NodeType::Presenter | NodeType::Node => { panic!("Present or Node RenderGraph passes should not have a pipeline descriptor!"); } }; @@ -319,7 +332,7 @@ impl RenderGraph { let label = format!("{:?} Encoder", pass_desc.label); // encoders are not needed for presenter nodes. - let encoder = if pass_desc.pass_type.should_have_pipeline() { + let encoder = if pass_desc.ty.should_have_pipeline() { Some( self.device .create_command_encoder(&wgpu::CommandEncoderDescriptor { @@ -336,7 +349,7 @@ impl RenderGraph { let mut context = RenderGraphContext::new(&device, &queue, encoder); // all encoders need to be submitted before a presenter node is executed. - if pass_desc.pass_type == RenderPassType::Presenter { + if pass_desc.ty == NodeType::Presenter { trace!("Submitting {} encoderd before presenting", encoders.len()); self.queue.submit(encoders.drain(..)); } @@ -369,7 +382,7 @@ impl RenderGraph { self.slots.get_mut(&id).map(|s| &mut s.value) } - pub fn pass(&self, id: u64) -> Option<&RenderGraphPassDesc> { + pub fn pass(&self, id: u64) -> Option<&NodeDesc> { self.passes.get(&id).map(|s| &*s.desc) } @@ -438,13 +451,13 @@ impl RenderGraph { /// graph.set_bind_groups( /// &mut pass, /// &[ - /// // retrieves the "depth_texture" bind group and sets the index 0 in the + /// // retrieves the `BasePassSlots::DepthTexture` bind group and sets the index 0 in the /// // pass to it. - /// ("depth_texture", 0), - /// ("camera", 1), - /// ("light_buffers", 2), - /// ("light_indices_grid", 3), - /// ("screen_size", 4), + /// (&BasePassSlots::DepthTexture, 0), + /// (&BasePassSlots::Camera, 1), + /// (&LightBasePassSlots::Lights, 2), + /// (&LightCullComputePassSlots::LightIndicesGridGroup, 3), + /// (&BasePassSlots::ScreenSize, 4), /// ], /// ); /// ``` diff --git a/lyra-game/src/render/graph/pass.rs b/lyra-game/src/render/graph/node.rs similarity index 57% rename from lyra-game/src/render/graph/pass.rs rename to lyra-game/src/render/graph/node.rs index 6c0f7bb..db45f02 100644 --- a/lyra-game/src/render/graph/pass.rs +++ b/lyra-game/src/render/graph/node.rs @@ -1,5 +1,6 @@ use std::{cell::{Ref, RefCell, RefMut}, collections::HashMap, num::NonZeroU32, rc::Rc}; +use bind_match::bind_match; use lyra_ecs::World; use crate::render::resource::PipelineDescriptor; @@ -7,26 +8,31 @@ use crate::render::resource::PipelineDescriptor; use super::{RenderGraph, RenderGraphContext, RenderGraphLabel, RenderGraphLabelValue, RenderTarget}; #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default)] -pub enum RenderPassType { +pub enum NodeType { /// A node doesn't render, compute, or present anything. This likely means it injects data into the graph. - Node, - Compute, #[default] + Node, + /// A Compute pass node type. + Compute, + /// A render pass node type. Render, + /// A node that presents render results to a render target. Presenter, } -impl RenderPassType { +impl NodeType { + /// Returns a boolean indicating if the node should have a [`Pipeline`](crate::render::resource::Pipeline). pub fn should_have_pipeline(&self) -> bool { match self { - RenderPassType::Node => false, - RenderPassType::Compute => true, - RenderPassType::Render => true, - RenderPassType::Presenter => false, + NodeType::Node => false, + NodeType::Compute => true, + NodeType::Render => true, + NodeType::Presenter => false, } } } +/// The type of data that is stored in a [`Node`] slot. #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] pub enum SlotType { TextureView, @@ -36,10 +42,13 @@ pub enum SlotType { RenderTarget, } +/// The value of a slot in a [`Node`]. #[derive(Debug, Clone)] pub enum SlotValue { + /// This slot doesn't have any value None, - /// The value will be set during a later phase of the render graph. + /// The value will be set during a later phase of the render graph. To see the type of value + /// this will be set to, see the slots type. Lazy, TextureView(Rc), Sampler(Rc), @@ -49,56 +58,51 @@ pub enum SlotValue { } impl SlotValue { - /// Gets `self` as a texture, panics if self is not a instance of [`SlotValue::Texture`]. - pub fn as_texture(&self) -> &wgpu::Texture { - match self { - Self::Texture(v) => v, - _ => panic!("self is not an instance of SlotValue::Texture"), - } + pub fn as_texture_view(&self) -> Option<&Rc> { + bind_match!(self, Self::TextureView(v) => v) } - pub fn as_texture_view(&self) -> &wgpu::TextureView { - match self { - Self::TextureView(v) => v, - _ => panic!("self is not an instance of SlotValue::TextureView"), - } + pub fn as_sampler(&self) -> Option<&Rc> { + bind_match!(self, Self::Sampler(v) => v) } - pub fn as_buffer(&self) -> Option<&wgpu::Buffer> { - match self { - Self::Buffer(v) => Some(v), - _ => None, - } + pub fn as_texture(&self) -> Option<&Rc> { + bind_match!(self, Self::Texture(v) => v) + } + + pub fn as_buffer(&self) -> Option<&Rc> { + bind_match!(self, Self::Buffer(v) => v) } pub fn as_render_target(&self) -> Option> { - match self { - Self::RenderTarget(v) => Some(v.borrow()), - _ => None, - } + bind_match!(self, Self::RenderTarget(v) => v.borrow()) } pub fn as_render_target_mut(&mut self) -> Option> { - match self { - Self::RenderTarget(v) => Some(v.borrow_mut()), - _ => None, - } + bind_match!(self, Self::RenderTarget(v) => v.borrow_mut()) } } #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] pub enum SlotAttribute { + /// This slot inputs a value into the node, expecting another node to `Output` it. Input, + /// This slot outputs a value from the node, providing the value to other nodes that + /// `Input`it. Output, } #[derive(Clone)] -pub struct RenderPassSlot { +pub struct NodeSlot { + /// The type of the value that this slot inputs/outputs. pub ty: SlotType, + /// The way this slot uses the value. Defines if this slot is an output or input. pub attribute: SlotAttribute, + // What if these are just completely removed and labels are used everywhere instead? pub id: u64, + /// The identifying label of this slot. pub label: RenderGraphLabelValue, - /// The descriptor of the slot value. - /// This will be `None` if this slot is an input. + /// The value of the slot. + /// This is `None` if the slot is a `SlotAttribute::Input` type. pub value: Option, } @@ -157,13 +161,23 @@ impl RenderGraphPipelineInfo { } } -pub struct RenderGraphPassDesc { +/// Descriptor of a Node in a [`RenderGraph`]. +pub struct NodeDesc { pub id: u64, + /// The label of the Node, used to identify the Node. pub label: RenderGraphLabelValue, - pub pass_type: RenderPassType, - pub slots: Vec, + /// The [`NodeType`] of the node. + pub ty: NodeType, + /// The slots that the Node uses. + /// This defines the resources that the node uses and creates in the graph. + pub slots: Vec, slot_label_lookup: HashMap, + /// An optional pipeline descriptor for the Node. + /// This is `None` if the Node type is not a node that requires a pipeline + /// (see [`NodeType::should_have_pipeline`]). pub pipeline_desc: Option, + /// The bind groups that this Node creates. + /// This makes the bind groups accessible to other Nodes. pub bind_groups: Vec<( RenderGraphLabelValue, Rc, @@ -171,18 +185,19 @@ pub struct RenderGraphPassDesc { )>, } -impl RenderGraphPassDesc { +impl NodeDesc { + /// Create a new node descriptor. pub fn new( id: u64, label: L, - pass_type: RenderPassType, + pass_type: NodeType, pipeline_desc: Option, bind_groups: Vec<(&dyn RenderGraphLabel, Rc, Option>)>, ) -> Self { Self { id, label: label.into(), - pass_type, + ty: pass_type, slots: vec![], slot_label_lookup: HashMap::default(), pipeline_desc, @@ -193,7 +208,11 @@ impl RenderGraphPassDesc { } } - pub fn add_slot(&mut self, slot: RenderPassSlot) { + /// Add a slot to the descriptor. + /// + /// In debug builds, there is an assert that triggers if the slot is an input slot and has + /// a value set. + pub fn add_slot(&mut self, slot: NodeSlot) { debug_assert!( !(slot.attribute == SlotAttribute::Input && slot.value.is_some()), "input slots should not have values" @@ -203,6 +222,11 @@ impl RenderGraphPassDesc { self.slots.push(slot); } + /// Add a buffer slot to the descriptor. + /// + /// In debug builds, there is an assert that triggers if the slot is an input slot and has + /// a value set. There is also an assert that is triggered if this slot value is not `None`, + /// `SlotValue::Lazy` or a `Buffer`. #[inline(always)] pub fn add_buffer_slot( &mut self, @@ -216,7 +240,7 @@ impl RenderGraphPassDesc { "slot value is not a buffer" ); - let slot = RenderPassSlot { + let slot = NodeSlot { id, label: label.into(), ty: SlotType::Buffer, @@ -226,6 +250,11 @@ impl RenderGraphPassDesc { self.add_slot(slot); } + /// Add a slot that stores a [`wgpu::Texture`] to the descriptor. + /// + /// In debug builds, there is an assert that triggers if the slot is an input slot and has + /// a value set. There is also an assert that is triggered if this slot value is not `None`, + /// `SlotValue::Lazy` or a `SlotValue::Texture`. #[inline(always)] pub fn add_texture_slot( &mut self, @@ -239,7 +268,7 @@ impl RenderGraphPassDesc { "slot value is not a texture" ); - let slot = RenderPassSlot { + let slot = NodeSlot { id, label: label.into(), ty: SlotType::Texture, @@ -249,6 +278,11 @@ impl RenderGraphPassDesc { self.add_slot(slot); } + /// Add a slot that stores a [`wgpu::TextureView`] to the descriptor. + /// + /// In debug builds, there is an assert that triggers if the slot is an input slot and has + /// a value set. There is also an assert that is triggered if this slot value is not `None`, + /// `SlotValue::Lazy` or a `SlotValue::TextureView`. #[inline(always)] pub fn add_texture_view_slot( &mut self, @@ -262,7 +296,7 @@ impl RenderGraphPassDesc { "slot value is not a texture view" ); - let slot = RenderPassSlot { + let slot = NodeSlot { id, label: label.into(), ty: SlotType::TextureView, @@ -272,6 +306,11 @@ impl RenderGraphPassDesc { self.add_slot(slot); } + /// Add a slot that stores a [`wgpu::Sampler`] to the descriptor. + /// + /// In debug builds, there is an assert that triggers if the slot is an input slot and has + /// a value set. There is also an assert that is triggered if this slot value is not `None`, + /// `SlotValue::Lazy` or a `SlotValue::Sampler`. #[inline(always)] pub fn add_sampler_slot( &mut self, @@ -285,7 +324,7 @@ impl RenderGraphPassDesc { "slot value is not a sampler" ); - let slot = RenderPassSlot { + let slot = NodeSlot { id, label: label.into(), ty: SlotType::Sampler, @@ -295,14 +334,16 @@ impl RenderGraphPassDesc { self.add_slot(slot); } - pub fn input_slots(&self) -> Vec<&RenderPassSlot> { + /// Returns all input slots that the descriptor defines. + pub fn input_slots(&self) -> Vec<&NodeSlot> { self.slots .iter() .filter(|s| s.attribute == SlotAttribute::Input) .collect() } - - pub fn output_slots(&self) -> Vec<&RenderPassSlot> { + + /// Returns all output slots that the descriptor defines. + pub fn output_slots(&self) -> Vec<&NodeSlot> { self.slots .iter() .filter(|s| s.attribute == SlotAttribute::Output) @@ -310,17 +351,34 @@ impl RenderGraphPassDesc { } } -pub trait RenderGraphPass: 'static { - /// Create a render pass describer. - /// - /// The `id` argument is passed as mutable so you can increment it as you use it for new slots. - fn desc<'a, 'b>(&'a mut self, graph: &'b mut RenderGraph) -> RenderGraphPassDesc; +/// A node that can be executed and scheduled in a [`RenderGraph`]. +/// +/// A node can be used for rendering, computing data on the GPU, collecting data from the main +/// world and writing it to GPU buffers, or presenting renders to a surface. +/// +/// The [`RenderGraph`] is ran in phases. The first phase is `prepare`, then `execute`. When a node +/// is first added to a RenderGraph, its [`Node::desc`] function will be ran. The descriptor +/// describes all resources the node requires for execution during the `execute` phase. +pub trait Node: 'static { + /// Retrieve a descriptor of the Node. + fn desc<'a, 'b>(&'a mut self, graph: &'b mut RenderGraph) -> NodeDesc; + /// Prepare the node for rendering. + /// + /// 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); + + /// Execute the node. + /// + /// Parameters: + /// * `graph` - The RenderGraph that this node is a part of. Can be used to get bind groups and bind to them. + /// * `desc` - The descriptor of this node. + /// * `context` - The rendering graph context. fn execute( &mut self, graph: &mut RenderGraph, - desc: &RenderGraphPassDesc, + desc: &NodeDesc, context: &mut RenderGraphContext, ); } diff --git a/lyra-game/src/render/graph/passes/base.rs b/lyra-game/src/render/graph/passes/base.rs index ebb6d94..cfe8877 100644 --- a/lyra-game/src/render/graph/passes/base.rs +++ b/lyra-game/src/render/graph/passes/base.rs @@ -9,8 +9,8 @@ use crate::{ render::{ camera::{CameraUniform, RenderCamera}, graph::{ - RenderGraphContext, RenderGraphPass, RenderGraphPassDesc, RenderPassSlot, - RenderPassType, RenderTarget, SlotAttribute, SlotType, SlotValue, + RenderGraphContext, Node, NodeDesc, NodeSlot, + NodeType, RenderTarget, SlotAttribute, SlotType, SlotValue, }, render_buffer::BufferWrapper, texture::RenderTexture, }, @@ -61,11 +61,11 @@ impl BasePass { } } -impl RenderGraphPass for BasePass { +impl Node for BasePass { fn desc( &mut self, graph: &mut crate::render::graph::RenderGraph, - ) -> crate::render::graph::RenderGraphPassDesc { + ) -> crate::render::graph::NodeDesc { let render_target = self.temp_render_target.take().unwrap(); self.screen_size = UVec2::new( render_target.surface_config.width, @@ -101,10 +101,10 @@ impl RenderGraphPass for BasePass { let depth_texture_bgl = dt_bg_pair.layout; let depth_texture_view = Rc::new(depth_texture.view); - let mut desc = RenderGraphPassDesc::new( + let mut desc = NodeDesc::new( graph.next_id(), BasePassLabel, - RenderPassType::Node, + NodeType::Node, None, vec![ // TODO: Make this a trait maybe? @@ -120,7 +120,7 @@ impl RenderGraphPass for BasePass { ); self.main_rt_id = graph.next_id(); - desc.add_slot(RenderPassSlot { + desc.add_slot(NodeSlot { ty: SlotType::RenderTarget, attribute: SlotAttribute::Output, id: self.main_rt_id, @@ -173,7 +173,7 @@ impl RenderGraphPass for BasePass { fn execute( &mut self, graph: &mut crate::render::graph::RenderGraph, - _desc: &crate::render::graph::RenderGraphPassDesc, + _desc: &crate::render::graph::NodeDesc, context: &mut crate::render::graph::RenderGraphContext, ) { let tv_slot = graph diff --git a/lyra-game/src/render/graph/passes/depth_prepass.rs b/lyra-game/src/render/graph/passes/depth_prepass.rs deleted file mode 100644 index 85f654c..0000000 --- a/lyra-game/src/render/graph/passes/depth_prepass.rs +++ /dev/null @@ -1,94 +0,0 @@ -use glam::UVec2; - -use crate::render::{ - camera::CameraUniform, - graph::{ - BufferInitDescriptor, RenderGraphPass, RenderGraphPassDesc, RenderPassType, SamplerDescriptor, SlotAttribute, SlotDescriptor, TextureDescriptor, TextureViewDescriptor - }, -}; - -/// Supplies some basic things other passes needs. -/// -/// screen size buffer, camera buffer, -#[derive(Default)] -pub struct DepthPrePass; - -impl DepthPrePass { - pub fn new() -> Self { - Self::default() - } -} - -impl RenderGraphPass for DepthPrePass { - fn desc( - &self, - graph: &mut crate::render::graph::RenderGraph, - id: &mut u64, - ) -> crate::render::graph::RenderGraphPassDesc { - let mut desc = RenderGraphPassDesc::new(*id, "DepthPrePass", RenderPassType::Compute); - *id += 1; - - let size = wgpu::Extent3d { - width: graph.surface_config.width, - height: graph.surface_config.height, - depth_or_array_layers: 1, - }; - - desc.add_texture_slot( - *id, - "depth_texture", - SlotAttribute::Output, - Some(SlotDescriptor::Texture(TextureDescriptor { - size, - mip_level_count: 1, - sample_count: 1, - dimension: wgpu::TextureDimension::D2, - format: wgpu::TextureFormat::Depth32Float, - usage: wgpu::TextureUsages::RENDER_ATTACHMENT - | wgpu::TextureUsages::TEXTURE_BINDING, - view_formats: vec![], - })), - ); - *id += 1; - - desc.add_texture_view_slot( - *id, - "depth_texture_view", - SlotAttribute::Output, - Some(SlotDescriptor::TextureView(TextureViewDescriptor::default_view("depth_texture"))), - ); - *id += 1; - - desc.add_texture_view_slot( - *id, - "depth_texture_sampler", - SlotAttribute::Output, - Some(SlotDescriptor::Sampler(SamplerDescriptor { - mag_filter: wgpu::FilterMode::Linear, - min_filter: wgpu::FilterMode::Linear, - compare: Some(wgpu::CompareFunction::LessEqual), - lod_min_clamp: 0.0, - lod_max_clamp: 100.0, - ..SamplerDescriptor::default_sampler("depth_texture") - })), - ); - *id += 1; - - desc - } - - fn prepare(&mut self, world: &mut lyra_ecs::World) { - let _ = world; - todo!() - } - - fn execute( - &mut self, - graph: &mut crate::render::graph::RenderGraph, - desc: &crate::render::graph::RenderGraphPassDesc, - context: &mut crate::render::graph::RenderGraphContext, - ) { - let _ = (graph, desc, context); - todo!() - } -} diff --git a/lyra-game/src/render/graph/passes/light_base.rs b/lyra-game/src/render/graph/passes/light_base.rs index b5176a4..31e7af3 100644 --- a/lyra-game/src/render/graph/passes/light_base.rs +++ b/lyra-game/src/render/graph/passes/light_base.rs @@ -2,7 +2,7 @@ use lyra_game_derive::RenderGraphLabel; use crate::render::{ graph::{ - RenderGraphContext, RenderGraphPass, RenderGraphPassDesc, RenderPassType, SlotAttribute, + RenderGraphContext, Node, NodeDesc, NodeType, SlotAttribute, SlotValue, }, light::LightUniformBuffers, @@ -30,19 +30,19 @@ impl LightBasePass { } } -impl RenderGraphPass for LightBasePass { +impl Node for LightBasePass { fn desc( &mut self, graph: &mut crate::render::graph::RenderGraph, - ) -> crate::render::graph::RenderGraphPassDesc { + ) -> crate::render::graph::NodeDesc { let device = &graph.device; self.light_buffers = Some(LightUniformBuffers::new(device)); let light_buffers = self.light_buffers.as_ref().unwrap(); - let mut desc = RenderGraphPassDesc::new( + let mut desc = NodeDesc::new( graph.next_id(), LightBasePassLabel, - RenderPassType::Node, + NodeType::Node, None, vec![( &LightBasePassSlots::Lights, @@ -70,7 +70,7 @@ impl RenderGraphPass for LightBasePass { fn execute( &mut self, _graph: &mut crate::render::graph::RenderGraph, - _desc: &crate::render::graph::RenderGraphPassDesc, + _desc: &crate::render::graph::NodeDesc, _context: &mut crate::render::graph::RenderGraphContext, ) { } diff --git a/lyra-game/src/render/graph/passes/light_cull_compute.rs b/lyra-game/src/render/graph/passes/light_cull_compute.rs index 41ca789..dec5d74 100644 --- a/lyra-game/src/render/graph/passes/light_cull_compute.rs +++ b/lyra-game/src/render/graph/passes/light_cull_compute.rs @@ -6,7 +6,7 @@ use wgpu::util::DeviceExt; use crate::render::{ graph::{ - RenderGraphContext, RenderGraphPass, RenderGraphPassDesc, RenderPassType, SlotAttribute, + RenderGraphContext, Node, NodeDesc, NodeType, SlotAttribute, SlotValue, }, resource::{ComputePipelineDescriptor, PipelineDescriptor, Shader}, @@ -37,11 +37,11 @@ impl LightCullComputePass { } } -impl RenderGraphPass for LightCullComputePass { +impl Node for LightCullComputePass { fn desc( &mut self, graph: &mut crate::render::graph::RenderGraph, - ) -> crate::render::graph::RenderGraphPassDesc { + ) -> crate::render::graph::NodeDesc { let shader = Rc::new(Shader { label: Some("light_cull_comp_shader".into()), source: include_str!("../../shaders/light_cull.comp.wgsl").to_string(), @@ -176,10 +176,10 @@ impl RenderGraphPass for LightCullComputePass { let lights_bgl = graph.bind_group_layout(graph.bind_group_id(&LightBasePassSlots::Lights).unwrap()); let screen_size_bgl = graph.bind_group_layout(graph.bind_group_id(&BasePassSlots::ScreenSize).unwrap()); - let mut desc = RenderGraphPassDesc::new( + let mut desc = NodeDesc::new( pass_id, LightCullComputePassLabel, - RenderPassType::Compute, + NodeType::Compute, Some(PipelineDescriptor::Compute(ComputePipelineDescriptor { label: Some("light_cull_pipeline".into()), push_constant_ranges: vec![], @@ -228,7 +228,7 @@ impl RenderGraphPass for LightCullComputePass { fn execute( &mut self, graph: &mut crate::render::graph::RenderGraph, - desc: &crate::render::graph::RenderGraphPassDesc, + desc: &crate::render::graph::NodeDesc, context: &mut RenderGraphContext, ) { let mut pass = context.begin_compute_pass(&wgpu::ComputePassDescriptor { diff --git a/lyra-game/src/render/graph/passes/meshes.rs b/lyra-game/src/render/graph/passes/meshes.rs index ac85c61..a773587 100644 --- a/lyra-game/src/render/graph/passes/meshes.rs +++ b/lyra-game/src/render/graph/passes/meshes.rs @@ -15,8 +15,8 @@ use wgpu::util::DeviceExt; use crate::{ render::{ desc_buf_lay::DescVertexBufferLayout, graph::{ - RenderGraphContext, RenderGraphPass, RenderGraphPassDesc, - RenderPassType, + RenderGraphContext, Node, NodeDesc, + 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 }, DeltaTime, @@ -201,11 +201,11 @@ impl MeshPass { } } -impl RenderGraphPass for MeshPass { +impl Node for MeshPass { fn desc( &mut self, graph: &mut crate::render::graph::RenderGraph, - ) -> crate::render::graph::RenderGraphPassDesc { + ) -> crate::render::graph::NodeDesc { let device = graph.device(); @@ -253,10 +253,10 @@ impl RenderGraphPass for MeshPass { source: include_str!("../../shaders/base.wgsl").to_string(), }); - let desc = RenderGraphPassDesc::new( + let desc = NodeDesc::new( pass_id, MeshesPassLabel, - RenderPassType::Render, + NodeType::Render, Some(PipelineDescriptor::Render(RenderPipelineDescriptor { label: Some("meshes".into()), layouts: vec![ @@ -445,7 +445,7 @@ impl RenderGraphPass for MeshPass { fn execute( &mut self, graph: &mut crate::render::graph::RenderGraph, - desc: &crate::render::graph::RenderGraphPassDesc, + desc: &crate::render::graph::NodeDesc, context: &mut crate::render::graph::RenderGraphContext, ) { let encoder = context.encoder.as_mut().unwrap(); @@ -453,12 +453,14 @@ impl RenderGraphPass for MeshPass { let view = graph .slot_value(graph.slot_id(&BasePassSlots::WindowTextureView).unwrap()) .unwrap() - .as_texture_view(); + .as_texture_view() + .expect("BasePassSlots::WindowTextureView was not a TextureView slot"); let depth_view = graph .slot_value(graph.slot_id(&BasePassSlots::DepthTextureView).unwrap()) .unwrap() - .as_texture_view(); + .as_texture_view() + .expect("BasePassSlots::DepthTextureView was not a TextureView slot"); let camera_bg = graph .bind_group(graph.bind_group_id(&BasePassSlots::Camera) diff --git a/lyra-game/src/render/graph/passes/present_pass.rs b/lyra-game/src/render/graph/passes/present_pass.rs index e496595..2302d8f 100644 --- a/lyra-game/src/render/graph/passes/present_pass.rs +++ b/lyra-game/src/render/graph/passes/present_pass.rs @@ -2,7 +2,7 @@ use std::hash::Hash; use lyra_game_derive::RenderGraphLabel; -use crate::render::graph::{RenderGraphContext, RenderGraphLabel, RenderGraphLabelValue, RenderGraphPass, RenderGraphPassDesc, RenderPassSlot, RenderPassType, SlotAttribute, SlotType}; +use crate::render::graph::{RenderGraphContext, RenderGraphLabel, RenderGraphLabelValue, Node, NodeDesc, NodeSlot, NodeType, SlotAttribute, SlotType}; #[derive(Debug, Clone, Hash, PartialEq, RenderGraphLabel)] pub struct PresentPassLabel(RenderGraphLabelValue); @@ -31,18 +31,18 @@ impl PresentPass { } } -impl RenderGraphPass for PresentPass { - fn desc(&mut self, graph: &mut crate::render::graph::RenderGraph) -> crate::render::graph::RenderGraphPassDesc { - let mut desc = RenderGraphPassDesc::new( +impl Node for PresentPass { + fn desc(&mut self, graph: &mut crate::render::graph::RenderGraph) -> crate::render::graph::NodeDesc { + let mut desc = NodeDesc::new( graph.next_id(), self.label.clone(), - RenderPassType::Presenter, + NodeType::Presenter, None, vec![], ); desc.add_slot( - RenderPassSlot { + NodeSlot { ty: SlotType::RenderTarget, attribute: SlotAttribute::Input, id: graph.next_id(), @@ -58,7 +58,7 @@ impl RenderGraphPass for PresentPass { } - fn execute(&mut self, graph: &mut crate::render::graph::RenderGraph, _desc: &crate::render::graph::RenderGraphPassDesc, _context: &mut crate::render::graph::RenderGraphContext) { + fn execute(&mut self, graph: &mut crate::render::graph::RenderGraph, _desc: &crate::render::graph::NodeDesc, _context: &mut crate::render::graph::RenderGraphContext) { let id = graph.slot_id_rc(&self.label.0) .expect(&format!("render target slot '{:?}' for PresentPass is missing", self.label.0)); let mut slot = graph.slot_value_mut(id).unwrap().as_render_target_mut().unwrap();