diff options
-rw-r--r-- | stockton-render/src/camera.rs | 7 | ||||
-rw-r--r-- | stockton-render/src/level.rs | 24 | ||||
-rw-r--r-- | stockton-render/src/ui.rs | 18 | ||||
-rw-r--r-- | stockton-render/src/window.rs | 11 | ||||
-rw-r--r-- | stockton-skeleton/src/context.rs | 11 | ||||
-rw-r--r-- | stockton-skeleton/src/draw_passes/cons.rs | 127 | ||||
-rw-r--r-- | stockton-skeleton/src/draw_passes/mod.rs | 109 | ||||
-rw-r--r-- | stockton-skeleton/src/lib.rs | 6 | ||||
-rw-r--r-- | stockton-skeleton/src/target.rs | 50 |
9 files changed, 236 insertions, 127 deletions
diff --git a/stockton-render/src/camera.rs b/stockton-render/src/camera.rs index dcc9d93..6abc183 100644 --- a/stockton-render/src/camera.rs +++ b/stockton-render/src/camera.rs @@ -7,7 +7,10 @@ use stockton_types::{ Vector3, }; -use stockton_skeleton::{draw_passes::DrawPass, Renderer}; +use stockton_skeleton::{ + draw_passes::{DrawPass, Singular}, + Renderer, +}; fn euler_to_direction(euler: &Vector3) -> Vector3 { let pitch = euler.x; @@ -23,7 +26,7 @@ fn euler_to_direction(euler: &Vector3) -> Vector3 { #[system(for_each)] #[filter(maybe_changed::<Transform>() | maybe_changed::<CameraSettings>())] -pub fn calc_vp_matrix<DP: DrawPass + 'static>( +pub fn calc_vp_matrix<DP: DrawPass<Singular> + 'static>( transform: &Transform, settings: &CameraSettings, matrix: &mut CameraVPMatrix, diff --git a/stockton-render/src/level.rs b/stockton-render/src/level.rs index 6c74211..0352ff7 100644 --- a/stockton-render/src/level.rs +++ b/stockton-render/src/level.rs @@ -13,7 +13,7 @@ use stockton_skeleton::{ VertexPrimitiveAssemblerSpec, }, context::RenderingContext, - draw_passes::{util::TargetSpecificResources, DrawPass, IntoDrawPass}, + draw_passes::{util::TargetSpecificResources, DrawPass, IntoDrawPass, PassPosition}, error::{EnvironmentError, LevelError, LockPoisoned}, queue_negotiator::QueueNegotiator, texture::{resolver::TextureResolver, TexLoadQueue, TextureLoadConfig, TextureRepo}, @@ -67,7 +67,7 @@ pub struct LevelDrawPass<'a, M> { _d: PhantomData<M>, } -impl<'a, M> DrawPass for LevelDrawPass<'a, M> +impl<'a, M, P: PassPosition> DrawPass<P> for LevelDrawPass<'a, M> where M: for<'b> MinRenderFeatures<'b> + 'static, { @@ -269,10 +269,11 @@ pub struct LevelDrawPassConfig<R> { pub tex_resolver: R, } -impl<'a, M, R> IntoDrawPass<LevelDrawPass<'a, M>> for LevelDrawPassConfig<R> +impl<'a, M, R, P> IntoDrawPass<LevelDrawPass<'a, M>, P> for LevelDrawPassConfig<R> where M: for<'b> MinRenderFeatures<'b> + 'static, R: TextureResolver + Send + Sync + 'static, + P: PassPosition, { fn init( self, @@ -303,12 +304,12 @@ where mask: ColorMask::ALL, blend: Some(BlendState { color: BlendOp::Add { - src: Factor::One, - dst: Factor::Zero, + src: Factor::SrcAlpha, + dst: Factor::OneMinusSrcAlpha, }, alpha: BlendOp::Add { - src: Factor::One, - dst: Factor::Zero, + src: Factor::SrcAlpha, + dst: Factor::OneMinusSrcAlpha, }, }), }], @@ -335,12 +336,9 @@ where colors: vec![Attachment { format: Some(context.target_chain().properties().format), samples: 1, - ops: AttachmentOps::new(AttachmentLoadOp::Clear, AttachmentStoreOp::Store), - stencil_ops: AttachmentOps::new( - AttachmentLoadOp::Clear, - AttachmentStoreOp::DontCare, - ), - layouts: Layout::ColorAttachmentOptimal..Layout::ColorAttachmentOptimal, + ops: P::attachment_ops(), + stencil_ops: P::attachment_ops(), + layouts: P::layout_as_range(), }], depth: Some(Attachment { format: Some(context.target_chain().properties().depth_format), diff --git a/stockton-render/src/ui.rs b/stockton-render/src/ui.rs index d1689be..77ff805 100644 --- a/stockton-render/src/ui.rs +++ b/stockton-render/src/ui.rs @@ -8,7 +8,7 @@ use stockton_skeleton::{ VertexPrimitiveAssemblerSpec, }, context::RenderingContext, - draw_passes::{util::TargetSpecificResources, DrawPass, IntoDrawPass}, + draw_passes::{util::TargetSpecificResources, DrawPass, IntoDrawPass, PassPosition}, error::{EnvironmentError, LockPoisoned}, queue_negotiator::QueueNegotiator, texture::{ @@ -32,8 +32,7 @@ use hal::{ buffer::SubRange, command::{ClearColor, ClearValue, RenderAttachmentInfo, SubpassContents}, format::Format, - image::Layout, - pass::{Attachment, AttachmentLoadOp, AttachmentOps, AttachmentStoreOp}, + pass::Attachment, pso::{ BlendDesc, BlendOp, BlendState, ColorBlendDesc, ColorMask, DepthStencilDesc, Face, Factor, FrontFace, InputAssemblerDesc, LogicOp, PolygonMode, Primitive, Rasterizer, Rect, @@ -54,7 +53,7 @@ pub struct UiDrawPass<'a> { framebuffers: TargetSpecificResources<FramebufferT>, } -impl<'a> DrawPass for UiDrawPass<'a> { +impl<'a, P: PassPosition> DrawPass<P> for UiDrawPass<'a> { fn queue_draw( &mut self, session: &Session, @@ -208,7 +207,7 @@ impl<'a> DrawPass for UiDrawPass<'a> { } } -impl<'a> IntoDrawPass<UiDrawPass<'a>> for () { +impl<'a, P: PassPosition> IntoDrawPass<UiDrawPass<'a>, P> for () { fn init(self, session: &mut Session, context: &mut RenderingContext) -> Result<UiDrawPass<'a>> { let spec = PipelineSpecBuilder::default() .rasterizer(Rasterizer { @@ -263,12 +262,9 @@ impl<'a> IntoDrawPass<UiDrawPass<'a>> for () { colors: vec![Attachment { format: Some(context.target_chain().properties().format), samples: 1, - ops: AttachmentOps::new(AttachmentLoadOp::Load, AttachmentStoreOp::Store), - stencil_ops: AttachmentOps::new( - AttachmentLoadOp::DontCare, - AttachmentStoreOp::DontCare, - ), - layouts: Layout::ColorAttachmentOptimal..Layout::ColorAttachmentOptimal, + ops: P::attachment_ops(), + stencil_ops: P::attachment_ops(), + layouts: P::layout_as_range(), }], depth: None, inputs: vec![], diff --git a/stockton-render/src/window.rs b/stockton-render/src/window.rs index 15dd5a6..da80915 100644 --- a/stockton-render/src/window.rs +++ b/stockton-render/src/window.rs @@ -1,5 +1,8 @@ use stockton_input::{Action as KBAction, InputManager, Mouse}; -use stockton_skeleton::{draw_passes::DrawPass, Renderer}; +use stockton_skeleton::{ + draw_passes::{DrawPass, Singular}, + Renderer, +}; use std::sync::{ mpsc::{channel, Receiver, Sender}, @@ -81,7 +84,7 @@ pub struct UiState { } impl UiState { - pub fn populate_initial_state<T: DrawPass>(&mut self, renderer: &Renderer<T>) { + pub fn populate_initial_state<T: DrawPass<Singular>>(&mut self, renderer: &Renderer<T>) { let props = &renderer.context().target_chain().properties(); self.set_dimensions(props.extent.width, props.extent.height); self.set_pixels_per_point(Some(renderer.context().pixels_per_point())); @@ -213,7 +216,7 @@ impl WindowFlow { #[system] /// A system to process the window events sent to renderer by the winit event loop. -pub fn _process_window_events<T: 'static + InputManager, DP: 'static + DrawPass>( +pub fn _process_window_events<T: 'static + InputManager, DP: 'static + DrawPass<Singular>>( #[resource] window_channel: &mut WindowFlow, #[resource] manager: &mut T, #[resource] mouse: &mut Mouse, @@ -270,7 +273,7 @@ pub fn _process_window_events<T: 'static + InputManager, DP: 'static + DrawPass> manager.handle_frame(&actions_buf[0..actions_buf_cursor]); } -pub fn process_window_events_system<T: 'static + InputManager, DP: 'static + DrawPass>( +pub fn process_window_events_system<T: 'static + InputManager, DP: 'static + DrawPass<Singular>>( ) -> impl Runnable { _process_window_events_system::<T, DP>(Vec::with_capacity(4)) } diff --git a/stockton-skeleton/src/context.rs b/stockton-skeleton/src/context.rs index 802b8ca..5e2d3a3 100644 --- a/stockton-skeleton/src/context.rs +++ b/stockton-skeleton/src/context.rs @@ -19,6 +19,7 @@ use super::{ target::{SwapchainProperties, TargetChain}, }; use crate::{ + draw_passes::Singular, error::{EnvironmentError, LockPoisoned}, types::*, }; @@ -56,7 +57,9 @@ pub struct RenderingContext { impl RenderingContext { /// Create a new RenderingContext for the given window. - pub fn new<IDP: IntoDrawPass<DP>, DP: DrawPass>(window: &Window) -> Result<Self> { + pub fn new<IDP: IntoDrawPass<DP, Singular>, DP: DrawPass<Singular>>( + window: &Window, + ) -> Result<Self> { // Create surface let (instance, surface, mut adapters) = unsafe { let instance = @@ -208,7 +211,11 @@ impl RenderingContext { } /// Draw onto the next frame of the swapchain - pub fn draw_next_frame<DP: DrawPass>(&mut self, session: &Session, dp: &mut DP) -> Result<()> { + pub fn draw_next_frame<DP: DrawPass<Singular>>( + &mut self, + session: &Session, + dp: &mut DP, + ) -> Result<()> { let mut device = self .device .write() diff --git a/stockton-skeleton/src/draw_passes/cons.rs b/stockton-skeleton/src/draw_passes/cons.rs index ad94b1c..cc4f142 100644 --- a/stockton-skeleton/src/draw_passes/cons.rs +++ b/stockton-skeleton/src/draw_passes/cons.rs @@ -1,66 +1,103 @@ //! Code for using multiple draw passes in place of just one //! Note that this can be extended to an arbitrary amount of draw passes. -use super::{DrawPass, IntoDrawPass}; +use super::{Beginning, DrawPass, End, IntoDrawPass, Middle, Singular}; use crate::{context::RenderingContext, queue_negotiator::QueueNegotiator, types::*}; use stockton_types::Session; use anyhow::Result; /// One draw pass, then another. -pub struct ConsDrawPass<A: DrawPass, B: DrawPass> { +pub struct ConsDrawPass<A, B> { pub a: A, pub b: B, } -impl<A: DrawPass, B: DrawPass> DrawPass for ConsDrawPass<A, B> { - fn queue_draw( - &mut self, - session: &Session, - img_view: &ImageViewT, - cmd_buffer: &mut CommandBufferT, - ) -> Result<()> { - self.a.queue_draw(session, img_view, cmd_buffer)?; - self.b.queue_draw(session, img_view, cmd_buffer)?; +macro_rules! cons_shared_impl { + () => { + fn queue_draw( + &mut self, + session: &Session, + img_view: &ImageViewT, + cmd_buffer: &mut CommandBufferT, + ) -> Result<()> { + self.a.queue_draw(session, img_view, cmd_buffer)?; + self.b.queue_draw(session, img_view, cmd_buffer)?; - Ok(()) - } + Ok(()) + } + fn deactivate(self, context: &mut RenderingContext) -> Result<()> { + self.a.deactivate(context)?; + self.b.deactivate(context) + } - fn deactivate(self, context: &mut RenderingContext) -> Result<()> { - self.a.deactivate(context)?; - self.b.deactivate(context) - } + fn handle_surface_change( + &mut self, + session: &Session, + context: &mut RenderingContext, + ) -> Result<()> { + self.a.handle_surface_change(session, context)?; + self.b.handle_surface_change(session, context) + } + }; +} + +impl<A, B> DrawPass<Singular> for ConsDrawPass<A, B> +where + A: DrawPass<Beginning>, + B: DrawPass<End>, +{ + cons_shared_impl! {} +} + +impl<A, B> DrawPass<End> for ConsDrawPass<A, B> +where + A: DrawPass<Middle>, + B: DrawPass<End>, +{ + cons_shared_impl! {} +} + +macro_rules! into_shared_impl { + () => { + fn init( + self, + session: &mut Session, + context: &mut RenderingContext, + ) -> Result<ConsDrawPass<A, B>> { + Ok(ConsDrawPass { + a: self.0.init(session, context)?, + b: self.1.init(session, context)?, + }) + } - fn handle_surface_change( - &mut self, - session: &Session, - context: &mut RenderingContext, - ) -> Result<()> { - self.a.handle_surface_change(session, context)?; - self.b.handle_surface_change(session, context) - } + fn find_aux_queues<'a>( + adapter: &'a Adapter, + queue_negotiator: &mut QueueNegotiator, + ) -> Result<Vec<(&'a QueueFamilyT, Vec<f32>)>> { + let mut v = IA::find_aux_queues(adapter, queue_negotiator)?; + v.extend(IB::find_aux_queues(adapter, queue_negotiator)?); + Ok(v) + } + }; } -impl<A: DrawPass, B: DrawPass, IA: IntoDrawPass<A>, IB: IntoDrawPass<B>> - IntoDrawPass<ConsDrawPass<A, B>> for (IA, IB) +impl<A, B, IA, IB> IntoDrawPass<ConsDrawPass<A, B>, Singular> for (IA, IB) +where + A: DrawPass<Beginning>, + B: DrawPass<End>, + IA: IntoDrawPass<A, Beginning>, + IB: IntoDrawPass<B, End>, { - fn init( - self, - session: &mut Session, - context: &mut RenderingContext, - ) -> Result<ConsDrawPass<A, B>> { - Ok(ConsDrawPass { - a: self.0.init(session, context)?, - b: self.1.init(session, context)?, - }) - } + into_shared_impl! {} +} - fn find_aux_queues<'a>( - adapter: &'a Adapter, - queue_negotiator: &mut QueueNegotiator, - ) -> Result<Vec<(&'a QueueFamilyT, Vec<f32>)>> { - let mut v = IA::find_aux_queues(adapter, queue_negotiator)?; - v.extend(IB::find_aux_queues(adapter, queue_negotiator)?); - Ok(v) - } +impl<A, B, IA, IB> IntoDrawPass<ConsDrawPass<A, B>, End> for (IA, IB) +where + A: DrawPass<Middle>, + B: DrawPass<End>, + IA: IntoDrawPass<A, Middle>, + IB: IntoDrawPass<B, End>, +{ + into_shared_impl! {} } diff --git a/stockton-skeleton/src/draw_passes/mod.rs b/stockton-skeleton/src/draw_passes/mod.rs index a0dbba5..5a92a45 100644 --- a/stockton-skeleton/src/draw_passes/mod.rs +++ b/stockton-skeleton/src/draw_passes/mod.rs @@ -1,6 +1,12 @@ //! Traits and common draw passes. +use std::ops::Range; + use super::{queue_negotiator::QueueNegotiator, RenderingContext}; use crate::types::*; +use hal::{ + image::Layout, + pass::{AttachmentLoadOp, AttachmentOps, AttachmentStoreOp}, +}; use stockton_types::Session; use anyhow::Result; @@ -11,7 +17,7 @@ pub mod util; pub use cons::ConsDrawPass; /// One of several 'passes' that draw on each frame. -pub trait DrawPass { +pub trait DrawPass<P: PassPosition> { /// Queue any necessary draw commands to cmd_buffer /// This should assume the command buffer isn't in the middle of a renderpass, and should leave it as such. fn queue_draw( @@ -34,7 +40,7 @@ pub trait DrawPass { /// A type that can be made into a specific draw pass type. /// This allows extra data to be used in initialisation without the Renderer needing to worry about it. -pub trait IntoDrawPass<T: DrawPass> { +pub trait IntoDrawPass<T: DrawPass<P>, P: PassPosition> { fn init(self, session: &mut Session, context: &mut RenderingContext) -> Result<T>; /// This function should ask the queue negotatior to find families for any auxilary operations this draw pass needs to perform @@ -45,3 +51,102 @@ pub trait IntoDrawPass<T: DrawPass> { queue_negotiator: &mut QueueNegotiator, ) -> Result<Vec<(&'a QueueFamilyT, Vec<f32>)>>; } + +/// Used so that draw passes can determine what state shared resources are in and how they should be left. +pub trait PassPosition: private::Sealed { + /// The layout the image is in going in. + fn layout_in() -> Layout; + + /// The layout the image should be once this drawpass is completed + fn layout_out() -> Layout; + + /// Has the layout already been cleared this frame + fn is_cleared() -> bool; + + /// Convenience function to get a range from layout_in() to layout_out() + fn layout_as_range() -> Range<Layout> { + Self::layout_in()..Self::layout_out() + } + + /// Convenience function to get the attachment ops that should be used when loading the image attachment. + fn attachment_ops() -> AttachmentOps { + match Self::is_cleared() { + true => AttachmentOps::new(AttachmentLoadOp::Load, AttachmentStoreOp::Store), + false => AttachmentOps::new(AttachmentLoadOp::Clear, AttachmentStoreOp::Store), + } + } +} + +/// Pass is at the beginning of the list +pub struct Beginning; +impl PassPosition for Beginning { + fn layout_in() -> Layout { + Layout::Undefined + } + + fn layout_out() -> Layout { + Layout::ColorAttachmentOptimal + } + + fn is_cleared() -> bool { + false + } +} + +/// Pass is in the middle of the list +pub struct Middle; +impl PassPosition for Middle { + fn layout_in() -> Layout { + Layout::ColorAttachmentOptimal + } + + fn layout_out() -> Layout { + Layout::ColorAttachmentOptimal + } + + fn is_cleared() -> bool { + true + } +} + +/// Pass is at the end of the list +pub struct End; +impl PassPosition for End { + fn layout_in() -> Layout { + Layout::ColorAttachmentOptimal + } + + fn layout_out() -> Layout { + Layout::Present + } + + fn is_cleared() -> bool { + true + } +} + +/// Pass is the only draw pass being used +pub struct Singular; +impl PassPosition for Singular { + fn layout_in() -> Layout { + Layout::Undefined + } + + fn layout_out() -> Layout { + Layout::Present + } + + fn is_cleared() -> bool { + false + } +} + +mod private { + use super::{Beginning, End, Middle, Singular}; + + pub trait Sealed {} + impl Sealed for Beginning {} + impl Sealed for Middle {} + impl Sealed for End {} + impl Sealed for Singular {} +} diff --git a/stockton-skeleton/src/lib.rs b/stockton-skeleton/src/lib.rs index 03f6d53..3212873 100644 --- a/stockton-skeleton/src/lib.rs +++ b/stockton-skeleton/src/lib.rs @@ -18,7 +18,7 @@ pub mod types; pub mod utils; use context::RenderingContext; -use draw_passes::{DrawPass, IntoDrawPass}; +use draw_passes::{DrawPass, IntoDrawPass, Singular}; use anyhow::{Context, Result}; @@ -35,9 +35,9 @@ pub struct Renderer<DP> { draw_pass: DP, } -impl<DP: DrawPass> Renderer<DP> { +impl<DP: DrawPass<Singular>> Renderer<DP> { /// Create a new Renderer. - pub fn new<IDP: IntoDrawPass<DP>>( + pub fn new<IDP: IntoDrawPass<DP, Singular>>( window: &Window, session: &mut Session, idp: IDP, diff --git a/stockton-skeleton/src/target.rs b/stockton-skeleton/src/target.rs index d0d2380..c3a212e 100644 --- a/stockton-skeleton/src/target.rs +++ b/stockton-skeleton/src/target.rs @@ -8,18 +8,14 @@ use std::{ use hal::{ command::CommandBufferFlags, - format::{Aspects, ChannelType, Format, ImageFeature}, - image::{ - Access, Extent, FramebufferAttachment, Layout, SubresourceRange, Usage as ImgUsage, - ViewCapabilities, - }, - memory::{Barrier, Dependencies}, - pso::{PipelineStage, Viewport}, + format::{ChannelType, Format, ImageFeature}, + image::{Extent, FramebufferAttachment, Usage as ImgUsage, ViewCapabilities}, + pso::Viewport, window::{CompositeAlphaMode, Extent2D, PresentMode, SwapchainConfig}, }; use super::draw_passes::DrawPass; -use crate::{error::EnvironmentError, types::*}; +use crate::{draw_passes::Singular, error::EnvironmentError, types::*}; use anyhow::{Context, Result}; use stockton_types::Session; @@ -236,7 +232,7 @@ impl TargetChain { unsafe { ManuallyDrop::into_inner(read(&self.surface)) } } - pub fn do_draw_with<'a, DP: DrawPass>( + pub fn do_draw_with<'a, DP: DrawPass<Singular>>( &'a mut self, device: &mut DeviceT, command_queue: &mut QueueT, @@ -270,45 +266,9 @@ impl TargetChain { unsafe { target.cmd_buffer.begin_primary(CommandBufferFlags::empty()); - target.cmd_buffer.pipeline_barrier( - PipelineStage::TOP_OF_PIPE..PipelineStage::TOP_OF_PIPE, - Dependencies::empty(), - once(Barrier::Image { - states: (Access::empty(), Layout::Undefined) - ..(Access::empty(), Layout::ColorAttachmentOptimal), - target: img.borrow(), - range: SubresourceRange { - aspects: Aspects::COLOR, - level_start: 0, - level_count: Some(1), - layer_start: 0, - layer_count: Some(1), - }, - families: None, - }), - ); - dp.queue_draw(session, img.borrow(), &mut target.cmd_buffer) .context("Error in draw pass")?; - target.cmd_buffer.pipeline_barrier( - PipelineStage::BOTTOM_OF_PIPE..PipelineStage::BOTTOM_OF_PIPE, - Dependencies::empty(), - once(Barrier::Image { - states: (Access::empty(), Layout::ColorAttachmentOptimal) - ..(Access::empty(), Layout::Present), - target: img.borrow(), - range: SubresourceRange { - aspects: Aspects::COLOR, - level_start: 0, - level_count: Some(1), - layer_start: 0, - layer_count: Some(1), - }, - families: None, - }), - ); - target.cmd_buffer.finish(); } |