Begin wgpu render passes

This commit is contained in:
mars 2022-04-18 17:40:51 -06:00
parent 718d609517
commit b81dbd1569
2 changed files with 117 additions and 11 deletions

View File

@ -2,6 +2,7 @@
//! in Rust.
use rayon::prelude::*;
use std::sync::Mutex;
use std::sync::{Arc, RwLock};
use strum::IntoEnumIterator;
@ -21,9 +22,9 @@ pub struct Renderer {
}
impl Renderer {
pub fn new(device: wgpu::Device, queue: wgpu::Queue) -> Self {
pub fn new(device: Arc<wgpu::Device>, queue: wgpu::Queue) -> Self {
Self {
device: Arc::new(device),
device,
queue,
frames_in_flight: 2,
render_passes: Vec::new(),
@ -48,7 +49,11 @@ impl Renderer {
self.render_passes.push(pass);
}
pub fn render(&mut self) {
pub fn render(
&mut self,
surface: &wgpu::Surface,
format: wgpu::TextureFormat,
) -> Result<(), wgpu::SurfaceError> {
let frame_index = 0;
let phase_passes = multimap::MultiMap::<Phase, usize>::new();
@ -71,6 +76,66 @@ impl Renderer {
let phase_passes = phase_passes.into_inner().unwrap();
let viewport = ViewportData;
// Up next is actual rendering to a surface!
let output = surface.get_current_texture()?;
let view = output
.texture
.create_view(&wgpu::TextureViewDescriptor::default());
let mut encoder = self
.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor {
label: Some("Render Encoder"),
});
{
let mut opaque_cmds = Vec::new();
if let Some(opaque) = phase_passes.get_vec(&Phase::Opaque) {
opaque.iter().for_each(|pass_index| {
let frame_data = IndexedPhaseData {
phase: Phase::Opaque,
frame_data: frame_index,
viewport: &viewport,
};
let pass = &self.render_passes[*pass_index];
let mut cmds = self.device.create_render_bundle_encoder(
&wgpu::RenderBundleEncoderDescriptor {
label: Some("Opaque Pass Render Bundle"),
color_formats: &[format],
depth_stencil: None,
sample_count: 1,
multiview: None,
},
);
pass.record_render(frame_data, &mut cmds);
opaque_cmds.push(cmds.finish(&wgpu::RenderBundleDescriptor::default()));
})
}
let mut rp = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("Render Pass"),
color_attachments: &[wgpu::RenderPassColorAttachment {
view: &view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(wgpu::Color {
r: 0.1,
g: 0.2,
b: 0.3,
a: 1.0,
}),
store: true,
},
}],
depth_stencil_attachment: None,
});
rp.execute_bundles(opaque_cmds.iter());
}
self.queue.submit(std::iter::once(encoder.finish()));
output.present();
Ok(())
}
}

View File

@ -1,7 +1,30 @@
use cyborg::{pass, Renderer};
use winit::{event::*, event_loop::{ControlFlow, EventLoop}, window::WindowBuilder};
use std::sync::Arc;
use winit::{
event::*,
event_loop::{ControlFlow, EventLoop},
window::WindowBuilder,
};
async fn make_window_renderer(window: &winit::window::Window) -> Renderer {
struct SurfaceViewport {
device: Arc<wgpu::Device>,
size: winit::dpi::PhysicalSize<u32>,
surface: wgpu::Surface,
config: wgpu::SurfaceConfiguration,
}
impl SurfaceViewport {
fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
if new_size.width > 0 && new_size.height > 0 {
self.size = new_size;
self.config.width = new_size.width;
self.config.height = new_size.height;
self.surface.configure(&self.device, &self.config);
}
}
}
async fn make_window_renderer(window: &winit::window::Window) -> (Renderer, SurfaceViewport) {
let size = window.inner_size();
let instance = wgpu::Instance::new(wgpu::Backends::all());
let surface = unsafe { instance.create_surface(window) };
@ -33,13 +56,21 @@ async fn make_window_renderer(window: &winit::window::Window) -> Renderer {
};
surface.configure(&device, &config);
Renderer::new(device, queue)
let device = Arc::new(device);
let renderer = Renderer::new(device.clone(), queue);
let viewport = SurfaceViewport {
device,
size,
surface,
config,
};
(renderer, viewport)
}
fn main() {
let event_loop = EventLoop::new();
let window = WindowBuilder::new().build(&event_loop).unwrap();
let mut renderer = pollster::block_on(make_window_renderer(&window));
let (mut renderer, mut viewport) = pollster::block_on(make_window_renderer(&window));
let device = renderer.get_device();
let mesh_pass = pass::mesh::MeshPass::new(device.to_owned());
@ -47,10 +78,14 @@ fn main() {
event_loop.run(move |event, _, control_flow| match event {
Event::RedrawRequested(_) => {
renderer.render();
match renderer.render(&viewport.surface, viewport.config.format) {
Ok(_) => {}
Err(wgpu::SurfaceError::Lost) => viewport.resize(viewport.size),
Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit,
Err(e) => eprintln!("error: {:?}", e),
};
}
Event::MainEventsCleared => {
std::thread::sleep(std::time::Duration::from_secs_f32( 1.0 / 60.0 ));
window.request_redraw();
}
Event::WindowEvent {
@ -58,8 +93,14 @@ fn main() {
window_id,
} if window_id == window.id() => match event {
WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
WindowEvent::Resized(physical_size) => {
viewport.resize(*physical_size);
}
WindowEvent::ScaleFactorChanged { new_inner_size, .. } => {
viewport.resize(**new_inner_size);
}
_ => {}
}
},
_ => {}
});
}