summaryrefslogtreecommitdiff
path: root/src/gfx/gpu.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/gfx/gpu.rs')
-rw-r--r--src/gfx/gpu.rs168
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);
+ }
+}