diff options
Diffstat (limited to 'stockton-render/src/draw/target.rs')
-rw-r--r-- | stockton-render/src/draw/target.rs | 334 |
1 files changed, 166 insertions, 168 deletions
diff --git a/stockton-render/src/draw/target.rs b/stockton-render/src/draw/target.rs index 1ee208b..8d308d9 100644 --- a/stockton-render/src/draw/target.rs +++ b/stockton-render/src/draw/target.rs @@ -1,14 +1,19 @@ //! Resources needed for drawing on the screen, including sync objects -use core::{iter::once, mem::ManuallyDrop}; +use std::{ + array::IntoIter, + borrow::Borrow, + iter::{empty, once}, + mem::ManuallyDrop, +}; use arrayvec::ArrayVec; use hal::{ - format::{ChannelType, Format, Swizzle}, - image::{Extent, Usage as ImgUsage, ViewKind}, - prelude::*, + buffer::SubRange, + command::RenderAttachmentInfo, + format::{ChannelType, Format}, + image::{Extent, FramebufferAttachment, Usage as ImgUsage, ViewCapabilities}, pso::Viewport, - queue::Submission, window::{CompositeAlphaMode, Extent2D, PresentMode, SwapchainConfig}, }; use na::Mat4; @@ -22,13 +27,6 @@ use super::{ }; use crate::types::*; -/// Defines the colour range we use. -const COLOR_RANGE: hal::image::SubresourceRange = hal::image::SubresourceRange { - aspects: hal::format::Aspects::COLOR, - levels: 0..1, - layers: 0..1, -}; - #[derive(Debug, Clone)] pub struct SwapchainProperties { pub format: Format, @@ -49,7 +47,7 @@ pub enum NoSupportedValuesError { impl SwapchainProperties { pub fn find_best( adapter: &Adapter, - surface: &Surface, + surface: &SurfaceT, ) -> Result<SwapchainProperties, NoSupportedValuesError> { let caps = surface.capabilities(&adapter.physical_device); let formats = surface.supported_formats(&adapter.physical_device); @@ -124,8 +122,8 @@ impl SwapchainProperties { } pub struct TargetChain { - /// Swapchain we're targeting - pub swapchain: ManuallyDrop<Swapchain>, + /// Surface we're targeting + pub surface: ManuallyDrop<SurfaceT>, pub properties: SwapchainProperties, @@ -147,16 +145,14 @@ pub struct TargetChain { } impl TargetChain { - #[allow(clippy::too_many_arguments)] pub fn new( - device: &mut Device, + device: &mut DeviceT, adapter: &Adapter, - surface: &mut Surface, + mut surface: SurfaceT, pipeline: &CompletePipeline, ui_pipeline: &UiPipeline, - cmd_pool: &mut CommandPool, + cmd_pool: &mut CommandPoolT, properties: SwapchainProperties, - old_swapchain: Option<Swapchain>, ) -> Result<TargetChain, TargetChainCreationError> { let caps = surface.capabilities(&adapter.physical_device); @@ -181,13 +177,6 @@ impl TargetChain { image_usage: ImgUsage::COLOR_ATTACHMENT, }; - // Swapchain - let (swapchain, mut backbuffer) = unsafe { - device - .create_swapchain(surface, swap_config, old_swapchain) - .map_err(|_| TargetChainCreationError::Todo)? - }; - let depth_buffer = { use hal::format::Aspects; use hal::image::SubresourceRange; @@ -199,8 +188,10 @@ impl TargetChain { ImgUsage::DEPTH_STENCIL_ATTACHMENT, SubresourceRange { aspects: Aspects::DEPTH, - levels: 0..1, - layers: 0..1, + level_start: 0, + level_count: Some(1), + layer_start: 0, + layer_count: Some(1), }, properties.extent.width as usize, properties.extent.height as usize, @@ -208,17 +199,24 @@ impl TargetChain { .map_err(|_| TargetChainCreationError::Todo) }?; - let mut targets: Vec<TargetResources> = Vec::with_capacity(backbuffer.len()); - let mut sync_objects: Vec<SyncObjects> = Vec::with_capacity(backbuffer.len()); - for image in backbuffer.drain(..) { + let fat = swap_config.framebuffer_attachment(); + let mut targets: Vec<TargetResources> = + Vec::with_capacity(swap_config.image_count as usize); + let mut sync_objects: Vec<SyncObjects> = + Vec::with_capacity(swap_config.image_count as usize); + for _ in 0..swap_config.image_count { targets.push( TargetResources::new( device, cmd_pool, &pipeline.renderpass, &ui_pipeline.renderpass, - image, - &(*depth_buffer.image_view), + fat.clone(), + FramebufferAttachment { + usage: ImgUsage::DEPTH_STENCIL_ATTACHMENT, + view_caps: ViewCapabilities::empty(), + format: properties.depth_format, + }, &properties, ) .map_err(|_| TargetChainCreationError::Todo)?, @@ -228,8 +226,15 @@ impl TargetChain { .push(SyncObjects::new(device).map_err(|_| TargetChainCreationError::Todo)?); } + // Configure Swapchain + unsafe { + surface + .configure_swapchain(device, swap_config) + .map_err(|_| TargetChainCreationError::Todo)?; + } + Ok(TargetChain { - swapchain: ManuallyDrop::new(swapchain), + surface: ManuallyDrop::new(surface), targets: targets.into_boxed_slice(), sync_objects: sync_objects.into_boxed_slice(), depth_buffer: ManuallyDrop::new(depth_buffer), @@ -239,19 +244,24 @@ impl TargetChain { }) } - pub fn deactivate(self, device: &mut Device, cmd_pool: &mut CommandPool) { - let swapchain = self.deactivate_with_recyling(device, cmd_pool); + pub fn deactivate( + self, + instance: &mut InstanceT, + device: &mut DeviceT, + cmd_pool: &mut CommandPoolT, + ) { + let surface = self.deactivate_with_recyling(device, cmd_pool); unsafe { - device.destroy_swapchain(swapchain); + instance.destroy_surface(surface); } } pub fn deactivate_with_recyling( - self, - device: &mut Device, - cmd_pool: &mut CommandPool, - ) -> Swapchain { + mut self, + device: &mut DeviceT, + cmd_pool: &mut CommandPoolT, + ) -> SurfaceT { use core::ptr::read; unsafe { ManuallyDrop::into_inner(read(&self.depth_buffer)).deactivate(device); @@ -263,84 +273,102 @@ impl TargetChain { for i in 0..self.sync_objects.len() { read(&self.sync_objects[i]).deactivate(device); } + + self.surface.unconfigure_swapchain(device); } - unsafe { ManuallyDrop::into_inner(read(&self.swapchain)) } + unsafe { ManuallyDrop::into_inner(read(&self.surface)) } } pub fn prep_next_target<'a>( &'a mut self, - device: &mut Device, + device: &mut DeviceT, draw_buffers: &mut DrawBuffers<UvPoint>, pipeline: &CompletePipeline, vp: &Mat4, - ) -> Result<&'a mut crate::types::CommandBuffer, &'static str> { + ) -> Result< + ( + &'a mut crate::types::CommandBufferT, + <SurfaceT as PresentationSurface<back::Backend>>::SwapchainImage, + ), + &'static str, + > { self.last_syncs = (self.last_syncs + 1) % self.sync_objects.len(); let syncs = &mut self.sync_objects[self.last_syncs]; + self.last_image = (self.last_image + 1) % self.targets.len() as u32; + + let target = &mut self.targets[self.last_image as usize]; + // Get the image - let (image_index, _) = unsafe { - self.swapchain - .acquire_image(core::u64::MAX, Some(&syncs.get_image), None) + let (img, _) = unsafe { + self.surface + .acquire_image(core::u64::MAX) .map_err(|_| "FrameError::AcquireError")? }; - self.last_image = image_index; - - let target = &mut self.targets[image_index as usize]; - // Make sure whatever was last using this has finished unsafe { device .wait_for_fence(&syncs.present_complete, core::u64::MAX) .map_err(|_| "FrameError::SyncObjectError")?; device - .reset_fence(&syncs.present_complete) + .reset_fence(&mut syncs.present_complete) .map_err(|_| "FrameError::SyncObjectError")?; }; // Record commands unsafe { - use hal::buffer::IndexBufferView; use hal::command::{ ClearColor, ClearDepthStencil, ClearValue, CommandBufferFlags, SubpassContents, }; use hal::pso::ShaderStageFlags; - // Colour to clear window to - let clear_values = [ - ClearValue { - color: ClearColor { - float32: [0.0, 0.0, 0.0, 1.0], - }, - }, - ClearValue { - depth_stencil: ClearDepthStencil { - depth: 1.0, - stencil: 0, - }, - }, - ]; - // Get references to our buffers let (vbufs, ibuf) = { let vbufref: &<back::Backend as hal::Backend>::Buffer = draw_buffers.vertex_buffer.get_buffer(); - let vbufs: ArrayVec<[_; 1]> = [(vbufref, 0)].into(); + let vbufs: ArrayVec<[_; 1]> = [( + vbufref, + SubRange { + offset: 0, + size: None, + }, + )] + .into(); let ibuf = draw_buffers.index_buffer.get_buffer(); (vbufs, ibuf) }; - target.cmd_buffer.begin_primary(CommandBufferFlags::EMPTY); + target.cmd_buffer.begin_primary(CommandBufferFlags::empty()); // Main render pass / pipeline target.cmd_buffer.begin_render_pass( &pipeline.renderpass, &target.framebuffer, self.properties.viewport.rect, - clear_values.iter(), + vec![ + RenderAttachmentInfo { + image_view: img.borrow(), + clear_value: ClearValue { + color: ClearColor { + float32: [0.0, 0.0, 0.0, 1.0], + }, + }, + }, + RenderAttachmentInfo { + image_view: &*self.depth_buffer.image_view, + clear_value: ClearValue { + depth_stencil: ClearDepthStencil { + depth: 1.0, + stencil: 0, + }, + }, + }, + ] + .into_iter(), SubpassContents::Inline, ); target.cmd_buffer.bind_graphics_pipeline(&pipeline.pipeline); @@ -356,22 +384,26 @@ impl TargetChain { ); // Bind buffers - target.cmd_buffer.bind_vertex_buffers(0, vbufs); - target.cmd_buffer.bind_index_buffer(IndexBufferView { - buffer: ibuf, - offset: 0, - index_type: hal::IndexType::U16, - }); + target.cmd_buffer.bind_vertex_buffers(0, vbufs.into_iter()); + target.cmd_buffer.bind_index_buffer( + &ibuf, + SubRange { + offset: 0, + size: None, + }, + hal::IndexType::U16, + ); }; - Ok(&mut target.cmd_buffer) + Ok((&mut target.cmd_buffer, img)) } pub fn target_2d_pass<'a>( &'a mut self, draw_buffers: &mut DrawBuffers<UiPoint>, + img: &<SurfaceT as PresentationSurface<back::Backend>>::SwapchainImage, pipeline: &UiPipeline, - ) -> Result<&'a mut CommandBuffer, &'static str> { + ) -> Result<&'a mut CommandBufferT, &'static str> { let target = &mut self.targets[self.last_image as usize]; unsafe { @@ -381,28 +413,27 @@ impl TargetChain { target.cmd_buffer.pipeline_barrier( PipelineStage::BOTTOM_OF_PIPE..PipelineStage::TOP_OF_PIPE, hal::memory::Dependencies::empty(), - &[], + std::iter::empty(), ); } // Record commands unsafe { - use hal::buffer::IndexBufferView; use hal::command::{ClearColor, ClearValue, SubpassContents}; - // Colour to clear window to - let clear_values = [ClearValue { - color: ClearColor { - float32: [1.0, 0.0, 0.0, 1.5], - }, - }]; - // Get references to our buffers let (vbufs, ibuf) = { let vbufref: &<back::Backend as hal::Backend>::Buffer = draw_buffers.vertex_buffer.get_buffer(); - let vbufs: ArrayVec<[_; 1]> = [(vbufref, 0)].into(); + let vbufs: ArrayVec<[_; 1]> = [( + vbufref, + SubRange { + offset: 0, + size: None, + }, + )] + .into(); let ibuf = draw_buffers.index_buffer.get_buffer(); (vbufs, ibuf) @@ -413,18 +444,29 @@ impl TargetChain { &pipeline.renderpass, &target.framebuffer_2d, self.properties.viewport.rect, - clear_values.iter(), + vec![RenderAttachmentInfo { + image_view: img.borrow(), + clear_value: ClearValue { + color: ClearColor { + float32: [0.0, 0.0, 0.0, 1.0], + }, + }, + }] + .into_iter(), SubpassContents::Inline, ); target.cmd_buffer.bind_graphics_pipeline(&pipeline.pipeline); // Bind buffers - target.cmd_buffer.bind_vertex_buffers(0, vbufs); - target.cmd_buffer.bind_index_buffer(IndexBufferView { - buffer: ibuf, - offset: 0, - index_type: hal::IndexType::U16, - }); + target.cmd_buffer.bind_vertex_buffers(0, vbufs.into_iter()); + target.cmd_buffer.bind_index_buffer( + &ibuf, + SubRange { + offset: 0, + size: None, + }, + hal::IndexType::U16, + ); }; Ok(&mut target.cmd_buffer) @@ -432,7 +474,8 @@ impl TargetChain { pub fn finish_and_submit_target( &mut self, - command_queue: &mut CommandQueue, + img: <SurfaceT as PresentationSurface<back::Backend>>::SwapchainImage, + command_queue: &mut QueueT, ) -> Result<(), &'static str> { let syncs = &mut self.sync_objects[self.last_syncs]; let target = &mut self.targets[self.last_image as usize]; @@ -442,31 +485,16 @@ impl TargetChain { target.cmd_buffer.finish(); } - // Make submission object - let command_buffers: std::iter::Once<&CommandBuffer> = once(&target.cmd_buffer); - let wait_semaphores: std::iter::Once<(&Semaphore, hal::pso::PipelineStage)> = once(( - &syncs.get_image, - hal::pso::PipelineStage::COLOR_ATTACHMENT_OUTPUT, - )); - let signal_semaphores: std::iter::Once<&Semaphore> = once(&syncs.render_complete); - - let present_wait_semaphores: std::iter::Once<&Semaphore> = once(&syncs.render_complete); - - let submission = Submission { - command_buffers, - wait_semaphores, - signal_semaphores, - }; - // Submit it unsafe { - command_queue.submit(submission, Some(&syncs.present_complete)); - self.swapchain - .present( - command_queue, - self.last_image as u32, - present_wait_semaphores, - ) + command_queue.submit( + once(&*target.cmd_buffer), + empty(), + once(&*syncs.render_complete), + Some(&mut syncs.present_complete), + ); + command_queue + .present(&mut self.surface, img, Some(&mut *syncs.render_complete)) .map_err(|_| "FrameError::PresentError")?; }; @@ -477,53 +505,34 @@ impl TargetChain { /// Resources for a single target frame, including sync objects pub struct TargetResources { /// Command buffer to use when drawing - pub cmd_buffer: ManuallyDrop<CommandBuffer>, - - /// The image for this frame - pub image: ManuallyDrop<Image>, - - /// Imageviews for this frame - pub imageview: ManuallyDrop<ImageView>, + pub cmd_buffer: ManuallyDrop<CommandBufferT>, /// Framebuffer for this frame - pub framebuffer: ManuallyDrop<Framebuffer>, + pub framebuffer: ManuallyDrop<FramebufferT>, /// Framebuffer for this frame when drawing in 2D - pub framebuffer_2d: ManuallyDrop<Framebuffer>, + pub framebuffer_2d: ManuallyDrop<FramebufferT>, } impl TargetResources { pub fn new( - device: &mut Device, - cmd_pool: &mut CommandPool, - renderpass: &RenderPass, - renderpass_2d: &RenderPass, - image: Image, - depth_pass: &ImageView, + device: &mut DeviceT, + cmd_pool: &mut CommandPoolT, + renderpass: &RenderPassT, + renderpass_2d: &RenderPassT, + fat: FramebufferAttachment, + dat: FramebufferAttachment, properties: &SwapchainProperties, ) -> Result<TargetResources, TargetResourcesCreationError> { // Command Buffer let cmd_buffer = unsafe { cmd_pool.allocate_one(hal::command::Level::Primary) }; - // ImageView - let imageview = unsafe { - device - .create_image_view( - &image, - ViewKind::D2, - properties.format, - Swizzle::NO, - COLOR_RANGE.clone(), - ) - .map_err(TargetResourcesCreationError::ImageViewError)? - }; - // Framebuffer let framebuffer = unsafe { device .create_framebuffer( &renderpass, - once(&imageview).chain(once(depth_pass)), + IntoIter::new([fat.clone(), dat]), properties.extent, ) .map_err(|_| TargetResourcesCreationError::FrameBufferNoMemory)? @@ -532,48 +541,39 @@ impl TargetResources { // 2D framebuffer just needs the imageview, not the depth pass let framebuffer_2d = unsafe { device - .create_framebuffer(&renderpass_2d, once(&imageview), properties.extent) + .create_framebuffer(&renderpass_2d, once(fat), properties.extent) .map_err(|_| TargetResourcesCreationError::FrameBufferNoMemory)? }; Ok(TargetResources { cmd_buffer: ManuallyDrop::new(cmd_buffer), - image: ManuallyDrop::new(image), - imageview: ManuallyDrop::new(imageview), framebuffer: ManuallyDrop::new(framebuffer), framebuffer_2d: ManuallyDrop::new(framebuffer_2d), }) } - pub fn deactivate(self, device: &mut Device, cmd_pool: &mut CommandPool) { + pub fn deactivate(self, device: &mut DeviceT, cmd_pool: &mut CommandPoolT) { use core::ptr::read; unsafe { cmd_pool.free(once(ManuallyDrop::into_inner(read(&self.cmd_buffer)))); device.destroy_framebuffer(ManuallyDrop::into_inner(read(&self.framebuffer))); device.destroy_framebuffer(ManuallyDrop::into_inner(read(&self.framebuffer_2d))); - device.destroy_image_view(ManuallyDrop::into_inner(read(&self.imageview))); } } } pub struct SyncObjects { - /// Triggered when the image is ready to draw to - pub get_image: ManuallyDrop<Semaphore>, - /// Triggered when rendering is done - pub render_complete: ManuallyDrop<Semaphore>, + pub render_complete: ManuallyDrop<SemaphoreT>, /// Triggered when the image is on screen - pub present_complete: ManuallyDrop<Fence>, + pub present_complete: ManuallyDrop<FenceT>, } impl SyncObjects { - pub fn new(device: &mut Device) -> Result<Self, TargetResourcesCreationError> { + pub fn new(device: &mut DeviceT) -> Result<Self, TargetResourcesCreationError> { // Sync objects - let get_image = device - .create_semaphore() - .map_err(|_| TargetResourcesCreationError::SyncObjectsNoMemory)?; let render_complete = device .create_semaphore() .map_err(|_| TargetResourcesCreationError::SyncObjectsNoMemory)?; @@ -582,17 +582,15 @@ impl SyncObjects { .map_err(|_| TargetResourcesCreationError::SyncObjectsNoMemory)?; Ok(SyncObjects { - get_image: ManuallyDrop::new(get_image), render_complete: ManuallyDrop::new(render_complete), present_complete: ManuallyDrop::new(present_complete), }) } - pub fn deactivate(self, device: &mut Device) { + pub fn deactivate(self, device: &mut DeviceT) { use core::ptr::read; unsafe { - device.destroy_semaphore(ManuallyDrop::into_inner(read(&self.get_image))); device.destroy_semaphore(ManuallyDrop::into_inner(read(&self.render_complete))); device.destroy_fence(ManuallyDrop::into_inner(read(&self.present_complete))); } @@ -606,7 +604,7 @@ pub enum TargetChainCreationError { #[derive(Debug)] pub enum TargetResourcesCreationError { - ImageViewError(hal::image::ViewError), + ImageViewError, FrameBufferNoMemory, SyncObjectsNoMemory, } |