// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use crate::check_errors;
use crate::device::Device;
use crate::device::DeviceOwned;
use crate::image::view::ImageViewAbstract;
use crate::render_pass::ensure_image_view_compatible;
use crate::render_pass::AttachmentsList;
use crate::render_pass::IncompatibleRenderPassAttachmentError;
use crate::render_pass::RenderPass;
use crate::Error;
use crate::OomError;
use crate::SafeDeref;
use crate::VulkanObject;
use smallvec::SmallVec;
use std::cmp;
use std::error;
use std::fmt;
use std::marker::PhantomData;
use std::mem::MaybeUninit;
use std::ptr;
use std::sync::Arc;

/// The image views that are attached to a render pass during drawing.
///
/// A framebuffer is a collection of images, and supplies the actual inputs and outputs of each
/// subpass within a render pass. It is created from a subpass and must match it: each attachment
/// point in the subpass must have a matching image in the framebuffer.
///
/// Creating a framebuffer is done by calling `Framebuffer::start`, which returns a
/// `FramebufferBuilder` object. You can then add the framebuffer attachments one by one by
/// calling `add(image)`. When you are done, call `build()`.
///
/// Both the `add` and the `build` functions perform various checks to make sure that the number
/// of images is correct and that each image is compatible with the attachment definition in the
/// render pass.
///
/// ```
/// # use std::sync::Arc;
/// # use vulkano::render_pass::RenderPass;
/// use vulkano::render_pass::Framebuffer;
///
/// # let render_pass: Arc<RenderPass> = return;
/// # let view: Arc<vulkano::image::view::ImageView<Arc<vulkano::image::AttachmentImage<vulkano::format::Format>>>> = return;
/// // let render_pass: Arc<_> = ...;
/// let framebuffer = Framebuffer::start(render_pass.clone())
///     .add(view).unwrap()
///     .build().unwrap();
/// ```
///
/// All framebuffer objects implement the `FramebufferAbstract` trait. This means that you can cast
/// any `Arc<Framebuffer<..>>` into an `Arc<FramebufferAbstract + Send + Sync>` for easier storage.
///
/// ## Framebuffer dimensions
///
/// If you use `Framebuffer::start()` to create a framebuffer then vulkano will automatically
/// make sure that all the attachments have the same dimensions, as this is the most common
/// situation.
///
/// Alternatively you can also use `with_intersecting_dimensions`, in which case the dimensions of
/// the framebuffer will be the intersection of the dimensions of all attachments, or
/// `with_dimensions` if you want to specify exact dimensions. If you use `with_dimensions`, you
/// are allowed to attach images that are larger than these dimensions.
///
/// If the dimensions of the framebuffer don't match the dimensions of one of its attachment, then
/// only the top-left hand corner of the image will be drawn to.
///
#[derive(Debug)]
pub struct Framebuffer<A> {
    device: Arc<Device>,
    render_pass: Arc<RenderPass>,
    framebuffer: ash::vk::Framebuffer,
    dimensions: [u32; 3],
    resources: A,
}

impl Framebuffer<()> {
    /// Starts building a framebuffer.
    pub fn start(render_pass: Arc<RenderPass>) -> FramebufferBuilder<()> {
        FramebufferBuilder {
            render_pass,
            raw_ids: SmallVec::new(),
            dimensions: FramebufferBuilderDimensions::AutoIdentical(None),
            attachments: (),
        }
    }

    /// Starts building a framebuffer. The dimensions of the framebuffer will automatically be
    /// the intersection of the dimensions of all the attachments.
    pub fn with_intersecting_dimensions(render_pass: Arc<RenderPass>) -> FramebufferBuilder<()> {
        FramebufferBuilder {
            render_pass,
            raw_ids: SmallVec::new(),
            dimensions: FramebufferBuilderDimensions::AutoSmaller(None),
            attachments: (),
        }
    }

    /// Starts building a framebuffer.
    pub fn with_dimensions(
        render_pass: Arc<RenderPass>,
        dimensions: [u32; 3],
    ) -> FramebufferBuilder<()> {
        FramebufferBuilder {
            render_pass,
            raw_ids: SmallVec::new(),
            dimensions: FramebufferBuilderDimensions::Specific(dimensions),
            attachments: (),
        }
    }
}

