use crate::{scene_prepare::ScenePreparer, scene_render::ScenePipeline}; use anyhow::{Result, anyhow}; use log::{info, warn}; use pollster::FutureExt; use std::sync::Arc; use weareshared::tree::SceneTree; use wgpu::{ Backends, CommandEncoderDescriptor, Device, DeviceDescriptor, Features, Instance, InstanceDescriptor, Limits, MaintainBase, PowerPreference, Queue, RequestAdapterOptions, Surface, SurfaceConfiguration, TextureViewDescriptor, }; use winit::window::Window; pub struct Renderer<'a> { surface: Surface<'a>, queue: Queue, device: Arc, surface_configuration: SurfaceConfiguration, scene_pipeline: ScenePipeline, pub scene_prepare: ScenePreparer, surface_needs_reconfigure: bool, } impl<'a> Renderer<'a> { pub fn new(window: &'a Window) -> Result { info!("wgpu init"); let instance = Instance::new(InstanceDescriptor { backends: Backends::all(), ..Default::default() }); let surface = instance.create_surface(window)?; let adapter = instance .request_adapter(&RequestAdapterOptions { compatible_surface: Some(&surface), power_preference: PowerPreference::HighPerformance, ..Default::default() }) .block_on() .ok_or(anyhow!("no adapter found"))?; let (device, queue) = adapter .request_device( &DeviceDescriptor { required_features: Features::PUSH_CONSTANTS, required_limits: Limits { max_push_constant_size: 48, ..Limits::default() }, ..Default::default() }, None, ) .block_on()?; let surface_configuration = surface .get_default_config(&adapter, 256, 256) .ok_or(anyhow!("no default config"))?; surface.configure(&device, &surface_configuration); let device = Arc::new(device); Ok(Self { scene_pipeline: ScenePipeline::new(&device, surface_configuration.format), scene_prepare: ScenePreparer::new(device.clone()), surface, device, queue, surface_configuration, surface_needs_reconfigure: false, }) } pub fn resize(&mut self, width: u32, height: u32) { self.surface_configuration.width = width; self.surface_configuration.height = height; self.surface .configure(&self.device, &self.surface_configuration); } pub fn draw(&mut self, scene: &SceneTree) -> Result<()> { if self.surface_needs_reconfigure { self.surface .configure(&self.device, &self.surface_configuration); self.surface_needs_reconfigure = false } let target = self.surface.get_current_texture()?; if target.suboptimal { warn!("suboptimal swapchain texture"); self.surface_needs_reconfigure = true; } let target_view = target .texture .create_view(&TextureViewDescriptor::default()); let mut commands = self .device .create_command_encoder(&CommandEncoderDescriptor { label: None }); self.scene_pipeline.draw( &mut commands, &target_view, scene, &self.scene_prepare.prefabs, &mut self.scene_prepare.prefabs_needed, ); let i = self.queue.submit(Some(commands.finish())); self.device.poll(MaintainBase::WaitForSubmissionIndex(i)); target.present(); Ok(()) } }