#[macro_export]
macro_rules! single_pass_renderpass {
(
$device:expr,
attachments: { $($a:tt)* },
pass: {
color: [$($color_atch:ident),* $(,)?]
$(, color_resolve: [$($color_resolve_atch:ident),* $(,)?])?
, depth_stencil: {$($depth_stencil_atch:ident)?}
$(
, depth_stencil_resolve: {$depth_stencil_resolve_atch:ident}
$(, depth_resolve_mode: $depth_resolve_mode:ident)?
$(, stencil_resolve_mode: $stencil_resolve_mode:ident)?
)?
$(,)?
} $(,)?
) => (
$crate::ordered_passes_renderpass!(
$device,
attachments: { $($a)* },
passes: [
{
color: [$($color_atch),*]
$(, color_resolve: [$($color_resolve_atch),*])?
, depth_stencil: {$($depth_stencil_atch)?}
$(
, depth_stencil_resolve: {$depth_stencil_resolve_atch}
$(, depth_resolve_mode: $depth_resolve_mode)?
$(, stencil_resolve_mode: $stencil_resolve_mode)?
)?
, input: [],
}
]
)
)
}
#[macro_export]
macro_rules! ordered_passes_renderpass {
(
$device:expr,
attachments: {
$(
$atch_name:ident: {
format: $format:expr,
samples: $samples:expr,
load_op: $load_op:ident,
store_op: $store_op:ident
$(,initial_layout: $init_layout:expr)?
$(,final_layout: $final_layout:expr)?
$(,)?
}
),* $(,)?
},
passes: [
$(
{
color: [$($color_atch:ident),* $(,)?]
$(, color_resolve: [$($color_resolve_atch:ident),* $(,)?])?
, depth_stencil: {$($depth_stencil_atch:ident)?}
$(
, depth_stencil_resolve: {$depth_stencil_resolve_atch:ident}
$(, depth_resolve_mode: $depth_resolve_mode:ident)?
$(, stencil_resolve_mode: $stencil_resolve_mode:ident)?
)?
, input: [$($input_atch:ident),* $(,)?]
$(,)*
}
),* $(,)?
] $(,)?
) => ({
use $crate::render_pass::RenderPass;
let create_info = {
#[allow(unused)]
let mut attachment_num = 0;
$(
let $atch_name = attachment_num;
attachment_num += 1;
)*
#[allow(unused)]
#[derive(Clone, Copy, Default)]
struct Layouts {
initial_layout: Option<$crate::image::ImageLayout>,
final_layout: Option<$crate::image::ImageLayout>,
}
#[allow(unused)]
let mut layouts: Vec<Layouts> = vec![Layouts::default(); attachment_num as usize];
let subpasses = vec![
$({
let desc = $crate::render_pass::SubpassDescription {
color_attachments: vec![
$({
let layouts = &mut layouts[$color_atch as usize];
layouts.initial_layout = layouts.initial_layout.or(Some($crate::image::ImageLayout::ColorAttachmentOptimal));
layouts.final_layout = Some($crate::image::ImageLayout::ColorAttachmentOptimal);
Some($crate::render_pass::AttachmentReference {
attachment: $color_atch,
layout: $crate::image::ImageLayout::ColorAttachmentOptimal,
..Default::default()
})
}),*
],
color_resolve_attachments: vec![$(
$({
let layouts = &mut layouts[$color_resolve_atch as usize];
layouts.final_layout = Some($crate::image::ImageLayout::TransferDstOptimal);
layouts.initial_layout = layouts.initial_layout.or(layouts.final_layout);
Some($crate::render_pass::AttachmentReference {
attachment: $color_resolve_atch,
layout: $crate::image::ImageLayout::TransferDstOptimal,
..Default::default()
})
}),*
)?],
depth_stencil_attachment: {
None $(.or({
let layouts = &mut layouts[$depth_stencil_atch as usize];
layouts.final_layout = Some($crate::image::ImageLayout::DepthStencilAttachmentOptimal);
layouts.initial_layout = layouts.initial_layout.or(layouts.final_layout);
Some($crate::render_pass::AttachmentReference {
attachment: $depth_stencil_atch,
layout: $crate::image::ImageLayout::DepthStencilAttachmentOptimal,
..Default::default()
})
}))?
},
depth_stencil_resolve_attachment: {
None $(.or({
let layouts = &mut layouts[$depth_stencil_resolve_atch as usize];
layouts.final_layout = Some($crate::image::ImageLayout::TransferDstOptimal);
layouts.initial_layout = layouts.initial_layout.or(layouts.final_layout);
Some($crate::render_pass::AttachmentReference {
attachment: $depth_stencil_resolve_atch,
layout: $crate::image::ImageLayout::TransferDstOptimal,
..Default::default()
})
}))?
},
depth_resolve_mode: {
None $($(.or({
Some($crate::render_pass::ResolveMode::$depth_resolve_mode)
}))?)?
},
stencil_resolve_mode: {
None $($(.or({
Some($crate::render_pass::ResolveMode::$stencil_resolve_mode)
}))?)?
},
input_attachments: vec![
$({
let layouts = &mut layouts[$input_atch as usize];
layouts.final_layout = Some($crate::image::ImageLayout::ShaderReadOnlyOptimal);
layouts.initial_layout = layouts.initial_layout.or(layouts.final_layout);
Some($crate::render_pass::AttachmentReference {
attachment: $input_atch,
layout: $crate::image::ImageLayout::ShaderReadOnlyOptimal,
..Default::default()
})
}),*
],
preserve_attachments: (0 .. attachment_num).filter(|&a| {
![
$($color_atch,)*
$($($color_resolve_atch,)*)?
$($depth_stencil_atch,)*
$($depth_stencil_resolve_atch,)*
$($input_atch,)*
].contains(&a)
}).collect(),
..Default::default()
};
desc
}),*
];
let dependencies: Vec<_> = (0..subpasses.len().saturating_sub(1) as u32)
.map(|id| {
let src_stages = $crate::sync::PipelineStages::ALL_GRAPHICS;
let dst_stages = $crate::sync::PipelineStages::ALL_GRAPHICS;
let src_access = $crate::sync::AccessFlags::MEMORY_READ
| $crate::sync::AccessFlags::MEMORY_WRITE;
let dst_access = $crate::sync::AccessFlags::MEMORY_READ
| $crate::sync::AccessFlags::MEMORY_WRITE;
$crate::render_pass::SubpassDependency {
src_subpass: id.into(),
dst_subpass: (id + 1).into(),
src_stages,
dst_stages,
src_access,
dst_access,
dependency_flags: $crate::sync::DependencyFlags::BY_REGION,
..Default::default()
}
})
.collect();
let attachments = vec![
$({
let layouts = &mut layouts[$atch_name as usize];
$(layouts.initial_layout = Some($init_layout);)*
$(layouts.final_layout = Some($final_layout);)*
$crate::render_pass::AttachmentDescription {
format: $format,
samples: $crate::image::SampleCount::try_from($samples).unwrap(),
load_op: $crate::render_pass::AttachmentLoadOp::$load_op,
store_op: $crate::render_pass::AttachmentStoreOp::$store_op,
initial_layout: layouts.initial_layout.expect(
format!(
"Attachment {} is missing initial_layout, this is normally \
automatically determined but you can manually specify it for an individual \
attachment in the single_pass_renderpass! macro",
attachment_num
)
.as_ref(),
),
final_layout: layouts.final_layout.expect(
format!(
"Attachment {} is missing final_layout, this is normally \
automatically determined but you can manually specify it for an individual \
attachment in the single_pass_renderpass! macro",
attachment_num
)
.as_ref(),
),
..Default::default()
}
}),*
];
$crate::render_pass::RenderPassCreateInfo {
attachments,
subpasses,
dependencies,
..Default::default()
}
};
RenderPass::new($device, create_info)
});
}
#[cfg(test)]
mod tests {
use crate::format::Format;
#[test]
fn single_pass_resolve() {
let (device, _) = gfx_dev_and_queue!();
let _ = single_pass_renderpass!(
device,
attachments: {
a: {
format: Format::R8G8B8A8_UNORM,
samples: 4,
load_op: Clear,
store_op: DontCare,
},
b: {
format: Format::R8G8B8A8_UNORM,
samples: 1,
load_op: DontCare,
store_op: Store,
},
},
pass: {
color: [a],
color_resolve: [b],
depth_stencil: {},
},
)
.unwrap();
}
}