/// Prototype of a framebuffer.
pub struct FramebufferBuilder<A> {
    render_pass: Arc<RenderPass>,
    raw_ids: SmallVec<[ash::vk::ImageView; 8]>,
    dimensions: FramebufferBuilderDimensions,
    attachments: A,
}

impl<A> fmt::Debug for FramebufferBuilder<A>
where
    A: fmt::Debug,
{
    #[inline]
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        fmt.debug_struct("FramebufferBuilder")
            .field("render_pass", &self.render_pass)
            .field("dimensions", &self.dimensions)
            .field("attachments", &self.attachments)
            .finish()
    }
}

#[derive(Debug)]
enum FramebufferBuilderDimensions {
    AutoIdentical(Option<[u32; 3]>),
    AutoSmaller(Option<[u32; 3]>),
    Specific([u32; 3]),
}

impl<A> FramebufferBuilder<A>
where
    A: AttachmentsList,
{
    /// Appends an attachment to the prototype of the framebuffer.
    ///
    /// Attachments must be added in the same order as the one defined in the render pass.
    pub fn add<T>(
        self,
        attachment: T,
    ) -> Result<FramebufferBuilder<(A, T)>, FramebufferCreationError>
    where
        T: ImageViewAbstract,
    {
        if self.raw_ids.len() >= self.render_pass.desc().attachments().len() {
            return Err(FramebufferCreationError::AttachmentsCountMismatch {
                expected: self.render_pass.desc().attachments().len(),
                obtained: self.raw_ids.len() + 1,
            });
        }

        match ensure_image_view_compatible(self.render_pass.desc(), self.raw_ids.len(), &attachment)
        {
            Ok(()) => (),
            Err(err) => return Err(FramebufferCreationError::IncompatibleAttachment(err)),
        };

        let image_dimensions = attachment.image().dimensions();
        let array_layers = attachment.array_layers();
        debug_assert_eq!(image_dimensions.depth(), 1);

        let view_dimensions = [
            image_dimensions.width(),
            image_dimensions.height(),
            array_layers.end - array_layers.start,
        ];

        let dimensions = match self.dimensions {
            FramebufferBuilderDimensions::AutoIdentical(None) => {
                FramebufferBuilderDimensions::AutoIdentical(Some(view_dimensions))
            }
            FramebufferBuilderDimensions::AutoIdentical(Some(current)) => {
                if view_dimensions != current {
                    return Err(FramebufferCreationError::AttachmentDimensionsIncompatible {
                        expected: current,
                        obtained: view_dimensions,
                    });
                }

                FramebufferBuilderDimensions::AutoIdentical(Some(current))
            }
            FramebufferBuilderDimensions::AutoSmaller(None) => {
                FramebufferBuilderDimensions::AutoSmaller(Some(view_dimensions))
            }
            FramebufferBuilderDimensions::AutoSmaller(Some(current)) => {
                let new_dims = [
                    cmp::min(current[0], view_dimensions[0]),
                    cmp::min(current[1], view_dimensions[1]),
                    cmp::min(current[2], view_dimensions[2]),
                ];

                FramebufferBuilderDimensions::AutoSmaller(Some(new_dims))
            }
            FramebufferBuilderDimensions::Specific(current) => {
                if view_dimensions[0] < current[0]
                    || view_dimensions[1] < current[1]
                    || view_dimensions[2] < current[2]
                {
                    return Err(FramebufferCreationError::AttachmentDimensionsIncompatible {
                        expected: current,
                        obtained: view_dimensions,
                    });
                }

                FramebufferBuilderDimensions::Specific(view_dimensions)
            }
        };

        let mut raw_ids = self.raw_ids;
        raw_ids.push(attachment.inner().internal_object());

        Ok(FramebufferBuilder {
            render_pass: self.render_pass,
            raw_ids,
            dimensions,
            attachments: (self.attachments, attachment),
        })
    }

    /// Turns this builder into a `FramebufferBuilder<Rp, Box<AttachmentsList>>`.
    ///
    /// This allows you to store the builder in situations where you don't know in advance the
    /// number of attachments.
    ///
    /// > **Note**: This is a very rare corner case and you shouldn't have to use this function
    /// > in most situations.
    #[inline]
    pub fn boxed(self) -> FramebufferBuilder<Box<dyn AttachmentsList>>
    where
        A: 'static,
    {
        FramebufferBuilder {
            render_pass: self.render_pass,
            raw_ids: self.raw_ids,
            dimensions: self.dimensions,
            attachments: Box::new(self.attachments) as Box<_>,
        }
    }

    /// Builds the framebuffer.
    pub fn build(self) -> Result<Framebuffer<A>, FramebufferCreationError> {
        let device = self.render_pass.device().clone();

        // Check the number of attachments.
        if self.raw_ids.len() != self.render_pass.desc().attachments().len() {
            return Err(FramebufferCreationError::AttachmentsCountMismatch {
                expected: self.render_pass.desc().attachments().len(),
                obtained: self.raw_ids.len(),
            });
        }

        // Compute the dimensions.
        let dimensions = match self.dimensions {
            FramebufferBuilderDimensions::Specific(dims)
            | FramebufferBuilderDimensions::AutoIdentical(Some(dims))
            | FramebufferBuilderDimensions::AutoSmaller(Some(dims)) => dims,
            FramebufferBuilderDimensions::AutoIdentical(None)
            | FramebufferBuilderDimensions::AutoSmaller(None) => {
                return Err(FramebufferCreationError::CantDetermineDimensions);
            }
        };

        // Checking the dimensions against the limits.
        {
            let properties = device.physical_device().properties();
            let limits = [
                properties.max_framebuffer_width,
                properties.max_framebuffer_height,
                properties.max_framebuffer_layers,
            ];
            if dimensions[0] > limits[0] || dimensions[1] > limits[1] || dimensions[2] > limits[2] {
                return Err(FramebufferCreationError::DimensionsTooLarge);
            }
        }

        let mut layers = 1;

        if let Some(multiview) = self.render_pass.desc().multiview() {
            // There needs to be at least as many layers in the framebuffer
            // as the highest layer that gets referenced by the multiview masking.
            if multiview.highest_used_layer() > dimensions[2] {
                return Err(FramebufferCreationError::InsufficientLayerCount {
                    minimum: multiview.highest_used_layer(),
                    current: dimensions[2],
                });
            }

            // VUID-VkFramebufferCreateInfo-renderPass-02531
            // The framebuffer has to be created with one layer if multiview is enabled even though
            // the underlying images generally have more layers
            // but these layers get used by the multiview functionality.
            if multiview.view_masks.iter().any(|&mask| mask != 0) {
                layers = 1;
            }
        }

        let framebuffer = unsafe {
            let fns = device.fns();

            let infos = ash::vk::FramebufferCreateInfo {
                flags: ash::vk::FramebufferCreateFlags::empty(),
                render_pass: self.render_pass.inner().internal_object(),
                attachment_count: self.raw_ids.len() as u32,
                p_attachments: self.raw_ids.as_ptr(),
                width: dimensions[0],
                height: dimensions[1],
                layers,
                ..Default::default()
            };

            let mut output = MaybeUninit::uninit();
            check_errors(fns.v1_0.create_framebuffer(
                device.internal_object(),
                &infos,
                ptr::null(),
                output.as_mut_ptr(),
            ))?;
            output.assume_init()
        };

        Ok(Framebuffer {
            device,
            render_pass: self.render_pass,
            framebuffer,
            dimensions,
            resources: self.attachments,
        })
    }
}

