aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--stockton-render/src/camera.rs7
-rw-r--r--stockton-render/src/level.rs24
-rw-r--r--stockton-render/src/ui.rs18
-rw-r--r--stockton-render/src/window.rs11
-rw-r--r--stockton-skeleton/src/context.rs11
-rw-r--r--stockton-skeleton/src/draw_passes/cons.rs127
-rw-r--r--stockton-skeleton/src/draw_passes/mod.rs109
-rw-r--r--stockton-skeleton/src/lib.rs6
-rw-r--r--stockton-skeleton/src/target.rs50
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();
}