diff options
Diffstat (limited to 'src/gfx/gpu.rs')
-rw-r--r-- | src/gfx/gpu.rs | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/src/gfx/gpu.rs b/src/gfx/gpu.rs new file mode 100644 index 0000000..f187fee --- /dev/null +++ b/src/gfx/gpu.rs @@ -0,0 +1,168 @@ +pub struct Frame<'a> { + pub gpu: &'a mut Gpu, + pub encoder: wgpu::CommandEncoder, + pub output: wgpu::SurfaceTexture, + pub view: wgpu::TextureView, +} + +impl<'a> Frame<'a> { + pub fn new(gpu: &'a mut Gpu) -> Result<Self, wgpu::SurfaceError> { + let output = gpu.surface.get_current_texture()?; + let view = output + .texture + .create_view(&wgpu::TextureViewDescriptor::default()); + + let encoder = gpu + .device + .create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None }); + + Ok(Self { + gpu, + encoder, + output, + view, + }) + } + + pub fn pass(&mut self) -> wgpu::RenderPass { + self.encoder.begin_render_pass(&wgpu::RenderPassDescriptor { + label: None, + color_attachments: &[Some(wgpu::RenderPassColorAttachment { + view: &self.view, + resolve_target: None, + ops: wgpu::Operations { + load: wgpu::LoadOp::Clear(wgpu::Color { + r: 0x87 as f64 / 255.0, + g: 0xCE as f64 / 255.0, + b: 0xEB as f64 / 255.0, + a: 1.0, + }), + store: true, + }, + })], + depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment { + view: &self.gpu.depth_texture, + depth_ops: Some(wgpu::Operations { + load: wgpu::LoadOp::Clear(1.0), + store: true, + }), + stencil_ops: None, + }), + }) + } + + pub fn finish(self) { + self.gpu.queue.submit(Some(self.encoder.finish())); + self.output.present(); + } +} + +pub struct Gpu { + pub surface: wgpu::Surface, + pub device: wgpu::Device, + pub queue: wgpu::Queue, + pub config: wgpu::SurfaceConfiguration, + pub depth_texture: wgpu::TextureView, +} + +impl Gpu { + pub async fn new(window: &winit::window::Window) -> Self { + let size = window.inner_size(); + + let instance = wgpu::Instance::new(wgpu::InstanceDescriptor { + backends: wgpu::Backends::all(), + dx12_shader_compiler: Default::default(), + }); + + let surface = unsafe { instance.create_surface(window) }.unwrap(); + + let adapter = instance + .request_adapter(&wgpu::RequestAdapterOptions { + power_preference: wgpu::PowerPreference::default(), + compatible_surface: Some(&surface), + force_fallback_adapter: false, + }) + .await + .unwrap(); + + let (device, queue) = adapter + .request_device( + &wgpu::DeviceDescriptor { + features: wgpu::Features::empty(), + limits: Default::default(), + label: None, + }, + None, + ) + .await + .unwrap(); + + let surface_caps = surface.get_capabilities(&adapter); + let surface_format = surface_caps + .formats + .iter() + .copied() + .find(|f| f.describe().srgb) + .unwrap_or(surface_caps.formats[0]); + + let config = wgpu::SurfaceConfiguration { + usage: wgpu::TextureUsages::RENDER_ATTACHMENT, + format: surface_format, + width: size.width, + height: size.height, + present_mode: surface_caps.present_modes[0], + alpha_mode: surface_caps.alpha_modes[0], + view_formats: vec![], + }; + + let depth_texture = Self::create_depth_texture(&config, &device); + + let mut state = Self { + surface, + device, + queue, + config, + depth_texture, + }; + + state.resize(size); + + state + } + + pub fn create_depth_texture( + config: &wgpu::SurfaceConfiguration, + device: &wgpu::Device, + ) -> wgpu::TextureView { + device + .create_texture(&wgpu::TextureDescriptor { + label: Some("depth texture"), + size: wgpu::Extent3d { + width: config.width, + height: config.height, + depth_or_array_layers: 1, + }, + mip_level_count: 1, + sample_count: 1, + dimension: wgpu::TextureDimension::D2, + format: wgpu::TextureFormat::Depth32Float, + usage: wgpu::TextureUsages::RENDER_ATTACHMENT + | wgpu::TextureUsages::TEXTURE_BINDING, + view_formats: &[], + }) + .create_view(&wgpu::TextureViewDescriptor::default()) + } + + pub fn resize(&mut self, size: winit::dpi::PhysicalSize<u32>) { + if size.width > 0 && size.height > 0 { + self.config.width = size.width; + self.config.height = size.height; + self.configure_surface(); + self.depth_texture = Self::create_depth_texture(&self.config, &self.device); + } + } + + pub fn configure_surface(&mut self) { + self.surface.configure(&self.device, &self.config); + } +} |