impl<A> Framebuffer<A> {
    /// Returns the width, height and layers of this framebuffer.
    #[inline]
    pub fn dimensions(&self) -> [u32; 3] {
        self.dimensions
    }

    /// Returns the width of the framebuffer in pixels.
    #[inline]
    pub fn width(&self) -> u32 {
        self.dimensions[0]
    }

    /// Returns the height of the framebuffer in pixels.
    #[inline]
    pub fn height(&self) -> u32 {
        self.dimensions[1]
    }

    /// Returns the number of layers (or depth) of the framebuffer.
    #[inline]
    pub fn layers(&self) -> u32 {
        self.dimensions[2]
    }

    /// Returns the device that was used to create this framebuffer.
    #[inline]
    pub fn device(&self) -> &Arc<Device> {
        &self.device
    }

    /// Returns the renderpass that was used to create this framebuffer.
    #[inline]
    pub fn render_pass(&self) -> &Arc<RenderPass> {
        &self.render_pass
    }
}

/// Trait for objects that contain a Vulkan framebuffer object.
///
/// Any `Framebuffer` object implements this trait. You can therefore turn a `Arc<Framebuffer<_>>`
/// into a `Arc<FramebufferAbstract + Send + Sync>` for easier storage.
pub unsafe trait FramebufferAbstract {
    /// Returns an opaque struct that represents the framebuffer's internals.
    fn inner(&self) -> FramebufferSys;

