2022-04-04 02:11:38 +00:00
|
|
|
//! Cyborg is a high-performance, modern, experimental rendering engine written
|
|
|
|
//! in Rust.
|
|
|
|
|
2022-04-04 03:56:28 +00:00
|
|
|
use rayon::prelude::*;
|
2022-04-04 02:11:38 +00:00
|
|
|
use strum::IntoEnumIterator;
|
|
|
|
|
2022-04-04 03:15:05 +00:00
|
|
|
pub mod pass;
|
2022-04-04 03:56:28 +00:00
|
|
|
pub mod phase;
|
2022-04-04 02:11:38 +00:00
|
|
|
|
2022-04-04 03:15:05 +00:00
|
|
|
use pass::*;
|
2022-04-04 02:31:20 +00:00
|
|
|
use phase::*;
|
2022-04-04 02:11:38 +00:00
|
|
|
|
|
|
|
pub struct Renderer {
|
|
|
|
pub render_passes: Vec<Box<dyn RenderPassBoxTrait>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Renderer {
|
|
|
|
pub fn render(&mut self) {
|
|
|
|
let frame_index = 0;
|
|
|
|
|
2022-04-04 03:56:28 +00:00
|
|
|
let phase_passes = PhaseMultiMap::<usize>::default();
|
|
|
|
let phase_passes = std::sync::Mutex::new(phase_passes);
|
2022-04-04 02:11:38 +00:00
|
|
|
|
2022-04-04 03:56:28 +00:00
|
|
|
self.render_passes
|
|
|
|
.par_iter_mut()
|
|
|
|
.enumerate()
|
|
|
|
.for_each(|(pass_index, rp)| {
|
|
|
|
let mut phases_buf = PhaseList::default();
|
|
|
|
phases_buf.clear();
|
|
|
|
rp.begin_frame(frame_index, &mut phases_buf);
|
|
|
|
phase_passes
|
|
|
|
.lock()
|
|
|
|
.unwrap()
|
|
|
|
.insert_multi(&phases_buf, pass_index);
|
|
|
|
});
|
2022-04-04 02:11:38 +00:00
|
|
|
|
2022-04-04 03:56:28 +00:00
|
|
|
let phase_passes = phase_passes.into_inner().unwrap();
|
|
|
|
|
|
|
|
PrePhase::iter().par_bridge().for_each(|phase| {
|
2022-04-04 02:11:38 +00:00
|
|
|
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);
|
|
|
|
}
|
2022-04-04 03:56:28 +00:00
|
|
|
});
|
2022-04-04 02:11:38 +00:00
|
|
|
|
|
|
|
let viewport = ViewportData;
|
|
|
|
|
2022-04-04 03:56:28 +00:00
|
|
|
ViewportPhase::iter().par_bridge().for_each(|phase| {
|
2022-04-04 02:11:38 +00:00
|
|
|
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);
|
|
|
|
}
|
2022-04-04 03:56:28 +00:00
|
|
|
});
|
2022-04-04 02:11:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// 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;
|
|
|
|
}
|
2022-04-04 03:56:28 +00:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
|
|
|
|
2022-04-04 04:11:14 +00:00
|
|
|
#[derive(Copy, Clone)]
|
2022-04-04 03:56:28 +00:00
|
|
|
struct DummyPass;
|
|
|
|
|
|
|
|
impl RenderPass for DummyPass {
|
|
|
|
type FrameData = usize;
|
|
|
|
|
|
|
|
fn create_frame_data(&mut self) -> usize {
|
|
|
|
0
|
|
|
|
}
|
|
|
|
|
|
|
|
fn begin_frame(&mut self, data: &mut Self::FrameData, phases: &mut PhaseList) {
|
|
|
|
println!("begin_frame()");
|
2022-04-04 04:11:14 +00:00
|
|
|
|
|
|
|
for phase in PrePhase::iter() {
|
|
|
|
phases.insert_pre(phase);
|
|
|
|
}
|
|
|
|
|
|
|
|
for phase in ViewportPhase::iter() {
|
|
|
|
phases.insert_viewport(phase);
|
|
|
|
}
|
2022-04-04 03:56:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn render_pre(
|
|
|
|
&self,
|
|
|
|
phase: PrePhase,
|
|
|
|
data: &Self::FrameData,
|
|
|
|
cmds: &mut gpu::RenderBundleEncoder,
|
|
|
|
) {
|
|
|
|
println!("render_pre(phase: {:?})", phase);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn render_viewport(
|
|
|
|
&self,
|
|
|
|
phase: ViewportPhase,
|
|
|
|
data: &Self::FrameData,
|
|
|
|
viewport: &ViewportData,
|
|
|
|
cmds: &mut gpu::RenderBundleEncoder,
|
|
|
|
) {
|
|
|
|
println!("render_viewport(phase: {:?})", phase);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn dummy_pass() {
|
|
|
|
use std::sync::{Arc, RwLock};
|
2022-04-04 04:11:14 +00:00
|
|
|
let render_passes = (0..10)
|
|
|
|
.map(|_| {
|
|
|
|
let dummy_pass = DummyPass;
|
|
|
|
let dummy_pass = Arc::new(RwLock::new(dummy_pass));
|
|
|
|
RenderPassBox::new(dummy_pass, 1)
|
|
|
|
})
|
|
|
|
.collect();
|
2022-04-04 03:56:28 +00:00
|
|
|
let mut renderer = Renderer { render_passes };
|
2022-04-04 04:11:14 +00:00
|
|
|
|
|
|
|
for n in 0..10 {
|
|
|
|
println!("Frame #{}", n);
|
|
|
|
renderer.render();
|
|
|
|
}
|
2022-04-04 03:56:28 +00:00
|
|
|
}
|
|
|
|
}
|