cyborg/src/pass.rs

140 lines
4.6 KiB
Rust
Raw Normal View History

2022-04-04 03:15:05 +00:00
//! Render pass data structures and interfaces.
2022-04-18 09:54:29 +00:00
use crate::phase::{Phase, PhaseKind};
2022-04-04 03:15:05 +00:00
use std::sync::{Arc, RwLock};
2022-04-05 04:21:14 +00:00
pub mod mesh;
2022-04-04 03:15:05 +00:00
/// Viewport data shared by all passes, once the [ViewportPhase] group is
/// entered.
pub struct ViewportData;
2022-04-18 09:54:29 +00:00
/// Data passed to each render pass's recording phases.
pub struct PhaseData<'a, T> {
pub phase: Phase,
pub frame_data: T,
pub viewport: &'a ViewportData,
}
pub type IndexedPhaseData<'a> = PhaseData<'a, usize>;
2022-04-04 03:15:05 +00:00
/// 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.
2022-04-04 03:56:28 +00:00
pub trait RenderPass: Send + Sync {
2022-04-04 03:15:05 +00:00
/// A structure that contains a pass's per-frame data.
2022-04-04 03:56:28 +00:00
type FrameData: Send + Sync;
2022-04-04 03:15:05 +00:00
/// 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.
2022-04-18 09:54:29 +00:00
fn begin_frame(&mut self, data: &mut Self::FrameData, phases: &mut Vec<Phase>);
2022-04-04 03:15:05 +00:00
2022-04-18 09:54:29 +00:00
fn record_commands(&self, data: PhaseData<&Self::FrameData>, cmds: &mut wgpu::CommandEncoder);
2022-04-04 03:15:05 +00:00
2022-04-18 09:54:29 +00:00
fn record_compute(&self, data: PhaseData<&Self::FrameData>, cmds: &mut wgpu::ComputePass);
fn record_render(
2022-04-04 03:15:05 +00:00
&self,
2022-04-18 09:54:29 +00:00
data: PhaseData<&Self::FrameData>,
cmds: &mut wgpu::RenderBundleEncoder,
2022-04-04 03:15:05 +00:00
);
}
/// 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.
2022-04-04 03:56:28 +00:00
pub trait RenderPassBoxTrait: Send + Sync {
2022-04-18 09:54:29 +00:00
fn begin_frame(&mut self, data_index: usize, phases: &mut Vec<Phase>);
2022-04-04 03:15:05 +00:00
2022-04-18 09:54:29 +00:00
fn record_commands(&self, data: IndexedPhaseData, cmds: &mut wgpu::CommandEncoder);
2022-04-04 03:15:05 +00:00
2022-04-18 09:54:29 +00:00
fn record_compute(&self, data: IndexedPhaseData, cmds: &mut wgpu::ComputePass);
fn record_render(&self, data: IndexedPhaseData, cmds: &mut wgpu::RenderBundleEncoder);
2022-04-04 03:15:05 +00:00
}
/// A container for a reference-counted render pass instance and its frame data.
pub struct RenderPassBox<T: RenderPass> {
render_pass: Arc<RwLock<T>>,
frame_data: Vec<T::FrameData>,
}
2022-04-04 03:56:28 +00:00
impl<T: 'static + RenderPass> RenderPassBox<T> {
2022-04-04 03:15:05 +00:00
/// 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.
2022-04-04 03:56:28 +00:00
pub fn new(render_pass: Arc<RwLock<T>>, frame_num: usize) -> Box<dyn RenderPassBoxTrait> {
2022-04-04 03:15:05 +00:00
let frame_data = {
let mut lock = render_pass.write().unwrap();
(0..frame_num).map(|_| lock.create_frame_data()).collect()
};
2022-04-04 03:56:28 +00:00
Box::new(Self {
2022-04-04 03:15:05 +00:00
render_pass,
frame_data,
2022-04-04 03:56:28 +00:00
})
2022-04-04 03:15:05 +00:00
}
}
2022-04-18 09:54:29 +00:00
impl<T: RenderPass> RenderPassBox<T> {
fn get_frame_data<'a>(
&'a self,
index: IndexedPhaseData<'a>,
) -> PhaseData<'a, &'a T::FrameData> {
let PhaseData {
phase,
frame_data,
viewport,
} = index;
let frame_data = self.frame_data.get(frame_data).unwrap();
PhaseData {
phase,
frame_data,
viewport,
}
}
}
2022-04-04 03:15:05 +00:00
impl<T: RenderPass> RenderPassBoxTrait for RenderPassBox<T> {
2022-04-18 09:54:29 +00:00
fn begin_frame(&mut self, data_index: usize, phases: &mut Vec<Phase>) {
2022-04-04 03:15:05 +00:00
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)
}
2022-04-18 09:54:29 +00:00
fn record_commands(&self, data: IndexedPhaseData, cmds: &mut wgpu::CommandEncoder) {
let frame_data = self.get_frame_data(data);
2022-04-04 03:15:05 +00:00
let render_pass = self.render_pass.read().unwrap();
2022-04-18 09:54:29 +00:00
render_pass.record_commands(frame_data, cmds)
2022-04-04 03:15:05 +00:00
}
2022-04-18 09:54:29 +00:00
fn record_compute(&self, data: IndexedPhaseData, cmds: &mut wgpu::ComputePass) {
let frame_data = self.get_frame_data(data);
let render_pass = self.render_pass.read().unwrap();
render_pass.record_compute(frame_data, cmds)
}
fn record_render(&self, data: IndexedPhaseData, cmds: &mut wgpu::RenderBundleEncoder) {
let frame_data = self.get_frame_data(data);
2022-04-04 03:15:05 +00:00
let render_pass = self.render_pass.read().unwrap();
2022-04-18 09:54:29 +00:00
render_pass.record_render(frame_data, cmds)
2022-04-04 03:15:05 +00:00
}
}