    /// Returns the width, height and array layers of the framebuffer.
    fn dimensions(&self) -> [u32; 3];

    /// Returns the render pass this framebuffer was created for.
    fn render_pass(&self) -> &Arc<RenderPass>;

    /// Returns the attachment of the framebuffer with the given index.
    ///
    /// If the `index` is not between `0` and `num_attachments`, then `None` should be returned.
    fn attached_image_view(&self, index: usize) -> Option<&dyn ImageViewAbstract>;

    /// Returns the width of the framebuffer in pixels.
    #[inline]
    fn width(&self) -> u32 {
        self.dimensions()[0]
    }

    /// Returns the height of the framebuffer in pixels.
    #[inline]
    fn height(&self) -> u32 {
        self.dimensions()[1]
    }

    /// Returns the number of layers (or depth) of the framebuffer.
    #[inline]
    fn layers(&self) -> u32 {
        self.dimensions()[2]
    }
}

unsafe impl<T> FramebufferAbstract for T
where
    T: SafeDeref,
    T::Target: FramebufferAbstract,
{
    #[inline]
    fn inner(&self) -> FramebufferSys {
        FramebufferAbstract::inner(&**self)
    }

    #[inline]
    fn dimensions(&self) -> [u32; 3] {
        (**self).dimensions()
    }

    #[inline]
    fn render_pass(&self) -> &Arc<RenderPass> {
        (**self).render_pass()
    }

    #[inline]
    fn attached_image_view(&self, index: usize) -> Option<&dyn ImageViewAbstract> {
        (**self).attached_image_view(index)
    }
}

unsafe impl<A> FramebufferAbstract for Framebuffer<A>
where
    A: AttachmentsList,
{
    #[inline]
    fn inner(&self) -> FramebufferSys {
        FramebufferSys(self.framebuffer, PhantomData)
    }

    #[inline]
    fn dimensions(&self) -> [u32; 3] {
        self.dimensions
    }

    #[inline]
    fn render_pass(&self) -> &Arc<RenderPass> {
        &self.render_pass
    }

    #[inline]
    fn attached_image_view(&self, index: usize) -> Option<&dyn ImageViewAbstract> {
        self.resources.as_image_view_access(index)
    }
}

unsafe impl<A> DeviceOwned for Framebuffer<A> {
    #[inline]
    fn device(&self) -> &Arc<Device> {
        &self.device
    }
}

impl<A> Drop for Framebuffer<A> {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            let fns = self.device.fns();
            fns.v1_0.destroy_framebuffer(
                self.device.internal_object(),
                self.framebuffer,
                ptr::null(),
            );
        }
    }
}

/// Opaque object that represents the internals of a framebuffer.
#[derive(Debug, Copy, Clone)]
pub struct FramebufferSys<'a>(ash::vk::Framebuffer, PhantomData<&'a ()>);

unsafe impl<'a> VulkanObject for FramebufferSys<'a> {
    type Object = ash::vk::Framebuffer;

    #[inline]
    fn internal_object(&self) -> ash::vk::Framebuffer {
        self.0
    }
}

