//! Render pass handling. //! //! A *render pass* represents a collection of //! //! - [attachments][crate::pass::Attachment] //! - [subpasses][crate::pass::SubpassDesc] //! - [dependencies][crate::pass::SubpassDependency] between the subpasses //! //! and describes how the attachments are used over the course of the subpasses. use crate::{format::Format, image, memory::Dependencies, pso::PipelineStage, Backend}; use std::ops::Range; /// Specifies the operation to be used when reading data from a subpass attachment. #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub enum AttachmentLoadOp { /// Preserve existing content in the attachment. Load, /// Clear the attachment. Clear, /// Attachment content will be undefined. DontCare, } /// Specifies the operation to be used when writing data to a subpass attachment. #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub enum AttachmentStoreOp { /// Content written to the attachment will be preserved. Store, /// Attachment content will be undefined. DontCare, } /// Image layout of an attachment. pub type AttachmentLayout = image::Layout; /// Attachment operations. #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct AttachmentOps { /// Indicates how the data of the attachment will be loaded at first usage at /// the beginning of the subpass. pub load: AttachmentLoadOp, /// Whether or not data from the store operation will be preserved after the subpass. pub store: AttachmentStoreOp, } impl AttachmentOps { /// Specifies `DontCare` for both load and store op. pub const DONT_CARE: Self = AttachmentOps { load: AttachmentLoadOp::DontCare, store: AttachmentStoreOp::DontCare, }; /// Specifies `Clear` for load op and `Store` for store op. pub const INIT: Self = AttachmentOps { load: AttachmentLoadOp::Clear, store: AttachmentStoreOp::Store, }; /// Specifies `Load` for load op and `Store` for store op. pub const PRESERVE: Self = AttachmentOps { load: AttachmentLoadOp::Load, store: AttachmentStoreOp::Store, }; /// Convenience function to create a new `AttachmentOps`. pub fn new(load: AttachmentLoadOp, store: AttachmentStoreOp) -> Self { AttachmentOps { load, store } } /// A method to provide `AttachmentOps::DONT_CARE` to things that expect /// a default function rather than a value. #[cfg(feature = "serde")] fn whatever() -> Self { Self::DONT_CARE } } /// An attachment is a description of a resource provided to a render subpass. /// /// It includes things such as render targets, images that were produced from /// previous subpasses, etc. #[derive(Clone, Debug, Hash, PartialEq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct Attachment { /// Format of this attachment. /// /// In the most cases `format` is not `None`. It should be only used for /// creating dummy renderpasses, which are used as placeholder for compatible /// renderpasses. pub format: Option, /// Number of samples to use when loading from this attachment. /// /// If greater than 1, [multisampling](https://en.wikipedia.org/wiki/Multisample_anti-aliasing) /// will take effect. pub samples: image::NumSamples, /// Load and store operations of the attachment. pub ops: AttachmentOps, /// Load and store operations of the stencil aspect, if any. #[cfg_attr(feature = "serde", serde(default = "AttachmentOps::whatever"))] pub stencil_ops: AttachmentOps, /// Initial and final image layouts of the renderpass. pub layouts: Range, } impl Attachment { /// Returns true if this attachment has some clear operations. /// /// Useful when starting a render pass, since there has to be a clear value provided. pub fn has_clears(&self) -> bool { self.ops.load == AttachmentLoadOp::Clear || self.stencil_ops.load == AttachmentLoadOp::Clear } } /// Index of an attachment within a framebuffer/renderpass, pub type AttachmentId = usize; /// Reference to an attachment by index and expected image layout. pub type AttachmentRef = (AttachmentId, AttachmentLayout); /// An AttachmentId that can be used instead of providing an attachment. pub const ATTACHMENT_UNUSED: AttachmentId = !0; /// Index of a subpass. pub type SubpassId = u8; /// Expresses a dependency between multiple [subpasses][SubpassDesc]. /// /// This is used both to describe a source or destination subpass; /// data either explicitly passes from this subpass to the next or from another /// subpass into this one. #[derive(Clone, Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct SubpassDependency { /// Other subpasses this one depends on. /// /// If one of the range sides is `None`, it refers to the external /// scope either before or after the whole render pass. pub passes: Range>, /// Other pipeline stages this subpass depends on. pub stages: Range, /// Resource accesses this subpass depends on. pub accesses: Range, /// Dependency flags. pub flags: Dependencies, } /// Description of a subpass for render pass creation. #[derive(Clone, Debug)] pub struct SubpassDesc<'a> { /// Which attachments will be used as color buffers. pub colors: &'a [AttachmentRef], /// Which attachments will be used as depth/stencil buffers. pub depth_stencil: Option<&'a AttachmentRef>, /// Which attachments will be used as input attachments. pub inputs: &'a [AttachmentRef], /// Which attachments will be used as resolve destinations. /// /// The number of resolve attachments may be zero or equal to the number of color attachments. /// /// At the end of a subpass the color attachment will be resolved to the corresponding /// resolve attachment. /// /// The resolve attachment must not be multisampled. pub resolves: &'a [AttachmentRef], /// Attachments that are not used by the subpass but must be preserved to be /// passed on to subsequent passes. pub preserves: &'a [AttachmentId], } /// A sub-pass borrow of a pass. #[derive(Debug)] pub struct Subpass<'a, B: Backend> { /// Index of the subpass pub index: SubpassId, /// Main pass borrow. pub main_pass: &'a B::RenderPass, } impl<'a, B: Backend> Clone for Subpass<'a, B> { fn clone(&self) -> Self { Subpass { index: self.index, main_pass: self.main_pass, } } } impl<'a, B: Backend> PartialEq for Subpass<'a, B> { fn eq(&self, other: &Self) -> bool { self.index == other.index && std::ptr::eq(self.main_pass, other.main_pass) } } impl<'a, B: Backend> Copy for Subpass<'a, B> {} impl<'a, B: Backend> Eq for Subpass<'a, B> {}