#[allow(unused_imports)] use log::{debug, error, info, trace, warn}; use std::{ mem::ManuallyDrop, iter, cell::RefCell, }; use crate::{ io::Output, utils::Triangle, }; mod gpu; use self::gpu::Gpu; mod swap_system; use self::swap_system::SwapSystem; mod pipeline; use self::pipeline::Pipeline; //--Renderer implementation------------------------------------------------------------------------- #[derive(Debug)] pub struct Renderer { instance: ManuallyDrop, gpu: ManuallyDrop>, swap_systems: Vec>, pipelines: Vec>, } impl Drop for Renderer where B: gfx_hal::Backend, { fn drop(&mut self) { use gfx_hal::{ Instance, device::Device, }; debug!("Dropping Pipelines..."); for pipeline in self.pipelines.drain(..) { pipeline.drop(&mut self.gpu); } debug!("Waiting for device to idle..."); let _ = self.gpu .device() .wait_idle(); info!("Dropping Renderer..."); unsafe { for mut swap_system in self.swap_systems.drain(..) { self.instance.destroy_surface(swap_system.drop(&mut self.gpu)); } ManuallyDrop::drop(&mut self.gpu); ManuallyDrop::drop(&mut self.instance); } trace!("Renderer dropped !"); } } impl Renderer where B: gfx_hal::Backend, { pub fn new<'a, W: 'a, O: 'a, I>(outputs: &mut I) -> Result, &'static str> where W: raw_window_handle::HasRawWindowHandle, O: Output, I: Iterator>, { use gfx_hal::Instance; info!("Creating renderer..."); let instance = B::Instance::create("IV", 1) .map_err(|_| "Could not create instance")?; let (mut gpu, mut surfaces) = Gpu::new(&instance, outputs) .map_err(|err| err)?; let swap_systems = { surfaces .drain(..) .map(|surface| SwapSystem::new(&mut gpu, surface)) .collect::, &str>>()? }; let pipelines = vec!(Pipeline::new(&mut gpu, &swap_systems[0]) //TODO improve that .map_err(|err| err)?); debug!("Renderer created !"); Ok( Renderer { instance: ManuallyDrop::new(instance), gpu: ManuallyDrop::new(gpu), swap_systems, pipelines, }) } pub fn draw_clear_frame(&mut self, output: &RefCell, color: [f32; 4]) -> Result<(), &'static str> where W: raw_window_handle::HasRawWindowHandle, O: Output, { use gfx_hal::{ window::AcquireError, device::Device, queue::Submission, }; let swap_system = &mut self.swap_systems[output.borrow_mut().get_id()]; let mut frame = match swap_system.acquire_frame(&self.gpu) { Ok(frame) => frame, Err(err) => match err { AcquireError::NotReady => { return Err("Frame acquisition failed because all Frames are in use"); }, AcquireError::OutOfDate => { swap_system.recreate(&mut self.gpu)?; debug!("SwapSystem : {:#?}", swap_system); return Ok(()); }, _ => Err("Could not acquire Frame from SwapSystem")?, }}; trace!("Waiting for Frame..."); unsafe { let _ = self.gpu.device() .wait_for_fence(&frame.fences[0], !0) .map_err(|_| "Failed to wait for Fence")?; let _ = self.gpu.device() .reset_fence(&frame.fences[0]) .map_err(|_| "Failed to reset fence")?; } trace!("Recording CommandBuffer..."); unsafe { use gfx_hal::command::{ CommandBufferFlags, SubpassContents, ClearValue, ClearColor, CommandBuffer, }; frame.command_buffer.begin_primary(CommandBufferFlags::ONE_TIME_SUBMIT); let clear_value = ClearValue {color: ClearColor{float32: color}}; frame.command_buffer.begin_render_pass( &swap_system.render_pass, &frame.framebuffer.as_ref().unwrap(), swap_system.render_area, iter::once(clear_value), SubpassContents::Inline, ); frame.command_buffer.end_render_pass(); frame.command_buffer.finish(); } trace!("Submiting to queue..."); let submission = Submission { command_buffers: iter::once(&*frame.command_buffer), wait_semaphores: None, signal_semaphores: iter::once(&frame.signal_semaphores[0]), }; unsafe { use gfx_hal::queue::CommandQueue; self.gpu.queue_mut().submit(submission, Some(&frame.fences[0])); } let result = swap_system.present_frame(frame, &mut self.gpu); if result.is_err() { swap_system.recreate(&mut self.gpu).unwrap(); } Ok(()) } pub fn draw_triangle_frame(&mut self, output: &RefCell, triangle: Triangle, colors: [[f32; 3]; 3]) -> Result<(), &'static str> where W: raw_window_handle::HasRawWindowHandle, O: Output, { use gfx_hal::{ window::AcquireError, queue::Submission, }; let swap_system = &mut self.swap_systems[output.borrow_mut().get_id()]; let mut frame = match swap_system.acquire_frame(&self.gpu) { Ok(frame) => frame, Err(err) => match err { AcquireError::NotReady => { return Err("Frame acquisition failed because all Frames are in use"); }, AcquireError::OutOfDate => { swap_system.recreate(&mut self.gpu)?; debug!("SwapSystem : {:#?}", swap_system); return Ok(()); }, _ => Err("Could not acquire Frame from SwapSystem")?, }}; trace!("Uploading triangle data..."); let points = triangle.points_flat(); self.pipelines[0].write_vertex_buffer(&self.gpu, 0, (&points).to_vec())?; //TODO meh let colors_flat = colors.iter().flatten().copied().collect(); self.pipelines[0].write_vertex_buffer(&self.gpu, 1, colors_flat)?; trace!("Recording CommandBuffer..."); unsafe { use gfx_hal::command::{ CommandBufferFlags, SubpassContents, ClearValue, ClearColor, CommandBuffer, }; frame.command_buffer.begin_primary(CommandBufferFlags::ONE_TIME_SUBMIT); const TRIANGLE_CLEAR: ClearValue = ClearValue {color : ClearColor{float32 : [0.5, 0.5, 0.5, 1.0]}}; frame.command_buffer.begin_render_pass( &swap_system.render_pass, &frame.framebuffer.as_ref().unwrap(), swap_system.render_area, iter::once(TRIANGLE_CLEAR), SubpassContents::Inline, ); frame.command_buffer.bind_graphics_pipeline(self.pipelines[0].raw_pipeline()); // storing const data via the CommandBuffer //let buffer_ref: &B::Buffer = &self.buffer; //let buffers: Vec<[_; 1]> = vec![(buffer_ref, 0)].into(); frame.command_buffer.bind_vertex_buffers(0, self.pipelines[0].raw_vertex_buffers()); frame.command_buffer.draw(0..3, 0..1); frame.command_buffer.end_render_pass(); frame.command_buffer.finish(); } trace!("Submiting to queue..."); let submission = Submission { command_buffers: iter::once(&*frame.command_buffer), wait_semaphores: None, signal_semaphores: iter::once(&frame.signal_semaphores[0]), }; unsafe { use gfx_hal::queue::CommandQueue; self.gpu.queue_mut().submit(submission, Some(&frame.fences[0])); } let result = swap_system.present_frame(frame, &mut self.gpu); if result.is_err() { swap_system.recreate(&mut self.gpu).unwrap(); } Ok(()) } }