/// Error that can happen when creating a framebuffer object.
#[derive(Copy, Clone, Debug)]
pub enum FramebufferCreationError {
    /// Out of memory.
    OomError(OomError),
    /// The requested dimensions exceed the device's limits.
    DimensionsTooLarge,
    /// The number of minimum layers expected by the render pass exceed the framebuffer layers.
    /// This can happen when the multiview feature is enabled and the specified view or correlation
    /// masks refer to more layers than the framebuffer has.
    InsufficientLayerCount {
        /// Minimum number of layers.
        minimum: u32,
        /// Number of framebuffer layers.
        current: u32,
    },
    /// The attachment has a size that isn't compatible with the requested framebuffer dimensions.
    AttachmentDimensionsIncompatible {
        /// Expected dimensions.
        expected: [u32; 3],
        /// Attachment dimensions.
        obtained: [u32; 3],
    },
    /// The number of attachments doesn't match the number expected by the render pass.
    AttachmentsCountMismatch {
        /// Expected number of attachments.
        expected: usize,
        /// Number of attachments that were given.
        obtained: usize,
    },
    /// One of the images cannot be used as the requested attachment.
    IncompatibleAttachment(IncompatibleRenderPassAttachmentError),
    /// The framebuffer has no attachment and no dimension was specified.
    CantDetermineDimensions,
}

impl From<OomError> for FramebufferCreationError {
    #[inline]
    fn from(err: OomError) -> FramebufferCreationError {
        FramebufferCreationError::OomError(err)
    }
}

impl error::Error for FramebufferCreationError {
    #[inline]
    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
        match *self {
            FramebufferCreationError::OomError(ref err) => Some(err),
            FramebufferCreationError::IncompatibleAttachment(ref err) => Some(err),
            _ => None,
        }
    }
}

impl fmt::Display for FramebufferCreationError {
    #[inline]
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(
            fmt,
            "{}",
            match *self {
                FramebufferCreationError::OomError(_) => "no memory available",
                FramebufferCreationError::DimensionsTooLarge => {
                    "the dimensions of the framebuffer are too large"
                }
                FramebufferCreationError::InsufficientLayerCount { .. } => {
                    "the number of minimum layers expected by the render pass exceed the framebuffer layers"
                }
                FramebufferCreationError::AttachmentDimensionsIncompatible { .. } => {
                    "the attachment has a size that isn't compatible with the framebuffer dimensions"
                }
                FramebufferCreationError::AttachmentsCountMismatch { .. } => {
                    "the number of attachments doesn't match the number expected by the render pass"
                }
                FramebufferCreationError::IncompatibleAttachment(_) => {
                    "one of the images cannot be used as the requested attachment"
                }
                FramebufferCreationError::CantDetermineDimensions => {
                    "the framebuffer has no attachment and no dimension was specified"
                }
            }
        )
    }
}

impl From<Error> for FramebufferCreationError {
    #[inline]
    fn from(err: Error) -> FramebufferCreationError {
        FramebufferCreationError::from(OomError::from(err))
    }
}

#[cfg(test)]
mod tests {
    use crate::format::Format;
    use crate::image::attachment::AttachmentImage;
    use crate::image::view::ImageView;
    use crate::render_pass::Framebuffer;
    use crate::render_pass::FramebufferCreationError;
    use crate::render_pass::RenderPass;
    use std::sync::Arc;

    #[test]
    fn simple_create() {
        let (device, _) = gfx_dev_and_queue!();

        let render_pass = Arc::new(
            single_pass_renderpass!(device.clone(),
                attachments: {
                    color: {
                        load: Clear,
                        store: DontCare,
                        format: Format::R8G8B8A8Unorm,
                        samples: 1,
                    }
                },
                pass: {
                    color: [color],
                    depth_stencil: {}
                }
            )
            .unwrap(),
        );

        let view = ImageView::new(
            AttachmentImage::new(device.clone(), [1024, 768], Format::R8G8B8A8Unorm).unwrap(),
        )
        .unwrap();
        let _ = Framebuffer::start(render_pass)
            .add(view)
            .unwrap()
            .build()
            .unwrap();
    }

    #[test]
    fn check_device_limits() {
        let (device, _) = gfx_dev_and_queue!();

        let rp = Arc::new(RenderPass::empty_single_pass(device).unwrap());
        let res = Framebuffer::with_dimensions(rp, [0xffffffff, 0xffffffff, 0xffffffff]).build();
        match res {
            Err(FramebufferCreationError::DimensionsTooLarge) => (),
            _ => panic!(),
        }
    }

    #[test]
    fn attachment_format_mismatch() {
        let (device, _) = gfx_dev_and_queue!();

        let render_pass = Arc::new(
            single_pass_renderpass!(device.clone(),
                attachments: {
                    color: {
                        load: Clear,
                        store: DontCare,
                        format: Format::R8G8B8A8Unorm,
                        samples: 1,
                    }
                },
                pass: {
                    color: [color],
                    depth_stencil: {}
                }
            )
            .unwrap(),
        );

        let view = ImageView::new(
            AttachmentImage::new(device.clone(), [1024, 768], Format::R8Unorm).unwrap(),
        )
        .unwrap();

        match Framebuffer::start(render_pass).add(view) {
            Err(FramebufferCreationError::IncompatibleAttachment(_)) => (),
            _ => panic!(),
        }
    }

    // TODO: check samples mismatch

    #[test]
    fn attachment_dims_larger_than_specified_valid() {
        let (device, _) = gfx_dev_and_queue!();

        let render_pass = Arc::new(
            single_pass_renderpass!(device.clone(),
                attachments: {
                    color: {
                        load: Clear,
                        store: DontCare,
                        format: Format::R8G8B8A8Unorm,
                        samples: 1,
                    }
                },
                pass: {
                    color: [color],
                    depth_stencil: {}
                }
            )
            .unwrap(),
        );

        let view = ImageView::new(
            AttachmentImage::new(device.clone(), [600, 600], Format::R8G8B8A8Unorm).unwrap(),
        )
        .unwrap();

        let _ = Framebuffer::with_dimensions(render_pass, [512, 512, 1])
            .add(view)
            .unwrap()
            .build()
            .unwrap();
    }

    #[test]
    fn attachment_dims_smaller_than_specified() {
        let (device, _) = gfx_dev_and_queue!();

        let render_pass = Arc::new(
            single_pass_renderpass!(device.clone(),
                attachments: {
                    color: {
                        load: Clear,
                        store: DontCare,
                        format: Format::R8G8B8A8Unorm,
                        samples: 1,
                    }
                },
                pass: {
                    color: [color],
                    depth_stencil: {}
                }
            )
            .unwrap(),
        );

        let view = ImageView::new(
            AttachmentImage::new(device.clone(), [512, 700], Format::R8G8B8A8Unorm).unwrap(),
        )
        .unwrap();

        match Framebuffer::with_dimensions(render_pass, [600, 600, 1]).add(view) {
            Err(FramebufferCreationError::AttachmentDimensionsIncompatible {
                expected,
                obtained,
            }) => {
                assert_eq!(expected, [600, 600, 1]);
                assert_eq!(obtained, [512, 700, 1]);
            }
            _ => panic!(),
        }
    }

    #[test]
    fn multi_attachments_dims_not_identical() {
        let (device, _) = gfx_dev_and_queue!();

        let render_pass = Arc::new(
            single_pass_renderpass!(device.clone(),
                attachments: {
                    a: {
                        load: Clear,
                        store: DontCare,
                        format: Format::R8G8B8A8Unorm,
                        samples: 1,
                    },
                    b: {
                        load: Clear,
                        store: DontCare,
                        format: Format::R8G8B8A8Unorm,
                        samples: 1,
                    }
                },
                pass: {
                    color: [a, b],
                    depth_stencil: {}
                }
            )
            .unwrap(),
        );

        let a = ImageView::new(
            AttachmentImage::new(device.clone(), [512, 512], Format::R8G8B8A8Unorm).unwrap(),
        )
        .unwrap();
        let b = ImageView::new(
            AttachmentImage::new(device.clone(), [512, 513], Format::R8G8B8A8Unorm).unwrap(),
        )
        .unwrap();

        match Framebuffer::start(render_pass).add(a).unwrap().add(b) {
            Err(FramebufferCreationError::AttachmentDimensionsIncompatible {
                expected,
                obtained,
            }) => {
                assert_eq!(expected, [512, 512, 1]);
                assert_eq!(obtained, [512, 513, 1]);
            }
            _ => panic!(),
        }
    }

