Enhance RenderPass usability

This commit is contained in:
mars 2022-04-23 00:37:43 -06:00
parent 4313ce8017
commit cf4ff0e80e
3 changed files with 40 additions and 21 deletions

View File

@ -201,7 +201,7 @@ impl Renderer {
.for_each(|(pass_index, rp)| { .for_each(|(pass_index, rp)| {
let mut phases_buf = Vec::new(); let mut phases_buf = Vec::new();
phases_buf.clear(); phases_buf.clear();
rp.begin_frame(frame_index, &mut phases_buf); rp.begin_frame(frame_index, &mut phases_buf, &self.queue);
let mut passes = phase_passes.lock().unwrap(); let mut passes = phase_passes.lock().unwrap();
for phase in phases_buf.into_iter() { for phase in phases_buf.into_iter() {

View File

@ -1,7 +1,7 @@
//! Render pass data structures and interfaces. //! Render pass data structures and interfaces.
use crate::phase::{Phase, PhaseKind}; use crate::phase::Phase;
use std::sync::{Arc, RwLock}; use std::sync::Arc;
pub mod mesh; pub mod mesh;
@ -30,6 +30,11 @@ pub trait RenderPass: Send + Sync {
/// A structure that contains a pass's per-frame data. /// A structure that contains a pass's per-frame data.
type FrameData: Send + Sync; type FrameData: Send + Sync;
/// Gets a short name for this pass.
fn get_name(&self) -> &str {
std::any::type_name::<Self>()
}
/// Sets up a new instance of [Self::FrameData]. /// Sets up a new instance of [Self::FrameData].
/// ///
/// Called when a render pass is added to [crate::Renderer]. /// Called when a render pass is added to [crate::Renderer].
@ -40,17 +45,24 @@ pub trait RenderPass: Send + Sync {
/// ///
/// This is the only opportunity the render pass has to mutate this frame's /// This is the only opportunity the render pass has to mutate this frame's
/// data this frame, so all setup for future phases should be done here. /// data this frame, so all setup for future phases should be done here.
fn begin_frame(&self, data: &mut Self::FrameData, phases: &mut Vec<Phase>); ///
/// The render pass is also given access to the [queue][wgpu::Queue] this
/// frame will be submitted on, and can be used to transfer image or buffer
/// data to the GPU.
fn begin_frame(&self, data: &mut Self::FrameData, phases: &mut Vec<Phase>, queue: &wgpu::Queue);
fn record_commands(&self, data: PhaseData<&Self::FrameData>, cmds: &mut wgpu::CommandEncoder); fn record_commands(&self, data: PhaseData<&Self::FrameData>, cmds: &mut wgpu::CommandEncoder) {}
fn record_compute<'a>( fn record_compute<'a>(
&'a self, &'a self,
data: PhaseData<&Self::FrameData>, data: PhaseData<&Self::FrameData>,
cmds: &mut wgpu::ComputePass<'a>, cmds: &mut wgpu::ComputePass<'a>,
); ) {
}
fn record_render(&self, data: PhaseData<&Self::FrameData>) -> Option<wgpu::RenderBundle>; fn record_render(&self, data: PhaseData<&Self::FrameData>) -> Option<wgpu::RenderBundle> {
None
}
} }
/// The interface trait for [RenderPassBox], allowing use of a statically-sized /// The interface trait for [RenderPassBox], allowing use of a statically-sized
@ -59,7 +71,7 @@ pub trait RenderPass: Send + Sync {
/// Functions on this trait map one-to-one with [RenderPass], except that /// Functions on this trait map one-to-one with [RenderPass], except that
/// frame data is passed by index and not by reference. /// frame data is passed by index and not by reference.
pub trait RenderPassBoxTrait: Send + Sync { pub trait RenderPassBoxTrait: Send + Sync {
fn begin_frame(&mut self, data_index: usize, phases: &mut Vec<Phase>); fn begin_frame(&mut self, data_index: usize, phases: &mut Vec<Phase>, queue: &wgpu::Queue);
fn record_commands(&self, data: IndexedPhaseData, cmds: &mut wgpu::CommandEncoder); fn record_commands(&self, data: IndexedPhaseData, cmds: &mut wgpu::CommandEncoder);
@ -117,23 +129,35 @@ impl<T: RenderPass> RenderPassBox<T> {
} }
impl<T: RenderPass> RenderPassBoxTrait for RenderPassBox<T> { impl<T: RenderPass> RenderPassBoxTrait for RenderPassBox<T> {
fn begin_frame(&mut self, data_index: usize, phases: &mut Vec<Phase>) { fn begin_frame(&mut self, data_index: usize, phases: &mut Vec<Phase>, queue: &wgpu::Queue) {
let rp = &self.render_pass;
let name = rp.get_name();
println!("{}::begin_frame()", name);
let frame_data = &mut self.frame_data[data_index]; let frame_data = &mut self.frame_data[data_index];
self.render_pass.begin_frame(frame_data, phases) rp.begin_frame(frame_data, phases, queue)
} }
fn record_commands(&self, data: IndexedPhaseData, cmds: &mut wgpu::CommandEncoder) { fn record_commands(&self, data: IndexedPhaseData, cmds: &mut wgpu::CommandEncoder) {
let rp = &self.render_pass;
let name = rp.get_name();
println!("{}::record_commands(phase: {:?})", name, data.phase);
let frame_data = self.get_frame_data(data); let frame_data = self.get_frame_data(data);
self.render_pass.record_commands(frame_data, cmds) rp.record_commands(frame_data, cmds)
} }
fn record_compute<'a>(&'a self, data: IndexedPhaseData, cmds: &mut wgpu::ComputePass<'a>) { fn record_compute<'a>(&'a self, data: IndexedPhaseData, cmds: &mut wgpu::ComputePass<'a>) {
let rp = &self.render_pass;
let name = rp.get_name();
println!("{}::record_compute(phase: {:?})", name, data.phase);
let frame_data = self.get_frame_data(data); let frame_data = self.get_frame_data(data);
self.render_pass.record_compute(frame_data, cmds) rp.record_compute(frame_data, cmds)
} }
fn record_render(&self, data: IndexedPhaseData) -> Option<wgpu::RenderBundle> { fn record_render(&self, data: IndexedPhaseData) -> Option<wgpu::RenderBundle> {
let rp = &self.render_pass;
let name = rp.get_name();
println!("{}::record_compute(phase: {:?})", name, data.phase);
let frame_data = self.get_frame_data(data); let frame_data = self.get_frame_data(data);
self.render_pass.record_render(frame_data) rp.record_render(frame_data)
} }
} }

View File

@ -103,7 +103,7 @@ impl MeshPass {
let render_pipeline_layout = let render_pipeline_layout =
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some("Render Pipeline Layout"), label: Some("MeshPass Pipeline Layout"),
bind_group_layouts: &[&layouts.bind_viewport], bind_group_layouts: &[&layouts.bind_viewport],
push_constant_ranges: &[], push_constant_ranges: &[],
}); });
@ -111,7 +111,7 @@ impl MeshPass {
let shader = device.create_shader_module(&wgpu::include_wgsl!("mesh_shader.wgsl")); let shader = device.create_shader_module(&wgpu::include_wgsl!("mesh_shader.wgsl"));
let opaque_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { let opaque_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: Some("Render Pipeline"), label: Some("Opaque MeshPass Pipeline"),
layout: Some(&render_pipeline_layout), layout: Some(&render_pipeline_layout),
vertex: wgpu::VertexState { vertex: wgpu::VertexState {
module: &shader, module: &shader,
@ -167,7 +167,7 @@ impl RenderPass for MeshPass {
FrameData {} FrameData {}
} }
fn begin_frame(&self, data: &mut FrameData, phases: &mut Vec<Phase>) { fn begin_frame(&self, data: &mut FrameData, phases: &mut Vec<Phase>, queue: &wgpu::Queue) {
println!("MeshPass::begin_frame()"); println!("MeshPass::begin_frame()");
phases.push(Phase::Upload); phases.push(Phase::Upload);
@ -177,17 +177,12 @@ impl RenderPass for MeshPass {
} }
fn record_commands(&self, data: PhaseData<&FrameData>, cmds: &mut wgpu::CommandEncoder) { fn record_commands(&self, data: PhaseData<&FrameData>, cmds: &mut wgpu::CommandEncoder) {
println!("MeshPass::record_commands(phase: {:?})", data.phase);
match data.phase { match data.phase {
Phase::Upload => self.mesh_pool.flush(cmds), Phase::Upload => self.mesh_pool.flush(cmds),
_ => {} _ => {}
} }
} }
fn record_compute(&self, data: PhaseData<&FrameData>, cmds: &mut wgpu::ComputePass) {
println!("MeshPass::record_compute(phase: {:?})", data.phase);
}
fn record_render(&self, data: PhaseData<&FrameData>) -> Option<wgpu::RenderBundle> { fn record_render(&self, data: PhaseData<&FrameData>) -> Option<wgpu::RenderBundle> {
println!("MeshPass::record_render(phase: {:?})", data.phase); println!("MeshPass::record_render(phase: {:?})", data.phase);