//! Render pass data structures and interfaces. use crate::gpu; use crate::phase::*; use std::sync::{Arc, RwLock}; /// Viewport data shared by all passes, once the [ViewportPhase] group is /// entered. pub struct ViewportData; /// The render pass interface trait. /// /// Render passes are persistent structures that share GPU resources, user data, /// and more across both phases and frames. /// /// Rendering functions record their GPU commands using the [gpu::RenderBundleEncoder] /// passed to them. pub trait RenderPass { /// A structure that contains a pass's per-frame data. type FrameData; /// Sets up a new instance of [Self::FrameData]. /// /// Called when a render pass is added to [crate::Renderer]. fn create_frame_data(&mut self) -> Self::FrameData; /// Initializes this frame's [Self::FrameData], and queries the pass for /// which phases to execute. /// /// This is the only opportunity the render pass has to mutate this frame's /// data this frame, so all setup for future phases should be done here. fn begin_frame(&mut self, data: &mut Self::FrameData, phases: &mut PhaseList); /// Renders a phase in the [PrePhase] group. fn render_pre( &self, phase: PrePhase, data: &Self::FrameData, cmds: &mut gpu::RenderBundleEncoder, ); /// Renders a phase in the [ViewportPhase] group. /// /// During these render phases, passes may have access to this frame's /// [ViewportData]. fn render_viewport( &self, phase: ViewportPhase, data: &Self::FrameData, viewport: &ViewportData, cmds: &mut gpu::RenderBundleEncoder, ); } /// The interface trait for [RenderPassBox], allowing use of a statically-sized /// [Box] for storage. /// /// Functions on this trait map one-to-one with [RenderPass], except that /// frame data is passed by index and not by reference. pub trait RenderPassBoxTrait { fn begin_frame(&mut self, data_index: usize, phases: &mut PhaseList); fn render_pre(&self, phase: PrePhase, data_index: usize, cmds: &mut gpu::RenderBundleEncoder); fn render_viewport( &self, phase: ViewportPhase, data_index: usize, viewport: &ViewportData, cmds: &mut gpu::RenderBundleEncoder, ); } /// A container for a reference-counted render pass instance and its frame data. pub struct RenderPassBox { render_pass: Arc>, frame_data: Vec, } impl RenderPassBox { /// Creates a new boxed render pass. /// /// Calls to [RenderPassBoxTrait] functions with frame indices greater /// than or equal to `frame_num` are out-of-bounds and will panic. pub fn new(render_pass: Arc>, frame_num: usize) -> Self { let frame_data = { let mut lock = render_pass.write().unwrap(); (0..frame_num).map(|_| lock.create_frame_data()).collect() }; Self { render_pass, frame_data, } } } impl RenderPassBoxTrait for RenderPassBox { fn begin_frame(&mut self, data_index: usize, phases: &mut PhaseList) { let frame_data = &mut self.frame_data[data_index]; let mut render_pass = self.render_pass.write().unwrap(); render_pass.begin_frame(frame_data, phases) } fn render_pre(&self, phase: PrePhase, data_index: usize, cmds: &mut gpu::RenderBundleEncoder) { let frame_data = &self.frame_data[data_index]; let render_pass = self.render_pass.read().unwrap(); render_pass.render_pre(phase, frame_data, cmds) } fn render_viewport( &self, phase: ViewportPhase, data_index: usize, viewport: &ViewportData, cmds: &mut gpu::RenderBundleEncoder, ) { let frame_data = &self.frame_data[data_index]; let render_pass = self.render_pass.read().unwrap(); render_pass.render_viewport(phase, frame_data, viewport, cmds) } }