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)| {
let mut phases_buf = Vec::new();
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();
for phase in phases_buf.into_iter() {

View File

@ -1,7 +1,7 @@
//! Render pass data structures and interfaces.
use crate::phase::{Phase, PhaseKind};
use std::sync::{Arc, RwLock};
use crate::phase::Phase;
use std::sync::Arc;
pub mod mesh;
@ -30,6 +30,11 @@ pub trait RenderPass: Send + Sync {
/// A structure that contains a pass's per-frame data.
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].
///
/// 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
/// 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>(
&'a self,
data: PhaseData<&Self::FrameData>,
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
@ -59,7 +71,7 @@ pub trait RenderPass: Send + Sync {
/// Functions on this trait map one-to-one with [RenderPass], except that
/// frame data is passed by index and not by reference.
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);
@ -117,23 +129,35 @@ impl<T: RenderPass> 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];
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) {
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);
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>) {
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);
self.render_pass.record_compute(frame_data, cmds)
rp.record_compute(frame_data, cmds)
}
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);
self.render_pass.record_render(frame_data)
rp.record_render(frame_data)
}
}

View File

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