use crate::Scene; use std::sync::Arc; const SURFACE_FRAME_COUNT: u32 = 3; const MAX_FRAME_TIME_MS: u32 = 1000; pub struct BladeRenderer { gpu: Arc, command_encoder: blade::CommandEncoder, last_sync_point: Option, } impl BladeRenderer { pub fn new(gpu: Arc, size: blade::Extent) -> Self { let _surface_format = gpu.resize(blade::SurfaceConfig { size, usage: blade::TextureUsage::TARGET, frame_count: SURFACE_FRAME_COUNT, }); let command_encoder = gpu.create_command_encoder(blade::CommandEncoderDesc { name: "main", buffer_count: 2, }); Self { gpu, command_encoder, last_sync_point: None, } } pub fn destroy(&mut self) { self.gpu.destroy_command_encoder(&mut self.command_encoder); } fn wait_for_gpu(&mut self) { if let Some(last_sp) = self.last_sync_point.take() { if !self.gpu.wait_for(&last_sp, MAX_FRAME_TIME_MS) { panic!("GPU hung"); } } } pub fn resize(&mut self, size: blade::Extent) { self.wait_for_gpu(); self.gpu.resize(blade::SurfaceConfig { size, usage: blade::TextureUsage::TARGET, frame_count: SURFACE_FRAME_COUNT, }); } pub fn draw(&mut self, scene: &Scene) { let frame = self.gpu.acquire_frame(); self.command_encoder.start(); self.command_encoder.init_texture(frame.texture()); self.command_encoder.present(frame); let sync_point = self.gpu.submit(&mut self.command_encoder); self.wait_for_gpu(); self.last_sync_point = Some(sync_point); } }