    #[test]
    fn multi_attachments_auto_smaller() {
        let (device, _) = gfx_dev_and_queue!();

        let render_pass = Arc::new(
            single_pass_renderpass!(device.clone(),
                attachments: {
                    a: {
                        load: Clear,
                        store: DontCare,
                        format: Format::R8G8B8A8Unorm,
                        samples: 1,
                    },
                    b: {
                        load: Clear,
                        store: DontCare,
                        format: Format::R8G8B8A8Unorm,
                        samples: 1,
                    }
                },
                pass: {
                    color: [a, b],
                    depth_stencil: {}
                }
            )
            .unwrap(),
        );

        let a = ImageView::new(
            AttachmentImage::new(device.clone(), [256, 512], Format::R8G8B8A8Unorm).unwrap(),
        )
        .unwrap();
        let b = ImageView::new(
            AttachmentImage::new(device.clone(), [512, 128], Format::R8G8B8A8Unorm).unwrap(),
        )
        .unwrap();

        let fb = Framebuffer::with_intersecting_dimensions(render_pass)
            .add(a)
            .unwrap()
            .add(b)
            .unwrap()
            .build()
            .unwrap();

        match (fb.width(), fb.height(), fb.layers()) {
            (256, 128, 1) => (),
            _ => panic!(),
        }
    }

    #[test]
    fn not_enough_attachments() {
        let (device, _) = gfx_dev_and_queue!();

        let render_pass = Arc::new(
            single_pass_renderpass!(device.clone(),
                attachments: {
                    a: {
                        load: Clear,
                        store: DontCare,
                        format: Format::R8G8B8A8Unorm,
                        samples: 1,
                    },
                    b: {
                        load: Clear,
                        store: DontCare,
                        format: Format::R8G8B8A8Unorm,
                        samples: 1,
                    }
                },
                pass: {
                    color: [a, b],
                    depth_stencil: {}
                }
            )
            .unwrap(),
        );

        let view = ImageView::new(
            AttachmentImage::new(device.clone(), [256, 512], Format::R8G8B8A8Unorm).unwrap(),
        )
        .unwrap();

        let res = Framebuffer::with_intersecting_dimensions(render_pass)
            .add(view)
            .unwrap()
            .build();

        match res {
            Err(FramebufferCreationError::AttachmentsCountMismatch {
                expected: 2,
                obtained: 1,
            }) => (),
            _ => panic!(),
        }
    }

    #[test]
    fn too_many_attachments() {
        let (device, _) = gfx_dev_and_queue!();

        let render_pass = Arc::new(
            single_pass_renderpass!(device.clone(),
                attachments: {
                    a: {
                        load: Clear,
                        store: DontCare,
                        format: Format::R8G8B8A8Unorm,
                        samples: 1,
                    }
                },
                pass: {
                    color: [a],
                    depth_stencil: {}
                }
            )
            .unwrap(),
        );

        let a = ImageView::new(
            AttachmentImage::new(device.clone(), [256, 512], Format::R8G8B8A8Unorm).unwrap(),
        )
        .unwrap();
        let b = ImageView::new(
            AttachmentImage::new(device.clone(), [256, 512], Format::R8G8B8A8Unorm).unwrap(),
        )
        .unwrap();

        let res = Framebuffer::with_intersecting_dimensions(render_pass)
            .add(a)
            .unwrap()
            .add(b);

        match res {
            Err(FramebufferCreationError::AttachmentsCountMismatch {
                expected: 1,
                obtained: 2,
            }) => (),
            _ => panic!(),
        }
    }

    #[test]
    fn empty_working() {
        let (device, _) = gfx_dev_and_queue!();

        let rp = Arc::new(RenderPass::empty_single_pass(device).unwrap());
        let _ = Framebuffer::with_dimensions(rp, [512, 512, 1])
            .build()
            .unwrap();
    }

    #[test]
    fn cant_determine_dimensions_auto() {
        let (device, _) = gfx_dev_and_queue!();

        let rp = Arc::new(RenderPass::empty_single_pass(device).unwrap());
        let res = Framebuffer::start(rp).build();
        match res {
            Err(FramebufferCreationError::CantDetermineDimensions) => (),
            _ => panic!(),
        }
    }

    #[test]
    fn cant_determine_dimensions_intersect() {
        let (device, _) = gfx_dev_and_queue!();

        let rp = Arc::new(RenderPass::empty_single_pass(device).unwrap());
        let res = Framebuffer::with_intersecting_dimensions(rp).build();
        match res {
            Err(FramebufferCreationError::CantDetermineDimensions) => (),
            _ => panic!(),
        }
    }
}
