Add FrameData and RenderLayouts
This commit is contained in:
parent
f590edb77f
commit
fa1620ddc0
140
src/lib.rs
140
src/lib.rs
|
@ -2,9 +2,8 @@
|
||||||
//! in Rust.
|
//! in Rust.
|
||||||
|
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
|
use std::sync::Arc;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
use std::sync::{Arc, RwLock};
|
|
||||||
use strum::IntoEnumIterator;
|
|
||||||
|
|
||||||
pub mod mesh;
|
pub mod mesh;
|
||||||
pub mod pass;
|
pub mod pass;
|
||||||
|
@ -14,19 +13,124 @@ pub mod staging;
|
||||||
use pass::*;
|
use pass::*;
|
||||||
use phase::*;
|
use phase::*;
|
||||||
|
|
||||||
|
pub struct ViewportUniform {
|
||||||
|
pub vp: [f32; 16],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ViewportUniform {
|
||||||
|
pub fn binding_size() -> wgpu::BufferSize {
|
||||||
|
let size = std::mem::size_of::<Self>() as u64;
|
||||||
|
size.try_into().unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct RenderLayouts {
|
||||||
|
pub device: Arc<wgpu::Device>,
|
||||||
|
pub bind_viewport: wgpu::BindGroupLayout,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RenderLayouts {
|
||||||
|
pub fn new_arc(device: Arc<wgpu::Device>) -> Arc<Self> {
|
||||||
|
let bind_viewport = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||||
|
label: Some("viewport"),
|
||||||
|
entries: &[wgpu::BindGroupLayoutEntry {
|
||||||
|
binding: 0,
|
||||||
|
visibility: wgpu::ShaderStages::VERTEX_FRAGMENT,
|
||||||
|
ty: wgpu::BindingType::Buffer {
|
||||||
|
ty: wgpu::BufferBindingType::Uniform,
|
||||||
|
has_dynamic_offset: false,
|
||||||
|
min_binding_size: Some(ViewportUniform::binding_size()),
|
||||||
|
},
|
||||||
|
count: None,
|
||||||
|
}],
|
||||||
|
});
|
||||||
|
|
||||||
|
Arc::new(Self {
|
||||||
|
device,
|
||||||
|
bind_viewport,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct FrameData {
|
||||||
|
pub frame_index: usize,
|
||||||
|
pub bind_viewport: wgpu::BindGroup,
|
||||||
|
pub viewport_uniform: wgpu::Buffer,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FrameData {
|
||||||
|
pub fn new(frame_index: usize, layouts: &RenderLayouts) -> Self {
|
||||||
|
let viewport_uniform = layouts.device.create_buffer(&wgpu::BufferDescriptor {
|
||||||
|
label: Some("viewport"),
|
||||||
|
size: ViewportUniform::binding_size().into(),
|
||||||
|
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
|
||||||
|
mapped_at_creation: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
let bind_viewport = layouts
|
||||||
|
.device
|
||||||
|
.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||||
|
label: Some("viewport"),
|
||||||
|
layout: &layouts.bind_viewport,
|
||||||
|
entries: &[wgpu::BindGroupEntry {
|
||||||
|
binding: 0,
|
||||||
|
resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding {
|
||||||
|
buffer: &viewport_uniform,
|
||||||
|
offset: 0,
|
||||||
|
size: None,
|
||||||
|
}),
|
||||||
|
}],
|
||||||
|
});
|
||||||
|
|
||||||
|
Self {
|
||||||
|
frame_index,
|
||||||
|
bind_viewport,
|
||||||
|
viewport_uniform,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn make_phase_data<'a>(
|
||||||
|
&'a self,
|
||||||
|
phase: Phase,
|
||||||
|
viewport_data: &'a ViewportData,
|
||||||
|
) -> IndexedPhaseData<'a> {
|
||||||
|
IndexedPhaseData {
|
||||||
|
phase,
|
||||||
|
frame_data: self.frame_index,
|
||||||
|
viewport_data,
|
||||||
|
bind_viewport: &self.bind_viewport,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Renderer {
|
pub struct Renderer {
|
||||||
device: Arc<wgpu::Device>,
|
device: Arc<wgpu::Device>,
|
||||||
|
layouts: Arc<RenderLayouts>,
|
||||||
queue: wgpu::Queue,
|
queue: wgpu::Queue,
|
||||||
frames_in_flight: usize,
|
frames_in_flight: usize,
|
||||||
|
frame_datas: Vec<FrameData>,
|
||||||
|
frame_index: usize,
|
||||||
render_passes: Vec<Box<dyn RenderPassBoxTrait>>,
|
render_passes: Vec<Box<dyn RenderPassBoxTrait>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Renderer {
|
impl Renderer {
|
||||||
pub fn new(device: Arc<wgpu::Device>, queue: wgpu::Queue) -> Self {
|
pub fn new(device: Arc<wgpu::Device>, queue: wgpu::Queue) -> Self {
|
||||||
|
let layouts = RenderLayouts::new_arc(device.clone());
|
||||||
|
|
||||||
|
let frames_in_flight = 1;
|
||||||
|
|
||||||
|
let mut frame_datas = Vec::with_capacity(frames_in_flight);
|
||||||
|
for frame_index in 0..frames_in_flight {
|
||||||
|
frame_datas.push(FrameData::new(frame_index, &layouts));
|
||||||
|
}
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
device,
|
device,
|
||||||
|
layouts,
|
||||||
queue,
|
queue,
|
||||||
frames_in_flight: 2,
|
frames_in_flight,
|
||||||
|
frame_datas,
|
||||||
|
frame_index: 0,
|
||||||
render_passes: Vec::new(),
|
render_passes: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,6 +139,10 @@ impl Renderer {
|
||||||
&self.device
|
&self.device
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_layouts(&self) -> &Arc<RenderLayouts> {
|
||||||
|
&self.layouts
|
||||||
|
}
|
||||||
|
|
||||||
pub fn add_pass<T: 'static + RenderPass>(&mut self, pass: T) {
|
pub fn add_pass<T: 'static + RenderPass>(&mut self, pass: T) {
|
||||||
let pass = Arc::new(pass);
|
let pass = Arc::new(pass);
|
||||||
self.add_pass_arc(pass);
|
self.add_pass_arc(pass);
|
||||||
|
@ -54,7 +162,13 @@ impl Renderer {
|
||||||
surface: &wgpu::Surface,
|
surface: &wgpu::Surface,
|
||||||
format: wgpu::TextureFormat,
|
format: wgpu::TextureFormat,
|
||||||
) -> Result<(), wgpu::SurfaceError> {
|
) -> Result<(), wgpu::SurfaceError> {
|
||||||
let frame_index = 0;
|
self.frame_index += 1;
|
||||||
|
if self.frame_index >= self.frame_datas.len() {
|
||||||
|
self.frame_index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
let frame_index = self.frame_index;
|
||||||
|
let frame_data = &self.frame_datas[frame_index];
|
||||||
|
|
||||||
let phase_passes = multimap::MultiMap::<Phase, usize>::new();
|
let phase_passes = multimap::MultiMap::<Phase, usize>::new();
|
||||||
let phase_passes = std::sync::Mutex::new(phase_passes);
|
let phase_passes = std::sync::Mutex::new(phase_passes);
|
||||||
|
@ -88,29 +202,19 @@ impl Renderer {
|
||||||
|
|
||||||
if let Some(upload) = phase_passes.get_vec(&Phase::Upload) {
|
if let Some(upload) = phase_passes.get_vec(&Phase::Upload) {
|
||||||
upload.iter().for_each(|pass_index| {
|
upload.iter().for_each(|pass_index| {
|
||||||
let frame_data = IndexedPhaseData {
|
let phase_data = frame_data.make_phase_data(Phase::Upload, &viewport);
|
||||||
phase: Phase::Upload,
|
|
||||||
frame_data: frame_index,
|
|
||||||
viewport: &viewport,
|
|
||||||
};
|
|
||||||
|
|
||||||
let pass = &self.render_passes[*pass_index];
|
let pass = &self.render_passes[*pass_index];
|
||||||
pass.record_commands(frame_data, &mut encoder);
|
pass.record_commands(phase_data, &mut encoder);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let opaque_cmds = Mutex::new(Vec::new());
|
let opaque_cmds = Mutex::new(Vec::new());
|
||||||
if let Some(opaque) = phase_passes.get_vec(&Phase::Opaque) {
|
if let Some(opaque) = phase_passes.get_vec(&Phase::Opaque) {
|
||||||
opaque.par_iter().for_each(|pass_index| {
|
opaque.par_iter().for_each(|pass_index| {
|
||||||
|
let phase_data = frame_data.make_phase_data(Phase::Opaque, &viewport);
|
||||||
let pass = &self.render_passes[*pass_index];
|
let pass = &self.render_passes[*pass_index];
|
||||||
|
|
||||||
let frame_data = IndexedPhaseData {
|
if let Some(cmd) = pass.record_render(phase_data) {
|
||||||
phase: Phase::Opaque,
|
|
||||||
frame_data: frame_index,
|
|
||||||
viewport: &viewport,
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(cmd) = pass.record_render(frame_data) {
|
|
||||||
opaque_cmds.lock().unwrap().push(cmd);
|
opaque_cmds.lock().unwrap().push(cmd);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
10
src/pass.rs
10
src/pass.rs
|
@ -13,7 +13,8 @@ pub struct ViewportData;
|
||||||
pub struct PhaseData<'a, T> {
|
pub struct PhaseData<'a, T> {
|
||||||
pub phase: Phase,
|
pub phase: Phase,
|
||||||
pub frame_data: T,
|
pub frame_data: T,
|
||||||
pub viewport: &'a ViewportData,
|
pub viewport_data: &'a ViewportData,
|
||||||
|
pub bind_viewport: &'a wgpu::BindGroup,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type IndexedPhaseData<'a> = PhaseData<'a, usize>;
|
pub type IndexedPhaseData<'a> = PhaseData<'a, usize>;
|
||||||
|
@ -100,7 +101,8 @@ impl<T: RenderPass> RenderPassBox<T> {
|
||||||
let PhaseData {
|
let PhaseData {
|
||||||
phase,
|
phase,
|
||||||
frame_data,
|
frame_data,
|
||||||
viewport,
|
viewport_data,
|
||||||
|
bind_viewport,
|
||||||
} = index;
|
} = index;
|
||||||
|
|
||||||
let frame_data = self.frame_data.get(frame_data).unwrap();
|
let frame_data = self.frame_data.get(frame_data).unwrap();
|
||||||
|
@ -108,7 +110,8 @@ impl<T: RenderPass> RenderPassBox<T> {
|
||||||
PhaseData {
|
PhaseData {
|
||||||
phase,
|
phase,
|
||||||
frame_data,
|
frame_data,
|
||||||
viewport,
|
viewport_data,
|
||||||
|
bind_viewport,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -131,7 +134,6 @@ impl<T: RenderPass> RenderPassBoxTrait for RenderPassBox<T> {
|
||||||
|
|
||||||
fn record_render(&self, data: IndexedPhaseData) -> Option<wgpu::RenderBundle> {
|
fn record_render(&self, data: IndexedPhaseData) -> Option<wgpu::RenderBundle> {
|
||||||
let frame_data = self.get_frame_data(data);
|
let frame_data = self.get_frame_data(data);
|
||||||
// let render_pass = self.render_pass.read().unwrap();
|
|
||||||
self.render_pass.record_render(frame_data)
|
self.render_pass.record_render(frame_data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue