1 // Copyright (c) 2016 The vulkano developers 2 // Licensed under the Apache License, Version 2.0 3 // <LICENSE-APACHE or 4 // https://www.apache.org/licenses/LICENSE-2.0> or the MIT 5 // license <LICENSE-MIT or https://opensource.org/licenses/MIT>, 6 // at your option. All files in the project carrying such 7 // notice may not be copied, modified, or distributed except 8 // according to those terms. 9 10 /// Builds a `RenderPass` object whose template parameter is of indeterminate type. 11 #[macro_export] 12 macro_rules! single_pass_renderpass { 13 ( 14 $device:expr, 15 attachments: { $($a:tt)* }, 16 pass: { 17 color: [$($color_atch:ident),* $(,)?], 18 depth_stencil: {$($depth_atch:ident)?} 19 $(,resolve: [$($resolve_atch:ident),* $(,)?])* 20 $(,)* 21 } $(,)? 22 ) => ( 23 $crate::ordered_passes_renderpass!( 24 $device, 25 attachments: { $($a)* }, 26 passes: [ 27 { 28 color: [$($color_atch),*], 29 depth_stencil: {$($depth_atch)*}, 30 input: [], 31 resolve: [$($($resolve_atch),*)*] 32 } 33 ] 34 ) 35 ) 36 } 37 38 /// Builds a `RenderPass` object whose template parameter is of indeterminate type. 39 #[macro_export] 40 macro_rules! ordered_passes_renderpass { 41 ( 42 $device:expr, 43 attachments: { 44 $( 45 $atch_name:ident: { 46 load: $load:ident, 47 store: $store:ident, 48 format: $format:expr, 49 samples: $samples:expr 50 $(,initial_layout: $init_layout:expr)? 51 $(,final_layout: $final_layout:expr)? 52 $(,)? 53 } 54 ),* $(,)? 55 }, 56 passes: [ 57 $( 58 { 59 color: [$($color_atch:ident),* $(,)?], 60 depth_stencil: {$($depth_atch:ident)* $(,)?}, 61 input: [$($input_atch:ident),* $(,)?] 62 $(,resolve: [$($resolve_atch:ident),* $(,)?])? 63 $(,)* 64 } 65 ),* $(,)? 66 ] $(,)? 67 ) => ({ 68 use $crate::render_pass::RenderPass; 69 70 let create_info = { 71 #[allow(unused)] 72 let mut attachment_num = 0; 73 $( 74 let $atch_name = attachment_num; 75 attachment_num += 1; 76 )* 77 78 #[allow(unused)] 79 let mut layouts: Vec<( 80 Option<$crate::image::ImageLayout>, 81 Option<$crate::image::ImageLayout> 82 )> = vec![(None, None); attachment_num as usize]; 83 84 let subpasses = vec![ 85 $({ 86 let desc = $crate::render_pass::SubpassDescription { 87 color_attachments: vec![ 88 $({ 89 let layout = &mut layouts[$color_atch as usize]; 90 layout.0 = layout.0.or(Some($crate::image::ImageLayout::ColorAttachmentOptimal)); 91 layout.1 = Some($crate::image::ImageLayout::ColorAttachmentOptimal); 92 93 Some($crate::render_pass::AttachmentReference { 94 attachment: $color_atch, 95 layout: $crate::image::ImageLayout::ColorAttachmentOptimal, 96 ..Default::default() 97 }) 98 }),* 99 ], 100 depth_stencil_attachment: { 101 let depth: Option<$crate::render_pass::AttachmentReference> = None; 102 $( 103 let layout = &mut layouts[$depth_atch as usize]; 104 layout.1 = Some($crate::image::ImageLayout::DepthStencilAttachmentOptimal); 105 layout.0 = layout.0.or(layout.1); 106 107 let depth = Some($crate::render_pass::AttachmentReference { 108 attachment: $depth_atch, 109 layout: $crate::image::ImageLayout::DepthStencilAttachmentOptimal, 110 ..Default::default() 111 }); 112 )* 113 depth 114 }, 115 input_attachments: vec![ 116 $({ 117 let layout = &mut layouts[$input_atch as usize]; 118 layout.1 = Some($crate::image::ImageLayout::ShaderReadOnlyOptimal); 119 layout.0 = layout.0.or(layout.1); 120 121 Some($crate::render_pass::AttachmentReference { 122 attachment: $input_atch, 123 layout: $crate::image::ImageLayout::ShaderReadOnlyOptimal, 124 ..Default::default() 125 }) 126 }),* 127 ], 128 resolve_attachments: vec![ 129 $($({ 130 let layout = &mut layouts[$resolve_atch as usize]; 131 layout.1 = Some($crate::image::ImageLayout::TransferDstOptimal); 132 layout.0 = layout.0.or(layout.1); 133 134 Some($crate::render_pass::AttachmentReference { 135 attachment: $resolve_atch, 136 layout: $crate::image::ImageLayout::TransferDstOptimal, 137 ..Default::default() 138 }) 139 }),*)* 140 ], 141 preserve_attachments: (0 .. attachment_num).filter(|&a| { 142 $(if a == $color_atch { return false; })* 143 $(if a == $depth_atch { return false; })* 144 $(if a == $input_atch { return false; })* 145 $($(if a == $resolve_atch { return false; })*)* 146 true 147 }).collect(), 148 ..Default::default() 149 }; 150 151 assert!(desc.resolve_attachments.is_empty() || 152 desc.resolve_attachments.len() == desc.color_attachments.len()); 153 desc 154 }),* 155 ]; 156 157 let dependencies: Vec<_> = (0..subpasses.len().saturating_sub(1) as u32) 158 .map(|id| { 159 // TODO: correct values 160 let src_stages = $crate::sync::PipelineStages::ALL_GRAPHICS; 161 let dst_stages = $crate::sync::PipelineStages::ALL_GRAPHICS; 162 let src_access = $crate::sync::AccessFlags::MEMORY_READ 163 | $crate::sync::AccessFlags::MEMORY_WRITE; 164 let dst_access = $crate::sync::AccessFlags::MEMORY_READ 165 | $crate::sync::AccessFlags::MEMORY_WRITE; 166 167 $crate::render_pass::SubpassDependency { 168 src_subpass: id.into(), 169 dst_subpass: (id + 1).into(), 170 src_stages, 171 dst_stages, 172 src_access, 173 dst_access, 174 // TODO: correct values 175 dependency_flags: $crate::sync::DependencyFlags::BY_REGION, 176 ..Default::default() 177 } 178 }) 179 .collect(); 180 181 let attachments = vec![ 182 $({ 183 let layout = &mut layouts[$atch_name as usize]; 184 $(layout.0 = Some($init_layout);)* 185 $(layout.1 = Some($final_layout);)* 186 187 $crate::render_pass::AttachmentDescription { 188 format: Some($format), 189 samples: $crate::image::SampleCount::try_from($samples).unwrap(), 190 load_op: $crate::render_pass::LoadOp::$load, 191 store_op: $crate::render_pass::StoreOp::$store, 192 stencil_load_op: $crate::render_pass::LoadOp::$load, 193 stencil_store_op: $crate::render_pass::StoreOp::$store, 194 initial_layout: layout.0.expect( 195 format!( 196 "Attachment {} is missing initial_layout, this is normally \ 197 automatically determined but you can manually specify it for an individual \ 198 attachment in the single_pass_renderpass! macro", 199 attachment_num 200 ) 201 .as_ref(), 202 ), 203 final_layout: layout.1.expect( 204 format!( 205 "Attachment {} is missing final_layout, this is normally \ 206 automatically determined but you can manually specify it for an individual \ 207 attachment in the single_pass_renderpass! macro", 208 attachment_num 209 ) 210 .as_ref(), 211 ), 212 ..Default::default() 213 } 214 }),* 215 ]; 216 217 $crate::render_pass::RenderPassCreateInfo { 218 attachments, 219 subpasses, 220 dependencies, 221 ..Default::default() 222 } 223 }; 224 225 RenderPass::new($device, create_info) 226 }); 227 } 228 229 #[cfg(test)] 230 mod tests { 231 use crate::format::Format; 232 233 #[test] single_pass_resolve()234 fn single_pass_resolve() { 235 let (device, _) = gfx_dev_and_queue!(); 236 let _ = single_pass_renderpass!( 237 device, 238 attachments: { 239 a: { 240 load: Clear, 241 store: DontCare, 242 format: Format::R8G8B8A8_UNORM, 243 samples: 4, 244 }, 245 b: { 246 load: DontCare, 247 store: Store, 248 format: Format::R8G8B8A8_UNORM, 249 samples: 1, 250 }, 251 }, 252 pass: { 253 color: [a], 254 depth_stencil: {}, 255 resolve: [b], 256 }, 257 ) 258 .unwrap(); 259 } 260 } 261