zray 0.0.0

A modular GPU renderer supporting voxel and rasterization pipelines
Documentation
pub mod render;

use crate::display::render::Renderer;
use std::sync::Arc;
use wgpu::{
    CurrentSurfaceTexture, Device, Instance, Queue, RequestAdapterOptions, Surface,
    SurfaceConfiguration, TextureViewDescriptor,
};
use winit::{application::ApplicationHandler, event::WindowEvent, window::Window as WinitWindow};

struct GpuState {
    surface: Surface<'static>,
    device: Device,
    queue: Queue,
    config: SurfaceConfiguration,
}

#[derive(Default)]
pub struct Window {
    pub inner: Option<Arc<WinitWindow>>,
    gpu: Option<GpuState>,
    renderer: Option<Box<dyn Renderer>>,
}
impl ApplicationHandler for Window {
    fn resumed(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) {
        let window = Arc::new(
            event_loop
                .create_window(WinitWindow::default_attributes())
                .unwrap(),
        );
        self.inner = Some(window.clone());
        let instance = Instance::default();
        let surface = instance
            .create_surface(window.clone())
            .expect("Could not create surface.");
        let adapter = pollster::block_on(instance.request_adapter(&RequestAdapterOptions {
            compatible_surface: Some(&surface),
            ..Default::default()
        }))
        .expect("Could not find an appropriate adapter.");
        let (device, queue) =
            pollster::block_on(adapter.request_device(&wgpu::DeviceDescriptor::default()))
                .expect("Failed to create device");
        let size = window.inner_size();
        let config = surface
            .get_default_config(&adapter, size.width, size.height)
            .unwrap();
        self.gpu = Some(GpuState {
            surface,
            device,
            queue,
            config,
        })
    }
    fn window_event(
        &mut self,
        event_loop: &winit::event_loop::ActiveEventLoop,
        _window_id: winit::window::WindowId,
        event: winit::event::WindowEvent,
    ) {
        let (Some(gpu), Some(renderer), Some(window)) =
            (&mut self.gpu, &mut self.renderer, &self.inner)
        else {
            return;
        };
        match event {
            WindowEvent::CloseRequested => {
                event_loop.exit();
            }
            WindowEvent::Resized(new_size) => {
                gpu.config.width = new_size.width;
                gpu.config.height = new_size.height;
                gpu.surface.configure(&gpu.device, &gpu.config);
            }
            WindowEvent::RedrawRequested => {
                let frame = gpu.surface.get_current_texture();
                match frame {
                    CurrentSurfaceTexture::Success(frame) => {
                        let view = frame.texture.create_view(&TextureViewDescriptor::default());
                        renderer
                            .render(&gpu.device, &gpu.queue, &view, window.inner_size())
                            .expect("Redraw failed: Renderer panic.");
                        frame.present();
                    }
                    CurrentSurfaceTexture::Outdated => {
                        gpu.surface.configure(&gpu.device, &gpu.config);
                    }
                    _ => {
                        eprintln!("Dropped frame: {:?}", frame);
                    }
                }
            }
            _ => {}
        }
    }
}