167 lines
5.1 KiB
Rust
167 lines
5.1 KiB
Rust
use std::sync::Arc;
|
|
|
|
#[derive(Clone)]
|
|
pub struct ViewportInfo {
|
|
pub output_format: wgpu::TextureFormat,
|
|
pub depth_format: wgpu::TextureFormat,
|
|
}
|
|
|
|
pub struct ViewportViews<'a> {
|
|
pub output: &'a wgpu::TextureView,
|
|
pub depth: &'a wgpu::TextureView,
|
|
}
|
|
|
|
pub trait Viewport {
|
|
fn get_info(&self) -> ViewportInfo;
|
|
fn get_queue(&self) -> &wgpu::Queue;
|
|
fn get_views(&self) -> ViewportViews;
|
|
}
|
|
|
|
pub struct WinitViewport {
|
|
pub device: Arc<wgpu::Device>,
|
|
pub queue: Arc<wgpu::Queue>,
|
|
pub size: winit::dpi::PhysicalSize<u32>,
|
|
surface: wgpu::Surface,
|
|
config: wgpu::SurfaceConfiguration,
|
|
info: ViewportInfo,
|
|
depth_texture: wgpu::Texture,
|
|
depth_texture_view: wgpu::TextureView,
|
|
surface_texture: Option<wgpu::SurfaceTexture>,
|
|
output_view: Option<wgpu::TextureView>,
|
|
}
|
|
|
|
impl WinitViewport {
|
|
pub const DEPTH_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Depth32Float;
|
|
|
|
pub async fn from_window(window: &winit::window::Window) -> Self {
|
|
let size = window.inner_size();
|
|
let instance = wgpu::Instance::new(wgpu::Backends::PRIMARY);
|
|
let surface = unsafe { instance.create_surface(window) };
|
|
let adapter = instance
|
|
.request_adapter(&wgpu::RequestAdapterOptions {
|
|
power_preference: wgpu::PowerPreference::LowPower,
|
|
compatible_surface: Some(&surface),
|
|
force_fallback_adapter: false,
|
|
})
|
|
.await
|
|
.unwrap();
|
|
let (device, queue) = adapter
|
|
.request_device(
|
|
&wgpu::DeviceDescriptor {
|
|
features: wgpu::Features::empty(),
|
|
limits: wgpu::Limits::default(),
|
|
label: None,
|
|
},
|
|
None,
|
|
)
|
|
.await
|
|
.unwrap();
|
|
let config = wgpu::SurfaceConfiguration {
|
|
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
|
|
format: surface.get_preferred_format(&adapter).unwrap(),
|
|
width: size.width,
|
|
height: size.height,
|
|
present_mode: wgpu::PresentMode::Mailbox,
|
|
};
|
|
surface.configure(&device, &config);
|
|
|
|
let device = Arc::new(device);
|
|
let queue = Arc::new(queue);
|
|
|
|
let info = ViewportInfo {
|
|
output_format: config.format,
|
|
depth_format: Self::DEPTH_FORMAT,
|
|
};
|
|
|
|
let (depth_texture, depth_texture_view) = Self::make_depth_texture(&device, &config);
|
|
|
|
Self {
|
|
device,
|
|
queue,
|
|
size,
|
|
surface,
|
|
config,
|
|
info,
|
|
depth_texture,
|
|
depth_texture_view,
|
|
surface_texture: None,
|
|
output_view: None,
|
|
}
|
|
}
|
|
|
|
pub fn acquire(&mut self) -> Result<(), wgpu::SurfaceError> {
|
|
if self.output_view.is_none() {
|
|
let surface_texture = self.surface.get_current_texture()?;
|
|
self.output_view = Some(
|
|
surface_texture
|
|
.texture
|
|
.create_view(&wgpu::TextureViewDescriptor::default()),
|
|
);
|
|
self.surface_texture = Some(surface_texture);
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub 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);
|
|
let (depth_texture, depth_texture_view) =
|
|
Self::make_depth_texture(&self.device, &self.config);
|
|
self.depth_texture = depth_texture;
|
|
self.depth_texture_view = depth_texture_view;
|
|
}
|
|
}
|
|
|
|
pub fn present(&mut self) {
|
|
if let Some(surface_texture) = self.surface_texture.take() {
|
|
surface_texture.present();
|
|
self.output_view.take();
|
|
}
|
|
}
|
|
|
|
fn make_depth_texture(
|
|
device: &wgpu::Device,
|
|
config: &wgpu::SurfaceConfiguration,
|
|
) -> (wgpu::Texture, wgpu::TextureView) {
|
|
let size = wgpu::Extent3d {
|
|
width: config.width,
|
|
height: config.height,
|
|
depth_or_array_layers: 1,
|
|
};
|
|
let desc = wgpu::TextureDescriptor {
|
|
label: Some("Depth Texture"),
|
|
size,
|
|
mip_level_count: 1,
|
|
sample_count: 1,
|
|
dimension: wgpu::TextureDimension::D2,
|
|
format: Self::DEPTH_FORMAT,
|
|
usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::TEXTURE_BINDING,
|
|
};
|
|
let texture = device.create_texture(&desc);
|
|
let view = texture.create_view(&wgpu::TextureViewDescriptor::default());
|
|
(texture, view)
|
|
}
|
|
}
|
|
|
|
impl Viewport for WinitViewport {
|
|
fn get_info(&self) -> ViewportInfo {
|
|
self.info.clone()
|
|
}
|
|
|
|
fn get_queue(&self) -> &wgpu::Queue {
|
|
&self.queue
|
|
}
|
|
|
|
fn get_views(&self) -> ViewportViews {
|
|
let output = self.output_view.as_ref().unwrap();
|
|
ViewportViews {
|
|
output,
|
|
depth: &self.depth_texture_view,
|
|
}
|
|
}
|
|
}
|