From 6d7932f6a5f01b877ed141383b177885ba4b88aa Mon Sep 17 00:00:00 2001 From: SeanOMik Date: Tue, 11 Jun 2024 20:59:55 -0400 Subject: [PATCH] render: remove IDs for everything, use only labels to identify things --- lyra-game/src/render/graph/mod.rs | 210 +++++++++--------- lyra-game/src/render/graph/node.rs | 27 +-- lyra-game/src/render/graph/passes/base.rs | 15 +- .../src/render/graph/passes/light_base.rs | 3 - .../render/graph/passes/light_cull_compute.rs | 42 ++-- lyra-game/src/render/graph/passes/meshes.rs | 37 ++- .../src/render/graph/passes/present_pass.rs | 14 +- lyra-game/src/render/renderer.rs | 13 +- 8 files changed, 150 insertions(+), 211 deletions(-) diff --git a/lyra-game/src/render/graph/mod.rs b/lyra-game/src/render/graph/mod.rs index 9e99897..7fd0ec4 100644 --- a/lyra-game/src/render/graph/mod.rs +++ b/lyra-game/src/render/graph/mod.rs @@ -1,9 +1,8 @@ mod node; use std::{ - cell::RefCell, collections::{HashMap, VecDeque}, fmt::Debug, hash::Hash, rc::Rc, sync::Arc + cell::{Ref, RefCell}, collections::{HashMap, VecDeque}, fmt::Debug, hash::Hash, rc::Rc, sync::Arc }; -use itertools::Itertools; use lyra_ecs::World; pub use node::*; @@ -34,6 +33,8 @@ pub trait RenderGraphLabel: Debug + 'static { } } +pub struct RenderGraphHash(u64); + #[derive(Clone)] pub struct RenderGraphLabelValue(Rc); @@ -77,9 +78,10 @@ impl Eq for RenderGraphLabelValue {} struct PassEntry { inner: Arc>, - desc: Arc, + desc: Rc>, /// The index of the pass in the execution graph graph_index: petgraph::matrix_graph::NodeIndex, + pipeline: Rc>>, } pub struct BindGroupEntry { @@ -116,20 +118,19 @@ pub struct RenderTarget { pub struct RenderGraph { device: Rc, queue: Rc, - slots: FxHashMap, + slots: FxHashMap, /// HashMap used to lookup the slot id using the label's hash - slot_label_lookup: FxHashMap, - passes: FxHashMap, + //slot_label_lookup: FxHashMap, + passes: FxHashMap, // TODO: Use a SlotMap - bind_groups: FxHashMap, + bind_groups: FxHashMap, /// HashMap used to lookup the bind group id using the label's hash - bind_group_names: FxHashMap, + //bind_group_names: FxHashMap, // TODO: make pipelines a `type` parameter in RenderPasses, // then the pipelines can be retrieved via TypeId to the pass. - pipelines: FxHashMap, - current_id: u64, + //pipelines: FxHashMap, /// A directed graph describing the execution path of the RenderGraph - execution_graph: petgraph::matrix_graph::DiMatrix, usize>, + execution_graph: petgraph::matrix_graph::DiMatrix, usize>, } impl RenderGraph { @@ -138,12 +139,8 @@ impl RenderGraph { device, queue, slots: Default::default(), - slot_label_lookup: Default::default(), passes: Default::default(), bind_groups: Default::default(), - bind_group_names: Default::default(), - pipelines: Default::default(), - current_id: 1, execution_graph: Default::default(), } } @@ -152,19 +149,6 @@ impl RenderGraph { &*self.device } - pub fn next_id(&mut self) -> u64 { - self.current_id += 1; - self.current_id - } - - pub(crate) fn slot_id_rc(&self, label: &RenderGraphLabelValue) -> Option { - self.slot_label_lookup.get(&label.clone().into()).cloned() - } - - pub fn slot_id(&self, label: &dyn RenderGraphLabel) -> Option { - 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. @@ -176,34 +160,35 @@ 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(&mut self, mut pass: P) { + pub fn add_pass(&mut self, label: impl RenderGraphLabel, mut pass: P) { let mut desc = pass.desc(self); // collect all the slots of the pass for slot in &mut desc.slots { - if let Some((id, other)) = self - .slot_label_lookup - .get(&slot.label) - .and_then(|id| self.slots.get_mut(id).map(|s| (id, s))) + if let Some(other) = self + .slots + .get_mut(&slot.label) + //.map(|s| (id, s)) + //.and_then(|id| self.slots.get_mut(id).map(|s| (id, s))) { debug_assert_eq!( slot.ty, other.ty, "slot {:?} in pass {:?} does not match existing slot of same name", - slot.label, desc.label + slot.label, label ); - trace!( + /* trace!( "Found existing slot for {:?}, changing id to {}", slot.label, id - ); + ); */ // if there is a slot of the same name - slot.id = *id; + //slot.id = *id; } else { - debug_assert!(!self.slots.contains_key(&slot.id), + debug_assert!(!self.slots.contains_key(&slot.label), "Reuse of id detected in render graph! Pass: {:?}, slot: {:?}", - desc.label, slot.label, + label, slot.label, ); let res_slot = ResourcedSlot { @@ -212,33 +197,29 @@ impl RenderGraph { value: slot.value.clone().unwrap_or(SlotValue::None), }; - self.slots.insert(slot.id, res_slot); - self.slot_label_lookup.insert(slot.label.clone(), slot.id); + self.slots.insert(slot.label.clone(), res_slot); } } // get clones of the bind groups and layouts for (label, bg, bgl) in &desc.bind_groups { - let bg_id = self.next_id(); - self.bind_groups.insert( - bg_id, - BindGroupEntry { - label: label.clone(), - bg: bg.clone(), - layout: bgl.clone(), - }, - ); - self.bind_group_names.insert(label.clone().into(), bg_id); + self.bind_groups.insert(label.clone(), BindGroupEntry { + label: label.clone(), + bg: bg.clone(), + layout: bgl.clone(), + }); } - let index = self.execution_graph.add_node(desc.id); + let label: RenderGraphLabelValue = label.into(); + let index = self.execution_graph.add_node(label.clone()); self.passes.insert( - desc.id, + label, PassEntry { inner: Arc::new(RefCell::new(pass)), - desc: Arc::new(desc), + desc: Rc::new(RefCell::new(desc)), graph_index: index, + pipeline: Rc::new(RefCell::new(None)), }, ); } @@ -250,9 +231,10 @@ impl RenderGraph { #[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.ty { + for pass in self.passes.values_mut() { + let desc = (*pass.desc).borrow(); + if let Some(pipeline_desc) = &desc.pipeline_desc { + let pipeline = match desc.ty { NodeType::Render => Pipeline::Render(RenderPipeline::create( device, pipeline_desc @@ -270,11 +252,14 @@ impl RenderGraph { } }; + drop(desc); let res = PipelineResource { pipeline, bg_layout_name_lookup: Default::default(), }; - self.pipelines.insert(pass.desc.id, res); + + let mut pipeline = pass.pipeline.borrow_mut(); + *pipeline = Some(res); } } } @@ -282,10 +267,16 @@ impl RenderGraph { #[instrument(skip(self, world))] pub fn prepare(&mut self, world: &mut World) { // prepare all passes - let mut context = RenderGraphContext::new(&self.device, &self.queue, None); - for (_, pass) in &mut self.passes { + let mut buffer_writes = VecDeque::::new(); + // reserve some buffer writes. not all nodes write so half the amount of them is probably + // fine. + buffer_writes.reserve(self.passes.len() / 2); + + for (label, pass) in &mut self.passes { + let mut context = RenderGraphContext::new(&self.device, &self.queue, None, label.clone()); let mut inner = pass.inner.borrow_mut(); inner.prepare(world, &mut context); + buffer_writes.append(&mut context.buffer_writes); } { @@ -293,10 +284,10 @@ impl RenderGraph { let s = debug_span!("queue_buffer_writes"); let _e = s.enter(); - while let Some(bufwr) = context.buffer_writes.pop_front() { + while let Some(bufwr) = buffer_writes.pop_front() { let slot = self .slots - .get(&self.slot_id_rc(&bufwr.target_slot).unwrap()) + .get(&bufwr.target_slot) .expect(&format!( "Failed to find slot '{:?}' for buffer write", bufwr.target_slot @@ -313,23 +304,22 @@ impl RenderGraph { #[instrument(skip(self))] pub fn render(&mut self) { - let mut sorted: VecDeque = petgraph::algo::toposort(&self.execution_graph, None) + let mut sorted: VecDeque = petgraph::algo::toposort(&self.execution_graph, None) .expect("RenderGraph had cycled!") .iter() - .map(|i| self.execution_graph[i.clone()]) + .map(|i| self.execution_graph[i.clone()].clone()) .collect(); - let path_names = sorted - .iter() - .map(|i| self.pass(*i).unwrap().label.clone()) - .collect_vec(); - trace!("Render graph execution order: {:?}", path_names); + //debug!("Render graph execution order: {:?}", sorted); let mut encoders = Vec::with_capacity(self.passes.len() / 2); - while let Some(pass_id) = sorted.pop_front() { - let pass = self.passes.get(&pass_id).unwrap(); + while let Some(pass_label) = sorted.pop_front() { + let pass = self.passes.get(&pass_label).unwrap(); let pass_inn = pass.inner.clone(); + let pass_desc = pass.desc.clone(); - let label = format!("{:?} Encoder", pass_desc.label); + let pass_desc = (*pass_desc).borrow(); + + let label = format!("{:?} Encoder", pass_label.0); // encoders are not needed for presenter nodes. let encoder = if pass_desc.ty.should_have_pipeline() { @@ -346,7 +336,7 @@ impl RenderGraph { // clone of the Rc's is required to appease the borrow checker let device = self.device.clone(); let queue = self.queue.clone(); - let mut context = RenderGraphContext::new(&device, &queue, encoder); + let mut context = RenderGraphContext::new(&device, &queue, encoder, pass_label.clone()); // all encoders need to be submitted before a presenter node is executed. if pass_desc.ty == NodeType::Presenter { @@ -354,9 +344,9 @@ impl RenderGraph { self.queue.submit(encoders.drain(..)); } - trace!("Executing {:?}", pass_desc.label); + trace!("Executing {:?}", pass_label.0); let mut inner = pass_inn.borrow_mut(); - inner.execute(self, &*pass_desc, &mut context); + inner.execute(self, &pass_desc, &mut context); if let Some(encoder) = context.encoder { encoders.push(encoder.finish()); @@ -374,49 +364,52 @@ impl RenderGraph { } } - pub fn slot_value(&self, id: u64) -> Option<&SlotValue> { - self.slots.get(&id).map(|s| &s.value) + pub fn slot_value>(&self, label: L) -> Option<&SlotValue> { + self.slots.get(&label.into()).map(|s| &s.value) } - pub fn slot_value_mut(&mut self, id: u64) -> Option<&mut SlotValue> { - self.slots.get_mut(&id).map(|s| &mut s.value) + pub fn slot_value_mut>(&mut self, label: L) -> Option<&mut SlotValue> { + self.slots.get_mut(&label.into()).map(|s| &mut s.value) } - pub fn pass(&self, id: u64) -> Option<&NodeDesc> { - self.passes.get(&id).map(|s| &*s.desc) + pub fn node_desc>(&self, label: L) -> Option> { + self.passes.get(&label.into()).map(|s| (*s.desc).borrow()) } #[inline(always)] - pub fn pipeline(&self, id: u64) -> &Pipeline { - &self.pipelines.get(&id).unwrap().pipeline + pub fn pipeline>(&self, label: L) -> Option> { + self.passes.get(&label.into()) + .and_then(|p| { + let v = p.pipeline.borrow(); + + match &*v { + Some(_) => Some(Ref::map(v, |p| &p.as_ref().unwrap().pipeline)), + None => None, + } + }) } #[inline(always)] - pub fn try_bind_group(&self, id: u64) -> Option<&Rc> { - self.bind_groups.get(&id).map(|e| &e.bg) + pub fn try_bind_group>(&self, label: L) -> Option<&Rc> { + self.bind_groups.get(&label.into()).map(|e| &e.bg) } #[inline(always)] - pub fn bind_group(&self, id: u64) -> &Rc { - self.try_bind_group(id).expect("Unknown id for bind group") + pub fn bind_group>(&self, label: L) -> &Rc { + self.try_bind_group(label).expect("Unknown id for bind group") } #[inline(always)] - pub fn try_bind_group_layout(&self, id: u64) -> Option<&Rc> { - self.bind_groups.get(&id).and_then(|e| e.layout.as_ref()) + pub fn try_bind_group_layout>(&self, label: L) -> Option<&Rc> { + self.bind_groups.get(&label.into()).and_then(|e| e.layout.as_ref()) } #[inline(always)] - pub fn bind_group_layout(&self, id: u64) -> &Rc { - self.try_bind_group_layout(id) + pub fn bind_group_layout>(&self, label: L) -> &Rc { + self.try_bind_group_layout(label) .expect("Unknown id for bind group layout") } - #[inline(always)] - pub fn bind_group_id(&self, label: &dyn RenderGraphLabel) -> Option { - self.bind_group_names.get(&label.rc_clone().into()).copied() - } - pub fn add_edge(&mut self, from: impl RenderGraphLabel, to: impl RenderGraphLabel) { let from = RenderGraphLabelValue::from(from); @@ -425,13 +418,13 @@ impl RenderGraph { let from_idx = self .passes .iter() - .find(|p| p.1.desc.label == from) + .find(|p| *p.0 == from) .map(|p| p.1.graph_index) .expect("Failed to find from pass"); let to_idx = self .passes .iter() - .find(|p| p.1.desc.label == to) + .find(|p| *p.0 == to) .map(|p| p.1.graph_index) .expect("Failed to find to pass"); @@ -471,9 +464,8 @@ impl RenderGraph { ) { for (label, index) in bind_groups { let bg = self - .bind_group_id(*label) - .map(|bgi| self.bind_group(bgi)) - .expect(&format!("Could not find bind group '{:?}'", label)); + .bind_group(label.rc_clone()); + //.expect(&format!("Could not find bind group '{:?}'", label)); pass.set_bind_group(*index, bg, &[]); } @@ -490,22 +482,28 @@ pub(crate) struct GraphBufferWrite { #[allow(dead_code)] pub struct RenderGraphContext<'a> { - /// Becomes None when the encoder is submitted - pub(crate) encoder: Option, - pub(crate) device: &'a wgpu::Device, - pub(crate) queue: &'a wgpu::Queue, + /// The [`wgpu::CommandEncoder`] used to encode GPU operations. + /// + /// This is `None` during the `prepare` stage. + pub encoder: Option, + /// The gpu device that is being used. + pub device: &'a wgpu::Device, + pub queue: &'a wgpu::Queue, pub(crate) buffer_writes: VecDeque, renderpass_desc: Vec>, + /// 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) -> Self { + pub(crate) fn new(device: &'a wgpu::Device, queue: &'a wgpu::Queue, encoder: Option, label: RenderGraphLabelValue) -> Self { Self { encoder, device, queue, buffer_writes: Default::default(), renderpass_desc: vec![], + label, } } diff --git a/lyra-game/src/render/graph/node.rs b/lyra-game/src/render/graph/node.rs index db45f02..806594e 100644 --- a/lyra-game/src/render/graph/node.rs +++ b/lyra-game/src/render/graph/node.rs @@ -1,4 +1,4 @@ -use std::{cell::{Ref, RefCell, RefMut}, collections::HashMap, num::NonZeroU32, rc::Rc}; +use std::{cell::{Ref, RefCell, RefMut}, num::NonZeroU32, rc::Rc}; use bind_match::bind_match; use lyra_ecs::World; @@ -97,8 +97,6 @@ pub struct NodeSlot { 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 value of the slot. @@ -163,15 +161,12 @@ impl RenderGraphPipelineInfo { /// 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, /// 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, + //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`]). @@ -187,19 +182,14 @@ pub struct NodeDesc { impl NodeDesc { /// Create a new node descriptor. - pub fn new( - id: u64, - label: L, + pub fn new( pass_type: NodeType, pipeline_desc: Option, bind_groups: Vec<(&dyn RenderGraphLabel, Rc, Option>)>, ) -> Self { Self { - id, - label: label.into(), ty: pass_type, slots: vec![], - slot_label_lookup: HashMap::default(), pipeline_desc, bind_groups: bind_groups .into_iter() @@ -218,7 +208,6 @@ impl NodeDesc { "input slots should not have values" ); - self.slot_label_lookup.insert(slot.label.clone().into(), slot.id); self.slots.push(slot); } @@ -230,7 +219,6 @@ impl NodeDesc { #[inline(always)] pub fn add_buffer_slot( &mut self, - id: u64, label: L, attribute: SlotAttribute, value: Option, @@ -241,7 +229,6 @@ impl NodeDesc { ); let slot = NodeSlot { - id, label: label.into(), ty: SlotType::Buffer, attribute, @@ -258,7 +245,6 @@ impl NodeDesc { #[inline(always)] pub fn add_texture_slot( &mut self, - id: u64, label: L, attribute: SlotAttribute, value: Option, @@ -269,7 +255,6 @@ impl NodeDesc { ); let slot = NodeSlot { - id, label: label.into(), ty: SlotType::Texture, attribute, @@ -286,7 +271,6 @@ impl NodeDesc { #[inline(always)] pub fn add_texture_view_slot( &mut self, - id: u64, label: L, attribute: SlotAttribute, value: Option, @@ -297,7 +281,6 @@ impl NodeDesc { ); let slot = NodeSlot { - id, label: label.into(), ty: SlotType::TextureView, attribute, @@ -314,7 +297,6 @@ impl NodeDesc { #[inline(always)] pub fn add_sampler_slot( &mut self, - id: u64, label: L, attribute: SlotAttribute, value: Option, @@ -325,7 +307,6 @@ impl NodeDesc { ); let slot = NodeSlot { - id, label: label.into(), ty: SlotType::Sampler, attribute, @@ -341,7 +322,7 @@ impl NodeDesc { .filter(|s| s.attribute == SlotAttribute::Input) .collect() } - + /// Returns all output slots that the descriptor defines. pub fn output_slots(&self) -> Vec<&NodeSlot> { self.slots diff --git a/lyra-game/src/render/graph/passes/base.rs b/lyra-game/src/render/graph/passes/base.rs index cfe8877..e524398 100644 --- a/lyra-game/src/render/graph/passes/base.rs +++ b/lyra-game/src/render/graph/passes/base.rs @@ -40,8 +40,6 @@ pub struct BasePass { /// This should be Some when the pass is first created then after its added to /// the render graph it will be None and stay None. temp_render_target: Option, - main_rt_id: u64, - window_tv_id: u64, screen_size: glam::UVec2, } @@ -102,8 +100,6 @@ impl Node for BasePass { let depth_texture_view = Rc::new(depth_texture.view); let mut desc = NodeDesc::new( - graph.next_id(), - BasePassLabel, NodeType::Node, None, vec![ @@ -119,37 +115,30 @@ impl Node for BasePass { ], ); - self.main_rt_id = graph.next_id(); desc.add_slot(NodeSlot { ty: SlotType::RenderTarget, attribute: SlotAttribute::Output, - id: self.main_rt_id, label: BasePassSlots::MainRenderTarget.into(), value: Some(SlotValue::RenderTarget(Rc::new(RefCell::new( render_target, )))), }); - self.window_tv_id = graph.next_id(); desc.add_texture_view_slot( - self.window_tv_id, BasePassSlots::WindowTextureView, SlotAttribute::Output, Some(SlotValue::Lazy), ); desc.add_texture_view_slot( - graph.next_id(), BasePassSlots::DepthTextureView, SlotAttribute::Output, Some(SlotValue::TextureView(depth_texture_view)), ); desc.add_buffer_slot( - graph.next_id(), BasePassSlots::ScreenSize, SlotAttribute::Output, Some(SlotValue::Buffer(Rc::new(screen_size_buf))), ); desc.add_buffer_slot( - graph.next_id(), BasePassSlots::Camera, SlotAttribute::Output, Some(SlotValue::Buffer(Rc::new(camera_buf))), @@ -177,7 +166,7 @@ impl Node for BasePass { context: &mut crate::render::graph::RenderGraphContext, ) { let tv_slot = graph - .slot_value_mut(self.main_rt_id) + .slot_value_mut(BasePassSlots::MainRenderTarget) .expect("somehow the main render target slot is missing"); let mut rt = tv_slot.as_render_target_mut().unwrap(); debug_assert!( @@ -203,7 +192,7 @@ impl Node for BasePass { // store the surface texture to the slot let tv_slot = graph - .slot_value_mut(self.window_tv_id) + .slot_value_mut(BasePassSlots::WindowTextureView) .expect("somehow the window texture view slot is missing"); *tv_slot = SlotValue::TextureView(Rc::new(view)); } diff --git a/lyra-game/src/render/graph/passes/light_base.rs b/lyra-game/src/render/graph/passes/light_base.rs index 31e7af3..62c3416 100644 --- a/lyra-game/src/render/graph/passes/light_base.rs +++ b/lyra-game/src/render/graph/passes/light_base.rs @@ -40,8 +40,6 @@ impl Node for LightBasePass { let light_buffers = self.light_buffers.as_ref().unwrap(); let mut desc = NodeDesc::new( - graph.next_id(), - LightBasePassLabel, NodeType::Node, None, vec![( @@ -52,7 +50,6 @@ impl Node for LightBasePass { ); desc.add_buffer_slot( - graph.next_id(), LightBasePassSlots::Lights, SlotAttribute::Output, Some(SlotValue::Buffer(light_buffers.buffer.clone())), 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 dec5d74..7b5c487 100644 --- a/lyra-game/src/render/graph/passes/light_cull_compute.rs +++ b/lyra-game/src/render/graph/passes/light_cull_compute.rs @@ -49,8 +49,7 @@ impl Node for LightCullComputePass { // get the size of the work group for the grid let main_rt = graph - .slot_id(&BasePassSlots::MainRenderTarget) - .and_then(|s| graph.slot_value(s)) + .slot_value(BasePassSlots::MainRenderTarget) .and_then(|s| s.as_render_target()) .expect("missing main render target"); self.workgroup_size = @@ -169,16 +168,13 @@ impl Node for LightCullComputePass { })); drop(main_rt); - let pass_id = graph.next_id(); - let depth_tex_bgl = graph.bind_group_layout(graph.bind_group_id(&BasePassSlots::DepthTexture).unwrap()); - let camera_bgl = graph.bind_group_layout(graph.bind_group_id(&BasePassSlots::Camera).unwrap()); - 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 depth_tex_bgl = graph.bind_group_layout(BasePassSlots::DepthTexture); + let camera_bgl = graph.bind_group_layout(BasePassSlots::Camera); + let lights_bgl = graph.bind_group_layout(LightBasePassSlots::Lights); + let screen_size_bgl = graph.bind_group_layout(BasePassSlots::ScreenSize); let mut desc = NodeDesc::new( - pass_id, - LightCullComputePassLabel, NodeType::Compute, Some(PipelineDescriptor::Compute(ComputePipelineDescriptor { label: Some("light_cull_pipeline".into()), @@ -201,20 +197,17 @@ impl Node for LightCullComputePass { ); desc.add_texture_view_slot( - graph.next_id(), BasePassSlots::WindowTextureView, SlotAttribute::Input, None, ); desc.add_buffer_slot( - graph.next_id(), BasePassSlots::ScreenSize, SlotAttribute::Input, None, ); - desc.add_buffer_slot(graph.next_id(), BasePassSlots::Camera, SlotAttribute::Input, None); + desc.add_buffer_slot(BasePassSlots::Camera, SlotAttribute::Input, None); desc.add_buffer_slot( - graph.next_id(), LightCullComputePassSlots::IndexCounterBuffer, SlotAttribute::Output, Some(SlotValue::Buffer(Rc::new(light_index_counter_buffer))), @@ -228,27 +221,20 @@ impl Node for LightCullComputePass { fn execute( &mut self, graph: &mut crate::render::graph::RenderGraph, - desc: &crate::render::graph::NodeDesc, + _: &crate::render::graph::NodeDesc, context: &mut RenderGraphContext, ) { + let label = context.label.clone(); + + let pipeline = graph.pipeline(label) + .expect("Failed to find Pipeline for LightCullComputePass"); + let pipeline = pipeline.as_compute(); + let mut pass = context.begin_compute_pass(&wgpu::ComputePassDescriptor { label: Some("light_cull_pass"), }); - let pipeline = graph.pipeline(desc.id); - pass.set_pipeline(pipeline.as_compute()); - - /* let depth_tex_bg = graph.bind_group(graph.bind_group_id("depth_texture").unwrap()); - let camera_bg = graph.bind_group(graph.bind_group_id("camera").unwrap()); - let lights_bg = graph.bind_group(graph.bind_group_id("light_buffers").unwrap()); - let grid_bg = graph.bind_group(graph.bind_group_id("light_indices_grid").unwrap()); - let screen_size_bg = graph.bind_group(graph.bind_group_id("screen_size").unwrap()); - - pass.set_bind_group(0, depth_tex_bg, &[]); - pass.set_bind_group(1, camera_bg, &[]); - pass.set_bind_group(2, lights_bg, &[]); - pass.set_bind_group(3, grid_bg, &[]); - pass.set_bind_group(4, screen_size_bg, &[]); */ + pass.set_pipeline(pipeline); graph.set_bind_groups( &mut pass, diff --git a/lyra-game/src/render/graph/passes/meshes.rs b/lyra-game/src/render/graph/passes/meshes.rs index a773587..c773ecb 100644 --- a/lyra-game/src/render/graph/passes/meshes.rs +++ b/lyra-game/src/render/graph/passes/meshes.rs @@ -232,21 +232,16 @@ impl Node for MeshPass { self.default_texture = Some(RenderTexture::from_bytes(&device, &graph.queue, texture_bind_group_layout.clone(), bytes, "default_texture").unwrap()); // get surface config format - let main_rt = graph.slot_id(&BasePassSlots::MainRenderTarget) - .and_then(|s| graph.slot_value(s)) + let main_rt = graph.slot_value(BasePassSlots::MainRenderTarget) .and_then(|s| s.as_render_target()) .expect("missing main render target"); let surface_config_format = main_rt.surface_config.format; drop(main_rt); - // get the id here to make borrow checker happy - let pass_id = graph.next_id(); - - let camera_bgl = graph.bind_group_layout(graph.bind_group_id(&BasePassSlots::Camera).unwrap()); - let lights_bgl = graph.bind_group_layout(graph.bind_group_id(&LightBasePassSlots::Lights).unwrap()); + let camera_bgl = graph.bind_group_layout(BasePassSlots::Camera); + let lights_bgl = graph.bind_group_layout(LightBasePassSlots::Lights); let light_grid_bgl = graph - .bind_group_layout(graph.bind_group_id(&LightCullComputePassSlots::LightIndicesGridGroup) - .expect("Missing light grid bind group")); + .bind_group_layout(LightCullComputePassSlots::LightIndicesGridGroup); let shader = Rc::new(Shader { label: Some("base_shader".into()), @@ -254,8 +249,6 @@ impl Node for MeshPass { }); let desc = NodeDesc::new( - pass_id, - MeshesPassLabel, NodeType::Render, Some(PipelineDescriptor::Render(RenderPipelineDescriptor { label: Some("meshes".into()), @@ -445,38 +438,37 @@ impl Node for MeshPass { fn execute( &mut self, graph: &mut crate::render::graph::RenderGraph, - desc: &crate::render::graph::NodeDesc, + _: &crate::render::graph::NodeDesc, context: &mut crate::render::graph::RenderGraphContext, ) { let encoder = context.encoder.as_mut().unwrap(); let view = graph - .slot_value(graph.slot_id(&BasePassSlots::WindowTextureView).unwrap()) + .slot_value(BasePassSlots::WindowTextureView) .unwrap() .as_texture_view() .expect("BasePassSlots::WindowTextureView was not a TextureView slot"); let depth_view = graph - .slot_value(graph.slot_id(&BasePassSlots::DepthTextureView).unwrap()) + .slot_value(BasePassSlots::DepthTextureView) .unwrap() .as_texture_view() .expect("BasePassSlots::DepthTextureView was not a TextureView slot"); let camera_bg = graph - .bind_group(graph.bind_group_id(&BasePassSlots::Camera) - .expect("Missing camera bind group")); + .bind_group(BasePassSlots::Camera); let lights_bg = graph - .bind_group(graph.bind_group_id(&LightBasePassSlots::Lights) - .expect("Missing lights bind group")); + .bind_group(LightBasePassSlots::Lights); let light_grid_bg = graph - .bind_group(graph.bind_group_id(&LightCullComputePassSlots::LightIndicesGridGroup) - .expect("Missing light grid bind group")); + .bind_group(LightCullComputePassSlots::LightIndicesGridGroup); let material_bg = graph - .bind_group(graph.bind_group_id(&MeshesPassSlots::Material) - .expect("Missing material bind group")); + .bind_group(MeshesPassSlots::Material); + + let pipeline = graph.pipeline(context.label.clone()) + .expect("Failed to find pipeline for MeshPass"); let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { label: Some("Render Pass"), @@ -504,7 +496,6 @@ impl Node for MeshPass { }), }); - let pipeline = graph.pipeline(desc.id); pass.set_pipeline(&pipeline.as_render()); //let material_buffer_bg = self.material_buffer.as_ref().unwrap().bindgroup(); diff --git a/lyra-game/src/render/graph/passes/present_pass.rs b/lyra-game/src/render/graph/passes/present_pass.rs index 2302d8f..af7d52d 100644 --- a/lyra-game/src/render/graph/passes/present_pass.rs +++ b/lyra-game/src/render/graph/passes/present_pass.rs @@ -18,8 +18,7 @@ impl PresentPassLabel { /// screen size buffer, camera buffer, pub struct PresentPass { /// Label of this pass - label: PresentPassLabel, - //render_target_slot: Rc, + pub label: PresentPassLabel, } impl PresentPass { @@ -32,10 +31,8 @@ impl PresentPass { } impl Node for PresentPass { - fn desc(&mut self, graph: &mut crate::render::graph::RenderGraph) -> crate::render::graph::NodeDesc { + 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(), NodeType::Presenter, None, vec![], @@ -45,7 +42,6 @@ impl Node for PresentPass { NodeSlot { ty: SlotType::RenderTarget, attribute: SlotAttribute::Input, - id: graph.next_id(), label: self.label.0.clone(), value: None, } @@ -59,9 +55,9 @@ impl Node for PresentPass { } 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(); + let mut slot = graph.slot_value_mut(self.label.0.clone()) + .expect(&format!("render target slot '{:?}' for PresentPass is missing", self.label.0)) + .as_render_target_mut().unwrap(); let surf_tex = slot.current_texture.take().unwrap(); surf_tex.present(); } diff --git a/lyra-game/src/render/renderer.rs b/lyra-game/src/render/renderer.rs index 353f45d..b73a0b9 100755 --- a/lyra-game/src/render/renderer.rs +++ b/lyra-game/src/render/renderer.rs @@ -125,19 +125,20 @@ impl BasicRenderer { let mut g = RenderGraph::new(device.clone(), queue.clone()); debug!("Adding base pass"); - g.add_pass(BasePass::new(surface, config)); + g.add_pass(BasePassLabel, BasePass::new(surface, config)); debug!("Adding light base pass"); - g.add_pass(LightBasePass::new()); + g.add_pass(LightBasePassLabel, LightBasePass::new()); debug!("Adding light cull compute pass"); - g.add_pass(LightCullComputePass::new(size)); + g.add_pass(LightCullComputePassLabel, LightCullComputePass::new(size)); //debug!("Adding triangle pass"); //g.add_pass(TrianglePass::new()); debug!("Adding mesh pass"); - g.add_pass(MeshPass::new()); + g.add_pass(MeshesPassLabel, MeshPass::new()); debug!("Adding present pass"); - g.add_pass(PresentPass::new(BasePassSlots::MainRenderTarget)); + let p = PresentPass::new(BasePassSlots::MainRenderTarget); + g.add_pass(p.label.clone(), p); g.add_edge(BasePassLabel, LightBasePassLabel); g.add_edge(LightBasePassLabel, LightCullComputePassLabel); @@ -188,7 +189,7 @@ impl Renderer for BasicRenderer { self.size = new_size; // update surface config and the surface - let mut rt = self.graph.slot_value_mut(self.graph.slot_id(&BasePassSlots::MainRenderTarget).unwrap()) + let mut rt = self.graph.slot_value_mut(BasePassSlots::MainRenderTarget) .unwrap().as_render_target_mut().unwrap(); rt.surface_config.width = new_size.width; rt.surface_config.height = new_size.height;