1 // Copyright (c) 2022 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 use crate::{ 11 command_buffer::{ 12 allocator::CommandBufferAllocator, 13 auto::{ 14 BeginRenderPassState, BeginRenderingAttachments, BeginRenderingState, RenderPassState, 15 RenderPassStateType, 16 }, 17 synced::{Command, Resource, SyncCommandBufferBuilder, SyncCommandBufferBuilderError}, 18 sys::UnsafeCommandBufferBuilder, 19 AutoCommandBufferBuilder, ResourceInCommand, ResourceUseRef, SubpassContents, 20 }, 21 device::{DeviceOwned, QueueFlags}, 22 format::{ClearColorValue, ClearValue, Format, NumericType}, 23 image::{ImageAspects, ImageLayout, ImageUsage, ImageViewAbstract, SampleCount}, 24 render_pass::{ 25 AttachmentDescription, Framebuffer, LoadOp, RenderPass, ResolveMode, StoreOp, 26 SubpassDescription, 27 }, 28 sync::{AccessFlags, PipelineMemoryAccess, PipelineStages}, 29 RequirementNotMet, RequiresOneOf, Version, VulkanObject, 30 }; 31 use smallvec::SmallVec; 32 use std::{ 33 cmp::min, 34 error::Error, 35 fmt::{Display, Error as FmtError, Formatter}, 36 ops::Range, 37 sync::Arc, 38 }; 39 40 /// # Commands for render passes. 41 /// 42 /// These commands require a graphics queue. 43 impl<L, A> AutoCommandBufferBuilder<L, A> 44 where 45 A: CommandBufferAllocator, 46 { 47 /// Begins a render pass using a render pass object and framebuffer. 48 /// 49 /// You must call this or `begin_rendering` before you can record draw commands. 50 /// 51 /// `contents` specifies what kinds of commands will be recorded in the render pass, either 52 /// draw commands or executions of secondary command buffers. begin_render_pass( &mut self, mut render_pass_begin_info: RenderPassBeginInfo, contents: SubpassContents, ) -> Result<&mut Self, RenderPassError>53 pub fn begin_render_pass( 54 &mut self, 55 mut render_pass_begin_info: RenderPassBeginInfo, 56 contents: SubpassContents, 57 ) -> Result<&mut Self, RenderPassError> { 58 self.validate_begin_render_pass(&mut render_pass_begin_info, contents)?; 59 60 unsafe { 61 let RenderPassBeginInfo { 62 ref render_pass, 63 ref framebuffer, 64 render_area_offset, 65 render_area_extent, 66 clear_values: _, 67 _ne: _, 68 } = render_pass_begin_info; 69 70 let subpass = render_pass.clone().first_subpass(); 71 let view_mask = subpass.subpass_desc().view_mask; 72 73 let render_pass_state = RenderPassState { 74 contents, 75 render_area_offset, 76 render_area_extent, 77 render_pass: BeginRenderPassState { 78 subpass, 79 framebuffer: Some(framebuffer.clone()), 80 } 81 .into(), 82 view_mask, 83 }; 84 85 self.inner 86 .begin_render_pass(render_pass_begin_info, contents)?; 87 self.render_pass_state = Some(render_pass_state); 88 89 Ok(self) 90 } 91 } 92 validate_begin_render_pass( &self, render_pass_begin_info: &mut RenderPassBeginInfo, contents: SubpassContents, ) -> Result<(), RenderPassError>93 fn validate_begin_render_pass( 94 &self, 95 render_pass_begin_info: &mut RenderPassBeginInfo, 96 contents: SubpassContents, 97 ) -> Result<(), RenderPassError> { 98 let device = self.device(); 99 100 // VUID-VkSubpassBeginInfo-contents-parameter 101 contents.validate_device(device)?; 102 103 let queue_family_properties = self.queue_family_properties(); 104 105 // VUID-vkCmdBeginRenderPass2-commandBuffer-cmdpool 106 if !queue_family_properties 107 .queue_flags 108 .intersects(QueueFlags::GRAPHICS) 109 { 110 return Err(RenderPassError::NotSupportedByQueueFamily); 111 } 112 113 // VUID-vkCmdBeginRenderPass2-renderpass 114 if self.render_pass_state.is_some() { 115 return Err(RenderPassError::ForbiddenInsideRenderPass); 116 } 117 118 let RenderPassBeginInfo { 119 render_pass, 120 framebuffer, 121 render_area_offset, 122 render_area_extent, 123 clear_values, 124 _ne: _, 125 } = render_pass_begin_info; 126 127 // VUID-VkRenderPassBeginInfo-commonparent 128 // VUID-vkCmdBeginRenderPass2-framebuffer-02779 129 assert_eq!(device, framebuffer.device()); 130 131 // VUID-VkRenderPassBeginInfo-renderPass-00904 132 if !render_pass.is_compatible_with(framebuffer.render_pass()) { 133 return Err(RenderPassError::FramebufferNotCompatible); 134 } 135 136 for i in 0..2 { 137 // VUID-VkRenderPassBeginInfo-pNext-02852 138 // VUID-VkRenderPassBeginInfo-pNext-02853 139 if render_area_offset[i] + render_area_extent[i] > framebuffer.extent()[i] { 140 return Err(RenderPassError::RenderAreaOutOfBounds); 141 } 142 } 143 144 for (attachment_index, (attachment_desc, image_view)) in render_pass 145 .attachments() 146 .iter() 147 .zip(framebuffer.attachments()) 148 .enumerate() 149 { 150 let attachment_index = attachment_index as u32; 151 let &AttachmentDescription { 152 initial_layout, 153 final_layout, 154 .. 155 } = attachment_desc; 156 157 for layout in [initial_layout, final_layout] { 158 match layout { 159 ImageLayout::ColorAttachmentOptimal => { 160 // VUID-vkCmdBeginRenderPass2-initialLayout-03094 161 if !image_view.usage().intersects(ImageUsage::COLOR_ATTACHMENT) { 162 return Err(RenderPassError::AttachmentImageMissingUsage { 163 attachment_index, 164 usage: "color_attachment", 165 }); 166 } 167 } 168 ImageLayout::DepthReadOnlyStencilAttachmentOptimal 169 | ImageLayout::DepthAttachmentStencilReadOnlyOptimal 170 | ImageLayout::DepthStencilAttachmentOptimal 171 | ImageLayout::DepthStencilReadOnlyOptimal => { 172 // VUID-vkCmdBeginRenderPass2-initialLayout-03096 173 if !image_view 174 .usage() 175 .intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT) 176 { 177 return Err(RenderPassError::AttachmentImageMissingUsage { 178 attachment_index, 179 usage: "depth_stencil_attachment", 180 }); 181 } 182 } 183 ImageLayout::ShaderReadOnlyOptimal => { 184 // VUID-vkCmdBeginRenderPass2-initialLayout-03097 185 if !image_view 186 .usage() 187 .intersects(ImageUsage::SAMPLED | ImageUsage::INPUT_ATTACHMENT) 188 { 189 return Err(RenderPassError::AttachmentImageMissingUsage { 190 attachment_index, 191 usage: "sampled or input_attachment", 192 }); 193 } 194 } 195 ImageLayout::TransferSrcOptimal => { 196 // VUID-vkCmdBeginRenderPass2-initialLayout-03098 197 if !image_view.usage().intersects(ImageUsage::TRANSFER_SRC) { 198 return Err(RenderPassError::AttachmentImageMissingUsage { 199 attachment_index, 200 usage: "transfer_src", 201 }); 202 } 203 } 204 ImageLayout::TransferDstOptimal => { 205 // VUID-vkCmdBeginRenderPass2-initialLayout-03099 206 if !image_view.usage().intersects(ImageUsage::TRANSFER_DST) { 207 return Err(RenderPassError::AttachmentImageMissingUsage { 208 attachment_index, 209 usage: "transfer_dst", 210 }); 211 } 212 } 213 _ => (), 214 } 215 } 216 } 217 218 for subpass_desc in render_pass.subpasses() { 219 let SubpassDescription { 220 view_mask: _, 221 input_attachments, 222 color_attachments, 223 resolve_attachments, 224 depth_stencil_attachment, 225 preserve_attachments: _, 226 _ne: _, 227 } = subpass_desc; 228 229 for atch_ref in (input_attachments.iter()) 230 .chain(color_attachments) 231 .chain(resolve_attachments) 232 .chain([depth_stencil_attachment]) 233 .flatten() 234 { 235 let image_view = &framebuffer.attachments()[atch_ref.attachment as usize]; 236 237 match atch_ref.layout { 238 ImageLayout::ColorAttachmentOptimal => { 239 // VUID-vkCmdBeginRenderPass2-initialLayout-03094 240 if !image_view.usage().intersects(ImageUsage::COLOR_ATTACHMENT) { 241 return Err(RenderPassError::AttachmentImageMissingUsage { 242 attachment_index: atch_ref.attachment, 243 usage: "color_attachment", 244 }); 245 } 246 } 247 ImageLayout::DepthReadOnlyStencilAttachmentOptimal 248 | ImageLayout::DepthAttachmentStencilReadOnlyOptimal 249 | ImageLayout::DepthStencilAttachmentOptimal 250 | ImageLayout::DepthStencilReadOnlyOptimal => { 251 // VUID-vkCmdBeginRenderPass2-initialLayout-03096 252 if !image_view 253 .usage() 254 .intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT) 255 { 256 return Err(RenderPassError::AttachmentImageMissingUsage { 257 attachment_index: atch_ref.attachment, 258 usage: "depth_stencil_attachment", 259 }); 260 } 261 } 262 ImageLayout::ShaderReadOnlyOptimal => { 263 // VUID-vkCmdBeginRenderPass2-initialLayout-03097 264 if !image_view 265 .usage() 266 .intersects(ImageUsage::SAMPLED | ImageUsage::INPUT_ATTACHMENT) 267 { 268 return Err(RenderPassError::AttachmentImageMissingUsage { 269 attachment_index: atch_ref.attachment, 270 usage: "sampled or input_attachment", 271 }); 272 } 273 } 274 ImageLayout::TransferSrcOptimal => { 275 // VUID-vkCmdBeginRenderPass2-initialLayout-03098 276 if !image_view.usage().intersects(ImageUsage::TRANSFER_SRC) { 277 return Err(RenderPassError::AttachmentImageMissingUsage { 278 attachment_index: atch_ref.attachment, 279 usage: "transfer_src", 280 }); 281 } 282 } 283 ImageLayout::TransferDstOptimal => { 284 // VUID-vkCmdBeginRenderPass2-initialLayout-03099 285 if !image_view.usage().intersects(ImageUsage::TRANSFER_DST) { 286 return Err(RenderPassError::AttachmentImageMissingUsage { 287 attachment_index: atch_ref.attachment, 288 usage: "transfer_dst", 289 }); 290 } 291 } 292 _ => (), 293 } 294 } 295 } 296 297 // VUID-VkRenderPassBeginInfo-clearValueCount-00902 298 if clear_values.len() < render_pass.attachments().len() { 299 return Err(RenderPassError::ClearValueMissing { 300 attachment_index: clear_values.len() as u32, 301 }); 302 } 303 304 // VUID-VkRenderPassBeginInfo-clearValueCount-04962 305 for (attachment_index, (attachment_desc, &mut clear_value)) in render_pass 306 .attachments() 307 .iter() 308 .zip(clear_values) 309 .enumerate() 310 { 311 let attachment_index = attachment_index as u32; 312 let attachment_format = attachment_desc.format.unwrap(); 313 314 if attachment_desc.load_op == LoadOp::Clear 315 || attachment_desc.stencil_load_op == LoadOp::Clear 316 { 317 let clear_value = match clear_value { 318 Some(x) => x, 319 None => return Err(RenderPassError::ClearValueMissing { attachment_index }), 320 }; 321 322 if let (Some(numeric_type), LoadOp::Clear) = 323 (attachment_format.type_color(), attachment_desc.load_op) 324 { 325 match numeric_type { 326 NumericType::SFLOAT 327 | NumericType::UFLOAT 328 | NumericType::SNORM 329 | NumericType::UNORM 330 | NumericType::SSCALED 331 | NumericType::USCALED 332 | NumericType::SRGB => { 333 if !matches!(clear_value, ClearValue::Float(_)) { 334 return Err(RenderPassError::ClearValueNotCompatible { 335 clear_value, 336 attachment_index, 337 attachment_format, 338 }); 339 } 340 } 341 NumericType::SINT => { 342 if !matches!(clear_value, ClearValue::Int(_)) { 343 return Err(RenderPassError::ClearValueNotCompatible { 344 clear_value, 345 attachment_index, 346 attachment_format, 347 }); 348 } 349 } 350 NumericType::UINT => { 351 if !matches!(clear_value, ClearValue::Uint(_)) { 352 return Err(RenderPassError::ClearValueNotCompatible { 353 clear_value, 354 attachment_index, 355 attachment_format, 356 }); 357 } 358 } 359 } 360 } else { 361 let attachment_aspects = attachment_format.aspects(); 362 let need_depth = attachment_aspects.intersects(ImageAspects::DEPTH) 363 && attachment_desc.load_op == LoadOp::Clear; 364 let need_stencil = attachment_aspects.intersects(ImageAspects::STENCIL) 365 && attachment_desc.stencil_load_op == LoadOp::Clear; 366 367 if need_depth && need_stencil { 368 if !matches!(clear_value, ClearValue::DepthStencil(_)) { 369 return Err(RenderPassError::ClearValueNotCompatible { 370 clear_value, 371 attachment_index, 372 attachment_format, 373 }); 374 } 375 } else if need_depth { 376 if !matches!(clear_value, ClearValue::Depth(_)) { 377 return Err(RenderPassError::ClearValueNotCompatible { 378 clear_value, 379 attachment_index, 380 attachment_format, 381 }); 382 } 383 } else if need_stencil { 384 if !matches!(clear_value, ClearValue::Stencil(_)) { 385 return Err(RenderPassError::ClearValueNotCompatible { 386 clear_value, 387 attachment_index, 388 attachment_format, 389 }); 390 } 391 } 392 } 393 } 394 } 395 396 // VUID-vkCmdBeginRenderPass2-initialLayout-03100 397 // TODO: 398 399 // VUID-vkCmdBeginRenderPass2-srcStageMask-06453 400 // TODO: 401 402 // VUID-vkCmdBeginRenderPass2-dstStageMask-06454 403 // TODO: 404 405 // VUID-vkCmdBeginRenderPass2-framebuffer-02533 406 // For any attachment in framebuffer that is used by renderPass and is bound to memory locations that are also bound to another attachment used by renderPass, and if at least one of those uses causes either 407 // attachment to be written to, both attachments must have had the VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT set 408 409 Ok(()) 410 } 411 412 /// Advances to the next subpass of the render pass previously begun with `begin_render_pass`. next_subpass( &mut self, contents: SubpassContents, ) -> Result<&mut Self, RenderPassError>413 pub fn next_subpass( 414 &mut self, 415 contents: SubpassContents, 416 ) -> Result<&mut Self, RenderPassError> { 417 self.validate_next_subpass(contents)?; 418 419 unsafe { 420 let render_pass_state = self.render_pass_state.as_mut().unwrap(); 421 let begin_render_pass_state = match &mut render_pass_state.render_pass { 422 RenderPassStateType::BeginRenderPass(x) => x, 423 _ => unreachable!(), 424 }; 425 426 begin_render_pass_state.subpass.next_subpass(); 427 render_pass_state.contents = contents; 428 render_pass_state.view_mask = begin_render_pass_state.subpass.subpass_desc().view_mask; 429 430 if render_pass_state.view_mask != 0 { 431 // When multiview is enabled, at the beginning of each subpass, all 432 // non-render pass state is undefined. 433 self.inner.reset_state(); 434 } 435 436 self.inner.next_subpass(contents); 437 } 438 439 Ok(self) 440 } 441 validate_next_subpass(&self, contents: SubpassContents) -> Result<(), RenderPassError>442 fn validate_next_subpass(&self, contents: SubpassContents) -> Result<(), RenderPassError> { 443 let device = self.device(); 444 445 // VUID-VkSubpassBeginInfo-contents-parameter 446 contents.validate_device(device)?; 447 448 // VUID-vkCmdNextSubpass2-renderpass 449 let render_pass_state = self 450 .render_pass_state 451 .as_ref() 452 .ok_or(RenderPassError::ForbiddenOutsideRenderPass)?; 453 454 let begin_render_pass_state = match &render_pass_state.render_pass { 455 RenderPassStateType::BeginRenderPass(state) => state, 456 RenderPassStateType::BeginRendering(_) => { 457 return Err(RenderPassError::ForbiddenWithBeginRendering) 458 } 459 }; 460 461 // VUID-vkCmdNextSubpass2-None-03102 462 if begin_render_pass_state.subpass.is_last_subpass() { 463 return Err(RenderPassError::NoSubpassesRemaining { 464 current_subpass: begin_render_pass_state.subpass.index(), 465 }); 466 } 467 468 // VUID? 469 if self.query_state.values().any(|state| state.in_subpass) { 470 return Err(RenderPassError::QueryIsActive); 471 } 472 473 // VUID-vkCmdNextSubpass2-commandBuffer-cmdpool 474 debug_assert!(self 475 .queue_family_properties() 476 .queue_flags 477 .intersects(QueueFlags::GRAPHICS)); 478 479 // VUID-vkCmdNextSubpass2-bufferlevel 480 // Ensured by the type of the impl block 481 482 Ok(()) 483 } 484 485 /// Ends the render pass previously begun with `begin_render_pass`. 486 /// 487 /// This must be called after you went through all the subpasses. end_render_pass(&mut self) -> Result<&mut Self, RenderPassError>488 pub fn end_render_pass(&mut self) -> Result<&mut Self, RenderPassError> { 489 self.validate_end_render_pass()?; 490 491 unsafe { 492 self.inner.end_render_pass(); 493 self.render_pass_state = None; 494 } 495 496 Ok(self) 497 } 498 validate_end_render_pass(&self) -> Result<(), RenderPassError>499 fn validate_end_render_pass(&self) -> Result<(), RenderPassError> { 500 // VUID-vkCmdEndRenderPass2-renderpass 501 let render_pass_state = self 502 .render_pass_state 503 .as_ref() 504 .ok_or(RenderPassError::ForbiddenOutsideRenderPass)?; 505 506 let begin_render_pass_state = match &render_pass_state.render_pass { 507 RenderPassStateType::BeginRenderPass(state) => state, 508 RenderPassStateType::BeginRendering(_) => { 509 return Err(RenderPassError::ForbiddenWithBeginRendering) 510 } 511 }; 512 513 // VUID-vkCmdEndRenderPass2-None-03103 514 if !begin_render_pass_state.subpass.is_last_subpass() { 515 return Err(RenderPassError::SubpassesRemaining { 516 current_subpass: begin_render_pass_state.subpass.index(), 517 remaining_subpasses: begin_render_pass_state 518 .subpass 519 .render_pass() 520 .subpasses() 521 .len() as u32 522 - begin_render_pass_state.subpass.index(), 523 }); 524 } 525 526 // VUID? 527 if self.query_state.values().any(|state| state.in_subpass) { 528 return Err(RenderPassError::QueryIsActive); 529 } 530 531 // VUID-vkCmdEndRenderPass2-commandBuffer-cmdpool 532 debug_assert!(self 533 .queue_family_properties() 534 .queue_flags 535 .intersects(QueueFlags::GRAPHICS)); 536 537 // VUID-vkCmdEndRenderPass2-bufferlevel 538 // Ensured by the type of the impl block 539 540 Ok(()) 541 } 542 } 543 544 impl<L, A> AutoCommandBufferBuilder<L, A> 545 where 546 A: CommandBufferAllocator, 547 { 548 /// Begins a render pass without a render pass object or framebuffer. 549 /// 550 /// You must call this or `begin_render_pass` before you can record draw commands. begin_rendering( &mut self, mut rendering_info: RenderingInfo, ) -> Result<&mut Self, RenderPassError>551 pub fn begin_rendering( 552 &mut self, 553 mut rendering_info: RenderingInfo, 554 ) -> Result<&mut Self, RenderPassError> { 555 rendering_info.set_extent_layers()?; 556 self.validate_begin_rendering(&mut rendering_info)?; 557 558 unsafe { 559 let RenderingInfo { 560 render_area_offset, 561 render_area_extent, 562 layer_count: _, 563 view_mask, 564 ref color_attachments, 565 ref depth_attachment, 566 ref stencil_attachment, 567 contents, 568 _ne: _, 569 } = rendering_info; 570 571 let render_pass_state = RenderPassState { 572 contents, 573 render_area_offset, 574 render_area_extent, 575 render_pass: BeginRenderingState { 576 attachments: Some(BeginRenderingAttachments { 577 color_attachments: color_attachments.clone(), 578 depth_attachment: depth_attachment.clone(), 579 stencil_attachment: stencil_attachment.clone(), 580 }), 581 color_attachment_formats: color_attachments 582 .iter() 583 .map(|a| a.as_ref().map(|a| a.image_view.format().unwrap())) 584 .collect(), 585 depth_attachment_format: depth_attachment 586 .as_ref() 587 .map(|a| a.image_view.format().unwrap()), 588 stencil_attachment_format: stencil_attachment 589 .as_ref() 590 .map(|a| a.image_view.format().unwrap()), 591 pipeline_used: false, 592 } 593 .into(), 594 view_mask, 595 }; 596 597 self.inner.begin_rendering(rendering_info)?; 598 599 self.render_pass_state = Some(render_pass_state); 600 } 601 602 Ok(self) 603 } 604 validate_begin_rendering( &self, rendering_info: &mut RenderingInfo, ) -> Result<(), RenderPassError>605 fn validate_begin_rendering( 606 &self, 607 rendering_info: &mut RenderingInfo, 608 ) -> Result<(), RenderPassError> { 609 let device = self.device(); 610 let properties = device.physical_device().properties(); 611 612 // VUID-vkCmdBeginRendering-dynamicRendering-06446 613 if !device.enabled_features().dynamic_rendering { 614 return Err(RenderPassError::RequirementNotMet { 615 required_for: "`AutoCommandBufferBuilder::begin_rendering`", 616 requires_one_of: RequiresOneOf { 617 features: &["dynamic_rendering"], 618 ..Default::default() 619 }, 620 }); 621 } 622 623 let queue_family_properties = self.queue_family_properties(); 624 625 // VUID-vkCmdBeginRendering-commandBuffer-cmdpool 626 if !queue_family_properties 627 .queue_flags 628 .intersects(QueueFlags::GRAPHICS) 629 { 630 return Err(RenderPassError::NotSupportedByQueueFamily); 631 } 632 633 // VUID-vkCmdBeginRendering-renderpass 634 if self.render_pass_state.is_some() { 635 return Err(RenderPassError::ForbiddenInsideRenderPass); 636 } 637 638 let &mut RenderingInfo { 639 render_area_offset, 640 render_area_extent, 641 layer_count, 642 view_mask, 643 ref color_attachments, 644 ref depth_attachment, 645 ref stencil_attachment, 646 contents, 647 _ne: _, 648 } = rendering_info; 649 650 // VUID-VkRenderingInfo-flags-parameter 651 contents.validate_device(device)?; 652 653 // VUID-vkCmdBeginRendering-commandBuffer-06068 654 if self.inheritance_info.is_some() && contents == SubpassContents::SecondaryCommandBuffers { 655 return Err(RenderPassError::ContentsForbiddenInSecondaryCommandBuffer); 656 } 657 658 // No VUID, but for sanity it makes sense to treat this the same as in framebuffers. 659 if view_mask != 0 && layer_count != 1 { 660 return Err(RenderPassError::MultiviewLayersInvalid); 661 } 662 663 // VUID-VkRenderingInfo-multiview-06127 664 if view_mask != 0 && !device.enabled_features().multiview { 665 return Err(RenderPassError::RequirementNotMet { 666 required_for: "`rendering_info.viewmask` is not `0`", 667 requires_one_of: RequiresOneOf { 668 features: &["multiview"], 669 ..Default::default() 670 }, 671 }); 672 } 673 674 let view_count = u32::BITS - view_mask.leading_zeros(); 675 676 // VUID-VkRenderingInfo-viewMask-06128 677 if view_count > properties.max_multiview_view_count.unwrap_or(0) { 678 return Err(RenderPassError::MaxMultiviewViewCountExceeded { 679 view_count, 680 max: properties.max_multiview_view_count.unwrap_or(0), 681 }); 682 } 683 684 let mut samples = None; 685 686 // VUID-VkRenderingInfo-colorAttachmentCount-06106 687 if color_attachments.len() > properties.max_color_attachments as usize { 688 return Err(RenderPassError::MaxColorAttachmentsExceeded { 689 color_attachment_count: color_attachments.len() as u32, 690 max: properties.max_color_attachments, 691 }); 692 } 693 694 for (attachment_index, attachment_info) in 695 color_attachments 696 .iter() 697 .enumerate() 698 .filter_map(|(index, attachment_info)| { 699 attachment_info 700 .as_ref() 701 .map(|attachment_info| (index, attachment_info)) 702 }) 703 { 704 let attachment_index = attachment_index as u32; 705 let RenderingAttachmentInfo { 706 image_view, 707 image_layout, 708 resolve_info, 709 load_op, 710 store_op, 711 clear_value: _, 712 _ne: _, 713 } = attachment_info; 714 715 // VUID-VkRenderingAttachmentInfo-imageLayout-parameter 716 image_layout.validate_device(device)?; 717 718 // VUID-VkRenderingAttachmentInfo-loadOp-parameter 719 load_op.validate_device(device)?; 720 721 // VUID-VkRenderingAttachmentInfo-storeOp-parameter 722 store_op.validate_device(device)?; 723 724 // VUID-VkRenderingInfo-colorAttachmentCount-06087 725 if !image_view.usage().intersects(ImageUsage::COLOR_ATTACHMENT) { 726 return Err(RenderPassError::ColorAttachmentMissingUsage { attachment_index }); 727 } 728 729 let image = image_view.image(); 730 let image_extent = image.dimensions().width_height_depth(); 731 732 for i in 0..2 { 733 // VUID-VkRenderingInfo-pNext-06079 734 // VUID-VkRenderingInfo-pNext-06080 735 if render_area_offset[i] + render_area_extent[i] > image_extent[i] { 736 return Err(RenderPassError::RenderAreaOutOfBounds); 737 } 738 } 739 740 // VUID-VkRenderingInfo-imageView-06070 741 match samples { 742 Some(samples) if samples == image.samples() => (), 743 Some(_) => { 744 return Err(RenderPassError::ColorAttachmentSamplesMismatch { 745 attachment_index, 746 }); 747 } 748 None => samples = Some(image.samples()), 749 } 750 751 // VUID-VkRenderingAttachmentInfo-imageView-06135 752 // VUID-VkRenderingAttachmentInfo-imageView-06145 753 // VUID-VkRenderingInfo-colorAttachmentCount-06090 754 // VUID-VkRenderingInfo-colorAttachmentCount-06096 755 if matches!( 756 image_layout, 757 ImageLayout::Undefined 758 | ImageLayout::ShaderReadOnlyOptimal 759 | ImageLayout::TransferSrcOptimal 760 | ImageLayout::TransferDstOptimal 761 | ImageLayout::Preinitialized 762 | ImageLayout::PresentSrc 763 | ImageLayout::DepthStencilAttachmentOptimal 764 | ImageLayout::DepthStencilReadOnlyOptimal 765 | ImageLayout::DepthReadOnlyStencilAttachmentOptimal 766 | ImageLayout::DepthAttachmentStencilReadOnlyOptimal 767 ) { 768 return Err(RenderPassError::ColorAttachmentLayoutInvalid { attachment_index }); 769 } 770 771 if let Some(resolve_info) = resolve_info { 772 let &RenderingAttachmentResolveInfo { 773 mode, 774 image_view: ref resolve_image_view, 775 image_layout: resolve_image_layout, 776 } = resolve_info; 777 778 // VUID-VkRenderingAttachmentInfo-resolveImageLayout-parameter 779 resolve_image_layout.validate_device(device)?; 780 781 // VUID-VkRenderingAttachmentInfo-resolveMode-parameter 782 mode.validate_device(device)?; 783 784 let resolve_image = resolve_image_view.image(); 785 786 match image_view.format().unwrap().type_color() { 787 Some( 788 NumericType::SFLOAT 789 | NumericType::UFLOAT 790 | NumericType::SNORM 791 | NumericType::UNORM 792 | NumericType::SSCALED 793 | NumericType::USCALED 794 | NumericType::SRGB, 795 ) => { 796 // VUID-VkRenderingAttachmentInfo-imageView-06129 797 if mode != ResolveMode::Average { 798 return Err(RenderPassError::ColorAttachmentResolveModeNotSupported { 799 attachment_index, 800 }); 801 } 802 } 803 Some(NumericType::SINT | NumericType::UINT) => { 804 // VUID-VkRenderingAttachmentInfo-imageView-06130 805 if mode != ResolveMode::SampleZero { 806 return Err(RenderPassError::ColorAttachmentResolveModeNotSupported { 807 attachment_index, 808 }); 809 } 810 } 811 None => (), 812 } 813 814 // VUID-VkRenderingAttachmentInfo-imageView-06132 815 if image.samples() == SampleCount::Sample1 { 816 return Err(RenderPassError::ColorAttachmentWithResolveNotMultisampled { 817 attachment_index, 818 }); 819 } 820 821 // VUID-VkRenderingAttachmentInfo-imageView-06133 822 if resolve_image.samples() != SampleCount::Sample1 { 823 return Err(RenderPassError::ColorAttachmentResolveMultisampled { 824 attachment_index, 825 }); 826 } 827 828 // VUID-VkRenderingAttachmentInfo-imageView-06134 829 if image_view.format() != resolve_image_view.format() { 830 return Err(RenderPassError::ColorAttachmentResolveFormatMismatch { 831 attachment_index, 832 }); 833 } 834 835 // VUID-VkRenderingAttachmentInfo-imageView-06136 836 // VUID-VkRenderingAttachmentInfo-imageView-06146 837 // VUID-VkRenderingInfo-colorAttachmentCount-06091 838 // VUID-VkRenderingInfo-colorAttachmentCount-06097 839 if matches!( 840 resolve_image_layout, 841 ImageLayout::Undefined 842 | ImageLayout::ShaderReadOnlyOptimal 843 | ImageLayout::TransferSrcOptimal 844 | ImageLayout::TransferDstOptimal 845 | ImageLayout::Preinitialized 846 | ImageLayout::PresentSrc 847 | ImageLayout::DepthStencilAttachmentOptimal 848 | ImageLayout::DepthStencilReadOnlyOptimal 849 | ImageLayout::DepthReadOnlyStencilAttachmentOptimal 850 | ImageLayout::DepthAttachmentStencilReadOnlyOptimal 851 ) { 852 return Err(RenderPassError::ColorAttachmentResolveLayoutInvalid { 853 attachment_index, 854 }); 855 } 856 } 857 } 858 859 if let Some(attachment_info) = depth_attachment { 860 let RenderingAttachmentInfo { 861 image_view, 862 image_layout, 863 resolve_info, 864 load_op, 865 store_op, 866 clear_value: _, 867 _ne: _, 868 } = attachment_info; 869 870 // VUID-VkRenderingAttachmentInfo-imageLayout-parameter 871 image_layout.validate_device(device)?; 872 873 // VUID-VkRenderingAttachmentInfo-loadOp-parameter 874 load_op.validate_device(device)?; 875 876 // VUID-VkRenderingAttachmentInfo-storeOp-parameter 877 store_op.validate_device(device)?; 878 879 let image_aspects = image_view.format().unwrap().aspects(); 880 881 // VUID-VkRenderingInfo-pDepthAttachment-06547 882 if !image_aspects.intersects(ImageAspects::DEPTH) { 883 return Err(RenderPassError::DepthAttachmentFormatUsageNotSupported); 884 } 885 886 // VUID-VkRenderingInfo-pDepthAttachment-06088 887 if !image_view 888 .usage() 889 .intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT) 890 { 891 return Err(RenderPassError::DepthAttachmentMissingUsage); 892 } 893 894 let image = image_view.image(); 895 let image_extent = image.dimensions().width_height_depth(); 896 897 for i in 0..2 { 898 // VUID-VkRenderingInfo-pNext-06079 899 // VUID-VkRenderingInfo-pNext-06080 900 if render_area_offset[i] + render_area_extent[i] > image_extent[i] { 901 return Err(RenderPassError::RenderAreaOutOfBounds); 902 } 903 } 904 905 // VUID-VkRenderingInfo-imageView-06070 906 match samples { 907 Some(samples) if samples == image.samples() => (), 908 Some(_) => { 909 return Err(RenderPassError::DepthAttachmentSamplesMismatch); 910 } 911 None => samples = Some(image.samples()), 912 } 913 914 // VUID-VkRenderingAttachmentInfo-imageView-06135 915 // VUID-VkRenderingAttachmentInfo-imageView-06145 916 // VUID-VkRenderingInfo-pDepthAttachment-06092 917 if matches!( 918 image_layout, 919 ImageLayout::Undefined 920 | ImageLayout::ShaderReadOnlyOptimal 921 | ImageLayout::TransferSrcOptimal 922 | ImageLayout::TransferDstOptimal 923 | ImageLayout::Preinitialized 924 | ImageLayout::PresentSrc 925 | ImageLayout::ColorAttachmentOptimal 926 ) { 927 return Err(RenderPassError::DepthAttachmentLayoutInvalid); 928 } 929 930 if let Some(resolve_info) = resolve_info { 931 let &RenderingAttachmentResolveInfo { 932 mode, 933 image_view: ref resolve_image_view, 934 image_layout: resolve_image_layout, 935 } = resolve_info; 936 937 // VUID-VkRenderingAttachmentInfo-resolveImageLayout-parameter 938 resolve_image_layout.validate_device(device)?; 939 940 // VUID-VkRenderingAttachmentInfo-resolveMode-parameter 941 mode.validate_device(device)?; 942 943 // VUID-VkRenderingInfo-pDepthAttachment-06102 944 if !properties 945 .supported_depth_resolve_modes 946 .map_or(false, |modes| modes.contains_enum(mode)) 947 { 948 return Err(RenderPassError::DepthAttachmentResolveModeNotSupported); 949 } 950 951 let resolve_image = resolve_image_view.image(); 952 953 // VUID-VkRenderingAttachmentInfo-imageView-06132 954 if image.samples() == SampleCount::Sample1 { 955 return Err(RenderPassError::DepthAttachmentWithResolveNotMultisampled); 956 } 957 958 // VUID-VkRenderingAttachmentInfo-imageView-06133 959 if resolve_image.samples() != SampleCount::Sample1 { 960 return Err(RenderPassError::DepthAttachmentResolveMultisampled); 961 } 962 963 // VUID-VkRenderingAttachmentInfo-imageView-06134 964 if image_view.format() != resolve_image_view.format() { 965 return Err(RenderPassError::DepthAttachmentResolveFormatMismatch); 966 } 967 968 // VUID-VkRenderingAttachmentInfo-imageView-06136 969 // VUID-VkRenderingAttachmentInfo-imageView-06146 970 // VUID-VkRenderingInfo-pDepthAttachment-06093 971 // VUID-VkRenderingInfo-pDepthAttachment-06098 972 if matches!( 973 resolve_image_layout, 974 ImageLayout::Undefined 975 | ImageLayout::DepthStencilReadOnlyOptimal 976 | ImageLayout::ShaderReadOnlyOptimal 977 | ImageLayout::TransferSrcOptimal 978 | ImageLayout::TransferDstOptimal 979 | ImageLayout::Preinitialized 980 | ImageLayout::PresentSrc 981 | ImageLayout::ColorAttachmentOptimal 982 | ImageLayout::DepthReadOnlyStencilAttachmentOptimal 983 ) { 984 return Err(RenderPassError::DepthAttachmentResolveLayoutInvalid); 985 } 986 } 987 } 988 989 if let Some(attachment_info) = stencil_attachment { 990 let RenderingAttachmentInfo { 991 image_view, 992 image_layout, 993 resolve_info, 994 load_op, 995 store_op, 996 clear_value: _, 997 _ne: _, 998 } = attachment_info; 999 1000 // VUID-VkRenderingAttachmentInfo-imageLayout-parameter 1001 image_layout.validate_device(device)?; 1002 1003 // VUID-VkRenderingAttachmentInfo-loadOp-parameter 1004 load_op.validate_device(device)?; 1005 1006 // VUID-VkRenderingAttachmentInfo-storeOp-parameter 1007 store_op.validate_device(device)?; 1008 1009 let image_aspects = image_view.format().unwrap().aspects(); 1010 1011 // VUID-VkRenderingInfo-pStencilAttachment-06548 1012 if !image_aspects.intersects(ImageAspects::STENCIL) { 1013 return Err(RenderPassError::StencilAttachmentFormatUsageNotSupported); 1014 } 1015 1016 // VUID-VkRenderingInfo-pStencilAttachment-06089 1017 if !image_view 1018 .usage() 1019 .intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT) 1020 { 1021 return Err(RenderPassError::StencilAttachmentMissingUsage); 1022 } 1023 1024 let image = image_view.image(); 1025 let image_extent = image.dimensions().width_height_depth(); 1026 1027 for i in 0..2 { 1028 // VUID-VkRenderingInfo-pNext-06079 1029 // VUID-VkRenderingInfo-pNext-06080 1030 if render_area_offset[i] + render_area_extent[i] > image_extent[i] { 1031 return Err(RenderPassError::RenderAreaOutOfBounds); 1032 } 1033 } 1034 1035 // VUID-VkRenderingInfo-imageView-06070 1036 match samples { 1037 Some(samples) if samples == image.samples() => (), 1038 Some(_) => { 1039 return Err(RenderPassError::StencilAttachmentSamplesMismatch); 1040 } 1041 None => (), 1042 } 1043 1044 // VUID-VkRenderingAttachmentInfo-imageView-06135 1045 // VUID-VkRenderingAttachmentInfo-imageView-06145 1046 // VUID-VkRenderingInfo-pStencilAttachment-06094 1047 if matches!( 1048 image_layout, 1049 ImageLayout::Undefined 1050 | ImageLayout::ShaderReadOnlyOptimal 1051 | ImageLayout::TransferSrcOptimal 1052 | ImageLayout::TransferDstOptimal 1053 | ImageLayout::Preinitialized 1054 | ImageLayout::PresentSrc 1055 | ImageLayout::ColorAttachmentOptimal 1056 ) { 1057 return Err(RenderPassError::StencilAttachmentLayoutInvalid); 1058 } 1059 1060 if let Some(resolve_info) = resolve_info { 1061 let &RenderingAttachmentResolveInfo { 1062 mode, 1063 image_view: ref resolve_image_view, 1064 image_layout: resolve_image_layout, 1065 } = resolve_info; 1066 1067 // VUID-VkRenderingAttachmentInfo-resolveImageLayout-parameter 1068 resolve_image_layout.validate_device(device)?; 1069 1070 // VUID-VkRenderingAttachmentInfo-resolveMode-parameter 1071 mode.validate_device(device)?; 1072 1073 // VUID-VkRenderingInfo-pStencilAttachment-06103 1074 if !properties 1075 .supported_stencil_resolve_modes 1076 .map_or(false, |modes| modes.contains_enum(mode)) 1077 { 1078 return Err(RenderPassError::StencilAttachmentResolveModeNotSupported); 1079 } 1080 1081 let resolve_image = resolve_image_view.image(); 1082 1083 // VUID-VkRenderingAttachmentInfo-imageView-06132 1084 if image.samples() == SampleCount::Sample1 { 1085 return Err(RenderPassError::StencilAttachmentWithResolveNotMultisampled); 1086 } 1087 1088 // VUID-VkRenderingAttachmentInfo-imageView-06133 1089 if resolve_image.samples() != SampleCount::Sample1 { 1090 return Err(RenderPassError::StencilAttachmentResolveMultisampled); 1091 } 1092 1093 // VUID-VkRenderingAttachmentInfo-imageView-06134 1094 if image_view.format() != resolve_image_view.format() { 1095 return Err(RenderPassError::StencilAttachmentResolveFormatMismatch); 1096 } 1097 1098 // VUID-VkRenderingAttachmentInfo-imageView-06136 1099 // VUID-VkRenderingAttachmentInfo-imageView-06146 1100 // VUID-VkRenderingInfo-pStencilAttachment-06095 1101 // VUID-VkRenderingInfo-pStencilAttachment-06099 1102 if matches!( 1103 resolve_image_layout, 1104 ImageLayout::Undefined 1105 | ImageLayout::DepthStencilReadOnlyOptimal 1106 | ImageLayout::ShaderReadOnlyOptimal 1107 | ImageLayout::TransferSrcOptimal 1108 | ImageLayout::TransferDstOptimal 1109 | ImageLayout::Preinitialized 1110 | ImageLayout::PresentSrc 1111 | ImageLayout::ColorAttachmentOptimal 1112 | ImageLayout::DepthAttachmentStencilReadOnlyOptimal 1113 ) { 1114 return Err(RenderPassError::StencilAttachmentResolveLayoutInvalid); 1115 } 1116 } 1117 } 1118 1119 if let (Some(depth_attachment_info), Some(stencil_attachment_info)) = 1120 (depth_attachment, stencil_attachment) 1121 { 1122 // VUID-VkRenderingInfo-pDepthAttachment-06085 1123 if &depth_attachment_info.image_view != &stencil_attachment_info.image_view { 1124 return Err(RenderPassError::DepthStencilAttachmentImageViewMismatch); 1125 } 1126 1127 match ( 1128 &depth_attachment_info.resolve_info, 1129 &stencil_attachment_info.resolve_info, 1130 ) { 1131 (None, None) => (), 1132 (None, Some(_)) | (Some(_), None) => { 1133 // VUID-VkRenderingInfo-pDepthAttachment-06104 1134 if !properties.independent_resolve_none.unwrap_or(false) { 1135 return Err( 1136 RenderPassError::DepthStencilAttachmentResolveModesNotSupported, 1137 ); 1138 } 1139 } 1140 (Some(depth_resolve_info), Some(stencil_resolve_info)) => { 1141 // VUID-VkRenderingInfo-pDepthAttachment-06105 1142 if !properties.independent_resolve.unwrap_or(false) 1143 && depth_resolve_info.mode != stencil_resolve_info.mode 1144 { 1145 return Err( 1146 RenderPassError::DepthStencilAttachmentResolveModesNotSupported, 1147 ); 1148 } 1149 1150 // VUID-VkRenderingInfo-pDepthAttachment-06086 1151 if &depth_resolve_info.image_view != &stencil_resolve_info.image_view { 1152 return Err( 1153 RenderPassError::DepthStencilAttachmentResolveImageViewMismatch, 1154 ); 1155 } 1156 } 1157 } 1158 } 1159 1160 Ok(()) 1161 } 1162 1163 /// Ends the render pass previously begun with `begin_rendering`. end_rendering(&mut self) -> Result<&mut Self, RenderPassError>1164 pub fn end_rendering(&mut self) -> Result<&mut Self, RenderPassError> { 1165 self.validate_end_rendering()?; 1166 1167 unsafe { 1168 self.inner.end_rendering(); 1169 self.render_pass_state = None; 1170 } 1171 1172 Ok(self) 1173 } 1174 validate_end_rendering(&self) -> Result<(), RenderPassError>1175 fn validate_end_rendering(&self) -> Result<(), RenderPassError> { 1176 // VUID-vkCmdEndRendering-renderpass 1177 let render_pass_state = self 1178 .render_pass_state 1179 .as_ref() 1180 .ok_or(RenderPassError::ForbiddenOutsideRenderPass)?; 1181 1182 // VUID? 1183 if self.inheritance_info.is_some() { 1184 return Err(RenderPassError::ForbiddenWithInheritedRenderPass); 1185 } 1186 1187 // VUID-vkCmdEndRendering-None-06161 1188 // VUID-vkCmdEndRendering-commandBuffer-06162 1189 match &render_pass_state.render_pass { 1190 RenderPassStateType::BeginRenderPass(_) => { 1191 return Err(RenderPassError::ForbiddenWithBeginRenderPass) 1192 } 1193 RenderPassStateType::BeginRendering(_) => (), 1194 } 1195 1196 // VUID-vkCmdEndRendering-commandBuffer-cmdpool 1197 debug_assert!(self 1198 .queue_family_properties() 1199 .queue_flags 1200 .intersects(QueueFlags::GRAPHICS)); 1201 1202 Ok(()) 1203 } 1204 1205 /// Clears specific regions of specific attachments of the framebuffer. 1206 /// 1207 /// `attachments` specify the types of attachments and their clear values. 1208 /// `rects` specify the regions to clear. 1209 /// 1210 /// A graphics pipeline must have been bound using 1211 /// [`bind_pipeline_graphics`](Self::bind_pipeline_graphics). And the command must be inside render pass. 1212 /// 1213 /// If the render pass instance this is recorded in uses multiview, 1214 /// then `ClearRect.base_array_layer` must be zero and `ClearRect.layer_count` must be one. 1215 /// 1216 /// The rectangle area must be inside the render area ranges. clear_attachments( &mut self, attachments: impl IntoIterator<Item = ClearAttachment>, rects: impl IntoIterator<Item = ClearRect>, ) -> Result<&mut Self, RenderPassError>1217 pub fn clear_attachments( 1218 &mut self, 1219 attachments: impl IntoIterator<Item = ClearAttachment>, 1220 rects: impl IntoIterator<Item = ClearRect>, 1221 ) -> Result<&mut Self, RenderPassError> { 1222 let attachments: SmallVec<[ClearAttachment; 3]> = attachments.into_iter().collect(); 1223 let rects: SmallVec<[ClearRect; 4]> = rects.into_iter().collect(); 1224 1225 self.validate_clear_attachments(&attachments, &rects)?; 1226 1227 unsafe { 1228 self.inner.clear_attachments(attachments, rects); 1229 } 1230 1231 Ok(self) 1232 } 1233 validate_clear_attachments( &self, attachments: &[ClearAttachment], rects: &[ClearRect], ) -> Result<(), RenderPassError>1234 fn validate_clear_attachments( 1235 &self, 1236 attachments: &[ClearAttachment], 1237 rects: &[ClearRect], 1238 ) -> Result<(), RenderPassError> { 1239 // VUID-vkCmdClearAttachments-renderpass 1240 let render_pass_state = self 1241 .render_pass_state 1242 .as_ref() 1243 .ok_or(RenderPassError::ForbiddenOutsideRenderPass)?; 1244 1245 if render_pass_state.contents != SubpassContents::Inline { 1246 return Err(RenderPassError::ForbiddenWithSubpassContents { 1247 contents: render_pass_state.contents, 1248 }); 1249 } 1250 1251 //let subpass_desc = begin_render_pass_state.subpass.subpass_desc(); 1252 //let render_pass = begin_render_pass_state.subpass.render_pass(); 1253 let is_multiview = render_pass_state.view_mask != 0; 1254 let mut layer_count = u32::MAX; 1255 1256 for &clear_attachment in attachments { 1257 match clear_attachment { 1258 ClearAttachment::Color { 1259 color_attachment, 1260 clear_value, 1261 } => { 1262 let attachment_format = match &render_pass_state.render_pass { 1263 RenderPassStateType::BeginRenderPass(state) => { 1264 let color_attachments = &state.subpass.subpass_desc().color_attachments; 1265 let atch_ref = color_attachments.get(color_attachment as usize).ok_or( 1266 RenderPassError::ColorAttachmentIndexOutOfRange { 1267 color_attachment_index: color_attachment, 1268 num_color_attachments: color_attachments.len() as u32, 1269 }, 1270 )?; 1271 1272 atch_ref.as_ref().map(|atch_ref| { 1273 state.subpass.render_pass().attachments() 1274 [atch_ref.attachment as usize] 1275 .format 1276 .unwrap() 1277 }) 1278 } 1279 RenderPassStateType::BeginRendering(state) => *state 1280 .color_attachment_formats 1281 .get(color_attachment as usize) 1282 .ok_or(RenderPassError::ColorAttachmentIndexOutOfRange { 1283 color_attachment_index: color_attachment, 1284 num_color_attachments: state.color_attachment_formats.len() as u32, 1285 })?, 1286 }; 1287 1288 // VUID-vkCmdClearAttachments-aspectMask-02501 1289 if !attachment_format.map_or(false, |format| { 1290 matches!( 1291 (clear_value, format.type_color().unwrap()), 1292 ( 1293 ClearColorValue::Float(_), 1294 NumericType::SFLOAT 1295 | NumericType::UFLOAT 1296 | NumericType::SNORM 1297 | NumericType::UNORM 1298 | NumericType::SSCALED 1299 | NumericType::USCALED 1300 | NumericType::SRGB 1301 ) | (ClearColorValue::Int(_), NumericType::SINT) 1302 | (ClearColorValue::Uint(_), NumericType::UINT) 1303 ) 1304 }) { 1305 return Err(RenderPassError::ClearAttachmentNotCompatible { 1306 clear_attachment, 1307 attachment_format, 1308 }); 1309 } 1310 1311 let image_view = match &render_pass_state.render_pass { 1312 RenderPassStateType::BeginRenderPass(state) => (state.framebuffer.as_ref()) 1313 .zip( 1314 state.subpass.subpass_desc().color_attachments 1315 [color_attachment as usize] 1316 .as_ref(), 1317 ) 1318 .map(|(framebuffer, atch_ref)| { 1319 &framebuffer.attachments()[atch_ref.attachment as usize] 1320 }), 1321 RenderPassStateType::BeginRendering(state) => state 1322 .attachments 1323 .as_ref() 1324 .and_then(|attachments| { 1325 attachments.color_attachments[color_attachment as usize].as_ref() 1326 }) 1327 .map(|attachment_info| &attachment_info.image_view), 1328 }; 1329 1330 // We only know the layer count if we have a known attachment image. 1331 if let Some(image_view) = image_view { 1332 let array_layers = &image_view.subresource_range().array_layers; 1333 layer_count = min(layer_count, array_layers.end - array_layers.start); 1334 } 1335 } 1336 ClearAttachment::Depth(_) 1337 | ClearAttachment::Stencil(_) 1338 | ClearAttachment::DepthStencil(_) => { 1339 let (depth_format, stencil_format) = match &render_pass_state.render_pass { 1340 RenderPassStateType::BeginRenderPass(state) => state 1341 .subpass 1342 .subpass_desc() 1343 .depth_stencil_attachment 1344 .as_ref() 1345 .map_or((None, None), |atch_ref| { 1346 let format = state.subpass.render_pass().attachments() 1347 [atch_ref.attachment as usize] 1348 .format 1349 .unwrap(); 1350 (Some(format), Some(format)) 1351 }), 1352 RenderPassStateType::BeginRendering(state) => ( 1353 state.depth_attachment_format, 1354 state.stencil_attachment_format, 1355 ), 1356 }; 1357 1358 // VUID-vkCmdClearAttachments-aspectMask-02502 1359 if matches!( 1360 clear_attachment, 1361 ClearAttachment::Depth(_) | ClearAttachment::DepthStencil(_) 1362 ) && !depth_format.map_or(false, |format| { 1363 format.aspects().intersects(ImageAspects::DEPTH) 1364 }) { 1365 return Err(RenderPassError::ClearAttachmentNotCompatible { 1366 clear_attachment, 1367 attachment_format: None, 1368 }); 1369 } 1370 1371 // VUID-vkCmdClearAttachments-aspectMask-02503 1372 if matches!( 1373 clear_attachment, 1374 ClearAttachment::Stencil(_) | ClearAttachment::DepthStencil(_) 1375 ) && !stencil_format.map_or(false, |format| { 1376 format.aspects().intersects(ImageAspects::STENCIL) 1377 }) { 1378 return Err(RenderPassError::ClearAttachmentNotCompatible { 1379 clear_attachment, 1380 attachment_format: None, 1381 }); 1382 } 1383 1384 let image_view = match &render_pass_state.render_pass { 1385 RenderPassStateType::BeginRenderPass(state) => (state.framebuffer.as_ref()) 1386 .zip( 1387 state 1388 .subpass 1389 .subpass_desc() 1390 .depth_stencil_attachment 1391 .as_ref(), 1392 ) 1393 .map(|(framebuffer, atch_ref)| { 1394 &framebuffer.attachments()[atch_ref.attachment as usize] 1395 }), 1396 RenderPassStateType::BeginRendering(state) => state 1397 .attachments 1398 .as_ref() 1399 .and_then(|attachments| attachments.depth_attachment.as_ref()) 1400 .map(|attachment_info| &attachment_info.image_view), 1401 }; 1402 1403 // We only know the layer count if we have a known attachment image. 1404 if let Some(image_view) = image_view { 1405 let array_layers = &image_view.subresource_range().array_layers; 1406 layer_count = min(layer_count, array_layers.end - array_layers.start); 1407 } 1408 } 1409 } 1410 } 1411 1412 for (rect_index, rect) in rects.iter().enumerate() { 1413 for i in 0..2 { 1414 // VUID-vkCmdClearAttachments-rect-02682 1415 // VUID-vkCmdClearAttachments-rect-02683 1416 if rect.extent[i] == 0 { 1417 return Err(RenderPassError::RectExtentZero { rect_index }); 1418 } 1419 1420 // VUID-vkCmdClearAttachments-pRects-00016 1421 // TODO: This check will always pass in secondary command buffers because of how 1422 // it's set in `with_level`. 1423 // It needs to be checked during `execute_commands` instead. 1424 if rect.offset[i] < render_pass_state.render_area_offset[i] 1425 || rect.offset[i] + rect.extent[i] 1426 > render_pass_state.render_area_offset[i] 1427 + render_pass_state.render_area_extent[i] 1428 { 1429 return Err(RenderPassError::RectOutOfBounds { rect_index }); 1430 } 1431 } 1432 1433 // VUID-vkCmdClearAttachments-layerCount-01934 1434 if rect.array_layers.is_empty() { 1435 return Err(RenderPassError::RectArrayLayersEmpty { rect_index }); 1436 } 1437 1438 // VUID-vkCmdClearAttachments-pRects-00017 1439 if rect.array_layers.end > layer_count { 1440 return Err(RenderPassError::RectArrayLayersOutOfBounds { rect_index }); 1441 } 1442 1443 // VUID-vkCmdClearAttachments-baseArrayLayer-00018 1444 if is_multiview && rect.array_layers != (0..1) { 1445 return Err(RenderPassError::MultiviewRectArrayLayersInvalid { rect_index }); 1446 } 1447 } 1448 1449 // VUID-vkCmdClearAttachments-commandBuffer-cmdpool 1450 debug_assert!(self 1451 .queue_family_properties() 1452 .queue_flags 1453 .intersects(QueueFlags::GRAPHICS)); 1454 1455 Ok(()) 1456 } 1457 } 1458 1459 impl SyncCommandBufferBuilder { 1460 /// Calls `vkCmdBeginRenderPass` on the builder. 1461 // TODO: it shouldn't be possible to get an error if the framebuffer checked conflicts already 1462 // TODO: after begin_render_pass has been called, flushing should be forbidden and an error 1463 // returned if conflict 1464 #[inline] begin_render_pass( &mut self, render_pass_begin_info: RenderPassBeginInfo, contents: SubpassContents, ) -> Result<(), SyncCommandBufferBuilderError>1465 pub unsafe fn begin_render_pass( 1466 &mut self, 1467 render_pass_begin_info: RenderPassBeginInfo, 1468 contents: SubpassContents, 1469 ) -> Result<(), SyncCommandBufferBuilderError> { 1470 struct Cmd { 1471 render_pass_begin_info: RenderPassBeginInfo, 1472 contents: SubpassContents, 1473 } 1474 1475 impl Command for Cmd { 1476 fn name(&self) -> &'static str { 1477 "begin_render_pass" 1478 } 1479 1480 unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { 1481 out.begin_render_pass(&self.render_pass_begin_info, self.contents); 1482 } 1483 } 1484 1485 let RenderPassBeginInfo { 1486 render_pass, 1487 framebuffer, 1488 render_area_offset: _, 1489 render_area_extent: _, 1490 clear_values: _, 1491 _ne: _, 1492 } = &render_pass_begin_info; 1493 1494 let command_index = self.commands.len(); 1495 let command_name = "begin_render_pass"; 1496 let resources = render_pass 1497 .attachments() 1498 .iter() 1499 .enumerate() 1500 .map(|(index, desc)| { 1501 let image_view = &framebuffer.attachments()[index]; 1502 let index = index as u32; 1503 1504 ( 1505 ResourceUseRef { 1506 command_index, 1507 command_name, 1508 resource_in_command: ResourceInCommand::FramebufferAttachment { index }, 1509 secondary_use_ref: None, 1510 }, 1511 Resource::Image { 1512 image: image_view.image(), 1513 subresource_range: image_view.subresource_range().clone(), 1514 memory: PipelineMemoryAccess { 1515 stages: PipelineStages::ALL_COMMANDS, // TODO: wrong! 1516 access: AccessFlags::INPUT_ATTACHMENT_READ 1517 | AccessFlags::COLOR_ATTACHMENT_READ 1518 | AccessFlags::COLOR_ATTACHMENT_WRITE 1519 | AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ 1520 | AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE, // TODO: suboptimal 1521 exclusive: true, // TODO: suboptimal ; note: remember to always pass true if desc.initial_layout != desc.final_layout 1522 }, 1523 start_layout: desc.initial_layout, 1524 end_layout: desc.final_layout, 1525 }, 1526 ) 1527 }) 1528 .collect::<Vec<_>>(); 1529 1530 for resource in &resources { 1531 self.check_resource_conflicts(resource)?; 1532 } 1533 1534 self.commands.push(Box::new(Cmd { 1535 render_pass_begin_info, 1536 contents, 1537 })); 1538 1539 for resource in resources { 1540 self.add_resource(resource); 1541 } 1542 1543 self.latest_render_pass_enter = Some(self.commands.len() - 1); 1544 1545 Ok(()) 1546 } 1547 1548 /// Calls `vkCmdNextSubpass` on the builder. 1549 #[inline] next_subpass(&mut self, contents: SubpassContents)1550 pub unsafe fn next_subpass(&mut self, contents: SubpassContents) { 1551 struct Cmd { 1552 contents: SubpassContents, 1553 } 1554 1555 impl Command for Cmd { 1556 fn name(&self) -> &'static str { 1557 "next_subpass" 1558 } 1559 1560 unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { 1561 out.next_subpass(self.contents); 1562 } 1563 } 1564 1565 self.commands.push(Box::new(Cmd { contents })); 1566 } 1567 1568 /// Calls `vkCmdEndRenderPass` on the builder. 1569 #[inline] end_render_pass(&mut self)1570 pub unsafe fn end_render_pass(&mut self) { 1571 struct Cmd; 1572 1573 impl Command for Cmd { 1574 fn name(&self) -> &'static str { 1575 "end_render_pass" 1576 } 1577 1578 unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { 1579 out.end_render_pass(); 1580 } 1581 } 1582 1583 self.commands.push(Box::new(Cmd)); 1584 debug_assert!(self.latest_render_pass_enter.is_some()); 1585 self.latest_render_pass_enter = None; 1586 } 1587 1588 /// Calls `vkCmdBeginRendering` on the builder. 1589 #[inline] begin_rendering( &mut self, rendering_info: RenderingInfo, ) -> Result<(), SyncCommandBufferBuilderError>1590 pub unsafe fn begin_rendering( 1591 &mut self, 1592 rendering_info: RenderingInfo, 1593 ) -> Result<(), SyncCommandBufferBuilderError> { 1594 struct Cmd { 1595 rendering_info: RenderingInfo, 1596 } 1597 1598 impl Command for Cmd { 1599 fn name(&self) -> &'static str { 1600 "begin_rendering" 1601 } 1602 1603 unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { 1604 out.begin_rendering(&self.rendering_info); 1605 } 1606 } 1607 1608 let RenderingInfo { 1609 render_area_offset: _, 1610 render_area_extent: _, 1611 layer_count: _, 1612 view_mask: _, 1613 color_attachments, 1614 depth_attachment, 1615 stencil_attachment, 1616 contents: _, 1617 _ne, 1618 } = &rendering_info; 1619 1620 let command_index = self.commands.len(); 1621 let command_name = "begin_rendering"; 1622 let resources = (color_attachments 1623 .iter() 1624 .enumerate() 1625 .filter_map(|(index, attachment_info)| { 1626 attachment_info 1627 .as_ref() 1628 .map(|attachment_info| (index as u32, attachment_info)) 1629 }) 1630 .flat_map(|(index, attachment_info)| { 1631 let &RenderingAttachmentInfo { 1632 ref image_view, 1633 image_layout, 1634 ref resolve_info, 1635 load_op: _, 1636 store_op: _, 1637 clear_value: _, 1638 _ne: _, 1639 } = attachment_info; 1640 1641 [ 1642 Some(( 1643 ResourceUseRef { 1644 command_index, 1645 command_name, 1646 resource_in_command: ResourceInCommand::ColorAttachment { index }, 1647 secondary_use_ref: None, 1648 }, 1649 Resource::Image { 1650 image: image_view.image(), 1651 subresource_range: image_view.subresource_range().clone(), 1652 memory: PipelineMemoryAccess { 1653 stages: PipelineStages::ALL_COMMANDS, // TODO: wrong! 1654 access: AccessFlags::COLOR_ATTACHMENT_READ 1655 | AccessFlags::COLOR_ATTACHMENT_WRITE, // TODO: suboptimal 1656 exclusive: true, // TODO: suboptimal 1657 }, 1658 start_layout: image_layout, 1659 end_layout: image_layout, 1660 }, 1661 )), 1662 resolve_info.as_ref().map(|resolve_info| { 1663 let &RenderingAttachmentResolveInfo { 1664 mode: _, 1665 ref image_view, 1666 image_layout, 1667 } = resolve_info; 1668 1669 ( 1670 ResourceUseRef { 1671 command_index, 1672 command_name, 1673 resource_in_command: ResourceInCommand::ColorResolveAttachment { 1674 index, 1675 }, 1676 secondary_use_ref: None, 1677 }, 1678 Resource::Image { 1679 image: image_view.image(), 1680 subresource_range: image_view.subresource_range().clone(), 1681 memory: PipelineMemoryAccess { 1682 stages: PipelineStages::ALL_COMMANDS, // TODO: wrong! 1683 access: AccessFlags::COLOR_ATTACHMENT_READ 1684 | AccessFlags::COLOR_ATTACHMENT_WRITE, // TODO: suboptimal 1685 exclusive: true, // TODO: suboptimal 1686 }, 1687 start_layout: image_layout, 1688 end_layout: image_layout, 1689 }, 1690 ) 1691 }), 1692 ] 1693 .into_iter() 1694 .flatten() 1695 })) 1696 .chain(depth_attachment.iter().flat_map(|attachment_info| { 1697 let &RenderingAttachmentInfo { 1698 ref image_view, 1699 image_layout, 1700 ref resolve_info, 1701 load_op: _, 1702 store_op: _, 1703 clear_value: _, 1704 _ne: _, 1705 } = attachment_info; 1706 1707 [ 1708 Some(( 1709 ResourceUseRef { 1710 command_index, 1711 command_name, 1712 resource_in_command: ResourceInCommand::DepthStencilAttachment, 1713 secondary_use_ref: None, 1714 }, 1715 Resource::Image { 1716 image: image_view.image(), 1717 subresource_range: image_view.subresource_range().clone(), 1718 memory: PipelineMemoryAccess { 1719 stages: PipelineStages::ALL_COMMANDS, // TODO: wrong! 1720 access: AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ 1721 | AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE, // TODO: suboptimal 1722 exclusive: true, // TODO: suboptimal 1723 }, 1724 start_layout: image_layout, 1725 end_layout: image_layout, 1726 }, 1727 )), 1728 resolve_info.as_ref().map(|resolve_info| { 1729 let &RenderingAttachmentResolveInfo { 1730 mode: _, 1731 ref image_view, 1732 image_layout, 1733 } = resolve_info; 1734 1735 ( 1736 ResourceUseRef { 1737 command_index, 1738 command_name, 1739 resource_in_command: ResourceInCommand::DepthStencilResolveAttachment, 1740 secondary_use_ref: None, 1741 }, 1742 Resource::Image { 1743 image: image_view.image(), 1744 subresource_range: image_view.subresource_range().clone(), 1745 memory: PipelineMemoryAccess { 1746 stages: PipelineStages::ALL_COMMANDS, // TODO: wrong! 1747 access: AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ 1748 | AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE, // TODO: suboptimal 1749 exclusive: true, // TODO: suboptimal 1750 }, 1751 start_layout: image_layout, 1752 end_layout: image_layout, 1753 }, 1754 ) 1755 }), 1756 ] 1757 .into_iter() 1758 .flatten() 1759 })) 1760 .chain(stencil_attachment.iter().flat_map(|attachment_info| { 1761 let &RenderingAttachmentInfo { 1762 ref image_view, 1763 image_layout, 1764 ref resolve_info, 1765 load_op: _, 1766 store_op: _, 1767 clear_value: _, 1768 _ne: _, 1769 } = attachment_info; 1770 1771 [ 1772 Some(( 1773 ResourceUseRef { 1774 command_index, 1775 command_name, 1776 resource_in_command: ResourceInCommand::DepthStencilAttachment, 1777 secondary_use_ref: None, 1778 }, 1779 Resource::Image { 1780 image: image_view.image(), 1781 subresource_range: image_view.subresource_range().clone(), 1782 memory: PipelineMemoryAccess { 1783 stages: PipelineStages::ALL_COMMANDS, // TODO: wrong! 1784 access: AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ 1785 | AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE, // TODO: suboptimal 1786 exclusive: true, // TODO: suboptimal 1787 }, 1788 start_layout: image_layout, 1789 end_layout: image_layout, 1790 }, 1791 )), 1792 resolve_info.as_ref().map(|resolve_info| { 1793 let &RenderingAttachmentResolveInfo { 1794 mode: _, 1795 ref image_view, 1796 image_layout, 1797 } = resolve_info; 1798 1799 ( 1800 ResourceUseRef { 1801 command_index, 1802 command_name, 1803 resource_in_command: ResourceInCommand::DepthStencilResolveAttachment, 1804 secondary_use_ref: None, 1805 }, 1806 Resource::Image { 1807 image: image_view.image(), 1808 subresource_range: image_view.subresource_range().clone(), 1809 memory: PipelineMemoryAccess { 1810 stages: PipelineStages::ALL_COMMANDS, // TODO: wrong! 1811 access: AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ 1812 | AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE, // TODO: suboptimal 1813 exclusive: true, // TODO: suboptimal 1814 }, 1815 start_layout: image_layout, 1816 end_layout: image_layout, 1817 }, 1818 ) 1819 }), 1820 ] 1821 .into_iter() 1822 .flatten() 1823 })) 1824 .collect::<Vec<_>>(); 1825 1826 for resource in &resources { 1827 self.check_resource_conflicts(resource)?; 1828 } 1829 1830 self.commands.push(Box::new(Cmd { rendering_info })); 1831 1832 for resource in resources { 1833 self.add_resource(resource); 1834 } 1835 1836 self.latest_render_pass_enter = Some(self.commands.len() - 1); 1837 1838 Ok(()) 1839 } 1840 1841 /// Calls `vkCmdEndRendering` on the builder. 1842 #[inline] end_rendering(&mut self)1843 pub unsafe fn end_rendering(&mut self) { 1844 struct Cmd; 1845 1846 impl Command for Cmd { 1847 fn name(&self) -> &'static str { 1848 "end_rendering" 1849 } 1850 1851 unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { 1852 out.end_rendering(); 1853 } 1854 } 1855 1856 self.commands.push(Box::new(Cmd)); 1857 debug_assert!(self.latest_render_pass_enter.is_some()); 1858 self.latest_render_pass_enter = None; 1859 } 1860 1861 /// Calls `vkCmdClearAttachments` on the builder. 1862 /// 1863 /// Does nothing if the list of attachments or the list of rects is empty, as it would be a 1864 /// no-op and isn't a valid usage of the command anyway. clear_attachments( &mut self, attachments: impl IntoIterator<Item = ClearAttachment>, rects: impl IntoIterator<Item = ClearRect>, )1865 pub unsafe fn clear_attachments( 1866 &mut self, 1867 attachments: impl IntoIterator<Item = ClearAttachment>, 1868 rects: impl IntoIterator<Item = ClearRect>, 1869 ) { 1870 struct Cmd { 1871 attachments: SmallVec<[ClearAttachment; 3]>, 1872 rects: SmallVec<[ClearRect; 4]>, 1873 } 1874 1875 impl Command for Cmd { 1876 fn name(&self) -> &'static str { 1877 "clear_attachments" 1878 } 1879 1880 unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { 1881 out.clear_attachments(self.attachments.iter().copied(), self.rects.iter().cloned()); 1882 } 1883 } 1884 let attachments: SmallVec<[_; 3]> = attachments.into_iter().collect(); 1885 let rects: SmallVec<[_; 4]> = rects.into_iter().collect(); 1886 1887 self.commands.push(Box::new(Cmd { attachments, rects })); 1888 } 1889 } 1890 1891 impl UnsafeCommandBufferBuilder { 1892 /// Calls `vkCmdBeginRenderPass` on the builder. 1893 #[inline] begin_render_pass( &mut self, render_pass_begin_info: &RenderPassBeginInfo, contents: SubpassContents, )1894 pub unsafe fn begin_render_pass( 1895 &mut self, 1896 render_pass_begin_info: &RenderPassBeginInfo, 1897 contents: SubpassContents, 1898 ) { 1899 let &RenderPassBeginInfo { 1900 ref render_pass, 1901 ref framebuffer, 1902 render_area_offset, 1903 render_area_extent, 1904 ref clear_values, 1905 _ne: _, 1906 } = render_pass_begin_info; 1907 1908 let clear_values_vk: SmallVec<[_; 4]> = clear_values 1909 .iter() 1910 .copied() 1911 .map(|clear_value| clear_value.map(Into::into).unwrap_or_default()) 1912 .collect(); 1913 1914 let render_pass_begin_info = ash::vk::RenderPassBeginInfo { 1915 render_pass: render_pass.handle(), 1916 framebuffer: framebuffer.handle(), 1917 render_area: ash::vk::Rect2D { 1918 offset: ash::vk::Offset2D { 1919 x: render_area_offset[0] as i32, 1920 y: render_area_offset[1] as i32, 1921 }, 1922 extent: ash::vk::Extent2D { 1923 width: render_area_extent[0], 1924 height: render_area_extent[1], 1925 }, 1926 }, 1927 clear_value_count: clear_values_vk.len() as u32, 1928 p_clear_values: clear_values_vk.as_ptr(), 1929 ..Default::default() 1930 }; 1931 1932 let subpass_begin_info = ash::vk::SubpassBeginInfo { 1933 contents: contents.into(), 1934 ..Default::default() 1935 }; 1936 1937 let fns = self.device.fns(); 1938 1939 if self.device.api_version() >= Version::V1_2 1940 || self.device.enabled_extensions().khr_create_renderpass2 1941 { 1942 if self.device.api_version() >= Version::V1_2 { 1943 (fns.v1_2.cmd_begin_render_pass2)( 1944 self.handle, 1945 &render_pass_begin_info, 1946 &subpass_begin_info, 1947 ); 1948 } else { 1949 (fns.khr_create_renderpass2.cmd_begin_render_pass2_khr)( 1950 self.handle, 1951 &render_pass_begin_info, 1952 &subpass_begin_info, 1953 ); 1954 } 1955 } else { 1956 debug_assert!(subpass_begin_info.p_next.is_null()); 1957 1958 (fns.v1_0.cmd_begin_render_pass)( 1959 self.handle, 1960 &render_pass_begin_info, 1961 subpass_begin_info.contents, 1962 ); 1963 } 1964 } 1965 1966 /// Calls `vkCmdNextSubpass` on the builder. 1967 #[inline] next_subpass(&mut self, contents: SubpassContents)1968 pub unsafe fn next_subpass(&mut self, contents: SubpassContents) { 1969 let fns = self.device.fns(); 1970 1971 let subpass_begin_info = ash::vk::SubpassBeginInfo { 1972 contents: contents.into(), 1973 ..Default::default() 1974 }; 1975 1976 let subpass_end_info = ash::vk::SubpassEndInfo::default(); 1977 1978 if self.device.api_version() >= Version::V1_2 1979 || self.device.enabled_extensions().khr_create_renderpass2 1980 { 1981 if self.device.api_version() >= Version::V1_2 { 1982 (fns.v1_2.cmd_next_subpass2)(self.handle, &subpass_begin_info, &subpass_end_info); 1983 } else { 1984 (fns.khr_create_renderpass2.cmd_next_subpass2_khr)( 1985 self.handle, 1986 &subpass_begin_info, 1987 &subpass_end_info, 1988 ); 1989 } 1990 } else { 1991 debug_assert!(subpass_begin_info.p_next.is_null()); 1992 debug_assert!(subpass_end_info.p_next.is_null()); 1993 1994 (fns.v1_0.cmd_next_subpass)(self.handle, subpass_begin_info.contents); 1995 } 1996 } 1997 1998 /// Calls `vkCmdEndRenderPass` on the builder. 1999 #[inline] end_render_pass(&mut self)2000 pub unsafe fn end_render_pass(&mut self) { 2001 let fns = self.device.fns(); 2002 2003 let subpass_end_info = ash::vk::SubpassEndInfo::default(); 2004 2005 if self.device.api_version() >= Version::V1_2 2006 || self.device.enabled_extensions().khr_create_renderpass2 2007 { 2008 if self.device.api_version() >= Version::V1_2 { 2009 (fns.v1_2.cmd_end_render_pass2)(self.handle, &subpass_end_info); 2010 } else { 2011 (fns.khr_create_renderpass2.cmd_end_render_pass2_khr)( 2012 self.handle, 2013 &subpass_end_info, 2014 ); 2015 } 2016 } else { 2017 debug_assert!(subpass_end_info.p_next.is_null()); 2018 2019 (fns.v1_0.cmd_end_render_pass)(self.handle); 2020 } 2021 } 2022 2023 /// Calls `vkCmdBeginRendering` on the builder. 2024 #[inline] begin_rendering(&mut self, rendering_info: &RenderingInfo)2025 pub unsafe fn begin_rendering(&mut self, rendering_info: &RenderingInfo) { 2026 let &RenderingInfo { 2027 render_area_offset, 2028 render_area_extent, 2029 layer_count, 2030 view_mask, 2031 ref color_attachments, 2032 ref depth_attachment, 2033 ref stencil_attachment, 2034 contents, 2035 _ne: _, 2036 } = rendering_info; 2037 2038 let map_attachment_info = |attachment_info: &Option<_>| { 2039 if let Some(attachment_info) = attachment_info { 2040 let &RenderingAttachmentInfo { 2041 ref image_view, 2042 image_layout, 2043 resolve_info: ref resolve, 2044 load_op, 2045 store_op, 2046 clear_value, 2047 _ne: _, 2048 } = attachment_info; 2049 2050 let (resolve_mode, resolve_image_view, resolve_image_layout) = 2051 if let Some(resolve) = resolve { 2052 let &RenderingAttachmentResolveInfo { 2053 mode, 2054 ref image_view, 2055 image_layout, 2056 } = resolve; 2057 2058 (mode.into(), image_view.handle(), image_layout.into()) 2059 } else { 2060 ( 2061 ash::vk::ResolveModeFlags::NONE, 2062 Default::default(), 2063 Default::default(), 2064 ) 2065 }; 2066 2067 ash::vk::RenderingAttachmentInfo { 2068 image_view: image_view.handle(), 2069 image_layout: image_layout.into(), 2070 resolve_mode, 2071 resolve_image_view, 2072 resolve_image_layout, 2073 load_op: load_op.into(), 2074 store_op: store_op.into(), 2075 clear_value: clear_value.map_or_else(Default::default, Into::into), 2076 ..Default::default() 2077 } 2078 } else { 2079 ash::vk::RenderingAttachmentInfo { 2080 image_view: ash::vk::ImageView::null(), 2081 ..Default::default() 2082 } 2083 } 2084 }; 2085 2086 let color_attachments: SmallVec<[_; 2]> = 2087 color_attachments.iter().map(map_attachment_info).collect(); 2088 let depth_attachment = map_attachment_info(depth_attachment); 2089 let stencil_attachment = map_attachment_info(stencil_attachment); 2090 2091 let rendering_info = ash::vk::RenderingInfo { 2092 flags: contents.into(), 2093 render_area: ash::vk::Rect2D { 2094 offset: ash::vk::Offset2D { 2095 x: render_area_offset[0] as i32, 2096 y: render_area_offset[1] as i32, 2097 }, 2098 extent: ash::vk::Extent2D { 2099 width: render_area_extent[0], 2100 height: render_area_extent[1], 2101 }, 2102 }, 2103 layer_count, 2104 view_mask, 2105 color_attachment_count: color_attachments.len() as u32, 2106 p_color_attachments: color_attachments.as_ptr(), 2107 p_depth_attachment: &depth_attachment, 2108 p_stencil_attachment: &stencil_attachment, 2109 ..Default::default() 2110 }; 2111 2112 let fns = self.device.fns(); 2113 2114 if self.device.api_version() >= Version::V1_3 { 2115 (fns.v1_3.cmd_begin_rendering)(self.handle, &rendering_info); 2116 } else { 2117 debug_assert!(self.device.enabled_extensions().khr_dynamic_rendering); 2118 (fns.khr_dynamic_rendering.cmd_begin_rendering_khr)(self.handle, &rendering_info); 2119 } 2120 } 2121 2122 /// Calls `vkCmdEndRendering` on the builder. 2123 #[inline] end_rendering(&mut self)2124 pub unsafe fn end_rendering(&mut self) { 2125 let fns = self.device.fns(); 2126 2127 if self.device.api_version() >= Version::V1_3 { 2128 (fns.v1_3.cmd_end_rendering)(self.handle); 2129 } else { 2130 debug_assert!(self.device.enabled_extensions().khr_dynamic_rendering); 2131 (fns.khr_dynamic_rendering.cmd_end_rendering_khr)(self.handle); 2132 } 2133 } 2134 2135 /// Calls `vkCmdClearAttachments` on the builder. 2136 /// 2137 /// Does nothing if the list of attachments or the list of rects is empty, as it would be a 2138 /// no-op and isn't a valid usage of the command anyway. clear_attachments( &mut self, attachments: impl IntoIterator<Item = ClearAttachment>, rects: impl IntoIterator<Item = ClearRect>, )2139 pub unsafe fn clear_attachments( 2140 &mut self, 2141 attachments: impl IntoIterator<Item = ClearAttachment>, 2142 rects: impl IntoIterator<Item = ClearRect>, 2143 ) { 2144 let attachments: SmallVec<[_; 3]> = attachments.into_iter().map(|v| v.into()).collect(); 2145 let rects: SmallVec<[_; 4]> = rects 2146 .into_iter() 2147 .map(|rect| ash::vk::ClearRect { 2148 rect: ash::vk::Rect2D { 2149 offset: ash::vk::Offset2D { 2150 x: rect.offset[0] as i32, 2151 y: rect.offset[1] as i32, 2152 }, 2153 extent: ash::vk::Extent2D { 2154 width: rect.extent[0], 2155 height: rect.extent[1], 2156 }, 2157 }, 2158 base_array_layer: rect.array_layers.start, 2159 layer_count: rect.array_layers.end - rect.array_layers.start, 2160 }) 2161 .collect(); 2162 2163 if attachments.is_empty() || rects.is_empty() { 2164 return; 2165 } 2166 2167 let fns = self.device.fns(); 2168 (fns.v1_0.cmd_clear_attachments)( 2169 self.handle, 2170 attachments.len() as u32, 2171 attachments.as_ptr(), 2172 rects.len() as u32, 2173 rects.as_ptr(), 2174 ); 2175 } 2176 } 2177 2178 /// Parameters to begin a new render pass. 2179 #[derive(Clone, Debug)] 2180 pub struct RenderPassBeginInfo { 2181 /// The render pass to begin. 2182 /// 2183 /// If this is not the render pass that `framebuffer` was created with, it must be compatible 2184 /// with that render pass. 2185 /// 2186 /// The default value is the render pass of `framebuffer`. 2187 pub render_pass: Arc<RenderPass>, 2188 2189 /// The framebuffer to use for rendering. 2190 /// 2191 /// There is no default value. 2192 pub framebuffer: Arc<Framebuffer>, 2193 2194 /// The offset from the top left corner of the framebuffer that will be rendered to. 2195 /// 2196 /// The default value is `[0, 0]`. 2197 pub render_area_offset: [u32; 2], 2198 2199 /// The size of the area that will be rendered to. 2200 /// 2201 /// `render_area_offset + render_area_extent` must not be greater than [`framebuffer.extent()`]. 2202 /// 2203 /// The default value is [`framebuffer.extent()`]. 2204 pub render_area_extent: [u32; 2], 2205 2206 /// Provides, for each attachment in `render_pass` that has a load operation of 2207 /// [`LoadOp::Clear`], the clear values that should be used for the attachments in the 2208 /// framebuffer. There must be exactly [`framebuffer.attachments().len()`] elements provided, 2209 /// and each one must match the attachment format. 2210 /// 2211 /// To skip over an attachment whose load operation is something else, provide `None`. 2212 /// 2213 /// The default value is empty, which must be overridden if the framebuffer has attachments. 2214 pub clear_values: Vec<Option<ClearValue>>, 2215 2216 pub _ne: crate::NonExhaustive, 2217 } 2218 2219 impl RenderPassBeginInfo { 2220 #[inline] framebuffer(framebuffer: Arc<Framebuffer>) -> Self2221 pub fn framebuffer(framebuffer: Arc<Framebuffer>) -> Self { 2222 let render_area_extent = framebuffer.extent(); 2223 2224 Self { 2225 render_pass: framebuffer.render_pass().clone(), 2226 framebuffer, 2227 render_area_offset: [0, 0], 2228 render_area_extent, 2229 clear_values: Vec::new(), 2230 _ne: crate::NonExhaustive(()), 2231 } 2232 } 2233 } 2234 2235 /// Parameters to begin rendering. 2236 #[derive(Clone, Debug)] 2237 pub struct RenderingInfo { 2238 /// The offset from the top left corner of the attachments that will be rendered to. 2239 /// 2240 /// This value must be smaller than the smallest width and height of the attachment images. 2241 /// 2242 /// The default value is `[0, 0]`. 2243 pub render_area_offset: [u32; 2], 2244 2245 /// The size of the area that will be rendered to. 2246 /// 2247 /// This value plus `render_area_offset` must be no larger than the smallest width and height 2248 /// of the attachment images. 2249 /// If one of the elements is set to 0, the extent will be calculated automatically from the 2250 /// extents of the attachment images to be the largest allowed. At least one attachment image 2251 /// must be specified in that case. 2252 /// 2253 /// The default value is `[0, 0]`. 2254 pub render_area_extent: [u32; 2], 2255 2256 /// The number of layers of the attachments that will be rendered to. 2257 /// 2258 /// This must be no larger than the smallest number of array layers of the attachment images. 2259 /// If set to 0, the number of layers will be calculated automatically from the 2260 /// layer ranges of the attachment images to be the largest allowed. At least one attachment 2261 /// image must be specified in that case. 2262 /// 2263 /// If the render pass uses multiview (`view_mask` is not 0), then this value must be 0 or 1. 2264 /// 2265 /// The default value is `0`. 2266 pub layer_count: u32, 2267 2268 /// If not `0`, enables multiview rendering, and specifies the view indices that are rendered 2269 /// to. The value is a bitmask, so that that for example `0b11` will draw to the first two 2270 /// views and `0b101` will draw to the first and third view. 2271 /// 2272 /// If set to a nonzero value, the [`multiview`](crate::device::Features::multiview) feature 2273 /// must be enabled on the device. 2274 /// 2275 /// The default value is `0`. 2276 pub view_mask: u32, 2277 2278 /// The color attachments to use for rendering. 2279 /// 2280 /// The number of color attachments must be less than the 2281 /// [`max_color_attachments`](crate::device::Properties::max_color_attachments) limit of the 2282 /// physical device. All color attachments must have the same `samples` value. 2283 /// 2284 /// The default value is empty. 2285 pub color_attachments: Vec<Option<RenderingAttachmentInfo>>, 2286 2287 /// The depth attachment to use for rendering. 2288 /// 2289 /// If set to `Some`, the image view must have the same `samples` value as those in 2290 /// `color_attachments`. 2291 /// 2292 /// The default value is `None`. 2293 pub depth_attachment: Option<RenderingAttachmentInfo>, 2294 2295 /// The stencil attachment to use for rendering. 2296 /// 2297 /// If set to `Some`, the image view must have the same `samples` value as those in 2298 /// `color_attachments`. 2299 /// 2300 /// The default value is `None`. 2301 pub stencil_attachment: Option<RenderingAttachmentInfo>, 2302 2303 /// What kinds of commands will be recorded in the render pass: either inline draw commands, or 2304 /// executions of secondary command buffers. 2305 /// 2306 /// If recorded in a secondary command buffer, this must be [`SubpassContents::Inline`]. 2307 /// 2308 /// The default value is [`SubpassContents::Inline`]. 2309 pub contents: SubpassContents, 2310 2311 pub _ne: crate::NonExhaustive, 2312 } 2313 2314 impl Default for RenderingInfo { 2315 #[inline] default() -> Self2316 fn default() -> Self { 2317 Self { 2318 render_area_offset: [0, 0], 2319 render_area_extent: [0, 0], 2320 layer_count: 0, 2321 view_mask: 0, 2322 color_attachments: Vec::new(), 2323 depth_attachment: None, 2324 stencil_attachment: None, 2325 contents: SubpassContents::Inline, 2326 _ne: crate::NonExhaustive(()), 2327 } 2328 } 2329 } 2330 2331 impl RenderingInfo { set_extent_layers(&mut self) -> Result<(), RenderPassError>2332 pub(crate) fn set_extent_layers(&mut self) -> Result<(), RenderPassError> { 2333 let &mut RenderingInfo { 2334 render_area_offset, 2335 ref mut render_area_extent, 2336 ref mut layer_count, 2337 view_mask, 2338 ref color_attachments, 2339 ref depth_attachment, 2340 ref stencil_attachment, 2341 contents: _, 2342 _ne: _, 2343 } = self; 2344 2345 let auto_extent = render_area_extent[0] == 0 || render_area_extent[1] == 0; 2346 let auto_layers = *layer_count == 0; 2347 2348 // Set the values based on the attachment sizes. 2349 if auto_extent || auto_layers { 2350 if auto_extent { 2351 *render_area_extent = [u32::MAX, u32::MAX]; 2352 } 2353 2354 if auto_layers { 2355 if view_mask != 0 { 2356 *layer_count = 1; 2357 } else { 2358 *layer_count = u32::MAX; 2359 } 2360 } 2361 2362 for image_view in (color_attachments.iter().flatten()) 2363 .chain(depth_attachment.iter()) 2364 .chain(stencil_attachment.iter()) 2365 .flat_map(|attachment_info| { 2366 Some(&attachment_info.image_view).into_iter().chain( 2367 attachment_info 2368 .resolve_info 2369 .as_ref() 2370 .map(|resolve_info| &resolve_info.image_view), 2371 ) 2372 }) 2373 { 2374 if auto_extent { 2375 let extent = image_view.dimensions().width_height(); 2376 2377 for i in 0..2 { 2378 render_area_extent[i] = min(render_area_extent[i], extent[i]); 2379 } 2380 } 2381 2382 if auto_layers { 2383 let subresource_range = image_view.subresource_range(); 2384 let array_layers = 2385 subresource_range.array_layers.end - subresource_range.array_layers.start; 2386 2387 *layer_count = min(*layer_count, array_layers); 2388 } 2389 } 2390 2391 if auto_extent { 2392 if *render_area_extent == [u32::MAX, u32::MAX] { 2393 return Err(RenderPassError::AutoExtentAttachmentsEmpty); 2394 } 2395 2396 // Subtract the offset from the calculated max extent. 2397 // If there is an underflow, then the offset is too large, and validation should 2398 // catch that later. 2399 for i in 0..2 { 2400 render_area_extent[i] = render_area_extent[i] 2401 .checked_sub(render_area_offset[i]) 2402 .unwrap_or(1); 2403 } 2404 } 2405 2406 if auto_layers { 2407 if *layer_count == u32::MAX { 2408 return Err(RenderPassError::AutoLayersAttachmentsEmpty); 2409 } 2410 } 2411 } 2412 2413 Ok(()) 2414 } 2415 } 2416 2417 /// Parameters to specify properties of an attachment. 2418 #[derive(Clone, Debug)] 2419 pub struct RenderingAttachmentInfo { 2420 /// The image view to use as the attachment. 2421 /// 2422 /// There is no default value. 2423 pub image_view: Arc<dyn ImageViewAbstract>, 2424 2425 /// The image layout that `image_view` should be in during the resolve operation. 2426 /// 2427 /// The default value is [`ImageLayout::ColorAttachmentOptimal`] if `image_view` has a color 2428 /// format, [`ImageLayout::DepthStencilAttachmentOptimal`] if `image_view` has a depth/stencil 2429 /// format. 2430 pub image_layout: ImageLayout, 2431 2432 /// The resolve operation that should be performed at the end of rendering. 2433 /// 2434 /// The default value is `None`. 2435 pub resolve_info: Option<RenderingAttachmentResolveInfo>, 2436 2437 /// What the implementation should do with the attachment at the start of rendering. 2438 /// 2439 /// The default value is [`LoadOp::DontCare`]. 2440 pub load_op: LoadOp, 2441 2442 /// What the implementation should do with the attachment at the end of rendering. 2443 /// 2444 /// The default value is [`StoreOp::DontCare`]. 2445 pub store_op: StoreOp, 2446 2447 /// If `load_op` is [`LoadOp::Clear`], specifies the clear value that should be used for the 2448 /// attachment. 2449 /// 2450 /// If `load_op` is something else, provide `None`. 2451 /// 2452 /// The default value is `None`. 2453 pub clear_value: Option<ClearValue>, 2454 2455 pub _ne: crate::NonExhaustive, 2456 } 2457 2458 impl RenderingAttachmentInfo { 2459 /// Returns a `RenderingAttachmentInfo` with the specified `image_view`. 2460 #[inline] image_view(image_view: Arc<dyn ImageViewAbstract>) -> Self2461 pub fn image_view(image_view: Arc<dyn ImageViewAbstract>) -> Self { 2462 let aspects = image_view.format().unwrap().aspects(); 2463 let image_layout = if aspects.intersects(ImageAspects::DEPTH | ImageAspects::STENCIL) { 2464 ImageLayout::DepthStencilAttachmentOptimal 2465 } else { 2466 ImageLayout::ColorAttachmentOptimal 2467 }; 2468 2469 Self { 2470 image_view, 2471 image_layout, 2472 resolve_info: None, 2473 load_op: LoadOp::DontCare, 2474 store_op: StoreOp::DontCare, 2475 clear_value: None, 2476 _ne: crate::NonExhaustive(()), 2477 } 2478 } 2479 } 2480 2481 /// Parameters to specify the resolve behavior of an attachment. 2482 #[derive(Clone, Debug)] 2483 pub struct RenderingAttachmentResolveInfo { 2484 /// How the resolve operation should be performed. 2485 /// 2486 /// The default value is [`ResolveMode::Average`]. 2487 pub mode: ResolveMode, 2488 2489 /// The image view that the result of the resolve operation should be written to. 2490 /// 2491 /// There is no default value. 2492 pub image_view: Arc<dyn ImageViewAbstract>, 2493 2494 /// The image layout that `image_view` should be in during the resolve operation. 2495 /// 2496 /// The default value is [`ImageLayout::ColorAttachmentOptimal`] if `image_view` has a color 2497 /// format, [`ImageLayout::DepthStencilAttachmentOptimal`] if `image_view` has a depth/stencil 2498 /// format. 2499 pub image_layout: ImageLayout, 2500 } 2501 2502 impl RenderingAttachmentResolveInfo { 2503 /// Returns a `RenderingAttachmentResolveInfo` with the specified `image_view`. 2504 #[inline] image_view(image_view: Arc<dyn ImageViewAbstract>) -> Self2505 pub fn image_view(image_view: Arc<dyn ImageViewAbstract>) -> Self { 2506 let aspects = image_view.format().unwrap().aspects(); 2507 let image_layout = if aspects.intersects(ImageAspects::DEPTH | ImageAspects::STENCIL) { 2508 ImageLayout::DepthStencilAttachmentOptimal 2509 } else { 2510 ImageLayout::ColorAttachmentOptimal 2511 }; 2512 2513 Self { 2514 mode: ResolveMode::Average, 2515 image_view, 2516 image_layout, 2517 } 2518 } 2519 } 2520 2521 /// Clear attachment type, used in [`clear_attachments`] command. 2522 /// 2523 /// [`clear_attachments`]: crate::command_buffer::AutoCommandBufferBuilder::clear_attachments 2524 #[derive(Clone, Copy, Debug)] 2525 pub enum ClearAttachment { 2526 /// Clear the color attachment at the specified index, with the specified clear value. 2527 Color { 2528 color_attachment: u32, 2529 clear_value: ClearColorValue, 2530 }, 2531 2532 /// Clear the depth attachment with the specified depth value. 2533 Depth(f32), 2534 2535 /// Clear the stencil attachment with the specified stencil value. 2536 Stencil(u32), 2537 2538 /// Clear the depth and stencil attachments with the specified depth and stencil values. 2539 DepthStencil((f32, u32)), 2540 } 2541 2542 impl From<ClearAttachment> for ash::vk::ClearAttachment { 2543 #[inline] from(v: ClearAttachment) -> Self2544 fn from(v: ClearAttachment) -> Self { 2545 match v { 2546 ClearAttachment::Color { 2547 color_attachment, 2548 clear_value, 2549 } => ash::vk::ClearAttachment { 2550 aspect_mask: ash::vk::ImageAspectFlags::COLOR, 2551 color_attachment, 2552 clear_value: ash::vk::ClearValue { 2553 color: clear_value.into(), 2554 }, 2555 }, 2556 ClearAttachment::Depth(depth) => ash::vk::ClearAttachment { 2557 aspect_mask: ash::vk::ImageAspectFlags::DEPTH, 2558 color_attachment: 0, 2559 clear_value: ash::vk::ClearValue { 2560 depth_stencil: ash::vk::ClearDepthStencilValue { depth, stencil: 0 }, 2561 }, 2562 }, 2563 ClearAttachment::Stencil(stencil) => ash::vk::ClearAttachment { 2564 aspect_mask: ash::vk::ImageAspectFlags::STENCIL, 2565 color_attachment: 0, 2566 clear_value: ash::vk::ClearValue { 2567 depth_stencil: ash::vk::ClearDepthStencilValue { 2568 depth: 0.0, 2569 stencil, 2570 }, 2571 }, 2572 }, 2573 ClearAttachment::DepthStencil((depth, stencil)) => ash::vk::ClearAttachment { 2574 aspect_mask: ash::vk::ImageAspectFlags::DEPTH | ash::vk::ImageAspectFlags::STENCIL, 2575 color_attachment: 0, 2576 clear_value: ash::vk::ClearValue { 2577 depth_stencil: ash::vk::ClearDepthStencilValue { depth, stencil }, 2578 }, 2579 }, 2580 } 2581 } 2582 } 2583 2584 /// Specifies the clear region for the [`clear_attachments`] command. 2585 /// 2586 /// [`clear_attachments`]: crate::command_buffer::AutoCommandBufferBuilder::clear_attachments 2587 #[derive(Clone, Debug, PartialEq, Eq)] 2588 pub struct ClearRect { 2589 /// The rectangle offset. 2590 pub offset: [u32; 2], 2591 2592 /// The width and height of the rectangle. 2593 pub extent: [u32; 2], 2594 2595 /// The range of array layers to be cleared. 2596 pub array_layers: Range<u32>, 2597 } 2598 2599 /// Error that can happen when recording a render pass command. 2600 #[derive(Clone, Debug)] 2601 pub enum RenderPassError { 2602 SyncCommandBufferBuilderError(SyncCommandBufferBuilderError), 2603 2604 RequirementNotMet { 2605 required_for: &'static str, 2606 requires_one_of: RequiresOneOf, 2607 }, 2608 2609 /// A framebuffer image did not have the required usage enabled. 2610 AttachmentImageMissingUsage { 2611 attachment_index: u32, 2612 usage: &'static str, 2613 }, 2614 2615 /// One of the elements of `render_pass_extent` is zero, but no attachment images were given to 2616 /// calculate the extent from. 2617 AutoExtentAttachmentsEmpty, 2618 2619 /// `layer_count` is zero, but no attachment images were given to calculate the number of layers 2620 /// from. 2621 AutoLayersAttachmentsEmpty, 2622 2623 /// A clear attachment value is not compatible with the attachment's format. 2624 ClearAttachmentNotCompatible { 2625 clear_attachment: ClearAttachment, 2626 attachment_format: Option<Format>, 2627 }, 2628 2629 /// A clear value for a render pass attachment is missing. 2630 ClearValueMissing { 2631 attachment_index: u32, 2632 }, 2633 2634 /// A clear value provided for a render pass attachment is not compatible with the attachment's 2635 /// format. 2636 ClearValueNotCompatible { 2637 clear_value: ClearValue, 2638 attachment_index: u32, 2639 attachment_format: Format, 2640 }, 2641 2642 /// An attachment clear value specifies a `color_attachment` index that is not less than the 2643 /// number of color attachments in the subpass. 2644 ColorAttachmentIndexOutOfRange { 2645 color_attachment_index: u32, 2646 num_color_attachments: u32, 2647 }, 2648 2649 /// A color attachment has a layout that is not supported. 2650 ColorAttachmentLayoutInvalid { 2651 attachment_index: u32, 2652 }, 2653 2654 /// A color attachment is missing the `color_attachment` usage. 2655 ColorAttachmentMissingUsage { 2656 attachment_index: u32, 2657 }, 2658 2659 /// A color resolve attachment has a `format` value different from the corresponding color 2660 /// attachment. 2661 ColorAttachmentResolveFormatMismatch { 2662 attachment_index: u32, 2663 }, 2664 2665 /// A color resolve attachment has a layout that is not supported. 2666 ColorAttachmentResolveLayoutInvalid { 2667 attachment_index: u32, 2668 }, 2669 2670 /// A color resolve attachment has a resolve mode that is not supported. 2671 ColorAttachmentResolveModeNotSupported { 2672 attachment_index: u32, 2673 }, 2674 2675 /// A color resolve attachment has a `samples` value other than [`SampleCount::Sample1`]. 2676 ColorAttachmentResolveMultisampled { 2677 attachment_index: u32, 2678 }, 2679 2680 /// A color attachment has a `samples` value that is different from the first 2681 /// color attachment. 2682 ColorAttachmentSamplesMismatch { 2683 attachment_index: u32, 2684 }, 2685 2686 /// A color attachment with a resolve attachment has a `samples` value of 2687 /// [`SampleCount::Sample1`]. 2688 ColorAttachmentWithResolveNotMultisampled { 2689 attachment_index: u32, 2690 }, 2691 2692 /// The contents `SubpassContents::SecondaryCommandBuffers` is not allowed inside a secondary 2693 /// command buffer. 2694 ContentsForbiddenInSecondaryCommandBuffer, 2695 2696 /// The depth attachment has a format that does not support that usage. 2697 DepthAttachmentFormatUsageNotSupported, 2698 2699 /// The depth attachment has a layout that is not supported. 2700 DepthAttachmentLayoutInvalid, 2701 2702 /// The depth attachment is missing the `depth_stencil_attachment` usage. 2703 DepthAttachmentMissingUsage, 2704 2705 /// The depth resolve attachment has a `format` value different from the corresponding depth 2706 /// attachment. 2707 DepthAttachmentResolveFormatMismatch, 2708 2709 /// The depth resolve attachment has a layout that is not supported. 2710 DepthAttachmentResolveLayoutInvalid, 2711 2712 /// The depth resolve attachment has a resolve mode that is not supported. 2713 DepthAttachmentResolveModeNotSupported, 2714 2715 /// The depth resolve attachment has a `samples` value other than [`SampleCount::Sample1`]. 2716 DepthAttachmentResolveMultisampled, 2717 2718 /// The depth attachment has a `samples` value that is different from the first 2719 /// color attachment. 2720 DepthAttachmentSamplesMismatch, 2721 2722 /// The depth attachment has a resolve attachment and has a `samples` value of 2723 /// [`SampleCount::Sample1`]. 2724 DepthAttachmentWithResolveNotMultisampled, 2725 2726 /// The depth and stencil attachments have different image views. 2727 DepthStencilAttachmentImageViewMismatch, 2728 2729 /// The depth and stencil resolve attachments have different image views. 2730 DepthStencilAttachmentResolveImageViewMismatch, 2731 2732 /// The combination of depth and stencil resolve modes is not supported by the device. 2733 DepthStencilAttachmentResolveModesNotSupported, 2734 2735 /// Operation forbidden inside a render pass. 2736 ForbiddenInsideRenderPass, 2737 2738 /// Operation forbidden outside a render pass. 2739 ForbiddenOutsideRenderPass, 2740 2741 /// Operation forbidden inside a render pass instance that was begun with `begin_rendering`. 2742 ForbiddenWithBeginRendering, 2743 2744 /// Operation forbidden inside a render pass instance that was begun with `begin_render_pass`. 2745 ForbiddenWithBeginRenderPass, 2746 2747 /// Operation forbidden inside a render pass instance that is inherited by a secondary command 2748 /// buffer. 2749 ForbiddenWithInheritedRenderPass, 2750 2751 /// Operation forbidden inside a render subpass with the specified contents. 2752 ForbiddenWithSubpassContents { 2753 contents: SubpassContents, 2754 }, 2755 2756 /// The framebuffer is not compatible with the render pass. 2757 FramebufferNotCompatible, 2758 2759 /// The `max_color_attachments` limit has been exceeded. 2760 MaxColorAttachmentsExceeded { 2761 color_attachment_count: u32, 2762 max: u32, 2763 }, 2764 2765 /// The `max_multiview_view_count` limit has been exceeded. 2766 MaxMultiviewViewCountExceeded { 2767 view_count: u32, 2768 max: u32, 2769 }, 2770 2771 /// The render pass uses multiview, but `layer_count` was not 0 or 1. 2772 MultiviewLayersInvalid, 2773 2774 /// The render pass uses multiview, and in a clear rectangle, `array_layers` was not `0..1`. 2775 MultiviewRectArrayLayersInvalid { 2776 rect_index: usize, 2777 }, 2778 2779 /// Tried to advance to the next subpass, but there are no subpasses remaining in the render 2780 /// pass. 2781 NoSubpassesRemaining { 2782 current_subpass: u32, 2783 }, 2784 2785 /// The queue family doesn't allow this operation. 2786 NotSupportedByQueueFamily, 2787 2788 /// A query is active that conflicts with the current operation. 2789 QueryIsActive, 2790 2791 /// A clear rectangle's `array_layers` is empty. 2792 RectArrayLayersEmpty { 2793 rect_index: usize, 2794 }, 2795 2796 /// A clear rectangle's `array_layers` is outside the range of layers of the attachments. 2797 RectArrayLayersOutOfBounds { 2798 rect_index: usize, 2799 }, 2800 2801 /// A clear rectangle's `extent` is zero. 2802 RectExtentZero { 2803 rect_index: usize, 2804 }, 2805 2806 /// A clear rectangle's `offset` and `extent` are outside the render area of the render pass 2807 /// instance. 2808 RectOutOfBounds { 2809 rect_index: usize, 2810 }, 2811 2812 /// The render area's `offset` and `extent` are outside the extent of the framebuffer. 2813 RenderAreaOutOfBounds, 2814 2815 /// The stencil attachment has a format that does not support that usage. 2816 StencilAttachmentFormatUsageNotSupported, 2817 2818 /// The stencil attachment has a layout that is not supported. 2819 StencilAttachmentLayoutInvalid, 2820 2821 /// The stencil attachment is missing the `depth_stencil_attachment` usage. 2822 StencilAttachmentMissingUsage, 2823 2824 /// The stencil resolve attachment has a `format` value different from the corresponding stencil 2825 /// attachment. 2826 StencilAttachmentResolveFormatMismatch, 2827 2828 /// The stencil resolve attachment has a layout that is not supported. 2829 StencilAttachmentResolveLayoutInvalid, 2830 2831 /// The stencil resolve attachment has a resolve mode that is not supported. 2832 StencilAttachmentResolveModeNotSupported, 2833 2834 /// The stencil resolve attachment has a `samples` value other than [`SampleCount::Sample1`]. 2835 StencilAttachmentResolveMultisampled, 2836 2837 /// The stencil attachment has a `samples` value that is different from the first 2838 /// color attachment or the depth attachment. 2839 StencilAttachmentSamplesMismatch, 2840 2841 /// The stencil attachment has a resolve attachment and has a `samples` value of 2842 /// [`SampleCount::Sample1`]. 2843 StencilAttachmentWithResolveNotMultisampled, 2844 2845 /// Tried to end a render pass with subpasses still remaining in the render pass. 2846 SubpassesRemaining { 2847 current_subpass: u32, 2848 remaining_subpasses: u32, 2849 }, 2850 } 2851 2852 impl Error for RenderPassError { source(&self) -> Option<&(dyn Error + 'static)>2853 fn source(&self) -> Option<&(dyn Error + 'static)> { 2854 match self { 2855 Self::SyncCommandBufferBuilderError(err) => Some(err), 2856 _ => None, 2857 } 2858 } 2859 } 2860 2861 impl Display for RenderPassError { fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError>2862 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { 2863 match self { 2864 Self::SyncCommandBufferBuilderError(_) => write!(f, "a SyncCommandBufferBuilderError"), 2865 Self::RequirementNotMet { 2866 required_for, 2867 requires_one_of, 2868 } => write!( 2869 f, 2870 "a requirement was not met for: {}; requires one of: {}", 2871 required_for, requires_one_of, 2872 ), 2873 Self::AttachmentImageMissingUsage { 2874 attachment_index, 2875 usage, 2876 } => write!( 2877 f, 2878 "the framebuffer image attached to attachment index {} did not have the required \ 2879 usage {} enabled", 2880 attachment_index, usage, 2881 ), 2882 Self::AutoExtentAttachmentsEmpty => write!( 2883 f, 2884 "one of the elements of `render_pass_extent` is zero, but no attachment images \ 2885 were given to calculate the extent from", 2886 ), 2887 Self::AutoLayersAttachmentsEmpty => write!( 2888 f, 2889 "`layer_count` is zero, but no attachment images were given to calculate the \ 2890 number of layers from", 2891 ), 2892 Self::ClearAttachmentNotCompatible { 2893 clear_attachment, 2894 attachment_format, 2895 } => write!( 2896 f, 2897 "a clear attachment value ({:?}) is not compatible with the attachment's format \ 2898 ({:?})", 2899 clear_attachment, attachment_format, 2900 ), 2901 Self::ClearValueMissing { attachment_index } => write!( 2902 f, 2903 "a clear value for render pass attachment {} is missing", 2904 attachment_index, 2905 ), 2906 Self::ClearValueNotCompatible { 2907 clear_value, 2908 attachment_index, 2909 attachment_format, 2910 } => write!( 2911 f, 2912 "a clear value ({:?}) provided for render pass attachment {} is not compatible \ 2913 with the attachment's format ({:?})", 2914 clear_value, attachment_index, attachment_format, 2915 ), 2916 Self::ColorAttachmentIndexOutOfRange { 2917 color_attachment_index, 2918 num_color_attachments, 2919 } => write!( 2920 f, 2921 "an attachment clear value specifies a `color_attachment` index {} that is not \ 2922 less than the number of color attachments in the subpass ({})", 2923 color_attachment_index, num_color_attachments, 2924 ), 2925 Self::ColorAttachmentLayoutInvalid { attachment_index } => write!( 2926 f, 2927 "color attachment {} has a layout that is not supported", 2928 attachment_index, 2929 ), 2930 Self::ColorAttachmentMissingUsage { attachment_index } => write!( 2931 f, 2932 "color attachment {} is missing the `color_attachment` usage", 2933 attachment_index, 2934 ), 2935 Self::ColorAttachmentResolveFormatMismatch { attachment_index } => write!( 2936 f, 2937 "color attachment {} has a `format` value different from the corresponding color \ 2938 attachment", 2939 attachment_index, 2940 ), 2941 Self::ColorAttachmentResolveLayoutInvalid { attachment_index } => write!( 2942 f, 2943 "color resolve attachment {} has a layout that is not supported", 2944 attachment_index, 2945 ), 2946 Self::ColorAttachmentResolveModeNotSupported { attachment_index } => write!( 2947 f, 2948 "color resolve attachment {} has a resolve mode that is not supported", 2949 attachment_index, 2950 ), 2951 Self::ColorAttachmentResolveMultisampled { attachment_index } => write!( 2952 f, 2953 "color resolve attachment {} has a `samples` value other than \ 2954 `SampleCount::Sample1`", 2955 attachment_index, 2956 ), 2957 Self::ColorAttachmentSamplesMismatch { attachment_index } => write!( 2958 f, 2959 "color attachment {} has a `samples` value that is different from the first color \ 2960 attachment", 2961 attachment_index, 2962 ), 2963 Self::ColorAttachmentWithResolveNotMultisampled { attachment_index } => write!( 2964 f, 2965 "color attachment {} with a resolve attachment has a `samples` value of \ 2966 `SampleCount::Sample1`", 2967 attachment_index, 2968 ), 2969 Self::ContentsForbiddenInSecondaryCommandBuffer => write!( 2970 f, 2971 "the contents `SubpassContents::SecondaryCommandBuffers` is not allowed inside a \ 2972 secondary command buffer", 2973 ), 2974 Self::DepthAttachmentFormatUsageNotSupported => write!( 2975 f, 2976 "the depth attachment has a format that does not support that usage", 2977 ), 2978 Self::DepthAttachmentLayoutInvalid => { 2979 write!(f, "the depth attachment has a layout that is not supported") 2980 } 2981 Self::DepthAttachmentMissingUsage => write!( 2982 f, 2983 "the depth attachment is missing the `depth_stencil_attachment` usage", 2984 ), 2985 Self::DepthAttachmentResolveFormatMismatch => write!( 2986 f, 2987 "the depth resolve attachment has a `format` value different from the \ 2988 corresponding depth attachment", 2989 ), 2990 Self::DepthAttachmentResolveLayoutInvalid => write!( 2991 f, 2992 "the depth resolve attachment has a layout that is not supported", 2993 ), 2994 Self::DepthAttachmentResolveModeNotSupported => write!( 2995 f, 2996 "the depth resolve attachment has a resolve mode that is not supported", 2997 ), 2998 Self::DepthAttachmentResolveMultisampled => write!( 2999 f, 3000 "the depth resolve attachment has a `samples` value other than \ 3001 `SampleCount::Sample1`", 3002 ), 3003 Self::DepthAttachmentSamplesMismatch => write!( 3004 f, 3005 "the depth attachment has a `samples` value that is different from the first color \ 3006 attachment", 3007 ), 3008 Self::DepthAttachmentWithResolveNotMultisampled => write!( 3009 f, 3010 "the depth attachment has a resolve attachment and has a `samples` value of \ 3011 `SampleCount::Sample1`", 3012 ), 3013 Self::DepthStencilAttachmentImageViewMismatch => write!( 3014 f, 3015 "the depth and stencil attachments have different image views", 3016 ), 3017 Self::DepthStencilAttachmentResolveImageViewMismatch => write!( 3018 f, 3019 "the depth and stencil resolve attachments have different image views", 3020 ), 3021 Self::DepthStencilAttachmentResolveModesNotSupported => write!( 3022 f, 3023 "the combination of depth and stencil resolve modes is not supported by the device", 3024 ), 3025 Self::ForbiddenInsideRenderPass => { 3026 write!(f, "operation forbidden inside a render pass") 3027 } 3028 Self::ForbiddenOutsideRenderPass => { 3029 write!(f, "operation forbidden outside a render pass") 3030 } 3031 Self::ForbiddenWithBeginRendering => write!( 3032 f, 3033 "operation forbidden inside a render pass instance that was begun with \ 3034 `begin_rendering`", 3035 ), 3036 Self::ForbiddenWithBeginRenderPass => write!( 3037 f, 3038 "operation forbidden inside a render pass instance that was begun with \ 3039 `begin_render_pass`", 3040 ), 3041 Self::ForbiddenWithInheritedRenderPass => write!( 3042 f, 3043 "operation forbidden inside a render pass instance that is inherited by a \ 3044 secondary command buffer", 3045 ), 3046 Self::ForbiddenWithSubpassContents { 3047 contents: subpass_contents, 3048 } => write!( 3049 f, 3050 "operation forbidden inside a render subpass with contents {:?}", 3051 subpass_contents, 3052 ), 3053 Self::FramebufferNotCompatible => { 3054 write!(f, "the framebuffer is not compatible with the render pass") 3055 } 3056 Self::MaxColorAttachmentsExceeded { .. } => { 3057 write!(f, "the `max_color_attachments` limit has been exceeded") 3058 } 3059 Self::MaxMultiviewViewCountExceeded { .. } => { 3060 write!(f, "the `max_multiview_view_count` limit has been exceeded") 3061 } 3062 Self::MultiviewLayersInvalid => write!( 3063 f, 3064 "the render pass uses multiview, but `layer_count` was not 0 or 1", 3065 ), 3066 Self::MultiviewRectArrayLayersInvalid { rect_index } => write!( 3067 f, 3068 "the render pass uses multiview, and in clear rectangle index {}, `array_layers` \ 3069 was not `0..1`", 3070 rect_index, 3071 ), 3072 Self::NoSubpassesRemaining { current_subpass } => write!( 3073 f, 3074 "tried to advance to the next subpass after subpass {}, but there are no subpasses \ 3075 remaining in the render pass", 3076 current_subpass, 3077 ), 3078 Self::NotSupportedByQueueFamily => { 3079 write!(f, "the queue family doesn't allow this operation") 3080 } 3081 Self::QueryIsActive => write!( 3082 f, 3083 "a query is active that conflicts with the current operation", 3084 ), 3085 Self::RectArrayLayersEmpty { rect_index } => write!( 3086 f, 3087 "clear rectangle index {} `array_layers` is empty", 3088 rect_index, 3089 ), 3090 Self::RectArrayLayersOutOfBounds { rect_index } => write!( 3091 f, 3092 "clear rectangle index {} `array_layers` is outside the range of layers of the \ 3093 attachments", 3094 rect_index, 3095 ), 3096 Self::RectExtentZero { rect_index } => { 3097 write!(f, "clear rectangle index {} `extent` is zero", rect_index) 3098 } 3099 Self::RectOutOfBounds { rect_index } => write!( 3100 f, 3101 "clear rectangle index {} `offset` and `extent` are outside the render area of the \ 3102 render pass instance", 3103 rect_index, 3104 ), 3105 Self::RenderAreaOutOfBounds => write!( 3106 f, 3107 "the render area's `offset` and `extent` are outside the extent of the framebuffer", 3108 ), 3109 Self::StencilAttachmentFormatUsageNotSupported => write!( 3110 f, 3111 "the stencil attachment has a format that does not support that usage", 3112 ), 3113 Self::StencilAttachmentLayoutInvalid => write!( 3114 f, 3115 "the stencil attachment has a layout that is not supported", 3116 ), 3117 Self::StencilAttachmentMissingUsage => write!( 3118 f, 3119 "the stencil attachment is missing the `depth_stencil_attachment` usage", 3120 ), 3121 Self::StencilAttachmentResolveFormatMismatch => write!( 3122 f, 3123 "the stencil resolve attachment has a `format` value different from the \ 3124 corresponding stencil attachment", 3125 ), 3126 Self::StencilAttachmentResolveLayoutInvalid => write!( 3127 f, 3128 "the stencil resolve attachment has a layout that is not supported", 3129 ), 3130 Self::StencilAttachmentResolveModeNotSupported => write!( 3131 f, 3132 "the stencil resolve attachment has a resolve mode that is not supported", 3133 ), 3134 Self::StencilAttachmentResolveMultisampled => write!( 3135 f, 3136 "the stencil resolve attachment has a `samples` value other than \ 3137 `SampleCount::Sample1`", 3138 ), 3139 Self::StencilAttachmentSamplesMismatch => write!( 3140 f, 3141 "the stencil attachment has a `samples` value that is different from the first \ 3142 color attachment", 3143 ), 3144 Self::StencilAttachmentWithResolveNotMultisampled => write!( 3145 f, 3146 "the stencil attachment has a resolve attachment and has a `samples` value of \ 3147 `SampleCount::Sample1`", 3148 ), 3149 Self::SubpassesRemaining { 3150 current_subpass, 3151 remaining_subpasses, 3152 } => write!( 3153 f, 3154 "tried to end a render pass at subpass {}, with {} subpasses still remaining in \ 3155 the render pass", 3156 current_subpass, remaining_subpasses, 3157 ), 3158 } 3159 } 3160 } 3161 3162 impl From<SyncCommandBufferBuilderError> for RenderPassError { from(err: SyncCommandBufferBuilderError) -> Self3163 fn from(err: SyncCommandBufferBuilderError) -> Self { 3164 Self::SyncCommandBufferBuilderError(err) 3165 } 3166 } 3167 3168 impl From<RequirementNotMet> for RenderPassError { from(err: RequirementNotMet) -> Self3169 fn from(err: RequirementNotMet) -> Self { 3170 Self::RequirementNotMet { 3171 required_for: err.required_for, 3172 requires_one_of: err.requires_one_of, 3173 } 3174 } 3175 } 3176