Refactor and document RenderPass
This commit is contained in:
parent
4b1dd0fb22
commit
9f6f57f6d4
89
src/lib.rs
89
src/lib.rs
|
@ -1,40 +1,14 @@
|
||||||
//! Cyborg is a high-performance, modern, experimental rendering engine written
|
//! Cyborg is a high-performance, modern, experimental rendering engine written
|
||||||
//! in Rust.
|
//! in Rust.
|
||||||
|
|
||||||
use std::sync::{Arc, RwLock};
|
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
pub mod phase;
|
pub mod phase;
|
||||||
|
pub mod pass;
|
||||||
|
|
||||||
|
use pass::*;
|
||||||
use phase::*;
|
use phase::*;
|
||||||
|
|
||||||
pub struct ViewportData;
|
|
||||||
|
|
||||||
pub trait FrameData {}
|
|
||||||
|
|
||||||
pub trait RenderPass {
|
|
||||||
type FrameData: FrameData;
|
|
||||||
|
|
||||||
fn create_frame_data(&mut self) -> Self::FrameData;
|
|
||||||
|
|
||||||
fn begin_frame(&mut self, data: &mut Self::FrameData, phases: &mut PhaseList);
|
|
||||||
|
|
||||||
fn render_pre(
|
|
||||||
&self,
|
|
||||||
phase: PrePhase,
|
|
||||||
data: &Self::FrameData,
|
|
||||||
cmds: &mut gpu::RenderBundleEncoder,
|
|
||||||
);
|
|
||||||
|
|
||||||
fn render_viewport(
|
|
||||||
&self,
|
|
||||||
phase: ViewportPhase,
|
|
||||||
data: &Self::FrameData,
|
|
||||||
viewport: &ViewportData,
|
|
||||||
cmds: &mut gpu::RenderBundleEncoder,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Renderer {
|
pub struct Renderer {
|
||||||
pub render_passes: Vec<Box<dyn RenderPassBoxTrait>>,
|
pub render_passes: Vec<Box<dyn RenderPassBoxTrait>>,
|
||||||
}
|
}
|
||||||
|
@ -72,65 +46,6 @@ impl Renderer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct RenderPassBox<T: RenderPass> {
|
|
||||||
render_pass: Arc<RwLock<T>>,
|
|
||||||
frame_data: Vec<T::FrameData>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: RenderPass> RenderPassBox<T> {
|
|
||||||
pub fn new(render_pass: Arc<RwLock<T>>, 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<T: RenderPass> RenderPassBoxTrait for RenderPassBox<T> {
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Mock GPU API (like Vulkan, WebGPU, or OpenGL) types for prototyping.
|
/// Mock GPU API (like Vulkan, WebGPU, or OpenGL) types for prototyping.
|
||||||
pub mod gpu {
|
pub mod gpu {
|
||||||
/// Thread-safe GPU command recorder that's later executed in a command buffer.
|
/// Thread-safe GPU command recorder that's later executed in a command buffer.
|
||||||
|
|
|
@ -0,0 +1,122 @@
|
||||||
|
//! 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<T: RenderPass> {
|
||||||
|
render_pass: Arc<RwLock<T>>,
|
||||||
|
frame_data: Vec<T::FrameData>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: RenderPass> RenderPassBox<T> {
|
||||||
|
/// 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<RwLock<T>>, 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<T: RenderPass> RenderPassBoxTrait for RenderPassBox<T> {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
//! Definitions and containers for rendering phase identifiers.
|
//! Definitions and containers for render phase identifiers.
|
||||||
//!
|
//!
|
||||||
//! Rendering phases are organized into different groups, which represent
|
//! Rendering phases are organized into different groups, which represent
|
||||||
//! different kinds of external data becoming available as the frame progresses.
|
//! different kinds of external data becoming available as the frame progresses.
|
||||||
|
|
Loading…
Reference in New Issue