cyborg/src/lib.rs

143 lines
4.1 KiB
Rust
Raw Normal View History

2022-04-04 02:11:38 +00:00
//! Cyborg is a high-performance, modern, experimental rendering engine written
//! in Rust.
use std::sync::{Arc, RwLock};
use strum::IntoEnumIterator;
2022-04-04 02:31:20 +00:00
pub mod phase;
2022-04-04 02:11:38 +00:00
2022-04-04 02:31:20 +00:00
use phase::*;
2022-04-04 02:11:38 +00:00
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 render_passes: Vec<Box<dyn RenderPassBoxTrait>>,
}
impl Renderer {
pub fn render(&mut self) {
let frame_index = 0;
let mut phase_passes = PhaseMultiMap::<usize>::default();
let mut phases_buf = PhaseList::default();
for (pass_index, rp) in self.render_passes.iter_mut().enumerate() {
phases_buf.clear();
rp.begin_frame(frame_index, &mut phases_buf);
phase_passes.insert_multi(&phases_buf, pass_index);
}
for phase in PrePhase::iter() {
for pass_index in phase_passes.iter_pre(&phase) {
let pass = &self.render_passes[*pass_index];
let mut encoder = gpu::RenderBundleEncoder;
pass.render_pre(phase, frame_index, &mut encoder);
}
}
let viewport = ViewportData;
for phase in ViewportPhase::iter() {
for pass_index in phase_passes.iter_viewport(&phase) {
let pass = &self.render_passes[*pass_index];
let mut encoder = gpu::RenderBundleEncoder;
pass.render_viewport(phase, frame_index, &viewport, &mut encoder);
}
}
}
}
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.
pub mod gpu {
/// Thread-safe GPU command recorder that's later executed in a command buffer.
///
/// Also known as a:
/// - RenderBundleEncoder in WebGPU
/// - secondary command buffer in Vulkan
pub struct RenderBundleEncoder;
}