vulkano/render_pass/
macros.rs

1/// Builds a `RenderPass` object whose template parameter is of indeterminate type.
2#[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/// Builds a `RenderPass` object whose template parameter is of indeterminate type.
40#[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                    // TODO: correct values
191                    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                        // TODO: correct values
206                        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}