1 // Copyright (c) 2016 The vulkano developers 2 // Licensed under the Apache License, Version 2.0 3 // <LICENSE-APACHE or 4 // https://www.apache.org/licenses/LICENSE-2.0> or the MIT 5 // license <LICENSE-MIT or https://opensource.org/licenses/MIT>, 6 // at your option. All files in the project carrying such 7 // notice may not be copied, modified, or distributed except 8 // according to those terms. 9 10 use super::RenderPass; 11 use crate::{ 12 device::{Device, DeviceOwned}, 13 format::Format, 14 image::{view::ImageViewType, ImageDimensions, ImageUsage, ImageViewAbstract, SampleCount}, 15 macros::impl_id_counter, 16 OomError, VulkanError, VulkanObject, 17 }; 18 use smallvec::SmallVec; 19 use std::{ 20 error::Error, 21 fmt::{Display, Error as FmtError, Formatter}, 22 mem::MaybeUninit, 23 num::NonZeroU64, 24 ops::Range, 25 ptr, 26 sync::Arc, 27 }; 28 29 /// The image views that are attached to a render pass during drawing. 30 /// 31 /// A framebuffer is a collection of images, and supplies the actual inputs and outputs of each 32 /// attachment within a render pass. Each attachment point in the render pass must have a matching 33 /// image in the framebuffer. 34 /// 35 /// ``` 36 /// # use std::sync::Arc; 37 /// # use vulkano::render_pass::RenderPass; 38 /// # use vulkano::image::AttachmentImage; 39 /// # use vulkano::image::view::ImageView; 40 /// use vulkano::render_pass::{Framebuffer, FramebufferCreateInfo}; 41 /// 42 /// # let render_pass: Arc<RenderPass> = return; 43 /// # let view: Arc<ImageView<AttachmentImage>> = return; 44 /// // let render_pass: Arc<_> = ...; 45 /// let framebuffer = Framebuffer::new( 46 /// render_pass.clone(), 47 /// FramebufferCreateInfo { 48 /// attachments: vec![view], 49 /// ..Default::default() 50 /// }, 51 /// ).unwrap(); 52 /// ``` 53 #[derive(Debug)] 54 pub struct Framebuffer { 55 handle: ash::vk::Framebuffer, 56 render_pass: Arc<RenderPass>, 57 id: NonZeroU64, 58 59 attachments: Vec<Arc<dyn ImageViewAbstract>>, 60 extent: [u32; 2], 61 layers: u32, 62 } 63 64 impl Framebuffer { 65 /// Creates a new `Framebuffer`. new( render_pass: Arc<RenderPass>, create_info: FramebufferCreateInfo, ) -> Result<Arc<Framebuffer>, FramebufferCreationError>66 pub fn new( 67 render_pass: Arc<RenderPass>, 68 create_info: FramebufferCreateInfo, 69 ) -> Result<Arc<Framebuffer>, FramebufferCreationError> { 70 let FramebufferCreateInfo { 71 attachments, 72 mut extent, 73 mut layers, 74 _ne: _, 75 } = create_info; 76 77 let device = render_pass.device(); 78 79 // VUID-VkFramebufferCreateInfo-attachmentCount-00876 80 if attachments.len() != render_pass.attachments().len() { 81 return Err(FramebufferCreationError::AttachmentCountMismatch { 82 provided: attachments.len() as u32, 83 required: render_pass.attachments().len() as u32, 84 }); 85 } 86 87 let auto_extent = extent[0] == 0 || extent[1] == 0; 88 let auto_layers = layers == 0; 89 90 // VUID-VkFramebufferCreateInfo-width-00885 91 // VUID-VkFramebufferCreateInfo-height-00887 92 if auto_extent { 93 if attachments.is_empty() { 94 return Err(FramebufferCreationError::AutoExtentAttachmentsEmpty); 95 } 96 97 extent = [u32::MAX, u32::MAX]; 98 } 99 100 // VUID-VkFramebufferCreateInfo-layers-00889 101 if auto_layers { 102 if attachments.is_empty() { 103 return Err(FramebufferCreationError::AutoLayersAttachmentsEmpty); 104 } 105 106 if render_pass.views_used() != 0 { 107 // VUID-VkFramebufferCreateInfo-renderPass-02531 108 layers = 1; 109 } else { 110 layers = u32::MAX; 111 } 112 } else { 113 // VUID-VkFramebufferCreateInfo-renderPass-02531 114 if render_pass.views_used() != 0 && layers != 1 { 115 return Err(FramebufferCreationError::MultiviewLayersInvalid); 116 } 117 } 118 119 let attachments_vk = attachments 120 .iter() 121 .zip(render_pass.attachments()) 122 .enumerate() 123 .map(|(attachment_num, (image_view, attachment_desc))| { 124 let attachment_num = attachment_num as u32; 125 assert_eq!(device, image_view.device()); 126 127 for subpass in render_pass.subpasses() { 128 // VUID-VkFramebufferCreateInfo-pAttachments-00877 129 if subpass 130 .color_attachments 131 .iter() 132 .flatten() 133 .any(|atch_ref| atch_ref.attachment == attachment_num) 134 { 135 if !image_view.usage().intersects(ImageUsage::COLOR_ATTACHMENT) { 136 return Err(FramebufferCreationError::AttachmentMissingUsage { 137 attachment: attachment_num, 138 usage: "color_attachment", 139 }); 140 } 141 } 142 143 // VUID-VkFramebufferCreateInfo-pAttachments-02633 144 if let Some(atch_ref) = &subpass.depth_stencil_attachment { 145 if atch_ref.attachment == attachment_num { 146 if !image_view 147 .usage() 148 .intersects(ImageUsage::DEPTH_STENCIL_ATTACHMENT) 149 { 150 return Err(FramebufferCreationError::AttachmentMissingUsage { 151 attachment: attachment_num, 152 usage: "depth_stencil", 153 }); 154 } 155 } 156 } 157 158 // VUID-VkFramebufferCreateInfo-pAttachments-00879 159 if subpass 160 .input_attachments 161 .iter() 162 .flatten() 163 .any(|atch_ref| atch_ref.attachment == attachment_num) 164 { 165 if !image_view.usage().intersects(ImageUsage::INPUT_ATTACHMENT) { 166 return Err(FramebufferCreationError::AttachmentMissingUsage { 167 attachment: attachment_num, 168 usage: "input_attachment", 169 }); 170 } 171 } 172 } 173 174 // VUID-VkFramebufferCreateInfo-pAttachments-00880 175 if image_view.format() != attachment_desc.format { 176 return Err(FramebufferCreationError::AttachmentFormatMismatch { 177 attachment: attachment_num, 178 provided: image_view.format(), 179 required: attachment_desc.format, 180 }); 181 } 182 183 // VUID-VkFramebufferCreateInfo-pAttachments-00881 184 if image_view.image().samples() != attachment_desc.samples { 185 return Err(FramebufferCreationError::AttachmentSamplesMismatch { 186 attachment: attachment_num, 187 provided: image_view.image().samples(), 188 required: attachment_desc.samples, 189 }); 190 } 191 192 let image_view_extent = image_view.image().dimensions().width_height(); 193 let image_view_array_layers = image_view.subresource_range().array_layers.end 194 - image_view.subresource_range().array_layers.start; 195 196 // VUID-VkFramebufferCreateInfo-renderPass-04536 197 if image_view_array_layers < render_pass.views_used() { 198 return Err( 199 FramebufferCreationError::MultiviewAttachmentNotEnoughLayers { 200 attachment: attachment_num, 201 provided: image_view_array_layers, 202 min: render_pass.views_used(), 203 }, 204 ); 205 } 206 207 // VUID-VkFramebufferCreateInfo-flags-04533 208 // VUID-VkFramebufferCreateInfo-flags-04534 209 if auto_extent { 210 extent[0] = extent[0].min(image_view_extent[0]); 211 extent[1] = extent[1].min(image_view_extent[1]); 212 } else if image_view_extent[0] < extent[0] || image_view_extent[1] < extent[1] { 213 return Err(FramebufferCreationError::AttachmentExtentTooSmall { 214 attachment: attachment_num, 215 provided: image_view_extent, 216 min: extent, 217 }); 218 } 219 220 // VUID-VkFramebufferCreateInfo-flags-04535 221 if auto_layers { 222 layers = layers.min(image_view_array_layers); 223 } else if image_view_array_layers < layers { 224 return Err(FramebufferCreationError::AttachmentNotEnoughLayers { 225 attachment: attachment_num, 226 provided: image_view_array_layers, 227 min: layers, 228 }); 229 } 230 231 // VUID-VkFramebufferCreateInfo-pAttachments-00883 232 if image_view.subresource_range().mip_levels.end 233 - image_view.subresource_range().mip_levels.start 234 != 1 235 { 236 return Err(FramebufferCreationError::AttachmentMultipleMipLevels { 237 attachment: attachment_num, 238 }); 239 } 240 241 // VUID-VkFramebufferCreateInfo-pAttachments-00884 242 if !image_view.component_mapping().is_identity() { 243 return Err( 244 FramebufferCreationError::AttachmentComponentMappingNotIdentity { 245 attachment: attachment_num, 246 }, 247 ); 248 } 249 250 // VUID-VkFramebufferCreateInfo-pAttachments-00891 251 if matches!( 252 image_view.view_type(), 253 ImageViewType::Dim2d | ImageViewType::Dim2dArray 254 ) && matches!( 255 image_view.image().dimensions(), 256 ImageDimensions::Dim3d { .. } 257 ) && image_view.format().unwrap().type_color().is_none() 258 { 259 return Err( 260 FramebufferCreationError::Attachment2dArrayCompatibleDepthStencil { 261 attachment: attachment_num, 262 }, 263 ); 264 } 265 266 // VUID-VkFramebufferCreateInfo-flags-04113 267 if image_view.view_type() == ImageViewType::Dim3d { 268 return Err(FramebufferCreationError::AttachmentViewType3d { 269 attachment: attachment_num, 270 }); 271 } 272 273 Ok(image_view.handle()) 274 }) 275 .collect::<Result<SmallVec<[_; 4]>, _>>()?; 276 277 { 278 let properties = device.physical_device().properties(); 279 280 // VUID-VkFramebufferCreateInfo-width-00886 281 // VUID-VkFramebufferCreateInfo-height-00888 282 if extent[0] > properties.max_framebuffer_width 283 || extent[1] > properties.max_framebuffer_height 284 { 285 return Err(FramebufferCreationError::MaxFramebufferExtentExceeded { 286 provided: extent, 287 max: [ 288 properties.max_framebuffer_width, 289 properties.max_framebuffer_height, 290 ], 291 }); 292 } 293 294 // VUID-VkFramebufferCreateInfo-layers-00890 295 if layers > properties.max_framebuffer_layers { 296 return Err(FramebufferCreationError::MaxFramebufferLayersExceeded { 297 provided: layers, 298 max: properties.max_framebuffer_layers, 299 }); 300 } 301 } 302 303 let create_info = ash::vk::FramebufferCreateInfo { 304 flags: ash::vk::FramebufferCreateFlags::empty(), 305 render_pass: render_pass.handle(), 306 attachment_count: attachments_vk.len() as u32, 307 p_attachments: attachments_vk.as_ptr(), 308 width: extent[0], 309 height: extent[1], 310 layers, 311 ..Default::default() 312 }; 313 314 let handle = unsafe { 315 let fns = device.fns(); 316 let mut output = MaybeUninit::uninit(); 317 (fns.v1_0.create_framebuffer)( 318 device.handle(), 319 &create_info, 320 ptr::null(), 321 output.as_mut_ptr(), 322 ) 323 .result() 324 .map_err(VulkanError::from)?; 325 output.assume_init() 326 }; 327 328 Ok(Arc::new(Framebuffer { 329 handle, 330 render_pass, 331 id: Self::next_id(), 332 attachments, 333 extent, 334 layers, 335 })) 336 } 337 338 /// Creates a new `Framebuffer` from a raw object handle. 339 /// 340 /// # Safety 341 /// 342 /// - `handle` must be a valid Vulkan object handle created from `render_pass`. 343 /// - `create_info` must match the info used to create the object. 344 #[inline] from_handle( render_pass: Arc<RenderPass>, handle: ash::vk::Framebuffer, create_info: FramebufferCreateInfo, ) -> Arc<Framebuffer>345 pub unsafe fn from_handle( 346 render_pass: Arc<RenderPass>, 347 handle: ash::vk::Framebuffer, 348 create_info: FramebufferCreateInfo, 349 ) -> Arc<Framebuffer> { 350 let FramebufferCreateInfo { 351 attachments, 352 extent, 353 layers, 354 _ne: _, 355 } = create_info; 356 357 Arc::new(Framebuffer { 358 handle, 359 render_pass, 360 id: Self::next_id(), 361 attachments, 362 extent, 363 layers, 364 }) 365 } 366 /// Returns the renderpass that was used to create this framebuffer. 367 #[inline] render_pass(&self) -> &Arc<RenderPass>368 pub fn render_pass(&self) -> &Arc<RenderPass> { 369 &self.render_pass 370 } 371 372 /// Returns the attachments of the framebuffer. 373 #[inline] attachments(&self) -> &[Arc<dyn ImageViewAbstract>]374 pub fn attachments(&self) -> &[Arc<dyn ImageViewAbstract>] { 375 &self.attachments 376 } 377 378 /// Returns the extent (width and height) of the framebuffer. 379 #[inline] extent(&self) -> [u32; 2]380 pub fn extent(&self) -> [u32; 2] { 381 self.extent 382 } 383 384 /// Returns the number of layers of the framebuffer. 385 #[inline] layers(&self) -> u32386 pub fn layers(&self) -> u32 { 387 self.layers 388 } 389 390 /// Returns the layer ranges for all attachments. 391 #[inline] attached_layers_ranges(&self) -> SmallVec<[Range<u32>; 4]>392 pub fn attached_layers_ranges(&self) -> SmallVec<[Range<u32>; 4]> { 393 self.attachments 394 .iter() 395 .map(|img| img.subresource_range().array_layers.clone()) 396 .collect() 397 } 398 } 399 400 impl Drop for Framebuffer { 401 #[inline] drop(&mut self)402 fn drop(&mut self) { 403 unsafe { 404 let fns = self.device().fns(); 405 (fns.v1_0.destroy_framebuffer)(self.device().handle(), self.handle, ptr::null()); 406 } 407 } 408 } 409 410 unsafe impl VulkanObject for Framebuffer { 411 type Handle = ash::vk::Framebuffer; 412 413 #[inline] handle(&self) -> Self::Handle414 fn handle(&self) -> Self::Handle { 415 self.handle 416 } 417 } 418 419 unsafe impl DeviceOwned for Framebuffer { 420 #[inline] device(&self) -> &Arc<Device>421 fn device(&self) -> &Arc<Device> { 422 self.render_pass.device() 423 } 424 } 425 426 impl_id_counter!(Framebuffer); 427 428 /// Parameters to create a new `Framebuffer`. 429 #[derive(Clone, Debug)] 430 pub struct FramebufferCreateInfo { 431 /// The attachment images that are to be used in the framebuffer. 432 /// 433 /// Attachments are specified in the same order as they are defined in the render pass, and 434 /// there must be exactly as many. This implies that the list must be empty if the render pass 435 /// specifies no attachments. Each image must have the correct usages set to be used for the 436 /// types of attachment that the render pass will use it as. 437 /// 438 /// The attachment images must not be smaller than `extent` and `layers`, but can be larger and 439 /// have different sizes from each other. Any leftover parts of an image will be left untouched 440 /// during rendering. 441 /// 442 /// If the render pass has multiview enabled (`views_used` does not return 0), then each 443 /// image must have at least `views_used` array layers. 444 /// 445 /// The default value is empty. 446 pub attachments: Vec<Arc<dyn ImageViewAbstract>>, 447 448 /// The extent (width and height) of the framebuffer. 449 /// 450 /// This must be no larger than the smallest width and height of the images in `attachments`. 451 /// If one of the elements is set to 0, the extent will be calculated automatically from the 452 /// extents of the attachment images to be the largest allowed. At least one attachment image 453 /// must be specified in that case. 454 /// 455 /// The extent, whether automatically calculated or specified explicitly, must not be larger 456 /// than the [`max_framebuffer_width`](crate::device::Properties::max_framebuffer_width) and 457 /// [`max_framebuffer_height`](crate::device::Properties::max_framebuffer_height) limits. 458 /// 459 /// The default value is `[0, 0]`. 460 pub extent: [u32; 2], 461 462 /// The number of layers of the framebuffer. 463 /// 464 /// This must be no larger than the smallest number of array layers of the images in 465 /// `attachments`. If set to 0, the number of layers will be calculated automatically from the 466 /// layer ranges of the attachment images to be the largest allowed. At least one attachment 467 /// image must be specified in that case. 468 /// 469 /// The number of layers, whether automatically calculated or specified explicitly, must not be 470 /// larger than the 471 /// [`max_framebuffer_layers`](crate::device::Properties::max_framebuffer_layers) limit. 472 /// 473 /// If the render pass has multiview enabled (`views_used` does not return 0), then this value 474 /// must be 0 or 1. 475 /// 476 /// The default value is `0`. 477 pub layers: u32, 478 479 pub _ne: crate::NonExhaustive, 480 } 481 482 impl Default for FramebufferCreateInfo { 483 #[inline] default() -> Self484 fn default() -> Self { 485 Self { 486 attachments: Vec::new(), 487 extent: [0, 0], 488 layers: 0, 489 _ne: crate::NonExhaustive(()), 490 } 491 } 492 } 493 494 /// Error that can happen when creating a `Framebuffer`. 495 #[derive(Copy, Clone, Debug)] 496 pub enum FramebufferCreationError { 497 /// Out of memory. 498 OomError(OomError), 499 500 /// An attachment image is a 2D image view created from a 3D image, and has a depth/stencil 501 /// format. 502 Attachment2dArrayCompatibleDepthStencil { attachment: u32 }, 503 504 /// An attachment image has a non-identity component mapping. 505 AttachmentComponentMappingNotIdentity { attachment: u32 }, 506 507 /// The number of attachments doesn't match the number expected by the render pass. 508 AttachmentCountMismatch { provided: u32, required: u32 }, 509 510 /// An attachment image has an extent smaller than the provided `extent`. 511 AttachmentExtentTooSmall { 512 attachment: u32, 513 provided: [u32; 2], 514 min: [u32; 2], 515 }, 516 517 /// An attachment image has a `format` different from what the render pass requires. 518 AttachmentFormatMismatch { 519 attachment: u32, 520 provided: Option<Format>, 521 required: Option<Format>, 522 }, 523 524 /// An attachment image is missing a usage that the render pass requires it to have. 525 AttachmentMissingUsage { 526 attachment: u32, 527 usage: &'static str, 528 }, 529 530 /// An attachment image has multiple mip levels. 531 AttachmentMultipleMipLevels { attachment: u32 }, 532 533 /// An attachment image has less array layers than the provided `layers`. 534 AttachmentNotEnoughLayers { 535 attachment: u32, 536 provided: u32, 537 min: u32, 538 }, 539 540 /// An attachment image has a `samples` different from what the render pass requires. 541 AttachmentSamplesMismatch { 542 attachment: u32, 543 provided: SampleCount, 544 required: SampleCount, 545 }, 546 547 /// An attachment image has a `ty` of [`ImageViewType::Dim3d`]. 548 AttachmentViewType3d { attachment: u32 }, 549 550 /// One of the elements of `extent` is zero, but no attachment images were given to calculate 551 /// the extent from. 552 AutoExtentAttachmentsEmpty, 553 554 /// `layers` is zero, but no attachment images were given to calculate the number of layers 555 /// from. 556 AutoLayersAttachmentsEmpty, 557 558 /// The provided `extent` exceeds the `max_framebuffer_width` or `max_framebuffer_height` 559 /// limits. 560 MaxFramebufferExtentExceeded { provided: [u32; 2], max: [u32; 2] }, 561 562 /// The provided `layers` exceeds the `max_framebuffer_layers` limit. 563 MaxFramebufferLayersExceeded { provided: u32, max: u32 }, 564 565 /// The render pass has multiview enabled, and an attachment image has less layers than the 566 /// number of views in the render pass. 567 MultiviewAttachmentNotEnoughLayers { 568 attachment: u32, 569 provided: u32, 570 min: u32, 571 }, 572 573 /// The render pass has multiview enabled, but `layers` was not 0 or 1. 574 MultiviewLayersInvalid, 575 } 576 577 impl From<OomError> for FramebufferCreationError { from(err: OomError) -> Self578 fn from(err: OomError) -> Self { 579 Self::OomError(err) 580 } 581 } 582 583 impl Error for FramebufferCreationError { source(&self) -> Option<&(dyn Error + 'static)>584 fn source(&self) -> Option<&(dyn Error + 'static)> { 585 match self { 586 Self::OomError(err) => Some(err), 587 _ => None, 588 } 589 } 590 } 591 592 impl Display for FramebufferCreationError { fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError>593 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { 594 match self { 595 Self::OomError(_) => write!(f, "no memory available",), 596 Self::Attachment2dArrayCompatibleDepthStencil { attachment } => write!( 597 f, 598 "attachment image {} is a 2D image view created from a 3D image, and has a \ 599 depth/stencil format", 600 attachment, 601 ), 602 Self::AttachmentComponentMappingNotIdentity { attachment } => write!( 603 f, 604 "attachment image {} has a non-identity component mapping", 605 attachment, 606 ), 607 Self::AttachmentCountMismatch { .. } => write!( 608 f, 609 "the number of attachments doesn't match the number expected by the render pass", 610 ), 611 Self::AttachmentExtentTooSmall { 612 attachment, 613 provided, 614 min, 615 } => write!( 616 f, 617 "attachment image {} has an extent ({:?}) smaller than the provided `extent` \ 618 ({:?})", 619 attachment, provided, min, 620 ), 621 Self::AttachmentFormatMismatch { 622 attachment, 623 provided, 624 required, 625 } => write!( 626 f, 627 "attachment image {} has a `format` ({:?}) different from what the render pass \ 628 requires ({:?})", 629 attachment, provided, required, 630 ), 631 Self::AttachmentMissingUsage { attachment, usage } => write!( 632 f, 633 "attachment image {} is missing usage `{}` that the render pass requires it to \ 634 have", 635 attachment, usage, 636 ), 637 Self::AttachmentMultipleMipLevels { attachment } => { 638 write!(f, "attachment image {} has multiple mip levels", attachment) 639 } 640 Self::AttachmentNotEnoughLayers { 641 attachment, 642 provided, 643 min, 644 } => write!( 645 f, 646 "attachment image {} has less layers ({}) than the provided `layers` ({})", 647 attachment, provided, min, 648 ), 649 Self::AttachmentSamplesMismatch { 650 attachment, 651 provided, 652 required, 653 } => write!( 654 f, 655 "attachment image {} has a `samples` ({:?}) different from what the render pass \ 656 requires ({:?})", 657 attachment, provided, required, 658 ), 659 Self::AttachmentViewType3d { attachment } => write!( 660 f, 661 "attachment image {} has a `ty` of `ImageViewType::Dim3d`", 662 attachment, 663 ), 664 Self::AutoExtentAttachmentsEmpty => write!( 665 f, 666 "one of the elements of `extent` is zero, but no attachment images were given to \ 667 calculate the extent from", 668 ), 669 Self::AutoLayersAttachmentsEmpty => write!( 670 f, 671 "`layers` is zero, but no attachment images were given to calculate the number of \ 672 layers from", 673 ), 674 Self::MaxFramebufferExtentExceeded { provided, max } => write!( 675 f, 676 "the provided `extent` ({:?}) exceeds the `max_framebuffer_width` or \ 677 `max_framebuffer_height` limits ({:?})", 678 provided, max, 679 ), 680 Self::MaxFramebufferLayersExceeded { provided, max } => write!( 681 f, 682 "the provided `layers` ({}) exceeds the `max_framebuffer_layers` limit ({})", 683 provided, max, 684 ), 685 Self::MultiviewAttachmentNotEnoughLayers { 686 attachment, 687 provided, 688 min, 689 } => write!( 690 f, 691 "the render pass has multiview enabled, and attachment image {} has less layers \ 692 ({}) than the number of views in the render pass ({})", 693 attachment, provided, min, 694 ), 695 Self::MultiviewLayersInvalid => write!( 696 f, 697 "the render pass has multiview enabled, but `layers` was not 0 or 1", 698 ), 699 } 700 } 701 } 702 703 impl From<VulkanError> for FramebufferCreationError { from(err: VulkanError) -> Self704 fn from(err: VulkanError) -> Self { 705 Self::from(OomError::from(err)) 706 } 707 } 708 709 #[cfg(test)] 710 mod tests { 711 use crate::{ 712 format::Format, 713 image::{attachment::AttachmentImage, view::ImageView}, 714 memory::allocator::StandardMemoryAllocator, 715 render_pass::{Framebuffer, FramebufferCreateInfo, FramebufferCreationError, RenderPass}, 716 }; 717 718 #[test] simple_create()719 fn simple_create() { 720 let (device, _) = gfx_dev_and_queue!(); 721 722 let render_pass = single_pass_renderpass!( 723 device.clone(), 724 attachments: { 725 color: { 726 load: Clear, 727 store: DontCare, 728 format: Format::R8G8B8A8_UNORM, 729 samples: 1, 730 }, 731 }, 732 pass: { 733 color: [color], 734 depth_stencil: {}, 735 }, 736 ) 737 .unwrap(); 738 739 let memory_allocator = StandardMemoryAllocator::new_default(device); 740 let view = ImageView::new_default( 741 AttachmentImage::new(&memory_allocator, [1024, 768], Format::R8G8B8A8_UNORM).unwrap(), 742 ) 743 .unwrap(); 744 let _ = Framebuffer::new( 745 render_pass, 746 FramebufferCreateInfo { 747 attachments: vec![view], 748 ..Default::default() 749 }, 750 ) 751 .unwrap(); 752 } 753 754 #[test] check_device_limits()755 fn check_device_limits() { 756 let (device, _) = gfx_dev_and_queue!(); 757 758 let render_pass = RenderPass::empty_single_pass(device).unwrap(); 759 let res = Framebuffer::new( 760 render_pass.clone(), 761 FramebufferCreateInfo { 762 extent: [0xffffffff, 0xffffffff], 763 layers: 1, 764 ..Default::default() 765 }, 766 ); 767 match res { 768 Err(FramebufferCreationError::MaxFramebufferExtentExceeded { .. }) => (), 769 _ => panic!(), 770 } 771 772 let res = Framebuffer::new( 773 render_pass, 774 FramebufferCreateInfo { 775 extent: [1, 1], 776 layers: 0xffffffff, 777 ..Default::default() 778 }, 779 ); 780 781 match res { 782 Err(FramebufferCreationError::MaxFramebufferLayersExceeded { .. }) => (), 783 _ => panic!(), 784 } 785 } 786 787 #[test] attachment_format_mismatch()788 fn attachment_format_mismatch() { 789 let (device, _) = gfx_dev_and_queue!(); 790 791 let render_pass = single_pass_renderpass!( 792 device.clone(), 793 attachments: { 794 color: { 795 load: Clear, 796 store: DontCare, 797 format: Format::R8G8B8A8_UNORM, 798 samples: 1, 799 }, 800 }, 801 pass: { 802 color: [color], 803 depth_stencil: {}, 804 }, 805 ) 806 .unwrap(); 807 808 let memory_allocator = StandardMemoryAllocator::new_default(device); 809 let view = ImageView::new_default( 810 AttachmentImage::new(&memory_allocator, [1024, 768], Format::R8_UNORM).unwrap(), 811 ) 812 .unwrap(); 813 814 match Framebuffer::new( 815 render_pass, 816 FramebufferCreateInfo { 817 attachments: vec![view], 818 ..Default::default() 819 }, 820 ) { 821 Err(FramebufferCreationError::AttachmentFormatMismatch { .. }) => (), 822 _ => panic!(), 823 } 824 } 825 826 // TODO: check samples mismatch 827 828 #[test] attachment_dims_larger_than_specified_valid()829 fn attachment_dims_larger_than_specified_valid() { 830 let (device, _) = gfx_dev_and_queue!(); 831 832 let render_pass = single_pass_renderpass!( 833 device.clone(), 834 attachments: { 835 color: { 836 load: Clear, 837 store: DontCare, 838 format: Format::R8G8B8A8_UNORM, 839 samples: 1, 840 }, 841 }, 842 pass: { 843 color: [color], 844 depth_stencil: {}, 845 }, 846 ) 847 .unwrap(); 848 849 let memory_allocator = StandardMemoryAllocator::new_default(device); 850 let view = ImageView::new_default( 851 AttachmentImage::new(&memory_allocator, [600, 600], Format::R8G8B8A8_UNORM).unwrap(), 852 ) 853 .unwrap(); 854 855 let _ = Framebuffer::new( 856 render_pass, 857 FramebufferCreateInfo { 858 attachments: vec![view], 859 extent: [512, 512], 860 layers: 1, 861 ..Default::default() 862 }, 863 ) 864 .unwrap(); 865 } 866 867 #[test] attachment_dims_smaller_than_specified()868 fn attachment_dims_smaller_than_specified() { 869 let (device, _) = gfx_dev_and_queue!(); 870 871 let render_pass = single_pass_renderpass!( 872 device.clone(), 873 attachments: { 874 color: { 875 load: Clear, 876 store: DontCare, 877 format: Format::R8G8B8A8_UNORM, 878 samples: 1, 879 }, 880 }, 881 pass: { 882 color: [color], 883 depth_stencil: {}, 884 }, 885 ) 886 .unwrap(); 887 888 let memory_allocator = StandardMemoryAllocator::new_default(device); 889 let view = ImageView::new_default( 890 AttachmentImage::new(&memory_allocator, [512, 700], Format::R8G8B8A8_UNORM).unwrap(), 891 ) 892 .unwrap(); 893 894 match Framebuffer::new( 895 render_pass, 896 FramebufferCreateInfo { 897 attachments: vec![view], 898 extent: [600, 600], 899 layers: 1, 900 ..Default::default() 901 }, 902 ) { 903 Err(FramebufferCreationError::AttachmentExtentTooSmall { .. }) => (), 904 _ => panic!(), 905 } 906 } 907 908 #[test] multi_attachments_auto_smaller()909 fn multi_attachments_auto_smaller() { 910 let (device, _) = gfx_dev_and_queue!(); 911 912 let render_pass = single_pass_renderpass!( 913 device.clone(), 914 attachments: { 915 a: { 916 load: Clear, 917 store: DontCare, 918 format: Format::R8G8B8A8_UNORM, 919 samples: 1, 920 }, 921 b: { 922 load: Clear, 923 store: DontCare, 924 format: Format::R8G8B8A8_UNORM, 925 samples: 1, 926 }, 927 }, 928 pass: { 929 color: [a, b], 930 depth_stencil: {}, 931 }, 932 ) 933 .unwrap(); 934 935 let memory_allocator = StandardMemoryAllocator::new_default(device); 936 let a = ImageView::new_default( 937 AttachmentImage::new(&memory_allocator, [256, 512], Format::R8G8B8A8_UNORM).unwrap(), 938 ) 939 .unwrap(); 940 let b = ImageView::new_default( 941 AttachmentImage::new(&memory_allocator, [512, 128], Format::R8G8B8A8_UNORM).unwrap(), 942 ) 943 .unwrap(); 944 945 let framebuffer = Framebuffer::new( 946 render_pass, 947 FramebufferCreateInfo { 948 attachments: vec![a, b], 949 ..Default::default() 950 }, 951 ) 952 .unwrap(); 953 954 match (framebuffer.extent(), framebuffer.layers()) { 955 ([256, 128], 1) => (), 956 _ => panic!(), 957 } 958 } 959 960 #[test] not_enough_attachments()961 fn not_enough_attachments() { 962 let (device, _) = gfx_dev_and_queue!(); 963 964 let render_pass = single_pass_renderpass!( 965 device.clone(), 966 attachments: { 967 a: { 968 load: Clear, 969 store: DontCare, 970 format: Format::R8G8B8A8_UNORM, 971 samples: 1, 972 }, 973 b: { 974 load: Clear, 975 store: DontCare, 976 format: Format::R8G8B8A8_UNORM, 977 samples: 1, 978 }, 979 }, 980 pass: { 981 color: [a, b], 982 depth_stencil: {}, 983 }, 984 ) 985 .unwrap(); 986 987 let memory_allocator = StandardMemoryAllocator::new_default(device); 988 let view = ImageView::new_default( 989 AttachmentImage::new(&memory_allocator, [256, 512], Format::R8G8B8A8_UNORM).unwrap(), 990 ) 991 .unwrap(); 992 993 let res = Framebuffer::new( 994 render_pass, 995 FramebufferCreateInfo { 996 attachments: vec![view], 997 ..Default::default() 998 }, 999 ); 1000 1001 match res { 1002 Err(FramebufferCreationError::AttachmentCountMismatch { 1003 required: 2, 1004 provided: 1, 1005 }) => (), 1006 _ => panic!(), 1007 } 1008 } 1009 1010 #[test] too_many_attachments()1011 fn too_many_attachments() { 1012 let (device, _) = gfx_dev_and_queue!(); 1013 1014 let render_pass = single_pass_renderpass!( 1015 device.clone(), 1016 attachments: { 1017 a: { 1018 load: Clear, 1019 store: DontCare, 1020 format: Format::R8G8B8A8_UNORM, 1021 samples: 1, 1022 }, 1023 }, 1024 pass: { 1025 color: [a], 1026 depth_stencil: {}, 1027 }, 1028 ) 1029 .unwrap(); 1030 1031 let memory_allocator = StandardMemoryAllocator::new_default(device); 1032 let a = ImageView::new_default( 1033 AttachmentImage::new(&memory_allocator, [256, 512], Format::R8G8B8A8_UNORM).unwrap(), 1034 ) 1035 .unwrap(); 1036 let b = ImageView::new_default( 1037 AttachmentImage::new(&memory_allocator, [256, 512], Format::R8G8B8A8_UNORM).unwrap(), 1038 ) 1039 .unwrap(); 1040 1041 let res = Framebuffer::new( 1042 render_pass, 1043 FramebufferCreateInfo { 1044 attachments: vec![a, b], 1045 ..Default::default() 1046 }, 1047 ); 1048 1049 match res { 1050 Err(FramebufferCreationError::AttachmentCountMismatch { 1051 required: 1, 1052 provided: 2, 1053 }) => (), 1054 _ => panic!(), 1055 } 1056 } 1057 1058 #[test] empty_working()1059 fn empty_working() { 1060 let (device, _) = gfx_dev_and_queue!(); 1061 1062 let render_pass = RenderPass::empty_single_pass(device).unwrap(); 1063 let _ = Framebuffer::new( 1064 render_pass, 1065 FramebufferCreateInfo { 1066 extent: [512, 512], 1067 layers: 1, 1068 ..Default::default() 1069 }, 1070 ) 1071 .unwrap(); 1072 } 1073 1074 #[test] cant_determine_dimensions_auto()1075 fn cant_determine_dimensions_auto() { 1076 let (device, _) = gfx_dev_and_queue!(); 1077 1078 let render_pass = RenderPass::empty_single_pass(device).unwrap(); 1079 let res = Framebuffer::new(render_pass, FramebufferCreateInfo::default()); 1080 match res { 1081 Err(FramebufferCreationError::AutoExtentAttachmentsEmpty) => (), 1082 _ => panic!(), 1083 } 1084 } 1085 } 1086