Add FrameData and RenderLayouts

This commit is contained in:
mars 2022-04-19 17:43:52 -06:00
parent f590edb77f
commit fa1620ddc0
2 changed files with 128 additions and 22 deletions

View File

@ -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);
}
})

View File

@ -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)
}
}