1 object Vulkan 2 let vk_attachment_unused : u32 = !0 3 4 object VkRenderPass = 5 def create (device : VkDevice 6 attachments : List<AttachmentFormat> 7 passes : List<SubpassFormat> 8 settings : Settings) : (SampleCountFlags, VkRenderPass) = 9 let default_access_mask = AccessFlags/InputAttachmentRead 10 | AccessFlags/ColorAttachmentRead 11 | AccessFlags/ColorAttachmentWrite 12 | AccessFlags/DepthStencilAttachmentRead 13 | AccessFlags/DepthStencilAttachmentWrite 14 15 let reading_stages = PipelineStageFlags/ComputeShader 16 | PipelineStageFlags/VertexShader 17 | PipelineStageFlags/FragmentShader 18 | PipelineStageFlags/Transfer 19 20 let mut dependency_from_external = SubpassDependency 21 src_subpass = Vulkan.subpass_external 22 dst_subpass = 0 23 src_stage_mask = PipelineStageFlags/TopOfPipe 24 dst_stage_mask = PipelineStageFlags/AllGraphics 25 src_access_mask = AccessFlags@zero 26 dst_access_mask = default_access_mask 27 dependency_flags = DependencyFlags@zero 28 29 let mut dependency_to_external = SubpassDependency 30 src_subpass = 0 31 dst_subpass = Vulkan.subpass_external 32 src_stage_mask = PipelineStageFlags/AllGraphics 33 dst_stage_mask = PipelineStageFlags/BottomOfPipe 34 src_access_mask = default_access_mask 35 dst_access_mask = AccessFlags@zero 36 dependency_flags = DependencyFlags@zero 37 38 let attachment_descriptions = List<AttachmentDescription>.new 39 40 for attachment in attachments do 41 let usage = attachment.usage 42 let is_sampled = usage.contains ImageUsageFlags/Sampled 43 let is_storage = usage.contains ImageUsageFlags/Storage 44 let is_color = usage.contains ImageUsageFlags/ColorAttachment 45 let is_depth = usage.contains ImageUsageFlags/DepthStencilAttachment 46 47 let (enter_op, exit_op) = 48 if is_depth 49 then (settings.depth_enter_op, settings.depth_exit_op) 50 else (settings.color_enter_op, settings.color_exit_op) 51 52 if enter_op == EnterOp/Clear 53 || enter_op == EnterOp/Load && is_depth 54 || not is_depth && not is_color 55 then 56 dependency_from_external.src_stage_mask |= reading_stages 57 58 if exit_op == ExitOp/Read then 59 dependency_to_external.dst_stage_mask |= PipelineStageFlags/Transfer 60 dependency_to_external.dst_access_mask |= AccessFlags/TransferRead 61 62 if is_sampled then 63 dependency_to_external.dst_stage_mask |= 64 PipelineStageFlags/VertexShader 65 | PipelineStageFlags/FragmentShader 66 | PipelineStageFlags/ComputeShader 67 68 dependency_to_external.dst_access_mask |= AccessFlags/ShaderRead 69 70 else if is_storage then 71 dependency_to_external.dst_stage_mask |= 72 PipelineStageFlags/VertexShader 73 | PipelineStageFlags/FragmentShader 74 | PipelineStageFlags/ComputeShader 75 76 dependency_to_external.dst_access_mask |= 77 AccessFlags/ShaderRead | AccessFlags/ShaderWrite 78 else 79 dependency_to_external.dst_stage_mask |= 80 PipelineStageFlags/ColorAttachmentOutput 81 82 dependency_to_external.dst_access_mask |= 83 AccessFlags/ColorAttachmentRead 84 | AccessFlags/ColorAttachmentWrite 85 86 if is_depth then 87 dependency_to_external.dst_stage_mask |= 88 PipelineStageFlags/EarlyFragmentTests 89 | PipelineStageFlags/LateFragmentTests 90 91 dependency_to_external.dst_access_mask |= 92 AccessFlags/DepthStencilAttachmentRead 93 | AccessFlags/DepthStencilAttachmentWrite 94 95 let description = if not is_depth && not is_color then 96 AttachmentDescription 97 flags = AttachmentDescriptionFlags@zero 98 format = attachment.format 99 samples = attachment.samples 100 load_op = AttachmentLoadOp/DontCare 101 stencil_load_op = AttachmentLoadOp/DontCare 102 initial_layout = ImageLayout/Undefined 103 store_op = AttachmentStoreOp/DontCare 104 stencil_store_op = AttachmentStoreOp/DontCare 105 final_layout = ImageLayout/Undefined 106 f@ AttachmentDescription.default 107 else 108 let optimal_layout = when 109 is_color && not is_depth -> ImageLayout/ColorAttachmentOptimal 110 not is_color && is_depth -> 111 ImageLayout/DepthStencilAttachmentOptimal 112 113 else -> fail 114 115 let default_layout = when 116 is_sampled -> ImageLayout/ShaderReadOnlyOptimal 117 is_storage -> ImageLayout/General 118 else -> optimal_layout 119 120 let initial_layout = case enter_op of 121 EnterOp/Clear -> ImageLayout/Undefined 122 EnterOp/Continue -> optimal_layout 123 EnterOp/Load -> default_layout 124 125 let final_layout = case exit_op of 126 ExitOp/Continue -> optimal_layout 127 ExitOp/Read | ExitOp/Discard -> default_layout 128 129 let load_op = case enter_op of 130 EnterOp/Clear -> AttachmentLoadOp/Clear 131 EnterOp/Load -> AttachmentLoadOp/Load 132 EnterOp/Continue -> AttachmentLoadOp/Load 133 134 let stencil_load_op = when 135 enter_op == EnterOp/Clear -> AttachmentLoadOp/Clear 136 is_color -> AttachmentLoadOp/DontCare 137 is_depth -> AttachmentLoadOp/Load 138 else -> fail 139 140 let (store_op, stencil_store_op) = if is_color then 141 case exit_op of 142 ExitOp/Read -> 143 (AttachmentStoreOp/Store, AttachmentStoreOp/DontCare) 144 145 ExitOp/Discard -> 146 (AttachmentStoreOp/DontCare, AttachmentStoreOp/DontCare) 147 148 ExitOp/Continue -> 149 (AttachmentStoreOp/Store, AttachmentStoreOp/DontCare) 150 151 else if is_depth then 152 case exit_op of 153 ExitOp/Read -> 154 (AttachmentStoreOp/Store, AttachmentStoreOp/Store) 155 156 ExitOp/Discard -> 157 (AttachmentStoreOp/DontCare, AttachmentStoreOp/DontCare) 158 159 ExitOp/Continue -> 160 (AttachmentStoreOp/Store, AttachmentStoreOp/Store) 161 else 162 fail 163 164 AttachmentDescription 165 flags = AttachmentDescriptionFlags@zero 166 format = attachment.format 167 samples = attachment.samples 168 =load_op 169 =stencil_load_op 170 =initial_layout 171 =store_op 172 =stencil_store_op 173 =final_layout 174 f@ AttachmentDescription.default 175 176 attachment_descriptions.add description 177 178 let subpasses = List<SubpassDescription>.new 179 let pass_color_references = List<List<AttachmentReference>>.new 180 let pass_input_references = List<List<AttachmentReference>>.new 181 let pass_resolve_references = List<List<AttachmentReference>>.new 182 let pass_preserve_references = List<List<u32>>.new 183 let pass_depth_references = List<AttachmentReference>.new 184 185 let subpass_dependencies = 186 if settings.no_dependencies 187 then List<SubpassDependency>.new 188 else [dependency_from_external, dependency_to_external] 189 190 let get_samples (pass : SubpassFormat) = 191 let attachment = if pass.color_attachments.is_empty 192 then pass.depth_attachment 193 else pass.color_attachments[0] 194 195 attachments[attachment].samples 196 197 for i = 0 until passes.size do 198 let pass = passes[i] 199 let color_references = List<AttachmentReference>.new 200 let samples = get_samples pass 201 202 for j = 0 until pass.color_attachments.size do 203 let attachment = pass.color_attachments[j] 204 let reference = if attachment == Vulkan.attachment_unused then 205 AttachmentReference 206 attachment = Vulkan.vk_attachment_unused 207 layout = ImageLayout/Undefined 208 else 209 assert attachments[attachment].usage.contains 210 ImageUsageFlags/ColorAttachment 211 && attachments[attachment].samples == samples 212 213 AttachmentReference 214 attachment = attachment as u32 215 layout = ImageLayout/ColorAttachmentOptimal 216 217 color_references.add reference 218 219 let input_references = List<AttachmentReference>.new 220 221 for j = 0 until pass.input_attachments.size do 222 let attachment = pass.input_attachments[j] 223 let reference = if attachment == Vulkan.attachment_unused then 224 AttachmentReference 225 attachment = Vulkan.vk_attachment_unused 226 layout = ImageLayout/Undefined 227 else 228 assert attachments[attachment].usage.contains 229 ImageUsageFlags/ColorAttachment 230 231 AttachmentReference 232 attachment = attachment as u32 233 layout = ImageLayout/ShaderReadOnlyOptimal 234 235 input_references.add reference 236 237 let resolve_references = List<AttachmentReference>.new 238 239 if pass.resolve_attachments.size > 0 then 240 assert pass.resolve_attachments.size == pass.color_attachments.size 241 && samples <> SampleCountFlags/1 242 243 for j = 0 until pass.resolve_attachments.size do 244 let attachment = pass.resolve_attachments[j] 245 let reference = if attachment == Vulkan.attachment_unused then 246 AttachmentReference 247 attachment = Vulkan.vk_attachment_unused 248 layout = ImageLayout/Undefined 249 else 250 assert pass.color_attachments[j] <> Vulkan.attachment_unused 251 assert attachments[attachment].usage.contains 252 ImageUsageFlags/ColorAttachment 253 254 assert attachments[attachment].samples == SampleCountFlags/1 255 256 AttachmentReference 257 attachment = attachment as u32 258 layout = ImageLayout/ShaderReadOnlyOptimal 259 260 resolve_references.add reference 261 262 let preserve_references = List<u32>.new 263 264 for j = 0 until pass.preserve_attachments.size do 265 let attachment = pass.preserve_attachments[j] 266 assert attachment <> Vulkan.attachment_unused 267 preserve_references.add attachment.as<u32> 268 269 let depth_stencil_reference = 270 if pass.depth_attachment <> Vulkan.attachment_unused then 271 let attachment = pass.depth_attachment 272 assert attachments[attachment].usage.contains 273 ImageUsageFlags/DepthStencilAttachment 274 && attachments[attachment].samples == samples 275 276 AttachmentReference 277 attachment = attachment as u32 278 layout = ImageLayout/DepthStencilAttachmentOptimal 279 else 280 AttachmentReference 281 attachment = Vulkan.vk_attachment_unused 282 layout = ImageLayout/Undefined 283 284 pass_depth_references.add depth_stencil_reference 285 let depth_stencil_ref_in_vec = pass_depth_references.last 286 287 let subpass = SubpassDescription 288 flags = SubpassDescriptionFlags@zero 289 pipeline_bind_point = PipelineBindPoint/Graphics 290 input_attachment_count = input_references.size 291 input_attachments = 292 if input_references.size > 0 293 then input_references.as_ptr 294 else null 295 296 color_attachment_count = color_references.size 297 color_attachments = 298 if color_references.size > 0 299 then color_references.as_ptr 300 else null 301 302 depth_stencil_attachment = 303 if depth_stencil_ref_in_vec.attachment <> Vulkan.vk_attachment_unused 304 then depth_stencil_ref_in_vec@ptr 305 else null 306 307 resolve_attachments = 308 if resolve_references.size > 0 309 then resolve_references.as_ptr 310 else null 311 312 preserve_attachment_count = preserve_references.size as u32 313 preserve_attachments = 314 if preserve_references.size > 0 315 then preserve_references.as_ptr 316 else null 317 318 subpasses.add subpass 319 pass_color_references.add color_references 320 pass_input_references.add input_references 321 pass_resolve_references.add resolve_references 322 pass_preserve_references.add preserve_references 323 324 if i > 0 then 325 let dependency = SubpassDependency 326 src_subpass = i - 1 327 dst_subpass = i 328 src_stage_mask = PipelineStageFlags/ColorAttachmentOutput 329 | PipelineStageFlags/EarlyFragmentTests 330 | PipelineStageFlags/LateFragmentTests 331 dst_stage_mask = PipelineStageFlags/ColorAttachmentOutput 332 | PipelineStageFlags/EarlyFragmentTests 333 | PipelineStageFlags/LateFragmentTests 334 | PipelineStageFlags/FragmentShader 335 src_access_mask = AccessFlags/ColorAttachmentWrite 336 | AccessFlags/DepthStencilAttachmentWrite 337 dst_access_mask = AccessFlags/ColorAttachmentRead 338 | AccessFlags/ColorAttachmentWrite 339 | AccessFlags/DepthStencilAttachmentRead 340 | AccessFlags/InputAttachmentRead 341 dependency_flags = DependencyFlags/ByRegion 342 343 subpass_dependencies.add dependency 344 345 let render_pass_create_info = RenderPassCreateInfo 346 type = StructureType/RenderPassCreateInfo 347 next = null 348 flags = RenderPassCreateFlags@zero 349 attachment_count = attachment_descriptions.size 350 attachments = attachment_descriptions.as_ptr 351 subpass_count = subpasses.size 352 subpasses = subpasses.as_ptr 353 dependency_count = subpass_dependencies.size 354 dependencies = if subpass_dependencies.size > 0 355 then subpass_dependencies.as_ptr 356 else null 357 358 let mut render_pass = null 359 vk/create_render_pass device render_pass_create_info@ptr null 360 render_pass@mut_ptr 361 |> assert_success 362 363 (get_samples passes[0], render_pass) 364 365 object RenderPass = 366 def create (format : RenderPassFormat 367 settings : Settings 368 cache : RenderPassCache) = 369 let instance : Instance @auto 370 371 if cache.contains settings then 372 return cache.get settings 373 374 let (samples, object) = VkRenderPass.create instance.device format.attachments 375 format.subpasses settings 376 377 let render_pass = RenderPass =format =object =samples 378 cache.add settings render_pass 379 380 render_pass 381