diff --git a/Cargo.lock b/Cargo.lock index 3b72c66..ee21473 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -284,9 +284,9 @@ dependencies = [ [[package]] name = "gfx-hal" -version = "0.5.0" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc96180204064c9493e0fe4a9efeb721e0ac59fe8e1906d0c659142a93114fb1" +checksum = "a18534b23d4c262916231511309bc1f307c74cda8dcb68b93a10ca213a22814b" dependencies = [ "bitflags", "raw-window-handle", diff --git a/Cargo.toml b/Cargo.toml index e490da6..f0bbe15 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ edition = "2018" log = "0.4.8" chrono = "0.4.11" fern = { version = "0.6.0", features = ["colored"] } -gfx-hal = "0.5.0" +gfx-hal = "0.5.3" winit = "0.22.0" raw-window-handle = "0.3.3" num-traits = "0.2.12" diff --git a/doc/architecture b/doc/architecture index e5a3284..68d9f08 100644 --- a/doc/architecture +++ b/doc/architecture @@ -1 +1 @@ -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 \ No newline at end of file +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 \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 81951ff..0c2d6fc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -65,11 +65,18 @@ pub fn run() -> Result<(), &'static str> { let mut renderer: Renderer = Renderer::new(&mut windows)?; //let local_state = LocalState::default(); - let color = [0.5, 0.0, 0.0, 0.1]; + let color = [0.5, 0.0, 0.0, 1.0]; + for window in &mut windows { + let _ = renderer.draw_clear_frame(window, color); + } + loop { - for mut window in &mut windows { - let _ = renderer.draw_clear_frame(&mut window, color); + for window in &mut windows { + match renderer.draw_frame(window) { + Err(err) => println!("{}", err), + _ => (), + } } } } diff --git a/src/renderer.rs b/src/renderer.rs index 73e3b68..86b2f48 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -86,18 +86,42 @@ where }) } - pub fn draw_clear_frame(&mut self, output: &mut O, _color: [f32; 4]) + pub fn draw_frame(&mut self, output: &mut O) -> Result<(), &'static str> where T: raw_window_handle::HasRawWindowHandle, O: Output { - let swap_index = output.get_id(); - let frame = self.swap_systems[swap_index].acquire_frame(); + use gfx_hal::window::AcquireError; + + let swap_index = output.get_id(); + let (frame, image_id) = match self.swap_systems[swap_index].acquire_frame() { + Ok((frame, image_id)) => (frame, image_id), + Err(err) => match err { + AcquireError::NotReady => { + return Err("Frame acquisition failed because all Frames are in use"); + }, + _ => Err("Could not acquire Frame from SwapSystem")?, + }}; + + let _ = frame.sync_gpu(&self.gpu)?; + + let queue = &mut self.gpu.queue_mut(); + frame.submit(queue); + + let _ = self.swap_systems[swap_index].present_frame(frame, image_id, queue)?; - frame.sync_gpu(&self.gpu); - Ok(()) } + + pub fn draw_clear_frame(&mut self, output: &mut O, color: [f32; 4]) + -> Result<(), &'static str> + where + T: raw_window_handle::HasRawWindowHandle, + O: Output + { + self.swap_systems[output.get_id()].configure_render_pass(color)?; + self.draw_frame(output) + } } diff --git a/src/renderer/gpu.rs b/src/renderer/gpu.rs index eefb2ed..ef4ee26 100644 --- a/src/renderer/gpu.rs +++ b/src/renderer/gpu.rs @@ -162,7 +162,7 @@ where trace!("Creating CommandPool..."); device .create_command_pool(queue_group.family, - CommandPoolCreateFlags::RESET_INDIVIDUAL) + CommandPoolCreateFlags::empty()) .map_err(|_| "Could not create CommandPool")? }; @@ -189,5 +189,9 @@ where pub fn command_pool_mut(&mut self) -> &mut B::CommandPool { &mut self.command_pool } + + pub fn queue_mut(&mut self) -> &mut B::CommandQueue { + &mut self.queue_group.queues[0] + } } diff --git a/src/renderer/swap_system.rs b/src/renderer/swap_system.rs index 1fb820f..81056c9 100644 --- a/src/renderer/swap_system.rs +++ b/src/renderer/swap_system.rs @@ -4,10 +4,11 @@ use log::{debug, error, info, trace, warn}; use std::{ mem::ManuallyDrop, ptr::read, + collections::HashMap, }; use gfx_hal::{ - window::Extent2D, + window::{Extent2D, AcquireError}, pso::Rect as GfxRect, format::Format, }; @@ -21,13 +22,14 @@ use super::gpu::Gpu; #[derive(Debug)] pub struct SwapSystem { surface: ManuallyDrop, - render_area: GfxRect, format: Format, extent: Extent2D, + render_area: GfxRect, //TODO may not be needed (duplicate of extent) swapchain: ManuallyDrop, spare_semaphore: ManuallyDrop, render_pass: ManuallyDrop, - frames: Vec>, + frames: HashMap>, + frame_nb: usize, } impl SwapSystem @@ -41,7 +43,7 @@ where }; debug!("Dropping SwapSystem..."); - for mut frame in self.frames.drain(..) { + for (_, mut frame) in self.frames.drain() { frame.drop(gpu); } unsafe { @@ -51,7 +53,7 @@ where ManuallyDrop::into_inner(read(&mut self.spare_semaphore))); gpu.device().destroy_swapchain( ManuallyDrop::into_inner(read(&mut self.swapchain))); - //render area can be dropped automatically + //render_area extent and format can be dropped automatically instance.destroy_surface( ManuallyDrop::into_inner(read(&mut self.surface))); } @@ -63,14 +65,9 @@ where { use gfx_hal::{ window::SwapchainConfig, - pso::Rect, }; debug!("Creating SwapSystem..."); - //TODO handle render_area properly - warn!("Hard-coding render area size !"); - let render_area = Rect{x: 0, y: 0, w: 1280, h: 720}; - trace!("Obtaining surface capabilities..."); let capabilities = { use gfx_hal::window::Surface; @@ -92,19 +89,81 @@ where .iter() .find(|f| f.base_format().1 == ChannelType::Srgb) .cloned() - .ok_or("Could no find suitabe format")? + .ok_or("Could no find suitable format")? }}; - trace!("Getting surface capabilities extend..."); + trace!("Getting surface's render area size..."); let extent = capabilities.current_extent .unwrap_or(*capabilities.extents.end()) .clone(); + let render_area = GfxRect{x: 0, y: 0, w: extent.width as i16, h: extent.height as i16}; trace!("Generating Swapchain configuration..."); - //TODO improve swapchain configuration - let swapchain_config = SwapchainConfig::from_caps(&capabilities, format, extent); - let swapchain_config = swapchain_config.with_image_count(3); - debug!("Swapchain configuration : {:?}", swapchain_config); + let (swapchain_config, frame_nb) = { + + let present_mode = { + use gfx_hal::window::PresentMode; + + [PresentMode::MAILBOX, PresentMode::FIFO, PresentMode::RELAXED, + PresentMode::IMMEDIATE] + .iter() + .cloned() + .find(|pm| capabilities.present_modes.contains(*pm)) + .ok_or("No PresentMode values specified!")? + }; + + let composite_alpha_mode = { + use gfx_hal::window::CompositeAlphaMode; + + [CompositeAlphaMode::OPAQUE, CompositeAlphaMode::INHERIT, + CompositeAlphaMode::PREMULTIPLIED, CompositeAlphaMode::POSTMULTIPLIED] + .iter() + .cloned() + .find(|ca| capabilities.composite_alpha_modes.contains(*ca)) + .ok_or("No CompositeAlpha values specified!")? + }; + + let image_count = { + use std::cmp::{min, max}; + use gfx_hal::window::PresentMode; + + let count = match present_mode { + PresentMode::MAILBOX => 3, + _ => 2, //TODO to be checked + }; + max(capabilities.image_count.start().clone(), + min(capabilities.image_count.end().clone(), count)) + }; + + warn!("Hard-coding number of layers per image !"); + let image_layers = 1; + + let image_usage = { + use gfx_hal::image::Usage; + + if capabilities.usage.contains(Usage::COLOR_ATTACHMENT) { + Usage::COLOR_ATTACHMENT + } else { + Err("The Surface isn't capable of supporting color!")? + }}; + + ( + SwapchainConfig { + present_mode, + composite_alpha_mode, + format: format.clone(), + extent: extent.clone(), + image_count: image_count.clone(), + image_layers, + image_usage, + }, + image_count as usize + ) + }; + // //TODO improve swapchain configuration + // let swapchain_config = SwapchainConfig::from_caps(&capabilities, format, extent); + // let swapchain_config = swapchain_config.with_image_count(3); + debug!("Swapchain configuration : {:#?}", swapchain_config); trace!("Creating Swapchain..."); let (swapchain, backbuffer) = unsafe { @@ -115,6 +174,8 @@ where .map_err(|_| "Failed to create swapchain and backbuffer")? }; + + trace!("Creating spare Semaphore..."); let spare_semaphore = { use gfx_hal::device::Device; @@ -157,31 +218,83 @@ where } }; - //TODO adapt to improved swapchain configuration warn!("Generating hard-coded number of frames !"); - let frames = { - backbuffer - .iter() - .map(|img| - Frame::new(gpu, &img, &format, &render_pass, &extent)) - .collect::, &str>>()? + let mut frames = HashMap::with_capacity(frame_nb); + for i in 0..frame_nb { + let frame = Frame::new(gpu, &backbuffer[i], &format, &render_pass, &extent) + .map_err(|_| "Could not create frame")?; + frames.insert(i, frame); }; + let frame_nb = frames.len(); + trace!("Created SwapSystem !"); Ok( SwapSystem { surface: ManuallyDrop::new(surface), - render_area, format, extent, + render_area, swapchain: ManuallyDrop::new(swapchain), spare_semaphore: ManuallyDrop::new(spare_semaphore), render_pass: ManuallyDrop::new(render_pass), frames, + frame_nb, }) } - pub fn acquire_frame(&mut self) -> Frame { - unimplemented!(); + pub fn configure_render_pass(&mut self, color: [f32; 4]) -> Result<(), &'static str> { + + if self.frames.len() != self.frame_nb { + return Err("Tried to configure RenderPass with frames acquired"); + } + + debug!("Configuring Color RenderPass..."); + for (_, frame) in &mut self.frames { + frame.record_command_buffer(&self.render_pass, self.render_area.clone(), color); + } + + Ok(()) + } + + pub fn acquire_frame(&mut self) -> Result<(Frame, u32), AcquireError> { + use gfx_hal::window::Swapchain; + + trace!("Acquiring Frame..."); + let image_id = unsafe { + match self.swapchain.acquire_image(core::u64::MAX, Some(&self.spare_semaphore), None) { + Ok((image_id, suboptimal)) => { + match suboptimal { + Some(_) => return Err(AcquireError::OutOfDate), + None => image_id, + }}, + Err(err) => return Err(err), + }}; + + //TODO give back image to swaphain + //debug!("image id : {}", image_id); + let mut frame = match self.frames.remove(&(image_id as usize)) { + Some(frame) => frame, + None => return Err(AcquireError::NotReady), + }; + frame.swap_semaphore(&mut self.spare_semaphore); + + Ok((frame, image_id)) + } + + pub fn present_frame(&mut self, frame: Frame, image_id: u32, queue: &mut B::CommandQueue) + -> Result<(), &'static str> { + use gfx_hal::window::Swapchain; + + trace!("Presenting Frame..."); + let _result = unsafe { + self.swapchain + .present(queue, image_id, Some(frame.get_present_semaphore())) + .map_err(|_| "Failed to present into the swapchain")?; + }; + + self.frames.insert(image_id as usize, frame); + + Ok(()) } } diff --git a/src/renderer/swap_system/frame.rs b/src/renderer/swap_system/frame.rs index a2d99d4..723c96f 100644 --- a/src/renderer/swap_system/frame.rs +++ b/src/renderer/swap_system/frame.rs @@ -5,7 +5,6 @@ use std::{ mem::ManuallyDrop, ptr::read, iter, - borrow::Borrow, }; use gfx_hal::{ @@ -40,7 +39,6 @@ where trace!("Dropping Frame..."); unsafe { - //TODO check that gpu.command_pool_mut().free( iter::once(ManuallyDrop::into_inner(read(&mut self.command_buffer)))); gpu.device().destroy_framebuffer( @@ -109,7 +107,7 @@ where layers : 0..1, }, ) - .map_err(|_| "Could not create ImageViews")? + .map_err(|_| "Could not create ImageView")? }; trace!("Creating Framebuffer..."); @@ -147,61 +145,77 @@ where pub fn sync_gpu(&self, gpu: &Gpu) -> Result<(), &'static str>{ use gfx_hal::device::Device; + trace!("Waiting for Frame..."); unsafe { - gpu.device() + let _ = gpu.device() .wait_for_fence(&self.fences[0], !0) - .map_err(|_| "Failed to wait for Fence"); - gpu.device() + .map_err(|_| "Failed to wait for Fence")?; + let _ = gpu.device() .reset_fence(&self.fences[0]) - .map_err(|_| "Failed to reset fence"); + .map_err(|_| "Failed to reset fence")?; } Ok(()) } -// pub fn construct_pipeline<'a, T, Ic, S, Iw, Is>(&self, -// render_pass: &B::RenderPass, -// render_area: GfxRect, -// color: [f32; 4]) -// -> Result, &'static str> -// where -// T: 'a + Borrow, -// Ic: IntoIterator, -// S: 'a + Borrow, -// Iw: IntoIterator, -// Is: IntoIterator, -// { -// use gfx_hal::pso::PipelineStage; -// -// unsafe { -// use gfx_hal::command::{ -// CommandBufferFlags, -// SubpassContents, -// ClearValue, -// ClearColor, -// CommandBuffer, -// }; -// -// self.command_buffer.begin_primary(CommandBufferFlags::ONE_TIME_SUBMIT); -// -// let clear_value = ClearValue {color: ClearColor{float32: color}}; -// -// self.command_buffer.begin_render_pass( -// render_pass, -// &self.framebuffer, -// render_area, -// iter::once(clear_value), -// SubpassContents::Inline, -// ); -// self.command_buffer.end_render_pass(); -// self.command_buffer.finish(); -// } -// -// Ok( Submission { -// command_buffers: iter::once(&self.command_buffer), -// wait_semaphores: iter::once((&self.wait_semaphores[0], -// PipelineStage::COLOR_ATTACHMENT_OUTPUT)), -// signal_semaphores: iter::once(&self.signal_semaphores[0]), -// }) -// } + pub fn record_command_buffer(&mut self, + render_pass: &B::RenderPass, + render_area: GfxRect, + color: [f32; 4]) { + + trace!("Recording CommandBuffer..."); + + unsafe { + use gfx_hal::command::{ + CommandBufferFlags, + SubpassContents, + ClearValue, + ClearColor, + CommandBuffer, + }; + + self.command_buffer.begin_primary(CommandBufferFlags::EMPTY); + + let clear_value = ClearValue {color: ClearColor{float32: color}}; + + self.command_buffer.begin_render_pass( + render_pass, + &self.framebuffer, + render_area, + iter::once(clear_value), + SubpassContents::Inline, + ); + self.command_buffer.end_render_pass(); + self.command_buffer.finish(); + } + } + + pub fn submit(&self, queue: &mut B::CommandQueue) { + use gfx_hal::pso::PipelineStage; + + trace!("Submiting to queue..."); + let submission = Submission { + command_buffers: iter::once(&*self.command_buffer), + wait_semaphores: iter::once((&self.wait_semaphores[0], + PipelineStage::COLOR_ATTACHMENT_OUTPUT)), + signal_semaphores: iter::once(&self.signal_semaphores[0]), + }; + + unsafe { + use gfx_hal::queue::CommandQueue; + + queue.submit(submission, Some(&self.fences[0])); + } + } + + pub fn swap_semaphore(&mut self, semaphore: &mut B::Semaphore) { + + std::mem::swap(&mut self.wait_semaphores[0], semaphore); + } + + pub fn get_present_semaphore(&self) -> &B::Semaphore { + + &self.signal_semaphores[0] + } } +