1 //! Render pass handling.
2 //!
3 //! A *render pass* represents a collection of
4 //!
5 //! - [attachments][crate::pass::Attachment]
6 //! - [subpasses][crate::pass::SubpassDesc]
7 //! - [dependencies][crate::pass::SubpassDependency] between the subpasses
8 //!
9 //! and describes how the attachments are used over the course of the subpasses.
10 
11 use crate::{format::Format, image, memory::Dependencies, pso::PipelineStage, Backend};
12 use std::ops::Range;
13 
14 /// Specifies the operation to be used when reading data from a subpass attachment.
15 #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
16 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
17 pub enum AttachmentLoadOp {
18     /// Preserve existing content in the attachment.
19     Load,
20     /// Clear the attachment.
21     Clear,
22     /// Attachment content will be undefined.
23     DontCare,
24 }
25 
26 /// Specifies the operation to be used when writing data to a subpass attachment.
27 #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
28 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
29 pub enum AttachmentStoreOp {
30     /// Content written to the attachment will be preserved.
31     Store,
32     /// Attachment content will be undefined.
33     DontCare,
34 }
35 
36 /// Image layout of an attachment.
37 pub type AttachmentLayout = image::Layout;
38 
39 /// Attachment operations.
40 #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
41 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
42 pub struct AttachmentOps {
43     /// Indicates how the data of the attachment will be loaded at first usage at
44     /// the beginning of the subpass.
45     pub load: AttachmentLoadOp,
46     /// Whether or not data from the store operation will be preserved after the subpass.
47     pub store: AttachmentStoreOp,
48 }
49 
50 impl AttachmentOps {
51     /// Specifies `DontCare` for both load and store op.
52     pub const DONT_CARE: Self = AttachmentOps {
53         load: AttachmentLoadOp::DontCare,
54         store: AttachmentStoreOp::DontCare,
55     };
56 
57     /// Specifies `Clear` for load op and `Store` for store op.
58     pub const INIT: Self = AttachmentOps {
59         load: AttachmentLoadOp::Clear,
60         store: AttachmentStoreOp::Store,
61     };
62 
63     /// Specifies `Load` for load op and `Store` for store op.
64     pub const PRESERVE: Self = AttachmentOps {
65         load: AttachmentLoadOp::Load,
66         store: AttachmentStoreOp::Store,
67     };
68 
69     /// Convenience function to create a new `AttachmentOps`.
new(load: AttachmentLoadOp, store: AttachmentStoreOp) -> Self70     pub fn new(load: AttachmentLoadOp, store: AttachmentStoreOp) -> Self {
71         AttachmentOps { load, store }
72     }
73 
74     /// A method to provide `AttachmentOps::DONT_CARE` to things that expect
75     /// a default function rather than a value.
76     #[cfg(feature = "serde")]
whatever() -> Self77     fn whatever() -> Self {
78         Self::DONT_CARE
79     }
80 }
81 
82 /// An attachment is a description of a resource provided to a render subpass.
83 ///
84 /// It includes things such as render targets, images that were produced from
85 /// previous subpasses, etc.
86 #[derive(Clone, Debug, Hash, PartialEq)]
87 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
88 pub struct Attachment {
89     /// Format of this attachment.
90     ///
91     /// In the most cases `format` is not `None`. It should be only used for
92     /// creating dummy renderpasses, which are used as placeholder for compatible
93     /// renderpasses.
94     pub format: Option<Format>,
95     /// Number of samples to use when loading from this attachment.
96     ///
97     /// If greater than 1, [multisampling](https://en.wikipedia.org/wiki/Multisample_anti-aliasing)
98     /// will take effect.
99     pub samples: image::NumSamples,
100     /// Load and store operations of the attachment.
101     pub ops: AttachmentOps,
102     /// Load and store operations of the stencil aspect, if any.
103     #[cfg_attr(feature = "serde", serde(default = "AttachmentOps::whatever"))]
104     pub stencil_ops: AttachmentOps,
105     /// Initial and final image layouts of the renderpass.
106     pub layouts: Range<AttachmentLayout>,
107 }
108 
109 impl Attachment {
110     /// Returns true if this attachment has some clear operations.
111     ///
112     /// Useful when starting a render pass, since there has to be a clear value provided.
has_clears(&self) -> bool113     pub fn has_clears(&self) -> bool {
114         self.ops.load == AttachmentLoadOp::Clear || self.stencil_ops.load == AttachmentLoadOp::Clear
115     }
116 }
117 
118 /// Index of an attachment within a framebuffer/renderpass,
119 pub type AttachmentId = usize;
120 /// Reference to an attachment by index and expected image layout.
121 pub type AttachmentRef = (AttachmentId, AttachmentLayout);
122 /// An AttachmentId that can be used instead of providing an attachment.
123 pub const ATTACHMENT_UNUSED: AttachmentId = !0;
124 
125 /// Index of a subpass.
126 pub type SubpassId = u8;
127 
128 /// Expresses a dependency between multiple [subpasses][SubpassDesc].
129 ///
130 /// This is used both to describe a source or destination subpass;
131 /// data either explicitly passes from this subpass to the next or from another
132 /// subpass into this one.
133 #[derive(Clone, Debug, Hash)]
134 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
135 pub struct SubpassDependency {
136     /// Other subpasses this one depends on.
137     ///
138     /// If one of the range sides is `None`, it refers to the external
139     /// scope either before or after the whole render pass.
140     pub passes: Range<Option<SubpassId>>,
141     /// Other pipeline stages this subpass depends on.
142     pub stages: Range<PipelineStage>,
143     /// Resource accesses this subpass depends on.
144     pub accesses: Range<image::Access>,
145     /// Dependency flags.
146     pub flags: Dependencies,
147 }
148 
149 /// Description of a subpass for render pass creation.
150 #[derive(Clone, Debug)]
151 pub struct SubpassDesc<'a> {
152     /// Which attachments will be used as color buffers.
153     pub colors: &'a [AttachmentRef],
154     /// Which attachments will be used as depth/stencil buffers.
155     pub depth_stencil: Option<&'a AttachmentRef>,
156     /// Which attachments will be used as input attachments.
157     pub inputs: &'a [AttachmentRef],
158     /// Which attachments will be used as resolve destinations.
159     ///
160     /// The number of resolve attachments may be zero or equal to the number of color attachments.
161     ///
162     /// At the end of a subpass the color attachment will be resolved to the corresponding
163     /// resolve attachment.
164     ///
165     /// The resolve attachment must not be multisampled.
166     pub resolves: &'a [AttachmentRef],
167     /// Attachments that are not used by the subpass but must be preserved to be
168     /// passed on to subsequent passes.
169     pub preserves: &'a [AttachmentId],
170 }
171 
172 /// A sub-pass borrow of a pass.
173 #[derive(Debug)]
174 pub struct Subpass<'a, B: Backend> {
175     /// Index of the subpass
176     pub index: SubpassId,
177     /// Main pass borrow.
178     pub main_pass: &'a B::RenderPass,
179 }
180 
181 impl<'a, B: Backend> Clone for Subpass<'a, B> {
clone(&self) -> Self182     fn clone(&self) -> Self {
183         Subpass {
184             index: self.index,
185             main_pass: self.main_pass,
186         }
187     }
188 }
189 
190 impl<'a, B: Backend> PartialEq for Subpass<'a, B> {
eq(&self, other: &Self) -> bool191     fn eq(&self, other: &Self) -> bool {
192         self.index == other.index && std::ptr::eq(self.main_pass, other.main_pass)
193     }
194 }
195 
196 impl<'a, B: Backend> Copy for Subpass<'a, B> {}
197 impl<'a, B: Backend> Eq for Subpass<'a, B> {}
198