diff options
Diffstat (limited to 'src/render_pass/macros.rs')
-rw-r--r-- | src/render_pass/macros.rs | 237 |
1 files changed, 237 insertions, 0 deletions
diff --git a/src/render_pass/macros.rs b/src/render_pass/macros.rs new file mode 100644 index 0000000..d73a204 --- /dev/null +++ b/src/render_pass/macros.rs @@ -0,0 +1,237 @@ +// Copyright (c) 2016 The vulkano developers +// Licensed under the Apache License, Version 2.0 +// <LICENSE-APACHE or +// https://www.apache.org/licenses/LICENSE-2.0> or the MIT +// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, +// at your option. All files in the project carrying such +// notice may not be copied, modified, or distributed except +// according to those terms. + +/// Builds a `RenderPass` object whose template parameter is of indeterminate type. +#[macro_export] +macro_rules! single_pass_renderpass { + ( + $device:expr, + attachments: { $($a:tt)* }, + pass: { + color: [$($color_atch:ident),*], + depth_stencil: {$($depth_atch:ident)*}$(,)* + $(resolve: [$($resolve_atch:ident),*])*$(,)* + } + ) => ( + $crate::ordered_passes_renderpass!( + $device, + attachments: { $($a)* }, + passes: [ + { + color: [$($color_atch),*], + depth_stencil: {$($depth_atch)*}, + input: [], + resolve: [$($($resolve_atch),*)*] + } + ] + ) + ) +} + +/// Builds a `RenderPass` object whose template parameter is of indeterminate type. +#[macro_export] +macro_rules! ordered_passes_renderpass { + ( + $device:expr, + attachments: { + $( + $atch_name:ident: { + load: $load:ident, + store: $store:ident, + format: $format:expr, + samples: $samples:expr, + $(initial_layout: $init_layout:expr,)* + $(final_layout: $final_layout:expr,)* + } + ),* + }, + passes: [ + $( + { + color: [$($color_atch:ident),*], + depth_stencil: {$($depth_atch:ident)*}, + input: [$($input_atch:ident),*]$(,)* + $(resolve: [$($resolve_atch:ident),*])*$(,)* + } + ),* + ] + ) => ({ + use $crate::render_pass::RenderPass; + + let desc = { + use $crate::render_pass::AttachmentDesc; + use $crate::render_pass::RenderPassDesc; + use $crate::render_pass::SubpassDependencyDesc; + use $crate::render_pass::SubpassDesc; + use $crate::image::ImageLayout; + use $crate::sync::AccessFlags; + use $crate::sync::PipelineStages; + use std::convert::TryInto; + + let mut attachment_num = 0; + $( + let $atch_name = attachment_num; + attachment_num += 1; + )* + + let mut layouts: Vec<(Option<ImageLayout>, Option<ImageLayout>)> = vec![(None, None); attachment_num]; + + let subpasses = vec![ + $({ + let desc = SubpassDesc { + color_attachments: vec![ + $({ + let layout = &mut layouts[$color_atch]; + layout.0 = layout.0.or(Some(ImageLayout::ColorAttachmentOptimal)); + layout.1 = Some(ImageLayout::ColorAttachmentOptimal); + + ($color_atch, ImageLayout::ColorAttachmentOptimal) + }),* + ], + depth_stencil: { + let depth: Option<(usize, ImageLayout)> = None; + $( + let layout = &mut layouts[$depth_atch]; + layout.1 = Some(ImageLayout::DepthStencilAttachmentOptimal); + layout.0 = layout.0.or(layout.1); + + let depth = Some(($depth_atch, ImageLayout::DepthStencilAttachmentOptimal)); + )* + depth + }, + input_attachments: vec![ + $({ + let layout = &mut layouts[$input_atch]; + layout.1 = Some(ImageLayout::ShaderReadOnlyOptimal); + layout.0 = layout.0.or(layout.1); + + ($input_atch, ImageLayout::ShaderReadOnlyOptimal) + }),* + ], + resolve_attachments: vec![ + $($({ + let layout = &mut layouts[$resolve_atch]; + layout.1 = Some(ImageLayout::TransferDstOptimal); + layout.0 = layout.0.or(layout.1); + + ($resolve_atch, ImageLayout::TransferDstOptimal) + }),*)* + ], + preserve_attachments: (0 .. attachment_num).filter(|&a| { + $(if a == $color_atch { return false; })* + $(if a == $depth_atch { return false; })* + $(if a == $input_atch { return false; })* + $($(if a == $resolve_atch { return false; })*)* + true + }).collect() + }; + + assert!(desc.resolve_attachments.is_empty() || + desc.resolve_attachments.len() == desc.color_attachments.len()); + desc + }),* + ]; + + let dependencies = (0..subpasses.len().saturating_sub(1)) + .map(|id| { + SubpassDependencyDesc { + source_subpass: id, + destination_subpass: id + 1, + source_stages: PipelineStages { + all_graphics: true, + ..PipelineStages::none() + }, // TODO: correct values + destination_stages: PipelineStages { + all_graphics: true, + ..PipelineStages::none() + }, // TODO: correct values + source_access: AccessFlags::all(), // TODO: correct values + destination_access: AccessFlags::all(), // TODO: correct values + by_region: true, // TODO: correct values + } + }) + .collect(); + + let attachments = vec![ + $({ + let layout = &mut layouts[$atch_name]; + $(layout.0 = Some($init_layout);)* + $(layout.1 = Some($final_layout);)* + + AttachmentDesc { + format: $format, + samples: $samples.try_into().unwrap(), + load: $crate::render_pass::LoadOp::$load, + store: $crate::render_pass::StoreOp::$store, + stencil_load: $crate::render_pass::LoadOp::$load, + stencil_store: $crate::render_pass::StoreOp::$store, + initial_layout: layout.0.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: layout.1.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(), + ), + } + }),* + ]; + + RenderPassDesc::new( + attachments, + subpasses, + dependencies, + ) + }; + + RenderPass::new($device, desc) + }); +} + +#[cfg(test)] +mod tests { + use crate::format::Format; + + #[test] + fn single_pass_resolve() { + let (device, _) = gfx_dev_and_queue!(); + let _ = single_pass_renderpass!(device.clone(), + attachments: { + a: { + load: Clear, + store: DontCare, + format: Format::R8G8B8A8Unorm, + samples: 4, + }, + b: { + load: DontCare, + store: Store, + format: Format::R8G8B8A8Unorm, + samples: 1, + } + }, + pass: { + color: [a], + depth_stencil: {}, + resolve: [b], + } + ) + .unwrap(); + } +} |