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.
|
||||
|
||||
use rayon::prelude::*;
|
||||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
use std::sync::{Arc, RwLock};
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
pub mod mesh;
|
||||
pub mod pass;
|
||||
|
@ -14,19 +13,124 @@ pub mod staging;
|
|||
use pass::*;
|
||||
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 {
|
||||
device: Arc<wgpu::Device>,
|
||||
layouts: Arc<RenderLayouts>,
|
||||
queue: wgpu::Queue,
|
||||
frames_in_flight: usize,
|
||||
frame_datas: Vec<FrameData>,
|
||||
frame_index: usize,
|
||||
render_passes: Vec<Box<dyn RenderPassBoxTrait>>,
|
||||
}
|
||||
|
||||
impl Renderer {
|
||||
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 {
|
||||
device,
|
||||
layouts,
|
||||
queue,
|
||||
frames_in_flight: 2,
|
||||
frames_in_flight,
|
||||
frame_datas,
|
||||
frame_index: 0,
|
||||
render_passes: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
@ -35,6 +139,10 @@ impl Renderer {
|
|||
&self.device
|
||||
}
|
||||
|
||||
pub fn get_layouts(&self) -> &Arc<RenderLayouts> {
|
||||
&self.layouts
|
||||
}
|
||||
|
||||
pub fn add_pass<T: 'static + RenderPass>(&mut self, pass: T) {
|
||||
let pass = Arc::new(pass);
|
||||
self.add_pass_arc(pass);
|
||||
|
@ -54,7 +162,13 @@ impl Renderer {
|
|||
surface: &wgpu::Surface,
|
||||
format: wgpu::TextureFormat,
|
||||
) -> 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 = std::sync::Mutex::new(phase_passes);
|
||||
|
@ -88,29 +202,19 @@ impl Renderer {
|
|||
|
||||
if let Some(upload) = phase_passes.get_vec(&Phase::Upload) {
|
||||
upload.iter().for_each(|pass_index| {
|
||||
let frame_data = IndexedPhaseData {
|
||||
phase: Phase::Upload,
|
||||
frame_data: frame_index,
|
||||
viewport: &viewport,
|
||||
};
|
||||
|
||||
let phase_data = frame_data.make_phase_data(Phase::Upload, &viewport);
|
||||
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());
|
||||
if let Some(opaque) = phase_passes.get_vec(&Phase::Opaque) {
|
||||
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 frame_data = IndexedPhaseData {
|
||||
phase: Phase::Opaque,
|
||||
frame_data: frame_index,
|
||||
viewport: &viewport,
|
||||
};
|
||||
|
||||
if let Some(cmd) = pass.record_render(frame_data) {
|
||||
if let Some(cmd) = pass.record_render(phase_data) {
|
||||
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 phase: Phase,
|
||||
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>;
|
||||
|
@ -100,7 +101,8 @@ impl<T: RenderPass> RenderPassBox<T> {
|
|||
let PhaseData {
|
||||
phase,
|
||||
frame_data,
|
||||
viewport,
|
||||
viewport_data,
|
||||
bind_viewport,
|
||||
} = index;
|
||||
|
||||
let frame_data = self.frame_data.get(frame_data).unwrap();
|
||||
|
@ -108,7 +110,8 @@ impl<T: RenderPass> RenderPassBox<T> {
|
|||
PhaseData {
|
||||
phase,
|
||||
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> {
|
||||
let frame_data = self.get_frame_data(data);
|
||||
// let render_pass = self.render_pass.read().unwrap();
|
||||
self.render_pass.record_render(frame_data)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue