1#[macro_export]
3macro_rules! single_pass_renderpass {
4 (
5 $device:expr,
6 attachments: { $($a:tt)* },
7 pass: {
8 color: [$($color_atch:ident),* $(,)?]
9 $(, color_resolve: [$($color_resolve_atch:ident),* $(,)?])?
10 , depth_stencil: {$($depth_stencil_atch:ident)?}
11 $(
12 , depth_stencil_resolve: {$depth_stencil_resolve_atch:ident}
13 $(, depth_resolve_mode: $depth_resolve_mode:ident)?
14 $(, stencil_resolve_mode: $stencil_resolve_mode:ident)?
15 )?
16 $(,)?
17 } $(,)?
18 ) => (
19 $crate::ordered_passes_renderpass!(
20 $device,
21 attachments: { $($a)* },
22 passes: [
23 {
24 color: [$($color_atch),*]
25 $(, color_resolve: [$($color_resolve_atch),*])?
26 , depth_stencil: {$($depth_stencil_atch)?}
27 $(
28 , depth_stencil_resolve: {$depth_stencil_resolve_atch}
29 $(, depth_resolve_mode: $depth_resolve_mode)?
30 $(, stencil_resolve_mode: $stencil_resolve_mode)?
31 )?
32 , input: [],
33 }
34 ]
35 )
36 )
37}
38
39#[macro_export]
41macro_rules! ordered_passes_renderpass {
42 (
43 $device:expr,
44 attachments: {
45 $(
46 $atch_name:ident: {
47 format: $format:expr,
48 samples: $samples:expr,
49 load_op: $load_op:ident,
50 store_op: $store_op:ident
51 $(,initial_layout: $init_layout:expr)?
52 $(,final_layout: $final_layout:expr)?
53 $(,)?
54 }
55 ),* $(,)?
56 },
57 passes: [
58 $(
59 {
60 color: [$($color_atch:ident),* $(,)?]
61 $(, color_resolve: [$($color_resolve_atch:ident),* $(,)?])?
62 , depth_stencil: {$($depth_stencil_atch:ident)?}
63 $(
64 , depth_stencil_resolve: {$depth_stencil_resolve_atch:ident}
65 $(, depth_resolve_mode: $depth_resolve_mode:ident)?
66 $(, stencil_resolve_mode: $stencil_resolve_mode:ident)?
67 )?
68 , input: [$($input_atch:ident),* $(,)?]
69 $(,)*
70 }
71 ),* $(,)?
72 ] $(,)?
73 ) => ({
74 use $crate::render_pass::RenderPass;
75
76 let create_info = {
77 #[allow(unused)]
78 let mut attachment_num = 0;
79 $(
80 let $atch_name = attachment_num;
81 attachment_num += 1;
82 )*
83
84 #[allow(unused)]
85 #[derive(Clone, Copy, Default)]
86 struct Layouts {
87 initial_layout: Option<$crate::image::ImageLayout>,
88 final_layout: Option<$crate::image::ImageLayout>,
89 }
90
91 #[allow(unused)]
92 let mut layouts: Vec<Layouts> = vec![Layouts::default(); attachment_num as usize];
93
94 let subpasses = vec![
95 $({
96 let desc = $crate::render_pass::SubpassDescription {
97 color_attachments: vec![
98 $({
99 let layouts = &mut layouts[$color_atch as usize];
100 layouts.initial_layout = layouts.initial_layout.or(Some($crate::image::ImageLayout::ColorAttachmentOptimal));
101 layouts.final_layout = Some($crate::image::ImageLayout::ColorAttachmentOptimal);
102
103 Some($crate::render_pass::AttachmentReference {
104 attachment: $color_atch,
105 layout: $crate::image::ImageLayout::ColorAttachmentOptimal,
106 ..Default::default()
107 })
108 }),*
109 ],
110 color_resolve_attachments: vec![$(
111 $({
112 let layouts = &mut layouts[$color_resolve_atch as usize];
113 layouts.final_layout = Some($crate::image::ImageLayout::TransferDstOptimal);
114 layouts.initial_layout = layouts.initial_layout.or(layouts.final_layout);
115
116 Some($crate::render_pass::AttachmentReference {
117 attachment: $color_resolve_atch,
118 layout: $crate::image::ImageLayout::TransferDstOptimal,
119 ..Default::default()
120 })
121 }),*
122 )?],
123 depth_stencil_attachment: {
124 None $(.or({
125 let layouts = &mut layouts[$depth_stencil_atch as usize];
126 layouts.final_layout = Some($crate::image::ImageLayout::DepthStencilAttachmentOptimal);
127 layouts.initial_layout = layouts.initial_layout.or(layouts.final_layout);
128
129 Some($crate::render_pass::AttachmentReference {
130 attachment: $depth_stencil_atch,
131 layout: $crate::image::ImageLayout::DepthStencilAttachmentOptimal,
132 ..Default::default()
133 })
134 }))?
135 },
136 depth_stencil_resolve_attachment: {
137 None $(.or({
138 let layouts = &mut layouts[$depth_stencil_resolve_atch as usize];
139 layouts.final_layout = Some($crate::image::ImageLayout::TransferDstOptimal);
140 layouts.initial_layout = layouts.initial_layout.or(layouts.final_layout);
141
142 Some($crate::render_pass::AttachmentReference {
143 attachment: $depth_stencil_resolve_atch,
144 layout: $crate::image::ImageLayout::TransferDstOptimal,
145 ..Default::default()
146 })
147 }))?
148 },
149 depth_resolve_mode: {
150 None $($(.or({
151 Some($crate::render_pass::ResolveMode::$depth_resolve_mode)
152 }))?)?
153 },
154 stencil_resolve_mode: {
155 None $($(.or({
156 Some($crate::render_pass::ResolveMode::$stencil_resolve_mode)
157 }))?)?
158 },
159 input_attachments: vec![
160 $({
161 let layouts = &mut layouts[$input_atch as usize];
162 layouts.final_layout = Some($crate::image::ImageLayout::ShaderReadOnlyOptimal);
163 layouts.initial_layout = layouts.initial_layout.or(layouts.final_layout);
164
165 Some($crate::render_pass::AttachmentReference {
166 attachment: $input_atch,
167 layout: $crate::image::ImageLayout::ShaderReadOnlyOptimal,
168 ..Default::default()
169 })
170 }),*
171 ],
172 preserve_attachments: (0 .. attachment_num).filter(|&a| {
173 ![
174 $($color_atch,)*
175 $($($color_resolve_atch,)*)?
176 $($depth_stencil_atch,)*
177 $($depth_stencil_resolve_atch,)*
178 $($input_atch,)*
179 ].contains(&a)
180 }).collect(),
181 ..Default::default()
182 };
183
184 desc
185 }),*
186 ];
187
188 let dependencies: Vec<_> = (0..subpasses.len().saturating_sub(1) as u32)
189 .map(|id| {
190 let src_stages = $crate::sync::PipelineStages::ALL_GRAPHICS;
192 let dst_stages = $crate::sync::PipelineStages::ALL_GRAPHICS;
193 let src_access = $crate::sync::AccessFlags::MEMORY_READ
194 | $crate::sync::AccessFlags::MEMORY_WRITE;
195 let dst_access = $crate::sync::AccessFlags::MEMORY_READ
196 | $crate::sync::AccessFlags::MEMORY_WRITE;
197
198 $crate::render_pass::SubpassDependency {
199 src_subpass: id.into(),
200 dst_subpass: (id + 1).into(),
201 src_stages,
202 dst_stages,
203 src_access,
204 dst_access,
205 dependency_flags: $crate::sync::DependencyFlags::BY_REGION,
207 ..Default::default()
208 }
209 })
210 .collect();
211
212 let attachments = vec![
213 $({
214 let layouts = &mut layouts[$atch_name as usize];
215 $(layouts.initial_layout = Some($init_layout);)*
216 $(layouts.final_layout = Some($final_layout);)*
217
218 $crate::render_pass::AttachmentDescription {
219 format: $format,
220 samples: $crate::image::SampleCount::try_from($samples).unwrap(),
221 load_op: $crate::render_pass::AttachmentLoadOp::$load_op,
222 store_op: $crate::render_pass::AttachmentStoreOp::$store_op,
223 initial_layout: layouts.initial_layout.expect(
224 format!(
225 "Attachment {} is missing initial_layout, this is normally \
226 automatically determined but you can manually specify it for an individual \
227 attachment in the single_pass_renderpass! macro",
228 attachment_num
229 )
230 .as_ref(),
231 ),
232 final_layout: layouts.final_layout.expect(
233 format!(
234 "Attachment {} is missing final_layout, this is normally \
235 automatically determined but you can manually specify it for an individual \
236 attachment in the single_pass_renderpass! macro",
237 attachment_num
238 )
239 .as_ref(),
240 ),
241 ..Default::default()
242 }
243 }),*
244 ];
245
246 $crate::render_pass::RenderPassCreateInfo {
247 attachments,
248 subpasses,
249 dependencies,
250 ..Default::default()
251 }
252 };
253
254 RenderPass::new($device, create_info)
255 });
256}
257
258#[cfg(test)]
259mod tests {
260 use crate::format::Format;
261
262 #[test]
263 fn single_pass_resolve() {
264 let (device, _) = gfx_dev_and_queue!();
265 let _ = single_pass_renderpass!(
266 device,
267 attachments: {
268 a: {
269 format: Format::R8G8B8A8_UNORM,
270 samples: 4,
271 load_op: Clear,
272 store_op: DontCare,
273 },
274 b: {
275 format: Format::R8G8B8A8_UNORM,
276 samples: 1,
277 load_op: DontCare,
278 store_op: Store,
279 },
280 },
281 pass: {
282 color: [a],
283 color_resolve: [b],
284 depth_stencil: {},
285 },
286 )
287 .unwrap();
288 }
289}