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