125 lines
3.2 KiB
Rust
125 lines
3.2 KiB
Rust
use glam::{uvec2, UVec2};
|
|
|
|
pub struct Viewport<'a> {
|
|
surface: wgpu::Surface<'a>,
|
|
config: wgpu::SurfaceConfiguration,
|
|
sample_count: u32,
|
|
multisample: Multisample,
|
|
}
|
|
|
|
impl<'a> Viewport<'a> {
|
|
pub fn new(adapter: &wgpu::Adapter, device: &wgpu::Device, surface: wgpu::Surface<'a>, size: UVec2) -> Self {
|
|
let caps = surface.get_capabilities(adapter);
|
|
let format = wgpu::TextureFormat::Bgra8UnormSrgb;
|
|
let sample_count = adapter
|
|
.get_texture_format_features(format)
|
|
.flags
|
|
.supported_sample_counts()
|
|
.into_iter()
|
|
.max()
|
|
.unwrap();
|
|
eprintln!("Using x{sample_count} mutlisampling");
|
|
let config = wgpu::SurfaceConfiguration {
|
|
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
|
|
format,
|
|
width: size.x,
|
|
height: size.y,
|
|
present_mode: wgpu::PresentMode::Fifo,
|
|
alpha_mode: caps.alpha_modes[0],
|
|
view_formats: vec![],
|
|
desired_maximum_frame_latency: 2,
|
|
};
|
|
let multisample = Multisample::new(device, format, size, sample_count);
|
|
Self {
|
|
surface,
|
|
config,
|
|
sample_count,
|
|
multisample,
|
|
}
|
|
}
|
|
|
|
pub fn configure(&mut self, device: &wgpu::Device) {
|
|
self.surface.configure(&device, &self.config);
|
|
self.multisample = Multisample::new(device, self.format(), self.size(), self.sample_count);
|
|
}
|
|
|
|
pub fn resize(&mut self, device: &wgpu::Device, size: UVec2) {
|
|
self.config.width = size.x;
|
|
self.config.height = size.y;
|
|
self.configure(&device);
|
|
}
|
|
|
|
pub fn size(&self) -> UVec2 {
|
|
uvec2(self.config.width, self.config.height)
|
|
}
|
|
|
|
pub fn format(&self) -> wgpu::TextureFormat {
|
|
self.config.format
|
|
}
|
|
|
|
pub fn sample_count(&self) -> u32 {
|
|
self.sample_count
|
|
}
|
|
|
|
pub fn render_single_pass(
|
|
&mut self,
|
|
device: &wgpu::Device,
|
|
queue: &wgpu::Queue,
|
|
f: impl FnOnce(wgpu::RenderPass),
|
|
) -> Result<(), wgpu::SurfaceError> {
|
|
let output = self.surface.get_current_texture()?;
|
|
let view = output.texture.create_view(&wgpu::TextureViewDescriptor::default());
|
|
let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor {
|
|
label: Some("Render CommandEncoder"),
|
|
});
|
|
let render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
|
label: Some("RenderPass"),
|
|
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
|
|
view: &self.multisample.view,
|
|
resolve_target: Some(&view),
|
|
ops: wgpu::Operations {
|
|
load: wgpu::LoadOp::Clear(wgpu::Color {
|
|
r: 0.,
|
|
g: 0.,
|
|
b: 0.,
|
|
a: 1.,
|
|
}),
|
|
store: wgpu::StoreOp::Store,
|
|
},
|
|
})],
|
|
depth_stencil_attachment: None,
|
|
occlusion_query_set: None,
|
|
timestamp_writes: None,
|
|
});
|
|
f(render_pass);
|
|
queue.submit(std::iter::once(encoder.finish()));
|
|
output.present();
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
struct Multisample {
|
|
view: wgpu::TextureView,
|
|
}
|
|
|
|
impl Multisample {
|
|
fn new(device: &wgpu::Device, format: wgpu::TextureFormat, size: UVec2, sample_count: u32) -> Multisample {
|
|
let tex = device.create_texture(&wgpu::TextureDescriptor {
|
|
label: Some("Multisample texture"),
|
|
size: wgpu::Extent3d {
|
|
width: size.x,
|
|
height: size.y,
|
|
depth_or_array_layers: 1,
|
|
},
|
|
mip_level_count: 1,
|
|
sample_count,
|
|
dimension: wgpu::TextureDimension::D2,
|
|
format,
|
|
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
|
|
view_formats: &[],
|
|
});
|
|
let view = tex.create_view(&wgpu::TextureViewDescriptor::default());
|
|
Multisample { view }
|
|
}
|
|
}
|